Jump to content
  • Advertisement
Sign in to follow this  
Alundra

Serializer/Endian

This topic is 2072 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi all,

you can detect if a platform is little endian or big endian with a macro.

The best way to manage serializer in an app to have endian correct is :

1) Write a char 0 or 1 to say if the file is BigEndian

2) Have a function to force to write little or big endian.

3) Have read/write functions in a serializer class.

4) Use these function to read/write.

Is it the correct way to handle endian ?

Thanks for the help

Share this post


Link to post
Share on other sites
Advertisement
There are several ways to do it, but perhaps the easiest one is to write every byte yourself:
void write_unsigned_short(unsigned short x) {
  write_byte(x / 256);
  write_byte(x % 256);
}

unsigned short read_unsigned_short() {
  unsigned short x = 0;
  x += read_byte() * 256;
  x += read_byte();
  return x;
}
This code will do the same thing on big-endian and little-endian platforms.

Share this post


Link to post
Share on other sites

Using this generic type of code is ok about perf or it's better to have 3 functions (uint16, uint32, uint64) :

void swapbytes(void *_object, size_t _size)
{
   unsigned char *start, *end;
   for( start = (unsigned char *)_object, end = start + _size - 1; start < end; ++start, --end )
   {
     unsigned char swap = *start;
     *start = *end;
     *end = swap;
   }
}

EDIT : Is it safe to not swap floats ?

Edited by Alundra

Share this post


Link to post
Share on other sites
Also, your swapbytes function is probably fine, depending on where you use it. We use a function that's almost identical at my office when we load files and need to perform some endian swapping. Since it's at load time the tiny overhead from using a generic swapping function is a non issue.

Share this post


Link to post
Share on other sites

But how do you decide if you need to swap bytes or not?

 

In my case that knowledge is a priori. For example, all our game asset files are written on a PC, and when loaded on a big-endian console we know they must be swapped. (sidebar: yes, it would probably be better if we had our asset building tools do the endian swapping at build time and spare the runtime from having to do the work, but..) We don't have any cases where must read data of unknown endianness, so a macro that resolves to swap or no-swap at compile time is sufficient. 

Share this post


Link to post
Share on other sites

macro + char on the beginning of the file to say the endian, but an option to save to selected endian is a must-have I think.

/*!
\brief
  Endian enum.
*/
enum TEndian
{
  E_BIG  = 0, //!< Big endian.
  E_LITTLE = 1  //!< Little endian.
};

/*!
\brief
  The CEndian class constructor.
*/
CEndian( const TEndian Endian );
Edited by Alundra

Share this post


Link to post
Share on other sites

Why are you insisting on having to set macros correctly (which people can make mistakes with) to sometimes swap bytes, when you could just use code like above from Alvaro that always does the right thing (reads/writes to files in network byte order in the right way for big and little endian processors because arithmetic is always the same)?

Share this post


Link to post
Share on other sites

If you want to be portable and don't want to mess around with endian detection, you can just use the ntoh* and htonl* family of functions.

 

htons, htonl, htonf, htond - (H)ost TO (N)etwork short, long, float, double

ntohs, ntohl, ntohf, ntohd - (N)etwork TO (H)ost short, long, float, double

 

Network is always big-endian.  The host is whatever you code is running on, can be little or big.

Edited by TangentZ

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!