October 24, 2006
Ever wondered about the capacity of an array?

# import internal.gc.gcbits;
# import internal.gc.gclinux;
# import internal.gc.gcx;
# import std.gc;
#
# /* return the maximum number of storable elements that
#  * would cause no relocation
#  *
#  * 0 for memory not allocated via the GC
#  *
#  * array/pointer kludge: "specialization not allowed for deduced parameter"
#  */
# template getCapacity(T){
#    size_t getCapacity(T data){
#       gc_t engine = cast(gc_t) getGCHandle();
#       static if(isArrayType!(T)){
#          // plain array
#          size_t size = engine.capacity(data.ptr);
#          return size ? (size / data[0].sizeof) - 1 : 0;
#       }else static if(is(T : void*)){
#          // pointer
#          size_t size = engine.capacity(data);
#          return size ? (size / data[0].sizeof) - 1 : 0;
#       }else static if(is(typeof(data.length))
#             && is(typeof(data.rehash) == T)
#             && is(typeof(data.keys))
#             && is(typeof(data.values))
#             && !is(typeof(data.ptr))
#             )
#       {
#          // most likely an associative array
#          return data.length;
#       }else{
#          static assert(0, "neither array nor pointer");
#       }
#    }
# }
#
# template isArrayType( T )       { const bool isArrayType = false; }
# template isArrayType( T : T[] ) { const bool isArrayType = true;  }
#

usage sample:

# import std.stdio, std.c.stdlib;
#
# int main(){
#    writefln("test\t\tcapacity\tcomment");
#    writefln("----");
#
#    short[char[]] aa;
#    aa["eins"] = 1;
#    aa["sechs"] = 6;
#    writefln("aa(2)\t\t%s", getCapacity(aa));
#    aa["vier"] = 4;
#    writefln("aa(3)\t\t%s", getCapacity(aa));
#
#    writefln("----");
#
#    dchar[] array = "Hallo";
#    writefln("literal\t\t%s", getCapacity(array));
#
#    writefln("----");
#
#    array = new dchar[5];
#    writefln("dynamic(5)\t%s\t(stored at 0x%X)", getCapacity(array), array.ptr);
#    array.length = 7;
#    writefln("dynamic(7)\t%s\t(stored at 0x%X)", getCapacity(array), array.ptr);
#    array.length = 8;
#    writefln("dynamic(8)\t%s\t(stored at 0x%X)", getCapacity(array), array.ptr);
#    array.length = 1;
#    writefln("dynamic(1)\t%s\t(stored at 0x%X)", getCapacity(array), array.ptr);
#
#    writefln("----");
#
#    array = (cast(dchar*)std.c.stdlib.malloc(5 * dchar.sizeof))[0 .. 4];
#    writefln("malloced\t%s", getCapacity(array));
#
#    return 0;
# }

output:

> test            capacity        comment
> ----
> aa(2)           2
> aa(3)           3
> ----
> literal         0
> ----
> dynamic(5)      7       (stored at 0xF7C86F80)
> dynamic(7)      7       (stored at 0xF7C86F80)
> dynamic(8)      15      (stored at 0xF7C87FC0)
> dynamic(1)      15      (stored at 0xF7C87FC0)
> ----
> malloced        0

Thomas