Boost logo

Boost :

From: Neil Mayhew (neil_mayhew_at_[hidden])
Date: 2008-05-26 16:31:24


On 24/05/08 05:45 AM Beman Dawes wrote:
> Neil Mayhew wrote:
>> The areas that I am interested in seeing more work done on are (1)
>> making constructors "conditional" and (2) adding a bit-range access
>> method.
>>
> * Should there be a way (#ifdef? separate class?) to provide an
> interoperable version that meets C++03 POD requirements, so endian
> objects can be put in unions? Is that what you mean by (1)?

Yes, this is what I meant. I was thinking that the most elegant solution
would be to have a base class that contains everything except the
constructors, and a derived class that adds the constructors (I think
this was in a post in 2006). The typedefs to big32_t etc. would then be
#if'd to correspond to the POD or non-POD classes as desired. I think
this is better than putting the #if's around the constructors themselves.

> Do you have a proposed design for bit-range access?

I was thinking of adding methods to read and write the given bits within
the value:

value_type endian::bits(std::size_t offset, std::size_t length) const;
value_type endian::bits(std::size_t offset, std::size_t length,
value_type value);

Making these template methods with offset and length being template
arguments might allow for more compile-time unrolling, but since these
methods just do shifting and masking, the compiler will probably do all
the needed optimization anyway.

A better design might be to specialize Bitfield to accept endians,
although I haven't studied Bitfield enough yet to see how well this
would work.

> What is the use case or motivation for bit-range access?

A packed binary structure like the following. The numbers are lengths in
bits, and the total length is 24 bits (ie 3 bytes):

+------------+-----------+------------+
| field_a:6 | field_b:4 | field_c:14 |
+------------+-----------+------------+

This may look contrived, but I have seen plenty of things similar to
this in protocols and data files.

As part of a bigger struct, this would be implemented using endian::bits
as follows:

struct packet
{
    ubig24_t abc;

    uint_least32_t field_a() const
    {
       return abc.bits(0, 6);
    }
    uint_least32_t field_b() const
    {
       return abc.bits(6, 4);
    }
    uint_least32_t field_b() const
    {
       return abc.bits(10, 14);
    }
    uint_least32_t field_a(uint_least32_t v)
    {
       return abc.bits(0, 6, v);
    }
    uint_least32_t field_b(uint_least32_t v)
    {
       return abc.bits(6, 4, v);
    }
    uint_least32_t field_b(uint_least32_t v)
    {
       return abc.bits(10, 14, v);
    }
};

If the design used Bitfield instead, there would be one access method
for both read and write, which would return by value a Bitfield on abc.
However, the method would need to have both const and non-const
versions, returning a const and non-const Bitfield respectively.
Unfortunately, the Bitfield can't be made a part of the struct because
it would take up space, breaking the mapping of the memory. So there
would be an inconsistency with the syntax for accessing other (non-bit)
fields within the structure, ie with and without parens, but I can live
with that.

--Neil


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