summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Smrž <roman.smrz@seznam.cz>2020-06-06 14:47:45 +0200
committerRoman Smrž <roman.smrz@seznam.cz>2020-06-06 15:01:19 +0200
commitc00945ec1e5804003fb47798e86cd0c737a14d46 (patch)
tree06fa802760dcfb041d0ff0eda22cd9a1e661dc49
parentfd04142b2accb08ab3c79bfd5c5bffd25b3f5784 (diff)
UUID: random generation and format checking functions
-rw-r--r--include/erebos/uuid.h9
-rw-r--r--src/uuid.cpp47
2 files changed, 47 insertions, 9 deletions
diff --git a/include/erebos/uuid.h b/include/erebos/uuid.h
index 9b615f8..e67677a 100644
--- a/include/erebos/uuid.h
+++ b/include/erebos/uuid.h
@@ -1,15 +1,22 @@
#pragma once
#include <array>
+#include <optional>
#include <string>
namespace erebos {
struct UUID
{
- explicit UUID(std::string);
+ UUID(): uuid({}) {}
+ explicit UUID(const std::string &);
explicit operator std::string() const;
+ static std::optional<UUID> fromString(const std::string &);
+ static bool fromString(const std::string &, UUID &);
+
+ static UUID generate();
+
bool operator==(const UUID &) const;
bool operator!=(const UUID &) const;
diff --git a/src/uuid.cpp b/src/uuid.cpp
index 9af32b7..a53bf27 100644
--- a/src/uuid.cpp
+++ b/src/uuid.cpp
@@ -2,8 +2,12 @@
#include <stdexcept>
+#include <openssl/rand.h>
+
using namespace erebos;
+using std::nullopt;
+using std::optional;
using std::runtime_error;
using std::string;
@@ -12,15 +16,9 @@ static const size_t UUID_STR_LEN = 36;
static const char * FORMAT_STRING = "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-"
"%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx";
-UUID::UUID(string str)
+UUID::UUID(const string & str)
{
- if (str.size() != UUID_STR_LEN)
- throw runtime_error("invalid UUID");
-
- if (sscanf(str.c_str(), FORMAT_STRING,
- &uuid[0], &uuid[1], &uuid[2], &uuid[3], &uuid[4], &uuid[5], &uuid[6], &uuid[7],
- &uuid[8], &uuid[9], &uuid[10], &uuid[11], &uuid[12], &uuid[13], &uuid[14], &uuid[15])
- != 16)
+ if (!fromString(str, *this))
throw runtime_error("invalid UUID");
}
@@ -33,6 +31,39 @@ UUID::operator string() const
return str;
}
+optional<UUID> UUID::fromString(const string & str)
+{
+ UUID u;
+ if (fromString(str, u))
+ return u;
+ return nullopt;
+}
+
+bool UUID::fromString(const string & str, UUID & u)
+{
+ if (str.size() != UUID_STR_LEN)
+ return false;
+
+ if (sscanf(str.c_str(), FORMAT_STRING,
+ &u.uuid[0], &u.uuid[1], &u.uuid[2], &u.uuid[3], &u.uuid[4], &u.uuid[5], &u.uuid[6], &u.uuid[7],
+ &u.uuid[8], &u.uuid[9], &u.uuid[10], &u.uuid[11], &u.uuid[12], &u.uuid[13], &u.uuid[14], &u.uuid[15])
+ != 16)
+ return false;
+
+ return true;
+}
+
+UUID UUID::generate()
+{
+ UUID u;
+ if (RAND_bytes(u.uuid.data(), u.uuid.size()) != 1)
+ throw runtime_error("failed to generate random UUID");
+
+ u.uuid[6] = (u.uuid[6] & 0x0f) | 0x40;
+ u.uuid[8] = (u.uuid[8] & 0x3f) | 0x80;
+ return u;
+}
+
bool UUID::operator==(const UUID & other) const
{
return std::equal(std::begin(uuid), std::end(uuid), std::begin(other.uuid));