Thread overview
How can I map bytes to a matrix of structures?
Sep 09, 2011
teo
Sep 09, 2011
Timon Gehr
Sep 09, 2011
bearophile
Sep 09, 2011
teo
Sep 09, 2011
teo
Sep 09, 2011
Timon Gehr
September 09, 2011
Here is an example of what I am after:

struct DATA
{
  ubyte D1;
  ubyte D2;
  ubyte D3;
  ubyte D4;
}

void main()
{
  ubyte[16] a = [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01,
0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 ];
  auto b = (cast(DATA*)a.ptr)[0 .. 4];
  auto c = (cast(DATA[]*)b.ptr)[0 .. 2][0 .. 2];
}

I need to have a DATA[2][2]. That code compiles but gives me a segmentation fault.
September 09, 2011
On 09/09/2011 05:19 PM, teo wrote:
> Here is an example of what I am after:
>
> struct DATA
> {
>    ubyte D1;
>    ubyte D2;
>    ubyte D3;
>    ubyte D4;
> }
>
> void main()
> {
>    ubyte[16] a = [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01,
> 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 ];
>    auto b = (cast(DATA*)a.ptr)[0 .. 4];
>    auto c = (cast(DATA[]*)b.ptr)[0 .. 2][0 .. 2];
> }
>
> I need to have a DATA[2][2]. That code compiles but gives me a
> segmentation fault.

If you actually want a dynamic DATA[2][] array of length 2, this works:
auto b=(*(cast(DATA[2][2]*)a.ptr))[];

Otherwise:

A simple reinterpret cast should do:
auto b=*(cast(DATA[2][2]*)a.ptr);

but note that this copies the data, because static arrays have value semantics.

If you want to have refer the new array to the same location, you can use a union.

void main(){
    union Myunion{
	ubyte[16] a = [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01,
			0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 ];
	DATA[2][2] b;
    }
    Myunion myunion;
    assert(*(cast(DATA[2][2]*)myunion.a.ptr)==myunion.b);
}











September 09, 2011
On Fri, 09 Sep 2011 11:43:04 -0400, Timon Gehr <timon.gehr@gmx.ch> wrote:

> On 09/09/2011 05:19 PM, teo wrote:
>> Here is an example of what I am after:
>>
>> struct DATA
>> {
>>    ubyte D1;
>>    ubyte D2;
>>    ubyte D3;
>>    ubyte D4;
>> }
>>
>> void main()
>> {
>>    ubyte[16] a = [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01,
>> 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 ];
>>    auto b = (cast(DATA*)a.ptr)[0 .. 4];
>>    auto c = (cast(DATA[]*)b.ptr)[0 .. 2][0 .. 2];
>> }
>>
>> I need to have a DATA[2][2]. That code compiles but gives me a
>> segmentation fault.
>
> If you actually want a dynamic DATA[2][] array of length 2, this works:
> auto b=(*(cast(DATA[2][2]*)a.ptr))[];
>
> Otherwise:
>
> A simple reinterpret cast should do:
> auto b=*(cast(DATA[2][2]*)a.ptr);
>
> but note that this copies the data, because static arrays have value semantics.
>
> If you want to have refer the new array to the same location, you can use a union.
>
> void main(){
>      union Myunion{
> 	ubyte[16] a = [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01,
> 			0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 ];
> 	DATA[2][2] b;
>      }
>      Myunion myunion;
>      assert(*(cast(DATA[2][2]*)myunion.a.ptr)==myunion.b);
> }

You can also use ref, but you have to use a function, as it's impossible to declare a ref local variable except as a function parameter.

void main()
{
   ubyte[16] a = ...;
   void foo(ref DATA[2][2] b)
   {
      ...
   }
   foo(*(cast(DATA[2][2]*)a.ptr));
}

-Steve
September 09, 2011
Timon Gehr:

> A simple reinterpret cast should do:
> auto b=*(cast(DATA[2][2]*)a.ptr);

I think this is enough:
auto b = cast(Data[2][2])a;

Bye,
bearophile
September 09, 2011
On Fri, 09 Sep 2011 17:43:04 +0200, Timon Gehr wrote:

> On 09/09/2011 05:19 PM, teo wrote:
>> Here is an example of what I am after:
>>
>> struct DATA
>> {
>>    ubyte D1;
>>    ubyte D2;
>>    ubyte D3;
>>    ubyte D4;
>> }
>>
>> void main()
>> {
>>    ubyte[16] a = [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
>>    0x01,
>> 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 ];
>>    auto b = (cast(DATA*)a.ptr)[0 .. 4];
>>    auto c = (cast(DATA[]*)b.ptr)[0 .. 2][0 .. 2];
>> }
>>
>> I need to have a DATA[2][2]. That code compiles but gives me a segmentation fault.
> 
> If you actually want a dynamic DATA[2][] array of length 2, this works:
> auto b=(*(cast(DATA[2][2]*)a.ptr))[];
> 
> Otherwise:
> 
> A simple reinterpret cast should do:
> auto b=*(cast(DATA[2][2]*)a.ptr);
> 
> but note that this copies the data, because static arrays have value semantics.
> 
> If you want to have refer the new array to the same location, you can use a union.
> 
> void main(){
>      union Myunion{
> 	ubyte[16] a = [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x01,
> 			0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 ];
> 	DATA[2][2] b;
>      }
>      Myunion myunion;
>      assert(*(cast(DATA[2][2]*)myunion.a.ptr)==myunion.b);
> }

Thank you Timon for the good explanation.

Just one more question (I suspect the answer will be no, but let me ask): is it possible to directly cast to ubyte[][]?
September 09, 2011
On Fri, 09 Sep 2011 13:10:41 -0400, bearophile wrote:

> Timon Gehr:
> 
>> A simple reinterpret cast should do:
>> auto b=*(cast(DATA[2][2]*)a.ptr);
> 
> I think this is enough:
> auto b = cast(Data[2][2])a;
> 
> Bye,
> bearophile

That works. Thanks.
September 09, 2011
On 09/09/2011 10:25 PM, teo wrote:
> On Fri, 09 Sep 2011 17:43:04 +0200, Timon Gehr wrote:
>
>> On 09/09/2011 05:19 PM, teo wrote:
>>> Here is an example of what I am after:
>>>
>>> struct DATA
>>> {
>>>     ubyte D1;
>>>     ubyte D2;
>>>     ubyte D3;
>>>     ubyte D4;
>>> }
>>>
>>> void main()
>>> {
>>>     ubyte[16] a = [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
>>>     0x01,
>>> 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 ];
>>>     auto b = (cast(DATA*)a.ptr)[0 .. 4];
>>>     auto c = (cast(DATA[]*)b.ptr)[0 .. 2][0 .. 2];
>>> }
>>>
>>> I need to have a DATA[2][2]. That code compiles but gives me a
>>> segmentation fault.
>>
>> If you actually want a dynamic DATA[2][] array of length 2, this works:
>> auto b=(*(cast(DATA[2][2]*)a.ptr))[];
>>
>> Otherwise:
>>
>> A simple reinterpret cast should do:
>> auto b=*(cast(DATA[2][2]*)a.ptr);
>>
>> but note that this copies the data, because static arrays have value
>> semantics.
>>
>> If you want to have refer the new array to the same location, you can
>> use a union.
>>
>> void main(){
>>       union Myunion{
>> 	ubyte[16] a = [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
> 0x01,
>> 			0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 ];
>> 	DATA[2][2] b;
>>       }
>>       Myunion myunion;
>>       assert(*(cast(DATA[2][2]*)myunion.a.ptr)==myunion.b);
>> }
>
> Thank you Timon for the good explanation.

You are welcome. As bearophile suggests, those are nicer though:

auto b=(cast(DATA[2][2]a);  // static array
auto b=(cast(DATA[2][2]a)[];// dynamic array

>
> Just one more question (I suspect the answer will be no, but let me ask):
> is it possible to directly cast to ubyte[][]?

Not directly, because you have to build some structure in memory.

an ubyte[][] is an array of dynamic arrays. Each of those dynamic arrays is a 2 field struct consisting of a ptr and a length field.
That data you have to construct manually.

in case you wanted to turn the ubyte[16] a array to a ubyte[][] b array, with b.length and b[i].length equal to 4, this would probably do the job:

ubyte[16] a=[ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 ];

auto b=new ubyte[][](4);// create a ubyte[][] array that can hold 4 ubyte[] values
foreach(i,ref x;b) x=a[i*4 .. (i+1)*4]; // compute the values by slicing the original array