basic_name_generator.hpp 5.0 KB

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