can create Timestamp UUIDs
This commit is contained in:
parent
c01cd08b86
commit
af8dcc92aa
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "uuid.h"
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
@ -42,7 +43,7 @@ uuid::uuid()
|
|||
timestamp_ = 0;
|
||||
clock_seq_ = 0;
|
||||
node_ = 0;
|
||||
setBytes();
|
||||
setBytes_();
|
||||
}
|
||||
|
||||
|
||||
|
@ -58,7 +59,7 @@ uuid::uuid(const uuid& other)
|
|||
timestamp_ = other.timestamp_;
|
||||
clock_seq_ = other.clock_seq_;
|
||||
node_ = other.node_;
|
||||
setBytes();
|
||||
setBytes_();
|
||||
}
|
||||
|
||||
|
||||
|
@ -77,9 +78,9 @@ uuid::~uuid()
|
|||
*
|
||||
* create this UUID from a byte array
|
||||
*/
|
||||
void uuid::fromArray(const uint8_t * bytes) {
|
||||
void uuid::fromArray_(const uint8_t * bytes) {
|
||||
std::memcpy(raw_, bytes, 16);
|
||||
setFields();
|
||||
setFields_();
|
||||
}
|
||||
|
||||
|
||||
|
@ -89,8 +90,8 @@ void uuid::fromArray(const uint8_t * bytes) {
|
|||
*
|
||||
* create this UUID from a C style char array
|
||||
*/
|
||||
void uuid::fromCstring(const char * cstr) {
|
||||
fromString(std::string(cstr));
|
||||
void uuid::fromCstring_(const char * cstr) {
|
||||
fromString_(std::string(cstr));
|
||||
}
|
||||
|
||||
|
||||
|
@ -100,7 +101,7 @@ void uuid::fromCstring(const char * cstr) {
|
|||
*
|
||||
* create this UUID from a string representation
|
||||
*/
|
||||
void uuid::fromString(std::string str) {
|
||||
void uuid::fromString_(std::string str) {
|
||||
// remove formating
|
||||
if (str.front() == '{' && str.back() == '}')
|
||||
str = str.substr(1, str.size() - 2);
|
||||
|
@ -111,7 +112,7 @@ void uuid::fromString(std::string str) {
|
|||
for (unsigned int i = 0; i < sizeof(buf); i++)
|
||||
buf[i] = std::strtoul(str.substr((i*2), 2).c_str(), NULL, 16);
|
||||
// process buffer
|
||||
fromArray(buf);
|
||||
fromArray_(buf);
|
||||
};
|
||||
|
||||
|
||||
|
@ -162,17 +163,17 @@ std::string uuid::urn() const {
|
|||
* @brief uuid::setBytes
|
||||
* make the raw bytes match the field contents
|
||||
*/
|
||||
void uuid::setBytes()
|
||||
void uuid::setBytes_()
|
||||
{
|
||||
switch (type_) {
|
||||
case NIL:
|
||||
std::memset(raw_, 0, 16);
|
||||
break;
|
||||
case NCS:
|
||||
setNCSBytes();
|
||||
setNCSBytes_();
|
||||
break;
|
||||
case RFC4122:
|
||||
setRFC4122Bytes();
|
||||
setRFC4122Bytes_();
|
||||
break;
|
||||
case MS:
|
||||
break;
|
||||
|
@ -185,7 +186,7 @@ void uuid::setBytes()
|
|||
/**
|
||||
* @brief uuid::setNCSBytes
|
||||
*/
|
||||
void uuid::setNCSBytes()
|
||||
void uuid::setNCSBytes_()
|
||||
{
|
||||
NCSFields fields;
|
||||
fields.time = timestamp_;
|
||||
|
@ -201,7 +202,7 @@ void uuid::setNCSBytes()
|
|||
* @brief uuid::setRFC4122Bytes
|
||||
* TODO: Check endianness
|
||||
*/
|
||||
void uuid::setRFC4122Bytes()
|
||||
void uuid::setRFC4122Bytes_()
|
||||
{
|
||||
RFC4122Fields fields;
|
||||
fields.time_low = timestamp_;
|
||||
|
@ -226,15 +227,15 @@ void uuid::setRFC4122Bytes()
|
|||
/**
|
||||
* @brief uuid::setFields
|
||||
*/
|
||||
void uuid::setFields()
|
||||
void uuid::setFields_()
|
||||
{
|
||||
setType();
|
||||
setType_();
|
||||
switch (type_) {
|
||||
case NCS:
|
||||
setNCSFields();
|
||||
setNCSFields_();
|
||||
break;
|
||||
case RFC4122:
|
||||
setRFC4122Fields();
|
||||
setRFC4122Fields_();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -245,7 +246,7 @@ void uuid::setFields()
|
|||
/**
|
||||
* @brief uuid::setNCSFields
|
||||
*/
|
||||
void uuid::setNCSFields()
|
||||
void uuid::setNCSFields_()
|
||||
{
|
||||
NCSFields fields;
|
||||
std::memcpy(&fields, raw_, 16);
|
||||
|
@ -259,7 +260,7 @@ void uuid::setNCSFields()
|
|||
/**
|
||||
* @brief uuid::setRFC4122Fields
|
||||
*/
|
||||
void uuid::setRFC4122Fields()
|
||||
void uuid::setRFC4122Fields_()
|
||||
{
|
||||
RFC4122Fields fields;
|
||||
std::memcpy(&fields, raw_, 16);
|
||||
|
@ -301,7 +302,7 @@ void uuid::setRFC4122Fields()
|
|||
*
|
||||
* exctract the type from the raw bytes
|
||||
*/
|
||||
void uuid::setType() {
|
||||
void uuid::setType_() {
|
||||
if ((raw_[8] >> 7) == 0b0) {
|
||||
type_ = NCS;
|
||||
} else if ((raw_[8] >> 6) == 0b10) {
|
||||
|
@ -323,7 +324,7 @@ uuid& uuid::operator=(const uuid& other)
|
|||
{
|
||||
if (this != &other) { // protect against invalid self-assignment
|
||||
std::memcpy(raw_, other.raw_, 16);
|
||||
setFields();
|
||||
setFields_();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
@ -343,6 +344,27 @@ bool operator== (const uuid& a, const uuid& b)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief uuid::uuid1
|
||||
* @param node
|
||||
* @param clock_seq
|
||||
* @return incrimented clock_sequence
|
||||
*
|
||||
* node ID and clock sequence tracking are the responsibility of the caller
|
||||
*/
|
||||
uint16_t uuid::uuid1(uint64_t node, uint16_t clock_seq)
|
||||
{
|
||||
type_ = RFC4122;
|
||||
version_ = TIME;
|
||||
timestamp_ = now_();
|
||||
clock_seq_ = clock_seq + 1;
|
||||
node_ = node;
|
||||
setBytes_();
|
||||
|
||||
return clock_seq_;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief uuid::uuid4
|
||||
*
|
||||
|
@ -357,7 +379,26 @@ void uuid::uuid4() {
|
|||
clock_seq_ = std::rand();
|
||||
node_ = std::rand();
|
||||
node_ |= (uint64_t)std::rand() << 32;
|
||||
setBytes();
|
||||
setBytes_();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief uuid::time_ 4.1.4. Timestamp
|
||||
* @return
|
||||
*
|
||||
* The timestamp is a 60-bit value. For UUID version 1, this is represented
|
||||
* by Coordinated Universal Time (UTC) as a count of 100-nanosecond intervals
|
||||
* since 00:00:00.00, 15 October 1582 (the date of Gregorian reform to the
|
||||
* Christian calendar).
|
||||
*/
|
||||
uint64_t uuid::now_()
|
||||
{
|
||||
auto now = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<uint64_t, std::nano> since = now.time_since_epoch();
|
||||
uint64_t periods = since.count() / 100;
|
||||
periods += UUID_TICKS_BETWEEK_EPOCH;
|
||||
return periods;
|
||||
}
|
||||
|
||||
// const std::string NAMESPACE_DNS = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
|
||||
|
|
62
uuid/uuid.h
62
uuid/uuid.h
|
@ -91,6 +91,14 @@ struct RFC4122Fields {
|
|||
}__attribute__((packed));
|
||||
|
||||
|
||||
/**
|
||||
* @brief UUID_TICKS_BETWEEK_EPOCH
|
||||
* The number of 100 ns ticks between the Gregorian epoch `1582-10-15 00:00:00`
|
||||
* and the Unix epoch `1970-01-01 00:00:00`.
|
||||
*/
|
||||
static const uint64_t UUID_TICKS_BETWEEK_EPOCH = 122192928000000000;
|
||||
|
||||
|
||||
// extern const std::string NAMESPACE_DNS;
|
||||
// extern const std::string NAMESPACE_URL;
|
||||
// extern const std::string NAMESPACE_OID;
|
||||
|
@ -103,27 +111,19 @@ struct RFC4122Fields {
|
|||
class uuid {
|
||||
public:
|
||||
uuid();
|
||||
uuid(const uuid& other);
|
||||
uuid(const uint8_t * raw) : uuid() { fromArray(raw); };
|
||||
uuid(const char * cstr) : uuid() { fromCstring(cstr); };
|
||||
uuid(std::string str) : uuid() { fromString(str); };
|
||||
uuid(const uuid&);
|
||||
uuid(const uint8_t * raw) : uuid() { fromArray_(raw); };
|
||||
uuid(const char * c_str) : uuid() { fromCstring_(c_str); };
|
||||
uuid(std::string str) : uuid() { fromString_(str); };
|
||||
~uuid();
|
||||
|
||||
// accessors
|
||||
const uint8_t * bytes() const { return raw_; };
|
||||
Type type() const { return type_; };
|
||||
uint16_t version() const { return version_; };
|
||||
uint64_t time() const { return timestamp_; };
|
||||
uint16_t sequence() const { return clock_seq_; };
|
||||
uint64_t node() const { return node_; };
|
||||
const uint8_t* bytes() const { return raw_; };
|
||||
|
||||
// operator overloads
|
||||
uuid& operator= (const uuid& other);
|
||||
friend bool operator== (const uuid& a, const uuid& b);
|
||||
|
||||
// typecast overload
|
||||
operator const uint8_t* () const { return raw_; };
|
||||
operator const std::string () const { return string(); };
|
||||
|
||||
// output
|
||||
std::string hex() const; // '12345678123456781234567812345678'
|
||||
|
@ -131,11 +131,19 @@ public:
|
|||
std::string urn() const; // 'urn:uuid:12345678-1234-5678-1234-567812345678'
|
||||
|
||||
// creators
|
||||
// virtual void uuid1(uint64_t node, uint16_t clock_seq) {};
|
||||
virtual uint16_t uuid1(uint64_t node, uint16_t clock_seq);
|
||||
// virtual void uuid3(Namespace, std::string) {};
|
||||
virtual void uuid4(); // very low quality of random
|
||||
virtual void uuid4(); // very low quality of random
|
||||
// virtual void uuid5(Namespace, std::string) {};
|
||||
|
||||
// operator overloads
|
||||
uuid& operator= (const uuid& other);
|
||||
friend bool operator== (const uuid&, const uuid&);
|
||||
|
||||
// typecast overload
|
||||
operator const uint8_t * () const { return raw_; };
|
||||
operator const std::string () const { return string(); };
|
||||
|
||||
private:
|
||||
uint8_t* raw_;
|
||||
Type type_;
|
||||
|
@ -144,18 +152,20 @@ private:
|
|||
uint16_t clock_seq_;
|
||||
uint64_t node_;
|
||||
|
||||
void fromArray(const uint8_t *);
|
||||
void fromCstring(const char *);
|
||||
void fromString(std::string);
|
||||
void fromArray_(const uint8_t *);
|
||||
void fromCstring_(const char *);
|
||||
void fromString_(std::string);
|
||||
|
||||
void setType();
|
||||
void setBytes();
|
||||
void setNCSBytes();
|
||||
void setRFC4122Bytes();
|
||||
void setType_();
|
||||
void setBytes_();
|
||||
void setNCSBytes_();
|
||||
void setRFC4122Bytes_();
|
||||
|
||||
void setFields();
|
||||
void setNCSFields();
|
||||
void setRFC4122Fields();
|
||||
void setFields_();
|
||||
void setNCSFields_();
|
||||
void setRFC4122Fields_();
|
||||
|
||||
uint64_t now_();
|
||||
};
|
||||
|
||||
} // namespace UUID
|
||||
|
@ -176,7 +186,7 @@ namespace std
|
|||
*/
|
||||
size_t operator()(UUID::uuid const& id) const noexcept
|
||||
{
|
||||
return hash<string>{}(id.hex());
|
||||
return std::hash<std::string>{}(id.hex());
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
|
Loading…
Reference in New Issue