Endian Template (C++)

Work with big endian and little endian types in C++ without ever calling an "endian swap" function

License

Download

About

The Endian Template is a set of C++ template class and typedefs that allow you use little endian or big endian types, without having to write or concern yourself with "endian swap" functions, on any platform that supports at least the C++98 standard. This provides a few benefits over other techniques: Guaranteed endian correctness when using a typedef

No need to call "endian swap" functions

No need for "endian detection macros", as everything is determined at compile-time / run-time

Ability to wrap your own types with the provided templates

How to Use

Setup

First, copy the header tEndian.h into your project.

Next, include the header somewhere in your project or precompiled header if you use one. #include "tEndian.h"

Typedefs

You'll now have the following typedefs to use in your project: leint16 , leint32 , leint64 - Little endian signed types

leuint16 , leuint32 , leuint64 - Little endian unsigned types

lefloat32 , lefloat64 - Little endian floating point types beint16 , beint32 , beint64 - Big endian signed types

beuint16 , beuint32 , beuint64 - Big endian unsigned types

befloat32 , befloat64 - Big endian floating point types The naming conventions are based on those in C++ standard library header cstdint; the only addition being a prefix of le or be to indicate little endian or big endian, respectively.

Templates

You'll also have the following template classes available for use in your project: tLittleEndian<T> - Little endian template wrapper

tBigEndian<T> - Big endian template wrapper With those template wrappers, you could in theory wrap your own types. For instance, if you wanted to define a big endian version of size_t and short , and a little endian version long long , the following example code will achieve this: typedef tBigEndian < size_t > besize ; typedef tBigEndian < short > beshort ; typedef tLittleEndian < long long > lelonglong ; You will also find a third template, tEndianBase<T> , however it's only meant to be used as a helper class from the other template classes, so I don't suggest you use it directly yourself.

Usage

When using the endian types, you can literally just drop them in to replace your current types, as long as you also remove any endian swapping functions you're calling. There are three primary reasons I see someone using the Endian Template: You're writing an emulator / virtual machine You're writing a binary file format reading / writing library Converting data sent over a network I'll cover these three use cases, but forgive me as I'll be very brief with each.

Emulator / Virtual Machine

Of course, depending on the machine type, memory itself will be stored as big or little endian. However, it's typically when you're loading memory into registers, then doing math on those registers, when endianness starts to matter. That said, you could define each register as the proper endian type for the platform you're emulating, and you won't have to worry or remember about shifting memory one way or another after a math operation– it just gets stored correctly on it's own.

Binary file formats

Binary formats are compact but are a potential minefield when dealing with different CPU architectures. The Endian Template can help here too. I used to love writing things like image decoders for formats like BMP and the like. For example, in a BMP file, the first two bytes are typically BM , but the next four bytes are "the size of the BMP file"– in little endian format. If you read this data into an uint32_t , you're fine as long as you're on a little endian machine (like an x86-based PC.) Not so much if you end up running your code on a PowerPC CPU, which is big endian. So take the guesswork out of the equation– read it into an leuint32 instead and it'll always work, regardless of the architecture.

Sending data over a network

If you're familiar with Network Byte Order, you'll know that the functions htons , htonl , ntohl , ntohs are generally suggested to use before sending data over a network. Since "Network Byte Order" is just "big endian"; instead you can now just define your data as beint32 , beint16 , or tBigEndian<unsigned short> and discard the conversion functions completely. And regardless of the endian of computer's CPU, the code will always work.

Running the unit tests

The Endian Template comes with a unit test class, tEndianTests.cc , and three project files: /project/win/EndianTests.sln - Visual Studio 2005, Windows console target

/project/mac/EndianTests.xcodeproject - Xcode 7 Mac OS console target

/project/ios/EndianTests.xcodeproject - Xcode 7 iOS console target When running the unit test on Visual Studio, note you will first need to convert the solution to the latest version. You'll also need to put a breakpoint on the last line of the main function, as the console window containing the results of the test will close on exit. When running the unit test on Mac or for iOS, the results of the test will be printed in Xcode's debug console, which is at the bottom right of Xcode's window. Also, when running for iOS, you'll note that an app won't appear or launch in the simulator or on a device, as the tests are purely meant to display in the debug console. (If you're curious, these project files were generated with Google GYP; the source project file is located in /project/common/EndianTests.gyp .)

Q & A

If you have a question not answered here, please feel free to contact me and ask.

vs Boost?

Q: What makes this better or different than What makes this better or different than Boost.Endian

A: I can't say for certain if it's better. The Endian Template is small, and only provides a minimum of what's needed to handle automatic endian conversion. As I understand it Boost.Endian provides three different mechanisms for handling endian (one providing swapping functions), whereas my primary philosophy here is "don't use swapping functions." Just for trivia: I originally created this class in 2001 as a proof-of-concept, hoping I could use it in some emulation projects (never got around to those unfortunately.) This predates when Boost.Endian came out, which was around 2002 or 2003. That said, I've used boost (in general) before on a day-to-day basis for a client project. I'm not a boost "hater", but I'm not a regular user of it either.

History