annotate DEPENDENCIES/generic/include/boost/endian/conversion.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents f46d142149f5
children
rev   line source
Chris@102 1 // boost/endian/conversion.hpp -------------------------------------------------------//
Chris@102 2
Chris@102 3 // Copyright Beman Dawes 2010, 2011, 2014
Chris@102 4
Chris@102 5 // Distributed under the Boost Software License, Version 1.0.
Chris@102 6 // http://www.boost.org/LICENSE_1_0.txt
Chris@102 7
Chris@102 8 #ifndef BOOST_ENDIAN_CONVERSION_HPP
Chris@102 9 #define BOOST_ENDIAN_CONVERSION_HPP
Chris@102 10
Chris@102 11 #include <boost/config.hpp>
Chris@102 12 #include <boost/predef/detail/endian_compat.h>
Chris@102 13 #include <boost/cstdint.hpp>
Chris@102 14 #include <boost/endian/detail/intrinsic.hpp>
Chris@102 15 #include <boost/core/scoped_enum.hpp>
Chris@102 16 #include <boost/static_assert.hpp>
Chris@102 17 #include <algorithm>
Chris@102 18 #include <cstring> // for memcpy
Chris@102 19
Chris@102 20 //------------------------------------- synopsis ---------------------------------------//
Chris@102 21
Chris@102 22 namespace boost
Chris@102 23 {
Chris@102 24 namespace endian
Chris@102 25 {
Chris@102 26 #ifndef BOOST_ENDIAN_ORDER_ENUM_DEFINED
Chris@102 27 BOOST_SCOPED_ENUM_START(order)
Chris@102 28 {
Chris@102 29 big, little,
Chris@102 30 # ifdef BOOST_BIG_ENDIAN
Chris@102 31 native = big
Chris@102 32 # else
Chris@102 33 native = little
Chris@102 34 # endif
Chris@102 35 }; BOOST_SCOPED_ENUM_END
Chris@102 36 # define BOOST_ENDIAN_ORDER_ENUM_DEFINED
Chris@102 37 #endif
Chris@102 38
Chris@102 39 //--------------------------------------------------------------------------------------//
Chris@102 40 // //
Chris@102 41 // return-by-value interfaces //
Chris@102 42 // suggested by Phil Endecott //
Chris@102 43 // //
Chris@102 44 // user-defined types (UDTs) //
Chris@102 45 // //
Chris@102 46 // All return-by-value conversion function templates are required to be implemented in //
Chris@102 47 // terms of an unqualified call to "endian_reverse(x)", a function returning the //
Chris@102 48 // value of x with endianness reversed. This provides a customization point for any //
Chris@102 49 // UDT that provides a "endian_reverse" free-function meeting the requirements. //
Chris@102 50 // It must be defined in the same namespace as the UDT itself so that it will be found //
Chris@102 51 // by argument dependent lookup (ADL). //
Chris@102 52 // //
Chris@102 53 //--------------------------------------------------------------------------------------//
Chris@102 54
Chris@102 55 // customization for exact-length arithmetic types. See doc/conversion.html/#FAQ
Chris@102 56 inline int8_t endian_reverse(int8_t x) BOOST_NOEXCEPT;
Chris@102 57 inline int16_t endian_reverse(int16_t x) BOOST_NOEXCEPT;
Chris@102 58 inline int32_t endian_reverse(int32_t x) BOOST_NOEXCEPT;
Chris@102 59 inline int64_t endian_reverse(int64_t x) BOOST_NOEXCEPT;
Chris@102 60 inline uint8_t endian_reverse(uint8_t x) BOOST_NOEXCEPT;
Chris@102 61 inline uint16_t endian_reverse(uint16_t x) BOOST_NOEXCEPT;
Chris@102 62 inline uint32_t endian_reverse(uint32_t x) BOOST_NOEXCEPT;
Chris@102 63 inline uint64_t endian_reverse(uint64_t x) BOOST_NOEXCEPT;
Chris@102 64
Chris@102 65 // reverse byte order unless native endianness is big
Chris@102 66 template <class EndianReversible >
Chris@102 67 inline EndianReversible big_to_native(EndianReversible x) BOOST_NOEXCEPT;
Chris@102 68 // Returns: x if native endian order is big, otherwise endian_reverse(x)
Chris@102 69 template <class EndianReversible >
Chris@102 70 inline EndianReversible native_to_big(EndianReversible x) BOOST_NOEXCEPT;
Chris@102 71 // Returns: x if native endian order is big, otherwise endian_reverse(x)
Chris@102 72
Chris@102 73 // reverse byte order unless native endianness is little
Chris@102 74 template <class EndianReversible >
Chris@102 75 inline EndianReversible little_to_native(EndianReversible x) BOOST_NOEXCEPT;
Chris@102 76 // Returns: x if native endian order is little, otherwise endian_reverse(x)
Chris@102 77 template <class EndianReversible >
Chris@102 78 inline EndianReversible native_to_little(EndianReversible x) BOOST_NOEXCEPT;
Chris@102 79 // Returns: x if native endian order is little, otherwise endian_reverse(x)
Chris@102 80
Chris@102 81 // generic conditional reverse byte order
Chris@102 82 template <BOOST_SCOPED_ENUM(order) From, BOOST_SCOPED_ENUM(order) To,
Chris@102 83 class EndianReversible>
Chris@102 84 inline EndianReversible conditional_reverse(EndianReversible from) BOOST_NOEXCEPT;
Chris@102 85 // Returns: If From == To have different values, from.
Chris@102 86 // Otherwise endian_reverse(from).
Chris@102 87 // Remarks: The From == To test, and as a consequence which form the return takes, is
Chris@102 88 // is determined at compile time.
Chris@102 89
Chris@102 90 // runtime conditional reverse byte order
Chris@102 91 template <class EndianReversible >
Chris@102 92 inline EndianReversible conditional_reverse(EndianReversible from,
Chris@102 93 BOOST_SCOPED_ENUM(order) from_order, BOOST_SCOPED_ENUM(order) to_order)
Chris@102 94 BOOST_NOEXCEPT;
Chris@102 95 // Returns: from_order == to_order ? from : endian_reverse(from).
Chris@102 96
Chris@102 97 //------------------------------------------------------------------------------------//
Chris@102 98
Chris@102 99
Chris@102 100 // Q: What happended to bswap, htobe, and the other synonym functions based on names
Chris@102 101 // popularized by BSD, OS X, and Linux?
Chris@102 102 // A: Turned out these may be implemented as macros on some systems. Ditto POSIX names
Chris@102 103 // for such functionality. Since macros would cause endless problems with functions
Chris@102 104 // of the same names, and these functions are just synonyms anyhow, they have been
Chris@102 105 // removed.
Chris@102 106
Chris@102 107
Chris@102 108 //------------------------------------------------------------------------------------//
Chris@102 109 // //
Chris@102 110 // reverse in place interfaces //
Chris@102 111 // //
Chris@102 112 // user-defined types (UDTs) //
Chris@102 113 // //
Chris@102 114 // All reverse in place function templates are required to be implemented in terms //
Chris@102 115 // of an unqualified call to "endian_reverse_inplace(x)", a function reversing //
Chris@102 116 // the endianness of x, which is a non-const reference. This provides a //
Chris@102 117 // customization point for any UDT that provides a "reverse_inplace" free-function //
Chris@102 118 // meeting the requirements. The free-function must be declared in the same //
Chris@102 119 // namespace as the UDT itself so that it will be found by argument-dependent //
Chris@102 120 // lookup (ADL). //
Chris@102 121 // //
Chris@102 122 //------------------------------------------------------------------------------------//
Chris@102 123
Chris@102 124 // reverse in place
Chris@102 125 template <class EndianReversible>
Chris@102 126 inline void endian_reverse_inplace(EndianReversible& x) BOOST_NOEXCEPT;
Chris@102 127 // Effects: x = endian_reverse(x)
Chris@102 128
Chris@102 129 // reverse in place unless native endianness is big
Chris@102 130 template <class EndianReversibleInplace>
Chris@102 131 inline void big_to_native_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT;
Chris@102 132 // Effects: none if native byte-order is big, otherwise endian_reverse_inplace(x)
Chris@102 133 template <class EndianReversibleInplace>
Chris@102 134 inline void native_to_big_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT;
Chris@102 135 // Effects: none if native byte-order is big, otherwise endian_reverse_inplace(x)
Chris@102 136
Chris@102 137 // reverse in place unless native endianness is little
Chris@102 138 template <class EndianReversibleInplace>
Chris@102 139 inline void little_to_native_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT;
Chris@102 140 // Effects: none if native byte-order is little, otherwise endian_reverse_inplace(x);
Chris@102 141 template <class EndianReversibleInplace>
Chris@102 142 inline void native_to_little_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT;
Chris@102 143 // Effects: none if native byte-order is little, otherwise endian_reverse_inplace(x);
Chris@102 144
Chris@102 145 // generic conditional reverse in place
Chris@102 146 template <BOOST_SCOPED_ENUM(order) From, BOOST_SCOPED_ENUM(order) To,
Chris@102 147 class EndianReversibleInplace>
Chris@102 148 inline void conditional_reverse_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT;
Chris@102 149
Chris@102 150 // runtime reverse in place
Chris@102 151 template <class EndianReversibleInplace>
Chris@102 152 inline void conditional_reverse_inplace(EndianReversibleInplace& x,
Chris@102 153 BOOST_SCOPED_ENUM(order) from_order, BOOST_SCOPED_ENUM(order) to_order)
Chris@102 154 BOOST_NOEXCEPT;
Chris@102 155
Chris@102 156 //----------------------------------- end synopsis -------------------------------------//
Chris@102 157
Chris@102 158 namespace detail
Chris@102 159 {
Chris@102 160 // generic reverse function template implementation approach using std::reverse
Chris@102 161 // suggested by Mathias Gaunard. Primary motivation for inclusion is to have an
Chris@102 162 // independent implementation to test against.
Chris@102 163
Chris@102 164 template <class T>
Chris@102 165 inline T std_endian_reverse(T x) BOOST_NOEXCEPT
Chris@102 166 {
Chris@102 167 T tmp(x);
Chris@102 168 std::reverse(
Chris@102 169 reinterpret_cast<unsigned char*>(&tmp),
Chris@102 170 reinterpret_cast<unsigned char*>(&tmp) + sizeof(T));
Chris@102 171 return tmp;
Chris@102 172 }
Chris@102 173
Chris@102 174 // conditional unaligned reverse copy, patterned after std::reverse_copy
Chris@102 175 template <class T>
Chris@102 176 inline void big_reverse_copy(T from, char* to) BOOST_NOEXCEPT;
Chris@102 177 template <class T>
Chris@102 178 inline void big_reverse_copy(const char* from, T& to) BOOST_NOEXCEPT;
Chris@102 179 template <class T>
Chris@102 180 inline void little_reverse_copy(T from, char* to) BOOST_NOEXCEPT;
Chris@102 181 template <class T>
Chris@102 182 inline void little_reverse_copy(const char* from, T& to) BOOST_NOEXCEPT;
Chris@102 183 } // namespace detail
Chris@102 184
Chris@102 185 //--------------------------------------------------------------------------------------//
Chris@102 186 // //
Chris@102 187 // return-by-value implementation //
Chris@102 188 // //
Chris@102 189 // -- portable approach suggested by tymofey, with avoidance of undefined behavior //
Chris@102 190 // as suggested by Giovanni Piero Deretta, with a further refinement suggested //
Chris@102 191 // by Pyry Jahkola. //
Chris@102 192 // -- intrinsic approach suggested by reviewers, and by David Stone, who provided //
Chris@102 193 // his Boost licensed macro implementation (detail/intrinsic.hpp) //
Chris@102 194 // //
Chris@102 195 //--------------------------------------------------------------------------------------//
Chris@102 196
Chris@102 197 inline int8_t endian_reverse(int8_t x) BOOST_NOEXCEPT
Chris@102 198 {
Chris@102 199 return x;
Chris@102 200 }
Chris@102 201
Chris@102 202 inline int16_t endian_reverse(int16_t x) BOOST_NOEXCEPT
Chris@102 203 {
Chris@102 204 # ifdef BOOST_ENDIAN_NO_INTRINSICS
Chris@102 205 return (static_cast<uint16_t>(x) << 8)
Chris@102 206 | (static_cast<uint16_t>(x) >> 8);
Chris@102 207 # else
Chris@102 208 return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_2(static_cast<uint16_t>(x));
Chris@102 209 # endif
Chris@102 210 }
Chris@102 211
Chris@102 212 inline int32_t endian_reverse(int32_t x) BOOST_NOEXCEPT
Chris@102 213 {
Chris@102 214 # ifdef BOOST_ENDIAN_NO_INTRINSICS
Chris@102 215 uint32_t step16;
Chris@102 216 step16 = static_cast<uint32_t>(x) << 16 | static_cast<uint32_t>(x) >> 16;
Chris@102 217 return
Chris@102 218 ((static_cast<uint32_t>(step16) << 8) & 0xff00ff00)
Chris@102 219 | ((static_cast<uint32_t>(step16) >> 8) & 0x00ff00ff);
Chris@102 220 # else
Chris@102 221 return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_4(static_cast<uint32_t>(x));
Chris@102 222 # endif
Chris@102 223 }
Chris@102 224
Chris@102 225 inline int64_t endian_reverse(int64_t x) BOOST_NOEXCEPT
Chris@102 226 {
Chris@102 227 # ifdef BOOST_ENDIAN_NO_INTRINSICS
Chris@102 228 uint64_t step32, step16;
Chris@102 229 step32 = static_cast<uint64_t>(x) << 32 | static_cast<uint64_t>(x) >> 32;
Chris@102 230 step16 = (step32 & 0x0000FFFF0000FFFFULL) << 16
Chris@102 231 | (step32 & 0xFFFF0000FFFF0000ULL) >> 16;
Chris@102 232 return static_cast<int64_t>((step16 & 0x00FF00FF00FF00FFULL) << 8
Chris@102 233 | (step16 & 0xFF00FF00FF00FF00ULL) >> 8);
Chris@102 234 # else
Chris@102 235 return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_8(static_cast<uint64_t>(x));
Chris@102 236 # endif
Chris@102 237 }
Chris@102 238
Chris@102 239 inline uint8_t endian_reverse(uint8_t x) BOOST_NOEXCEPT
Chris@102 240 {
Chris@102 241 return x;
Chris@102 242 }
Chris@102 243
Chris@102 244 inline uint16_t endian_reverse(uint16_t x) BOOST_NOEXCEPT
Chris@102 245 {
Chris@102 246 # ifdef BOOST_ENDIAN_NO_INTRINSICS
Chris@102 247 return (x << 8)
Chris@102 248 | (x >> 8);
Chris@102 249 # else
Chris@102 250 return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_2(x);
Chris@102 251 # endif
Chris@102 252 }
Chris@102 253
Chris@102 254 inline uint32_t endian_reverse(uint32_t x) BOOST_NOEXCEPT
Chris@102 255 {
Chris@102 256 # ifdef BOOST_ENDIAN_NO_INTRINSICS
Chris@102 257 uint32_t step16;
Chris@102 258 step16 = x << 16 | x >> 16;
Chris@102 259 return
Chris@102 260 ((step16 << 8) & 0xff00ff00)
Chris@102 261 | ((step16 >> 8) & 0x00ff00ff);
Chris@102 262 # else
Chris@102 263 return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_4(x);
Chris@102 264 # endif
Chris@102 265 }
Chris@102 266
Chris@102 267 inline uint64_t endian_reverse(uint64_t x) BOOST_NOEXCEPT
Chris@102 268 {
Chris@102 269 # ifdef BOOST_ENDIAN_NO_INTRINSICS
Chris@102 270 uint64_t step32, step16;
Chris@102 271 step32 = x << 32 | x >> 32;
Chris@102 272 step16 = (step32 & 0x0000FFFF0000FFFFULL) << 16
Chris@102 273 | (step32 & 0xFFFF0000FFFF0000ULL) >> 16;
Chris@102 274 return (step16 & 0x00FF00FF00FF00FFULL) << 8
Chris@102 275 | (step16 & 0xFF00FF00FF00FF00ULL) >> 8;
Chris@102 276 # else
Chris@102 277 return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_8(x);
Chris@102 278 # endif
Chris@102 279 }
Chris@102 280
Chris@102 281 template <class EndianReversible >
Chris@102 282 inline EndianReversible big_to_native(EndianReversible x) BOOST_NOEXCEPT
Chris@102 283 {
Chris@102 284 # ifdef BOOST_BIG_ENDIAN
Chris@102 285 return x;
Chris@102 286 # else
Chris@102 287 return endian_reverse(x);
Chris@102 288 # endif
Chris@102 289 }
Chris@102 290
Chris@102 291 template <class EndianReversible >
Chris@102 292 inline EndianReversible native_to_big(EndianReversible x) BOOST_NOEXCEPT
Chris@102 293 {
Chris@102 294 # ifdef BOOST_BIG_ENDIAN
Chris@102 295 return x;
Chris@102 296 # else
Chris@102 297 return endian_reverse(x);
Chris@102 298 # endif
Chris@102 299 }
Chris@102 300
Chris@102 301 template <class EndianReversible >
Chris@102 302 inline EndianReversible little_to_native(EndianReversible x) BOOST_NOEXCEPT
Chris@102 303 {
Chris@102 304 # ifdef BOOST_LITTLE_ENDIAN
Chris@102 305 return x;
Chris@102 306 # else
Chris@102 307 return endian_reverse(x);
Chris@102 308 # endif
Chris@102 309 }
Chris@102 310
Chris@102 311 template <class EndianReversible >
Chris@102 312 inline EndianReversible native_to_little(EndianReversible x) BOOST_NOEXCEPT
Chris@102 313 {
Chris@102 314 # ifdef BOOST_LITTLE_ENDIAN
Chris@102 315 return x;
Chris@102 316 # else
Chris@102 317 return endian_reverse(x);
Chris@102 318 # endif
Chris@102 319 }
Chris@102 320
Chris@102 321 namespace detail
Chris@102 322 {
Chris@102 323 // Primary template and specializations to support endian_reverse().
Chris@102 324 // See rationale in endian_reverse() below.
Chris@102 325 template <BOOST_SCOPED_ENUM(order) From, BOOST_SCOPED_ENUM(order) To,
Chris@102 326 class EndianReversible>
Chris@102 327 class value_converter ; // primary template
Chris@102 328 template <class T> class value_converter <order::big, order::big, T>
Chris@102 329 {public: T operator()(T x) BOOST_NOEXCEPT {return x;}};
Chris@102 330 template <class T> class value_converter <order::little, order::little, T>
Chris@102 331 {public: T operator()(T x) BOOST_NOEXCEPT {return x;}};
Chris@102 332 template <class T> class value_converter <order::big, order::little, T>
Chris@102 333 {public: T operator()(T x) BOOST_NOEXCEPT {return endian_reverse(x);}};
Chris@102 334 template <class T> class value_converter <order::little, order::big, T>
Chris@102 335 {public: T operator()(T x) BOOST_NOEXCEPT {return endian_reverse(x);}};
Chris@102 336 }
Chris@102 337
Chris@102 338 // generic conditional reverse
Chris@102 339 template <BOOST_SCOPED_ENUM(order) From, BOOST_SCOPED_ENUM(order) To,
Chris@102 340 class EndianReversible>
Chris@102 341 inline EndianReversible conditional_reverse(EndianReversible from) BOOST_NOEXCEPT {
Chris@102 342 // work around lack of function template partial specialization by instantiating
Chris@102 343 // a function object of a class that is partially specialized on the two order
Chris@102 344 // template parameters, and then calling its operator().
Chris@102 345 detail::value_converter <From, To, EndianReversible> tmp;
Chris@102 346 return tmp(from);
Chris@102 347 }
Chris@102 348
Chris@102 349 // runtime conditional reverse
Chris@102 350 template <class EndianReversible >
Chris@102 351 inline EndianReversible conditional_reverse(EndianReversible from,
Chris@102 352 BOOST_SCOPED_ENUM(order) from_order, BOOST_SCOPED_ENUM(order) to_order) BOOST_NOEXCEPT
Chris@102 353 {
Chris@102 354 return from_order == to_order ? from : endian_reverse(from);
Chris@102 355 }
Chris@102 356
Chris@102 357 //--------------------------------------------------------------------------------------//
Chris@102 358 // reverse-in-place implementation //
Chris@102 359 //--------------------------------------------------------------------------------------//
Chris@102 360
Chris@102 361 // reverse in place
Chris@102 362 template <class EndianReversible>
Chris@102 363 inline void endian_reverse_inplace(EndianReversible& x) BOOST_NOEXCEPT
Chris@102 364 {
Chris@102 365 x = endian_reverse(x);
Chris@102 366 }
Chris@102 367
Chris@102 368 template <class EndianReversibleInplace>
Chris@102 369 # ifdef BOOST_BIG_ENDIAN
Chris@102 370 inline void big_to_native_inplace(EndianReversibleInplace&) BOOST_NOEXCEPT {}
Chris@102 371 # else
Chris@102 372 inline void big_to_native_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT
Chris@102 373 { endian_reverse_inplace(x); }
Chris@102 374 # endif
Chris@102 375 template <class EndianReversibleInplace>
Chris@102 376 # ifdef BOOST_BIG_ENDIAN
Chris@102 377 inline void native_to_big_inplace(EndianReversibleInplace&) BOOST_NOEXCEPT {}
Chris@102 378 # else
Chris@102 379 inline void native_to_big_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT
Chris@102 380 {
Chris@102 381 endian_reverse_inplace(x);
Chris@102 382 }
Chris@102 383 # endif
Chris@102 384
Chris@102 385 template <class EndianReversibleInplace>
Chris@102 386 # ifdef BOOST_LITTLE_ENDIAN
Chris@102 387 inline void little_to_native_inplace(EndianReversibleInplace&) BOOST_NOEXCEPT {}
Chris@102 388 # else
Chris@102 389 inline void little_to_native_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT
Chris@102 390 { endian_reverse_inplace(x); }
Chris@102 391 # endif
Chris@102 392 template <class EndianReversibleInplace>
Chris@102 393 # ifdef BOOST_LITTLE_ENDIAN
Chris@102 394 inline void native_to_little_inplace(EndianReversibleInplace&) BOOST_NOEXCEPT {}
Chris@102 395 # else
Chris@102 396 inline void native_to_little_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT
Chris@102 397 {
Chris@102 398 endian_reverse_inplace(x);
Chris@102 399 }
Chris@102 400 # endif
Chris@102 401
Chris@102 402 namespace detail
Chris@102 403 {
Chris@102 404 // Primary template and specializations support generic
Chris@102 405 // endian_reverse_inplace().
Chris@102 406 // See rationale in endian_reverse_inplace() below.
Chris@102 407 template <BOOST_SCOPED_ENUM(order) From, BOOST_SCOPED_ENUM(order) To,
Chris@102 408 class EndianReversibleInplace>
Chris@102 409 class converter; // primary template
Chris@102 410 template <class T> class converter<order::big, order::big, T>
Chris@102 411 {public: void operator()(T&) BOOST_NOEXCEPT {/*no effect*/}};
Chris@102 412 template <class T> class converter<order::little, order::little, T>
Chris@102 413 {public: void operator()(T&) BOOST_NOEXCEPT {/*no effect*/}};
Chris@102 414 template <class T> class converter<order::big, order::little, T>
Chris@102 415 {public: void operator()(T& x) BOOST_NOEXCEPT { endian_reverse_inplace(x); }};
Chris@102 416 template <class T> class converter<order::little, order::big, T>
Chris@102 417 {public: void operator()(T& x) BOOST_NOEXCEPT { endian_reverse_inplace(x); }};
Chris@102 418 } // namespace detail
Chris@102 419
Chris@102 420 // generic conditional reverse in place
Chris@102 421 template <BOOST_SCOPED_ENUM(order) From, BOOST_SCOPED_ENUM(order) To,
Chris@102 422 class EndianReversibleInplace>
Chris@102 423 inline void conditional_reverse_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT
Chris@102 424 {
Chris@102 425 // work around lack of function template partial specialization by instantiating
Chris@102 426 // a function object of a class that is partially specialized on the two order
Chris@102 427 // template parameters, and then calling its operator().
Chris@102 428 detail::converter<From, To, EndianReversibleInplace> tmp;
Chris@102 429 tmp(x); // call operator ()
Chris@102 430 }
Chris@102 431
Chris@102 432 // runtime reverse in place
Chris@102 433 template <class EndianReversibleInplace>
Chris@102 434 inline void conditional_reverse_inplace(EndianReversibleInplace& x,
Chris@102 435 BOOST_SCOPED_ENUM(order) from_order, BOOST_SCOPED_ENUM(order) to_order)
Chris@102 436 BOOST_NOEXCEPT
Chris@102 437 {
Chris@102 438 if (from_order != to_order)
Chris@102 439 endian_reverse_inplace(x);
Chris@102 440 }
Chris@102 441
Chris@102 442
Chris@102 443 namespace detail
Chris@102 444 {
Chris@102 445 template <class T>
Chris@102 446 inline void big_reverse_copy(T from, char* to) BOOST_NOEXCEPT
Chris@102 447 {
Chris@102 448 # ifdef BOOST_BIG_ENDIAN
Chris@102 449 std::memcpy(to, reinterpret_cast<const char*>(&from), sizeof(T));
Chris@102 450 # else
Chris@102 451 std::reverse_copy(reinterpret_cast<const char*>(&from),
Chris@102 452 reinterpret_cast<const char*>(&from) + sizeof(T), to);
Chris@102 453 # endif
Chris@102 454 }
Chris@102 455 template <class T>
Chris@102 456 inline void big_reverse_copy(const char* from, T& to) BOOST_NOEXCEPT
Chris@102 457 {
Chris@102 458 # ifdef BOOST_BIG_ENDIAN
Chris@102 459 std::memcpy(reinterpret_cast<char*>(&to), from, sizeof(T));
Chris@102 460 # else
Chris@102 461 std::reverse_copy(from, from + sizeof(T), reinterpret_cast<char*>(&to));
Chris@102 462 # endif
Chris@102 463 }
Chris@102 464 template <class T>
Chris@102 465 inline void little_reverse_copy(T from, char* to) BOOST_NOEXCEPT
Chris@102 466 {
Chris@102 467 # ifdef BOOST_LITTLE_ENDIAN
Chris@102 468 std::memcpy(to, reinterpret_cast<const char*>(&from), sizeof(T));
Chris@102 469 # else
Chris@102 470 std::reverse_copy(reinterpret_cast<const char*>(&from),
Chris@102 471 reinterpret_cast<const char*>(&from) + sizeof(T), to);
Chris@102 472 # endif
Chris@102 473 }
Chris@102 474 template <class T>
Chris@102 475 inline void little_reverse_copy(const char* from, T& to) BOOST_NOEXCEPT
Chris@102 476 {
Chris@102 477 # ifdef BOOST_LITTLE_ENDIAN
Chris@102 478 std::memcpy(reinterpret_cast<char*>(&to), from, sizeof(T));
Chris@102 479 # else
Chris@102 480 std::reverse_copy(from, from + sizeof(T), reinterpret_cast<char*>(&to));
Chris@102 481 # endif
Chris@102 482 }
Chris@102 483 } // namespace detail
Chris@102 484 } // namespace endian
Chris@102 485 } // namespace boost
Chris@102 486
Chris@102 487 #endif // BOOST_ENDIAN_CONVERSION_HPP