constructors implementation

This commit is contained in:
Marius Bancila 2018-01-16 16:35:48 +02:00
parent f6e2b21fc7
commit 9b1ef4f116
2 changed files with 89 additions and 92 deletions

View File

@ -21,6 +21,36 @@
namespace uuids namespace uuids
{ {
namespace detail
{
template <typename TChar>
constexpr inline unsigned char hex2char(TChar const ch)
{
if (ch >= static_cast<TChar>('0') && ch <= static_cast<TChar>('9'))
return ch - static_cast<TChar>('0');
if (ch >= static_cast<TChar>('a') && ch <= static_cast<TChar>('f'))
return 10 + ch - static_cast<TChar>('a');
if (ch >= static_cast<TChar>('A') && ch <= static_cast<TChar>('F'))
return 10 + ch - static_cast<TChar>('A');
return 0;
}
template <typename TChar>
constexpr inline bool is_hex(TChar const ch)
{
return
(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'));
}
template <typename TChar>
constexpr inline unsigned char hexpair2char(TChar const a, TChar const b)
{
return (hex2char(a) << 4) | hex2char(b);
}
}
// UUID format https://tools.ietf.org/html/rfc4122 // UUID format https://tools.ietf.org/html/rfc4122
// Field NDR Data Type Octet # Note // Field NDR Data Type Octet # Note
// -------------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------------
@ -397,8 +427,15 @@ namespace uuids
std::copy(first, last, std::begin(data)); std::copy(first, last, std::begin(data));
} }
explicit uuid(std::string_view str); explicit uuid(std::string_view str)
explicit uuid(std::wstring_view str); {
create(str.data(), str.size());
}
explicit uuid(std::wstring_view str)
{
create(str.data(), str.size());
}
constexpr uuid_variant variant() const noexcept constexpr uuid_variant variant() const noexcept
{ {
@ -457,11 +494,43 @@ namespace uuids
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 <typename TChar>
void create(TChar const * const str, size_t const size);
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 <typename TChar>
void create(TChar const * const str, size_t const size)
{
TChar digit = 0;
bool firstdigit = true;
size_t index = 0;
for (size_t i = 0; i < size; ++i)
{
if (str[i] == static_cast<TChar>('-')) continue;
if (index >= 16 || !detail::is_hex(str[i]))
{
std::fill(std::begin(data), std::end(data), 0);
return;
}
if (firstdigit)
{
digit = str[i];
firstdigit = false;
}
else
{
data[index++] = detail::hexpair2char(digit, str[i]);
firstdigit = true;
}
}
if (index < 16)
{
std::fill(std::begin(data), std::end(data), 0);
}
}
}; };
inline bool operator== (uuid const& lhs, uuid const& rhs) noexcept inline bool operator== (uuid const& lhs, uuid const& rhs) noexcept
@ -655,81 +724,6 @@ namespace uuids
}; };
using uuid_random_generator = basic_uuid_random_generator<std::mt19937>; using uuid_random_generator = basic_uuid_random_generator<std::mt19937>;
namespace detail
{
template <typename TChar>
constexpr inline unsigned char hex2char(TChar const ch)
{
if (ch >= static_cast<TChar>('0') && ch <= static_cast<TChar>('9'))
return ch - static_cast<TChar>('0');
if (ch >= static_cast<TChar>('a') && ch <= static_cast<TChar>('f'))
return 10 + ch - static_cast<TChar>('a');
if (ch >= static_cast<TChar>('A') && ch <= static_cast<TChar>('F'))
return 10 + ch - static_cast<TChar>('A');
return 0;
}
template <typename TChar>
constexpr inline bool is_hex(TChar const ch)
{
return
(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'));
}
template <typename TChar>
constexpr inline unsigned char hexpair2char(TChar const a, TChar const b)
{
return (hex2char(a) << 4) | hex2char(b);
}
}
uuid::uuid(std::string_view str)
{
create(str.data(), str.size());
}
uuid::uuid(std::wstring_view str)
{
create(str.data(), str.size());
}
template <typename TChar>
void uuid::create(TChar const * const str, size_t const size)
{
TChar digit = 0;
bool firstdigit = true;
size_t index = 0;
for (size_t i = 0; i < size; ++i)
{
if (str[i] == static_cast<TChar>('-')) continue;
if (index >= 16 || !detail::is_hex(str[i]))
{
std::fill(std::begin(data), std::end(data), 0);
return;
}
if (firstdigit)
{
digit = str[i];
firstdigit = false;
}
else
{
data[index++] = detail::hexpair2char(digit, str[i]);
firstdigit = true;
}
}
if (index < 16)
{
std::fill(std::begin(data), std::end(data), 0);
}
}
} }
namespace std namespace std

View File

@ -52,7 +52,7 @@ int main()
using namespace std::string_literals; using namespace std::string_literals;
{ {
std::array<uint8_t, 16> arr{ { std::array<uuids::uuid::value_type, 16> arr{ {
0x47, 0x18, 0x38, 0x23, 0x47, 0x18, 0x38, 0x23,
0x25, 0x74, 0x25, 0x74,
0x4b, 0xfd, 0x4b, 0xfd,
@ -64,7 +64,7 @@ int main()
} }
{ {
uint8_t arr[16] = { uuids::uuid::value_type arr[16] = {
0x47, 0x18, 0x38, 0x23, 0x47, 0x18, 0x38, 0x23,
0x25, 0x74, 0x25, 0x74,
0x4b, 0xfd, 0x4b, 0xfd,
@ -91,16 +91,17 @@ int main()
std::cout << "Test comparison" << std::endl; std::cout << "Test comparison" << std::endl;
auto empty = uuid{}; auto empty = uuid{};
auto id = uuids::uuid_default_generator{}(); uuids::uuid_default_generator gen;
auto id = gen();
assert(empty < id); assert(empty < id);
std::set<uuids::uuid> ids{ std::set<uuids::uuid> ids{
uuid{}, uuid{},
uuids::uuid_default_generator{}(), gen(),
uuids::uuid_default_generator{}(), gen(),
uuids::uuid_default_generator{}(), gen(),
uuids::uuid_default_generator{}() gen()
}; };
assert(ids.size() == 5); assert(ids.size() == 5);
@ -118,12 +119,14 @@ int main()
auto h2 = std::hash<uuid>{}; auto h2 = std::hash<uuid>{};
assert(h1(str) == h2(guid)); assert(h1(str) == h2(guid));
uuids::uuid_default_generator gen;
std::unordered_set<uuids::uuid> ids{ std::unordered_set<uuids::uuid> ids{
uuid{}, uuid{},
uuids::uuid_default_generator{}(), gen(),
uuids::uuid_default_generator{}(), gen(),
uuids::uuid_default_generator{}(), gen(),
uuids::uuid_default_generator{}() gen()
}; };
assert(ids.size() == 5); assert(ids.size() == 5);
@ -161,7 +164,7 @@ int main()
{ {
std::cout << "Test iterators" << std::endl; std::cout << "Test iterators" << std::endl;
std::array<uint8_t, 16> arr{{ std::array<uuids::uuid::value_type, 16> arr{{
0x47, 0x18, 0x38, 0x23, 0x47, 0x18, 0x38, 0x23,
0x25, 0x74, 0x25, 0x74,
0x4b, 0xfd, 0x4b, 0xfd,