guix_mirror_bot pushed a commit to branch master
in repository guix.
commit 64a0824955aa40ea8e59bd4328ecaaf8caaa2acc
Author: Reepca Russelstein <[email protected]>
AuthorDate: Sun Jun 21 07:13:16 2026 -0500
daemon: libutil: add base32Values and use them.
Recognizing base32 characters and/or parsing them into byte sequences is
done
in several places, so it makes sense to provide a common lookup table.
* nix/libutil/hash.hh (base32Values, base32ValuesInitialized): new
variables.
(initializeBase32Values, getBase32Value): new functions.
* nix/libutil/hash.cc (base32Values, base32ValuesInitialized): provide
definition for variables.
(initializeBase32Values, getBase32Value): provide function
implementations.
(parseHash32): use base32Values.
* nix/libstore/references.cc (search): use base32Values.
Signed-off-by: Ludovic Courtès <[email protected]>
---
nix/libstore/references.cc | 11 +----------
nix/libutil/hash.cc | 19 +++++++++++++++----
nix/libutil/hash.hh | 3 +++
3 files changed, 19 insertions(+), 14 deletions(-)
diff --git a/nix/libstore/references.cc b/nix/libstore/references.cc
index a8ec39ee34..20b55db6ab 100644
--- a/nix/libstore/references.cc
+++ b/nix/libstore/references.cc
@@ -17,20 +17,11 @@ static unsigned int refLength = 32; /* characters */
static void search(const unsigned char * s, unsigned int len,
StringSet & hashes, StringSet & seen)
{
- static bool initialised = false;
- static bool isBase32[256];
- if (!initialised) {
- for (unsigned int i = 0; i < 256; ++i) isBase32[i] = false;
- for (unsigned int i = 0; i < base32Chars.size(); ++i)
- isBase32[(unsigned char) base32Chars[i]] = true;
- initialised = true;
- }
-
for (unsigned int i = 0; i + refLength <= len; ) {
int j;
bool match = true;
for (j = refLength - 1; j >= 0; --j)
- if (!isBase32[(unsigned char) s[i + j]]) {
+ if (base32Values[(unsigned char) s[i + j]] == -1) {
i += j + 1;
match = false;
break;
diff --git a/nix/libutil/hash.cc b/nix/libutil/hash.cc
index ac9eb14514..06753d1961 100644
--- a/nix/libutil/hash.cc
+++ b/nix/libutil/hash.cc
@@ -17,6 +17,18 @@
namespace nix {
+static std::vector<char> getBase32Values()
+{
+ assert(base32Chars.size() <= std::numeric_limits<unsigned char>::max()+1);
+ assert(base32Chars.size() <= std::numeric_limits<char>::max()+1);
+ std::vector<char> values(std::numeric_limits<unsigned char>::max()+1, -1);
+ for (string::size_type j = 0; j < base32Chars.size(); j++)
+ values[(unsigned char) base32Chars[j]] = (char) j;
+ return values;
+}
+
+const std::vector<char> base32Values = getBase32Values();
+
Hash::Hash()
{
@@ -139,11 +151,10 @@ Hash parseHash32(HashType ht, std::string_view s)
for (unsigned int n = 0; n < len; ++n) {
char c = s[len - n - 1];
- unsigned char digit;
- for (digit = 0; digit < base32Chars.size(); ++digit) /* !!! slow */
- if (base32Chars[digit] == c) break;
- if (digit >= 32)
+ char sdigit = base32Values[(unsigned char) c];
+ if (sdigit < 0)
throw Error(std::format("invalid base-32 hash '{}'", s));
+ unsigned char digit = (unsigned char) sdigit;
unsigned int b = n * 5;
unsigned int i = b / 8;
unsigned int j = b % 8;
diff --git a/nix/libutil/hash.hh b/nix/libutil/hash.hh
index cedb5077c1..fabe50c11c 100644
--- a/nix/libutil/hash.hh
+++ b/nix/libutil/hash.hh
@@ -1,6 +1,7 @@
#pragma once
#include <gcrypt.h>
+#include <limits>
#include "archive.hh"
#include "types.hh"
@@ -11,6 +12,8 @@ namespace nix {
// omitted: E O U T
inline const string base32Chars {"0123456789abcdfghijklmnpqrsvwxyz"};
+/* Maps character to value, or -1 if not part of base32 character set. */
+extern const std::vector<char> base32Values;
typedef enum {
htUnknown = 0,