From 29a8aa7ee87bc01245b082986c2859891fb5e648 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Mon, 29 Aug 2011 14:37:20 +1000 Subject: [PATCH] Add GUID type --- Makefile.am | 2 + guid.cpp | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++++ guid.hpp | 62 ++++++++++++++++ 3 files changed, 274 insertions(+) create mode 100644 guid.cpp create mode 100644 guid.hpp diff --git a/Makefile.am b/Makefile.am index ee3c1975..f30140eb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -15,6 +15,7 @@ UTIL_INCLUDE = \ except.hpp \ fixed.hpp \ float.hpp \ + guid.hpp \ io.hpp \ ip.hpp \ json.hpp \ @@ -38,6 +39,7 @@ UTIL_FILES = \ except.cpp \ fixed.cpp \ float.cpp \ + guid.cpp \ io.cpp \ ip.cpp \ json.cpp \ diff --git a/guid.cpp b/guid.cpp new file mode 100644 index 00000000..ca665dd5 --- /dev/null +++ b/guid.cpp @@ -0,0 +1,210 @@ +/* + * This file is part of libgim. + * + * libgim is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * libgim is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with libgim. If not, see . + * + * Copyright 2011 Danny Robson + */ + +#include "guid.hpp" + +#include "debug.hpp" +#include "endian.hpp" +#include "types.hpp" + +#include +#include +#include + +using namespace std; + + +guid::guid (uint32_t _data1, + uint16_t _data2, + uint16_t _data3, + uint8_t _data4[8]): + data1 (_data1), + data2 (_data2), + data3 (_data3) +{ + copy (_data4, _data4 + elems (data4), data4); +} + + +guid::guid (void) +{ + ; +} + + +guid::guid (const char *str) { + istringstream is (str); + is >> *this; +} + + +guid::guid (const guid &rhs) { + *this = rhs; +} + + +guid& +guid::operator= (const guid &rhs) { + data1 = rhs.data1; + data2 = rhs.data2; + data3 = rhs.data3; + copy (rhs.data4 + 0, rhs.data4 + elems (rhs.data4), data4 + 0); + + return *this; +} + + +guid +guid::from_bytes (const uint8_t *bytes) { + guid g; + + g.data1 = *reinterpret_cast (bytes); + bytes += sizeof (g.data1); + + g.data2 = *reinterpret_cast (bytes); + bytes += sizeof (g.data2); + + g.data3 = *reinterpret_cast (bytes); + bytes += sizeof (g.data3); + + for (signed i = 7; i >= 0; --i) { + g.data4[i] = *reinterpret_cast (bytes); + ++bytes; + } + + return g; +} + + +guid +guid::from_string (const char *bytes) + { return guid (bytes); } + + +guid::type +guid::get_type (void) const { + // Top three bits signal the type + unsigned bits = (unsigned)data4[2] >> 5U; + + switch (bits) { + case 0x0: + case 0x1: + case 0x2: + case 0x3: return NCS_BACKWARD; + + case 0x4: + case 0x5: return STANDARD; + + case 0x6: return COM_BACKWARD; + + case 0x7: return RESERVED; + } + + unreachable (); +} + + +bool +guid::operator< (const guid &rhs) const { + if (data1 != rhs.data1) + return data1 < rhs.data1; + if (data2 != rhs.data2) + return data2 < rhs.data2; + if (data3 != rhs.data3) + return data3 < rhs.data3; + + for (unsigned i = 0; i < elems (data4); ++i) { + if (data4[i] == rhs.data4[i]) + return data4[i] < rhs.data4[i]; + } + + // All equal, so not less than + return false; +} + + +bool +guid::operator== (const guid &rhs) const { + return data1 == rhs.data1 && + data2 == rhs.data2 && + data3 == rhs.data3 && + data4[0] == rhs.data4[0] && + data4[1] == rhs.data4[1] && + data4[2] == rhs.data4[2] && + data4[3] == rhs.data4[3] && + data4[4] == rhs.data4[4] && + data4[5] == rhs.data4[5] && + data4[6] == rhs.data4[6] && + data4[7] == rhs.data4[7]; +} + +std::ostream& +operator<< (std::ostream &os, const guid &g) { + uint64_t data4_b = (uint64_t)g.data4[0] << 0 | + (uint64_t)g.data4[1] << 8 | + (uint64_t)g.data4[2] << 16 | + (uint64_t)g.data4[3] << 24 | + (uint64_t)g.data4[4] << 32 | + (uint64_t)g.data4[5] << 40; + uint16_t data4_a = (uint16_t)g.data4[6] << 0 | + (uint16_t)g.data4[7] << 8; + + os << hex << setfill ('0') << setw (2 * sizeof (g.data1)) << g.data1 << "-" + << setw (2 * sizeof (g.data2)) << g.data2 << "-" + << setw (2 * sizeof (g.data3)) << g.data3 << "-" + << setw (2 * 2) << data4_a << "-" + << setw (2 * 6) << data4_b; + + os << dec; + return os; +} + + +std::istream& +operator>> (std::istream &is, guid &g) { + bool braces = '{' == is.peek (); + if (braces) + is.get (); + + uint8_t dash1, dash2, dash3, dash4a; + uint16_t data4_a; + uint64_t data4_b; + + is >> hex >> g.data1 >> dash1 + >> g.data2 >> dash2 + >> g.data3 >> dash3 + >> data4_a >> dash4a + >> data4_b; + + uint64_t data4 = data4_b | (uint64_t)data4_a << 48; + g.data4[0] = data4 & 0xFF; data4 >>= 8; + g.data4[1] = data4 & 0xFF; data4 >>= 8; + g.data4[2] = data4 & 0xFF; data4 >>= 8; + g.data4[3] = data4 & 0xFF; data4 >>= 8; + g.data4[4] = data4 & 0xFF; data4 >>= 8; + g.data4[5] = data4 & 0xFF; data4 >>= 8; + g.data4[6] = data4 & 0xFF; data4 >>= 8; + g.data4[7] = data4 & 0xFF; data4 >>= 8; + + if (braces) + is.get (); + + return is; +} + diff --git a/guid.hpp b/guid.hpp new file mode 100644 index 00000000..e9da8571 --- /dev/null +++ b/guid.hpp @@ -0,0 +1,62 @@ +/* + * This file is part of libgim. + * + * libgim is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * libgim is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with libgim. If not, see . + * + * Copyright 2011 Danny Robson + */ + +#ifndef __UTIL_GUID_HPP +#define __UTIL_GUID_HPP + +#include +#include + +class guid { + public: + enum type { + NCS_BACKWARD, // 0xx: Network Computing System backward compatibility + STANDARD, // 10x: Standard + COM_BACKWARD, // 110: Microsoft Component Object Model backward compatibility + RESERVED // 111: Reserved for future use + }; + + private: + guid (void); + + public: + guid (uint32_t, uint16_t, uint16_t, uint8_t[8]); + guid (const char *); + guid (const guid&); + + guid& operator= (const guid&); + + static guid from_bytes (const uint8_t *bytes); + static guid from_string (const char *bytes); + + uint32_t data1; + uint16_t data2; + uint16_t data3; + uint8_t data4[8]; + + type get_type (void) const; + + bool operator< (const guid&) const; + bool operator== (const guid&) const; +}; + +std::istream& operator>> (std::istream&, guid&); +std::ostream& operator<< (std::ostream&, const guid&); + +#endif