1 /*
2 * Copyright (C) 2014-2017 Codership Oy <info@codership.com>
3 *
4 */
5
6 #ifndef _gu_uuid_hpp_
7 #define _gu_uuid_hpp_
8
9 #include "gu_uuid.h"
10 #include "gu_arch.h" // GU_ASSERT_ALIGNMENT
11 #include "gu_assert.hpp"
12 #include "gu_macros.hpp"
13 #include "gu_buffer.hpp"
14 #include "gu_exception.hpp"
15 #include "gu_serialize.hpp" // check_range()
16 #include "gu_utils.hpp" // ptr_offset()
17
18 #include <istream>
19 #include <cstring>
20
operator ==(const gu_uuid_t & a,const gu_uuid_t & b)21 inline bool operator==(const gu_uuid_t& a, const gu_uuid_t& b)
22 {
23 return gu_uuid_compare(&a, &b) == 0;
24 }
25
operator !=(const gu_uuid_t & a,const gu_uuid_t & b)26 inline bool operator!=(const gu_uuid_t& a, const gu_uuid_t& b)
27 {
28 return !(a == b);
29 }
30
operator <<(std::ostream & os,const gu_uuid_t & uuid)31 inline std::ostream& operator<<(std::ostream& os, const gu_uuid_t& uuid)
32 {
33 char uuid_buf[GU_UUID_STR_LEN + 1];
34 ssize_t ret(gu_uuid_print(&uuid, uuid_buf, sizeof(uuid_buf)));
35 (void)ret;
36 assert(ret == GU_UUID_STR_LEN);
37 uuid_buf[GU_UUID_STR_LEN] = '\0';
38 return (os << uuid_buf);
39 }
40
41 namespace gu {
42 class UUIDScanException : public Exception
43 {
44 public:
45 UUIDScanException(const std::string& s);
46 };
47 }
48
gu_uuid_from_string(const std::string & s,gu_uuid_t & uuid)49 inline ssize_t gu_uuid_from_string(const std::string& s, gu_uuid_t& uuid)
50 {
51 ssize_t ret(gu_uuid_scan(s.c_str(), s.size(), &uuid));
52 if (gu_unlikely(ret == -1)) throw gu::UUIDScanException(s);
53 return ret;
54 }
55
operator >>(std::istream & is,gu_uuid_t & uuid)56 inline std::istream& operator>>(std::istream& is, gu_uuid_t& uuid)
57 {
58 char str[GU_UUID_STR_LEN + 1];
59 is.width(GU_UUID_STR_LEN + 1);
60 is >> str;
61 gu_uuid_from_string(str, uuid);
62 return is;
63 }
64
65 namespace gu {
66 class UUID_base;
67 class UUID;
68 }
69
70 /* This class should not be used directly. It is here to allow
71 * gu::UUID and gcomm::UUID to inherit from it without the virtual table
72 (* overhead. */
73 class gu::UUID_base
74 {
75 public:
76
UUID_base()77 UUID_base() : uuid_(GU_UUID_NIL) {}
78
UUID_base(const void * const node,const size_t node_len)79 UUID_base(const void* const node, const size_t node_len) : uuid_()
80 {
81 gu_uuid_generate(&uuid_, node, node_len);
82 }
83
UUID_base(gu_uuid_t uuid)84 UUID_base(gu_uuid_t uuid) : uuid_(uuid) {}
85
86 class SerializeException : public Exception
87 {
88 public:
89 SerializeException(size_t need, size_t have);
90 };
91
serial_size()92 static size_t serial_size()
93 {
94 return sizeof(UUID_base().uuid_);
95 }
96
unserialize(const void * const buf,const size_t offset)97 size_t unserialize(const void* const buf, const size_t offset)
98 {
99 size_t const len(serial_size());
100 ::memcpy(&uuid_, ptr_offset(buf, offset), len);
101 return offset + len;
102 }
103
serialize(void * const buf,const size_t offset) const104 size_t serialize (void* const buf, const size_t offset) const
105 {
106 size_t const len(serial_size());
107 ::memcpy(ptr_offset(buf, offset), &uuid_, len);
108 return offset + len;
109 }
110
unserialize(const void * const buf,const size_t buflen,const size_t offset)111 size_t unserialize(const void* const buf, const size_t buflen,
112 const size_t offset)
113 {
114 gu_trace(gu::check_bounds(offset + serial_size(), buflen));
115 return unserialize(buf, offset);
116 }
117
serialize(void * const buf,const size_t buflen,const size_t offset) const118 size_t serialize (void* const buf, const size_t buflen,
119 const size_t offset) const
120 {
121 gu_trace(gu::check_bounds(offset + serial_size(), buflen));
122 return serialize(buf, offset);
123 }
124
ptr() const125 const gu_uuid_t* ptr() const
126 {
127 return &uuid_;
128 }
129
130 GU_FORCE_INLINE
operator =(const UUID_base & u)131 UUID_base& operator=(const UUID_base& u)
132 {
133 gu_uuid_copy(&uuid_, &u.uuid_);
134 return *this;
135 }
136
operator <(const UUID_base & cmp) const137 bool operator<(const UUID_base& cmp) const
138 {
139 return (gu_uuid_compare(&uuid_, &cmp.uuid_) < 0);
140 }
141
operator ==(const gu_uuid_t & cmp) const142 bool operator==(const gu_uuid_t& cmp) const
143 {
144 return (gu_uuid_compare(&uuid_, &cmp) == 0);
145 }
146
operator !=(const gu_uuid_t & cmp) const147 bool operator!=(const gu_uuid_t& cmp) const
148 {
149 return !(*this == cmp);
150 }
151
operator ==(const UUID_base & cmp) const152 bool operator==(const UUID_base& cmp) const
153 {
154 return (gu_uuid_compare(&uuid_, &cmp.uuid_) == 0);
155 }
156
operator !=(const UUID_base & cmp) const157 bool operator!=(const UUID_base& cmp) const
158 {
159 return !(*this == cmp);
160 }
161
older(const UUID_base & cmp) const162 bool older(const UUID_base& cmp) const
163 {
164 return (gu_uuid_older(&uuid_, &cmp.uuid_) > 0);
165 }
166
print(std::ostream & os) const167 std::ostream& print(std::ostream& os) const
168 {
169 return (os << uuid_);
170 }
171
scan(std::istream & is)172 std::istream& scan(std::istream& is)
173 {
174 return (is >> uuid_);
175 }
176
operator ()() const177 const gu_uuid_t& operator()() const
178 {
179 return uuid_;
180 }
181
182 protected:
183
~UUID_base()184 ~UUID_base() {}
185
186 gu_uuid_t uuid_;
187
188 private:
189
190 GU_COMPILE_ASSERT(sizeof(gu_uuid_t) == GU_UUID_LEN, UUID_size);
191
192 }; /* class UUID_base */
193
194 class gu::UUID : public UUID_base
195 {
196 public:
197
UUID()198 UUID() : UUID_base() {}
199
UUID(const void * node,const size_t node_len)200 UUID(const void* node, const size_t node_len) : UUID_base(node, node_len)
201 {}
202
UUID(gu_uuid_t uuid)203 UUID(gu_uuid_t uuid) : UUID_base(uuid) {}
204 }; /* class UUID */
205
206 namespace gu
207 {
operator <<(std::ostream & os,const gu::UUID_base & uuid)208 inline std::ostream& operator<< (std::ostream& os, const gu::UUID_base& uuid)
209 {
210 uuid.print(os); return os;
211 }
212
operator >>(std::istream & is,gu::UUID_base & uuid)213 inline std::istream& operator>> (std::istream& is, gu::UUID_base& uuid)
214 {
215 uuid.scan(is); return is;
216 }
217 } /* namespace gu */
218
219 #endif // _gu_uuid_hpp_
220