Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
endian: Endian-Aware Facilities For Manipulating Binary Data

When reading or writing binary data that is to be shared between applications, it is important to define the byte order for data types that occupy more than one byte, so that the applications can read the correct value for the data type even if they have different native byte orders.

The public header is

Public export header for the endian subpackage.

The Bazel target is

//:endian

Determining the endianness of the current system

The arene::base::endian enumeration is a back-port of the C++20 std::endian enumeration. The arene::base::endian::native value can be compared against arene::base::endian::little and arene::base::endian::big to determine if the current target platform is big-endian or little-endian.

The specifications for std::endianis available on cppreference.

Reading and writing data with a specific endianness

The various overloads of arene::base::read_little_endian and arene::base::read_big_endian facilitate reading values that are stored in little-endian or big-endian byte order respectively. Similarly, the overloads of arene::base::write_little_endian and arene::base::write_big_endian facilitate writing values in little-endian or big-endian byte order respectively. These are provided for:

  • integral types
  • floating-point types except long double.
  • enumeration types

long double is not supported because it requires additional runtime support on some platforms.

Usage is simple: just pass in a suitably-sized arene::base::span to read, or the value to be written and a suitably-sized arene::base::span to write, as in the following code.

void write(std::span<arene::base::byte> buffer) {
int my_val = create_value();
arene::base::write_little_endian<int>(my_val, buffer.first<sizeof(int)>());
}
void read(std::span<const arene::base::byte> buffer) {
my_val, buffer.first<sizeof(int)>());
do_something_with(my_val);
}
void write_little_endian(base::type_identity_t< T > value, span< byte, sizeof(T)> bytes) noexcept=delete
Write a value to a buffer in little-endian binary representation.
Definition endian.hpp:618
auto read_little_endian(span< byte const, sizeof(T)> bytes) noexcept -> T=delete
Read a value from a serialized binary representation stored in little-endian byte order.
Definition endian.hpp:660

Note that arene::base::read_little_endian, arene::base::read_big_endian, arene::base::write_little_endian and arene::base::write_big_endian require that the provided spans have exactly the right size. The example code above uses buffer.first<sizeof(int)>() to obtain a fixed-size span for the beginning of the specified buffer. buffer.subspan or buffer.last could also be used to obtain a fixed-size span for other parts of the buffer, or read and write could accept fixed-size spans directly.

Swapping the byte order of an integer

If you're manually processing data with a specific endianness, then you may need to swap the order of bytes in an integral value, depending on the value of arene::base::endian::native. The arene::base::byte_swap function provides that facility: arene::base::byte_swap(some_integral) yields an integral value of the same type as some_integral, but with the reverse byte order. Thus 0x1234 becomes 0x3412 and 0x12345678 becomes 0x78563412. For signed values this may change the sign.