Loading...
Searching...
No Matches
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-2025 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
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 <algorithm>
32#include <cstring>
33
34// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
35
38static const char hexChars[] = "0123456789abcdef";
39
40// The char '0' == 0
41static constexpr int offsetZero = int('0');
42
43// The char 'A' (or 'a') == 10
44static constexpr int offsetAlpha = int('A') - 10;
45
47// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
48
49namespace Foam
50{
51
52// Read hexadecimal value, ignoring leading or intermediate '_'
53static unsigned char readHexDigit(Istream& is)
54{
55 // Silently ignore leading or intermediate '_'
56 char c = 0;
57 do
58 {
59 is.read(c);
60 }
61 while (c == '_');
62
63 if (isdigit(c))
64 {
65 return int(c) - offsetZero;
66 }
67 else if (!isxdigit(c))
68 {
70 << "Illegal hex digit: '" << c << "'"
72 }
73
74 return toupper(c) - offsetAlpha;
75}
76
77} // End namespace Foam
78
79
80namespace
81{
82
83// Copy assign digest from content
84bool assign
85(
86 std::array<unsigned char, 20>& digest,
87 const unsigned char* content,
88 std::size_t len
89)
90{
91 if (!content || !len)
92 {
93 return false;
94 }
95
96 if (len == digest.size())
97 {
98 std::copy_n(content, len, digest.data());
99 return true;
100 }
101
102 // Skip possible '_' prefix
103 if (*content == '_')
104 {
105 ++content;
106 --len;
107 }
108
109 // Incorrect length - can never assign
110 if (len != 2*digest.size())
111 {
112 return false;
113 }
114
115 for (auto& val : digest)
116 {
117 const unsigned char upp = *content++;
118 const unsigned char low = *content++;
119
120 val = (upp << 4) + low;
121 }
122
123 return true;
124}
125
126
127// Byte-wise compare digest contents
128bool isEqual
129(
130 const std::array<unsigned char, 20>& digest,
131 const char* hexdigits,
132 std::size_t len
133)
134{
135 // Skip possible '_' prefix
136 if (*hexdigits == '_')
137 {
138 ++hexdigits;
139 --len;
140 }
141
142 // Incorrect length - can never match
143 if (len != 2*digest.size())
144 {
145 return false;
146 }
147
148 for (const auto& byteVal : digest)
149 {
150 const char upp = hexChars[((byteVal >> 4) & 0xF)];
151 const char low = hexChars[(byteVal & 0xF)];
152
153 if (upp != *hexdigits++) return false;
154 if (low != *hexdigits++) return false;
155 }
156
157 return true;
159
160} // End anonymous namespace
161
162
163// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
166{
167 dig_.fill(0);
168}
169
170
171Foam::SHA1Digest::SHA1Digest(const char* content, std::size_t len)
172{
173 dig_.fill(0);
174 assign(dig_, reinterpret_cast<const unsigned char*>(content), len);
175}
176
177
178Foam::SHA1Digest::SHA1Digest(const unsigned char* content, std::size_t len)
179{
180 dig_.fill(0);
181 assign(dig_, content, len);
182}
183
184
186{
187 dig_.fill(0);
188 read(is);
189}
190
191
192// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
195{
196 dig_.fill(0);
197}
198
199
200bool Foam::SHA1Digest::empty() const
201{
202 for (const auto& byteVal : dig_)
203 {
204 if (byteVal)
205 {
206 return false;
208 }
209
210 return true;
211}
212
213
214Foam::Istream& Foam::SHA1Digest::read(Istream& is)
215{
216 for (auto& byteVal : dig_)
217 {
218 const unsigned char upp = readHexDigit(is);
219 const unsigned char low = readHexDigit(is);
220
221 byteVal = (upp << 4) + low;
223
225 return is;
226}
227
228
229std::string Foam::SHA1Digest::str(const bool prefixed) const
230{
231 std::string buf;
232 int nChar = 0;
233
234 if (prefixed)
235 {
236 buf.resize(1 + 2*dig_.size());
237 buf[nChar++] = '_';
238 }
239 else
240 {
241 buf.resize(2*dig_.size());
242 }
243
244 for (const auto& byteVal : dig_)
245 {
246 buf[nChar++] = hexChars[((byteVal >> 4) & 0xF)]; // Upper nibble
247 buf[nChar++] = hexChars[(byteVal & 0xF)]; // Lower nibble
248 }
249
250 return buf;
251}
252
253
254Foam::Ostream& Foam::SHA1Digest::write(Ostream& os, const bool prefixed) const
255{
256 if (prefixed)
257 {
258 os.write('_');
259 }
260
261 for (const auto& byteVal : dig_)
262 {
263 os.write(hexChars[((byteVal >> 4) & 0xF)]); // Upper nibble
264 os.write(hexChars[(byteVal & 0xF)]); // Lower nibble
265 }
266
268 return os;
269}
270
271
272// * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * * //
275{
276 return (dig_ == rhs.dig_);
277}
278
279
280bool Foam::SHA1Digest::operator==(const std::string& hexdigits) const
281{
282 // Interpret empty string as '0000..'
283 size_t len = hexdigits.length();
284
285 return len ? isEqual(dig_, hexdigits.data(), len) : empty();
286}
287
288
289bool Foam::SHA1Digest::operator==(const char* hexdigits) const
290{
291 // Interpret nullptr or empty string as '0000..'
292 size_t len = (hexdigits ? strlen(hexdigits) : 0);
294 return len ? isEqual(dig_, hexdigits, len) : empty();
295}
296
297
298// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
301{
302 return dig.read(is);
303}
304
305
306Foam::Ostream& Foam::operator<<(Ostream& os, const SHA1Digest& dig)
307{
308 // Write with prefixed = false
309 return dig.write(os, false);
310}
311
312
313// ************************************************************************* //
Useful combination of include files which define Sin, Sout and Serr and the use of IO streams general...
static const char hexChars[]
Definition SHA1Digest.C:31
static constexpr int offsetAlpha
Definition SHA1Digest.C:37
static constexpr int offsetZero
Definition SHA1Digest.C:34
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:60
virtual Istream & read(token &)=0
Return next token from stream.
virtual Ostream & write(const char c) override
Write character.
Definition OBJstream.C:69
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition Ostream.H:59
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
The SHA1 message digest.
Definition SHA1Digest.H:58
std::string str(const bool prefixed=false) const
Return (40-byte) text representation, optionally with '_' prefix.
Definition SHA1Digest.C:222
bool empty() const
Return true if the digest is empty (ie, all zero).
Definition SHA1Digest.C:193
SHA1Digest()
Default construct a zero digest.
Definition SHA1Digest.C:158
Ostream & write(Ostream &os, const bool prefixed=false) const
Write (40-byte) text representation, optionally with '_' prefix.
Definition SHA1Digest.C:247
bool operator==(const SHA1Digest &rhs) const
Equality operator.
Definition SHA1Digest.C:267
void clear()
Reset the digest to zero.
Definition SHA1Digest.C:187
static const SHA1Digest null
A null digest (ie, all zero).
Definition SHA1Digest.H:85
Istream & read(Istream &is)
Read (40-byte) text representation.
Definition SHA1Digest.C:207
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition error.H:629
OBJstream os(runTime.globalPath()/outputName)
#define FUNCTION_NAME
void assign(Field< Tout > &result, const Field< T1 > &a, const UnaryOp &op)
Populate a field as the result of a unary operation on an input.
Definition FieldOps.C:28
Namespace for OpenFOAM.
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition int32.H:127
Ostream & operator<<(Ostream &, const boundaryPatch &p)
Write boundaryPatch as dictionary entries (without surrounding braces).
Istream & operator>>(Istream &, directionInfo &)
IOerror FatalIOError
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...
void rhs(fvMatrix< typename Expr::value_type > &m, const Expr &expression)
static unsigned char readHexDigit(Istream &is)
Definition SHA1Digest.C:46
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
constexpr bool isdigit(char c) noexcept
Test for digits [0-9] (C-locale only).
Definition char.H:69