100.00% Lines (27/27) 100.00% Functions (1/1)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) 2   // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3   // 3   //
4   // Distributed under the Boost Software License, Version 1.0. (See accompanying 4   // Distributed under the Boost Software License, Version 1.0. (See accompanying
5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6   // 6   //
7   // Official repository: https://github.com/boostorg/json 7   // Official repository: https://github.com/boostorg/json
8   // 8   //
9   9  
10   #ifndef BOOST_JSON_DETAIL_DIGEST_HPP 10   #ifndef BOOST_JSON_DETAIL_DIGEST_HPP
11   #define BOOST_JSON_DETAIL_DIGEST_HPP 11   #define BOOST_JSON_DETAIL_DIGEST_HPP
12   12  
13   #include <boost/json/detail/config.hpp> 13   #include <boost/json/detail/config.hpp>
14   14  
15   #include <algorithm> 15   #include <algorithm>
16   #include <iterator> 16   #include <iterator>
17   17  
18   namespace boost { 18   namespace boost {
19   namespace json { 19   namespace json {
20   namespace detail { 20   namespace detail {
21   21  
22   // Calculate salted digest of string 22   // Calculate salted digest of string
23   template<class ForwardIterator> 23   template<class ForwardIterator>
24   std::size_t 24   std::size_t
HITCBC 25   11274 digest(ForwardIterator b, ForwardIterator e, std::size_t salt) noexcept 25   11251 digest(ForwardIterator b, ForwardIterator e, std::size_t salt) noexcept
26   { 26   {
HITCBC 27   11274 std::size_t const len = std::distance(b, e); 27   11251 std::size_t const len = std::distance(b, e);
28   28  
29   #if BOOST_JSON_ARCH == 64 29   #if BOOST_JSON_ARCH == 64
30   30  
31   using state_type = std::uint64_t; 31   using state_type = std::uint64_t;
HITCBC 32   11274 state_type const m = 0xc6a4a7935bd1e995ULL; 32   11251 state_type const m = 0xc6a4a7935bd1e995ULL;
HITCBC 33   11274 int const r = 47; 33   11251 int const r = 47;
HITCBC 34   11274 state_type hash = salt ^ (len * m); 34   11251 state_type hash = salt ^ (len * m);
35   35  
HITCBC 36   11274 constexpr std::size_t N = sizeof(state_type); 36   11251 constexpr std::size_t N = sizeof(state_type);
HITCBC 37   11274 e = std::next( b, len & ~std::size_t(N-1) ); 37   11251 e = std::next( b, len & ~std::size_t(N-1) );
HITCBC 38   11304 for( ; b != e; std::advance(b, N) ) 38   11281 for( ; b != e; std::advance(b, N) )
39   { 39   {
40   state_type num; 40   state_type num;
41   #ifdef _MSC_VER 41   #ifdef _MSC_VER
42   # pragma warning(push) 42   # pragma warning(push)
43   # pragma warning(disable: 4996) 43   # pragma warning(disable: 4996)
44   #endif 44   #endif
HITCBC 45   30 std::copy_n( b, N, reinterpret_cast<unsigned char*>(&num) ); 45   30 std::copy_n( b, N, reinterpret_cast<unsigned char*>(&num) );
46   #ifdef _MSC_VER 46   #ifdef _MSC_VER
47   # pragma warning(pop) 47   # pragma warning(pop)
48   #endif 48   #endif
49   49  
HITCBC 50   30 num *= m; 50   30 num *= m;
HITCBC 51   30 num ^= num >> r; 51   30 num ^= num >> r;
HITCBC 52   30 num *= m; 52   30 num *= m;
HITCBC 53   30 hash ^= num; 53   30 hash ^= num;
HITCBC 54   30 hash *= m; 54   30 hash *= m;
55   } 55   }
56   56  
HITCBC 57   11274 switch( len & (N - 1) ) 57   11251 switch( len & (N - 1) )
58   { 58   {
HITCBC 59   12 case 7: hash ^= state_type( *std::next(b, 6) ) << 48; // fall through 59   12 case 7: hash ^= state_type( *std::next(b, 6) ) << 48; // fall through
HITCBC 60   24 case 6: hash ^= state_type( *std::next(b, 5) ) << 40; // fall through 60   24 case 6: hash ^= state_type( *std::next(b, 5) ) << 40; // fall through
HITCBC 61   40 case 5: hash ^= state_type( *std::next(b, 4) ) << 32; // fall through 61   40 case 5: hash ^= state_type( *std::next(b, 4) ) << 32; // fall through
HITCBC 62   70 case 4: hash ^= state_type( *std::next(b, 3) ) << 24; // fall through 62   70 case 4: hash ^= state_type( *std::next(b, 3) ) << 24; // fall through
HITCBC 63   5502 case 3: hash ^= state_type( *std::next(b, 2) ) << 16; // fall through 63   5502 case 3: hash ^= state_type( *std::next(b, 2) ) << 16; // fall through
HITCBC 64   12624 case 2: hash ^= state_type( *std::next(b, 1) ) << 8; // fall through 64   12624 case 2: hash ^= state_type( *std::next(b, 1) ) << 8; // fall through
HITCBC 65   11284 case 1: hash ^= state_type( *std::next(b, 0) ); 65   11261 case 1: hash ^= state_type( *std::next(b, 0) );
HITCBC 66   11268 hash *= m; 66   11245 hash *= m;
67   }; 67   };
68   68  
HITCBC 69   11274 hash ^= hash >> r; 69   11251 hash ^= hash >> r;
HITCBC 70   11274 hash *= m; 70   11251 hash *= m;
HITCBC 71   11274 hash ^= hash >> r; 71   11251 hash ^= hash >> r;
72   72  
73   #else 73   #else
74   74  
75   using state_type = std::uint32_t; 75   using state_type = std::uint32_t;
76   state_type const m = 0x5bd1e995; 76   state_type const m = 0x5bd1e995;
77   int const r = 24; 77   int const r = 24;
78   state_type hash = salt ^ len; 78   state_type hash = salt ^ len;
79   79  
80   constexpr std::size_t N = sizeof(state_type); 80   constexpr std::size_t N = sizeof(state_type);
81   e = std::next( b, len & ~std::size_t(N-1) ); 81   e = std::next( b, len & ~std::size_t(N-1) );
82   for( ; b != e; std::advance(b, N) ) 82   for( ; b != e; std::advance(b, N) )
83   { 83   {
84   state_type num; 84   state_type num;
85   std::copy_n( b, N, reinterpret_cast<unsigned char*>(&num) ); 85   std::copy_n( b, N, reinterpret_cast<unsigned char*>(&num) );
86   86  
87   num *= m; 87   num *= m;
88   num ^= num >> r; 88   num ^= num >> r;
89   num *= m; 89   num *= m;
90   hash *= m; 90   hash *= m;
91   hash ^= num; 91   hash ^= num;
92   } 92   }
93   93  
94   switch( len & (N - 1) ) 94   switch( len & (N - 1) )
95   { 95   {
96   case 3: hash ^= state_type( *std::next(b, 2) ) << 16; // fall through 96   case 3: hash ^= state_type( *std::next(b, 2) ) << 16; // fall through
97   case 2: hash ^= state_type( *std::next(b, 1) ) << 8; // fall through 97   case 2: hash ^= state_type( *std::next(b, 1) ) << 8; // fall through
98   case 1: hash ^= state_type( *std::next(b, 0) ); 98   case 1: hash ^= state_type( *std::next(b, 0) );
99   hash *= m; 99   hash *= m;
100   }; 100   };
101   101  
102   hash ^= hash >> 13; 102   hash ^= hash >> 13;
103   hash *= m; 103   hash *= m;
104   hash ^= hash >> 15; 104   hash ^= hash >> 15;
105   105  
106   #endif 106   #endif
107   107  
HITCBC 108   11274 return hash; 108   11251 return hash;
109   } 109   }
110   110  
111   } // detail 111   } // detail
112   } // namespace json 112   } // namespace json
113   } // namespace boost 113   } // namespace boost
114   114  
115   #endif 115   #endif