// Boost exact.hpp header file (proposed) ----------------------------------// // (C) Copyright Darin Adler 2000 // (C) Copyright Beman Dawes 2006 // (C) Copyright Scott McMurray 2006 // Use, modification, and distribution is subject to the Boost Software // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy // at http://www.boost.org/LICENSE_1_0.txt) // See library home page at http://www.boost.org/libs/integer //----------------------------------------------------------------------------// // Interface to the big_endian and little_endian class templates developed by // Darin Adler based on classes of the same name developed by Mark Borgerding. #ifndef BOOST_EXACT_HPP #define BOOST_EXACT_HPP #include #include #include #include #include #include #include #include #include #include namespace boost { namespace detail { // A class that adds integer operators to an integer cover class, // like the little_endian and big_endian class templates. template class integer_cover_operators : boost::operators { // The other operations take advantage of the type conversion that's // built into unary +. // Unary operations. friend IntegerType operator+(const T& x) { return x; } friend IntegerType operator-(const T& x) { return -+x; } friend IntegerType operator~(const T& x) { return ~+x; } friend IntegerType operator!(const T& x) { return !+x; } // The basic ordering operations. friend bool operator==(const T& x, IntegerType y) { return +x == y; } friend bool operator<(const T& x, IntegerType y) { return +x < y; } // The basic arithmetic operations. friend T& operator+=(T& x, IntegerType y) { return x = +x + y; } friend T& operator-=(T& x, IntegerType y) { return x = +x - y; } friend T& operator*=(T& x, IntegerType y) { return x = +x * y; } friend T& operator/=(T& x, IntegerType y) { return x = +x / y; } friend T& operator%=(T& x, IntegerType y) { return x = +x % y; } friend T& operator&=(T& x, IntegerType y) { return x = +x & y; } friend T& operator|=(T& x, IntegerType y) { return x = +x | y; } friend T& operator^=(T& x, IntegerType y) { return x = +x ^ y; } friend T& operator<<=(T& x, IntegerType y) { return x = +x << y; } friend T& operator>>=(T& x, IntegerType y) { return x = +x >> y; } // A few binary arithmetic operations not covered by operators base class. friend IntegerType operator<<(const T& x, IntegerType y) { return +x << y; } friend IntegerType operator>>(const T& x, IntegerType y) { return +x >> y; } // Auto-increment and auto-decrement can be defined in terms of the // arithmetic operations. friend T& operator++(T& x) { return x += 1; } friend T& operator--(T& x) { return x -= 1; } // Stream input and output. friend std::ostream& operator<<(std::ostream& s, const T& x) { return s << +x; } friend std::istream& operator>>(std::istream& s, T& x) { IntegerType i; if (s >> i) x = i; return s; } }; // Class that represents unaligned bytes. // Taking an integer type as a parameter provides a nice way to pass both the // size and signedness of the desired integer and get the appropriate // corresponding integer type for the interface. template class exact_t : integer_cover_operators, T> { enum { bits_per_byte = std::numeric_limits::digits }; enum { num_bytes = num_bits/bits_per_byte }; BOOST_STATIC_ASSERT( !(num_bits % bits_per_byte) ); public: typedef T value_type; exact_t() {} exact_t(T i) { char * const icp = reinterpret_cast(&i); #ifdef BOOST_BIG_ENDIAN std::copy( icp + sizeof(T) - num_bytes, icp + sizeof(T), #else std::copy( icp, icp + num_bytes, #endif bytes ); } operator T() const { /* // Sign extending trick from // http://graphics.stanford.edu/~seander/bithacks.html#FixedSignExtend // It's quite elegant, but wouldn't work were T not a fundamental // integral type, so I also included the manual one below struct { T x : num_bits; } s; std::copy( bytes, bytes + num_bytes, reinterpret_cast(&s) ); return s.x; */ ///* // Sign extending trick from // http://graphics.stanford.edu/~seander/bithacks.html#VariableSignExtend T i = 0; char * const icp = reinterpret_cast(&i); std::copy( bytes, bytes + num_bytes, #ifdef BOOST_BIG_ENDIAN icp + sizeof(T)-num_bytes ); #else icp ); #endif // g++ 3.4.6 resolves this if at compile-time if ( boost::is_signed::value ) { T const mask = T(1) << ( num_bits - 1 ); return -(i & mask) | i; } else { return i; } //*/ } private: char bytes[num_bytes]; }; } // namespace detail template class exact_int_t { typedef typename boost::int_t::fast value_type; typedef detail::exact_t< value_type, N > base_type; base_type b; public: exact_int_t() {} exact_int_t(value_type i) : b(i) {} operator value_type() { return b; } }; template class exact_uint_t { typedef typename boost::uint_t::fast value_type; typedef detail::exact_t< value_type, N > base_type; base_type b; public: exact_uint_t() {} exact_uint_t(value_type i) : b(i) {} operator value_type() { return b; } }; } // namespace boost #endif // BOOST_EXACT_HPP