Endianess conversion thru C++ templates
Sunday, May 20th, 2007I wanted to review the historically cumbersome endianess conversion for our ExactImage for some time now. Thanks that the good old C macros (and the various variants of it) annoyed me enough to finally do so. What we now have in our “exact-base” repository is a C++ template setup that can be used to either define variables that have a specifc endianess in memory - probably because the composed structures are read and written as part of a externally defined format (such as BMP :-) - or to explicitly convert as in former times, just with the syntactic sugar of C++.
Using the template in packed structures is as easy as:
/* Size in bytes of the bitmap file */
Exact::EndianessConverter < uint32_t, LittleEndianTraits > iSize;
This defines iSize as ‘unsigned 32 bit’ with little-endian representation in-memory.
The next handy thing this Plain Old Data template avoids, is accidently messing with the data. As the type is incompatible with the usual ‘uint32_t’ it can not mangled. hWile the assignment operator is overloaded to store the data in the indended order, the cast to type passed to the template yield the swapped value, so straight-forward code just works:
#include < iostream >
#include “utility/Endianess.hh”
int main() {
Exact::EndianessConverter < int16_t, Exact::BigEndianTraits > test;
test = 0×1234;
std::cerr << "sizeof: " << sizeof (test) << std::endl
<< "value: " << std::hex << (int32_t)test << std::endl
<< "in-memory: " << test.value << std::endl;
}
Prints out:
sizeof: 2
value: 1234
in-memory: 3412
Checking the actual native endianess is as easy as:
if (Exact::NativeEndianTraits::IsBigendian)
And explicit conversion done like this:
Exact::ByteSwap < BigEndianTraits, NativeEndianTraits, uint16_t > ::Swap (some_data)
The whole source is available under the terms of the GPL!