2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
22 #include <boost/operators.hpp>
24 #include <folly/Range.h>
25 #include <folly/String.h>
27 #include "hphp/util/assertions.h"
28 #include "hphp/util/byte-order.h"
32 //////////////////////////////////////////////////////////////////////
34 struct SHA1
: private boost::totally_ordered
<SHA1
> {
35 static constexpr size_t kQNumWords
= 5;
36 static constexpr size_t kQWordLen
= sizeof(uint32_t);
38 // One byte = two ascii hex characters
39 static constexpr size_t kQWordHexLen
= 2 * kQWordLen
;
41 std::array
<uint32_t, kQNumWords
> q
;
46 * Build from a SHA1 hexadecimal string
48 explicit SHA1(folly::StringPiece str
) {
49 assertx(str
.size() == kQNumWords
* kQWordHexLen
);
51 char buf
[kQWordHexLen
+ 1];
52 buf
[kQWordHexLen
] = '\0';
53 for (auto i
= 0; i
< kQNumWords
; i
++) {
54 memcpy(buf
, str
.begin() + (i
* kQWordHexLen
), kQWordHexLen
);
55 q
.at(i
) = strtoul(buf
, nullptr, 16);
59 // Blob is assumed to be in network byte order.
60 explicit SHA1(const void* blob
, DEBUG_ONLY
size_t len
) {
61 assertx(len
== kQNumWords
* kQWordLen
);
63 for (auto i
= 0; i
< kQNumWords
; i
++) {
64 q
.at(i
) = ntohl(reinterpret_cast<const uint32_t*>(blob
)[i
]);
68 explicit SHA1(uint64_t x
): q
{} {
69 q
.at(kQNumWords
- 2) = x
>> 32;
70 q
.at(kQNumWords
- 1) = x
;
73 // Copy out in network byte order.
74 void nbo(void* blob
) const {
75 for (auto i
= 0; i
< kQNumWords
; i
++) {
76 reinterpret_cast<uint32_t*>(blob
)[i
] = htonl(q
.at(i
));
80 std::string
toString() const {
82 char sha1nbo
[kQNumWords
* kQWordLen
];
84 folly::hexlify(folly::StringPiece(sha1nbo
, sizeof sha1nbo
), ret
);
88 // Convert to a string using an arbitrary base-64 alphabet. This
89 // leaves two unused bits (27 base-64 characters is 162 bits), which
90 // can be used to encode extra data.
91 std::string
toStringBase64(unsigned int extra
= 0) const {
92 assertx(extra
< 4); // Only room for two bits
94 static const char table
[64] = {
95 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
96 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
97 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
98 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D',
99 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
100 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
105 char sha1nbo
[kQNumWords
* kQWordLen
];
108 // Below logic is specialized for this size:
109 static_assert(sizeof(sha1nbo
) == 20);
111 for (size_t i
= 0; i
< sizeof(sha1nbo
)-2; i
+= 3) {
112 ret
.push_back(table
[(sha1nbo
[i
] >> 2) & 0x3F]);
113 ret
.push_back(table
[((sha1nbo
[i
] & 0x03) << 4) |
114 ((sha1nbo
[i
+1] & 0xF0) >> 4)]);
115 ret
.push_back(table
[((sha1nbo
[i
+1] & 0x0F) << 2) |
116 ((sha1nbo
[i
+2] & 0xC0) >> 6)]);
117 ret
.push_back(table
[sha1nbo
[i
+2] & 0x3F]);
119 ret
.push_back(table
[(sha1nbo
[sizeof(sha1nbo
)-2] >> 2) & 0x3F]);
120 ret
.push_back(table
[((sha1nbo
[sizeof(sha1nbo
)-2] & 0x03) << 4) |
121 ((sha1nbo
[sizeof(sha1nbo
)-1] & 0xF0) >> 4)]);
122 ret
.push_back(table
[((sha1nbo
[sizeof(sha1nbo
)-1] & 0x0F) << 2) + extra
]);
126 bool operator==(const SHA1
& r
) const {
127 for (auto i
= 0; i
< kQNumWords
; i
++) {
128 if (q
.at(i
) != r
.q
.at(i
)) {
135 bool operator<(const SHA1
& r
) const {
136 for (auto i
= 0; i
< kQNumWords
; i
++) {
137 if (q
.at(i
) < r
.q
.at(i
)) {
141 if (q
.at(i
) > r
.q
.at(i
)) {
148 uint64_t hash() const {
149 // All the bits here are fantastically good.
150 return (uint64_t(q
[0]) << 32) + q
[1];
154 //////////////////////////////////////////////////////////////////////