Boost logo

Boost :

From: Neil Mayhew (neil_mayhew_at_[hidden])
Date: 2008-05-29 01:54:47


On 2008-05-27 23:58, Roland Schwarz wrote:
> I have buffer in terms of char, i.e. char buffer[]. This buffer is not
> from stream, file or socket. It comes from a fifo in my application.

If you are using a FIFO, then I assume the data is originating on the
same machine. In which case, there should be no need to use endian, as
you can arrange that the endianness, and even the alignment, is native
to the machine.

> The I want to make use of the buffer as:
>
> if (type == id_foo) {
> foo& f(*reinterpret_cast<foo*>(&buffer[0]));
> ... do something with foo ...
> }
>
> And I think this is not only ugly but also unnecessary, since foo
> already might be expressed in terms of char[]. If not, e.g. because
> foo is not made of unaligned data, I'd prefer a compiler error instead.
>
> Yes of course I always can do the reinterpret_cast, but if we can do
> better, why shouldn't we?

I think reinterpret_cast is the honest thing to do, because that is
actually what you are doing, reinterpreting a memory location. Just
because an endian is defined in terms of chars internally, that's not
actually what it is. Also, people reading your code will find it easier
to understand what is going on if they see the reinterpret_cast, since
this sort of poking around in memory, based on a type id, conventionally
uses reinterpret_cast. It may be a little long-winded, but it's not
necessarily ugly, just explicit.

Maybe your use case isn't really suited to endian, and you should
instead define a few functions like the load_big_endian that's in the
detail section of endian.hpp. Then you could write:

if (type == id_foo) {
    u_int32_t f(load_big_endian<u_int32_t, 24>(&buffer[0]));

Another possibility would be to put this f in a union:

struct data
{
    int8_t type;
    union {
       ubig24_t f;
       ubig32_t g;
       my_type h;
       // etc.
    };
};

However, I realise this may not fit your data. Have you looked at boost
serialization? That might fit your needs better. Endian is designed for
when a block of data is fetched in one go, and you want to map a complex
structure directly over it, without fiddling with pointers and offsets.

> Btw. read(&foo, sizeof(foo)) also will need to do an equivalent of
> reinterpret cast internally. Doesn't it?

I meant the POSIX read which has a void* parameter for the buffer.
fstream's read uses char*, and so would need a reinterpret_cast.

--Neil


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk