diff options
Diffstat (limited to 'nix/libutil/hash.cc')
-rw-r--r-- | nix/libutil/hash.cc | 101 |
1 files changed, 28 insertions, 73 deletions
diff --git a/nix/libutil/hash.cc b/nix/libutil/hash.cc index 050446610f..2da00a53de 100644 --- a/nix/libutil/hash.cc +++ b/nix/libutil/hash.cc @@ -84,7 +84,7 @@ string printHash(const Hash & hash) return string(buf, hash.hashSize * 2); } - + Hash parseHash(HashType ht, const string & s) { Hash hash(ht); @@ -92,7 +92,7 @@ Hash parseHash(HashType ht, const string & s) throw Error(format("invalid hash `%1%'") % s); for (unsigned int i = 0; i < hash.hashSize; i++) { string s2(s, i * 2, 2); - if (!isxdigit(s2[0]) || !isxdigit(s2[1])) + if (!isxdigit(s2[0]) || !isxdigit(s2[1])) throw Error(format("invalid hash `%1%'") % s); std::istringstream str(s2); int n; @@ -103,24 +103,6 @@ Hash parseHash(HashType ht, const string & s) } -static unsigned char divMod(unsigned char * bytes, unsigned char y) -{ - unsigned int borrow = 0; - - int pos = Hash::maxHashSize - 1; - while (pos >= 0 && !bytes[pos]) --pos; - - for ( ; pos >= 0; --pos) { - unsigned int s = bytes[pos] + (borrow << 8); - unsigned int d = s / y; - borrow = s % y; - bytes[pos] = d; - } - - return borrow; -} - - unsigned int hashLength32(const Hash & hash) { return (hash.hashSize * 8 - 1) / 5 + 1; @@ -136,19 +118,19 @@ string printHash32(const Hash & hash) Hash hash2(hash); unsigned int len = hashLength32(hash); - const char * chars = base32Chars.data(); - - string s(len, '0'); - - int pos = len - 1; - while (pos >= 0) { - unsigned char digit = divMod(hash2.hash, 32); - s[pos--] = chars[digit]; + string s; + s.reserve(len); + + for (int n = len - 1; n >= 0; n--) { + unsigned int b = n * 5; + unsigned int i = b / 8; + unsigned int j = b % 8; + unsigned char c = + (hash.hash[i] >> j) + | (i >= hash.hashSize - 1 ? 0 : hash.hash[i + 1] << (8 - j)); + s.push_back(base32Chars[c & 0x1f]); } - for (unsigned int i = 0; i < hash2.maxHashSize; ++i) - assert(hash2.hash[i] == 0); - return s; } @@ -159,51 +141,24 @@ string printHash16or32(const Hash & hash) } -static bool mul(unsigned char * bytes, unsigned char y, int maxSize) -{ - unsigned char carry = 0; - - for (int pos = 0; pos < maxSize; ++pos) { - unsigned int m = bytes[pos] * y + carry; - bytes[pos] = m & 0xff; - carry = m >> 8; - } - - return carry; -} - - -static bool add(unsigned char * bytes, unsigned char y, int maxSize) -{ - unsigned char carry = y; - - for (int pos = 0; pos < maxSize; ++pos) { - unsigned int m = bytes[pos] + carry; - bytes[pos] = m & 0xff; - carry = m >> 8; - if (carry == 0) break; - } - - return carry; -} - - Hash parseHash32(HashType ht, const string & s) { Hash hash(ht); + unsigned int len = hashLength32(ht); + assert(s.size() == len); - const char * chars = base32Chars.data(); - - for (unsigned int i = 0; i < s.length(); ++i) { - char c = s[i]; + 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 (chars[digit] == c) break; + if (base32Chars[digit] == c) break; if (digit >= 32) - throw Error(format("invalid base-32 hash `%1%'") % s); - if (mul(hash.hash, 32, hash.hashSize) || - add(hash.hash, digit, hash.hashSize)) - throw Error(format("base-32 hash `%1%' is too large") % s); + throw Error(format("invalid base-32 hash '%1%'") % s); + unsigned int b = n * 5; + unsigned int i = b / 8; + unsigned int j = b % 8; + hash.hash[i] |= digit << j; + if (i < hash.hashSize - 1) hash.hash[i + 1] |= digit >> (8 - j); } return hash; @@ -299,7 +254,7 @@ Hash hashFile(HashType ht, const Path & path) if (n == -1) throw SysError(format("reading file `%1%'") % path); update(ht, ctx, buf, n); } - + finish(ht, ctx, hash.hash); return hash; } @@ -311,7 +266,7 @@ HashSink::HashSink(HashType ht) : ht(ht) bytes = 0; start(ht, *ctx); } - + HashSink::~HashSink() { bufPos = 0; @@ -369,7 +324,7 @@ HashType parseHashType(const string & s) else return htUnknown; } - + string printHashType(HashType ht) { if (ht == htMD5) return "md5"; @@ -378,5 +333,5 @@ string printHashType(HashType ht) else throw Error("cannot print unknown hash type"); } - + } |