Allegro.cc - Online Community

Allegro.cc Forums » Endianness » Reply

 Forums: Endianness: Reply
This section is only available to registered Allegro.cc members.
 Thread Review
DanielH:

Does Allegro have a function to check endianness?

Can someone post a snippet of a) how to tell what endianness the machine has b) how they would read/write an 32bit int?

You could read/write little e regardless of machine type then convert to big e if required. Sound about correct?

Niunio:

IIRC there's a define somewhere in the header files (maybe type.h?) so you can use #IFDEF to know the endianess. Also, there are defines for the target system (CPU and operating system).

DanielH:

FYI, Allegro defines endianness with ALLEGRO_LITTLE_ENDIAN or ALLEGRO_BIG_ENDIAN defined

What about this pseudocode?
'type' would be a primitive like int, float, etc.

#SelectExpand
1// returns number of bytes written or EOF if error 2int write(ALLEGRO_FILE *file, type value) 3{ 4 // if big endian, swap bytes 5#ifdef ALLEGRO_BIG_ENDIAN 6 value = swap_bytes(&value, sizeof(type)); 7#endif 8 9 // write little endian 10 return write_bytes(file, &value, sizeof(type)); 11} 12 13// returns number of bytes read or EOF if error 14int read(ALLEGRO_FILE *file, type&value) 15{ 16 // read little endian 17 int sz = read_bytes(file, &value, sizeof(type)); 18 19 if (sz == EOF) return EOF: 20 21 // if big endian, swap bytes 22#ifdef ALLEGRO_BIG_ENDIAN 23 value = swap_bytes(&value, sizeof(type)); 24#endif 25 26 return sz; 27}

GullRaDriel:

Allegro aside, here are some macros I'm using in my lib, mainly a scrap of a lot of detection macros that I took here and there.

#SelectExpand
1/*! Little endian macro value */ 2#define BYTEORDER_LITTLE_ENDIAN 0 // Little endian machine. 3/*! Big endian macro value */ 4#define BYTEORDER_BIG_ENDIAN 1 // Big endian machine. 5 6 7#ifndef BYTEORDER_ENDIAN 8// Detect with GCC 4.6's macro. 9#if defined(__BYTE_ORDER__) 10#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) 11#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN 12#elif (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) 13#define BYTEORDER_ENDIAN BYTEORDER_BIG_ENDIAN 14#else 15#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN 16#warning "Unknown machine byteorder endianness detected. User needs to define BYTEORDER_ENDIAN." 17#warning "Setting default to BYTEORDER_LITTLE_ENDIAN" 18#endif 19// Detect with GLIBC's endian.h. 20#elif defined(__GLIBC__) 21#include <endian.h> 22#if (__BYTE_ORDER == __LITTLE_ENDIAN) 23#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN 24#elif (__BYTE_ORDER == __BIG_ENDIAN) 25#define BYTEORDER_ENDIAN BYTEORDER_BIG_ENDIAN 26#else 27#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN 28#warning "Unknown machine byteorder endianness detected. User needs to define BYTEORDER_ENDIAN." 29#warning "Setting default to BYTEORDER_LITTLE_ENDIAN" 30#endif 31// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro. 32#elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) 33#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN 34#elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN) 35#define BYTEORDER_ENDIAN BYTEORDER_BIG_ENDIAN 36// Detect with architecture macros. 37#elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__) 38#define BYTEORDER_ENDIAN BYTEORDER_BIG_ENDIAN 39#elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__) 40#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN 41#elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64)) 42#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN 43#else 44#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN 45#warning "Unknown machine byteorder endianness detected. User needs to define BYTEORDER_ENDIAN." 46#warning "Setting default to BYTEORDER_LITTLE_ENDIAN" 47#endif 48#endif

Well. Old and new GCC specific code, maybe. I had no problem with it on Solaris, AIX, Linux, Windows MinGW.

BTW I also had to detect 32 or 64 bits, and that little piece covered all my needs:

#SelectExpand
1#if defined( _WIN32 ) || defined( _WIN64 ) 2#if defined( _WIN64 ) 3#define __ENVBITS ENV_64BITS 4#else 5#define __ENVBITS ENV_32BITS 6#endif 7#endif 8 9#if !defined( __ENVBITS ) 10#if defined( __GNUC__ ) 11#if defined( __x86_64__ ) || defined( __ppc64__ ) 12#define __ENVBITS __ENV_64BITS 13#else 14#define __ENVBITS __ENV_32BITS 15#endif 16#endif 17#endif

Your mileage may vary. It may only be right on my own os targets.

Edit:
BTW endianness is only a problem if you are having datas or networks communications between systems that are not the same endian or bits. Problems may arise if i.e you write a datafile containing dumps on A and read it on B, and that B is not the same bits / endianness as A.
Commonly when I need to write something I'm rarely dumping a int64, as it's not portable across all my targets ( a mix of 32/64bits ), and anyway I always htonX before dumping, and ntohX when reading the dump. That way data is consistent.
I'm not sure if I'm clear, but my dear I'm tired today X-D

guin hanki:

It seems there is a definition somewhere in the header files (maybe type.h?) so you can check the endianness using #IFDEF. It specifies the target system's CPU and operating system.https://maxifoot.info/

Edgar Reynaldo:

You can perform a run time check easily enough.

bool BigEndian() {
   int pack = 'b' << 24 | 'e' << 16 | 'e' << 8 | 'l';
   return (char*)(pack)[0] == 'b';
}

Polybios:

Beels live in memory.

DanielH:

Yes, as I said before, it's defined by Allegro depending on how Allegro was compiled

ALLEGRO_LITTLE_ENDIAN or ALLEGRO_BIG_ENDIAN

This is about what I have.

Written and Read as little. Convert to big if needed.

#SelectExpand
1 void SwapBytes(const void* input, void* output, size_t bytes); 2 int32_t WriteBytes(Allegro::File& file, const void* value, size_t bytes); 3 int32_t ReadBytes(Allegro::File& file, void* value, size_t bytes); 4 5 template <typename type> 6 int32_t WritePrimitive(Allegro::File& file, const type value) 7 { 8 const type output; 9 10#ifdef ALLEGRO_LITTLE_ENDIAN 11 output = value; 12#else 13 SwapBytes(value, output, sizeof(type)); 14#endif 15 16 return Wind::WriteBytes(file, &output, sizeof(type)); 17 } 18 19 // special case. read/write as byte 0 or 1 20 template <> int32_t WritePrimitive(Allegro::File& file, const bool& input); 21 22 23 template <typename type> 24 int32_t ReadPrimitive(Allegro::File& file, type& value) 25 { 26 type input; 27 int32_t size = Wind::ReadBytes(file, &input, sizeof(type)); 28 29 if (size == EOF) 30 { 31 return EOF; 32 } 33 34#ifdef ALLEGRO_BIG_ENDIAN 35 SwapBytes(input, value, sizeof(type)); 36#else 37 value = input; 38#endif 39 return 0; 40 } 41 42 // special case. read/write as byte 0 or 1 43 template <> int32_t ReadPrimitive(Allegro::File& file, const bool& input);