From 64a0824955aa40ea8e59bd4328ecaaf8caaa2acc Mon Sep 17 00:00:00 2001 From: Reepca Russelstein Date: Sun, 21 Jun 2026 07:13:16 -0500 Subject: daemon: libutil: add base32Values and use them. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- nix/libutil/hash.cc | 19 +++++++++++++++---- nix/libutil/hash.hh | 3 +++ 2 files changed, 18 insertions(+), 4 deletions(-) (limited to 'nix/libutil') diff --git a/nix/libutil/hash.cc b/nix/libutil/hash.cc index ac9eb14514b..06753d19619 100644 --- a/nix/libutil/hash.cc +++ b/nix/libutil/hash.cc @@ -17,6 +17,18 @@ namespace nix { +static std::vector getBase32Values() +{ + assert(base32Chars.size() <= std::numeric_limits::max()+1); + assert(base32Chars.size() <= std::numeric_limits::max()+1); + std::vector values(std::numeric_limits::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 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 cedb5077c16..fabe50c11c6 100644 --- a/nix/libutil/hash.hh +++ b/nix/libutil/hash.hh @@ -1,6 +1,7 @@ #pragma once #include +#include #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 base32Values; typedef enum { htUnknown = 0, -- cgit v1.2.3