Declare variables as inline

Declare empty_guid and guid_encoder as inline to fix multiple defined
symbol errors when compiling with clang++.
This commit is contained in:
Jason 2022-01-04 07:26:47 -08:00
parent 9357e5280c
commit 5f739d3e26

View File

@ -69,16 +69,16 @@ namespace uuids
template <typename TChar> template <typename TChar>
constexpr inline bool is_hex(TChar const ch) constexpr inline bool is_hex(TChar const ch)
{ {
return return (ch >= static_cast<TChar>('0') && ch <= static_cast<TChar>('9')) ||
(ch >= static_cast<TChar>('0') && ch <= static_cast<TChar>('9')) ||
(ch >= static_cast<TChar>('a') && ch <= static_cast<TChar>('f')) || (ch >= static_cast<TChar>('a') && ch <= static_cast<TChar>('f')) ||
(ch >= static_cast<TChar>('A') && ch <= static_cast<TChar>('F')); (ch >= static_cast<TChar>('A') && ch <= static_cast<TChar>('F'));
} }
template <typename TChar> template <typename TChar>
constexpr std::basic_string_view<TChar> to_string_view(TChar const * str) constexpr std::basic_string_view<TChar> to_string_view(TChar const *str)
{ {
if (str) return str; if (str)
return str;
return {}; return {};
} }
@ -86,7 +86,7 @@ namespace uuids
constexpr std::basic_string_view< constexpr std::basic_string_view<
typename StringType::value_type, typename StringType::value_type,
typename StringType::traits_type> typename StringType::traits_type>
to_string_view(StringType const & str) to_string_view(StringType const &str)
{ {
return str; return str;
} }
@ -128,10 +128,10 @@ namespace uuids
} }
} }
void process_block(void const * const start, void const * const end) void process_block(void const *const start, void const *const end)
{ {
const uint8_t* begin = static_cast<const uint8_t*>(start); const uint8_t *begin = static_cast<const uint8_t *>(start);
const uint8_t* finish = static_cast<const uint8_t*>(end); const uint8_t *finish = static_cast<const uint8_t *>(end);
while (begin != finish) while (begin != finish)
{ {
process_byte(*begin); process_byte(*begin);
@ -139,26 +139,31 @@ namespace uuids
} }
} }
void process_bytes(void const * const data, size_t const len) void process_bytes(void const *const data, size_t const len)
{ {
const uint8_t* block = static_cast<const uint8_t*>(data); const uint8_t *block = static_cast<const uint8_t *>(data);
process_block(block, block + len); process_block(block, block + len);
} }
uint32_t const * get_digest(digest32_t digest) uint32_t const *get_digest(digest32_t digest)
{ {
size_t const bitCount = this->m_byteCount * 8; size_t const bitCount = this->m_byteCount * 8;
process_byte(0x80); process_byte(0x80);
if (this->m_blockByteIndex > 56) { if (this->m_blockByteIndex > 56)
while (m_blockByteIndex != 0) { {
while (m_blockByteIndex != 0)
{
process_byte(0); process_byte(0);
} }
while (m_blockByteIndex < 56) { while (m_blockByteIndex < 56)
{
process_byte(0); process_byte(0);
} }
} }
else { else
while (m_blockByteIndex < 56) { {
while (m_blockByteIndex < 56)
{
process_byte(0); process_byte(0);
} }
} }
@ -169,13 +174,13 @@ namespace uuids
process_byte(static_cast<unsigned char>((bitCount >> 24) & 0xFF)); process_byte(static_cast<unsigned char>((bitCount >> 24) & 0xFF));
process_byte(static_cast<unsigned char>((bitCount >> 16) & 0xFF)); process_byte(static_cast<unsigned char>((bitCount >> 16) & 0xFF));
process_byte(static_cast<unsigned char>((bitCount >> 8) & 0xFF)); process_byte(static_cast<unsigned char>((bitCount >> 8) & 0xFF));
process_byte(static_cast<unsigned char>((bitCount) & 0xFF)); process_byte(static_cast<unsigned char>((bitCount)&0xFF));
memcpy(digest, m_digest, 5 * sizeof(uint32_t)); memcpy(digest, m_digest, 5 * sizeof(uint32_t));
return digest; return digest;
} }
uint8_t const * get_digest_bytes(digest8_t digest) uint8_t const *get_digest_bytes(digest8_t digest)
{ {
digest32_t d32; digest32_t d32;
get_digest(d32); get_digest(d32);
@ -212,13 +217,15 @@ namespace uuids
void process_block() void process_block()
{ {
uint32_t w[80]; uint32_t w[80];
for (size_t i = 0; i < 16; i++) { for (size_t i = 0; i < 16; i++)
{
w[i] = static_cast<uint32_t>(m_block[i * 4 + 0] << 24); w[i] = static_cast<uint32_t>(m_block[i * 4 + 0] << 24);
w[i] |= static_cast<uint32_t>(m_block[i * 4 + 1] << 16); w[i] |= static_cast<uint32_t>(m_block[i * 4 + 1] << 16);
w[i] |= static_cast<uint32_t>(m_block[i * 4 + 2] << 8); w[i] |= static_cast<uint32_t>(m_block[i * 4 + 2] << 8);
w[i] |= static_cast<uint32_t>(m_block[i * 4 + 3]); w[i] |= static_cast<uint32_t>(m_block[i * 4 + 3]);
} }
for (size_t i = 16; i < 80; i++) { for (size_t i = 16; i < 80; i++)
{
w[i] = left_rotate((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1); w[i] = left_rotate((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1);
} }
@ -233,19 +240,23 @@ namespace uuids
uint32_t f = 0; uint32_t f = 0;
uint32_t k = 0; uint32_t k = 0;
if (i < 20) { if (i < 20)
{
f = (b & c) | (~b & d); f = (b & c) | (~b & d);
k = 0x5A827999; k = 0x5A827999;
} }
else if (i < 40) { else if (i < 40)
{
f = b ^ c ^ d; f = b ^ c ^ d;
k = 0x6ED9EBA1; k = 0x6ED9EBA1;
} }
else if (i < 60) { else if (i < 60)
{
f = (b & c) | (b & d) | (c & d); f = (b & c) | (b & d) | (c & d);
k = 0x8F1BBCDC; k = 0x8F1BBCDC;
} }
else { else
{
f = b ^ c ^ d; f = b ^ c ^ d;
k = 0xCA62C1D6; k = 0xCA62C1D6;
} }
@ -272,16 +283,16 @@ namespace uuids
}; };
template <typename CharT> template <typename CharT>
constexpr CharT empty_guid[37] = "00000000-0000-0000-0000-000000000000"; inline constexpr CharT empty_guid[37] = "00000000-0000-0000-0000-000000000000";
template <> template <>
constexpr wchar_t empty_guid<wchar_t>[37] = L"00000000-0000-0000-0000-000000000000"; inline constexpr wchar_t empty_guid<wchar_t>[37] = L"00000000-0000-0000-0000-000000000000";
template <typename CharT> template <typename CharT>
constexpr CharT guid_encoder[17] = "0123456789abcdef"; inline constexpr CharT guid_encoder[17] = "0123456789abcdef";
template <> template <>
constexpr wchar_t guid_encoder<wchar_t>[17] = L"0123456789abcdef"; inline constexpr wchar_t guid_encoder<wchar_t>[17] = L"0123456789abcdef";
} }
// -------------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------------
@ -362,19 +373,19 @@ namespace uuids
constexpr uuid() noexcept = default; constexpr uuid() noexcept = default;
uuid(value_type(&arr)[16]) noexcept uuid(value_type (&arr)[16]) noexcept
{ {
std::copy(std::cbegin(arr), std::cend(arr), std::begin(data)); std::copy(std::cbegin(arr), std::cend(arr), std::begin(data));
} }
constexpr uuid(std::array<value_type, 16> const & arr) noexcept : data{arr} {} constexpr uuid(std::array<value_type, 16> const &arr) noexcept : data{arr} {}
explicit uuid(span<value_type, 16> bytes) explicit uuid(span<value_type, 16> bytes)
{ {
std::copy(std::cbegin(bytes), std::cend(bytes), std::begin(data)); std::copy(std::cbegin(bytes), std::cend(bytes), std::begin(data));
} }
template<typename ForwardIterator> template <typename ForwardIterator>
explicit uuid(ForwardIterator first, ForwardIterator last) explicit uuid(ForwardIterator first, ForwardIterator last)
{ {
if (std::distance(first, last) == 16) if (std::distance(first, last) == 16)
@ -411,22 +422,24 @@ namespace uuids
constexpr bool is_nil() const noexcept constexpr bool is_nil() const noexcept
{ {
for (size_t i = 0; i < data.size(); ++i) if (data[i] != 0) return false; for (size_t i = 0; i < data.size(); ++i)
if (data[i] != 0)
return false;
return true; return true;
} }
void swap(uuid & other) noexcept void swap(uuid &other) noexcept
{ {
data.swap(other.data); data.swap(other.data);
} }
inline span<std::byte const, 16> as_bytes() const inline span<std::byte const, 16> as_bytes() const
{ {
return span<std::byte const, 16>(reinterpret_cast<std::byte const*>(data.data()), 16); return span<std::byte const, 16>(reinterpret_cast<std::byte const *>(data.data()), 16);
} }
template <typename StringType> template <typename StringType>
constexpr static bool is_valid_uuid(StringType const & in_str) noexcept constexpr static bool is_valid_uuid(StringType const &in_str) noexcept
{ {
auto str = detail::to_string_view(in_str); auto str = detail::to_string_view(in_str);
bool firstDigit = true; bool firstDigit = true;
@ -443,7 +456,8 @@ namespace uuids
for (size_t i = hasBraces; i < str.size() - hasBraces; ++i) for (size_t i = hasBraces; i < str.size() - hasBraces; ++i)
{ {
if (str[i] == '-') continue; if (str[i] == '-')
continue;
if (index >= 16 || !detail::is_hex(str[i])) if (index >= 16 || !detail::is_hex(str[i]))
{ {
@ -470,16 +484,17 @@ namespace uuids
} }
template <typename StringType> template <typename StringType>
constexpr static std::optional<uuid> from_string(StringType const & in_str) noexcept constexpr static std::optional<uuid> from_string(StringType const &in_str) noexcept
{ {
auto str = detail::to_string_view(in_str); auto str = detail::to_string_view(in_str);
bool firstDigit = true; bool firstDigit = true;
size_t hasBraces = 0; size_t hasBraces = 0;
size_t index = 0; size_t index = 0;
std::array<uint8_t, 16> data{ { 0 } }; std::array<uint8_t, 16> data{{0}};
if (str.empty()) return {}; if (str.empty())
return {};
if (str.front() == '{') if (str.front() == '{')
hasBraces = 1; hasBraces = 1;
@ -488,7 +503,8 @@ namespace uuids
for (size_t i = hasBraces; i < str.size() - hasBraces; ++i) for (size_t i = hasBraces; i < str.size() - hasBraces; ++i)
{ {
if (str[i] == '-') continue; if (str[i] == '-')
continue;
if (index >= 16 || !detail::is_hex(str[i])) if (index >= 16 || !detail::is_hex(str[i]))
{ {
@ -513,20 +529,20 @@ namespace uuids
return {}; return {};
} }
return uuid{ data }; return uuid{data};
} }
private: private:
std::array<value_type, 16> data{ { 0 } }; std::array<value_type, 16> data{{0}};
friend bool operator==(uuid const & lhs, uuid const & rhs) noexcept; friend bool operator==(uuid const &lhs, uuid const &rhs) noexcept;
friend bool operator<(uuid const & lhs, uuid const & rhs) noexcept; friend bool operator<(uuid const &lhs, uuid const &rhs) noexcept;
template <class Elem, class Traits> template <class Elem, class Traits>
friend std::basic_ostream<Elem, Traits> & operator<<(std::basic_ostream<Elem, Traits> &s, uuid const & id); friend std::basic_ostream<Elem, Traits> &operator<<(std::basic_ostream<Elem, Traits> &s, uuid const &id);
template<class CharT, class Traits, class Allocator> template <class CharT, class Traits, class Allocator>
friend std::basic_string<CharT, Traits, Allocator> to_string(uuid const& id); friend std::basic_string<CharT, Traits, Allocator> to_string(uuid const &id);
friend std::hash<uuid>; friend std::hash<uuid>;
}; };
@ -535,25 +551,25 @@ namespace uuids
// operators and non-member functions // operators and non-member functions
// -------------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------------
inline bool operator== (uuid const& lhs, uuid const& rhs) noexcept inline bool operator==(uuid const &lhs, uuid const &rhs) noexcept
{ {
return lhs.data == rhs.data; return lhs.data == rhs.data;
} }
inline bool operator!= (uuid const& lhs, uuid const& rhs) noexcept inline bool operator!=(uuid const &lhs, uuid const &rhs) noexcept
{ {
return !(lhs == rhs); return !(lhs == rhs);
} }
inline bool operator< (uuid const& lhs, uuid const& rhs) noexcept inline bool operator<(uuid const &lhs, uuid const &rhs) noexcept
{ {
return lhs.data < rhs.data; return lhs.data < rhs.data;
} }
template<class CharT = char, template <class CharT = char,
class Traits = std::char_traits<CharT>, class Traits = std::char_traits<CharT>,
class Allocator = std::allocator<CharT>> class Allocator = std::allocator<CharT>>
inline std::basic_string<CharT, Traits, Allocator> to_string(uuid const & id) inline std::basic_string<CharT, Traits, Allocator> to_string(uuid const &id)
{ {
std::basic_string<CharT, Traits, Allocator> uustr{detail::empty_guid<CharT>}; std::basic_string<CharT, Traits, Allocator> uustr{detail::empty_guid<CharT>};
@ -572,13 +588,13 @@ namespace uuids
} }
template <class Elem, class Traits> template <class Elem, class Traits>
std::basic_ostream<Elem, Traits>& operator<<(std::basic_ostream<Elem, Traits>& s, uuid const& id) std::basic_ostream<Elem, Traits> &operator<<(std::basic_ostream<Elem, Traits> &s, uuid const &id)
{ {
s << to_string(id); s << to_string(id);
return s; return s;
} }
inline void swap(uuids::uuid & lhs, uuids::uuid & rhs) noexcept inline void swap(uuids::uuid &lhs, uuids::uuid &rhs) noexcept
{ {
lhs.swap(rhs); lhs.swap(rhs);
} }
@ -588,16 +604,16 @@ namespace uuids
// -------------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------------
// Name string is a fully-qualified domain name // Name string is a fully-qualified domain name
static uuid uuid_namespace_dns{ {0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} }; static uuid uuid_namespace_dns{{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}};
// Name string is a URL // Name string is a URL
static uuid uuid_namespace_url{ {0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} }; static uuid uuid_namespace_url{{0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}};
// Name string is an ISO OID (See https://oidref.com/, https://en.wikipedia.org/wiki/Object_identifier) // Name string is an ISO OID (See https://oidref.com/, https://en.wikipedia.org/wiki/Object_identifier)
static uuid uuid_namespace_oid{ {0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} }; static uuid uuid_namespace_oid{{0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}};
// Name string is an X.500 DN, in DER or a text output format (See https://en.wikipedia.org/wiki/X.500, https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One) // Name string is an X.500 DN, in DER or a text output format (See https://en.wikipedia.org/wiki/X.500, https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One)
static uuid uuid_namespace_x500{ {0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} }; static uuid uuid_namespace_x500{{0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}};
// -------------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------------
// uuid generators // uuid generators
@ -622,8 +638,7 @@ namespace uuids
} }
std::array<uint8_t, 16> bytes = std::array<uint8_t, 16> bytes =
{ { {{static_cast<unsigned char>((newId.Data1 >> 24) & 0xFF),
static_cast<unsigned char>((newId.Data1 >> 24) & 0xFF),
static_cast<unsigned char>((newId.Data1 >> 16) & 0xFF), static_cast<unsigned char>((newId.Data1 >> 16) & 0xFF),
static_cast<unsigned char>((newId.Data1 >> 8) & 0xFF), static_cast<unsigned char>((newId.Data1 >> 8) & 0xFF),
static_cast<unsigned char>((newId.Data1) & 0xFF), static_cast<unsigned char>((newId.Data1) & 0xFF),
@ -641,10 +656,9 @@ namespace uuids
newId.Data4[4], newId.Data4[4],
newId.Data4[5], newId.Data4[5],
newId.Data4[6], newId.Data4[6],
newId.Data4[7] newId.Data4[7]}};
} };
return uuid{ std::begin(bytes), std::end(bytes) }; return uuid{std::begin(bytes), std::end(bytes)};
#elif defined(__linux__) || defined(__unix__) #elif defined(__linux__) || defined(__unix__)
@ -652,8 +666,7 @@ namespace uuids
uuid_generate(id); uuid_generate(id);
std::array<uint8_t, 16> bytes = std::array<uint8_t, 16> bytes =
{ { {{id[0],
id[0],
id[1], id[1],
id[2], id[2],
id[3], id[3],
@ -668,10 +681,9 @@ namespace uuids
id[12], id[12],
id[13], id[13],
id[14], id[14],
id[15] id[15]}};
} };
return uuid{ std::begin(bytes), std::end(bytes) }; return uuid{std::begin(bytes), std::end(bytes)};
#elif defined(__APPLE__) #elif defined(__APPLE__)
auto newId = CFUUIDCreate(NULL); auto newId = CFUUIDCreate(NULL);
@ -679,8 +691,7 @@ namespace uuids
CFRelease(newId); CFRelease(newId);
std::array<uint8_t, 16> arrbytes = std::array<uint8_t, 16> arrbytes =
{ { {{bytes.byte0,
bytes.byte0,
bytes.byte1, bytes.byte1,
bytes.byte2, bytes.byte2,
bytes.byte3, bytes.byte3,
@ -695,9 +706,8 @@ namespace uuids
bytes.byte12, bytes.byte12,
bytes.byte13, bytes.byte13,
bytes.byte14, bytes.byte14,
bytes.byte15 bytes.byte15}};
} }; return uuid{std::begin(arrbytes), std::end(arrbytes)};
return uuid{ std::begin(arrbytes), std::end(arrbytes) };
#else #else
return uuid{}; return uuid{};
#endif #endif
@ -711,16 +721,14 @@ namespace uuids
public: public:
using engine_type = UniformRandomNumberGenerator; using engine_type = UniformRandomNumberGenerator;
explicit basic_uuid_random_generator(engine_type& gen) : explicit basic_uuid_random_generator(engine_type &gen) : generator(&gen, [](auto) {}) {}
generator(&gen, [](auto) {}) {} explicit basic_uuid_random_generator(engine_type *gen) : generator(gen, [](auto) {}) {}
explicit basic_uuid_random_generator(engine_type* gen) :
generator(gen, [](auto) {}) {}
uuid operator()() uuid operator()()
{ {
uint8_t bytes[16]; uint8_t bytes[16];
for (int i = 0; i < 16; i += 4) for (int i = 0; i < 16; i += 4)
*reinterpret_cast<uint32_t*>(bytes + i) = distribution(*generator); *reinterpret_cast<uint32_t *>(bytes + i) = distribution(*generator);
// variant must be 10xxxxxx // variant must be 10xxxxxx
bytes[8] &= 0xBF; bytes[8] &= 0xBF;
@ -743,12 +751,13 @@ namespace uuids
class uuid_name_generator class uuid_name_generator
{ {
public: public:
explicit uuid_name_generator(uuid const& namespace_uuid) noexcept explicit uuid_name_generator(uuid const &namespace_uuid) noexcept
: nsuuid(namespace_uuid) : nsuuid(namespace_uuid)
{} {
}
template <typename StringType> template <typename StringType>
uuid operator()(StringType const & name) uuid operator()(StringType const &name)
{ {
reset(); reset();
process_characters(detail::to_string_view(name)); process_characters(detail::to_string_view(name));
@ -793,7 +802,7 @@ namespace uuids
digest[6] &= 0x5F; digest[6] &= 0x5F;
digest[6] |= 0x50; digest[6] |= 0x50;
return uuid{ digest, digest + 16 }; return uuid{digest, digest + 16};
} }
private: private:
@ -820,11 +829,13 @@ namespace uuids
#ifdef _WIN32 #ifdef _WIN32
DWORD len = 0; DWORD len = 0;
auto ret = GetAdaptersInfo(nullptr, &len); auto ret = GetAdaptersInfo(nullptr, &len);
if (ret != ERROR_BUFFER_OVERFLOW) return false; if (ret != ERROR_BUFFER_OVERFLOW)
return false;
std::vector<unsigned char> buf(len); std::vector<unsigned char> buf(len);
auto pips = reinterpret_cast<PIP_ADAPTER_INFO>(&buf.front()); auto pips = reinterpret_cast<PIP_ADAPTER_INFO>(&buf.front());
ret = GetAdaptersInfo(pips, &len); ret = GetAdaptersInfo(pips, &len);
if (ret != ERROR_SUCCESS) return false; if (ret != ERROR_SUCCESS)
return false;
mac_address addr; mac_address addr;
std::copy(pips->Address, pips->Address + 6, std::begin(addr)); std::copy(pips->Address, pips->Address + 6, std::begin(addr));
device_address = addr; device_address = addr;
@ -860,7 +871,7 @@ namespace uuids
auto clock_seq = get_clock_sequence(); auto clock_seq = get_clock_sequence();
auto ptm = reinterpret_cast<uuids::uuid::value_type*>(&tm); auto ptm = reinterpret_cast<uuids::uuid::value_type *>(&tm);
memcpy(&data[0], ptm + 4, 4); memcpy(&data[0], ptm + 4, 4);
memcpy(&data[4], ptm + 2, 2); memcpy(&data[4], ptm + 2, 2);