Chris@16
|
1 // Boost name_generator.hpp header file ----------------------------------------------//
|
Chris@16
|
2
|
Chris@16
|
3 // Copyright 2010 Andy Tompkins.
|
Chris@16
|
4 // Distributed under the Boost Software License, Version 1.0. (See
|
Chris@16
|
5 // accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
6 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
7
|
Chris@16
|
8 #ifndef BOOST_UUID_NAME_GENERATOR_HPP
|
Chris@16
|
9 #define BOOST_UUID_NAME_GENERATOR_HPP
|
Chris@16
|
10
|
Chris@16
|
11 #include <boost/uuid/uuid.hpp>
|
Chris@16
|
12 #include <boost/uuid/sha1.hpp>
|
Chris@16
|
13 #include <boost/assert.hpp>
|
Chris@16
|
14 #include <string>
|
Chris@16
|
15 #include <cstring> // for strlen, wcslen
|
Chris@16
|
16
|
Chris@16
|
17 #ifdef BOOST_NO_STDC_NAMESPACE
|
Chris@16
|
18 namespace std {
|
Chris@16
|
19 using ::strlen;
|
Chris@16
|
20 using ::wcslen;
|
Chris@16
|
21 } //namespace std
|
Chris@16
|
22 #endif //BOOST_NO_STDC_NAMESPACE
|
Chris@16
|
23
|
Chris@16
|
24 namespace boost {
|
Chris@16
|
25 namespace uuids {
|
Chris@16
|
26
|
Chris@16
|
27 // generate a name-based uuid
|
Chris@16
|
28 // TODO: add in common namesspace uuids
|
Chris@16
|
29 class name_generator {
|
Chris@16
|
30 public:
|
Chris@16
|
31 typedef uuid result_type;
|
Chris@16
|
32
|
Chris@101
|
33 explicit name_generator(uuid const& namespace_uuid_)
|
Chris@101
|
34 : namespace_uuid(namespace_uuid_)
|
Chris@16
|
35 {}
|
Chris@16
|
36
|
Chris@16
|
37 uuid operator()(const char* name) {
|
Chris@16
|
38 reset();
|
Chris@16
|
39 process_characters(name, std::strlen(name));
|
Chris@16
|
40 return sha_to_uuid();
|
Chris@16
|
41 }
|
Chris@16
|
42
|
Chris@16
|
43 uuid operator()(const wchar_t* name) {
|
Chris@16
|
44 reset();
|
Chris@16
|
45 process_characters(name, std::wcslen(name));
|
Chris@16
|
46 return sha_to_uuid();
|
Chris@16
|
47 }
|
Chris@16
|
48
|
Chris@16
|
49 template <typename ch, typename char_traits, typename alloc>
|
Chris@16
|
50 uuid operator()(std::basic_string<ch, char_traits, alloc> const& name) {
|
Chris@16
|
51 reset();
|
Chris@16
|
52 process_characters(name.c_str(), name.length());
|
Chris@16
|
53 return sha_to_uuid();
|
Chris@16
|
54 }
|
Chris@16
|
55
|
Chris@16
|
56 uuid operator()(void const* buffer, std::size_t byte_count) {
|
Chris@16
|
57 reset();
|
Chris@16
|
58 sha.process_bytes(buffer, byte_count);
|
Chris@16
|
59 return sha_to_uuid();
|
Chris@16
|
60 };
|
Chris@16
|
61
|
Chris@16
|
62 private:
|
Chris@16
|
63 // we convert all characters to uint32_t so that each
|
Chris@16
|
64 // character is 4 bytes reguardless of sizeof(char) or
|
Chris@16
|
65 // sizeof(wchar_t). We want the name string on any
|
Chris@16
|
66 // platform / compiler to generate the same uuid
|
Chris@16
|
67 // except for char
|
Chris@16
|
68 template <typename char_type>
|
Chris@16
|
69 void process_characters(char_type const*const characters, size_t count) {
|
Chris@16
|
70 BOOST_ASSERT(sizeof(uint32_t) >= sizeof(char_type));
|
Chris@16
|
71
|
Chris@16
|
72 for (size_t i=0; i<count; i++) {
|
Chris@16
|
73 uint32_t c = characters[i];
|
Chris@101
|
74 sha.process_byte(static_cast<unsigned char>((c >> 0) & 0xFF));
|
Chris@101
|
75 sha.process_byte(static_cast<unsigned char>((c >> 8) & 0xFF));
|
Chris@101
|
76 sha.process_byte(static_cast<unsigned char>((c >> 16) & 0xFF));
|
Chris@101
|
77 sha.process_byte(static_cast<unsigned char>((c >> 24) & 0xFF));
|
Chris@16
|
78 }
|
Chris@16
|
79 }
|
Chris@16
|
80
|
Chris@16
|
81 void process_characters(char const*const characters, size_t count) {
|
Chris@16
|
82 sha.process_bytes(characters, count);
|
Chris@16
|
83 }
|
Chris@16
|
84
|
Chris@16
|
85 void reset()
|
Chris@16
|
86 {
|
Chris@16
|
87 sha.reset();
|
Chris@16
|
88 sha.process_bytes(namespace_uuid.begin(), namespace_uuid.size());
|
Chris@16
|
89 }
|
Chris@16
|
90
|
Chris@16
|
91 uuid sha_to_uuid()
|
Chris@16
|
92 {
|
Chris@16
|
93 unsigned int digest[5];
|
Chris@16
|
94
|
Chris@16
|
95 sha.get_digest(digest);
|
Chris@16
|
96
|
Chris@16
|
97 uuid u;
|
Chris@16
|
98 for (int i=0; i<4; ++i) {
|
Chris@101
|
99 *(u.begin() + i*4+0) = static_cast<uint8_t>((digest[i] >> 24) & 0xFF);
|
Chris@101
|
100 *(u.begin() + i*4+1) = static_cast<uint8_t>((digest[i] >> 16) & 0xFF);
|
Chris@101
|
101 *(u.begin() + i*4+2) = static_cast<uint8_t>((digest[i] >> 8) & 0xFF);
|
Chris@101
|
102 *(u.begin() + i*4+3) = static_cast<uint8_t>((digest[i] >> 0) & 0xFF);
|
Chris@16
|
103 }
|
Chris@16
|
104
|
Chris@16
|
105 // set variant
|
Chris@16
|
106 // must be 0b10xxxxxx
|
Chris@16
|
107 *(u.begin()+8) &= 0xBF;
|
Chris@16
|
108 *(u.begin()+8) |= 0x80;
|
Chris@16
|
109
|
Chris@16
|
110 // set version
|
Chris@16
|
111 // must be 0b0101xxxx
|
Chris@16
|
112 *(u.begin()+6) &= 0x5F; //0b01011111
|
Chris@16
|
113 *(u.begin()+6) |= 0x50; //0b01010000
|
Chris@16
|
114
|
Chris@16
|
115 return u;
|
Chris@16
|
116 }
|
Chris@16
|
117
|
Chris@16
|
118 private:
|
Chris@16
|
119 uuid namespace_uuid;
|
Chris@16
|
120 detail::sha1 sha;
|
Chris@16
|
121 };
|
Chris@16
|
122
|
Chris@16
|
123 }} // namespace boost::uuids
|
Chris@16
|
124
|
Chris@16
|
125 #endif // BOOST_UUID_NAME_GENERATOR_HPP
|