My chess programs are designed to have portable coded opening books that have the same representation on both big endian (Intel/AMD) and little endian (PowerPC/Motorola) machines. Having to code for both flavors help make for a more reliable program. To support multi-byte integer I/O, my programs use a small and simple library to help.
The routines do I/O one byte at a time. This isn't slow as one might think as the underlying system buffering takes care of much of the work. Every single I/O operation is tested for success/failure.
Note: The streams must be opened in std::ios::binary mode to work on some systems (e.g., Windows).
To assist other C++ programmers, here's the source:
I've also done this before and it can work reasonably well. However, it once led to a hard-to-find bug where I had forgotten to include the header file with the override definition and got the defualt operator semantics by mistake. There is no compiler issued warning or error to help in that case.
enum EEndian
{
LITTLE_ENDIAN_ORDER,
BIG_ENDIAN_ORDER,
#if defined(BOOST_LITTLE_ENDIAN)
HOST_ENDIAN_ORDER = LITTLE_ENDIAN_ORDER
#elif defined(BOOST_BIG_ENDIAN)
HOST_ENDIAN_ORDER = BIG_ENDIAN_ORDER
#else
#error "Impossible de determiner l'indianness du systeme cible."
#endif
};
template <class T, unsigned int size>
inline T SwapBytes(T value)
{
union
{
T value;
char bytes[size];
} in, out;
in.value = value;
for (unsigned int i = 0; i < size / 2; ++i)
{
out.bytes[i] = in.bytes[size - 1 - i];
out.bytes[size - 1 - i] = in.bytes[i];
}
return out.value;
}
template<EEndian from, EEndian to, class T>
inline T EndianSwapBytes(T value)
{
// A : La donnée à swapper à une taille de 2, 4 ou 8 octets
BOOST_STATIC_ASSERT(sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8);
// A : La donnée à swapper est d'un type arithmetic
BOOST_STATIC_ASSERT(boost::is_arithmetic<T>::value);
// Si from et to sont du même type on ne swap pas.
if (from == to)
return value;
return SwapBytes<T, sizeof(T)>(value);
}
Thisway littleEndian is the representation of anyIntegerVariable in little endian order whatever the host endian order is. If the host endian order is the same as the target order (in this case LITTLE_ENDIAN_ORDER) no code is generated at all.
sje wrote:
I've also done this before and it can work reasonably well. However, it once led to a hard-to-find bug where I had forgotten to include the header file with the override definition and got the defualt operator semantics by mistake. There is no compiler issued warning or error to help in that case.