September 22, 2004
We still need an bigendian, bigendian, littleendian, etc attribute.
The assumption that you'd only need to deal with this on stream I/O on
individual variables is false because of needing to input/output entire
structures from memory. Does std.inbuffer in the Phobos
system library (http://www.digitalmars.com/d/) provide a method to define
an entire structure from memory and have the correct endianness reflected?
I don't like the idea of having to overload outbuffer for
structs differently on different systems depending upon endianness. It
sounds really yucky to have to overload in all these cases. The solution
in part 3 is what people have suggested years ago. The only other viable
method would to have something that works like printf with formatting
characters that specify endianness of the data characters... I'll show
that in part 5.

1) On C/C++ system-specific where the endianness is known to be the same as the data in memory, you could do the following pseudocode:

struct someimageheader
{
	short a;
	short b;
	long  c;
	long  d;
	char  e[2];
}

someimageheader ih;

void somefunc()
{
	memcpy(&ih,somemem,12);
}

and would fill the buffer properly.

2) I don't see how outbuffer could do this kind of thing... It seems like you'd have to read in the values one at a time and explicitly convert their endianness... Although this is essentially the same thing that happens on cross-platform code in C++, it'd be nice to be able to do something like this this:

struct someimageheader
{
	bigendian short a;
	bigendian short b;
	bigendian long  c;
	bigendian long  d;
	char e[2];
}

or equivalent if you know every variable will be the proper value (char, of course, has no endianness):

bigendian struct someimageheader
{
	short a;
	short b;
	long  c;
	long  d;
	char e[2];
}

3) You could make it so structs defined with inbigendian or outbigendian can not be worked with directly unless you copy it to a normal structure. So the code I showed in 1 would be equivalent to this (there is probably a better way to do this, but I'm just trying to give an idea):

bigendian struct be_someimageheader
{
	short a;
	short b;
	long  c;
	long  d;
	char e[2];
}
struct someimageheader
{
	short a;
	short b;
	long  c;
	long  d;
	char e[2];
}

be_someimageheader beih;
someimageheader ih;

void somefunc()
{
	memcpy(&beih,somemem,12);
	ih=beih;
}

4) This could also work for:

void somefunc()
{
	bigendian int a=5;
	int b=a;
}

On a little-endian machine, it'd convert endianness.

5) The only viable solution I can think of would be to have a function that can reorder bytes in a struct based on some formatting character like this:

structreorder(void * struct, va_list commands)

example:

structreorder((void *)&ih, "r%s", "r%s", "r%l", r%l", "%b");

Which means, "reorder short,reorder short,reorder long,reorder long, don't reorder byte"

I think this suffers from having to rewrite the formatting every time you change the struct, and doesn't save anything from overloading the outbuffer functions.