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_buffer.hpp"
13 #include "gu_exception.hpp"
14 
15 #include <istream>
16 #include <cstring>
17 
operator ==(const gu_uuid_t & a,const gu_uuid_t & b)18 inline bool operator==(const gu_uuid_t& a, const gu_uuid_t& b)
19 {
20     return gu_uuid_compare(&a, &b) == 0;
21 }
22 
operator !=(const gu_uuid_t & a,const gu_uuid_t & b)23 inline bool operator!=(const gu_uuid_t& a, const gu_uuid_t& b)
24 {
25     return !(a == b);
26 }
27 
operator <<(std::ostream & os,const gu_uuid_t & uuid)28 inline std::ostream& operator<<(std::ostream& os, const gu_uuid_t& uuid)
29 {
30     char uuid_buf[GU_UUID_STR_LEN + 1];
31     ssize_t ret(gu_uuid_print(&uuid, uuid_buf, sizeof(uuid_buf)));
32     (void)ret;
33     assert(ret == GU_UUID_STR_LEN);
34     uuid_buf[GU_UUID_STR_LEN] = '\0';
35     return (os << uuid_buf);
36 }
37 
38 namespace gu {
39     class UUIDScanException : public Exception
40     {
41     public:
42         UUIDScanException(const std::string& s);
43     };
44 }
45 
gu_uuid_from_string(const std::string & s,gu_uuid_t & uuid)46 inline ssize_t gu_uuid_from_string(const std::string& s, gu_uuid_t& uuid)
47 {
48     ssize_t ret(gu_uuid_scan(s.c_str(), s.size(), &uuid));
49     if (gu_unlikely(ret == -1)) throw gu::UUIDScanException(s);
50     return ret;
51 }
52 
operator >>(std::istream & is,gu_uuid_t & uuid)53 inline std::istream& operator>>(std::istream& is, gu_uuid_t& uuid)
54 {
55     char str[GU_UUID_STR_LEN + 1];
56     is.width(GU_UUID_STR_LEN + 1);
57     is >> str;
58     gu_uuid_from_string(str, uuid);
59     return is;
60 }
61 
gu_uuid_serial_size(const gu_uuid_t & uuid)62 GU_FORCE_INLINE size_t gu_uuid_serial_size(const gu_uuid_t& uuid)
63 {
64     return sizeof(uuid.data);
65 }
66 
67 namespace gu {
68     class UUIDSerializeException : public Exception
69     {
70     public:
71         UUIDSerializeException(size_t need, size_t have);
72     };
73 }
74 
gu_uuid_serialize(const gu_uuid_t & uuid,gu::byte_t * buf,size_t const buflen,size_t const offset)75 inline size_t gu_uuid_serialize(const gu_uuid_t& uuid, gu::byte_t* buf,
76                                 size_t const buflen, size_t const offset)
77 {
78     size_t const len(gu_uuid_serial_size(uuid));
79     size_t const end_offset(offset + len);
80 
81     if (gu_unlikely(end_offset > buflen))
82         throw gu::UUIDSerializeException(len, buflen - offset);
83 
84     ::memcpy(buf + offset, uuid.data, len);
85     return end_offset;
86 }
87 
gu_uuid_unserialize(const gu::byte_t * buf,size_t const buflen,size_t const offset,gu_uuid_t & uuid)88 inline size_t gu_uuid_unserialize(const gu::byte_t* buf, size_t const buflen,
89                                   size_t const offset, gu_uuid_t& uuid)
90 {
91     size_t const len(gu_uuid_serial_size(uuid));
92     size_t const end_offset(offset + len);
93 
94     if (gu_unlikely(end_offset > buflen))
95         throw gu::UUIDSerializeException(len, buflen - offset);
96 
97     ::memcpy(uuid.data, buf + offset, len);
98     return end_offset;
99 }
100 
101 namespace gu {
102     class UUID;
103 }
104 
105 class gu::UUID
106 {
107 public:
108 
UUID()109     UUID() : uuid_(GU_UUID_NIL) {}
110 
UUID(const void * node,const size_t node_len)111     UUID(const void* node, const size_t node_len) : uuid_()
112     {
113         gu_uuid_generate(&uuid_, node, node_len);
114     }
115 
UUID(gu_uuid_t uuid)116     UUID(gu_uuid_t uuid) : uuid_(uuid) {}
117 
unserialize(const gu::byte_t * buf,const size_t buflen,const size_t offset)118     size_t unserialize(const gu::byte_t* buf,
119                        const size_t buflen, const size_t offset)
120     {
121         return gu_uuid_unserialize(buf, buflen, offset, uuid_);
122     }
123 
serialize(gu::byte_t * buf,const size_t buflen,const size_t offset) const124     size_t serialize(gu::byte_t* buf,
125                      const size_t buflen, const size_t offset) const
126     {
127         return gu_uuid_serialize(uuid_, buf, buflen, offset);
128     }
129 
serial_size()130     static size_t serial_size()
131     {
132         return sizeof(gu_uuid_t);
133     }
134 
uuid_ptr() const135     const gu_uuid_t* uuid_ptr() const
136     {
137         return &uuid_;
138     }
139 
140     GU_FORCE_INLINE
operator =(const UUID & u)141     UUID& operator=(const UUID& u)
142     {
143         gu_uuid_copy(&uuid_, &u.uuid_);
144         return *this;
145     }
146 
operator <(const UUID & cmp) const147     bool operator<(const UUID& cmp) const
148     {
149         return (gu_uuid_compare(&uuid_, &cmp.uuid_) < 0);
150     }
151 
operator ==(const UUID & cmp) const152     bool operator==(const UUID& cmp) const
153     {
154         return (gu_uuid_compare(&uuid_, &cmp.uuid_) == 0);
155     }
156 
operator !=(const UUID & cmp) const157     bool operator!=(const UUID& cmp) const
158     {
159         return !(*this == cmp);
160     }
161 
older(const UUID & cmp) const162     bool older(const UUID& cmp) const
163     {
164         return (gu_uuid_older(&uuid_, &cmp.uuid_) > 0);
165     }
166 
write_stream(std::ostream & os) const167     void write_stream(std::ostream& os) const
168     {
169         os << uuid_;
170     }
171 
read_stream(std::istream & is)172     void read_stream(std::istream& is)
173     {
174         is >> uuid_;
175     }
176 
177 protected:
178     gu_uuid_t         uuid_;
179 }; // class UUID
180 
181 namespace gu
182 {
operator <<(std::ostream & os,const gu::UUID & uuid)183 inline std::ostream& operator<<(std::ostream& os, const gu::UUID& uuid)
184 {
185     uuid.write_stream(os);
186     return os;
187 }
188 
operator >>(std::istream & is,gu::UUID & uuid)189 inline std::istream& operator>>(std::istream& is, gu::UUID& uuid)
190 {
191     uuid.read_stream(is);
192     return is;
193 }
194 } // namespace gu
195 
196 #endif // _gu_uuid_hpp_
197