From 0484d1b25b4f6a14949e2f0334a6baab74e829ae Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Fri, 25 Feb 2011 14:53:12 +0100 Subject: [PATCH] ENH: allow '_' prefix when reading/writing SHA1Digest - the resulting SHA1 can be written and parsed directly without any ambiguities when it starts with a digit eg, SHA1: _024ea2fa570968069f52f55aa47ee82ac417f5f6 - provide same optional prefix functionality in conversion to string and in comparison with strings - add SHA1Digest::null --- src/OpenFOAM/primitives/hashes/SHA1/SHA1.C | 20 +-- .../primitives/hashes/SHA1/SHA1Digest.C | 92 +++++++++----- .../primitives/hashes/SHA1/SHA1Digest.H | 114 +++++++++++------- 3 files changed, 147 insertions(+), 79 deletions(-) diff --git a/src/OpenFOAM/primitives/hashes/SHA1/SHA1.C b/src/OpenFOAM/primitives/hashes/SHA1/SHA1.C index 5a54e10d6e..5c97cee6c4 100644 --- a/src/OpenFOAM/primitives/hashes/SHA1/SHA1.C +++ b/src/OpenFOAM/primitives/hashes/SHA1/SHA1.C @@ -151,7 +151,7 @@ void Foam::SHA1::processBytes(const void *data, size_t len) // while (len > 64) while (len >= 64) { - processBlock(memcpy (buffer_, data, 64), 64); + processBlock(memcpy(buffer_, data, 64), 64); data = reinterpret_cast(data) + 64; len -= 64; } @@ -177,7 +177,7 @@ void Foam::SHA1::processBytes(const void *data, size_t len) { processBlock(buffer_, 64); remaining -= 64; - memcpy (buffer_, &buffer_[16], remaining); + memcpy(buffer_, &buffer_[16], remaining); } bufLen_ = remaining; } @@ -241,10 +241,10 @@ Foam::SHA1::processBlock(const void *data, size_t len) while (words < endp) { uint32_t tm; - for (int t = 0; t < 16; t++) + for (int t = 0; t < 16; ++t) { - x[t] = swapBytes (*words); - words++; + x[t] = swapBytes(*words); + ++words; } R( a, b, c, d, e, F1, K1, x[ 0] ); @@ -343,11 +343,11 @@ void Foam::SHA1::calcDigest(SHA1Digest& dig) const { unsigned char *r = dig.v_; - set_uint32 (r + 0 * sizeof(uint32_t), swapBytes(hashsumA_)); - set_uint32 (r + 1 * sizeof(uint32_t), swapBytes(hashsumB_)); - set_uint32 (r + 2 * sizeof(uint32_t), swapBytes(hashsumC_)); - set_uint32 (r + 3 * sizeof(uint32_t), swapBytes(hashsumD_)); - set_uint32 (r + 4 * sizeof(uint32_t), swapBytes(hashsumE_)); + set_uint32(r + 0 * sizeof(uint32_t), swapBytes(hashsumA_)); + set_uint32(r + 1 * sizeof(uint32_t), swapBytes(hashsumB_)); + set_uint32(r + 2 * sizeof(uint32_t), swapBytes(hashsumC_)); + set_uint32(r + 3 * sizeof(uint32_t), swapBytes(hashsumD_)); + set_uint32(r + 4 * sizeof(uint32_t), swapBytes(hashsumE_)); } else { diff --git a/src/OpenFOAM/primitives/hashes/SHA1/SHA1Digest.C b/src/OpenFOAM/primitives/hashes/SHA1/SHA1Digest.C index 16dbd838cd..bf0730d2e4 100644 --- a/src/OpenFOAM/primitives/hashes/SHA1/SHA1Digest.C +++ b/src/OpenFOAM/primitives/hashes/SHA1/SHA1Digest.C @@ -30,6 +30,8 @@ License // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // +const Foam::SHA1Digest Foam::SHA1Digest::null; + //! \cond fileScope static const char hexChars[] = "0123456789abcdef"; //! \endcond @@ -40,12 +42,18 @@ static const char hexChars[] = "0123456789abcdef"; unsigned char Foam::SHA1Digest::readHexDigit(Istream& is) { // Takes into account that 'a' (or 'A') is 10 - static const label alphaOffset = toupper('A') - 10; + static const int alphaOffset = toupper('A') - 10; // Takes into account that '0' is 0 - static const label zeroOffset = int('0'); + static const int zeroOffset = int('0'); + + // silently ignore leading or intermediate '_' char c = 0; - is.read(c); + do + { + is.read(c); + } + while (c == '_'); if (!isxdigit(c)) { @@ -101,12 +109,21 @@ bool Foam::SHA1Digest::empty() const } -std::string Foam::SHA1Digest::str() const +std::string Foam::SHA1Digest::str(const bool prefixed) const { std::string buf; - buf.resize(length*2); - unsigned nChar = 0; + + if (prefixed) + { + buf.resize(1 + length*2); + buf[nChar++] = '_'; + } + else + { + buf.resize(length*2); + } + for (unsigned i = 0; i < length; ++i) { buf[nChar++] = hexChars[((v_[i] >> 4) & 0xF)]; @@ -117,6 +134,24 @@ std::string Foam::SHA1Digest::str() const } +Foam::Ostream& Foam::SHA1Digest::write(Ostream& os, const bool prefixed) const +{ + if (prefixed) + { + os.write('_'); + } + + for (unsigned i = 0; i < length; ++i) + { + os.write(hexChars[((v_[i] >> 4) & 0xF)]); + os.write(hexChars[(v_[i] & 0xF)]); + } + + os.check("SHA1Digest::write(Ostream&, const bool)"); + return os; +} + + // * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * * // bool Foam::SHA1Digest::operator==(const SHA1Digest& rhs) const @@ -141,21 +176,26 @@ bool Foam::SHA1Digest::operator==(const std::string& hexdigits) const return empty(); } + // skip possible '_' prefix + unsigned charI = 0; + if (hexdigits[0] == '_') + { + ++charI; + } + // incorrect length - can never match - if (hexdigits.size() != length*2) + if (hexdigits.size() != charI + length*2) { return false; } - for (unsigned i = 0, charI = 0; i < length; ++i, charI += 2) + for (unsigned i = 0; i < length; ++i) { const char c1 = hexChars[((v_[i] >> 4) & 0xF)]; const char c2 = hexChars[(v_[i] & 0xF)]; - if (c1 != hexdigits[charI] || c2 != hexdigits[charI+1]) - { - return false; - } + if (c1 != hexdigits[charI++]) return false; + if (c2 != hexdigits[charI++]) return false; } return true; @@ -170,21 +210,26 @@ bool Foam::SHA1Digest::operator==(const char* hexdigits) const return empty(); } + // skip possible '_' prefix + unsigned charI = 0; + if (hexdigits[0] == '_') + { + ++charI; + } + // incorrect length - can never match - if (strlen(hexdigits) != length*2) + if (strlen(hexdigits) != charI + length*2) { return false; } - for (unsigned i = 0, charI = 0; i < length; ++i, charI += 2) + for (unsigned i = 0; i < length; ++i) { const char c1 = hexChars[((v_[i] >> 4) & 0xF)]; const char c2 = hexChars[(v_[i] & 0xF)]; - if (c1 != hexdigits[charI] || c2 != hexdigits[charI+1]) - { - return false; - } + if (c1 != hexdigits[charI++]) return false; + if (c2 != hexdigits[charI++]) return false; } return true; @@ -230,16 +275,7 @@ Foam::Istream& Foam::operator>>(Istream& is, SHA1Digest& dig) Foam::Ostream& Foam::operator<<(Ostream& os, const SHA1Digest& dig) { - const unsigned char *v = dig.v_; - - for (unsigned i = 0; i < dig.length; ++i) - { - os.write(hexChars[((v[i] >> 4) & 0xF)]); - os.write(hexChars[(v[i] & 0xF)]); - } - - os.check("Ostream& operator<<(Ostream&, const SHA1Digest&)"); - return os; + return dig.write(os); } diff --git a/src/OpenFOAM/primitives/hashes/SHA1/SHA1Digest.H b/src/OpenFOAM/primitives/hashes/SHA1/SHA1Digest.H index dca6adc367..e93a72b020 100644 --- a/src/OpenFOAM/primitives/hashes/SHA1/SHA1Digest.H +++ b/src/OpenFOAM/primitives/hashes/SHA1/SHA1Digest.H @@ -46,8 +46,8 @@ namespace Foam { // Forward declaration of classes -class Ostream; class Istream; +class Ostream; // Forward declaration of friend functions and operators class SHA1; @@ -57,7 +57,7 @@ Istream& operator>>(Istream&, SHA1Digest&); /*---------------------------------------------------------------------------*\ - Class SHA1Digest Declaration + Class SHA1Digest Declaration \*---------------------------------------------------------------------------*/ class SHA1Digest @@ -65,57 +65,89 @@ class SHA1Digest public: friend class SHA1; - //- The length of the digest contents - static const unsigned length = 20; + // Static data members - //- Construct a zero digest - SHA1Digest(); + //- The length of the (uncoded) digest contents + static const unsigned length = 20; - //- Construct read a digest - SHA1Digest(Istream&); - - //- Reset the digest to zero - void clear(); - - //- Return true if the digest is empty (ie, all zero). - bool empty() const; - - //- Return string representation - std::string str() const; - - //- Equality operator - bool operator==(const SHA1Digest&) const; - - //- Compare to (40-byte) text representation (eg, from sha1sum) - // An %empty string is equivalent to - // "0000000000000000000000000000000000000000" - bool operator==(const std::string& hexdigits) const; - - //- Compare to (40-byte) text representation (eg, from sha1sum) - // A %null or %empty string is equivalent to - // "0000000000000000000000000000000000000000" - bool operator==(const char* hexdigits) const; + //- A null digest (ie, all zero) + static const SHA1Digest null; - //- Inequality operator - bool operator!=(const SHA1Digest&) const; + // Constructors - //- Inequality operator - bool operator!=(const std::string& hexdigits) const; + //- Construct a zero digest + SHA1Digest(); - //- Inequality operator - bool operator!=(const char* hexdigits) const; + //- Construct read a digest + SHA1Digest(Istream&); - friend Ostream& operator<<(Ostream&, const SHA1Digest&); - friend Istream& operator>>(Istream&, SHA1Digest&); + // Member Functions + + //- Reset the digest to zero + void clear(); + + //- Return true if the digest is empty (ie, all zero). + bool empty() const; + + //- Return (40-byte) text representation, optionally with '_' prefix + std::string str(const bool prefixed=false) const; + + //- Write (40-byte) text representation, optionally with '_' prefix + Ostream& write(Ostream&, const bool prefixed=false) const; + + + // Member Operators + + //- Equality operator + bool operator==(const SHA1Digest&) const; + + //- Compare to (40-byte) text representation (eg, from sha1sum) + // An %empty string is equivalent to + // "0000000000000000000000000000000000000000" + // The hexdigits may optionally start with a '_' prefix + bool operator==(const std::string& hexdigits) const; + + //- Compare to (40-byte) text representation (eg, from sha1sum) + // A %null or %empty string is equivalent to + // "0000000000000000000000000000000000000000" + // The hexdigits may optionally start with a '_' prefix + bool operator==(const char* hexdigits) const; + + + //- Inequality operator + bool operator!=(const SHA1Digest&) const; + + //- Inequality operator + bool operator!=(const std::string& hexdigits) const; + + //- Inequality operator + bool operator!=(const char* hexdigits) const; + + + + + // IOstream Operators + + //- Read (40-byte) text representation + // Since leading and intermediate underscores are skipped, a '_' can + // be prefixed to the text representation to use an unquoted + // SHA1Digest without parsing ambiguities as a number. + friend Istream& operator>>(Istream&, SHA1Digest&); + + //- Write (40-byte) text representation, unquoted and without prefix + friend Ostream& operator<<(Ostream&, const SHA1Digest&); + private: + // Private data - //- The digest contents - unsigned char v_[length]; + //- The digest contents + unsigned char v_[length]; - static unsigned char readHexDigit(Istream&); + //- Read hexadecimal value, ignoring leading or intermediate '_' + static unsigned char readHexDigit(Istream&); };