Servus  1.5.1
C++ network oriented utilities including a zeroconf implementation
uint128_t.h
1 /* Copyright (c) 2010-2017, Cedric Stalder <cedric.stalder@gmail.com>
2  * Stefan Eilemann <eile@eyescale.ch>
3  * Daniel Nachbaur <danielnachbaur@gmail.com>
4  *
5  * This file is part of Servus <https://github.com/HBPVIS/Servus>
6  *
7  * This library is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU Lesser General Public License version 3.0 as published
9  * by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14  * details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
21 #ifndef SERVUS_UINT128_H
22 #define SERVUS_UINT128_H
23 
24 #include <servus/api.h>
25 #include <servus/types.h>
26 
27 #include <sstream>
28 #ifdef _MSC_VER
29 // Don't include <servus/types.h> to be minimally intrusive for apps
30 // using uint128_t
31 #include <basetsd.h>
32 typedef UINT64 uint64_t;
33 #define snprintf _snprintf
34 #else
35 #include <stdint.h>
36 #endif
37 
38 namespace servus
39 {
40 class uint128_t;
41 std::ostream& operator<<(std::ostream& os, const uint128_t& id);
42 
48 class uint128_t
49 {
50 public:
54  explicit uint128_t(const unsigned long long low_ = 0)
55  : _high(0)
56  , _low(low_)
57  {
58  }
59 
63  explicit uint128_t(const unsigned long low_)
64  : _high(0)
65  , _low(low_)
66  {
67  }
68 
72  explicit uint128_t(const int low_)
73  : _high(0)
74  , _low(low_)
75  {
76  }
77 
81  uint128_t(const uint64_t high_, const uint64_t low_)
82  : _high(high_)
83  , _low(low_)
84  {
85  }
86 
90  explicit uint128_t(const std::string& string)
91  : _high(0)
92  , _low(0)
93  {
94  *this = string;
95  }
96 
101  bool isUUID() const { return high() != 0; }
104  {
105  _high = rhs._high;
106  _low = rhs._low;
107  return *this;
108  }
109 
111  uint128_t& operator=(const uint64_t rhs)
112  {
113  _high = 0;
114  _low = rhs;
115  return *this;
116  }
117 
119  uint128_t& operator=(const int rhs)
120  {
121  _high = 0;
122  _low = rhs;
123  return *this;
124  }
125 
127  SERVUS_API uint128_t& operator=(const std::string& from);
128 
132  bool operator==(const servus::uint128_t& rhs) const
133  {
134  return _high == rhs._high && _low == rhs._low;
135  }
136 
140  bool operator!=(const servus::uint128_t& rhs) const
141  {
142  return _high != rhs._high || _low != rhs._low;
143  }
144 
148  bool operator==(const unsigned long long& low_) const
149  {
150  return *this == uint128_t(low_);
151  }
152 
156  bool operator!=(const unsigned long long& low_) const
157  {
158  return *this != uint128_t(low_);
159  }
160 
164  bool operator<(const servus::uint128_t& rhs) const
165  {
166  if (_high < rhs._high)
167  return true;
168  if (_high > rhs._high)
169  return false;
170  return _low < rhs._low;
171  }
172 
176  bool operator>(const servus::uint128_t& rhs) const
177  {
178  if (_high > rhs._high)
179  return true;
180  if (_high < rhs._high)
181  return false;
182  return _low > rhs._low;
183  }
184 
189  bool operator<=(const servus::uint128_t& rhs) const
190  {
191  if (_high < rhs._high)
192  return true;
193  if (_high > rhs._high)
194  return false;
195  return _low <= rhs._low;
196  }
197 
202  bool operator>=(const servus::uint128_t& rhs) const
203  {
204  if (_high > rhs._high)
205  return true;
206  if (_high < rhs._high)
207  return false;
208  return _low >= rhs._low;
209  }
210 
213  {
214  ++_low;
215  if (!_low)
216  ++_high;
217 
218  return *this;
219  }
220 
223  {
224  if (!_low)
225  --_high;
226  --_low;
227  return *this;
228  }
229 
232  {
233  const uint64_t oldLow = _low;
234  _low += rhs._low;
235  if (_low < oldLow) // overflow
236  _high += rhs._high + 1;
237  else
238  _high += rhs._high;
239  return *this;
240  }
241 
243  const uint64_t& low() const { return _low; }
245  const uint64_t& high() const { return _high; }
247  uint64_t& low() { return _low; }
249  uint64_t& high() { return _high; }
251  std::string getShortString() const
252  {
253  std::stringstream stream;
254  stream << std::hex << _high << _low;
255  const std::string str = stream.str();
256  return str.substr(0, 3) + ".." +
257  str.substr(str.length() - 3, std::string::npos);
258  }
259 
261  std::string getString() const
262  {
263  // OPT: snprintf is faster than using std::stringstream
264  char buffer[34] /* 2 x 16 bytes + : + \0 */;
265  snprintf(buffer, 34, "%llx:%llx", ull_t(high()), ull_t(low()));
266  return std::string(buffer);
267  }
268 
270  template <class Archive>
271  void serialize(Archive& ar, const unsigned int /*version*/)
272  {
273  ar& low();
274  ar& high();
275  }
276 
277 private:
278  uint64_t _high;
279  uint64_t _low;
280 };
281 
283 inline std::ostream& operator<<(std::ostream& os, const uint128_t& id)
284 {
285  if (id.high() == 0)
286  os << std::hex << id.low() << std::dec;
287  else
288  os << std::hex << id.high() << ':' << id.low() << std::dec;
289  return os;
290 }
291 
293 inline std::istream& operator>>(std::istream& is, uint128_t& id)
294 {
295  std::string str;
296  is >> str;
297  id = str;
298  return is;
299 }
300 
302 inline uint128_t operator+(const servus::uint128_t& a, const uint64_t& b)
303 {
304  uint128_t result = a;
305  result.low() += b;
306  if (result.low() < a.low())
307  ++result.high();
308  return result;
309 }
310 
312 inline uint128_t operator+(const servus::uint128_t& a,
313  const servus::uint128_t& b)
314 {
315  uint128_t result = a;
316  result += b;
317  return result;
318 }
319 
321 inline uint128_t operator-(const servus::uint128_t& a, const uint64_t& b)
322 {
323  uint128_t result = a;
324  result.low() -= b;
325  if (result.low() > a.low())
326  --result.high();
327  return result;
328 }
329 
331 inline uint128_t operator&(const servus::uint128_t& a,
332  const servus::uint128_t& b)
333 {
334  uint128_t result = a;
335  result.high() &= b.high();
336  result.low() &= b.low();
337  return result;
338 }
339 
341 inline uint128_t operator|(const servus::uint128_t& a,
342  const servus::uint128_t& b)
343 {
344  uint128_t result = a;
345  result.high() |= b.high();
346  result.low() |= b.low();
347  return result;
348 }
349 
357 SERVUS_API uint128_t make_uint128(const char* string);
358 
360 inline uint128_t make_uint128(const std::string& string)
361 {
362  return make_uint128(string.c_str());
363 }
364 
369 SERVUS_API uint128_t make_UUID();
370 }
371 
372 namespace std
373 {
374 template <>
375 struct hash<servus::uint128_t>
376 {
377  typedef size_t result_type;
378 
379  result_type operator()(const servus::uint128_t& in) const
380  {
381  hash<uint64_t> forward;
382  return forward(in.high()) ^ forward(in.low());
383  }
384 };
385 
386 inline string to_string(const servus::uint128_t& value)
387 {
388  return value.getString();
389 }
390 }
391 
392 #endif // SERVUS_UINT128_H
uint64_t & low()
Definition: uint128_t.h:247
const uint64_t & low() const
Definition: uint128_t.h:243
Defines export visibility macros for library Servus.
uint128_t & operator++()
Increment the value.
Definition: uint128_t.h:212
std::string getString() const
Definition: uint128_t.h:261
bool operator==(const servus::uint128_t &rhs) const
Definition: uint128_t.h:132
uint128_t(const int low_)
Construct a new 128 bit integer with a default value.
Definition: uint128_t.h:72
void serialize(Archive &ar, const unsigned int)
Serialize this object to a boost archive.
Definition: uint128_t.h:271
uint128_t & operator--()
Decrement the value.
Definition: uint128_t.h:222
STL namespace.
uint128_t & operator+=(const servus::uint128_t &rhs)
Add value and return the new value.
Definition: uint128_t.h:231
bool operator<(const servus::uint128_t &rhs) const
Definition: uint128_t.h:164
bool operator>=(const servus::uint128_t &rhs) const
Definition: uint128_t.h:202
uint64_t & high()
Definition: uint128_t.h:249
bool operator!=(const servus::uint128_t &rhs) const
Definition: uint128_t.h:140
const uint64_t & high() const
Definition: uint128_t.h:245
std::string getShortString() const
Definition: uint128_t.h:251
bool operator>(const servus::uint128_t &rhs) const
Definition: uint128_t.h:176
uint128_t(const std::string &string)
Construct a new 128 bit integer from a string representation.
Definition: uint128_t.h:90
bool operator<=(const servus::uint128_t &rhs) const
Definition: uint128_t.h:189
uint128_t(const unsigned long long low_=0)
Construct a new 128 bit integer with a default value.
Definition: uint128_t.h:54
uint128_t(const unsigned long low_)
Construct a new 128 bit integer with a default value.
Definition: uint128_t.h:63
bool operator!=(const unsigned long long &low_) const
Definition: uint128_t.h:156
A base type for 128 bit unsigned integer values.
Definition: uint128_t.h:48
uint128_t & operator=(const int rhs)
Assign an integer value.
Definition: uint128_t.h:119
bool isUUID() const
Definition: uint128_t.h:101
uint128_t(const uint64_t high_, const uint64_t low_)
Construct a new 128 bit integer with default values.
Definition: uint128_t.h:81
uint128_t & operator=(const servus::uint128_t &rhs)
Assign another 128 bit value.
Definition: uint128_t.h:103
bool operator==(const unsigned long long &low_) const
Definition: uint128_t.h:148
uint128_t & operator=(const uint64_t rhs)
Assign another 64 bit value.
Definition: uint128_t.h:111