initial UUID library
This commit is contained in:
parent
d8ef8b3279
commit
0e85f41548
|
@ -29,10 +29,13 @@ namespace RLP {
|
|||
|
||||
rlp_header::rlp_header(PDU::Stream stream)
|
||||
: PDU::pdu_header()
|
||||
, cid()
|
||||
{
|
||||
stream->read(cid, 16);
|
||||
uint8_t buf[16];
|
||||
stream->read(buf, 16);
|
||||
if (stream->gcount() != 16)
|
||||
stream->setstate(stream->rdstate() | std::ios_base::failbit);
|
||||
cid = UUID::uuid(buf);
|
||||
}
|
||||
|
||||
Pdu::Pdu(PDU::Stream stream)
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include "pdu.h"
|
||||
#include "../uuid/uuid.h"
|
||||
|
||||
namespace ACN {
|
||||
namespace RLP {
|
||||
|
@ -34,7 +35,7 @@ namespace RLP {
|
|||
// The Header field in Root Layer PDUs shall contain the CID of the component
|
||||
// that generated the PDU (the Source CID).
|
||||
struct rlp_header : PDU::pdu_header {
|
||||
uint8_t cid[16];
|
||||
UUID::uuid cid;
|
||||
rlp_header(PDU::Stream);
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
uuid.h
|
||||
|
||||
Copyright (c) 2021 Kevin Matz (kevin.matz@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uuid.h"
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <ctime>
|
||||
|
||||
namespace UUID {
|
||||
|
||||
/**
|
||||
construct a NIL UUID
|
||||
*/
|
||||
uuid::uuid() {
|
||||
type_ = NIL;
|
||||
version_ = VOID;
|
||||
timestamp_ = 0;
|
||||
clock_seq_ = 0;
|
||||
node_ = 0;
|
||||
setBytes();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
create this UUID from a byte array
|
||||
*/
|
||||
void uuid::fromArray(const uint8_t * bytes) {
|
||||
std::memcpy(raw_, bytes, sizeof(raw_));
|
||||
setType();
|
||||
if (type_ != RFC4122) return;
|
||||
setVersion();
|
||||
setFields();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
create this UUID from a C style char array
|
||||
*/
|
||||
void uuid::fromCstring(const char * cstr) {
|
||||
fromString(std::string(cstr));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
create this UUID from a string representation
|
||||
*/
|
||||
void uuid::fromString(std::string str) {
|
||||
// remove dashes
|
||||
str.erase(std::remove(str.begin(), str.end(), '-'), str.end());
|
||||
if (str.length() != 32) return;
|
||||
// fill buffer
|
||||
uint8_t buf[16];
|
||||
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);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
output this UUID as a hex string
|
||||
*/
|
||||
std::string uuid::hex() const {
|
||||
std::ostringstream oss;
|
||||
oss << std::hex << std::setfill('0') << std::setw(2);
|
||||
for (uint8_t raw : raw_)
|
||||
oss << raw;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
output this UUID as formated hex string
|
||||
*/
|
||||
std::string uuid::string() const {
|
||||
std::string str = hex();
|
||||
str.reserve(str.length() + 4);
|
||||
for (int idx : {8, 13, 18, 23})
|
||||
str.insert(idx, "-");
|
||||
return str;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
output this UUID as a urn specified in RFC 4122
|
||||
*/
|
||||
std::string uuid::urn() const {
|
||||
return "urn:uuid:" + string();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
make the raw bytes match the field contents
|
||||
*/
|
||||
// TODO: Check endianness
|
||||
void uuid::setBytes() {
|
||||
if (type_ == NIL)
|
||||
std::memset(raw_, 0, sizeof(raw_));
|
||||
if (type_ != RFC4122) return;
|
||||
|
||||
Fields fields;
|
||||
fields.time_low = timestamp_;
|
||||
fields.time_mid = timestamp_ >> 32;
|
||||
fields.time_hi_version = timestamp_ >> 48;
|
||||
|
||||
fields.clock_seq_low = clock_seq_;
|
||||
fields.clock_seq_hi_variant = clock_seq_ >> 8;
|
||||
|
||||
fields.node_low = node_;
|
||||
fields.node_high = node_ >> 16;
|
||||
|
||||
std::memcpy(raw_, &fields, sizeof(raw_));
|
||||
|
||||
// version
|
||||
raw_[7] = (raw_[7] & 0x0f) | (version_ << 4);
|
||||
// type
|
||||
raw_[8] = (raw_[8] & 0b00111111) | (type_ << 6);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
populate data fields from byte array
|
||||
*/
|
||||
// TODO: Check endianness
|
||||
void uuid::setFields() {
|
||||
Fields fields;
|
||||
std::memcpy(&fields, raw_, sizeof(raw_));
|
||||
|
||||
timestamp_ = fields.time_low;
|
||||
timestamp_ |= (uint64_t)fields.time_mid << 32;
|
||||
timestamp_ |= (uint64_t)(fields.time_hi_version & 0x0fff) << 48;
|
||||
|
||||
clock_seq_ = fields.clock_seq_low;
|
||||
clock_seq_ |= (fields.clock_seq_hi_variant & 0b00111111) << 8;
|
||||
|
||||
node_ = fields.node_low;
|
||||
node_ |= (fields.node_high << 16);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
exctract the type from the raw bytes
|
||||
*/
|
||||
void uuid::setType() {
|
||||
if ((raw_[8] >> 7) == 0b0) {
|
||||
type_ = NCS;
|
||||
} else if ((raw_[8] >> 6) == 0b10) {
|
||||
type_ = RFC4122;
|
||||
} else if ((raw_[8] >> 5) == 0b110) {
|
||||
type_ = MS;
|
||||
} else {
|
||||
type_ = RESVERED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
exctract the version from the raw bytes
|
||||
*/
|
||||
void uuid::setVersion() {
|
||||
switch (raw_[7] >> 4) {
|
||||
case TIME:
|
||||
version_ = TIME;
|
||||
break;
|
||||
case DCE:
|
||||
version_ = DCE;
|
||||
break;
|
||||
case MD5:
|
||||
version_ = MD5;
|
||||
break;
|
||||
case RAND:
|
||||
version_ = RAND;
|
||||
break;
|
||||
case SHA1:
|
||||
version_ = SHA1;
|
||||
break;
|
||||
default:
|
||||
version_ = VOID;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
compare to another UUID
|
||||
*/
|
||||
bool uuid::operator== (const uuid & other) const {
|
||||
return std::memcmp(raw_, other.bytes(), sizeof(raw_));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
compare to another byte array
|
||||
*/
|
||||
bool uuid::operator== (const uint8_t * other) const {
|
||||
if (sizeof(raw_) != sizeof(other))
|
||||
return false;
|
||||
return std::memcmp(raw_, other, sizeof(raw_));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
compare to another formatted C string
|
||||
*/
|
||||
bool uuid::operator== (const char* other) const {
|
||||
return std::strcmp(string().c_str(), other);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
compare to another formatted std::string
|
||||
*/
|
||||
bool uuid::operator== (const std::string & other) const {
|
||||
return string().compare(other);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
create this UUID as a Version 4 (RANDOM) UUID
|
||||
*/
|
||||
void uuid::uuid4() {
|
||||
type_ = RFC4122;
|
||||
version_ = RAND;
|
||||
std::srand(std::time(nullptr));
|
||||
timestamp_ = std::rand();
|
||||
timestamp_ |= (uint64_t)std::rand() << 32;
|
||||
clock_seq_ = std::rand();
|
||||
node_ = std::rand();
|
||||
node_ |= (uint64_t)std::rand() << 32;
|
||||
setBytes();
|
||||
}
|
||||
|
||||
// const std::string NAMESPACE_DNS = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
|
||||
// const std::string NAMESPACE_URL = "6ba7b811-9dad-11d1-80b4-00c04fd430c8";
|
||||
// const std::string NAMESPACE_OID = "6ba7b812-9dad-11d1-80b4-00c04fd430c8";
|
||||
// const std::string NAMESPACE_X500 = "6ba7b814-9dad-11d1-80b4-00c04fd430c8";
|
||||
|
||||
}; // UUID
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
uuid.h
|
||||
|
||||
Copyright (c) 2021 Kevin Matz (kevin.matz@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
// RFC4122 A Universally Unique IDentifier (UUID) URN Namespace
|
||||
namespace UUID {
|
||||
|
||||
class uuid {
|
||||
public:
|
||||
enum Type {
|
||||
NCS, // Reserved, NCS backward compatibility.
|
||||
RFC4122, // The variant specified in this document.
|
||||
MS, // Reserved, Microsoft Corporation backward compatibility
|
||||
RESVERED, // Reserved for future definition.
|
||||
NIL
|
||||
};
|
||||
|
||||
enum Version {
|
||||
VOID = 0b0000,
|
||||
TIME = 0b0001, // The time-based version specified in this document.
|
||||
DCE = 0b0010, // DCE Security version, with embedded POSIX UIDs.
|
||||
MD5 = 0b0011, // The name-based version that uses MD5 hashing.
|
||||
RAND = 0b0100, // The randomly or pseudo-randomly generated version.
|
||||
SHA1 = 0b0101 // The name-based version that uses SHA-1 hashing.
|
||||
};
|
||||
|
||||
enum Namespace {
|
||||
DNS, // the name string is a fully-qualified domain name.
|
||||
URL, // the name string is a URL.
|
||||
OID, // the name string is an ISO OID.
|
||||
X500 // the name string is an X.500 DN in DER or a text output format.
|
||||
};
|
||||
|
||||
struct Fields {
|
||||
uint32_t time_low;
|
||||
uint16_t time_mid;
|
||||
uint16_t time_hi_version;
|
||||
uint8_t clock_seq_hi_variant;
|
||||
uint8_t clock_seq_low;
|
||||
uint16_t node_low;
|
||||
uint32_t node_high;
|
||||
}__attribute__((packed));
|
||||
|
||||
// constructor
|
||||
uuid();
|
||||
uuid(const uint8_t * raw) : uuid() { fromArray(raw); };
|
||||
uuid(const char * cstr) : uuid() { fromCstring(cstr); };
|
||||
uuid(std::string str) : uuid() { fromString(str); };
|
||||
|
||||
// accessors
|
||||
const Type type() const { return type_; };
|
||||
const Version version() const { return version_; };
|
||||
const uint64_t time() const { return timestamp_; };
|
||||
const uint16_t sequence() const { return clock_seq_; };
|
||||
const uint64_t node() const { return node_; };
|
||||
const uint8_t * bytes() const { return raw_; };
|
||||
|
||||
// comparitor overload
|
||||
bool operator== (const uuid &) const;
|
||||
bool operator== (const uint8_t *) const;
|
||||
bool operator== (const char *) const;
|
||||
bool operator== (const std::string &) const;
|
||||
|
||||
// typecast overload
|
||||
operator const uint8_t * () const { return raw_; };
|
||||
operator const std::string () const { return string(); };
|
||||
|
||||
// output
|
||||
std::string hex() const; // '12345678123456781234567812345678'
|
||||
std::string string() const;// '12345678-1234-5678-1234-567812345678'
|
||||
std::string urn() const; // 'urn:uuid:12345678-1234-5678-1234-567812345678'
|
||||
|
||||
// creators
|
||||
virtual void uuid1(uint64_t node, uint16_t clock_seq) {};
|
||||
virtual void uuid3(Namespace, std::string) {};
|
||||
virtual void uuid4(); // very low quality of random
|
||||
virtual void uuid5(Namespace, std::string) {};
|
||||
|
||||
private:
|
||||
uint8_t raw_[16];
|
||||
Type type_;
|
||||
Version version_;
|
||||
uint64_t timestamp_ : 60;
|
||||
uint16_t clock_seq_ : 14;
|
||||
uint64_t node_ : 48;
|
||||
|
||||
void fromArray(const uint8_t *);
|
||||
void fromCstring(const char *);
|
||||
void fromString(std::string);
|
||||
|
||||
void setBytes();
|
||||
void setType();
|
||||
void setVersion();
|
||||
void setFields();
|
||||
}; // uuid
|
||||
|
||||
|
||||
// extern const std::string NAMESPACE_DNS;
|
||||
// extern const std::string NAMESPACE_URL;
|
||||
// extern const std::string NAMESPACE_OID;
|
||||
// extern const std::string NAMESPACE_X500;
|
||||
|
||||
}; // UUID
|
Loading…
Reference in New Issue