25 March 2009

bytefluo

I was reading Gulliver’s Travels to one of my children tonight and we came across the term Big-endian in a passage about the reason for the war between Lilliputians and Blefuscudians (the latter crack their eggs at the big end, the former at the little end). Although I read Gulliver’s Travels many years ago I had obviously forgotten this because I assumed that big- and little-endian were just computer jargon. But it seems Swift coined the term.

It is computed that eleven thousand persons have at several times suffered death, rather than submit to break their eggs at the smaller end. Many hundred large volumes have been published upon this controversy: but the books of the Big-endians have been long forbidden, and the whole party rendered incapable by law of holding employments. During the course of these troubles, the emperors of Blefusca did frequently expostulate by their ambassadors, accusing us of making a schism in religion, by offending against a fundamental doctrine of our great prophet Lustrog, in the fifty-fourth chapter of the Blundecral (which is their Alcoran). This, however, is thought to be a mere strain upon the text; for the words are these: 'that all true believers break their eggs at the convenient end.'

Gulliver’s Travels, Chapter 4

Anyway, following my previous post about UUID and Byte Order I wanted to advertise a way to break your eggs at the convenient end, namely a C++ class called bytefluo. Here’s how you might use it to read big- and little-endian UUIDs




#include "bytefluo.h"

namespace RFC_4122 {
// types borrowed from RFC 4122

typedef unsigned long unsigned32;
typedef unsigned short unsigned16;
typedef unsigned char unsigned8;
typedef unsigned char byte;

typedef struct {
unsigned32 time_low;
unsigned16 time_mid;
unsigned16 time_hi_and_version;
unsigned8 clock_seq_hi_and_reserved;
unsigned8 clock_seq_low;
byte node[6];
} uuid_t;
}//namespace RFC_4122

namespace {
// read UUID structure from given bytefluo stream
RFC_4122::uuid_t read_common(bytefluo & buf)
{
// note that this code will read the data in the correct byte order
// regardless of the natural byte order of this system; also reading
// the structure one field at a time makes it immune to possible
// compiler-specific structure packing for machine word alignment
RFC_4122::uuid_t result;
buf >> result.time_low
>> result.time_mid
>> result.time_hi_and_version
>> result.clock_seq_hi_and_reserved
>> result.clock_seq_low;
buf.read(result.node, sizeof(result.node));
return result;
}
}//anonymous namespace

// read big-endian encoded UUID structure from given 16-byte buffer
RFC_4122::uuid_t uuid_from_16_bytes_big_endian(const unsigned char * bytes)
{
bytefluo buf(bytes, bytes + 16, bytefluo::big_endian);
return read_common(buf);
}

// read little-endian encoded UUID structure from given 16-byte buffer
RFC_4122::uuid_t uuid_from_16_bytes_little_endian(const unsigned char * bytes)
{
bytefluo buf(bytes, bytes + 16, bytefluo::little_endian);
return read_common(buf);
}

int main()
{
const unsigned char bytes[16] = {
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
};
using RFC_4122::uuid_t;

// first read raw data assuming big-endian byte ordering
{
const uuid_t uuid(uuid_from_16_bytes_big_endian(bytes));
assert(uuid.time_low == 0x00112233);
assert(uuid.time_mid == 0x4455);
assert(uuid.time_hi_and_version == 0x6677);
assert(uuid.clock_seq_hi_and_reserved == 0x88);
assert(uuid.clock_seq_low == 0x99);
assert(::memcmp(uuid.node, "\xAA\xBB\xCC\xDD\xEE\xFF", 6) == 0);
}

// now read the same raw data assuming little-endian byte ordering
{
const uuid_t uuid(uuid_from_16_bytes_little_endian(bytes));
assert(uuid.time_low == 0x33221100);
assert(uuid.time_mid == 0x5544);
assert(uuid.time_hi_and_version == 0x7766);
assert(uuid.clock_seq_hi_and_reserved == 0x88);
assert(uuid.clock_seq_low == 0x99);
assert(::memcmp(uuid.node, "\xAA\xBB\xCC\xDD\xEE\xFF", 6) == 0);
}
}

Notice how bytefluo abstracts away the details of reading big- and little-endian scalars? Get your copy here!


 

index of blog posts

No comments:

Post a Comment