Back to home page

EIC code displayed by LXR

 
 

    


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 // Boost basic_name_generator.hpp header file  -----------------------//
0005 
0006 // Copyright 2010 Andy Tompkins.
0007 // Copyright 2017 James E. King III
0008 
0009 // Distributed under the Boost Software License, Version 1.0. (See
0010 // accompanying file LICENSE_1_0.txt or copy at
0011 //  https://www.boost.org/LICENSE_1_0.txt)
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     // For portability, we convert all wide characters to uint32_t so that each
0083     // character is 4 bytes regardless of sizeof(wchar_t).
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; // Unicode replacement character
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         // set variant: must be 0b10xxxxxx
0201         *(u.begin()+8) &= 0x3F;
0202         *(u.begin()+8) |= 0x80;
0203 
0204         // set version
0205         unsigned char hashver = hash.get_version();
0206         *(u.begin()+6) &= 0x0F;             // clear out the relevant bits
0207         *(u.begin()+6) |= (hashver << 4);   // and apply them
0208 
0209         return u;
0210     }
0211 };
0212 
0213 } // namespace detail
0214 } // uuids
0215 } // boost
0216 
0217 #endif // BOOST_UUID_DETAIL_BASIC_NAME_GENERATOR_HPP_INCLUDED