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