Commit 0484d1b2 authored by Mark Olesen's avatar Mark Olesen
Browse files

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: _024ea2fa

- provide same optional prefix functionality in conversion to string
  and in comparison with strings

- add SHA1Digest::null
parent 74bc658f
......@@ -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<const unsigned char*>(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
{
......
......@@ -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);
}
......
......@@ -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
//- The length of the (uncoded) digest contents
static const unsigned length = 20;
//- A null digest (ie, all zero)
static const SHA1Digest null;
// Constructors
//- Construct a zero digest
SHA1Digest();
//- Construct read a digest
SHA1Digest(Istream&);
// 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
//- Construct a zero digest
SHA1Digest();
//- Equality operator
bool operator==(const SHA1Digest&) const;
//- Construct read a digest
SHA1Digest(Istream&);
//- 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;
//- Reset the digest to zero
void clear();
//- 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;
//- Return true if the digest is empty (ie, all zero).
bool empty() const;
//- Return string representation
std::string str() const;
//- Inequality operator
bool operator!=(const SHA1Digest&) const;
//- Equality operator
bool operator==(const SHA1Digest&) const;
//- Inequality operator
bool operator!=(const std::string& hexdigits) const;
//- Compare to (40-byte) text representation (eg, from sha1sum)
// An %empty string is equivalent to
// "0000000000000000000000000000000000000000"
bool operator==(const std::string& hexdigits) const;
//- Inequality operator
bool operator!=(const char* 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;
//- Inequality operator
bool operator!=(const SHA1Digest&) const;
//- Inequality operator
bool operator!=(const std::string& hexdigits) const;
// IOstream Operators
//- Inequality operator
bool operator!=(const char* hexdigits) const;
//- 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&);
friend Ostream& operator<<(Ostream&, const SHA1Digest&);
friend Istream& operator>>(Istream&, 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&);
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment