File indexing completed on 2025-07-05 08:50:32
0001 #ifndef BOOST_UUID_UUID_HPP_INCLUDED
0002 #define BOOST_UUID_UUID_HPP_INCLUDED
0003
0004
0005
0006
0007
0008
0009 #include <boost/uuid/uuid_clock.hpp>
0010 #include <boost/uuid/detail/endian.hpp>
0011 #include <boost/uuid/detail/hash_mix.hpp>
0012 #include <boost/uuid/detail/config.hpp>
0013 #include <boost/type_traits/integral_constant.hpp> // for Serialization support
0014 #include <boost/config.hpp>
0015 #include <boost/config/workaround.hpp>
0016 #include <array>
0017 #include <chrono>
0018 #include <typeindex> // cheapest std::hash
0019 #include <cstddef>
0020 #include <cstdint>
0021 #include <cstring>
0022
0023 #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L && defined(__has_include)
0024 # if __has_include(<compare>)
0025 # include <compare>
0026 # if defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
0027 # define BOOST_UUID_HAS_THREE_WAY_COMPARISON __cpp_lib_three_way_comparison
0028 # elif defined(_LIBCPP_VERSION)
0029
0030 # define BOOST_UUID_HAS_THREE_WAY_COMPARISON _LIBCPP_VERSION
0031 # endif
0032 # endif
0033 #endif
0034
0035 namespace boost {
0036 namespace uuids {
0037
0038 struct uuid
0039 {
0040 private:
0041
0042 using repr_type = std::uint8_t[ 16 ];
0043
0044 struct data_type
0045 {
0046 private:
0047
0048 union
0049 {
0050 #if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
0051
0052 std::uint8_t repr_[ 16 ] = {};
0053
0054 #else
0055
0056 std::uint8_t repr_[ 16 ];
0057
0058 #endif
0059
0060 #if !defined(BOOST_UUID_DISABLE_ALIGNMENT)
0061
0062 std::uint64_t align_u64_;
0063
0064 #endif
0065 };
0066
0067 public:
0068
0069 operator repr_type& () noexcept { return repr_; }
0070 operator repr_type const& () const noexcept { return repr_; }
0071
0072 std::uint8_t* operator()() noexcept { return repr_; }
0073 std::uint8_t const* operator()() const noexcept { return repr_; }
0074
0075 #if BOOST_WORKAROUND(BOOST_MSVC, < 1930)
0076
0077 std::uint8_t* operator+( std::ptrdiff_t i ) noexcept { return repr_ + i; }
0078 std::uint8_t const* operator+( std::ptrdiff_t i ) const noexcept { return repr_ + i; }
0079
0080 std::uint8_t& operator[]( std::ptrdiff_t i ) noexcept { return repr_[ i ]; }
0081 std::uint8_t const& operator[]( std::ptrdiff_t i ) const noexcept { return repr_[ i ]; }
0082
0083 #endif
0084 };
0085
0086 public:
0087
0088
0089
0090 #if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
0091
0092 data_type data;
0093
0094 #else
0095
0096 data_type data = {};
0097
0098 #endif
0099
0100 public:
0101
0102
0103
0104 uuid() = default;
0105
0106 uuid( repr_type const& r )
0107 {
0108 std::memcpy( data, r, 16 );
0109 }
0110
0111
0112
0113 using value_type = std::uint8_t;
0114 using reference = std::uint8_t&;
0115 using const_reference = std::uint8_t const&;
0116 using iterator = std::uint8_t*;
0117 using const_iterator = std::uint8_t const*;
0118 using size_type = std::size_t;
0119 using difference_type = std::ptrdiff_t;
0120
0121 iterator begin() noexcept { return data; }
0122 const_iterator begin() const noexcept { return data; }
0123
0124 iterator end() noexcept { return data + size(); }
0125 const_iterator end() const noexcept { return data + size(); }
0126
0127
0128
0129 constexpr size_type size() const noexcept { return static_size(); }
0130
0131
0132
0133
0134
0135 static constexpr size_type static_size() noexcept { return 16; }
0136
0137
0138
0139 bool is_nil() const noexcept;
0140
0141
0142
0143 enum variant_type
0144 {
0145 variant_ncs,
0146 variant_rfc_4122,
0147 variant_microsoft,
0148 variant_future
0149 };
0150
0151 variant_type variant() const noexcept
0152 {
0153
0154
0155 unsigned char octet7 = data[8];
0156 if ( (octet7 & 0x80) == 0x00 ) {
0157 return variant_ncs;
0158 } else if ( (octet7 & 0xC0) == 0x80 ) {
0159 return variant_rfc_4122;
0160 } else if ( (octet7 & 0xE0) == 0xC0 ) {
0161 return variant_microsoft;
0162 } else {
0163
0164 return variant_future;
0165 }
0166 }
0167
0168
0169
0170 enum version_type
0171 {
0172 version_unknown = -1,
0173 version_time_based = 1,
0174 version_dce_security = 2,
0175 version_name_based_md5 = 3,
0176 version_random_number_based = 4,
0177 version_name_based_sha1 = 5,
0178 version_time_based_v6 = 6,
0179 version_time_based_v7 = 7,
0180 version_custom_v8 = 8
0181 };
0182
0183 version_type version() const noexcept
0184 {
0185
0186
0187 std::uint8_t octet9 = data[6];
0188 if ( (octet9 & 0xF0) == 0x10 ) {
0189 return version_time_based;
0190 } else if ( (octet9 & 0xF0) == 0x20 ) {
0191 return version_dce_security;
0192 } else if ( (octet9 & 0xF0) == 0x30 ) {
0193 return version_name_based_md5;
0194 } else if ( (octet9 & 0xF0) == 0x40 ) {
0195 return version_random_number_based;
0196 } else if ( (octet9 & 0xF0) == 0x50 ) {
0197 return version_name_based_sha1;
0198 } else if ( (octet9 & 0xF0) == 0x60 ) {
0199 return version_time_based_v6;
0200 } else if ( (octet9 & 0xF0) == 0x70 ) {
0201 return version_time_based_v7;
0202 } else if ( (octet9 & 0xF0) == 0x80 ) {
0203 return version_custom_v8;
0204 } else {
0205 return version_unknown;
0206 }
0207 }
0208
0209
0210
0211 using timestamp_type = std::uint64_t;
0212
0213 timestamp_type timestamp_v1() const noexcept
0214 {
0215 std::uint32_t time_low = detail::load_big_u32( this->data + 0 );
0216 std::uint16_t time_mid = detail::load_big_u16( this->data + 4 );
0217 std::uint16_t time_hi = detail::load_big_u16( this->data + 6 ) & 0x0FFF;
0218
0219 return time_low | static_cast<std::uint64_t>( time_mid ) << 32 | static_cast<std::uint64_t>( time_hi ) << 48;
0220 }
0221
0222 timestamp_type timestamp_v6() const noexcept
0223 {
0224 std::uint32_t time_high = detail::load_big_u32( this->data + 0 );
0225 std::uint16_t time_mid = detail::load_big_u16( this->data + 4 );
0226 std::uint16_t time_low = detail::load_big_u16( this->data + 6 ) & 0x0FFF;
0227
0228 return time_low | static_cast<std::uint64_t>( time_mid ) << 12 | static_cast<std::uint64_t>( time_high ) << 28;
0229 }
0230
0231 timestamp_type timestamp_v7() const noexcept
0232 {
0233 std::uint64_t time_and_version = detail::load_big_u64( this->data + 0 );
0234 return time_and_version >> 16;
0235 }
0236
0237
0238
0239 uuid_clock::time_point time_point_v1() const noexcept
0240 {
0241 return uuid_clock::from_timestamp( timestamp_v1() );
0242 }
0243
0244 uuid_clock::time_point time_point_v6() const noexcept
0245 {
0246 return uuid_clock::from_timestamp( timestamp_v6() );
0247 }
0248
0249 std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds> time_point_v7() const noexcept
0250 {
0251 return std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>( std::chrono::milliseconds( timestamp_v7() ) );
0252 }
0253
0254
0255
0256 using clock_seq_type = std::uint16_t;
0257
0258 clock_seq_type clock_seq() const noexcept
0259 {
0260 return detail::load_big_u16( this->data + 8 ) & 0x3FFF;
0261 }
0262
0263
0264
0265 using node_type = std::array<std::uint8_t, 6>;
0266
0267 node_type node_identifier() const noexcept
0268 {
0269 node_type node = {};
0270
0271 std::memcpy( node.data(), this->data + 10, 6 );
0272 return node;
0273 }
0274
0275
0276
0277 void swap( uuid& rhs ) noexcept;
0278 };
0279
0280
0281
0282 inline bool operator==( uuid const& lhs, uuid const& rhs ) noexcept;
0283 inline bool operator< ( uuid const& lhs, uuid const& rhs ) noexcept;
0284
0285 inline bool operator!=( uuid const& lhs, uuid const& rhs ) noexcept
0286 {
0287 return !(lhs == rhs);
0288 }
0289
0290 inline bool operator>( uuid const& lhs, uuid const& rhs ) noexcept
0291 {
0292 return rhs < lhs;
0293 }
0294 inline bool operator<=( uuid const& lhs, uuid const& rhs ) noexcept
0295 {
0296 return !(rhs < lhs);
0297 }
0298
0299 inline bool operator>=( uuid const& lhs, uuid const& rhs ) noexcept
0300 {
0301 return !(lhs < rhs);
0302 }
0303
0304 #if defined(BOOST_UUID_HAS_THREE_WAY_COMPARISON)
0305
0306 inline std::strong_ordering operator<=>( uuid const& lhs, uuid const& rhs ) noexcept;
0307
0308 #endif
0309
0310
0311
0312 inline void swap( uuid& lhs, uuid& rhs ) noexcept
0313 {
0314 lhs.swap( rhs );
0315 }
0316
0317
0318
0319 inline std::size_t hash_value( uuid const& u ) noexcept
0320 {
0321 std::uint64_t r = 0;
0322
0323 r = detail::hash_mix_mx( r + detail::load_little_u32( u.data + 0 ) );
0324 r = detail::hash_mix_mx( r + detail::load_little_u32( u.data + 4 ) );
0325 r = detail::hash_mix_mx( r + detail::load_little_u32( u.data + 8 ) );
0326 r = detail::hash_mix_mx( r + detail::load_little_u32( u.data + 12 ) );
0327
0328 return static_cast<std::size_t>( detail::hash_mix_fmx( r ) );
0329 }
0330
0331 }}
0332
0333
0334
0335
0336
0337 namespace boost
0338 {
0339 namespace serialization
0340 {
0341
0342 template<class T> struct implementation_level_impl;
0343 template<> struct implementation_level_impl<const uuids::uuid>: boost::integral_constant<int, 1> {};
0344
0345 }
0346 }
0347
0348
0349
0350 namespace std
0351 {
0352
0353 template<> struct hash<boost::uuids::uuid>
0354 {
0355 std::size_t operator()( boost::uuids::uuid const& value ) const noexcept
0356 {
0357 return boost::uuids::hash_value( value );
0358 }
0359 };
0360
0361 }
0362
0363 #if defined(BOOST_UUID_USE_SSE2)
0364 # include <boost/uuid/detail/uuid_x86.ipp>
0365 #elif defined(__SIZEOF_INT128__)
0366 # include <boost/uuid/detail/uuid_uint128.ipp>
0367 #else
0368 # include <boost/uuid/detail/uuid_generic.ipp>
0369 #endif
0370
0371 #endif