On Sun, 2011-04-03, Joe Pfeiffer wrote:
> Jorgen Grahn <grahn+(E-Mail Removed)> writes:
>
>> On Fri, 2011-04-01, Riccardo Manfrin wrote:
>>> Hi, I'm looking for the best way to handle byte order when switching
>>> from network (big-endian) to host (little-endian in my case), from an
>>> implementation point of view..
>>>
>>> I'd like to have a structure data type (e.g. bigendian_short_t that
>>> is capable of aligning bytes in the correct way when passing from
>>> memory to the value and viceversa).
>>
>> I suggest not doing that. Keep a source file with functions like:
>>
>> void encode_foo(const Foo* val, uint8_t * buf);
>> void encode_bar(const Bar* val, uint8_t * buf);
>> ...
>>
>> And you can implement those any way you want. I'd read and write
>> octet-by-octet and stay away from memcpy, ntolh, htonl, non-standard
>> struct packing and compiler-dependent layout issues ...
>
> The only disagreement I'd have is regarding ntolh and htonl -- copying
> objects of the sizes supported by these, and using them, gives you more
> portability.
But not more portability than this, or? (Untested, and only useful
with unsigned types):
void encode_u32(uint32_t n. uint8_t* buf)
{
*buf++ = n>>24;
*buf++ = n>>16;
*buf++ = n>> 8;
*buf++ = n;
}
The reason I don't like htonl() and friends is that they do the
conversion quickly and correctly -- but then half the work remains.
You're stuck with a "poisoned" variable, and you still have the
problem to serialize it into an octet buffer without doing anything
non-portable like unaligned memory access.
/Jorgen
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
|