123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- #ifndef BOOST_UUID_DETAIL_BASIC_NAME_GENERATOR_HPP_INCLUDED
- #define BOOST_UUID_DETAIL_BASIC_NAME_GENERATOR_HPP_INCLUDED
- // 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)
- #include <boost/uuid/namespaces.hpp>
- #include <boost/uuid/uuid.hpp>
- #include <boost/uuid/detail/static_assert.hpp>
- #include <boost/config.hpp>
- #include <string>
- #include <cstdint>
- #include <cstring> // for strlen, wcslen
- namespace boost {
- namespace uuids {
- namespace detail {
- template<class HashAlgo>
- class basic_name_generator
- {
- private:
- uuid namespace_uuid_;
- private:
- using digest_type = typename HashAlgo::digest_type;
- public:
- using result_type = uuid;
- explicit basic_name_generator( uuid const& namespace_uuid ) noexcept
- : namespace_uuid_( namespace_uuid )
- {}
- template<class Ch> uuid operator()( Ch const* name ) const noexcept
- {
- HashAlgo hash;
- hash.process_bytes( namespace_uuid_.begin(), namespace_uuid_.size() );
- process_characters( hash, name, std::char_traits<Ch>().length( name ) );
- return hash_to_uuid( hash );
- }
- template<class Ch, class Traits, class Alloc>
- uuid operator()( std::basic_string<Ch, Traits, Alloc> const& name ) const noexcept
- {
- 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 noexcept
- {
- HashAlgo hash;
- hash.process_bytes( namespace_uuid_.begin(), namespace_uuid_.size() );
- hash.process_bytes( buffer, byte_count );
- return hash_to_uuid( hash );
- }
- private:
- void process_characters( HashAlgo& hash, char const* p, std::size_t n ) const noexcept
- {
- hash.process_bytes( p, n );
- }
- // For portability, we convert all wide characters to uint32_t so that each
- // character is 4 bytes regardless of sizeof(wchar_t).
- void process_characters( HashAlgo& hash, wchar_t const* p, std::size_t n ) const noexcept
- {
- BOOST_UUID_STATIC_ASSERT( sizeof( std::uint32_t ) >= sizeof( wchar_t ) );
- for( std::size_t i = 0; i < n; ++i)
- {
- std::uint32_t ch = p[ i ];
- unsigned char bytes[ 4 ] =
- {
- static_cast<unsigned char>( ( ch >> 0 ) & 0xFF ),
- static_cast<unsigned char>( ( ch >> 8 ) & 0xFF ),
- static_cast<unsigned char>( ( ch >> 16 ) & 0xFF ),
- static_cast<unsigned char>( ( ch >> 24 ) & 0xFF )
- };
- hash.process_bytes( bytes, 4 );
- }
- }
- void process_characters( HashAlgo& hash, char32_t const* p, std::size_t n ) const noexcept
- {
- for( std::size_t i = 0; i < n; ++i)
- {
- process_utf32_codepoint( hash, p[ i ] );
- }
- }
- void process_characters( HashAlgo& hash, char16_t const* p, std::size_t n ) const noexcept
- {
- for( std::size_t i = 0; i < n; ++i)
- {
- char16_t ch = p[ i ];
- if( ch >= 0xD800 && ch <= 0xDBFF && i + 1 < n && p[ i+1 ] >= 0xDC00 && p[ i+1 ] <= 0xDFFF )
- {
- char16_t ch2 = p[ ++i ];
- std::uint32_t high = ch - 0xD800;
- std::uint32_t low = ch2 - 0xDC00;
- process_utf32_codepoint( hash, ( high << 10 ) + low + 0x10000 );
- }
- else
- {
- process_utf32_codepoint( hash, ch );
- }
- }
- }
- void process_utf32_codepoint( HashAlgo& hash, std::uint32_t cp ) const noexcept
- {
- if( ( cp >= 0xD800 && cp <= 0xDFFF ) || cp > 0x10FFFF )
- {
- cp = 0xFFFD; // Unicode replacement character
- }
- if( cp < 0x80 )
- {
- hash.process_byte( static_cast<unsigned char>( cp ) );
- }
- else if( cp < 0x800 )
- {
- unsigned char bytes[ 2 ] =
- {
- static_cast<unsigned char>( 0xC0 | (cp >> 6) ),
- static_cast<unsigned char>( 0x80 | (cp & 0x3F) )
- };
- hash.process_bytes( bytes, 2 );
- }
- else if( cp < 0x10000 )
- {
- unsigned char bytes[ 3 ] =
- {
- static_cast<unsigned char>( 0xE0 | (cp >> 12) ),
- static_cast<unsigned char>( 0x80 | ((cp >> 6) & 0x3F) ),
- static_cast<unsigned char>( 0x80 | (cp & 0x3F) )
- };
- hash.process_bytes( bytes, 3 );
- }
- else
- {
- unsigned char bytes[ 4 ] =
- {
- static_cast<unsigned char>( 0xF0 | ( cp >> 18 ) ),
- static_cast<unsigned char>( 0x80 | ((cp >> 12 ) & 0x3F ) ),
- static_cast<unsigned char>( 0x80 | ((cp >> 6 ) & 0x3F ) ),
- static_cast<unsigned char>( 0x80 | (cp & 0x3F) )
- };
- hash.process_bytes( bytes, 4 );
- }
- }
- #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L
- void process_characters( HashAlgo& hash, char8_t const* p, std::size_t n ) const noexcept
- {
- hash.process_bytes( p, n );
- }
- #endif
- uuid hash_to_uuid( HashAlgo& hash ) const noexcept
- {
- digest_type digest;
- hash.get_digest(digest);
- BOOST_UUID_STATIC_ASSERT( sizeof(digest_type) >= 16 );
- uuid u;
- std::memcpy( u.data, digest, 16 );
- // set variant: must be 0b10xxxxxx
- *(u.begin()+8) &= 0x3F;
- *(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;
- }
- };
- } // namespace detail
- } // uuids
- } // boost
- #endif // BOOST_UUID_DETAIL_BASIC_NAME_GENERATOR_HPP_INCLUDED
|