FILENAME 3/4 - delete the old get_fun_path etc.
[hiphop-php.git] / hphp / util / sha1.h
blob6712c99e50579fe72b6e2da586bddb3681a9b0e6
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 std::array<uint32_t, kQNumWords> q;
43 SHA1() : q{} {}
45 /**
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 {
81 std::string ret;
82 char sha1nbo[kQNumWords * kQWordLen];
83 nbo(sha1nbo);
84 folly::hexlify(folly::StringPiece(sha1nbo, sizeof sha1nbo), ret);
85 return 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',
101 'Y', 'Z', '_', '+'
104 std::string ret;
105 char sha1nbo[kQNumWords * kQWordLen];
106 nbo(sha1nbo);
108 // Below logic is specialized for this size:
109 static_assert(sizeof(sha1nbo) == 20);
110 ret.reserve(27);
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]);
123 return ret;
126 bool operator==(const SHA1& r) const {
127 for (auto i = 0; i < kQNumWords; i++) {
128 if (q.at(i) != r.q.at(i)) {
129 return false;
132 return true;
135 bool operator<(const SHA1& r) const {
136 for (auto i = 0; i < kQNumWords; i++) {
137 if (q.at(i) < r.q.at(i)) {
138 return true;
141 if (q.at(i) > r.q.at(i)) {
142 return false;
145 return false;
148 uint64_t hash() const {
149 // All the bits here are fantastically good.
150 return (uint64_t(q[0]) << 32) + q[1];
154 //////////////////////////////////////////////////////////////////////