mirror of
https://github.com/NixOS/nix.git
synced 2025-11-09 03:56:01 +01:00
Merge pull request #13680 from avnik/avnik/fast-base32
Improve base-32 hash decoding performance with reverse map
This commit is contained in:
commit
6ab8cbe31a
3 changed files with 20 additions and 18 deletions
|
|
@ -72,7 +72,19 @@ static std::string printHash16(const Hash & hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// omitted: E O U T
|
// omitted: E O U T
|
||||||
const std::string nix32Chars = "0123456789abcdfghijklmnpqrsvwxyz";
|
constexpr char nix32Chars[] = "0123456789abcdfghijklmnpqrsvwxyz";
|
||||||
|
|
||||||
|
constexpr const std::array<unsigned char, 256> reverseNix32Map = [] {
|
||||||
|
std::array<unsigned char, 256> map{};
|
||||||
|
|
||||||
|
for (size_t i = 0; i < map.size(); ++i)
|
||||||
|
map[i] = 0xFF; // invalid
|
||||||
|
|
||||||
|
for (unsigned char i = 0; i < 32; ++i)
|
||||||
|
map[static_cast<unsigned char>(nix32Chars[i])] = i;
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}();
|
||||||
|
|
||||||
static std::string printHash32(const Hash & hash)
|
static std::string printHash32(const Hash & hash)
|
||||||
{
|
{
|
||||||
|
|
@ -217,12 +229,11 @@ Hash::Hash(std::string_view rest, HashAlgorithm algo, bool isSRI)
|
||||||
|
|
||||||
for (unsigned int n = 0; n < rest.size(); ++n) {
|
for (unsigned int n = 0; n < rest.size(); ++n) {
|
||||||
char c = rest[rest.size() - n - 1];
|
char c = rest[rest.size() - n - 1];
|
||||||
unsigned char digit;
|
unsigned char digit = reverseNix32Map[static_cast<unsigned char>(c)];
|
||||||
for (digit = 0; digit < nix32Chars.size(); ++digit) /* !!! slow */
|
|
||||||
if (nix32Chars[digit] == c)
|
if (digit == 0xFF)
|
||||||
break;
|
throw BadHash("invalid base-32 hash: '%s'", rest);
|
||||||
if (digit >= 32)
|
|
||||||
throw BadHash("invalid base-32 hash '%s'", rest);
|
|
||||||
unsigned int b = n * 5;
|
unsigned int b = n * 5;
|
||||||
unsigned int i = b / 8;
|
unsigned int i = b / 8;
|
||||||
unsigned int j = b % 8;
|
unsigned int j = b % 8;
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ constexpr inline size_t regularHashSize(HashAlgorithm type)
|
||||||
|
|
||||||
extern const StringSet hashAlgorithms;
|
extern const StringSet hashAlgorithms;
|
||||||
|
|
||||||
extern const std::string nix32Chars;
|
extern const std::array<unsigned char, 256> reverseNix32Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enumeration representing the hash formats.
|
* @brief Enumeration representing the hash formats.
|
||||||
|
|
|
||||||
|
|
@ -13,20 +13,11 @@ static size_t refLength = 32; /* characters */
|
||||||
|
|
||||||
static void search(std::string_view s, StringSet & hashes, StringSet & seen)
|
static void search(std::string_view s, StringSet & hashes, StringSet & seen)
|
||||||
{
|
{
|
||||||
static std::once_flag initialised;
|
|
||||||
static bool isBase32[256];
|
|
||||||
std::call_once(initialised, []() {
|
|
||||||
for (unsigned int i = 0; i < 256; ++i)
|
|
||||||
isBase32[i] = false;
|
|
||||||
for (unsigned int i = 0; i < nix32Chars.size(); ++i)
|
|
||||||
isBase32[(unsigned char) nix32Chars[i]] = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
for (size_t i = 0; i + refLength <= s.size();) {
|
for (size_t i = 0; i + refLength <= s.size();) {
|
||||||
int j;
|
int j;
|
||||||
bool match = true;
|
bool match = true;
|
||||||
for (j = refLength - 1; j >= 0; --j)
|
for (j = refLength - 1; j >= 0; --j)
|
||||||
if (!isBase32[(unsigned char) s[i + j]]) {
|
if (reverseNix32Map[(unsigned char) s[i + j]] == 0xFF) {
|
||||||
i += j + 1;
|
i += j + 1;
|
||||||
match = false;
|
match = false;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue