Lunchbox  1.8.0
uint128_t.h
1 
2 /* Copyright (c) 2010, Cedric Stalder <cedric.stalder@gmail.com>
3  * 2010-2013, Stefan Eilemann <eile@eyescale.ch>
4  * 2010-2012, Daniel Nachbaur <danielnachbaur@gmail.com>
5  *
6  * This library is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU Lesser General Public License version 2.1 as published
8  * by the Free Software Foundation.
9  *
10  * This library is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13  * details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this library; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 #ifndef LUNCHBOX_UINT128_H
21 #define LUNCHBOX_UINT128_H
22 
23 #include <lunchbox/api.h>
24 #include <sstream>
25 
26 #ifdef _MSC_VER
27 // Don't include <lunchbox/types.h> to be minimally intrusive for apps
28 // using uint128_t
29 # include <basetsd.h>
30 typedef UINT64 uint64_t;
31 #else
32 # include <stdint.h>
33 #endif
34 
35 namespace lunchbox
36 {
37  class uint128_t;
38  std::ostream& operator << ( std::ostream& os, const uint128_t& id );
39 
41  class uint128_t
42  {
43  public:
48  uint128_t( const uint64_t low_ = 0 )
49  : _high( 0 ), _low( low_ ) {}
50 
55  explicit uint128_t( const uint64_t high_, const uint64_t low_ )
56  : _high( high_ ), _low( low_ ) {}
57 
62  explicit uint128_t( const std::string& string )
63  : _high( 0 ), _low( 0 ) { *this = string; }
64 
67  {
68  _high = rhs._high;
69  _low = rhs._low;
70  return *this;
71  }
72 
74  uint128_t& operator = ( const uint64_t rhs )
75  {
76  _high = 0;
77  _low = rhs;
78  return *this;
79  }
80 
82  uint128_t& operator = ( const int rhs )
83  {
84  _high = 0;
85  _low = rhs;
86  return *this;
87  }
88 
90  LUNCHBOX_API uint128_t& operator = ( const std::string& from );
91 
96  bool operator == ( const uint128_t& rhs ) const
97  { return _high == rhs._high && _low == rhs._low; }
98 
103  bool operator != ( const uint128_t& rhs ) const
104  { return _high != rhs._high || _low != rhs._low; }
105 
110  bool operator < ( const uint128_t& rhs ) const
111  {
112  if( _high < rhs._high )
113  return true;
114  if( _high > rhs._high )
115  return false;
116  return _low < rhs._low;
117  }
118 
123  bool operator > ( const uint128_t& rhs ) const
124  {
125  if( _high > rhs._high )
126  return true;
127  if( _high < rhs._high )
128  return false;
129  return _low > rhs._low;
130  }
131 
137  bool operator <= ( const uint128_t& rhs ) const
138  {
139  if( _high < rhs._high )
140  return true;
141  if( _high > rhs._high )
142  return false;
143  return _low <= rhs._low;
144  }
145 
151  bool operator >= ( const uint128_t& rhs ) const
152  {
153  if( _high > rhs._high )
154  return true;
155  if( _high < rhs._high )
156  return false;
157  return _low >= rhs._low;
158  }
159 
162  {
163  ++_low;
164  if( !_low )
165  ++_high;
166 
167  return *this;
168  }
169 
172  {
173  if( !_low )
174  --_high;
175  --_low;
176  return *this;
177  }
178 
181  {
182  const uint64_t oldLow = _low;
183  _low += rhs._low;
184  if( _low < oldLow ) // overflow
185  _high += rhs._high + 1;
186  else
187  _high += rhs._high;
188  return *this;
189  }
190 
192  const uint64_t& low() const { return _low; }
194  const uint64_t& high() const { return _high; }
195 
197  uint64_t& low() { return _low; }
199  uint64_t& high() { return _high; }
200 
202  std::string getShortString() const
203  {
204  std::stringstream stream;
205  stream << std::hex << _high << _low;
206  const std::string str = stream.str();
207  return str.substr( 0, 3 ) + ".." +
208  str.substr( str.length() - 3, std::string::npos );
209  }
210 
212  std::string getString() const
213  {
214  std::stringstream stream;
215  stream << *this;
216  return stream.str();
217  }
218 
220  template< class Archive >
221  void serialize( Archive& ar, const unsigned int version )
222  {
223  ar & low();
224  ar & high();
225  }
226 
227 #ifdef LUNCHBOX_USE_V1_API
228 
229  static LUNCHBOX_API const uint128_t ZERO;
230 #endif
231 
232  private:
233  uint64_t _high;
234  uint64_t _low;
235  };
236 
238  inline std::ostream& operator << ( std::ostream& os, const uint128_t& id )
239  {
240  if( id.high() == 0 )
241  os << std::hex << id.low() << std::dec;
242  else
243  os << std::hex << id.high() << ':' << id.low() << std::dec;
244  return os;
245  }
246 
248  inline std::istream& operator >> ( std::istream& is, uint128_t& id )
249  {
250  std::string str;
251  is >> str;
252  id = str;
253  return is;
254  }
255 
257  inline uint128_t operator+ ( const uint128_t& a, const uint64_t& b )
258  {
259  uint128_t result = a;
260  result.low() += b;
261  if( result.low() < a.low( ))
262  ++result.high();
263  return result;
264  }
265 
267  inline uint128_t operator+ ( const uint128_t& a, const uint128_t& b )
268  {
269  uint128_t result = a;
270  result += b;
271  return result;
272  }
273 
275  inline uint128_t operator- ( const uint128_t& a, const uint64_t& b )
276  {
277  uint128_t result = a;
278  result.low() -= b;
279  if( result.low() > a.low( ))
280  --result.high();
281  return result;
282  }
283 
285  inline uint128_t operator & ( const uint128_t& a, const uint128_t& b )
286  {
287  uint128_t result = a;
288  result.high() &= b.high();
289  result.low() &= b.low();
290  return result;
291  }
292 
294  inline uint128_t operator | ( const uint128_t& a, const uint128_t& b )
295  {
296  uint128_t result = a;
297  result.high() |= b.high();
298  result.low() |= b.low();
299  return result;
300  }
301 
310  LUNCHBOX_API uint128_t make_uint128( const char* string );
311 }
312 #endif // LUNCHBOX_UINT128_H