liuxiaolong
2021-07-20 58d904a328c0d849769b483e901a0be9426b8209
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// Boost basic_name_generator.hpp header file  -----------------------//
 
// Copyright 2010 Andy Tompkins.
// Copyright 2017 James E. King III
 
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
//  https://www.boost.org/LICENSE_1_0.txt)
 
#ifndef BOOST_UUID_BASIC_NAME_GENERATOR_HPP
#define BOOST_UUID_BASIC_NAME_GENERATOR_HPP
 
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#include <boost/static_assert.hpp>
#include <boost/uuid/uuid.hpp>
#include <cstring> // for strlen, wcslen
#include <string>
 
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
 
#ifdef BOOST_NO_STDC_NAMESPACE
namespace std {
    using ::size_t;
    using ::strlen;
    using ::wcslen;
} //namespace std
#endif //BOOST_NO_STDC_NAMESPACE
 
namespace boost {
namespace uuids {
 
//! \brief Generate a name based UUID using
//!        the provided hashing algorithm that
//!        implements the NameHashProvider concept.
template<class HashAlgo>
class basic_name_generator
{
  public:
    typedef uuid result_type;
    typedef typename HashAlgo::digest_type digest_type;
 
    explicit basic_name_generator(uuid const& namespace_uuid_)
        : namespace_uuid(namespace_uuid_)
    {}
 
    uuid operator()(const char* name) const {
        HashAlgo hash;
        hash.process_bytes(namespace_uuid.begin(), namespace_uuid.size());
        process_characters(hash, name, std::strlen(name));
        return hash_to_uuid(hash);
    }
 
    uuid operator()(const wchar_t* name) const {
        HashAlgo hash;
        hash.process_bytes(namespace_uuid.begin(), namespace_uuid.size());
        process_characters(hash, name, std::wcslen(name));
        return hash_to_uuid(hash);
    }
 
    template <typename ch, typename char_traits, typename alloc>
    uuid operator()(std::basic_string<ch, char_traits, alloc> const& name) const {
        HashAlgo hash;
        hash.process_bytes(namespace_uuid.begin(), namespace_uuid.size());
        process_characters(hash, name.c_str(), name.length());
        return hash_to_uuid(hash);
    }
 
    uuid operator()(void const* buffer, std::size_t byte_count) const {
        HashAlgo hash;
        hash.process_bytes(namespace_uuid.begin(), namespace_uuid.size());
        hash.process_bytes(buffer, byte_count);
        return hash_to_uuid(hash);
    }
 
private:
    // we convert all characters to uint32_t so that each
    // character is 4 bytes regardless of sizeof(char) or
    // sizeof(wchar_t).  We want the name string on any
    // platform / compiler to generate the same uuid
    // except for char
    template <typename char_type>
    void process_characters(HashAlgo& hash, char_type const*const characters, std::size_t count) const {
        BOOST_STATIC_ASSERT(sizeof(uint32_t) >= sizeof(char_type));
 
        for (std::size_t i=0; i<count; i++) {
            std::size_t c = characters[i];
            hash.process_byte(static_cast<unsigned char>((c >>  0) & 0xFF));
            hash.process_byte(static_cast<unsigned char>((c >>  8) & 0xFF));
            hash.process_byte(static_cast<unsigned char>((c >> 16) & 0xFF));
            hash.process_byte(static_cast<unsigned char>((c >> 24) & 0xFF));
        }
    }
 
    void process_characters(HashAlgo& hash, char const*const characters, std::size_t count) const {
        hash.process_bytes(characters, count);
    }
 
    uuid hash_to_uuid(HashAlgo& hash) const
    {
        digest_type digest;
        hash.get_digest(digest);
 
        BOOST_STATIC_ASSERT(sizeof(digest_type) >= 16);
 
        uuid u;
        for (int i=0; i<4; ++i) {
            *(u.begin() + i*4+0) = static_cast<uint8_t>((digest[i] >> 24) & 0xFF);
            *(u.begin() + i*4+1) = static_cast<uint8_t>((digest[i] >> 16) & 0xFF);
            *(u.begin() + i*4+2) = static_cast<uint8_t>((digest[i] >> 8) & 0xFF);
            *(u.begin() + i*4+3) = static_cast<uint8_t>((digest[i] >> 0) & 0xFF);
        }
 
        // set variant: must be 0b10xxxxxx
        *(u.begin()+8) &= 0xBF;
        *(u.begin()+8) |= 0x80;
 
        // set version
        unsigned char hashver = hash.get_version();
        *(u.begin()+6) &= 0x0F;             // clear out the relevant bits
        *(u.begin()+6) |= (hashver << 4);   // and apply them
 
        return u;
    }
 
private:
    uuid namespace_uuid;
};
 
namespace ns {
 
BOOST_FORCEINLINE uuid dns() {
    uuid result = {{
        0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1 ,
        0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 }};
    return result;
}
 
BOOST_FORCEINLINE uuid url() {
    uuid result = {{
        0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1 ,
        0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 }};
    return result;
}
 
BOOST_FORCEINLINE uuid oid() {
    uuid result = {{
        0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1 ,
        0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 }};
    return result;
}
 
BOOST_FORCEINLINE uuid x500dn() {
    uuid result = {{
        0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1 ,
        0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 }};
    return result;
}
 
} // ns
} // uuids
} // boost
 
#endif // BOOST_UUID_BASIC_NAME_GENERATOR_HPP