Thread overview
Getting byte size of POD classes and dynamic arrays
May 16, 2013
Byron Heads
May 16, 2013
1100110
May 16, 2013
Byron Heads
May 16, 2013
bearophile
May 16, 2013
Byron Heads
May 16, 2013
1100110
May 16, 2013
Byron Heads
May 16, 2013
Byron Heads
May 16, 2013
bearophile
May 16, 2013
Andrej Mitrovic
May 16, 2013
I am working on d-leveldb wrapper (https://github.com/bheads/d-leveldb) and I need to be able to pass blocks of data between D and leveldb API. I am having rouble getting the byte size of dynamic arrays and POD classes.

I can get the right size for 1D dynamic arrays, need a way to compute the total size.

POD Classes always give me the size of the ref, is it possible?

-Byron

You can see in my example code:
----------------------------
module sizeof;

import std.stdio,
        std.traits;

align(1)
struct SBlock
{
    ubyte b[13];
}

align(1)
class CBlock
{
    ubyte b[13];
}

size_t size(P)(in P p)
{
	// Working so far
    static if(isStaticArray!P || isBasicType!P || isPODStruct!P)
		return P.sizeof;
	// works if *p is not another pointer,
    else static if(isPointer!P)
		return typeof(*p).sizeof;
	// works on 1D arrays
    else static if(isDynamicArray!P)
		return (p.length ? typeof(p[0]).sizeof * p.length : 0 );
	// does not work, only gets size of the class ref
    else static if(__traits(isPOD, P) && is(P == class))
		return typeid(P).tsize;
    else assert(0);
}

template isPODStruct(T)
{
    static if(is(T == struct))
        enum isPODStruct = __traits(isPOD, T);
    else
        enum isPODStruct = false;
}

@property
void Size(alias V)()
{
    writeln(V, ": ", size(V));
}


void main()
{
    Size!55;
    Size!"Hello World";

    Size!(SBlock());

    auto c = new CBlock();
    Size!c;

    real x = 3.14;
    writeln(x, ": ", size(&x));
    auto _x = &x;
    Size!_x;
    writeln(x, ": ", size(&_x));

    ubyte[5][5] a;
    Size!a;

    ubyte[2][2][3] b;
    Size!b;

    ubyte[][] d;
    d ~= [1, 2, 3, 4, 5];
    d ~= [6, 7, 8];
    Size!d;

    SBlock[] e;
    e ~= SBlock();
    e ~= SBlock();
    Size!e;

    SBlock[][] f;
    f ~= [SBlock()];
    f ~= [SBlock()];
    Size!f;
}
s
-------------------------
5: 4
Hello World: 11
SBlock([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]): 13
sizeof.CBlock: 8
3.14: 16
7FFF51B64820: 16
3.14: 8
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0,
0, 0, 0, 0]]: 25
[[[0, 0], [0, 0]], [[0, 0], [0, 0]], [[0, 0], [0, 0]]]: 12
[[1, 2, 3, 4, 5], [6, 7, 8]]: 32
[SBlock([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), SBlock([0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0])]: 26
[[SBlock([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])], [SBlock([0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0])]]: 32




May 16, 2013
On 05/16/2013 08:09 AM, Byron Heads wrote:
> I am working on d-leveldb wrapper (https://github.com/bheads/d-leveldb) and I need to be able to pass blocks of data between D and leveldb API. I am having rouble getting the byte size of dynamic arrays and POD classes.
> 
> I can get the right size for 1D dynamic arrays, need a way to compute the total size.
> 
> POD Classes always give me the size of the ref, is it possible?
> 
> -Byron


__traits(classInstanceSize, MyClass); ?



May 16, 2013
On Thu, 16 May 2013 08:11:35 -0500, 1100110 wrote:

> On 05/16/2013 08:09 AM, Byron Heads wrote:
>> I am working on d-leveldb wrapper (https://github.com/bheads/d-leveldb) and I need to be able to pass blocks of data between D and leveldb API. I am having rouble getting the byte size of dynamic arrays and POD classes.
>> 
>> I can get the right size for 1D dynamic arrays, need a way to compute the total size.
>> 
>> POD Classes always give me the size of the ref, is it possible?
>> 
>> -Byron
> 
> 
> __traits(classInstanceSize, MyClass); ?

I missed that one, in my test it returns 29 bytes,
8 for __vptr
8 for __monitor
13 for data

now I am wondering way a POD has a vtable.  Either way its not safe to store a byte copy in to leveldb
May 16, 2013
Byron Heads:

> now I am wondering way a POD has a vtable.

In D global structs are PODs, while classe instances are are not PODs.

All classes have a vtable because they inherit some methods from the Object class.

Bye,
bearophile
May 16, 2013
On 05/16/2013 08:21 AM, Byron Heads wrote:
> On Thu, 16 May 2013 08:11:35 -0500, 1100110 wrote:
> 
>> On 05/16/2013 08:09 AM, Byron Heads wrote:
>>> I am working on d-leveldb wrapper (https://github.com/bheads/d-leveldb) and I need to be able to pass blocks of data between D and leveldb API. I am having rouble getting the byte size of dynamic arrays and POD classes.
>>>
>>> I can get the right size for 1D dynamic arrays, need a way to compute the total size.
>>>
>>> POD Classes always give me the size of the ref, is it possible?
>>>
>>> -Byron
>>
>>
>> __traits(classInstanceSize, MyClass); ?
> 
> I missed that one, in my test it returns 29 bytes,
> 8 for __vptr
> 8 for __monitor
> 13 for data
> 
> now I am wondering way a POD has a vtable.  Either way its not safe to store a byte copy in to leveldb

Why not just use a struct?  .sizeof gives those accurately.  Oh you wanted both...

Maybe take a look at vibe's rest interface?  It extracts the members of classes and does funny things with them.  Can't say I understand it. Over my head...

https://github.com/rejectedsoftware/vibe.d/blob/master/source/vibe/http/rest.d

or
final class MyPodClass {} ?

And yeah, if you get stuck, std.traits is a really rich resource. =D


Good luck!



May 16, 2013
On Thu, 16 May 2013 15:32:35 +0200, bearophile wrote:

> Byron Heads:
> 
>> now I am wondering way a POD has a vtable.
> 
> In D global structs are PODs, while classe instances are are not PODs.
> 
> All classes have a vtable because they inherit some methods from the Object class.
> 
> Bye,
> bearophile

Thanks, I will just block them since they are unsafe for a database.
May 16, 2013
On Thu, 16 May 2013 08:11:35 -0500, 1100110 wrote:
> 
> __traits(classInstanceSize, MyClass); ?

Any ideas on how to get the element type of an array
ie:   int[]  -> int   int[][]  -> int[]

I am going to block dynamic arrays with more then 1D, since they are holding pointers in the data block



May 16, 2013
On Thu, 16 May 2013 13:49:51 +0000, Byron Heads wrote:

> On Thu, 16 May 2013 08:11:35 -0500, 1100110 wrote:
>> 
>> __traits(classInstanceSize, MyClass); ?
> 
> Any ideas on how to get the element type of an array ie:   int[]  -> int
>   int[][]  -> int[]
> 
> I am going to block dynamic arrays with more then 1D, since they are holding pointers in the data block

Found ForeachType!T  this seems to do the trick.  Not the most initiative name for the function but works for my case.

Thanks for the help
May 16, 2013
Byron Heads:

> Not the most initiative name for the function but works for my case.<

It has a strange name because a string (that is a dynamic array) iterated as range (like by map()) has a type different from the same iterated on default with foreach...

Bye,
bearophile
May 16, 2013
On 5/16/13, Byron Heads <byron.heads@gmail.com> wrote:
> On Thu, 16 May 2013 08:11:35 -0500, 1100110 wrote:
>>
>> __traits(classInstanceSize, MyClass); ?
>
> Any ideas on how to get the element type of an array
> ie:   int[]  -> int   int[][]  -> int[]

Try the ElementType template in std.range. There's also ElementEncodingType