[ox/std] Add UUID fromString

This commit is contained in:
Gary Talent 2023-02-12 00:02:07 -06:00
parent e19559d7a7
commit 2b821b73ff
5 changed files with 100 additions and 7 deletions

View File

@ -28,7 +28,7 @@ class Optional {
constexpr Optional() noexcept = default;
template<typename ...Args>
constexpr Optional(Args &&... args);
explicit constexpr Optional(Args &&... args);
constexpr Optional(const Optional &other) {
if (other.m_ptr) {
@ -131,7 +131,7 @@ class Optional {
if (std::is_constant_evaluated()) {
m_ptr = new U(ox::forward<Args>(args)...);
} else {
m_ptr = std::construct_at<U>(reinterpret_cast<T*>(m_data.data()), ox::forward<Args>(args)...);
m_ptr = std::construct_at<U>(reinterpret_cast<U*>(m_data.data()), ox::forward<Args>(args)...);
}
return *m_ptr;
}

View File

@ -19,4 +19,5 @@ add_test("[ox/std] HeapMgr" StdTest malloc)
add_test("[ox/std] Serialize-Int" StdTest "Serialize-Int")
add_test("[ox/std] BufferWriter" StdTest "BufferWriter")
add_test("[ox/std] StringSplit" StdTest "StringSplit")
add_test("[ox/std] FromHex" StdTest "FromHex")
add_test("[ox/std] ToHex" StdTest "ToHex")

View File

@ -60,6 +60,8 @@ static std::map<ox::String, ox::Error(*)()> tests = {
oxAssert(s == "AB9C", "BString append broken");
s = "asdf";
oxAssert(s == "asdf", "String assign broken");
oxAssert(s != "aoeu", "String assign broken");
oxAssert(s.len() == 4, "String assign broken");
return OxError(0);
}
},
@ -156,6 +158,29 @@ static std::map<ox::String, ox::Error(*)()> tests = {
return OxError(0);
}
},
{
"FromHex",
[] {
oxExpect(ox::detail::fromHex("01").unwrap(), 0x01);
oxExpect(ox::detail::fromHex("02").unwrap(), 0x02);
oxExpect(ox::detail::fromHex("03").unwrap(), 0x03);
oxExpect(ox::detail::fromHex("04").unwrap(), 0x04);
oxExpect(ox::detail::fromHex("05").unwrap(), 0x05);
oxExpect(ox::detail::fromHex("06").unwrap(), 0x06);
oxExpect(ox::detail::fromHex("07").unwrap(), 0x07);
oxExpect(ox::detail::fromHex("08").unwrap(), 0x08);
oxExpect(ox::detail::fromHex("0d").unwrap(), 0x0d);
oxExpect(ox::detail::fromHex("0e").unwrap(), 0x0e);
oxExpect(ox::detail::fromHex("0f").unwrap(), 0x0f);
oxExpect(ox::detail::fromHex("0F").unwrap(), 0x0f);
oxExpect(ox::detail::fromHex("fF").unwrap(), 0xff);
oxExpect(ox::detail::fromHex("ff").unwrap(), 0xff);
oxExpect(ox::detail::fromHex("a0").unwrap(), 0xa0);
oxExpect(ox::detail::fromHex("93").unwrap(), 0x93);
oxExpect(ox::detail::fromHex("40").unwrap(), 0x40);
return OxError(0);
}
},
{
"ToHex",
[] {
@ -168,7 +193,7 @@ static std::map<ox::String, ox::Error(*)()> tests = {
oxExpect(ox::detail::toHex(0x07), "07");
oxExpect(ox::detail::toHex(0x08), "08");
oxExpect(ox::detail::toHex(0x0d), "0d");
oxExpect(ox::detail::toHex(0x0e), "03");
oxExpect(ox::detail::toHex(0x0e), "0e");
oxExpect(ox::detail::toHex(0x0f), "0f");
oxExpect(ox::detail::toHex(0x93), "93");
oxExpect(ox::detail::toHex(0x40), "40");

View File

@ -13,7 +13,7 @@ namespace ox {
bool UUID::s_seeded = false;
Random UUID::s_rand;
void UUID::seed(const RandomSeed &seed) noexcept {
void UUID::seedGenerator(const RandomSeed &seed) noexcept {
s_seeded = true;
s_rand.seed(seed);
}

View File

@ -11,12 +11,56 @@
#include "array.hpp"
#include "bstring.hpp"
#include "random.hpp"
#include "stringview.hpp"
#include "strops.hpp"
#include "trace.hpp"
namespace ox {
using UUIDStr = ox::BString<36>;
namespace detail {
[[nodiscard]]
constexpr auto isHexChar(char c) noexcept {
return (c >= '0' && c <= '9')
|| (c >= 'a' && c <= 'f')
|| (c >= 'A' && c <= 'F');
}
constexpr ox::Result<uint8_t> fromHex(ox::CRStringView v) noexcept {
constexpr auto valMap = [] {
ox::Array<uint8_t, 128> out;
out['A'] = out['a'] = 10;
out['B'] = out['b'] = 11;
out['C'] = out['c'] = 12;
out['D'] = out['d'] = 13;
out['E'] = out['e'] = 14;
out['F'] = out['f'] = 15;
out['0'] = 0;
out['1'] = 1;
out['2'] = 2;
out['3'] = 3;
out['4'] = 4;
out['5'] = 5;
out['6'] = 6;
out['7'] = 7;
out['8'] = 8;
out['9'] = 9;
return out;
}();
if (!detail::isHexChar(v[0]) || !detail::isHexChar(v[1])) {
return OxError(1, "Invalid UUID");
}
if (v.len() != 2) {
return OxError(2);
}
uint8_t out = 0;
out += valMap[static_cast<unsigned>(v[0])] * 16u;
out += valMap[static_cast<unsigned>(v[1])];
return out;
}
constexpr ox::BString<2> toHex(uint8_t v) noexcept {
constexpr ox::Array<char, 16> valMap {
'0',
@ -42,6 +86,7 @@ constexpr ox::BString<2> toHex(uint8_t v) noexcept {
out[2] = 0;
return out.data();
}
}
class UUID {
@ -51,13 +96,35 @@ class UUID {
ox::Array<uint8_t, 16> m_value;
public:
static void seed(const RandomSeed &seed) noexcept;
static void seedGenerator(const RandomSeed &seed) noexcept;
static ox::Result<UUID> generate() noexcept;
constexpr ox::Error fromString(ox::CRStringView s) noexcept {
if (s.len() < 36) {
return OxError(1, "Insufficient data contain complete UUID");
}
auto valueI = 0u;
for (auto i = 0u; i < s.len();) {
if (s[i] == '-') {
++i;
continue;
}
const auto seg = s.substr(i, i + 2);
if (seg.len() != 2) {
return OxError(1, "Invalid UUID");
}
oxRequire(val, detail::fromHex(seg));
m_value[valueI] = val;
i += 2;
++valueI;
}
return {};
}
[[nodiscard]]
constexpr ox::BString<36> toString() const noexcept {
ox::BString<36> out;
constexpr UUIDStr toString() const noexcept {
UUIDStr out;
auto i = 0u;
constexpr auto printChars = [](
ox::BString<36> *out, const Array<uint8_t, 16> &value, std::size_t cnt, unsigned i) {