1 // boost/endian/arithmetic.hpp -------------------------------------------------------// 2 3 // (C) Copyright Darin Adler 2000 4 // (C) Copyright Beman Dawes 2006, 2009, 2014 5 6 // Distributed under the Boost Software License, Version 1.0. 7 // See http://www.boost.org/LICENSE_1_0.txt 8 9 // See library home page at http://www.boost.org/libs/endian 10 11 //--------------------------------------------------------------------------------------// 12 13 // Original design developed by Darin Adler based on classes developed by Mark 14 // Borgerding. Four original class templates were combined into a single endian 15 // class template by Beman Dawes, who also added the unrolled_byte_loops sign 16 // partial specialization to correctly extend the sign when cover integer size 17 // differs from endian representation size. 18 19 // TODO: When a compiler supporting constexpr becomes available, try possible uses. 20 21 #ifndef BOOST_ENDIAN_ARITHMETIC_HPP 22 #define BOOST_ENDIAN_ARITHMETIC_HPP 23 24 #if defined(_MSC_VER) 25 # pragma warning(push) 26 # pragma warning(disable:4365) // conversion ... signed/unsigned mismatch 27 #endif 28 29 #ifdef BOOST_ENDIAN_LOG 30 # include <iostream> 31 #endif 32 33 #if defined(__BORLANDC__) || defined( __CODEGEARC__) 34 # pragma pack(push, 1) 35 #endif 36 37 #include <boost/config.hpp> 38 #include <boost/predef/detail/endian_compat.h> 39 #include <boost/endian/conversion.hpp> 40 #include <boost/endian/buffers.hpp> 41 #define BOOST_ENDIAN_MINIMAL_COVER_OPERATORS 42 #include <boost/endian/detail/cover_operators.hpp> 43 #undef BOOST_ENDIAN_MINIMAL_COVER_OPERATORS 44 #include <boost/type_traits/is_signed.hpp> 45 #include <boost/cstdint.hpp> 46 #include <boost/static_assert.hpp> 47 #include <boost/core/scoped_enum.hpp> 48 #include <iosfwd> 49 #include <climits> 50 51 # if CHAR_BIT != 8 52 # error Platforms with CHAR_BIT != 8 are not supported 53 # endif 54 55 # ifdef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS 56 # define BOOST_ENDIAN_DEFAULT_CONSTRUCT {} // C++03 57 # else 58 # define BOOST_ENDIAN_DEFAULT_CONSTRUCT = default; // C++0x 59 # endif 60 61 # if defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) && defined(BOOST_ENDIAN_FORCE_PODNESS) 62 # define BOOST_ENDIAN_NO_CTORS 63 # endif 64 65 # ifndef BOOST_ENDIAN_EXPLICIT_CTORS 66 # define BOOST_ENDIAN_EXPLICIT_OPT 67 # else 68 # define BOOST_ENDIAN_EXPLICIT_OPT explicit 69 # endif 70 71 //---------------------------------- synopsis ----------------------------------------// 72 73 namespace boost 74 { 75 namespace endian 76 { 77 78 template <BOOST_SCOPED_ENUM(order) Order, class T, std::size_t n_bits, 79 BOOST_SCOPED_ENUM(align) A = align::no> 80 class endian_arithmetic; 81 82 // big endian signed integer aligned types 83 typedef endian_arithmetic<order::big, int8_t, 8, align::yes> big_int8_at; 84 typedef endian_arithmetic<order::big, int16_t, 16, align::yes> big_int16_at; 85 typedef endian_arithmetic<order::big, int32_t, 32, align::yes> big_int32_at; 86 typedef endian_arithmetic<order::big, int64_t, 64, align::yes> big_int64_at; 87 88 // big endian unsigned integer aligned types 89 typedef endian_arithmetic<order::big, uint8_t, 8, align::yes> big_uint8_at; 90 typedef endian_arithmetic<order::big, uint16_t, 16, align::yes> big_uint16_at; 91 typedef endian_arithmetic<order::big, uint32_t, 32, align::yes> big_uint32_at; 92 typedef endian_arithmetic<order::big, uint64_t, 64, align::yes> big_uint64_at; 93 94 // little endian signed integer aligned types 95 typedef endian_arithmetic<order::little, int8_t, 8, align::yes> little_int8_at; 96 typedef endian_arithmetic<order::little, int16_t, 16, align::yes> little_int16_at; 97 typedef endian_arithmetic<order::little, int32_t, 32, align::yes> little_int32_at; 98 typedef endian_arithmetic<order::little, int64_t, 64, align::yes> little_int64_at; 99 100 // little endian unsigned integer aligned types 101 typedef endian_arithmetic<order::little, uint8_t, 8, align::yes> little_uint8_at; 102 typedef endian_arithmetic<order::little, uint16_t, 16, align::yes> little_uint16_at; 103 typedef endian_arithmetic<order::little, uint32_t, 32, align::yes> little_uint32_at; 104 typedef endian_arithmetic<order::little, uint64_t, 64, align::yes> little_uint64_at; 105 106 // aligned native endian typedefs are not provided because 107 // <cstdint> types are superior for this use case 108 109 // big endian signed integer unaligned types 110 typedef endian_arithmetic<order::big, int_least8_t, 8> big_int8_t; 111 typedef endian_arithmetic<order::big, int_least16_t, 16> big_int16_t; 112 typedef endian_arithmetic<order::big, int_least32_t, 24> big_int24_t; 113 typedef endian_arithmetic<order::big, int_least32_t, 32> big_int32_t; 114 typedef endian_arithmetic<order::big, int_least64_t, 40> big_int40_t; 115 typedef endian_arithmetic<order::big, int_least64_t, 48> big_int48_t; 116 typedef endian_arithmetic<order::big, int_least64_t, 56> big_int56_t; 117 typedef endian_arithmetic<order::big, int_least64_t, 64> big_int64_t; 118 119 // big endian unsigned integer unaligned types 120 typedef endian_arithmetic<order::big, uint_least8_t, 8> big_uint8_t; 121 typedef endian_arithmetic<order::big, uint_least16_t, 16> big_uint16_t; 122 typedef endian_arithmetic<order::big, uint_least32_t, 24> big_uint24_t; 123 typedef endian_arithmetic<order::big, uint_least32_t, 32> big_uint32_t; 124 typedef endian_arithmetic<order::big, uint_least64_t, 40> big_uint40_t; 125 typedef endian_arithmetic<order::big, uint_least64_t, 48> big_uint48_t; 126 typedef endian_arithmetic<order::big, uint_least64_t, 56> big_uint56_t; 127 typedef endian_arithmetic<order::big, uint_least64_t, 64> big_uint64_t; 128 129 // little endian signed integer unaligned types 130 typedef endian_arithmetic<order::little, int_least8_t, 8> little_int8_t; 131 typedef endian_arithmetic<order::little, int_least16_t, 16> little_int16_t; 132 typedef endian_arithmetic<order::little, int_least32_t, 24> little_int24_t; 133 typedef endian_arithmetic<order::little, int_least32_t, 32> little_int32_t; 134 typedef endian_arithmetic<order::little, int_least64_t, 40> little_int40_t; 135 typedef endian_arithmetic<order::little, int_least64_t, 48> little_int48_t; 136 typedef endian_arithmetic<order::little, int_least64_t, 56> little_int56_t; 137 typedef endian_arithmetic<order::little, int_least64_t, 64> little_int64_t; 138 139 // little endian unsigned integer unaligned types 140 typedef endian_arithmetic<order::little, uint_least8_t, 8> little_uint8_t; 141 typedef endian_arithmetic<order::little, uint_least16_t, 16> little_uint16_t; 142 typedef endian_arithmetic<order::little, uint_least32_t, 24> little_uint24_t; 143 typedef endian_arithmetic<order::little, uint_least32_t, 32> little_uint32_t; 144 typedef endian_arithmetic<order::little, uint_least64_t, 40> little_uint40_t; 145 typedef endian_arithmetic<order::little, uint_least64_t, 48> little_uint48_t; 146 typedef endian_arithmetic<order::little, uint_least64_t, 56> little_uint56_t; 147 typedef endian_arithmetic<order::little, uint_least64_t, 64> little_uint64_t; 148 149 # ifdef BOOST_BIG_ENDIAN 150 // native endian signed integer unaligned types 151 typedef big_int8_t native_int8_t; 152 typedef big_int16_t native_int16_t; 153 typedef big_int24_t native_int24_t; 154 typedef big_int32_t native_int32_t; 155 typedef big_int40_t native_int40_t; 156 typedef big_int48_t native_int48_t; 157 typedef big_int56_t native_int56_t; 158 typedef big_int64_t native_int64_t; 159 160 // native endian unsigned integer unaligned types 161 typedef big_uint8_t native_uint8_t; 162 typedef big_uint16_t native_uint16_t; 163 typedef big_uint24_t native_uint24_t; 164 typedef big_uint32_t native_uint32_t; 165 typedef big_uint40_t native_uint40_t; 166 typedef big_uint48_t native_uint48_t; 167 typedef big_uint56_t native_uint56_t; 168 typedef big_uint64_t native_uint64_t; 169 # else 170 // native endian signed integer unaligned types 171 typedef little_int8_t native_int8_t; 172 typedef little_int16_t native_int16_t; 173 typedef little_int24_t native_int24_t; 174 typedef little_int32_t native_int32_t; 175 typedef little_int40_t native_int40_t; 176 typedef little_int48_t native_int48_t; 177 typedef little_int56_t native_int56_t; 178 typedef little_int64_t native_int64_t; 179 180 // native endian unsigned integer unaligned types 181 typedef little_uint8_t native_uint8_t; 182 typedef little_uint16_t native_uint16_t; 183 typedef little_uint24_t native_uint24_t; 184 typedef little_uint32_t native_uint32_t; 185 typedef little_uint40_t native_uint40_t; 186 typedef little_uint48_t native_uint48_t; 187 typedef little_uint56_t native_uint56_t; 188 typedef little_uint64_t native_uint64_t; 189 # endif 190 191 # ifdef BOOST_ENDIAN_DEPRECATED_NAMES 192 193 typedef order endianness; 194 typedef align alignment; 195 196 # ifndef BOOST_NO_CXX11_TEMPLATE_ALIASES 197 template <BOOST_SCOPED_ENUM(order) Order, class T, std::size_t n_bits, 198 BOOST_SCOPED_ENUM(align) Align = align::no> 199 using endian = endian_arithmetic<Order, T, n_bits, Align>; 200 # endif 201 202 // unaligned big endian signed integer types 203 typedef endian_arithmetic< order::big, int_least8_t, 8 > big8_t; 204 typedef endian_arithmetic< order::big, int_least16_t, 16 > big16_t; 205 typedef endian_arithmetic< order::big, int_least32_t, 24 > big24_t; 206 typedef endian_arithmetic< order::big, int_least32_t, 32 > big32_t; 207 typedef endian_arithmetic< order::big, int_least64_t, 40 > big40_t; 208 typedef endian_arithmetic< order::big, int_least64_t, 48 > big48_t; 209 typedef endian_arithmetic< order::big, int_least64_t, 56 > big56_t; 210 typedef endian_arithmetic< order::big, int_least64_t, 64 > big64_t; 211 212 // unaligned big endian_arithmetic unsigned integer types 213 typedef endian_arithmetic< order::big, uint_least8_t, 8 > ubig8_t; 214 typedef endian_arithmetic< order::big, uint_least16_t, 16 > ubig16_t; 215 typedef endian_arithmetic< order::big, uint_least32_t, 24 > ubig24_t; 216 typedef endian_arithmetic< order::big, uint_least32_t, 32 > ubig32_t; 217 typedef endian_arithmetic< order::big, uint_least64_t, 40 > ubig40_t; 218 typedef endian_arithmetic< order::big, uint_least64_t, 48 > ubig48_t; 219 typedef endian_arithmetic< order::big, uint_least64_t, 56 > ubig56_t; 220 typedef endian_arithmetic< order::big, uint_least64_t, 64 > ubig64_t; 221 222 // unaligned little endian_arithmetic signed integer types 223 typedef endian_arithmetic< order::little, int_least8_t, 8 > little8_t; 224 typedef endian_arithmetic< order::little, int_least16_t, 16 > little16_t; 225 typedef endian_arithmetic< order::little, int_least32_t, 24 > little24_t; 226 typedef endian_arithmetic< order::little, int_least32_t, 32 > little32_t; 227 typedef endian_arithmetic< order::little, int_least64_t, 40 > little40_t; 228 typedef endian_arithmetic< order::little, int_least64_t, 48 > little48_t; 229 typedef endian_arithmetic< order::little, int_least64_t, 56 > little56_t; 230 typedef endian_arithmetic< order::little, int_least64_t, 64 > little64_t; 231 232 // unaligned little endian_arithmetic unsigned integer types 233 typedef endian_arithmetic< order::little, uint_least8_t, 8 > ulittle8_t; 234 typedef endian_arithmetic< order::little, uint_least16_t, 16 > ulittle16_t; 235 typedef endian_arithmetic< order::little, uint_least32_t, 24 > ulittle24_t; 236 typedef endian_arithmetic< order::little, uint_least32_t, 32 > ulittle32_t; 237 typedef endian_arithmetic< order::little, uint_least64_t, 40 > ulittle40_t; 238 typedef endian_arithmetic< order::little, uint_least64_t, 48 > ulittle48_t; 239 typedef endian_arithmetic< order::little, uint_least64_t, 56 > ulittle56_t; 240 typedef endian_arithmetic< order::little, uint_least64_t, 64 > ulittle64_t; 241 242 // unaligned native endian_arithmetic signed integer types 243 typedef endian_arithmetic< order::native, int_least8_t, 8 > native8_t; 244 typedef endian_arithmetic< order::native, int_least16_t, 16 > native16_t; 245 typedef endian_arithmetic< order::native, int_least32_t, 24 > native24_t; 246 typedef endian_arithmetic< order::native, int_least32_t, 32 > native32_t; 247 typedef endian_arithmetic< order::native, int_least64_t, 40 > native40_t; 248 typedef endian_arithmetic< order::native, int_least64_t, 48 > native48_t; 249 typedef endian_arithmetic< order::native, int_least64_t, 56 > native56_t; 250 typedef endian_arithmetic< order::native, int_least64_t, 64 > native64_t; 251 252 // unaligned native endian_arithmetic unsigned integer types 253 typedef endian_arithmetic< order::native, uint_least8_t, 8 > unative8_t; 254 typedef endian_arithmetic< order::native, uint_least16_t, 16 > unative16_t; 255 typedef endian_arithmetic< order::native, uint_least32_t, 24 > unative24_t; 256 typedef endian_arithmetic< order::native, uint_least32_t, 32 > unative32_t; 257 typedef endian_arithmetic< order::native, uint_least64_t, 40 > unative40_t; 258 typedef endian_arithmetic< order::native, uint_least64_t, 48 > unative48_t; 259 typedef endian_arithmetic< order::native, uint_least64_t, 56 > unative56_t; 260 typedef endian_arithmetic< order::native, uint_least64_t, 64 > unative64_t; 261 262 // aligned native endian_arithmetic typedefs are not provided because 263 // <cstdint> types are superior for this use case 264 265 typedef endian_arithmetic< order::big, int16_t, 16, align::yes > aligned_big16_t; 266 typedef endian_arithmetic< order::big, uint16_t, 16, align::yes > aligned_ubig16_t; 267 typedef endian_arithmetic< order::little, int16_t, 16, align::yes > aligned_little16_t; 268 typedef endian_arithmetic< order::little, uint16_t, 16, align::yes > aligned_ulittle16_t; 269 270 typedef endian_arithmetic< order::big, int32_t, 32, align::yes > aligned_big32_t; 271 typedef endian_arithmetic< order::big, uint32_t, 32, align::yes > aligned_ubig32_t; 272 typedef endian_arithmetic< order::little, int32_t, 32, align::yes > aligned_little32_t; 273 typedef endian_arithmetic< order::little, uint32_t, 32, align::yes > aligned_ulittle32_t; 274 275 typedef endian_arithmetic< order::big, int64_t, 64, align::yes > aligned_big64_t; 276 typedef endian_arithmetic< order::big, uint64_t, 64, align::yes > aligned_ubig64_t; 277 typedef endian_arithmetic< order::little, int64_t, 64, align::yes > aligned_little64_t; 278 typedef endian_arithmetic< order::little, uint64_t, 64, align::yes > aligned_ulittle64_t; 279 280 # endif 281 282 //---------------------------------- end synopsis ------------------------------------// 283 284 // endian class template specializations ---------------------------------------------// 285 286 // Specializations that represent unaligned bytes. 287 // Taking an integer type as a parameter provides a nice way to pass both 288 // the size and signness of the desired integer and get the appropriate 289 // corresponding integer type for the interface. 290 291 // unaligned integer big endian specialization 292 template <typename T, std::size_t n_bits> 293 class endian_arithmetic< order::big, T, n_bits, align::no > 294 : public endian_buffer< order::big, T, n_bits, align::no >, 295 cover_operators<endian_arithmetic<order::big, T, n_bits>, T> 296 { 297 BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits ); 298 public: 299 typedef T value_type; 300 # ifndef BOOST_ENDIAN_NO_CTORS endian_arithmetic()301 endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT 302 BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT 303 { 304 # ifdef BOOST_ENDIAN_LOG 305 if ( endian_log ) 306 std::cout << "big, unaligned, " << n_bits << "-bits, construct(" << val << ")\n"; 307 # endif 308 detail::store_big_endian<T, n_bits/8>(this->m_value, val); 309 } 310 # endif operator =(T val)311 endian_arithmetic& operator=(T val) BOOST_NOEXCEPT 312 { detail::store_big_endian<T, n_bits/8>(this->m_value, val); return *this; } operator value_type() const313 operator value_type() const BOOST_NOEXCEPT { return this->value(); } 314 }; 315 316 // unaligned little endian specialization 317 template <typename T, std::size_t n_bits> 318 class endian_arithmetic< order::little, T, n_bits, align::no > 319 : public endian_buffer< order::little, T, n_bits, align::no >, 320 cover_operators< endian_arithmetic< order::little, T, n_bits >, T > 321 { 322 BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits ); 323 public: 324 typedef T value_type; 325 # ifndef BOOST_ENDIAN_NO_CTORS endian_arithmetic()326 endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT 327 BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT 328 { 329 # ifdef BOOST_ENDIAN_LOG 330 if ( endian_log ) 331 std::cout << "little, unaligned, " << n_bits << "-bits, construct(" << val << ")\n"; 332 # endif 333 detail::store_little_endian<T, n_bits/8>(this->m_value, val); 334 } 335 # endif operator =(T val)336 endian_arithmetic& operator=(T val) BOOST_NOEXCEPT 337 { detail::store_little_endian<T, n_bits/8>(this->m_value, val); return *this; } operator value_type() const338 operator value_type() const BOOST_NOEXCEPT { return this->value(); } 339 }; 340 341 // align::yes specializations; only n_bits == 16/32/64 supported 342 343 // aligned big endian specialization 344 template <typename T, std::size_t n_bits> 345 class endian_arithmetic<order::big, T, n_bits, align::yes> 346 : public endian_buffer< order::big, T, n_bits, align::yes >, 347 cover_operators<endian_arithmetic<order::big, T, n_bits, align::yes>, T> 348 { 349 BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits ); 350 BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 ); 351 public: 352 typedef T value_type; 353 # ifndef BOOST_ENDIAN_NO_CTORS endian_arithmetic()354 endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT 355 BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT 356 { 357 # ifdef BOOST_ENDIAN_LOG 358 if ( endian_log ) 359 std::cout << "big, aligned, " << n_bits << "-bits, construct(" << val << ")\n"; 360 # endif 361 this->m_value = ::boost::endian::native_to_big(val); 362 } 363 364 # endif operator =(T val)365 endian_arithmetic& operator=(T val) BOOST_NOEXCEPT 366 { 367 this->m_value = ::boost::endian::native_to_big(val); 368 return *this; 369 } operator value_type() const370 operator value_type() const BOOST_NOEXCEPT { return this->value(); } 371 }; 372 373 // aligned little endian specialization 374 template <typename T, std::size_t n_bits> 375 class endian_arithmetic<order::little, T, n_bits, align::yes> 376 : public endian_buffer< order::little, T, n_bits, align::yes >, 377 cover_operators<endian_arithmetic<order::little, T, n_bits, align::yes>, T> 378 { 379 BOOST_STATIC_ASSERT( (n_bits/8)*8 == n_bits ); 380 BOOST_STATIC_ASSERT( sizeof(T) == n_bits/8 ); 381 public: 382 typedef T value_type; 383 # ifndef BOOST_ENDIAN_NO_CTORS endian_arithmetic()384 endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT 385 BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT 386 { 387 # ifdef BOOST_ENDIAN_LOG 388 if ( endian_log ) 389 std::cout << "little, aligned, " << n_bits << "-bits, construct(" << val << ")\n"; 390 # endif 391 this->m_value = ::boost::endian::native_to_little(val); 392 } 393 # endif operator =(T val)394 endian_arithmetic& operator=(T val) BOOST_NOEXCEPT 395 { 396 this->m_value = ::boost::endian::native_to_little(val); 397 return *this; 398 } operator value_type() const399 operator value_type() const BOOST_NOEXCEPT { return this->value(); } 400 }; 401 402 } // namespace endian 403 } // namespace boost 404 405 #if defined(__BORLANDC__) || defined( __CODEGEARC__) 406 # pragma pack(pop) 407 #endif 408 409 #if defined(_MSC_VER) 410 # pragma warning(pop) 411 #endif 412 413 #endif // BOOST_ENDIAN_ARITHMETIC_HPP 414