[Issue 1968] New: boxer.d does not work
Fawzi Mohamed
fmohamed at mac.com
Sun Apr 6 07:32:55 PDT 2008
I had posted into digitalmars.D the proposal to introduce the function
void *dyn_va_arg(in TypeInfo ti,inout va_list argptr)
along with the template va_arg.
Such function would clear up the mess in boxer.d, and I think that such
a function would be nice also for other things.
After having read the gcc ABI on AMD64 where it is made clear that the
treatment of the va_arg depends only on the size, I implemented
dyn_va_arg for sizes up to 42 bytes (easily increasable) using that
assumption.
I think that such a function (maybe extended to all possible cases)
should go in std.stdarg, but for the moment I have modified std.boxer
and put it there.
Indeed the code now is much better, I think that one could also avoid
the transformation to the base type, but for now I have left it in.
I also modified the unit test with a more stringent test (one that
would fail with the previous version).
===================================================================
--- boxer.d (revision 209)
+++ boxer.d (working copy)
@@ -68,10 +68,9 @@
module std.boxer;
private import std.format;
+import std.stdarg;
private import std.string;
private import std.utf;
-version (GNU)
- private import std.stdarg;
/* These functions and types allow packing objects into generic containers
* and recovering them later. This comes into play in a wide spectrum of
@@ -500,9 +499,47 @@
return array;
}
+/+
+ + Template to get arbitrary structures out of va_arg
+ + assumes that all argument of the same size are treated in the same way
+ +/
+void *dyn_va_argT(int s1,int s2)(in TypeInfo ti,inout va_list argptr){
+ static if (s1 <= s2){
+ if (ti.tsize == s1)
+ {
+ struct ms{byte[s1] mse;};
+ return cast(void *)&va_arg!(ms)(argptr);
+ }
+ return dyn_va_argT!(s1+1,s2)(ti,argptr);
+ }
+ else{
+ char[10] str,str2;
+ throw new Exception("hit max size of dyn_va_argT ("~format(str,s2)~
+ "), ti.tsize="~format(str2,ti.tsize));
+ // if you hit this then either increase the getSizes s2 limit or
+ // hope that the follwing hack works
+ //
+ // assumes a stack based storage, and that the pointer to it
+ // can be retrived via cast...
+ void *v=cast(void*)argptr;
+ void **vv=cast(void**)&argptr;
+ *vv=v+ti.tsize;
+ return v;
+ }
+}
+
+/+
+ + Function that return a pointer to the current argument of the va_list
+ + and updates the va_list.
+ + assumes that all argument of the same size are treated in the same way
+ +/
+void *dyn_va_arg(in TypeInfo ti,inout va_list argptr){
+ return dyn_va_argT!(1,42)(ti,argptr);
+}
+
/**
* Box each argument passed to the function, returning an array of boxes.
- */
+ */
Box[] boxArray(...)
{
version (GNU)
@@ -516,29 +553,9 @@
while ( (ttd = cast(TypeInfo_Typedef) ti) !is null )
ti = ttd.base;
-
- if (ti is typeid(float))
- {
- float f = va_arg!(float)(_argptr);
- array[index] = box(ti_orig, cast(void *) & f);
- }
- else if (ti is typeid(char) || ti is typeid(byte) || ti is
typeid(ubyte))
- {
- byte b = va_arg!(byte)(_argptr);
- array[index] = box(ti_orig, cast(void *) & b);
- }
- else if (ti is typeid(wchar) || ti is typeid(short) || ti
is typeid(ushort))
- {
- short s = va_arg!(short)(_argptr);
- array[index] = box(ti_orig, cast(void *) & s);
- }
- else if (ti is typeid(bool))
- {
- bool b = va_arg!(bool)(_argptr);
- array[index] = box(ti_orig, cast(void *) & b);
- }
- else
- array[index] = box(ti_orig, cast(void*) _argptr);
+
+ void *p=dyn_va_arg(ti,_argptr);
+ array[index] = box(ti, p);
}
return array;
@@ -797,7 +814,7 @@
if (isArrayTypeInfo(value.type))
return (*cast(void[]*) value.data).ptr;
if (cast(TypeInfo_Class) value.type)
- return *cast(Object*) value.data;
+ return cast(T)(*cast(Object*) value.data);
throw new UnboxException(value, typeid(T));
}
@@ -891,13 +908,13 @@
assert(unboxTest!(ireal)(box(45i)) == 45i);
/* Create an array of boxes from arguments. */
- Box[] array = boxArray(16, "foobar", new Object);
+ Box[] array = boxArray(new Object, "foobar",16);
assert(array.length == 3);
- assert(unboxTest!(int)(array[0]) == 16);
+ assert(unboxTest!(Object)(array[0]) !is null);
assert(unboxTest!(char[])(array[1]) == "foobar");
- assert(unboxTest!(Object)(array[2]) !is null);
-
+ assert(unboxTest!(int)(array[2]) == 16);
+
/* Convert the box array back into arguments. */
TypeInfo[] array_types;
void* array_data;
===================================================================
More information about the D.gnu
mailing list