www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Getting byte size of POD classes and dynamic arrays

reply Byron Heads <byron.heads gmail.com> writes:
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
parent reply 1100110 <0b1100110 gmail.com> writes:
On 05/16/2013 08:09 AM, Byron Heads wrote:
 I am working on d-leveldb wrapper (https://github.com/bheads/d-leveldb)=
=20
 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=20
 classes.
=20
 I can get the right size for 1D dynamic arrays, need a way to compute t=
he=20
 total size.
=20
 POD Classes always give me the size of the ref, is it possible?
=20
 -Byron
__traits(classInstanceSize, MyClass); ?
May 16 2013
next sibling parent reply Byron Heads <byron.heads gmail.com> writes:
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
next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
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
parent Byron Heads <byron.heads gmail.com> writes:
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
prev sibling parent 1100110 <0b1100110 gmail.com> writes:
On 05/16/2013 08:21 AM, Byron Heads wrote:
 On Thu, 16 May 2013 08:11:35 -0500, 1100110 wrote:
=20
 On 05/16/2013 08:09 AM, Byron Heads wrote:
 I am working on d-leveldb wrapper (https://github.com/bheads/d-leveld=
b)
 and I need to be able to pass blocks of data between D and leveldb AP=
I.
 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); ?
=20 I missed that one, in my test it returns 29 bytes, 8 for __vptr 8 for __monitor 13 for data =20 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/r= est.d or final class MyPodClass {} ? And yeah, if you get stuck, std.traits is a really rich resource. =3DD Good luck!
May 16 2013
prev sibling parent reply Byron Heads <byron.heads gmail.com> writes:
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
next sibling parent reply Byron Heads <byron.heads gmail.com> writes:
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
parent "bearophile" <bearophileHUGS lycos.com> writes:
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
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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
May 16 2013