372 lines
9.7 KiB
C++
372 lines
9.7 KiB
C++
#ifndef BOOST_UUID_UUID_HPP_INCLUDED
|
|
#define BOOST_UUID_UUID_HPP_INCLUDED
|
|
|
|
// Copyright 2006 Andy Tompkins
|
|
// Copyright 2024 Peter Dimov
|
|
// Distributed under the Boost Software License, Version 1.0.
|
|
// https://www.boost.org/LICENSE_1_0.txt
|
|
|
|
#include <boost/uuid/uuid_clock.hpp>
|
|
#include <boost/uuid/detail/endian.hpp>
|
|
#include <boost/uuid/detail/hash_mix.hpp>
|
|
#include <boost/uuid/detail/config.hpp>
|
|
#include <boost/type_traits/integral_constant.hpp> // for Serialization support
|
|
#include <boost/config.hpp>
|
|
#include <boost/config/workaround.hpp>
|
|
#include <array>
|
|
#include <chrono>
|
|
#include <typeindex> // cheapest std::hash
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <cstring>
|
|
|
|
#if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L && defined(__has_include)
|
|
# if __has_include(<compare>)
|
|
# include <compare>
|
|
# if defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
|
|
# define BOOST_UUID_HAS_THREE_WAY_COMPARISON __cpp_lib_three_way_comparison
|
|
# elif defined(_LIBCPP_VERSION)
|
|
// https://github.com/llvm/llvm-project/issues/73953
|
|
# define BOOST_UUID_HAS_THREE_WAY_COMPARISON _LIBCPP_VERSION
|
|
# endif
|
|
# endif
|
|
#endif
|
|
|
|
namespace boost {
|
|
namespace uuids {
|
|
|
|
struct uuid
|
|
{
|
|
private:
|
|
|
|
using repr_type = std::uint8_t[ 16 ];
|
|
|
|
struct data_type
|
|
{
|
|
private:
|
|
|
|
union
|
|
{
|
|
#if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
|
|
|
|
std::uint8_t repr_[ 16 ] = {};
|
|
|
|
#else
|
|
|
|
std::uint8_t repr_[ 16 ];
|
|
|
|
#endif
|
|
|
|
#if !defined(BOOST_UUID_DISABLE_ALIGNMENT)
|
|
|
|
std::uint64_t align_u64_;
|
|
|
|
#endif
|
|
};
|
|
|
|
public:
|
|
|
|
operator repr_type& () noexcept { return repr_; }
|
|
operator repr_type const& () const noexcept { return repr_; }
|
|
|
|
std::uint8_t* operator()() noexcept { return repr_; }
|
|
std::uint8_t const* operator()() const noexcept { return repr_; }
|
|
|
|
#if BOOST_WORKAROUND(BOOST_MSVC, < 1930)
|
|
|
|
std::uint8_t* operator+( std::ptrdiff_t i ) noexcept { return repr_ + i; }
|
|
std::uint8_t const* operator+( std::ptrdiff_t i ) const noexcept { return repr_ + i; }
|
|
|
|
std::uint8_t& operator[]( std::ptrdiff_t i ) noexcept { return repr_[ i ]; }
|
|
std::uint8_t const& operator[]( std::ptrdiff_t i ) const noexcept { return repr_[ i ]; }
|
|
|
|
#endif
|
|
};
|
|
|
|
public:
|
|
|
|
// data
|
|
|
|
#if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
|
|
|
|
data_type data;
|
|
|
|
#else
|
|
|
|
data_type data = {};
|
|
|
|
#endif
|
|
|
|
public:
|
|
|
|
// constructors
|
|
|
|
uuid() = default;
|
|
|
|
uuid( repr_type const& r )
|
|
{
|
|
std::memcpy( data, r, 16 );
|
|
}
|
|
|
|
// iteration
|
|
|
|
using value_type = std::uint8_t;
|
|
using reference = std::uint8_t&;
|
|
using const_reference = std::uint8_t const&;
|
|
using iterator = std::uint8_t*;
|
|
using const_iterator = std::uint8_t const*;
|
|
using size_type = std::size_t;
|
|
using difference_type = std::ptrdiff_t;
|
|
|
|
iterator begin() noexcept { return data; }
|
|
const_iterator begin() const noexcept { return data; }
|
|
|
|
iterator end() noexcept { return data + size(); }
|
|
const_iterator end() const noexcept { return data + size(); }
|
|
|
|
// size
|
|
|
|
constexpr size_type size() const noexcept { return static_size(); }
|
|
|
|
// This does not work on some compilers
|
|
// They seem to want the variable defined in
|
|
// a cpp file
|
|
//BOOST_STATIC_CONSTANT(size_type, static_size = 16);
|
|
static constexpr size_type static_size() noexcept { return 16; }
|
|
|
|
// is_nil
|
|
|
|
bool is_nil() const noexcept;
|
|
|
|
// variant
|
|
|
|
enum variant_type
|
|
{
|
|
variant_ncs, // NCS backward compatibility
|
|
variant_rfc_4122, // defined in RFC 4122 document
|
|
variant_microsoft, // Microsoft Corporation backward compatibility
|
|
variant_future // future definition
|
|
};
|
|
|
|
variant_type variant() const noexcept
|
|
{
|
|
// variant is stored in octet 7
|
|
// which is index 8, since indexes count backwards
|
|
unsigned char octet7 = data[8]; // octet 7 is array index 8
|
|
if ( (octet7 & 0x80) == 0x00 ) { // 0b0xxxxxxx
|
|
return variant_ncs;
|
|
} else if ( (octet7 & 0xC0) == 0x80 ) { // 0b10xxxxxx
|
|
return variant_rfc_4122;
|
|
} else if ( (octet7 & 0xE0) == 0xC0 ) { // 0b110xxxxx
|
|
return variant_microsoft;
|
|
} else {
|
|
//assert( (octet7 & 0xE0) == 0xE0 ) // 0b111xxxx
|
|
return variant_future;
|
|
}
|
|
}
|
|
|
|
// version
|
|
|
|
enum version_type
|
|
{
|
|
version_unknown = -1,
|
|
version_time_based = 1,
|
|
version_dce_security = 2,
|
|
version_name_based_md5 = 3,
|
|
version_random_number_based = 4,
|
|
version_name_based_sha1 = 5,
|
|
version_time_based_v6 = 6,
|
|
version_time_based_v7 = 7,
|
|
version_custom_v8 = 8
|
|
};
|
|
|
|
version_type version() const noexcept
|
|
{
|
|
// version is stored in octet 9
|
|
// which is index 6, since indexes count backwards
|
|
std::uint8_t octet9 = data[6];
|
|
if ( (octet9 & 0xF0) == 0x10 ) {
|
|
return version_time_based;
|
|
} else if ( (octet9 & 0xF0) == 0x20 ) {
|
|
return version_dce_security;
|
|
} else if ( (octet9 & 0xF0) == 0x30 ) {
|
|
return version_name_based_md5;
|
|
} else if ( (octet9 & 0xF0) == 0x40 ) {
|
|
return version_random_number_based;
|
|
} else if ( (octet9 & 0xF0) == 0x50 ) {
|
|
return version_name_based_sha1;
|
|
} else if ( (octet9 & 0xF0) == 0x60 ) {
|
|
return version_time_based_v6;
|
|
} else if ( (octet9 & 0xF0) == 0x70 ) {
|
|
return version_time_based_v7;
|
|
} else if ( (octet9 & 0xF0) == 0x80 ) {
|
|
return version_custom_v8;
|
|
} else {
|
|
return version_unknown;
|
|
}
|
|
}
|
|
|
|
// timestamp
|
|
|
|
using timestamp_type = std::uint64_t;
|
|
|
|
timestamp_type timestamp_v1() const noexcept
|
|
{
|
|
std::uint32_t time_low = detail::load_big_u32( this->data + 0 );
|
|
std::uint16_t time_mid = detail::load_big_u16( this->data + 4 );
|
|
std::uint16_t time_hi = detail::load_big_u16( this->data + 6 ) & 0x0FFF;
|
|
|
|
return time_low | static_cast<std::uint64_t>( time_mid ) << 32 | static_cast<std::uint64_t>( time_hi ) << 48;
|
|
}
|
|
|
|
timestamp_type timestamp_v6() const noexcept
|
|
{
|
|
std::uint32_t time_high = detail::load_big_u32( this->data + 0 );
|
|
std::uint16_t time_mid = detail::load_big_u16( this->data + 4 );
|
|
std::uint16_t time_low = detail::load_big_u16( this->data + 6 ) & 0x0FFF;
|
|
|
|
return time_low | static_cast<std::uint64_t>( time_mid ) << 12 | static_cast<std::uint64_t>( time_high ) << 28;
|
|
}
|
|
|
|
timestamp_type timestamp_v7() const noexcept
|
|
{
|
|
std::uint64_t time_and_version = detail::load_big_u64( this->data + 0 );
|
|
return time_and_version >> 16;
|
|
}
|
|
|
|
// time_point
|
|
|
|
uuid_clock::time_point time_point_v1() const noexcept
|
|
{
|
|
return uuid_clock::from_timestamp( timestamp_v1() );
|
|
}
|
|
|
|
uuid_clock::time_point time_point_v6() const noexcept
|
|
{
|
|
return uuid_clock::from_timestamp( timestamp_v6() );
|
|
}
|
|
|
|
std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds> time_point_v7() const noexcept
|
|
{
|
|
return std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>( std::chrono::milliseconds( timestamp_v7() ) );
|
|
}
|
|
|
|
// clock_seq
|
|
|
|
using clock_seq_type = std::uint16_t;
|
|
|
|
clock_seq_type clock_seq() const noexcept
|
|
{
|
|
return detail::load_big_u16( this->data + 8 ) & 0x3FFF;
|
|
}
|
|
|
|
// node_identifier
|
|
|
|
using node_type = std::array<std::uint8_t, 6>;
|
|
|
|
node_type node_identifier() const noexcept
|
|
{
|
|
node_type node = {};
|
|
|
|
std::memcpy( node.data(), this->data + 10, 6 );
|
|
return node;
|
|
}
|
|
|
|
// swap
|
|
|
|
void swap( uuid& rhs ) noexcept;
|
|
};
|
|
|
|
// operators
|
|
|
|
inline bool operator==( uuid const& lhs, uuid const& rhs ) noexcept;
|
|
inline bool operator< ( uuid const& lhs, uuid const& rhs ) noexcept;
|
|
|
|
inline bool operator!=( uuid const& lhs, uuid const& rhs ) noexcept
|
|
{
|
|
return !(lhs == rhs);
|
|
}
|
|
|
|
inline bool operator>( uuid const& lhs, uuid const& rhs ) noexcept
|
|
{
|
|
return rhs < lhs;
|
|
}
|
|
inline bool operator<=( uuid const& lhs, uuid const& rhs ) noexcept
|
|
{
|
|
return !(rhs < lhs);
|
|
}
|
|
|
|
inline bool operator>=( uuid const& lhs, uuid const& rhs ) noexcept
|
|
{
|
|
return !(lhs < rhs);
|
|
}
|
|
|
|
#if defined(BOOST_UUID_HAS_THREE_WAY_COMPARISON)
|
|
|
|
inline std::strong_ordering operator<=>( uuid const& lhs, uuid const& rhs ) noexcept;
|
|
|
|
#endif
|
|
|
|
// swap
|
|
|
|
inline void swap( uuid& lhs, uuid& rhs ) noexcept
|
|
{
|
|
lhs.swap( rhs );
|
|
}
|
|
|
|
// hash_value
|
|
|
|
inline std::size_t hash_value( uuid const& u ) noexcept
|
|
{
|
|
std::uint64_t r = 0;
|
|
|
|
r = detail::hash_mix_mx( r + detail::load_little_u32( u.data + 0 ) );
|
|
r = detail::hash_mix_mx( r + detail::load_little_u32( u.data + 4 ) );
|
|
r = detail::hash_mix_mx( r + detail::load_little_u32( u.data + 8 ) );
|
|
r = detail::hash_mix_mx( r + detail::load_little_u32( u.data + 12 ) );
|
|
|
|
return static_cast<std::size_t>( detail::hash_mix_fmx( r ) );
|
|
}
|
|
|
|
}} //namespace boost::uuids
|
|
|
|
// Boost.Serialization support
|
|
|
|
// BOOST_CLASS_IMPLEMENTATION(boost::uuids::uuid, boost::serialization::primitive_type)
|
|
|
|
namespace boost
|
|
{
|
|
namespace serialization
|
|
{
|
|
|
|
template<class T> struct implementation_level_impl;
|
|
template<> struct implementation_level_impl<const uuids::uuid>: boost::integral_constant<int, 1> {};
|
|
|
|
} // namespace serialization
|
|
} // namespace boost
|
|
|
|
// std::hash support
|
|
|
|
namespace std
|
|
{
|
|
|
|
template<> struct hash<boost::uuids::uuid>
|
|
{
|
|
std::size_t operator()( boost::uuids::uuid const& value ) const noexcept
|
|
{
|
|
return boost::uuids::hash_value( value );
|
|
}
|
|
};
|
|
|
|
} // namespace std
|
|
|
|
#if defined(BOOST_UUID_USE_SSE2)
|
|
# include <boost/uuid/detail/uuid_x86.ipp>
|
|
#elif defined(__SIZEOF_INT128__)
|
|
# include <boost/uuid/detail/uuid_uint128.ipp>
|
|
#else
|
|
# include <boost/uuid/detail/uuid_generic.ipp>
|
|
#endif
|
|
|
|
#endif // BOOST_UUID_UUID_HPP_INCLUDED
|