SHA1Digest.C 6.22 KB
Newer Older
Mark Olesen's avatar
Mark Olesen committed
1
2
3
4
/*---------------------------------------------------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     |
OpenFOAM bot's avatar
OpenFOAM bot committed
5
    \\  /    A nd           | www.openfoam.com
Mark Olesen's avatar
Mark Olesen committed
6
     \\/     M anipulation  |
OpenFOAM bot's avatar
OpenFOAM bot committed
7
-------------------------------------------------------------------------------
OpenFOAM bot's avatar
OpenFOAM bot committed
8
9
    Copyright (C) 2011-2015 OpenFOAM Foundation
    Copyright (C) 2019 OpenCFD Ltd.
Mark Olesen's avatar
Mark Olesen committed
10
11
12
13
-------------------------------------------------------------------------------
License
    This file is part of OpenFOAM.

14
15
16
17
    OpenFOAM is free software: you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
Mark Olesen's avatar
Mark Olesen committed
18
19
20
21
22
23
24

    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    for more details.

    You should have received a copy of the GNU General Public License
25
    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
Mark Olesen's avatar
Mark Olesen committed
26
27
28

\*---------------------------------------------------------------------------*/

29
#include "SHA1Digest.H"
Mark Olesen's avatar
Mark Olesen committed
30
31
32
33
34
#include "IOstreams.H"
#include <cstring>

// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //

35
36
const Foam::SHA1Digest Foam::SHA1Digest::null;

37
static const char hexChars[] = "0123456789abcdef";
38

39
40
// The char '0' == 0
static constexpr int offsetZero = int('0');
41

42
43
// The char 'A' (or 'a') == 10
static constexpr int offsetUpper = int('A') - 10;
44

45

46
47
48
49
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //

namespace Foam
{
50

51
52
53
54
// Read hexadecimal value, ignoring leading or intermediate '_'
static unsigned char readHexDigit(Istream& is)
{
    // Silently ignore leading or intermediate '_'
55
    char c = 0;
56
57
58
59
60
    do
    {
        is.read(c);
    }
    while (c == '_');
61

62
63
64
65
66
    if (isdigit(c))
    {
        return int(c) - offsetZero;
    }
    else if (!isxdigit(c))
67
    {
68
        FatalIOErrorInFunction(is)
69
70
71
72
            << "Illegal hex digit: '" << c << "'"
            << exit(FatalIOError);
    }

73
    return toupper(c) - offsetUpper;
74
}
Mark Olesen's avatar
Mark Olesen committed
75

76
77
} // End namespace Foam

Mark Olesen's avatar
Mark Olesen committed
78
79
80

// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //

81
Foam::SHA1Digest::SHA1Digest()
Mark Olesen's avatar
Mark Olesen committed
82
83
84
85
86
{
    clear();
}


87
88
Foam::SHA1Digest::SHA1Digest(Istream& is)
{
89
90
    clear();
    read(is);
91
92
93
}


Mark Olesen's avatar
Mark Olesen committed
94
95
// * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //

96
void Foam::SHA1Digest::clear()
Mark Olesen's avatar
Mark Olesen committed
97
{
98
    dig_.fill(0);  // Same as memset(dig_.data(), 0, dig_.size());
Mark Olesen's avatar
Mark Olesen committed
99
100
101
}


102
103
bool Foam::SHA1Digest::empty() const
{
104
    for (const auto& byteVal : dig_)
105
    {
106
        if (byteVal)
107
108
109
110
111
112
113
114
115
        {
            return false;
        }
    }

    return true;
}


116
std::string Foam::SHA1Digest::str(const bool prefixed) const
117
118
119
{
    std::string buf;
    unsigned nChar = 0;
120
121
122

    if (prefixed)
    {
123
        buf.resize(1 + 2*dig_.size());
124
125
126
127
        buf[nChar++] = '_';
    }
    else
    {
128
        buf.resize(2*dig_.size());
129
130
    }

131
    for (const auto& byteVal : dig_)
132
    {
133
134
        buf[nChar++] = hexChars[((byteVal >> 4) & 0xF)];  // Upper nibble
        buf[nChar++] = hexChars[(byteVal & 0xF)];         // Lower nibble
135
136
137
138
139
140
    }

    return buf;
}


141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
Foam::Istream& Foam::SHA1Digest::read(Istream& is)
{
    for (auto& byteVal : dig_)
    {
        const unsigned char upp = readHexDigit(is);
        const unsigned char low = readHexDigit(is);

        byteVal = (upp << 4) + low;
    }

    is.check(FUNCTION_NAME);
    return is;
}


156
157
158
159
160
161
162
Foam::Ostream& Foam::SHA1Digest::write(Ostream& os, const bool prefixed) const
{
    if (prefixed)
    {
        os.write('_');
    }

163
    for (const auto& byteVal : dig_)
164
    {
165
166
        os.write(hexChars[((byteVal >> 4) & 0xF)]);  // Upper nibble
        os.write(hexChars[(byteVal & 0xF)]);         // Lower nibble
167
168
    }

169
    os.check(FUNCTION_NAME);
170
171
172
173
    return os;
}


Mark Olesen's avatar
Mark Olesen committed
174
175
// * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * * //

176
bool Foam::SHA1Digest::operator==(const SHA1Digest& rhs) const
Mark Olesen's avatar
Mark Olesen committed
177
{
178
    return (dig_ == rhs.dig_);
Mark Olesen's avatar
Mark Olesen committed
179
180
181
}


182
183
bool Foam::SHA1Digest::operator==(const std::string& hexdigits) const
{
184
    // Null or empty string is not an error - interpret as '0000..'
185
186
187
188
189
    if (hexdigits.empty())
    {
        return empty();
    }

190
191
    // Skip possible '_' prefix
    unsigned nChar = 0;
192
193
    if (hexdigits[0] == '_')
    {
194
        ++nChar;
195
196
    }

197
198
    // Incorrect length - can never match
    if (hexdigits.size() != nChar + 2*dig_.size())
199
200
201
202
    {
        return false;
    }

203
    for (const auto& byteVal : dig_)
204
    {
205
206
        const char upp = hexChars[((byteVal >> 4) & 0xF)];  // Upper nibble
        const char low = hexChars[(byteVal & 0xF)];         // Lower nibble
207

208
209
        if (upp != hexdigits[nChar++]) return false;
        if (low != hexdigits[nChar++]) return false;
210
211
212
213
214
215
216
217
    }

    return true;
}


bool Foam::SHA1Digest::operator==(const char* hexdigits) const
{
218
    // Null or empty string is not an error - interpret as '0000..'
219
220
221
222
223
    if (!hexdigits || !*hexdigits)
    {
        return empty();
    }

224
225
    // Skip possible '_' prefix
    unsigned nChar = 0;
226
227
    if (hexdigits[0] == '_')
    {
228
        ++nChar;
229
230
    }

231
232
    // Incorrect length - can never match
    if (strlen(hexdigits) != nChar + 2*dig_.size())
233
234
235
236
    {
        return false;
    }

237
    for (const auto& byteVal : dig_)
238
    {
239
240
        const char upp = hexChars[((byteVal >> 4) & 0xF)];
        const char low = hexChars[(byteVal & 0xF)];
241

242
243
        if (upp != hexdigits[nChar++]) return false;
        if (low != hexdigits[nChar++]) return false;
244
245
246
247
248
249
    }

    return true;
}


250
bool Foam::SHA1Digest::operator!=(const SHA1Digest& rhs) const
Mark Olesen's avatar
Mark Olesen committed
251
{
252
253
254
255
256
257
258
259
260
261
262
263
264
    return !operator==(rhs);
}


bool Foam::SHA1Digest::operator!=(const std::string& rhs) const
{
    return !operator==(rhs);
}


bool Foam::SHA1Digest::operator!=(const char* rhs) const
{
    return !operator==(rhs);
Mark Olesen's avatar
Mark Olesen committed
265
266
267
}


268
// * * * * * * * * * * * * * * * IOstream Operators  * * * * * * * * * * * * //
Mark Olesen's avatar
Mark Olesen committed
269

270
271
Foam::Istream& Foam::operator>>(Istream& is, SHA1Digest& dig)
{
272
    return dig.read(is);
273
274
275
}


276
Foam::Ostream& Foam::operator<<(Ostream& os, const SHA1Digest& dig)
Mark Olesen's avatar
Mark Olesen committed
277
{
278
    return dig.write(os);
Mark Olesen's avatar
Mark Olesen committed
279
280
281
282
}


// ************************************************************************* //