www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - endian: std.inbuffer/std.outbuffer is not a sufficient

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.
Sep 22 2004