The easy way to load many file formats (I'll use a BMP here to be concrete) is just to point a
struct at it :
struct BITMAPFILEHEADER
{
U16 bfType;
U32 bfSize;
U16 bfReserved1;
U16 bfReserved2;
U32 bfOffBits;
} __attribute__ ((__packed__));
BITMAPFILEHEADER * bmfh = (BITMAPFILEHEADER *)data;
if ( bmfh->bfType != 0x4D42 )
ERROR_RETURN("not a BM",0);
etc..
but of course this doesn't work cross platform.
So people do all kinds of convoluted things (which I have usually done), like changing to a
method like :
U16 bfType = Get16LE(&ptr);
U32 bfSize = Get32LE(&ptr);
or they'll do some crazy struct-parse fixup thing which I've always found to be bananas.
But there's a super trivial and convenient solution :
struct BITMAPFILEHEADER
{
U16LE bfType;
U32LE bfSize;
U16LE bfReserved1;
U16LE bfReserved2;
U32LE bfOffBits;
} __attribute__ ((__packed__));
where U16LE is just U16 on little-endian platforms and is a class that does bswap on itself on big-endian
platforms.
Then you can still just use the old struct-pointing method and everything just works. Duh, I can't believe I didn't think of this earlier.
Similarly, here's a WAV header :
struct WAV_header_LE
{
U32LE FOURCC_RIFF; // RIFF Header
U32LE riffChunkSize; // RIFF Chunk Size
U32LE FOURCC_WAVE; // WAVE Header
U32LE FOURCC_FMT; // FMT header
U32LE fmtChunkSize; // Size of the fmt chunk
U16LE audioFormat; // Audio format 1=PCM,6=mulaw,7=alaw, 257=IBM Mu-Law, 258=IBM A-Law, 259=ADPCM
U16LE numChan; // Number of channels 1=Mono 2=Sterio
U32LE samplesPerSec; // Sampling Frequency in Hz
U32LE bytesPerSec; // bytes per second
U16LE blockAlign; // normall NumChan* bytes per sample
U16LE bitsPerSample; // Number of bits per sample
} __attribute__ ((__packed__));;
easy.
For file-input type structs, you just do this and there's no penalty. For structs you keep in memory you wouldn't want to eat the bswap all the time, but even in that case this provides a simple way to get the swizzle into native structs by just copying all the members over.
Of course if you have the Reflection-Visitor system that I'm fond of, that's also a good way to go. (cursed C, give me a "do this macro on all members").
3 comments:
That's a really good idea for the endian-independent structs.
I recently did something similar with fixed-point numbers: using constexpr to guarantee the compiler converted the floats to the fixed-point class, and then typedef'ing 'number' to float or leaving it as a number class. Kind of neat if you want to share code between a small microcontroller and a PC project. :-)
Charles, question about your cubic controller... PID makes this easy, but, for cubic do you have any ideas how it could be made to work if the frame time was substantially less than the system response time? Seems like if one makes the commanded speed 'one frame' in the future, it'd just stick at a really really low speed for a long time..
I'm not sure I understand the question; can you email me?
For C I did something like this: https://github.com/alexfru/TypeTraitsInC
Post a Comment