Thread overview
data mapping, more elegant solution?
Dec 13, 2007
mandel
Dec 13, 2007
Regan Heath
Dec 13, 2007
mandel
Dec 13, 2007
Regan Heath
Dec 13, 2007
Regan Heath
Dec 13, 2007
Mike
Dec 13, 2007
0ffh
December 13, 2007
Hi,

I want to map a uint to a position of an ubyte array.
Atm. I use this:

ubyte[8] array;
*cast(uint*) &array.ptr[0] = 42;

But is there a nicer solution to do achive this?

Smth. like  "array[0..4] = 42;", but this tries to assign 42 to every byte (resulting in [0x2a, 0x2a, 0x2a, 0x2a, 0x00, 0x00, 0x00, 0x00]).
December 13, 2007
mandel wrote:
> Hi,
> 
> I want to map a uint to a position of an ubyte array.
> Atm. I use this:
> 
> ubyte[8] array;
> *cast(uint*) &array.ptr[0] = 42;
> 
> But is there a nicer solution to do achive this?
> 
> Smth. like  "array[0..4] = 42;", but this tries to assign 42 to every byte (resulting in [0x2a, 0x2a, 0x2a, 0x2a, 0x00, 0x00, 0x00, 0x00]).

Use a union?

union thing
{
  ubyte[8] ub;
  uint     ui;
}

void main()
{
  thing a;
  a.ui = 42;
}

Regan
December 13, 2007
On Thu, 13 Dec 2007 13:35:35 +0000, Regan Heath wrote:
> Use a union?
> 
> union thing
> {
>    ubyte[8] ub;
>    uint     ui;
> }
> 
> void main()
> {
>    thing a;
>    a.ui = 42;
> }
> 
This way I can't insert data at arbitrary places, e.g. array[4..8].
I also would have to cast thing to ubyte[8] when I pass it to functions.
It's also hackish. :P
December 13, 2007
mandel wrote:
> On Thu, 13 Dec 2007 13:35:35 +0000, Regan Heath wrote:
>> Use a union?
>>
>> union thing
>> {
>>    ubyte[8] ub;
>>    uint     ui;
>> }
>>
>> void main()
>> {
>>    thing a;
>>    a.ui = 42;
>> }
>>
> This way I can't insert data at arbitrary places, e.g. array[4..8].
> I also would have to cast thing to ubyte[8] when I pass it to functions.
> It's also hackish. :P

If you want to insert a 'short' into it then add an array of shorts too:

union thing
{
   ubyte[8]  ub;
   ushort[2] us;
   uint      ui;
}

thing a;

a.us[0] = 1; //ub[0..4]
a.us[1] = 2; //ub[4..8]

It's less hackish, and cleaner/clearer than using casts.

Regan
December 13, 2007
On Thu, 13 Dec 2007 14:43:51 +0100, mandel <oh@no.es> wrote:

> On Thu, 13 Dec 2007 13:35:35 +0000, Regan Heath wrote:
>> Use a union?
>>
>> union thing
>> {
>>    ubyte[8] ub;
>>    uint     ui;
>> }
>>
>> void main()
>> {
>>    thing a;
>>    a.ui = 42;
>> }
>>
> This way I can't insert data at arbitrary places, e.g. array[4..8].
> I also would have to cast thing to ubyte[8] when I pass it to functions.
> It's also hackish. :P

Then pack the hackish things away into something:

struct thing
{
    union
    {
        ubyte[8] ub;
        uint ui;
    }

    void opAssign(uint value)
    {
        ui = value;
    }

    uint opCall()
    {
        return value;
    }

    void opIndexAssign(byte value, uint idx)
    {
        ub[idx] = value;
    }

    byte opIndex(uint idx)
    {
        return ub[idx];
    }
}

Better? You can pass that to functions. For arbitrary places you're either stuck with the casting or you maybe can do something with opSlice.

-Mike

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
December 13, 2007
Regan Heath wrote:
> mandel wrote:
>> On Thu, 13 Dec 2007 13:35:35 +0000, Regan Heath wrote:
>>> Use a union?
>>>
>>> union thing
>>> {
>>>    ubyte[8] ub;
>>>    uint     ui;
>>> }
>>>
>>> void main()
>>> {
>>>    thing a;
>>>    a.ui = 42;
>>> }
>>>
>> This way I can't insert data at arbitrary places, e.g. array[4..8].
>> I also would have to cast thing to ubyte[8] when I pass it to functions.
>> It's also hackish. :P
> 
> If you want to insert a 'short' into it then add an array of shorts too:
> 
> union thing
> {
>    ubyte[8]  ub;
>    ushort[2] us;
>    uint      ui;
> }
> 
> thing a;
> 
> a.us[0] = 1; //ub[0..4]
> a.us[1] = 2; //ub[4..8]
> 
> It's less hackish, and cleaner/clearer than using casts.

I must have been half asleep when I posted that.  I got the sizes confused.  You have 64 bits of data, so your complete union would look something like:

union thing
{
  ubyte[8]	ub;
  ushort[4]	us;
  uint[2]	ui;
  ulong		ul;
}

I got the assignments correct though, a.us[0] assigns to a.ub[0..4] and so on.  You may need to deal with big/little endian issues, not sure.

If you really hate the union and would rather use a cast I suggest:

ubyte[8] array;

(cast(uint*)&array)[0] = 1;  //array[0..4]
(cast(uint*)&array)[1] = 2;  //array[4..8]

I think that works, I don't have a compiler here to test it, it might need to be:

(cast(uint*)&array)[0..2][0] = 1;  //array[0..4]
(cast(uint*)&array)[0..2][1] = 2;  //array[4..8]

The above creates a temporary dynamic array of type uint with length == 2, which is less efficient than the union .. and more typing too.

Regan
December 13, 2007
mandel wrote:
> Hi,
> 
> I want to map a uint to a position of an ubyte array.
> Atm. I use this:
> 
> ubyte[8] array;
> *cast(uint*) &array.ptr[0] = 42;
> 
> But is there a nicer solution to do achive this?
> 
> Smth. like  "array[0..4] = 42;", but this tries to assign 42 to every byte (resulting in [0x2a, 0x2a, 0x2a, 0x2a, 0x00, 0x00, 0x00, 0x00]).

Well, if "array[0..4]=42;" does what you say, I think it does the right
thing. Your solution is the right one, altough I'd use more braces.
It's hard to be more elegant when crossing type boundaries. Some other
languages I could mention would not even allow the canonical C solution
(which is what you are doing)...

regards, frank