LCOV - code coverage report
Current view: top level - lunchbox - uint128_t.h (source / functions) Hit Total Coverage
Test: lcov2.info Lines: 52 55 94.5 %
Date: 2014-10-01 Functions: 21 21 100.0 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2010, Cedric Stalder <cedric.stalder@gmail.com>
       3             :  *               2010-2014, 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 <lunchbox/compiler.h>
      25             : 
      26             : #include <sstream>
      27             : #ifdef _MSC_VER
      28             : // Don't include <lunchbox/types.h> to be minimally intrusive for apps
      29             : // using uint128_t
      30             : #  include <basetsd.h>
      31             : typedef UINT64     uint64_t;
      32             : #else
      33             : #  include <stdint.h>
      34             : #endif
      35             : 
      36             : namespace lunchbox
      37             : {
      38             : class uint128_t;
      39             : std::ostream& operator << ( std::ostream& os, const uint128_t& id );
      40             : 
      41             : /**
      42             :  * A base type for 128 bit unsigned integer values.
      43             :  *
      44             :  * Example: @include tests/uint128_t.cpp
      45             :  */
      46             : class uint128_t
      47             : {
      48             : public:
      49             :     /**
      50             :      * Construct a new 128 bit integer with a default value.
      51             :      * @version 1.0
      52             :      */
      53      199542 :     explicit uint128_t( const unsigned long long low_ = 0 )
      54      199542 :         : _high( 0 ), _low( low_ ) {}
      55             : 
      56             :     /**
      57             :      * Construct a new 128 bit integer with a default value.
      58             :      * @version 1.9.1
      59             :      */
      60             :     explicit uint128_t( const unsigned long low_ ) : _high( 0 ), _low( low_ ) {}
      61             : 
      62             :     /**
      63             :      * Construct a new 128 bit integer with a default value.
      64             :      * @version 1.9.1
      65             :      */
      66           2 :     explicit uint128_t( const int low_ ) : _high( 0 ), _low( low_ ) {}
      67             : 
      68             : #ifdef LUNCHBOX_USE_V1_API
      69             :     /**
      70             :      * Construct a new 128 bit integer with a generated universally unique
      71             :      * identifier.
      72             :      *
      73             :      * @param generate if set to false, the uint128_t will be set to 0.
      74             :      * @version 1.9.1
      75             :      * @deprecated
      76             :      */
      77             :     LUNCHBOX_API explicit uint128_t( const bool generate ) LB_DEPRECATED;
      78             : #endif
      79             : 
      80             :     /**
      81             :      * Construct a new 128 bit integer with default values.
      82             :      * @version 1.0
      83             :      **/
      84          13 :     uint128_t( const uint64_t high_, const uint64_t low_ )
      85          13 :         : _high( high_ ), _low( low_ ) {}
      86             : 
      87             :     /**
      88             :      * Construct a new 128 bit integer from a string representation.
      89             :      * @version 1.3.2
      90             :      **/
      91             :     explicit uint128_t( const std::string& string )
      92             :         : _high( 0 ), _low( 0 ) { *this = string; }
      93             : 
      94             :     /**
      95             :      * @return true if the uint128_t is a generated universally unique
      96             :      *         identifier.
      97             :      * @version 1.9.1
      98             :      */
      99       99996 :     bool isUUID() const { return high() != 0; }
     100             : 
     101             :     /** Assign another 128 bit value. @version 1.0 */
     102      400014 :     uint128_t& operator = ( const lunchbox::uint128_t& rhs )
     103             :         {
     104      400014 :             _high = rhs._high;
     105      400014 :             _low = rhs._low;
     106      400014 :             return *this;
     107             :         }
     108             : 
     109             :     /** Assign another 64 bit value. @version 1.1.1 */
     110             :     uint128_t& operator = ( const uint64_t rhs )
     111             :         {
     112             :             _high = 0;
     113             :             _low = rhs;
     114             :             return *this;
     115             :         }
     116             : 
     117             :     /** Assign an integer value. @version 1.7.1 */
     118             :     uint128_t& operator = ( const int rhs )
     119             :         {
     120             :             _high = 0;
     121             :             _low = rhs;
     122             :             return *this;
     123             :         }
     124             : 
     125             :     /** Assign an 128 bit value from a std::string. @version 1.0 */
     126             :     LUNCHBOX_API uint128_t& operator = ( const std::string& from );
     127             : 
     128             :     /**
     129             :      * @return true if the values are equal, false if not.
     130             :      * @version 1.0
     131             :      **/
     132      180011 :     bool operator == ( const lunchbox::uint128_t& rhs ) const
     133      180011 :         { return _high == rhs._high && _low == rhs._low; }
     134             : 
     135             :     /**
     136             :      * @return true if the values are different, false otherwise.
     137             :      * @version 1.0
     138             :      **/
     139      383661 :     bool operator != ( const lunchbox::uint128_t& rhs ) const
     140      383661 :         { return _high != rhs._high || _low != rhs._low; }
     141             : 
     142             :     /**
     143             :      * @return true if the values are equal, false otherwise.
     144             :      * @version 1.9.1
     145             :      **/
     146             :     bool operator == ( const unsigned long long& low_ ) const
     147             :         { return *this == uint128_t( low_ ); }
     148             : 
     149             :     /**
     150             :      * @return true if the values are different, false otherwise.
     151             :      * @version 1.9.1
     152             :      **/
     153             :     bool operator != ( const unsigned long long& low_ ) const
     154             :         { return *this != uint128_t( low_ ); }
     155             : 
     156             :     /**
     157             :      * @return true if this value is smaller than the RHS value.
     158             :      * @version 1.0
     159             :      **/
     160             :     bool operator < ( const lunchbox::uint128_t& rhs ) const
     161             :         {
     162             :             if( _high < rhs._high )
     163             :                 return true;
     164             :             if( _high > rhs._high )
     165             :                 return false;
     166             :             return _low < rhs._low;
     167             :         }
     168             : 
     169             :     /**
     170             :      * @return true if this value is bigger than the rhs value.
     171             :      * @version 1.0
     172             :      */
     173       76731 :     bool operator > ( const lunchbox::uint128_t& rhs ) const
     174             :         {
     175       76731 :             if( _high > rhs._high )
     176           0 :                 return true;
     177       76731 :             if( _high < rhs._high )
     178       76731 :                 return false;
     179           0 :             return _low > rhs._low;
     180             :         }
     181             : 
     182             :     /**
     183             :      * @return true if this value is smaller or equal than the
     184             :      *         RHS value.
     185             :      * @version 1.0
     186             :      */
     187             :     bool operator <= ( const lunchbox::uint128_t& rhs ) const
     188             :         {
     189             :             if( _high < rhs._high )
     190             :                 return true;
     191             :             if( _high > rhs._high )
     192             :                 return false;
     193             :             return _low <= rhs._low;
     194             :         }
     195             : 
     196             :     /**
     197             :      * @return true if this value is smaller or equal than the
     198             :      *         RHS value.
     199             :      * @version 1.0
     200             :      */
     201             :     bool operator >= ( const lunchbox::uint128_t& rhs ) const
     202             :         {
     203             :             if( _high > rhs._high )
     204             :                 return true;
     205             :             if( _high < rhs._high )
     206             :                 return false;
     207             :             return _low >= rhs._low;
     208             :         }
     209             : 
     210             :     /** Increment the value. @version 1.0 */
     211           4 :     uint128_t& operator ++()
     212             :         {
     213           4 :             ++_low;
     214           4 :             if( !_low )
     215           2 :                 ++_high;
     216             : 
     217           4 :             return *this;
     218             :         }
     219             : 
     220             :     /** Decrement the value. @version 1.0 */
     221           4 :     uint128_t& operator --()
     222             :         {
     223           4 :             if( !_low )
     224           2 :                 --_high;
     225           4 :             --_low;
     226           4 :             return *this;
     227             :         }
     228             : 
     229             :     /** Add value and return the new value. @version 1.5.1 */
     230             :     uint128_t& operator +=( const lunchbox::uint128_t& rhs )
     231             :         {
     232             :             const uint64_t oldLow = _low;
     233             :             _low += rhs._low;
     234             :             if( _low < oldLow ) // overflow
     235             :                 _high += rhs._high + 1;
     236             :             else
     237             :                 _high += rhs._high;
     238             :             return *this;
     239             :         }
     240             : 
     241             :     /** @return the reference to the lower 64 bits of this 128 bit value. */
     242      469079 :     const uint64_t& low() const { return _low; }
     243             :     /** @return the reference to the high 64 bits of this 128 bit value. */
     244      658418 :     const uint64_t& high() const { return _high; }
     245             : 
     246             :     /** @return the reference to the lower 64 bits of this 128 bit value. */
     247      100044 :     uint64_t& low() { return _low; }
     248             :     /** @return the reference to the high 64 bits of this 128 bit value. */
     249      296329 :     uint64_t& high() { return _high; }
     250             : 
     251             :     /** @return a short, but not necessarily unique, string of the value. */
     252             :     std::string getShortString() const
     253             :         {
     254             :             std::stringstream stream;
     255             :             stream << std::hex << _high << _low;
     256             :             const std::string str = stream.str();
     257             :             return str.substr( 0, 3 ) + ".." +
     258             :                 str.substr( str.length() - 3, std::string::npos );
     259             :         }
     260             : 
     261             :     /** @return the full string representation of the value. */
     262             :     std::string getString() const
     263             :         {
     264             :             std::stringstream stream;
     265             :             stream << *this;
     266             :             return stream.str();
     267             :         }
     268             : 
     269             :     /** Serialize this object to a boost archive. @version 1.3.1 */
     270             :     template< class Archive >
     271           4 :     void serialize( Archive& ar, const unsigned int /*version*/ )
     272             :     {
     273           4 :         ar & low();
     274           4 :         ar & high();
     275           4 :     }
     276             : 
     277             : #ifdef LUNCHBOX_USE_V1_API
     278             :     /** @return true if the uint128_t was generated.
     279             :      *  @deprecated
     280             :      */
     281             :     bool isGenerated() const LB_DEPRECATED { return high() != 0; }
     282             : 
     283             :     /** @deprecated Don't use, static initializer fiasco. Use 0/uint128_t()*/
     284             :     static LUNCHBOX_API const uint128_t ZERO LB_DEPRECATED;
     285             : #endif
     286             : 
     287             : private:
     288             :     uint64_t _high;
     289             :     uint64_t _low;
     290             : };
     291             : 
     292             : /** ostream operator for 128 bit unsigned integers. @version 1.0 */
     293       90000 : inline std::ostream& operator << ( std::ostream& os, const uint128_t& id )
     294             : {
     295       90000 :     if( id.high() == 0 )
     296           0 :         os << std::hex << id.low() << std::dec;
     297             :     else
     298       90000 :         os << std::hex << id.high() << ':' << id.low() << std::dec;
     299       90000 :     return os;
     300             : }
     301             : 
     302             : /** istream operator for 128 bit unsigned integers. @version 1.7.0 */
     303             : inline std::istream& operator >> ( std::istream& is, uint128_t& id )
     304             : {
     305             :     std::string str;
     306             :     is >> str;
     307             :     id = str;
     308             :     return is;
     309             : }
     310             : 
     311             : /** Add a 64 bit value to a 128 bit value. @version 1.0 */
     312           4 : inline uint128_t operator+ ( const lunchbox::uint128_t& a, const uint64_t& b )
     313             : {
     314           4 :     uint128_t result = a;
     315           4 :     result.low() += b;
     316           4 :     if( result.low() < a.low( ))
     317           2 :         ++result.high();
     318           4 :     return result;
     319             : }
     320             : 
     321             : /** Add two 128 bit values. @version 1.5.1 */
     322             : inline uint128_t operator+ ( const lunchbox::uint128_t& a,
     323             :                              const lunchbox::uint128_t& b )
     324             : {
     325             :     uint128_t result = a;
     326             :     result += b;
     327             :     return result;
     328             : }
     329             : 
     330             : /** Subtract a 64 bit value from a 128 bit value. @version 1.0 */
     331           4 : inline uint128_t operator- ( const lunchbox::uint128_t& a, const uint64_t& b )
     332             : {
     333           4 :     uint128_t result = a;
     334           4 :     result.low() -= b;
     335           4 :     if( result.low() > a.low( ))
     336           2 :         --result.high();
     337           4 :     return result;
     338             : }
     339             : 
     340             : /** Bitwise and operation on two 128 bit values. @version 1.1.5 */
     341             : inline uint128_t operator & ( const lunchbox::uint128_t& a,
     342             :                               const lunchbox::uint128_t& b )
     343             : {
     344             :     uint128_t result = a;
     345             :     result.high() &= b.high();
     346             :     result.low() &= b.low();
     347             :     return result;
     348             : }
     349             : 
     350             : /** Bitwise or operation on two 128 bit values. @version 1.1.5 */
     351             : inline uint128_t operator | ( const lunchbox::uint128_t& a,
     352             :                               const lunchbox::uint128_t& b )
     353             : {
     354             :     uint128_t result = a;
     355             :     result.high() |= b.high();
     356             :     result.low() |= b.low();
     357             :     return result;
     358             : }
     359             : 
     360             : /**
     361             :  * Create a 128 bit integer based on a string.
     362             :  *
     363             :  * The MD5 hash of the given text is used to form the uint128_t.
     364             :  *
     365             :  * @param string the string to form the uint128_t from.
     366             :  * @version 1.3.2
     367             :  */
     368             : LUNCHBOX_API uint128_t make_uint128( const char* string );
     369             : 
     370             : /**
     371             :  * Construct a new 128 bit integer with a generated universally unique
     372             :  * identifier.
     373             :  * @version 1.9.1
     374             :  */
     375             : LUNCHBOX_API uint128_t make_UUID();
     376             : 
     377             : }
     378             : #endif // LUNCHBOX_UINT128_H

Generated by: LCOV version 1.10