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 -
#include <boost/json/detail/config.hpp>
 
13 -

 
14 -
#include <algorithm>
 
15 -
#include <iterator>
 
16 -

 
17  

12  

18  
namespace boost {
13  
namespace boost {
19  
namespace json {
14  
namespace json {
20  
namespace detail {
15  
namespace detail {
21  

16  

22  
// Calculate salted digest of string
17  
// Calculate salted digest of string
23  
template<class ForwardIterator>
18  
template<class ForwardIterator>
24  
std::size_t
19  
std::size_t
25 -
digest(ForwardIterator b, ForwardIterator e, std::size_t salt) noexcept
20 +
digest(
 
21 +
    ForwardIterator b,
 
22 +
    ForwardIterator e,
 
23 +
    std::size_t salt) noexcept
26 -
    std::size_t const len = std::distance(b, e);
 
27 -

 
28  
{
24  
{
29  
#if BOOST_JSON_ARCH == 64
25  
#if BOOST_JSON_ARCH == 64
30 -

26 +
    std::uint64_t const prime = 0x100000001B3ULL;
31 -
    using state_type = std::uint64_t;
27 +
    std::uint64_t hash  = 0xcbf29ce484222325ULL;
32 -
    state_type const m = 0xc6a4a7935bd1e995ULL;
 
33 -
    int const r = 47;
 
34 -
    state_type hash = salt ^ (len * m);
 
35 -

 
36 -
    constexpr std::size_t N = sizeof(state_type);
 
37 -
    e = std::next( b, len & ~std::size_t(N-1) );
 
38 -
    for( ; b != e; std::advance(b, N) )
 
39 -
    {
 
40 -
        state_type num;
 
41 -
#ifdef _MSC_VER
 
42 -
# pragma warning(push)
 
43 -
# pragma warning(disable: 4996)
 
44 -
#endif
 
45 -
        std::copy_n( b, N, reinterpret_cast<unsigned char*>(&num) );
 
46 -
#ifdef _MSC_VER
 
47 -
# pragma warning(pop)
 
48 -
#endif
 
49 -

 
50 -
        num *= m;
 
51 -
        num ^= num >> r;
 
52 -
        num *= m;
 
53 -
        hash ^= num;
 
54 -
        hash *= m;
 
55 -
    }
 
56 -

 
57 -
    switch( len & (N - 1) )
 
58 -
    {
 
59 -
    case 7: hash ^= state_type( *std::next(b, 6) ) << 48; // fall through
 
60 -
    case 6: hash ^= state_type( *std::next(b, 5) ) << 40; // fall through
 
61 -
    case 5: hash ^= state_type( *std::next(b, 4) ) << 32; // fall through
 
62 -
    case 4: hash ^= state_type( *std::next(b, 3) ) << 24; // fall through
 
63 -
    case 3: hash ^= state_type( *std::next(b, 2) ) << 16; // fall through
 
64 -
    case 2: hash ^= state_type( *std::next(b, 1) ) << 8;  // fall through
 
65 -
    case 1: hash ^= state_type( *std::next(b, 0) );
 
66 -
            hash *= m;
 
67 -
    };
 
68 -

 
69 -
    hash ^= hash >> r;
 
70 -
    hash *= m;
 
71 -
    hash ^= hash >> r;
 
72 -

 
73  
#else
28  
#else
74 -

29 +
    std::uint32_t const prime = 0x01000193UL;
75 -
    using state_type = std::uint32_t;
30 +
    std::uint32_t hash  = 0x811C9DC5UL;
76 -
    state_type const m = 0x5bd1e995;
 
77 -
    int const r = 24;
 
78 -
    state_type hash = salt ^ len;
 
79 -

 
80 -
    constexpr std::size_t N = sizeof(state_type);
 
81 -
    e = std::next( b, len & ~std::size_t(N-1) );
 
82 -
    for( ; b != e; std::advance(b, N) )
 
83 -
    {
 
84 -
        state_type num;
 
85 -
        std::copy_n( b, N, reinterpret_cast<unsigned char*>(&num) );
 
86 -

 
87 -
        num *= m;
 
88 -
        num ^= num >> r;
 
89 -
        num *= m;
 
90 -
        hash *= m;
 
91 -
        hash ^= num;
 
92 -
    }
 
93 -

 
94 -
    switch( len & (N - 1) )
 
95 -
    {
 
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
 
98 -
    case 1: hash ^= state_type( *std::next(b, 0) );
 
99 -
            hash *= m;
 
100 -
    };
 
101 -

 
102 -
    hash ^= hash >> 13;
 
103 -
    hash *= m;
 
104 -
    hash ^= hash >> 15;
 
105 -

 
106  
#endif
31  
#endif
107 -

32 +
    hash += salt;
 
33 +
    for(; b != e; ++b)
 
34 +
        hash = (*b ^ hash) * prime;
108  
    return hash;
35  
    return hash;
109  
}
36  
}
110  

37  

111  
} // detail
38  
} // detail
112  
} // namespace json
39  
} // namespace json
113  
} // namespace boost
40  
} // namespace boost
114  

41  

115  
#endif
42  
#endif