Warning, file /include/boost/uuid/detail/basic_name_generator.hpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 #ifndef BOOST_UUID_DETAIL_BASIC_NAME_GENERATOR_HPP_INCLUDED
0002 #define BOOST_UUID_DETAIL_BASIC_NAME_GENERATOR_HPP_INCLUDED
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <boost/uuid/namespaces.hpp>
0014 #include <boost/uuid/uuid.hpp>
0015 #include <boost/uuid/detail/static_assert.hpp>
0016 #include <boost/config.hpp>
0017 #include <string>
0018 #include <cstdint>
0019 #include <cstring> // for strlen, wcslen
0020
0021 namespace boost {
0022 namespace uuids {
0023 namespace detail {
0024
0025 template<class HashAlgo>
0026 class basic_name_generator
0027 {
0028 private:
0029
0030 uuid namespace_uuid_;
0031
0032 private:
0033
0034 using digest_type = typename HashAlgo::digest_type;
0035
0036 public:
0037
0038 using result_type = uuid;
0039
0040 explicit basic_name_generator( uuid const& namespace_uuid ) noexcept
0041 : namespace_uuid_( namespace_uuid )
0042 {}
0043
0044 template<class Ch> uuid operator()( Ch const* name ) const noexcept
0045 {
0046 HashAlgo hash;
0047
0048 hash.process_bytes( namespace_uuid_.begin(), namespace_uuid_.size() );
0049 process_characters( hash, name, std::char_traits<Ch>().length( name ) );
0050
0051 return hash_to_uuid( hash );
0052 }
0053
0054 template<class Ch, class Traits, class Alloc>
0055 uuid operator()( std::basic_string<Ch, Traits, Alloc> const& name ) const noexcept
0056 {
0057 HashAlgo hash;
0058
0059 hash.process_bytes( namespace_uuid_.begin(), namespace_uuid_.size() );
0060 process_characters( hash, name.c_str(), name.length() );
0061
0062 return hash_to_uuid( hash );
0063 }
0064
0065 uuid operator()( void const* buffer, std::size_t byte_count ) const noexcept
0066 {
0067 HashAlgo hash;
0068
0069 hash.process_bytes( namespace_uuid_.begin(), namespace_uuid_.size() );
0070 hash.process_bytes( buffer, byte_count );
0071
0072 return hash_to_uuid( hash );
0073 }
0074
0075 private:
0076
0077 void process_characters( HashAlgo& hash, char const* p, std::size_t n ) const noexcept
0078 {
0079 hash.process_bytes( p, n );
0080 }
0081
0082
0083
0084
0085 void process_characters( HashAlgo& hash, wchar_t const* p, std::size_t n ) const noexcept
0086 {
0087 BOOST_UUID_STATIC_ASSERT( sizeof( std::uint32_t ) >= sizeof( wchar_t ) );
0088
0089 for( std::size_t i = 0; i < n; ++i)
0090 {
0091 std::uint32_t ch = p[ i ];
0092
0093 unsigned char bytes[ 4 ] =
0094 {
0095 static_cast<unsigned char>( ( ch >> 0 ) & 0xFF ),
0096 static_cast<unsigned char>( ( ch >> 8 ) & 0xFF ),
0097 static_cast<unsigned char>( ( ch >> 16 ) & 0xFF ),
0098 static_cast<unsigned char>( ( ch >> 24 ) & 0xFF )
0099 };
0100
0101 hash.process_bytes( bytes, 4 );
0102 }
0103 }
0104
0105 void process_characters( HashAlgo& hash, char32_t const* p, std::size_t n ) const noexcept
0106 {
0107 for( std::size_t i = 0; i < n; ++i)
0108 {
0109 process_utf32_codepoint( hash, p[ i ] );
0110 }
0111 }
0112
0113 void process_characters( HashAlgo& hash, char16_t const* p, std::size_t n ) const noexcept
0114 {
0115 for( std::size_t i = 0; i < n; ++i)
0116 {
0117 char16_t ch = p[ i ];
0118
0119 if( ch >= 0xD800 && ch <= 0xDBFF && i + 1 < n && p[ i+1 ] >= 0xDC00 && p[ i+1 ] <= 0xDFFF )
0120 {
0121 char16_t ch2 = p[ ++i ];
0122
0123 std::uint32_t high = ch - 0xD800;
0124 std::uint32_t low = ch2 - 0xDC00;
0125
0126 process_utf32_codepoint( hash, ( high << 10 ) + low + 0x10000 );
0127 }
0128 else
0129 {
0130 process_utf32_codepoint( hash, ch );
0131 }
0132 }
0133 }
0134
0135 void process_utf32_codepoint( HashAlgo& hash, std::uint32_t cp ) const noexcept
0136 {
0137 if( ( cp >= 0xD800 && cp <= 0xDFFF ) || cp > 0x10FFFF )
0138 {
0139 cp = 0xFFFD;
0140 }
0141
0142 if( cp < 0x80 )
0143 {
0144 hash.process_byte( static_cast<unsigned char>( cp ) );
0145 }
0146 else if( cp < 0x800 )
0147 {
0148 unsigned char bytes[ 2 ] =
0149 {
0150 static_cast<unsigned char>( 0xC0 | (cp >> 6) ),
0151 static_cast<unsigned char>( 0x80 | (cp & 0x3F) )
0152 };
0153
0154 hash.process_bytes( bytes, 2 );
0155 }
0156 else if( cp < 0x10000 )
0157 {
0158 unsigned char bytes[ 3 ] =
0159 {
0160 static_cast<unsigned char>( 0xE0 | (cp >> 12) ),
0161 static_cast<unsigned char>( 0x80 | ((cp >> 6) & 0x3F) ),
0162 static_cast<unsigned char>( 0x80 | (cp & 0x3F) )
0163 };
0164
0165 hash.process_bytes( bytes, 3 );
0166 }
0167 else
0168 {
0169 unsigned char bytes[ 4 ] =
0170 {
0171 static_cast<unsigned char>( 0xF0 | ( cp >> 18 ) ),
0172 static_cast<unsigned char>( 0x80 | ((cp >> 12 ) & 0x3F ) ),
0173 static_cast<unsigned char>( 0x80 | ((cp >> 6 ) & 0x3F ) ),
0174 static_cast<unsigned char>( 0x80 | (cp & 0x3F) )
0175 };
0176
0177 hash.process_bytes( bytes, 4 );
0178 }
0179 }
0180
0181 #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L
0182
0183 void process_characters( HashAlgo& hash, char8_t const* p, std::size_t n ) const noexcept
0184 {
0185 hash.process_bytes( p, n );
0186 }
0187
0188 #endif
0189
0190 uuid hash_to_uuid( HashAlgo& hash ) const noexcept
0191 {
0192 digest_type digest;
0193 hash.get_digest(digest);
0194
0195 BOOST_UUID_STATIC_ASSERT( sizeof(digest_type) >= 16 );
0196
0197 uuid u;
0198 std::memcpy( u.data, digest, 16 );
0199
0200
0201 *(u.begin()+8) &= 0x3F;
0202 *(u.begin()+8) |= 0x80;
0203
0204
0205 unsigned char hashver = hash.get_version();
0206 *(u.begin()+6) &= 0x0F;
0207 *(u.begin()+6) |= (hashver << 4);
0208
0209 return u;
0210 }
0211 };
0212
0213 }
0214 }
0215 }
0216
0217 #endif