Boost logo

Boost :

Subject: Re: [boost] [endian] endian flip and endian domain
From: Stewart, Robert (Robert.Stewart_at_[hidden])
Date: 2010-06-09 07:39:15


Gottlob Frege wrote:
> On Tue, Jun 8, 2010 at 12:59 PM, Stewart, Robert
> <Robert.Stewart_at_[hidden]> wrote:
> > Gottlob Frege wrote:
> >> On Tue, Jun 8, 2010 at 11:52 AM, Stewart, Robert
> >> <Robert.Stewart_at_[hidden]> wrote:
> >> >>
> >> > It would be possible to also include the cases in which the
> >> > input and output endiannesses are specified (the filter
> >> > case), but those lead right back to confusion about the
> >> > template argument order.
> >>
> >> Technically, the output endianness would take the place of the int.
> >
> > That doesn't fit the pattern because the result is an int,
> > not a "big endian," for example. Hence the cast is to int first.
>
> If you are explicitly converting with a from_type and a to_type, then
> (to me) the result is not actually an int, but a to_type. If you want
> to store it into an int, then cast it as one, or use to_type.raw().

Here we must diverge, at least partially. For me, the point of any conversion is to get usable data. The object-based approach achieves this by providing access to a specifically ordered value each time it is requested, whether that involves a conversion or not. The function-based approach achieves this by replacing a value with the desired order (in-place) or by returning the value with the desired order. The function-based approach should always result in a client type T ready to use.

I see no point in wrapping T in something to call a function that will, potentially, change its order and return a wrapped T when the point of the conversion is to get a usable T. Doing otherwise simply clutters the interface and requires an additional step from the client.

> >> But then you'd need a secondary cast, I suppose. ie
> >>
> >> big j = endian_cast<big, little>(k);
> >> int i = reinterpret_cast<int>(endian_cast<big, little>(k));
> >
> > Those aren't casts following the pattern of the new-style
> > casts in the language.
>
> Sorry if I wasn't clear, or don't understand - in my mind, k was

The particular point I was raising is the two template arguments for endian_cast in the above not being new-style cast compatible.

> typed/stored/declared as an int, it is holding a little-endian value
> that needs to be converted to big endian, then stored as another int
> (i).
>
> so
> int k = some_little_endian_int();
> int i = reinterpret_cast<int>(endian_cast<big, little>(k));
> or
> int i = endian_cast<big, little>(k).raw(); // interpret k as little,
> convert/cast to big, return raw (big) data.

This example illustrates the extra syntax I don't want. Here's the simpler version of what you've shown:

   int const k(get_little_endian_int());
   int const i(convert_to<big_endian>(k));

With a wrapper type, that might look like this:

   endian_wrapper<int,little_endian> k(get_little_endian_int());
   int const i(endian_cast<int>(k));

It's probably not unreasonable to support both.

> >> wrapper.data() // raw data. or raw_data() or raw() or...
> >> wrapper.value() // converted to host *value*
> >
> > I could live with raw() and host(). In fact, the copying
> > conversion logic could actually be on that class:
> >
> > w.convert<big_endian>();
> > w.convert<little_endian>();
> > w.raw();
>
> Yes for the object-based approach. I like forcing everyone to use
> endian_cast<> but I can live with the above as well.

If endian_wrapper is found a reasonable means to indicate endianness assumptions, and the object-based approach is based upon endian_wrapper, then the conversion logic, other than that for in-place reordering, can be put in one place.

> >> convert_from<big_endian>()
> >> is slightly nicer, but
> >> endian_cast<T, big_endian>()
> >> isn't really much worse (only 2 characters! (not really...))
> >
> > Actually, you're comparing those wrong.
> > convert_from<big_endian>() means convert from big endian to
> > host order. The equivalent cast requires knowing the host
> > order: endian_cast<T, native_endian>(). I like the former
> > better because it reads nicely, not just that it is shorter.
>
> to me
>
> endian_cast<int>(e)
>
> takes a known endian type and converts to a host int. ie e was
> previously declared to be a big_endian or something. Thus
>
> endian_cast<int, big_endian>(i)
>
> takes an int (I suppose), reinterprets it as a big_endian, then
> converts (swaps if necessary) it to an int. The 'int' in the cast is
> for the return type, not the input type of i. I wonder if this is the
> source of confusion?

I don't like that at all. Not only does it violate cast syntax with the extra template argument, but one dictates the result type and the other the input endianness. This would be a major source of confusion.

I'd say this is the purview of convert_to/from rather than endian_cast. Thus, convert_from<big_endian>(i) would return a host order object of i's type, assuming i to be in big_endian form. The question is whether convert_to/from should accept unwrapped types. (More below.)

> If i is not an int, (in particular, if i is an
> endian type?) I'm not sure what it should do. And, as mentioned
>
> endian_cast<little_endian, big_endian>(i)
>
> takes an int, reinterprets it as a big_endian, converts it to a
> little_endian, returning a little_endian.

I don't see the point of that. Surely the endian types can provide converting constructors.

> endian_cast<little_endian, big_endian>(i).raw();
>
> as above, returning an "int". At least an int by declaration
> and storage.

That's an interesting case, but I don't like using a cast for it. Perhaps the following, more verbose incantation would be appropriate:

   convert_to<little_endian>(endian_wrapper<int,big_endian>(i));

That makes the big endian assumption about i explicit. Of course that could be made prettier with the following:

   template <class T>
   endian_wrapper<T,big_endian>
   as_big_endian(T _value)
   {
      return endian_wrapper<T,big_endian>(_value);
   }

   convert_to<little_endian>(as_big_endian(i));

> Is the above 4 cases clear/consistent/explicit? It wasn't completely
> formed in my mind at the start of this all, so thanks for the
> back-and-forth.

I think I understand you better. I hope I've made my concerns clear and that we can soon converge on a concrete proposal of interfaces that others can critique.

_____
Rob Stewart robert.stewart_at_[hidden]
Software Engineer, Core Software using std::disclaimer;
Susquehanna International Group, LLP http://www.sig.com

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.


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