boost.png (6897 bytes) Endian Conversion Functions
Boost Home     Endian Home     Conversion Functions     Arithmetic Types     Buffer Types

Contents
Introduction
Reference
    Synopsis
    Requirements
      Reversible
      Customization for UDTs
Functions
FAQ
Acknowledgements
Headers
<boost/endian/conversion.hpp>
<boost/endian/buffers.hpp>
<boost/endian/arithmetic.hpp>

Introduction

Header boost/endian/conversion.hpp provides byte order reversal and conversion functions that convert objects of the built-in integer types, and also types float and double, between native, big, or little endian byte ordering. User defined types are also supported.

Reference

Functions are implemented inline if appropriate. noexcept is elided for compilers that do not support it. Boost scoped enum emulation is used so that the library still works for compilers that do not support scoped enums.

Header <boost/endian/conversion.hpp> Synopsis

#define BOOST_ENDIAN_INTRINSIC_MSG "message describing presence or absence of intrinsics"

namespace boost
{
namespace endian
{
  enum class order
  {
    big,                             // big-endian
    little,                          // little-endian
    native = implementation-defined  // same as order::big or order::little
  };

  // reverse byte order (i.e. endianness)
  int8_t   reverse_endianness(int8_t x) noexcept;
  int16_t  reverse_endianness(int16_t x) noexcept;
  int32_t  reverse_endianness(int32_t x) noexcept;
  int64_t  reverse_endianness(int64_t x) noexcept;
  uint8_t  reverse_endianness(uint8_t x) noexcept;
  uint16_t reverse_endianness(uint16_t x) noexcept;
  uint32_t reverse_endianness(uint32_t x) noexcept;
  uint64_t reverse_endianness(uint64_t x) noexcept;
  float    reverse_endianness(float x) noexcept;
  double   reverse_endianness(double x) noexcept;

  template <class Value>
  void     reverse(Value& x) noexcept;

  // reverse byte order unless native endianness is big
  template <class ReversibleValue >
    ReversibleValue big_endian_value(ReversibleValue x) noexcept; 
  template <class Reversible>
    void big_endian(Reversible& x) noexcept; 

  // reverse byte order unless native endianness is little
  template <class ReversibleValue >
    ReversibleValue little_endian_value(ReversibleValue x) noexcept; 
  template <class Reversible>
    void little_endian(Reversible& x) noexcept; 

  // generic byte order conversion
  template <order From, order To, class ReversibleValue>
    ReversibleValue convert_value(ReversibleValue from) noexcept;
  template <order From, order To, class Reversible>
    void convert(Reversible& x) noexcept; 

  // runtime byte-order conversion
  template <class ReversibleValue>
    ReversibleValue convert_value(ReversibleValue from,
      order from_order, order to_order) noexcept;
  template <class Reversible>
    void convert(Reversible& x,
      order from_order, order to_order) noexcept;

} // namespace endian
} // namespace boost

The implementation is required to define the enum class order constant native as big on big endian platforms and little on little endian platforms.

Requirements

Template argument Reversible requirements

This subsection describes names that are used to specify constraints on template arguments.

User-defined types may be used in the function templates in this header only if they meet these requirements.

Reversible is an object type to be supplied by a C++ program instantiating a template.

Expression Meaning of x Requirements

reverse_endianness(x)

x is a value of a possibly const type convertible to Reversible.

The value of x with the order of its constituent bytes reversed is returned.

reverse_endianness_in_place(x) x is a modifiable lvalue of type Reversible. The order of the constituent bytes of x are reversed.

[Note: A user-defined type meets these requirements by defining a non-member function in the same namespace as the UDT itself so that the function can be found by argument dependent lookup (ADL). —end note]

Customization points for user-defined types (UDTs)

This subsection describes requirements on the endian library's own implementation.

The endianness conversion function templates that return values are required to perform reversal of endianness if needed by making an unqualified call to reverse_endianness(argument), as described in the preceding table.

The endianness conversion function templates that modify their argument in place are required to perform reversal of endianness if needed by making an unqualified call to reverse_endianness_in_place(argument), as described in the preceding table.

See udt_conversion_example.cpp for an example user-defined type.

Functions

int8_t  reverse_endianness(int8_t x) noexcept;
int16_t  reverse_endianness(int16_t x) noexcept;
int32_t  reverse_endianness(int32_t x) noexcept;
int64_t  reverse_endianness(int64_t x) noexcept;
uint8_t  reverse_endianness(uint8_t x) noexcept;
uint16_t reverse_endianness(uint16_t x) noexcept;
uint32_t reverse_endianness(uint32_t x) noexcept;
uint64_t reverse_endianness(uint64_t x) noexcept;
float    reverse_endianness(float x) noexcept;
double   reverse_endianness(double x) noexcept;

Returns: x, with the order of its constituent bytes reversed.

template <class Value>
  void     reverse(Value& x) noexcept;

Postconditions: The order of the constituent bytes of x are reversed.

template <class ReversibleValue >
  ReversibleValue big_endian_value(ReversibleValue x) noexcept; 
template <class Reversible>
  void big_endian(Reversible& x) noexcept;

Returns (first form): x if the native byte order is big endian, otherwise reverse_endianness(x).

Effects (second form): None if the native byte order is big endian, otherwise reverse(x).

Example:

int32_t x = some-value;
big_endian(x);  // reverses the byte order of x, unless
                // the native byte order is big-endian
template <class ReversibleValue >
  ReversibleValue little_endian_value(ReversibleValue x) noexcept; 
template <class Reversible>
  void little_endian(Reversible& x) noexcept;

Returns (first form): x if the native byte order is little endian, otherwise reverse_endianness(x).

Effects (second form): None if the native byte order is little endian, otherwise reverse(x).

Example:

int32_t x = some-value;
int32_t y(little_endian(x));
// y has been set to x; the byte order is reversed unless
// the native byte order is little-endian.
template <order From, order To, class ReversibleValue>
  ReversibleValue convert_value(ReversibleValue from) noexcept;
template <order From, order To, class Reversible>
  void convert(Reversible& x) noexcept;

The effective order of an order template parameter is the same as the order template parameter if the parameter is not order::native, otherwise it is the constant order::big or order::little that represents the actual native byte order.

Returns (first form): from if From and To have the same effective order, otherwise reverse_endianness(from).

Effects (second form): None if From and To have the same effective order, otherwise reverse(x).

Example:

int32_t x;
... read an external big-endian value into x
convert<order::big, order::native>(x);  // more generic equivalent of big_endian(x);
template <class ReversibleValue>
  ReversibleValue convert_value(ReversibleValue from,
    order from_order, order to_order) noexcept;
template <class Reversible>
  void convert(Reversible& x,
    order from_order, order to_order) noexcept;

Returns (first form): from if effect_order(from_order) == effective_order(to_order), otherwise reverse_endianness(from).

Effects (second form): None if effect_order(from_order) == effective_order(to_order), otherwise reverse(x).

Example:

int32_t x;
... read an external value of an endianness know only at runtime into x
convert(x, some_order, order::native);  // convert to native byte order if needed

FAQ

See the Endian home page FAQ for a library-wide FAQ.

Why are the template versions of reverse() and reverse_endianness() in a detail namespace?

They are unsafe for general use. Consider reversing the bytes of a std::pair as a whole - the bytes from first would end up in second and visa versa, and this is totally wrong!

Why are both value returning and modify-in-place functions provided?

Returning the result by value is the standard C and C++ idiom for functions that compute a value from an argument. Modify-in-place functions allow cleaner code in many real-world endian use cases and are more efficient for user defined types that have members such as string data that do not need to be reversed. Thus both forms are provided.

Acknowledgements

Tomas Puverle was instrumental in identifying and articulating the need to support endian conversion as separate from endian integer types. Phil Endecott suggested the form of the value returning signatures. Vicente Botet and other reviewers suggested supporting floating point types and user defined types. General reverse template implementation approach using std::reverse suggested by Mathias Gaunard. Portable implementation approach for 16, 32, and 64-bit integers suggested by tymofey, with avoidance of undefined behavior as suggested by Giovanni Piero Deretta, and a further refinement suggested by Pyry Jahkola. Intrinsic builtins implementation approach for 16, 32, and 64-bit integers suggested by several reviewers, and by David Stone, who provided his Boost licensed macro implementation that became the starting point for boost/endian/detail/intrinsic.hpp. Pierre Talbot provided the int8_t reverse_endianness() and templated reverse() implementations.


Last revised: 07 December, 2014

© Copyright Beman Dawes, 2011, 2013

Distributed under the Boost Software License, Version 1.0. See www.boost.org/ LICENSE_1_0.txt