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 { 182 private: 183 184 typedef endian_buffer<Order, T, n_bits, Align> buffer_type; 185 186 #ifdef BOOST_ENDIAN_NO_CTORS 187 public: 188 #else 189 private: 190 #endif 191 192 buffer_type buf_; 193 194 public: 195 196 typedef T value_type; 197 198 #ifndef BOOST_ENDIAN_NO_CTORS 199 endian_arithmetic()200 endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT 201 202 BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic( T val ) BOOST_NOEXCEPT: buf_( val ) 203 { 204 } 205 206 #endif 207 operator =(T val)208 endian_arithmetic& operator=( T val ) BOOST_NOEXCEPT 209 { 210 buf_ = val; 211 return *this; 212 } 213 value() const214 value_type value() const BOOST_NOEXCEPT 215 { 216 return buf_.value(); 217 } 218 data() const219 unsigned char const * data() const BOOST_NOEXCEPT 220 { 221 return buf_.data(); 222 } 223 data()224 unsigned char * data() BOOST_NOEXCEPT 225 { 226 return buf_.data(); 227 } 228 operator value_type() const229 operator value_type() const BOOST_NOEXCEPT 230 { 231 return this->value(); 232 } 233 operator buffer_type&()234 operator buffer_type& () BOOST_NOEXCEPT 235 { 236 return buf_; 237 } 238 operator buffer_type const&()239 operator buffer_type const& () BOOST_NOEXCEPT 240 { 241 return buf_; 242 } 243 244 // operators 245 operator +() const246 T operator+() const BOOST_NOEXCEPT 247 { 248 return this->value(); 249 } 250 operator +=(T y)251 endian_arithmetic& operator+=( T y ) BOOST_NOEXCEPT 252 { 253 *this = static_cast<T>( this->value() + y ); 254 return *this; 255 } 256 operator -=(T y)257 endian_arithmetic& operator-=( T y ) BOOST_NOEXCEPT 258 { 259 *this = static_cast<T>( this->value() - y ); 260 return *this; 261 } 262 operator *=(T y)263 endian_arithmetic& operator*=( T y ) BOOST_NOEXCEPT 264 { 265 *this = static_cast<T>( this->value() * y ); 266 return *this; 267 } 268 operator /=(T y)269 endian_arithmetic& operator/=( T y ) BOOST_NOEXCEPT 270 { 271 *this = static_cast<T>( this->value() / y ); 272 return *this; 273 } 274 operator %=(T y)275 endian_arithmetic& operator%=( T y ) BOOST_NOEXCEPT 276 { 277 *this = static_cast<T>( this->value() % y ); 278 return *this; 279 } 280 operator &=(T y)281 endian_arithmetic& operator&=( T y ) BOOST_NOEXCEPT 282 { 283 *this = static_cast<T>( this->value() & y ); 284 return *this; 285 } 286 operator |=(T y)287 endian_arithmetic& operator|=( T y ) BOOST_NOEXCEPT 288 { 289 *this = static_cast<T>( this->value() | y ); 290 return *this; 291 } 292 operator ^=(T y)293 endian_arithmetic& operator^=( T y ) BOOST_NOEXCEPT 294 { 295 *this = static_cast<T>( this->value() ^ y ); 296 return *this; 297 } 298 operator <<=(T y)299 endian_arithmetic& operator<<=( T y ) BOOST_NOEXCEPT 300 { 301 *this = static_cast<T>( this->value() << y ); 302 return *this; 303 } 304 operator >>=(T y)305 endian_arithmetic& operator>>=( T y ) BOOST_NOEXCEPT 306 { 307 *this = static_cast<T>( this->value() >> y ); 308 return *this; 309 } 310 operator ++()311 endian_arithmetic& operator++() BOOST_NOEXCEPT 312 { 313 *this += 1; 314 return *this; 315 } 316 operator --()317 endian_arithmetic& operator--() BOOST_NOEXCEPT 318 { 319 *this -= 1; 320 return *this; 321 } 322 operator ++(int)323 endian_arithmetic operator++(int) BOOST_NOEXCEPT 324 { 325 endian_arithmetic tmp( *this ); 326 *this += 1; 327 return tmp; 328 } 329 operator --(int)330 endian_arithmetic operator--(int) BOOST_NOEXCEPT 331 { 332 endian_arithmetic tmp( *this ); 333 *this -= 1; 334 return tmp; 335 } 336 337 template<class Ch, class Tr> 338 friend std::basic_ostream<Ch, Tr>& operator <<(std::basic_ostream<Ch,Tr> & os,endian_arithmetic const & x)339 operator<<( std::basic_ostream<Ch, Tr>& os, endian_arithmetic const& x ) 340 { 341 return os << x.value(); 342 } 343 344 template<class Ch, class Tr> 345 friend std::basic_istream<Ch, Tr>& operator >>(std::basic_istream<Ch,Tr> & is,endian_arithmetic & x)346 operator>>( std::basic_istream<Ch, Tr>& is, endian_arithmetic& x ) 347 { 348 T i; 349 350 if( is >> i ) 351 { 352 x = i; 353 } 354 355 return is; 356 } 357 }; 358 359 } // namespace endian 360 } // namespace boost 361 362 #if defined(BOOST_BORLANDC) || defined(BOOST_CODEGEARC) 363 # pragma pack(pop) 364 #endif 365 366 #if defined(_MSC_VER) 367 # pragma warning(pop) 368 #endif 369 370 #endif // BOOST_ENDIAN_ARITHMETIC_HPP 371