Question: I want to write some C++ code that can read and write from files in an endian-correct way. More exactly, I want to be able to read a particular type of file, whose endianness I can easily detect (its magic number being reversed or not).

But how would I then go about cleanly reading the file correctly? I've read the following article which gives a helpful idea:

<http://www.gamedev.net/page/resources/_/technical/game-programming/writing-endian-independent-code-in-c-r2091>

The idea there is to make a class which has some function pointers to the endianness-correct read() function desired. But in my experience, function pointers are slow, especially when you have to call them so frequently as in this case. Another alternative is to have an

```
if (file_was_detected_big_endian) { read_bigendian(); } else { read_littleendian(); }

```

for every single read\_x\_bit\_int() function I have but this too seems inefficient.

I'm using Boost so I have all its magnificence to help me. In particular, there's the endian sublibrary:

<http://www.boost.org/doc/libs/develop/libs/endian/doc/buffers.html>

Though I'm not sure how I can cleanly use this code to do what I want. I'd love to have some code where I can read say 16 bytes directly into the pointer of a `struct` that represents a part of the file while automatically correcting for endianness. I could of course write this code myself but I have a feeling a solid solution must already exist.

I think all the code I have will be manually padded and guarded against alignment issues.

Thanks!

Answer: 
There are two approaches to this problem:

1. Write your files in an endianness-agnostic way, and
2. Add a marker, and read files in an endianness-aware way.

The first approach requires more work on writing, while the second approach makes writing "overhead-free".

Both approaches can be implemented without function pointers: the need for them has greatly diminished in C++ due to virtual functions\*.

Implementing both approaches is similar: you need to make an abstract base class for serializing primitive data types, make an instance of that class that reads the correct endianness, and call its virtual member functions for reading and writing:

```
struct PrimitiveSerializer {
    virtual void serializeInt(ostream& out, const int val) = 0;
    virtual void serializeChar(ostream& out, const char val) = 0;
    virtual void serializeString(ostream& out, const std::string& val) = 0;
    ...
    virtual int deserializeInt(istream& in) = 0;
    virtual char deserializeChar(istream& in) = 0;
    virtual std::string deserializeString(istream& in) = 0;
};
struct BigEndianSerializer : public PrimitiveSerializer {
    ...
};
struct LittleEndianSerializer : public PrimitiveSerializer {
    ...
};

```

Depending on the approach, the decision which subclass to use is made differently. If you use the first approach (i.e. writing endianness-agnostic files) then you would instantiate the serializer that matches your system's endianness. If you take the second approach, you would read the magic number from the file, and choose the subclass that matches the endianness of your file.

In addition, the first approach can be implemented using [`hton` / `ntoh`](https://stackoverflow.com/q/21996794/335858) functions.

\* Function pointers are not "slow" by themselves, although they make it easier to write inefficient code.
So the virtual-function method that dasblinkenlight proposes will probably suffice - especially since I/O will probably be the dominant eater of time. However, if you *do* find that your read function is eating up a lot of cpu time, you can get rid of the virtual function dispatch by templatizing your file reader.

Here's some pseudocode demonstrating this:

Basically, create two reader classes, one for each endianness:

```
class LittleReader {
  public:
  LittleReader(std::istream& is) : m_is(is) {}
  char read_char() {//read byte from m_is}
  int read_int32() {//read 32-bit int and convert;}
  float read_float()....
  private:
  std::istream& m_is;
};

class BigReader {
  public:
  BigReader(std::istream& is): m_is(is){}
  char read_char(){...}
  int read_int32(){..}
  float read_float(){...}
  private:
  std::istream& m_is;
}

```

Separate out the main part of your reading logic (except for the magic number bit) into a function template that takes an instance of one of the above classes as an argument:

```
template <class Reader>
void read_endian(Reader &rdr){
  field1 = rdr.read_int32();
  field2 = rdr.read_float();
  // process rest of data file
  ...
}

```

Essentially, the compiler will create two implementations of your read\_endian function - one for each endianness. Since there is no dynamic dispatch, the compiler can also inline all the calls to read\_int32, read\_float, etc.

Finally, in your main reader function, look at the magic number to determine which kind of reader to instantiate:

```
void read_file(std::istream& is){
  int magic(read_magic_no(is));
  if (magic == MAGIC_BIG_ENDIAN)
     read_endian(BigReader(is));
  else
     read_endian(LittleReader(is));
}

```

This technique gives you flexibility without incurring any virtual dispatch overhead, at the cost of increased (binary) code size. It can be very useful where you have extremely tight loops and you need to squeeze every last drop of performance.