SHA1Digest.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2015 OpenFOAM Foundation
9  Copyright (C) 2019-2022 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "SHA1Digest.H"
30 #include "IOstreams.H"
31 #include <cstring>
32 
33 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34 
36 
37 static const char hexChars[] = "0123456789abcdef";
38 
39 // The char '0' == 0
40 static constexpr int offsetZero = int('0');
41 
42 // The char 'A' (or 'a') == 10
43 static constexpr int offsetAlpha = int('A') - 10;
44 
45 
46 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
47 
48 namespace Foam
49 {
50 
51 // Read hexadecimal value, ignoring leading or intermediate '_'
52 static unsigned char readHexDigit(Istream& is)
53 {
54  // Silently ignore leading or intermediate '_'
55  char c = 0;
56  do
57  {
58  is.read(c);
59  }
60  while (c == '_');
61 
62  if (isdigit(c))
63  {
64  return int(c) - offsetZero;
65  }
66  else if (!isxdigit(c))
67  {
69  << "Illegal hex digit: '" << c << "'"
70  << exit(FatalIOError);
71  }
72 
73  return toupper(c) - offsetAlpha;
74 }
75 
76 } // End namespace Foam
77 
78 
79 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
80 
81 bool Foam::SHA1Digest::isEqual(const char* hexdigits, std::size_t len) const
82 {
83  // Skip possible '_' prefix
84  if (*hexdigits == '_')
85  {
86  ++hexdigits;
87  --len;
88  }
89 
90  // Incorrect length - can never match
91  if (len != 2*dig_.size())
92  {
93  return false;
94  }
95 
96  for (const auto& byteVal : dig_)
97  {
98  const char upp = hexChars[((byteVal >> 4) & 0xF)];
99  const char low = hexChars[(byteVal & 0xF)];
100 
101  if (upp != *hexdigits++) return false;
102  if (low != *hexdigits++) return false;
103  }
105  return true;
106 }
107 
108 
109 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
112 {
113  clear();
114 }
115 
116 
118 {
119  clear();
120  read(is);
121 }
122 
123 
124 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
127 {
128  dig_.fill(0); // Same as memset(dig_.data(), 0, dig_.size());
129 }
130 
131 
132 bool Foam::SHA1Digest::empty() const
133 {
134  for (const auto& byteVal : dig_)
135  {
136  if (byteVal)
137  {
138  return false;
139  }
140  }
141 
142  return true;
143 }
144 
145 
147 {
148  for (auto& byteVal : dig_)
149  {
150  const unsigned char upp = readHexDigit(is);
151  const unsigned char low = readHexDigit(is);
152 
153  byteVal = (upp << 4) + low;
154  }
155 
156  is.check(FUNCTION_NAME);
157  return is;
158 }
159 
160 
161 std::string Foam::SHA1Digest::str(const bool prefixed) const
162 {
163  std::string buf;
164  std::size_t nChar = 0;
165 
166  if (prefixed)
167  {
168  buf.resize(1 + 2*dig_.size());
169  buf[nChar++] = '_';
170  }
171  else
172  {
173  buf.resize(2*dig_.size());
174  }
175 
176  for (const auto& byteVal : dig_)
177  {
178  buf[nChar++] = hexChars[((byteVal >> 4) & 0xF)]; // Upper nibble
179  buf[nChar++] = hexChars[(byteVal & 0xF)]; // Lower nibble
180  }
181 
182  return buf;
183 }
184 
185 
186 Foam::Ostream& Foam::SHA1Digest::write(Ostream& os, const bool prefixed) const
187 {
188  if (prefixed)
189  {
190  os.write('_');
191  }
192 
193  for (const auto& byteVal : dig_)
194  {
195  os.write(hexChars[((byteVal >> 4) & 0xF)]); // Upper nibble
196  os.write(hexChars[(byteVal & 0xF)]); // Lower nibble
197  }
198 
200  return os;
201 }
202 
203 
204 // * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * * //
206 bool Foam::SHA1Digest::operator==(const SHA1Digest& rhs) const
207 {
208  return (dig_ == rhs.dig_);
209 }
210 
211 
212 bool Foam::SHA1Digest::operator==(const std::string& hexdigits) const
213 {
214  // Interpret empty string as '0000..'
215  size_t len = hexdigits.length();
216 
217  return len ? isEqual(hexdigits.data(), len) : empty();
218 }
219 
220 
221 bool Foam::SHA1Digest::operator==(const char* hexdigits) const
222 {
223  // Interpret nullptr or empty string as '0000..'
224  size_t len = (hexdigits ? strlen(hexdigits) : 0);
225 
226  return len ? isEqual(hexdigits, len) : empty();
227 }
228 
230 bool Foam::SHA1Digest::operator!=(const SHA1Digest& rhs) const
231 {
232  return !this->operator==(rhs);
233 }
234 
236 bool Foam::SHA1Digest::operator!=(const std::string& hexdigits) const
237 {
238  return !this->operator==(hexdigits);
239 }
240 
241 
242 bool Foam::SHA1Digest::operator!=(const char* hexdigits) const
243 {
244  return !this->operator==(hexdigits);
245 }
246 
247 
248 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
251 {
252  return dig.read(is);
253 }
254 
255 
256 Foam::Ostream& Foam::operator<<(Ostream& os, const SHA1Digest& dig)
257 {
258  // Write with prefixed = false
259  return dig.write(os, false);
260 }
261 
262 
263 // ************************************************************************* //
static constexpr int offsetZero
Definition: SHA1Digest.C:33
virtual Ostream & write(const char c)
Write character.
Definition: OBJstream.C:71
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
virtual bool check(const char *operation) const
Check IOstream status for given operation.
Definition: IOstream.C:45
An Istream is an abstract base class for all input systems (streams, files, token lists etc)...
Definition: Istream.H:57
The SHA1 message digest.
Definition: SHA1Digest.H:56
bool operator!=(const SHA1Digest &rhs) const
Inequality operator.
Definition: SHA1Digest.C:223
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition: int32.H:125
Useful combination of include files which define Sin, Sout and Serr and the use of IO streams general...
virtual Istream & read(token &)=0
Return next token from stream.
static const char hexChars[]
Definition: SHA1Digest.C:30
Istream & operator>>(Istream &, directionInfo &)
SHA1Digest()
Default construct a zero digest.
Definition: SHA1Digest.C:104
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
patchWriters clear()
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:55
bool empty() const
Return true if the digest is empty (ie, all zero).
Definition: SHA1Digest.C:125
OBJstream os(runTime.globalPath()/outputName)
#define FUNCTION_NAME
Ostream & operator<<(Ostream &, const boundaryPatch &p)
Write boundaryPatch as dictionary entries (without surrounding braces)
Definition: boundaryPatch.C:76
Ostream & write(Ostream &os, const bool prefixed=false) const
Write (40-byte) text representation, optionally with &#39;_&#39; prefix.
Definition: SHA1Digest.C:179
static constexpr int offsetAlpha
Definition: SHA1Digest.C:36
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:607
void clear()
Reset the digest to zero.
Definition: SHA1Digest.C:119
static unsigned char readHexDigit(Istream &is)
Definition: SHA1Digest.C:45
bool operator==(const SHA1Digest &rhs) const
Equality operator.
Definition: SHA1Digest.C:199
const dimensionedScalar c
Speed of light in a vacuum.
std::string str(const bool prefixed=false) const
Return (40-byte) text representation, optionally with &#39;_&#39; prefix.
Definition: SHA1Digest.C:154
tmp< faMatrix< Type > > operator==(const faMatrix< Type > &, const faMatrix< Type > &)
Istream & read(Istream &is)
Read (40-byte) text representation.
Definition: SHA1Digest.C:139
static const SHA1Digest null
A null digest (ie, all zero)
Definition: SHA1Digest.H:92
Namespace for OpenFOAM.
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...