1 // boost/endian/arithmetic.hpp -------------------------------------------------------// 2 3 // (C) Copyright Darin Adler 2000 4 // (C) Copyright Beman Dawes 2006, 2009, 2014 5 // (C) Copyright Peter Dimov 2019 6 7 // Distributed under the Boost Software License, Version 1.0. 8 // See http://www.boost.org/LICENSE_1_0.txt 9 10 // See library home page at http://www.boost.org/libs/endian 11 12 //--------------------------------------------------------------------------------------// 13 14 // Original design developed by Darin Adler based on classes developed by Mark 15 // Borgerding. Four original class templates were combined into a single endian 16 // class template by Beman Dawes, who also added the unrolled_byte_loops sign 17 // partial specialization to correctly extend the sign when cover integer size 18 // differs from endian representation size. 19 20 // TODO: When a compiler supporting constexpr becomes available, try possible uses. 21 22 #ifndef BOOST_ENDIAN_ARITHMETIC_HPP 23 #define BOOST_ENDIAN_ARITHMETIC_HPP 24 25 #if defined(_MSC_VER) 26 # pragma warning(push) 27 # pragma warning(disable:4365) // conversion ... signed/unsigned mismatch 28 #endif 29 30 #include <boost/endian/buffers.hpp> 31 #include <boost/core/scoped_enum.hpp> 32 #include <boost/static_assert.hpp> 33 #include <boost/cstdint.hpp> 34 #include <boost/config.hpp> 35 #include <boost/config/workaround.hpp> 36 #include <iosfwd> 37 #include <climits> 38 39 #if defined(BOOST_BORLANDC) || defined(BOOST_CODEGEARC) 40 # pragma pack(push, 1) 41 #endif 42 43 # if CHAR_BIT != 8 44 # error Platforms with CHAR_BIT != 8 are not supported 45 # endif 46 47 # ifdef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS 48 # define BOOST_ENDIAN_DEFAULT_CONSTRUCT {} // C++03 49 # else 50 # define BOOST_ENDIAN_DEFAULT_CONSTRUCT = default; // C++0x 51 # endif 52 53 // g++ pre-4.6 does not support unrestricted unions, but we have no Config macro for that 54 # if (defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || BOOST_WORKAROUND(BOOST_GCC, < 40600)) && defined(BOOST_ENDIAN_FORCE_PODNESS) 55 # define BOOST_ENDIAN_NO_CTORS 56 # endif 57 58 # ifndef BOOST_ENDIAN_EXPLICIT_CTORS 59 # define BOOST_ENDIAN_EXPLICIT_OPT 60 # else 61 # define BOOST_ENDIAN_EXPLICIT_OPT explicit 62 # endif 63 64 //---------------------------------- synopsis ----------------------------------------// 65 66 namespace boost 67 { 68 namespace endian 69 { 70 71 template <BOOST_SCOPED_ENUM(order) Order, class T, std::size_t n_bits, 72 BOOST_SCOPED_ENUM(align) Align = align::no> 73 class endian_arithmetic; 74 75 // big endian signed integer aligned types 76 typedef endian_arithmetic<order::big, int8_t, 8, align::yes> big_int8_at; 77 typedef endian_arithmetic<order::big, int16_t, 16, align::yes> big_int16_at; 78 typedef endian_arithmetic<order::big, int32_t, 32, align::yes> big_int32_at; 79 typedef endian_arithmetic<order::big, int64_t, 64, align::yes> big_int64_at; 80 81 // big endian unsigned integer aligned types 82 typedef endian_arithmetic<order::big, uint8_t, 8, align::yes> big_uint8_at; 83 typedef endian_arithmetic<order::big, uint16_t, 16, align::yes> big_uint16_at; 84 typedef endian_arithmetic<order::big, uint32_t, 32, align::yes> big_uint32_at; 85 typedef endian_arithmetic<order::big, uint64_t, 64, align::yes> big_uint64_at; 86 87 // little endian signed integer aligned types 88 typedef endian_arithmetic<order::little, int8_t, 8, align::yes> little_int8_at; 89 typedef endian_arithmetic<order::little, int16_t, 16, align::yes> little_int16_at; 90 typedef endian_arithmetic<order::little, int32_t, 32, align::yes> little_int32_at; 91 typedef endian_arithmetic<order::little, int64_t, 64, align::yes> little_int64_at; 92 93 // little endian unsigned integer aligned types 94 typedef endian_arithmetic<order::little, uint8_t, 8, align::yes> little_uint8_at; 95 typedef endian_arithmetic<order::little, uint16_t, 16, align::yes> little_uint16_at; 96 typedef endian_arithmetic<order::little, uint32_t, 32, align::yes> little_uint32_at; 97 typedef endian_arithmetic<order::little, uint64_t, 64, align::yes> little_uint64_at; 98 99 // aligned floating point types 100 typedef endian_arithmetic<order::big, float, 32, align::yes> big_float32_at; 101 typedef endian_arithmetic<order::big, double, 64, align::yes> big_float64_at; 102 typedef endian_arithmetic<order::little, float, 32, align::yes> little_float32_at; 103 typedef endian_arithmetic<order::little, double, 64, align::yes> little_float64_at; 104 105 // aligned native endian typedefs are not provided because 106 // <cstdint> types are superior for this use case 107 108 // big endian signed integer unaligned types 109 typedef endian_arithmetic<order::big, int_least8_t, 8> big_int8_t; 110 typedef endian_arithmetic<order::big, int_least16_t, 16> big_int16_t; 111 typedef endian_arithmetic<order::big, int_least32_t, 24> big_int24_t; 112 typedef endian_arithmetic<order::big, int_least32_t, 32> big_int32_t; 113 typedef endian_arithmetic<order::big, int_least64_t, 40> big_int40_t; 114 typedef endian_arithmetic<order::big, int_least64_t, 48> big_int48_t; 115 typedef endian_arithmetic<order::big, int_least64_t, 56> big_int56_t; 116 typedef endian_arithmetic<order::big, int_least64_t, 64> big_int64_t; 117 118 // big endian unsigned integer unaligned types 119 typedef endian_arithmetic<order::big, uint_least8_t, 8> big_uint8_t; 120 typedef endian_arithmetic<order::big, uint_least16_t, 16> big_uint16_t; 121 typedef endian_arithmetic<order::big, uint_least32_t, 24> big_uint24_t; 122 typedef endian_arithmetic<order::big, uint_least32_t, 32> big_uint32_t; 123 typedef endian_arithmetic<order::big, uint_least64_t, 40> big_uint40_t; 124 typedef endian_arithmetic<order::big, uint_least64_t, 48> big_uint48_t; 125 typedef endian_arithmetic<order::big, uint_least64_t, 56> big_uint56_t; 126 typedef endian_arithmetic<order::big, uint_least64_t, 64> big_uint64_t; 127 128 // little endian signed integer unaligned types 129 typedef endian_arithmetic<order::little, int_least8_t, 8> little_int8_t; 130 typedef endian_arithmetic<order::little, int_least16_t, 16> little_int16_t; 131 typedef endian_arithmetic<order::little, int_least32_t, 24> little_int24_t; 132 typedef endian_arithmetic<order::little, int_least32_t, 32> little_int32_t; 133 typedef endian_arithmetic<order::little, int_least64_t, 40> little_int40_t; 134 typedef endian_arithmetic<order::little, int_least64_t, 48> little_int48_t; 135 typedef endian_arithmetic<order::little, int_least64_t, 56> little_int56_t; 136 typedef endian_arithmetic<order::little, int_least64_t, 64> little_int64_t; 137 138 // little endian unsigned integer unaligned types 139 typedef endian_arithmetic<order::little, uint_least8_t, 8> little_uint8_t; 140 typedef endian_arithmetic<order::little, uint_least16_t, 16> little_uint16_t; 141 typedef endian_arithmetic<order::little, uint_least32_t, 24> little_uint24_t; 142 typedef endian_arithmetic<order::little, uint_least32_t, 32> little_uint32_t; 143 typedef endian_arithmetic<order::little, uint_least64_t, 40> little_uint40_t; 144 typedef endian_arithmetic<order::little, uint_least64_t, 48> little_uint48_t; 145 typedef endian_arithmetic<order::little, uint_least64_t, 56> little_uint56_t; 146 typedef endian_arithmetic<order::little, uint_least64_t, 64> little_uint64_t; 147 148 // native endian signed integer unaligned types 149 typedef endian_arithmetic<order::native, int_least8_t, 8> native_int8_t; 150 typedef endian_arithmetic<order::native, int_least16_t, 16> native_int16_t; 151 typedef endian_arithmetic<order::native, int_least32_t, 24> native_int24_t; 152 typedef endian_arithmetic<order::native, int_least32_t, 32> native_int32_t; 153 typedef endian_arithmetic<order::native, int_least64_t, 40> native_int40_t; 154 typedef endian_arithmetic<order::native, int_least64_t, 48> native_int48_t; 155 typedef endian_arithmetic<order::native, int_least64_t, 56> native_int56_t; 156 typedef endian_arithmetic<order::native, int_least64_t, 64> native_int64_t; 157 158 // native endian unsigned integer unaligned types 159 typedef endian_arithmetic<order::native, uint_least8_t, 8> native_uint8_t; 160 typedef endian_arithmetic<order::native, uint_least16_t, 16> native_uint16_t; 161 typedef endian_arithmetic<order::native, uint_least32_t, 24> native_uint24_t; 162 typedef endian_arithmetic<order::native, uint_least32_t, 32> native_uint32_t; 163 typedef endian_arithmetic<order::native, uint_least64_t, 40> native_uint40_t; 164 typedef endian_arithmetic<order::native, uint_least64_t, 48> native_uint48_t; 165 typedef endian_arithmetic<order::native, uint_least64_t, 56> native_uint56_t; 166 typedef endian_arithmetic<order::native, uint_least64_t, 64> native_uint64_t; 167 168 // unaligned floating point types 169 typedef endian_arithmetic<order::big, float, 32, align::no> big_float32_t; 170 typedef endian_arithmetic<order::big, double, 64, align::no> big_float64_t; 171 typedef endian_arithmetic<order::little, float, 32, align::no> little_float32_t; 172 typedef endian_arithmetic<order::little, double, 64, align::no> little_float64_t; 173 typedef endian_arithmetic<order::native, float, 32, align::no> native_float32_t; 174 typedef endian_arithmetic<order::native, double, 64, align::no> native_float64_t; 175 176 //---------------------------------- end synopsis ------------------------------------// 177 178 template <BOOST_SCOPED_ENUM(order) Order, class T, std::size_t n_bits, 179 BOOST_SCOPED_ENUM(align) Align> 180 class endian_arithmetic: 181 public endian_buffer<Order, T, n_bits, Align> 182 { 183 private: 184 185 typedef endian_buffer<Order, T, n_bits, Align> inherited; 186 187 public: 188 189 typedef T value_type; 190 191 #ifndef BOOST_ENDIAN_NO_CTORS 192 endian_arithmetic()193 endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT 194 195 BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic( T val ) BOOST_NOEXCEPT: inherited( val ) 196 { 197 } 198 199 #endif 200 operator =(T val)201 endian_arithmetic& operator=( T val ) BOOST_NOEXCEPT 202 { 203 inherited::operator=( val ); 204 return *this; 205 } 206 operator value_type() const207 operator value_type() const BOOST_NOEXCEPT 208 { 209 return this->value(); 210 } 211 212 // operators 213 operator +() const214 T operator+() const BOOST_NOEXCEPT 215 { 216 return this->value(); 217 } 218 operator +=(T y)219 endian_arithmetic& operator+=( T y ) BOOST_NOEXCEPT 220 { 221 *this = static_cast<T>( this->value() + y ); 222 return *this; 223 } 224 operator -=(T y)225 endian_arithmetic& operator-=( T y ) BOOST_NOEXCEPT 226 { 227 *this = static_cast<T>( this->value() - y ); 228 return *this; 229 } 230 operator *=(T y)231 endian_arithmetic& operator*=( T y ) BOOST_NOEXCEPT 232 { 233 *this = static_cast<T>( this->value() * y ); 234 return *this; 235 } 236 operator /=(T y)237 endian_arithmetic& operator/=( T y ) BOOST_NOEXCEPT 238 { 239 *this = static_cast<T>( this->value() / y ); 240 return *this; 241 } 242 operator %=(T y)243 endian_arithmetic& operator%=( T y ) BOOST_NOEXCEPT 244 { 245 *this = static_cast<T>( this->value() % y ); 246 return *this; 247 } 248 operator &=(T y)249 endian_arithmetic& operator&=( T y ) BOOST_NOEXCEPT 250 { 251 *this = static_cast<T>( this->value() & y ); 252 return *this; 253 } 254 operator |=(T y)255 endian_arithmetic& operator|=( T y ) BOOST_NOEXCEPT 256 { 257 *this = static_cast<T>( this->value() | y ); 258 return *this; 259 } 260 operator ^=(T y)261 endian_arithmetic& operator^=( T y ) BOOST_NOEXCEPT 262 { 263 *this = static_cast<T>( this->value() ^ y ); 264 return *this; 265 } 266 operator <<=(T y)267 endian_arithmetic& operator<<=( T y ) BOOST_NOEXCEPT 268 { 269 *this = static_cast<T>( this->value() << y ); 270 return *this; 271 } 272 operator >>=(T y)273 endian_arithmetic& operator>>=( T y ) BOOST_NOEXCEPT 274 { 275 *this = static_cast<T>( this->value() >> y ); 276 return *this; 277 } 278 operator ++()279 endian_arithmetic& operator++() BOOST_NOEXCEPT 280 { 281 *this += 1; 282 return *this; 283 } 284 operator --()285 endian_arithmetic& operator--() BOOST_NOEXCEPT 286 { 287 *this -= 1; 288 return *this; 289 } 290 operator ++(int)291 endian_arithmetic operator++(int) BOOST_NOEXCEPT 292 { 293 endian_arithmetic tmp( *this ); 294 *this += 1; 295 return tmp; 296 } 297 operator --(int)298 endian_arithmetic operator--(int) BOOST_NOEXCEPT 299 { 300 endian_arithmetic tmp( *this ); 301 *this -= 1; 302 return tmp; 303 } 304 305 template<class Ch, class Tr> 306 friend std::basic_ostream<Ch, Tr>& operator <<(std::basic_ostream<Ch,Tr> & os,endian_arithmetic const & x)307 operator<<( std::basic_ostream<Ch, Tr>& os, endian_arithmetic const& x ) 308 { 309 return os << x.value(); 310 } 311 312 template<class Ch, class Tr> 313 friend std::basic_istream<Ch, Tr>& operator >>(std::basic_istream<Ch,Tr> & is,endian_arithmetic & x)314 operator>>( std::basic_istream<Ch, Tr>& is, endian_arithmetic& x ) 315 { 316 T i; 317 318 if( is >> i ) 319 { 320 x = i; 321 } 322 323 return is; 324 } 325 }; 326 327 } // namespace endian 328 } // namespace boost 329 330 #if defined(BOOST_BORLANDC) || defined(BOOST_CODEGEARC) 331 # pragma pack(pop) 332 #endif 333 334 #if defined(_MSC_VER) 335 # pragma warning(pop) 336 #endif 337 338 #endif // BOOST_ENDIAN_ARITHMETIC_HPP 339