Toplevel entrypoints for classes/traits/interfaces
[hiphop-php.git] / hphp / util / sha1.h
blobe10ee489227fc57dea78442dc597112ea327dba3
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
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 +----------------------------------------------------------------------+
17 #pragma once
19 #include <array>
20 #include <cstdlib>
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"
30 namespace HPHP {
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 static constexpr size_t kStrLen = kQNumWords * kQWordHexLen;
43 std::array<uint32_t, kQNumWords> q;
45 SHA1() : q{} {}
47 /**
48 * Build from a SHA1 hexadecimal string
50 explicit SHA1(folly::StringPiece str) {
51 assertx(str.size() == kStrLen);
53 char buf[kQWordHexLen + 1];
54 buf[kQWordHexLen] = '\0';
55 for (auto i = 0; i < kQNumWords; i++) {
56 memcpy(buf, str.begin() + (i * kQWordHexLen), kQWordHexLen);
57 q.at(i) = strtoul(buf, nullptr, 16);
61 // Blob is assumed to be in network byte order.
62 explicit SHA1(const void* blob, DEBUG_ONLY size_t len) {
63 assertx(len == kQNumWords * kQWordLen);
65 for (auto i = 0; i < kQNumWords; i++) {
66 q.at(i) = ntohl(reinterpret_cast<const uint32_t*>(blob)[i]);
70 explicit SHA1(uint64_t x): q{} {
71 q.at(kQNumWords - 2) = x >> 32;
72 q.at(kQNumWords - 1) = x;
75 // Copy out in network byte order.
76 void nbo(void* blob) const {
77 for (auto i = 0; i < kQNumWords; i++) {
78 reinterpret_cast<uint32_t*>(blob)[i] = htonl(q.at(i));
82 std::string toString() const {
83 std::string ret;
84 char sha1nbo[kQNumWords * kQWordLen];
85 nbo(sha1nbo);
86 folly::hexlify(folly::StringPiece(sha1nbo, sizeof sha1nbo), ret);
87 return ret;
90 // Convert to a string using an arbitrary base-64 alphabet. This
91 // leaves two unused bits (27 base-64 characters is 162 bits), which
92 // can be used to encode extra data.
93 std::string toStringBase64(unsigned int extra = 0) const {
94 assertx(extra < 4); // Only room for two bits
96 static const char table[64] = {
97 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
98 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
99 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
100 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D',
101 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
102 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
103 'Y', 'Z', '_', '+'
106 std::string ret;
107 char sha1nbo[kQNumWords * kQWordLen];
108 nbo(sha1nbo);
110 // Below logic is specialized for this size:
111 static_assert(sizeof(sha1nbo) == 20);
112 ret.reserve(27);
113 for (size_t i = 0; i < sizeof(sha1nbo)-2; i += 3) {
114 ret.push_back(table[(sha1nbo[i] >> 2) & 0x3F]);
115 ret.push_back(table[((sha1nbo[i] & 0x03) << 4) |
116 ((sha1nbo[i+1] & 0xF0) >> 4)]);
117 ret.push_back(table[((sha1nbo[i+1] & 0x0F) << 2) |
118 ((sha1nbo[i+2] & 0xC0) >> 6)]);
119 ret.push_back(table[sha1nbo[i+2] & 0x3F]);
121 ret.push_back(table[(sha1nbo[sizeof(sha1nbo)-2] >> 2) & 0x3F]);
122 ret.push_back(table[((sha1nbo[sizeof(sha1nbo)-2] & 0x03) << 4) |
123 ((sha1nbo[sizeof(sha1nbo)-1] & 0xF0) >> 4)]);
124 ret.push_back(table[((sha1nbo[sizeof(sha1nbo)-1] & 0x0F) << 2) + extra]);
125 return ret;
128 bool operator==(const SHA1& r) const {
129 for (auto i = 0; i < kQNumWords; i++) {
130 if (q.at(i) != r.q.at(i)) {
131 return false;
134 return true;
137 bool operator<(const SHA1& r) const {
138 for (auto i = 0; i < kQNumWords; i++) {
139 if (q.at(i) < r.q.at(i)) {
140 return true;
143 if (q.at(i) > r.q.at(i)) {
144 return false;
147 return false;
150 uint64_t hash() const {
151 // All the bits here are fantastically good.
152 return (uint64_t(q[0]) << 32) + q[1];
155 template <typename SerDe> void serde(SerDe& serde) {
156 for (auto& w : q) serde(w);
160 //////////////////////////////////////////////////////////////////////