1 /**
2  * The variant module contains a variant, or polymorphic type.
3  *
4  * Copyright: Copyright (C) 2005-2009 The Tango Team.  All rights reserved.
5  * License:   BSD style: $(LICENSE)
6  * Authors:   Daniel Keep, Sean Kelly
7  */
8 module tango.core.Variant;
9 
10 private import tango.core.Memory : GC;
11 private import tango.core.Vararg;
12 private import tango.core.Traits;
13 private import tango.core.Tuple;
14 
15 private import tango.core.Compiler;
16 
17 private extern(C) Object _d_toObject(void*);
18 
19 /*
20  * This is to control when we compile in vararg support.  Vararg is a complete
21  * pain in the arse.  I haven't been able to test under GDC at all (and
22  * support for it may disappear soon anyway) and LDC refuses to build for me.
23  *
24  * As other compilers are tested and verified to work, they should be added
25  * below.  It would also probably be a good idea to verify the platforms for
26  * which it works.
27  */
28 
29 version( DigitalMars )
30 {
31     version( X86 )
32     {
33         version( Windows )
34         {
35             version=EnableVararg;
36         }
37         else version( Posix )
38         {
39             version=EnableVararg;
40         }
41     }
42     version( X86_64 )
43     {
44         version( Windows )
45         {
46             version=EnableVararg;
47         }
48         else version( Posix )
49         {
50             version=EnableVararg;
51         }
52 
53         version = DigitalMarsX64;
54 
55         import tango.math.Math : max;
56 
57     }
58 }
59 else version( LDC )
60 {
61     version( X86 )
62     {
63         version( linux )
64         {
65             version=EnableVararg; // thanks rawler
66         }
67     }
68     else version( X86_64 )
69     {
70         version( linux )
71         {
72             version=EnableVararg; // thanks mwarning
73         }
74 
75         import tango.math.Math : max;
76     }
77 }
78 else version( DDoc )
79 {
80     // Let's hope DDoc is smart enough to catch this...
81     version=EnableVararg;
82 }
83 
84 version( EnableVararg ) {} else
85 {
86     pragma(msg, "Note: Variant vararg functionality not supported for this " ~
87             "compiler/platform combination.");
88     pragma(msg, "To override and enable vararg support anyway, compile with " ~
89             "the EnableVararg version.");
90 }
91 
92 private
93 {
94     /*
95      * This is used to store the actual value being kept in a Variant.
96      */
97     struct VariantStorage
98     {
99         union
100         {
101             /*
102              * Contains heap-allocated storage for values which are too large
103              * to fit into the Variant directly.
104              */
105             void[] heap;
106 
107             /*
108              * Used to store arrays directly.  Note that this is NOT an actual
109              * array; using a void[] causes the length to change, which screws
110              * up the ptr() property.
111              *
112              * WARNING: this structure MUST match the ABI for arrays for this
113              * platform.  AFAIK, all compilers implement arrays this way.
114              * There needs to be a case in the unit test to ensure this.
115              */
116             struct Array
117             {
118                 size_t length;
119                 const(void)* ptr;
120             }
121             Array array;
122 
123             // Used to simplify dealing with objects.
124             Object obj;
125 
126             // Used to address storage as an array.
127             ubyte[array.sizeof] data;
128         }
129 
130         /*
131          * This is used to set the array structure safely.  We're essentially
132          * just ensuring that if a garbage collection happens mid-assign, we
133          * don't accidentally mark bits of memory we shouldn't.
134          *
135          * Of course, the compiler could always re-order the length and ptr
136          * assignment.  Oh well.
137          */
138         void setArray(const(void)* ptr, size_t length)
139         {
140             array.length = 0;
141             array.ptr = ptr;
142             array.length = length;
143         }
144     }
145 
146     // Determines if the given type is an Object (class) type.
147     template isObject(T)
148     {
149         static if( is( T : Object ) )
150             enum isObject = true;
151         else
152             enum isObject = false;
153     }
154 
155     // Determines if the given type is an interface
156     template isInterface(T)
157     {
158         static if( is( T == interface ) )
159             enum isInterface = true;
160         else
161             enum isInterface = false;
162     }
163 
164     // A list of all basic types
165     alias Tuple!(bool, char, wchar, dchar,
166             byte, short, int, long, //cent,
167             ubyte, ushort, uint, ulong, //ucent,
168             float, double, real,
169             ifloat, idouble, ireal,
170             cfloat, cdouble, creal) BasicTypes;
171 
172     // see isBasicType
173     template isBasicTypeImpl(T, U)
174     {
175         enum isBasicTypeImpl = is( T == U );
176     }
177 
178     // see isBasicType
179     template isBasicTypeImpl(T, U, Us...)
180     {
181         static if( is( T == U ) )
182             enum isBasicTypeImpl = true;
183         else
184             enum isBasicTypeImpl = isBasicTypeImpl!(T, Us);
185     }
186 
187     // Determines if the given type is one of the basic types.
188     template isBasicType(T)
189     {
190         enum isBasicType = isBasicTypeImpl!(T, BasicTypes);
191     }
192 
193     /*
194      * Used to determine if we can cast a value of the given TypeInfo to the
195      * specified type implicitly.  This should be somewhat faster than the
196      * version in RuntimeTraits since we can basically eliminate half of the
197      * tests.
198      */
199     bool canImplicitCastToType(dsttypeT)(const TypeInfo srctype)
200     {
201         /*
202          * First, we'll generate tests for the basic types.  The list of
203          * things which can be cast TO basic types is finite and easily
204          * computed.
205          */
206         foreach( T ; BasicTypes )
207         {
208             // If the current type is the target...
209             static if( is( dsttypeT == T ) )
210             {
211                 // ... then for all of the other basic types ...
212                 foreach( U ; BasicTypes )
213                 {
214                     static if
215                     (
216                         // ... if that type is smaller than ...
217                         U.sizeof < T.sizeof
218 
219                         // ... or the same size and signed-ness ...
220                         || ( U.sizeof == T.sizeof &&
221                             ((isCharType!(T) || isUnsignedIntegerType!(T))
222                              ^ !(isCharType!(U) || isUnsignedIntegerType!(U)))
223                         )
224                     )
225                     {
226                         // ... test.
227                         if( srctype is typeid(U) )
228                             return true;
229                     }
230                 }
231                 // Nothing matched; no implicit casting.
232                 return false;
233             }
234         }
235 
236         /*
237          * Account for static arrays being implicitly convertible to dynamic
238          * arrays.
239          */
240         static if( is( T[] : dsttypeT ) )
241         {
242             if( typeid(T[]) is srctype )
243                 return true;
244 
245             if( auto ti_sa = cast(const(TypeInfo_StaticArray)) srctype )
246                 return ti_sa.next is typeid(T);
247 
248             return false;
249         }
250 
251         /*
252          * Any pointer can be cast to void*.
253          */
254         else static if( is( dsttypeT == void* ) )
255             return (cast(const(TypeInfo_Pointer)) srctype) !is null;
256 
257         /*
258          * Any array can be cast to void[], however remember that it has to
259          * be manually adjusted to preserve the correct length.
260          */
261         else static if( is( dsttypeT == void[] ) )
262             return ((cast(const(TypeInfo_Array)) srctype) !is null)
263                 || ((cast(const(TypeInfo_StaticArray)) srctype) !is null);
264 
265         else return false;
266     }
267 
268     /*
269      * Aliases itself to the type used to return a value of type T out of a
270      * function.  This is basically a work-around for not being able to return
271      * static arrays.
272      */
273     template returnT(T)
274     {
275         static if( isStaticArrayType!(T) )
276             alias typeof(T.dup) returnT;
277         else
278             alias T returnT;
279     }
280 
281     /*
282      * Here are some tests that perform runtime versions of the compile-time
283      * traits functions.
284      */
285 
286     bool isBasicTypeInfo(const(TypeInfo) ti)
287     {
288         foreach( T ; BasicTypes )
289             if( ti is typeid(T) )
290                 return true;
291         return false;
292     }
293 
294     private import RuntimeTraits = tango.core.RuntimeTraits;
295 
296     alias RuntimeTraits.isStaticArray isStaticArrayTypeInfo;
297     alias RuntimeTraits.isClass isObjectTypeInfo;
298     alias RuntimeTraits.isInterface isInterfaceTypeInfo;
299 }
300 
301 /**
302  * This exception is thrown whenever you attempt to get the value of a Variant
303  * without using a compatible type.
304  */
305 class VariantTypeMismatchException : Exception
306 {
307     this(const(TypeInfo) expected, const(TypeInfo) got)
308     {
309         super("cannot convert "~expected.toString()
310                     ~" value to a "~got.toString());
311     }
312 }
313 
314 /**
315  * This exception is thrown when you attempt to use an empty Variant with
316  * varargs.
317  */
318 class VariantVoidVarargException : Exception
319 {
320     this()
321     {
322         super("cannot use Variants containing a void with varargs");
323     }
324 }
325 
326 /**
327  * The Variant type is used to dynamically store values of different types at
328  * runtime.
329  *
330  * You can create a Variant using either the pseudo-constructor or direct
331  * assignment.
332  *
333  * -----
334  *  Variant v = Variant(42);
335  *  v = "abc";
336  * -----
337  */
338 struct Variant
339 {
340     /**
341      * This pseudo-constructor is used to place a value into a new Variant.
342      *
343      * Params:
344      *  value = The value you wish to put in the Variant.
345      *
346      * Returns:
347      *  The new Variant.
348      *
349      * Example:
350      * -----
351      *  auto v = Variant(42);
352      * -----
353      */
354     static Variant opCall(T)(T value)
355     {
356         Variant _this;
357 
358         static if( isStaticArrayType!(T) )
359             _this = value.dup;
360 
361         else
362             _this = value;
363 
364         return _this;
365     }
366 
367     /**
368      * This pseudo-constructor creates a new Variant using a specified
369      * TypeInfo and raw pointer to the value.
370      *
371      * Params:
372      *  type = Type of the value.
373      *  ptr  = Pointer to the value.
374      *
375      * Returns:
376      *  The new Variant.
377      *
378      * Example:
379      * -----
380      *  int life = 42;
381      *  auto v = Variant(typeid(typeof(life)), &life);
382      * -----
383      */
384     static Variant opCall()(const TypeInfo type, void* ptr)
385     {
386         Variant _this;
387         Variant.fromPtr(type, ptr, _this);
388         return _this;
389     }
390 
391     /**
392      * This operator allows you to assign arbitrary values directly into an
393      * existing Variant.
394      *
395      * Params:
396      *  value = The value you wish to put in the Variant.
397      *
398      * Returns:
399      *  The new value of the assigned-to variant.
400      *
401      * Example:
402      * -----
403      *  Variant v;
404      *  v = 42;
405      * -----
406      */
407     Variant opAssign(T)(T value)
408     {
409         static if( isStaticArrayType!(T) )
410         {
411             return (this = value.dup);
412         }
413         else static if( is(T == Variant) )
414         {
415             type = value.type;
416             this.value = value.value;
417             return this;
418         }
419         else
420         {
421             type = typeid(T);
422 
423             static if( isDynamicArrayType!(T) )
424             {
425                 this.value.setArray(value.ptr, value.length);
426             }
427             else static if( isInterface!(T) )
428             {
429                 this.value.obj = cast(Object) value;
430             }
431             else
432             {
433                 /*
434                  * If the value is small enough to fit in the storage
435                  * available, do so.  If it isn't, then make a heap copy.
436                  *
437                  * Obviously, this pretty clearly breaks value semantics for
438                  * large values, but without a postblit operator, there's not
439                  * much we can do.  :(
440                  */
441                 static if( T.sizeof <= this.value.data.length )
442                 {
443                     this.value.data[0..T.sizeof] =
444                         (cast(ubyte*)&value)[0..T.sizeof];
445                 }
446                 else
447                 {
448                     auto buffer = (cast(ubyte*)&value)[0..T.sizeof].dup;
449                     this.value.heap = cast(void[])buffer;
450                 }
451             }
452             return this;
453         }
454     }
455 
456     /**
457      * This member can be used to determine if the value stored in the Variant
458      * is of the specified type.  Note that this comparison is exact: it does
459      * not take implicit casting rules into account.
460      *
461      * Returns:
462      *  true if the Variant contains a value of type T, false otherwise.
463      *
464      * Example:
465      * -----
466      *  auto v = Variant(cast(int) 42);
467      *  assert(   v.isA!(int) );
468      *  assert( ! v.isA!(short) ); // note no implicit conversion
469      * -----
470      */
471     @property bool isA(T)()
472     {
473         return cast(bool)(typeid(T) is type);
474     }
475 
476     /**
477      * This member can be used to determine if the value stored in the Variant
478      * is of the specified type.  This comparison attempts to take implicit
479      * conversion rules into account.
480      *
481      * Returns:
482      *  true if the Variant contains a value of type T, or if the Variant
483      *  contains a value that can be implicitly cast to type T; false
484      *  otherwise.
485      *
486      * Example:
487      * -----
488      *  auto v = Variant(cast(int) 42);
489      *  assert( v.isA!(int) );
490      *  assert( v.isA!(short) ); // note implicit conversion
491      * -----
492      */
493     @property bool isImplicitly(T)()
494     {
495         static if( is( T == class ) || is( T == interface ) )
496         {
497             // Check for classes and interfaces first.
498             if( cast(TypeInfo_Class) type || cast(TypeInfo_Interface) type )
499                 return (cast(T) value.obj) !is null;
500 
501             else
502                 // We're trying to cast TO an object, but we don't have
503                 // an object stored.
504                 return false;
505         }
506         else
507         {
508             // Test for basic types (oh, and dynamic->static arrays and
509             // pointers.)
510             return ( cast(bool)(typeid(T) is type)
511                     || canImplicitCastToType!(T)(type) );
512         }
513     }
514 
515     /**
516      * This determines whether the Variant has an assigned value or not.  It
517      * is simply short-hand for calling the isA member with a type of void.
518      *
519      * Returns:
520      *  true if the Variant does not contain a value, false otherwise.
521      */
522     @property bool isEmpty()
523     {
524         return isA!(void);
525     }
526 
527     /**
528      * This member will clear the Variant, returning it to an empty state.
529      */
530     void clear()
531     {
532         _type = typeid(void);
533         value = value.init;
534     }
535 
536     version( DDoc )
537     {
538         /**
539          * This is the primary mechanism for extracting a value from a Variant.
540          * Given a destination type S, it will attempt to extract the value of the
541          * Variant into that type.  If the value contained within the Variant
542          * cannot be implicitly cast to the given type S, it will throw an
543          * exception.
544          *
545          * You can check to see if this operation will fail by calling the
546          * isImplicitly member with the type S.
547          *
548          * Note that attempting to get a statically-sized array will result in a
549          * dynamic array being returned; this is a language limitation.
550          *
551          * Returns:
552          *  The value stored within the Variant.
553          */
554         @property T get(T)()
555         {
556             // For actual implementation, see below.
557         }
558     }
559     else
560     {
561         @property returnT!(S) get(S)()
562         {
563             alias returnT!(S) T;
564 
565             // If we're not dealing with the exact same type as is being
566             // stored, we fail NOW if the type in question isn't an object (we
567             // can let the runtime do the test) and if it isn't something we
568             // know we can implicitly cast to.
569             if( type !is typeid(T)
570                     // Let D do runtime check itself
571                     && !isObject!(T)
572                     && !isInterface!(T)
573 
574                     // Allow implicit upcasts
575                     && !canImplicitCastToType!(T)(type)
576               )
577                 throw new VariantTypeMismatchException(type,typeid(T));
578 
579             // Handle basic types, since they account for most of the implicit
580             // casts.
581             static if( isBasicType!(T) )
582             {
583                 if( type is typeid(T) )
584                 {
585                     // We got lucky; the types match exactly.  If the type is
586                     // small, grab it out of storage; otherwise, copy it from
587                     // the heap.
588                     static if( T.sizeof <= value.sizeof )
589                         return *cast(T*)(&value);
590 
591                     else
592                         return *cast(T*)(value.heap.ptr);
593                 }
594                 else
595                 {
596                     // This handles implicit coercion.  What it does is finds
597                     // the basic type U which is actually being stored.  It
598                     // then unpacks the value of type U stored in the Variant
599                     // and casts it to type T.
600                     //
601                     // It is assumed that this is valid to perform since we
602                     // should have already eliminated invalid coercions.
603                     foreach( U ; BasicTypes )
604                     {
605                         if( type is typeid(U) )
606                         {
607                             static if( U.sizeof <= value.sizeof )
608                                 return cast(T) *cast(U*)(&value);
609 
610                             else
611                                 return cast(T) *cast(U*)(value.heap.ptr);
612                         }
613                     }
614                     throw new VariantTypeMismatchException(type,typeid(T));
615                 }
616             }
617             else static if( isDynamicArrayType!(T) )
618             {
619                 return (cast(typeof(T.init.ptr)) value.array.ptr)
620                     [0..value.array.length];
621             }
622             else static if( isObject!(T) || isInterface!(T) )
623             {
624                 return cast(T)this.value.obj;
625             }
626             else
627             {
628                 static if( T.sizeof <= this.value.data.length )
629                 {
630                     T result;
631                     (cast(ubyte*)&result)[0..T.sizeof] =
632                         this.value.data[0..T.sizeof];
633                     return result;
634                 }
635                 else
636                 {
637                     T result;
638                     (cast(ubyte*)&result)[0..T.sizeof] =
639                         (cast(ubyte[])this.value.heap)[0..T.sizeof];
640                     return result;
641                 }
642             }
643         }
644     }
645 
646     /**
647      * The following operator overloads are defined for the sake of
648      * convenience.  It is important to understand that they do not allow you
649      * to use a Variant as both the left-hand and right-hand sides of an
650      * expression.  One side of the operator must be a concrete type in order
651      * for the Variant to know what code to generate.
652      */
653     auto opBinary(immutable(char)[] op, T)(T rhs)
654     {
655         mixin("return get!(T) " ~ op ~ " rhs;");
656     }
657 
658     auto opBinaryRight(immutable(char)[] op, T)(T lhs)
659     {
660         mixin("return lhs " ~ op ~ " get!(T);");
661     }
662 
663     Variant opOpAssign(immutable(char)[] op, T)(T value)
664     {
665         mixin("return (this = get!(T) " ~ op ~ " value);");
666     }
667 
668     /**
669      * The following operators can be used with Variants on both sides.  Note
670      * that these operators do not follow the standard rules of
671      * implicit conversions.
672      */
673     int opEquals(T)(T rhs)
674     {
675         static if( is( T == Variant ) )
676             return opEqualsVariant(rhs);
677 
678         else
679             return get!(T) == rhs;
680     }
681 
682     bool opEquals(const ref Variant other) const
683     {
684         return opEqualsVariant(other) != 0;
685     }
686 
687     /* This opCmp is not detectable as one for the purposes of TypeInfo_Struct.xopCmp.
688      * Try doing opCmp(const ref Variant) and opCmp(...). My tests indicate that this may work. */
689     /// ditto
690     int opCmp(T)(T rhs)
691     {
692         static if( is( T == Variant ) )
693             return opCmpVariant(rhs);
694         else
695         {
696             auto lhs = get!(T);
697             return (lhs < rhs) ? -1 : (lhs == rhs) ? 0 : 1;
698         }
699     }
700 
701     /// ditto
702     hash_t toHash() const nothrow @safe
703     {
704         return type.getHash(this.ptr);
705     }
706 
707     /**
708      * Returns a string representation of the type being stored in this
709      * Variant.
710      *
711      * Returns:
712      *  The string representation of the type contained within the Variant.
713      */
714     string toString()
715     {
716         return type.toString();
717     }
718 
719     /**
720      * This can be used to retrieve the TypeInfo for the currently stored
721      * value.
722      */
723     @property const(TypeInfo) type() const nothrow @safe
724     {
725         return _type;
726     }
727 
728     /**
729      * This can be used to retrieve a pointer to the value stored in the
730      * variant.
731      */
732     @property inout(void*) ptr() inout nothrow @trusted
733     {
734         if( type.tsize <= value.sizeof )
735             return &value;
736 
737         else
738             return value.heap.ptr;
739     }
740 
741     version( EnableVararg )
742     {
743         /**
744          * Converts a vararg function argument list into an array of Variants.
745          */
746         static Variant[] fromVararg(const(TypeInfo[]) types, void* args)
747         {
748             auto vs = new Variant[](types.length);
749 
750             foreach( i, ref v ; vs )
751             {
752                 version(DigitalMarsX64)
753                 {
754                     scope void[] buffer = new void[types[i].tsize];
755                     va_arg(*cast(va_list*)&args, cast(TypeInfo)types[i], buffer.ptr);
756                     Variant.fromPtr(types[i], buffer.ptr, v);
757                 }
758                 else
759                 {
760                     args = Variant.fromPtr(types[i], args, v);
761                 }
762             }
763 
764             return vs;
765         }
766 
767         /// ditto
768         static Variant[] fromVararg(...)
769         {
770             return Variant.fromVararg(_arguments, _argptr);
771         }
772 
773         /+
774         /**
775          * Converts an array of Variants into a vararg function argument list.
776          *
777          * This will allocate memory to store the arguments in; you may destroy
778          * this memory when you are done with it if you feel so inclined.
779          */
780         deprecated static void toVararg(Variant[] vars, out TypeInfo[] types, out va_list args)
781         {
782             // First up, compute the total amount of space we'll need.  While
783             // we're at it, work out if any of the values we're storing have
784             // pointers.  If they do, we'll need to tell the GC.
785             size_t size = 0;
786             bool noptr = true;
787             foreach( ref v ; vars )
788             {
789                 auto ti = v.type;
790                 size += (ti.tsize + size_t.sizeof-1) & ~(size_t.sizeof-1);
791                 noptr = noptr && (ti.flags & 2);
792             }
793 
794             // Create the storage, and tell the GC whether it needs to be scanned
795             // or not.
796             auto storage = new ubyte[size];
797             GC.setAttr(storage.ptr,
798                 (GC.getAttr(storage.ptr) & ~GC.BlkAttr.NO_SCAN)
799                 | (noptr ? GC.BlkAttr.NO_SCAN : 0));
800 
801             // Dump the variants into the storage.
802             args = storage.ptr;
803             auto arg_temp = args;
804 
805             types = new TypeInfo[vars.length];
806 
807             foreach( i, ref v ; vars )
808             {
809                 types[i] = v.type;
810                 arg_temp = v.toPtr(arg_temp);
811             }
812         }
813         +/
814     } // version( EnableVararg )
815 
816 private:
817     TypeInfo _type = typeid(void);
818     VariantStorage value;
819 
820     @property const(TypeInfo) type(const(TypeInfo) v)
821     {
822         return (_type = cast(TypeInfo)v);
823     }
824 
825     /*
826      * Creates a Variant using a given TypeInfo and a void*.  Returns the
827      * given pointer adjusted for the next vararg.
828      */
829     static void* fromPtr(const TypeInfo type, void* ptr, out Variant r)
830     in
831     {
832         assert(type !is null);
833     }
834     do
835     {
836         /*
837          * This function basically duplicates the functionality of
838          * opAssign, except that we can't generate code based on the
839          * type of the data we're storing.
840          */
841 
842         if( type is typeid(void) )
843             throw new VariantVoidVarargException;
844 
845         r.type = type;
846 
847         if( isStaticArrayTypeInfo(type) )
848         {
849             /*
850              * Static arrays are passed by-value; for example, if type is
851              * typeid(int[4]), then ptr is a pointer to 16 bytes of memory
852              * (four 32-bit integers).
853              *
854              * It's possible that the memory being pointed to is on the
855              * stack, so we need to copy it before storing it.  type.tsize
856              * tells us exactly how many bytes we need to copy.
857              *
858              * Sadly, we can't directly construct the dynamic array version
859              * of type.  We'll store the static array type and cope with it
860              * in isImplicitly(S) and get(S).
861              */
862             r.value.heap = ptr[0 .. type.tsize].dup;
863         }
864         else
865         {
866             if( isObjectTypeInfo(type)
867                 || isInterfaceTypeInfo(type) )
868             {
869                 /*
870                  * We have to call into the core runtime to turn this pointer
871                  * into an actual Object reference.
872                  */
873                 r.value.obj = _d_toObject(*cast(void**)ptr);
874             }
875             else
876             {
877                 if( type.tsize <= this.value.data.length )
878                 {
879                     // Copy into storage
880                     r.value.data[0 .. type.tsize] =
881                         (cast(ubyte*)ptr)[0 .. type.tsize];
882                 }
883                 else
884                 {
885                     // Store in heap
886                     auto buffer = (cast(ubyte*)ptr)[0 .. type.tsize].dup;
887                     r.value.heap = cast(void[])buffer;
888                 }
889             }
890         }
891 
892         // Compute the "advanced" pointer.
893         return ptr + ( (type.tsize + size_t.sizeof-1) & ~(size_t.sizeof-1) );
894     }
895 
896     /+version( EnableVararg )
897     {
898         /*
899          * Takes the current Variant, and dumps its contents into memory pointed
900          * at by a void*, suitable for vararg calls.
901          *
902          * It also returns the supplied pointer adjusted by the size of the data
903          * written to memory.
904          */
905         void* toPtr(void* ptr)
906         {
907             version( GNU )
908             {
909                 pragma(msg, "WARNING: tango.core.Variant's vararg support has "
910                         "not been tested with this compiler." );
911             }
912             version( LDC )
913             {
914                 pragma(msg, "WARNING: tango.core.Variant's vararg support has "
915                         "not been tested with this compiler." );
916             }
917 
918             if( type is typeid(void) )
919                 throw new VariantVoidVarargException;
920 
921             if( isStaticArrayTypeInfo(type) )
922             {
923                 // Just dump straight
924                 ptr[0 .. type.tsize] = this.value.heap[0 .. type.tsize];
925             }
926             else
927             {
928                 if( isInterfaceTypeInfo(type) )
929                 {
930                     /*
931                      * This is tricky.  What we actually have stored in
932                      * value.obj is an Object, not an interface.  What we
933                      * need to do is manually "cast" value.obj to the correct
934                      * interface.
935                      *
936                      * We have the original interface's TypeInfo.  This gives us
937                      * the interface's ClassInfo.  We can also obtain the object's
938                      * ClassInfo which contains a list of Interfaces.
939                      *
940                      * So what we need to do is loop over the interfaces obj
941                      * implements until we find the one we're interested in.  Then
942                      * we just read out the interface's offset and adjust obj
943                      * accordingly.
944                      */
945                     auto type_i = cast(TypeInfo_Interface) type;
946                     bool found = false;
947                     foreach( i ; this.value.obj.classinfo.interfaces )
948                     {
949                         if( i.classinfo is type_i.info )
950                         {
951                             // Found it
952                             void* i_ptr = (cast(void*) this.value.obj) + i.offset;
953                             *cast(void**)ptr = i_ptr;
954                             found = true;
955                             break;
956                         }
957                     }
958                     assert(found,"Could not convert Object to interface; "
959                             "bad things have happened.");
960                 }
961                 else
962                 {
963                     if( type.tsize <= this.value.data.length )
964                     {
965                         // Value stored in storage
966                         ptr[0 .. type.tsize] = this.value.data[0 .. type.tsize];
967                     }
968                     else
969                     {
970                         // Value stored on heap
971                         ptr[0 .. type.tsize] = this.value.heap[0 .. type.tsize];
972                     }
973                 }
974             }
975 
976             // Compute the "advanced" pointer.
977             return ptr + ( (type.tsize + size_t.sizeof-1) & ~(size_t.sizeof-1) );
978         }
979     } // version( EnableVararg )
980     +/
981 
982     /*
983      * Performs a type-dependant comparison.  Note that this obviously doesn't
984      * take into account things like implicit conversions.
985      */
986     int opEqualsVariant(const ref Variant rhs) const
987     {
988         if( type != rhs.type ) return false;
989         return cast(bool) type.equals(this.ptr, rhs.ptr);
990     }
991 
992     /*
993      * Same as opEqualsVariant except it does opCmp.
994      */
995     int opCmpVariant(Variant rhs)
996     {
997         if( type != rhs.type )
998             throw new VariantTypeMismatchException(type, rhs.type);
999         return type.compare(this.ptr, rhs.ptr);
1000     }
1001 }
1002 
1003 debug( UnitTest )
1004 {
1005     /*
1006      * Language tests.
1007      */
1008 
1009     unittest
1010     {
1011         {
1012             int[2] a;
1013             void[] b = a;
1014             int[]  c = cast(int[]) b;
1015             assert( b.length == 2*int.sizeof );
1016             assert( c.length == a.length );
1017         }
1018 
1019         {
1020             struct A { size_t l; void* p; }
1021             const(char)[] b = "123";
1022             A a = *cast(A*)(&b);
1023 
1024             assert( a.l == b.length );
1025             assert( a.p == b.ptr );
1026         }
1027     }
1028 
1029     /*
1030      * Basic tests.
1031      */
1032 
1033     unittest
1034     {
1035         Variant v;
1036         assert( v.isA!(void), v.type.toString() );
1037         assert( v.isEmpty, v.type.toString() );
1038 
1039         // Test basic integer storage and implicit casting support
1040         v = 42;
1041         assert( v.isA!(int), v.type.toString() );
1042         assert( v.isImplicitly!(long), v.type.toString() );
1043         assert( v.isImplicitly!(ulong), v.type.toString() );
1044         assert( !v.isImplicitly!(uint), v.type.toString() );
1045         assert( v.get!(int) == 42 );
1046         assert( v.get!(long) == 42L );
1047         assert( v.get!(ulong) == 42uL );
1048 
1049         // Test clearing
1050         v.clear();
1051         assert( v.isA!(void), v.type.toString() );
1052         assert( v.isEmpty, v.type.toString() );
1053 
1054         // Test strings
1055         v = "Hello, World!"c;
1056         assert( v.isA!(immutable(char)[]), v.type.toString() );
1057         assert( !v.isImplicitly!(wchar[]), v.type.toString() );
1058         assert( v.get!(immutable(char)[]) == "Hello, World!" );
1059 
1060         // Test array storage
1061         v = [1,2,3,4,5];
1062         assert( v.isA!(int[]), v.type.toString() );
1063         assert( v.get!(int[]) == [1,2,3,4,5] );
1064 
1065         // Make sure arrays are correctly stored so that .ptr works.
1066         {
1067             int[] a = [1,2,3,4,5];
1068             v = a;
1069             auto b = *cast(int[]*)(v.ptr);
1070 
1071             assert( a.ptr == b.ptr );
1072             assert( a.length == b.length );
1073         }
1074 
1075         // Test pointer storage
1076         v = &v;
1077         assert( v.isA!(Variant*), v.type.toString() );
1078         assert( !v.isImplicitly!(int*), v.type.toString() );
1079         assert( v.isImplicitly!(void*), v.type.toString() );
1080         assert( v.get!(Variant*) == &v );
1081 
1082         // Test object storage
1083         {
1084             scope o = new Object;
1085             v = o;
1086             assert( v.isA!(Object), v.type.toString() );
1087             assert( v.get!(Object) is o );
1088         }
1089 
1090         // Test interface support
1091         {
1092             interface A {}
1093             interface B : A {}
1094             class C : B {}
1095             class D : C {}
1096 
1097             A a = new D;
1098             Variant v2 = a;
1099             B b = v2.get!(B);
1100             C c = v2.get!(C);
1101             D d = v2.get!(D);
1102         }
1103 
1104         // Test class/interface implicit casting
1105         {
1106             class G {}
1107             interface H {}
1108             class I : G {}
1109             class J : H {}
1110             struct K {}
1111 
1112             scope a = new G;
1113             scope c = new I;
1114             scope d = new J;
1115             K e;
1116 
1117             Variant v2 = a;
1118             assert( v2.isImplicitly!(Object), v2.type.toString() );
1119             assert( v2.isImplicitly!(G), v2.type.toString() );
1120             assert(!v2.isImplicitly!(I), v2.type.toString() );
1121 
1122             v2 = c;
1123             assert( v2.isImplicitly!(Object), v2.type.toString() );
1124             assert( v2.isImplicitly!(G), v2.type.toString() );
1125             assert( v2.isImplicitly!(I), v2.type.toString() );
1126 
1127             v2 = d;
1128             assert( v2.isImplicitly!(Object), v2.type.toString() );
1129             assert(!v2.isImplicitly!(G), v2.type.toString() );
1130             assert( v2.isImplicitly!(H), v2.type.toString() );
1131             assert( v2.isImplicitly!(J), v2.type.toString() );
1132 
1133             v2 = e;
1134             assert(!v2.isImplicitly!(Object), v2.type.toString() );
1135         }
1136 
1137         // Test doubles and implicit casting
1138         v = 3.1413;
1139         assert( v.isA!(double), v.type.toString() );
1140         assert( v.isImplicitly!(real), v.type.toString() );
1141         assert( !v.isImplicitly!(float), v.type.toString() );
1142         assert( v.get!(double) == 3.1413 );
1143 
1144         // Test storage transitivity
1145         auto u = Variant(v);
1146         assert( u.isA!(double), u.type.toString() );
1147         assert( u.get!(double) == 3.1413 );
1148 
1149         // Test operators
1150         v = 38;
1151         assert( v + 4 == 42 );
1152         assert( 4 + v == 42 );
1153         assert( v - 4 == 34 );
1154         assert( 4 - v == -34 );
1155         assert( v * 2 == 76 );
1156         assert( 2 * v == 76 );
1157         assert( v / 2 == 19 );
1158         assert( 2 / v == 0 );
1159         assert( v % 2 == 0 );
1160         assert( 2 % v == 2 );
1161         assert( (v & 6) == 6 );
1162         assert( (6 & v) == 6 );
1163         assert( (v | 9) == 47 );
1164         assert( (9 | v) == 47 );
1165         assert( (v ^ 5) == 35 );
1166         assert( (5 ^ v) == 35 );
1167         assert( v << 1 == 76 );
1168         assert( 1 << Variant(2) == 4 );
1169         assert( v >> 1 == 19 );
1170         assert( 4 >> Variant(2) == 1 );
1171 
1172         assert( Variant("abc") ~ "def" == "abcdef" );
1173         assert( "abc" ~ Variant("def") == "abcdef" );
1174 
1175         // Test op= operators
1176         v = 38; v += 4; assert( v == 42 );
1177         v = 38; v -= 4; assert( v == 34 );
1178         v = 38; v *= 2; assert( v == 76 );
1179         v = 38; v /= 2; assert( v == 19 );
1180         v = 38; v %= 2; assert( v == 0 );
1181         v = 38; v &= 6; assert( v == 6 );
1182         v = 38; v |= 9; assert( v == 47 );
1183         v = 38; v ^= 5; assert( v == 35 );
1184         v = 38; v <<= 1; assert( v == 76 );
1185         v = 38; v >>= 1; assert( v == 19 );
1186 
1187         v = "abc"; v ~= "def"; assert( v == "abcdef" );
1188 
1189         // Test comparison
1190         assert( Variant(0) < Variant(42) );
1191         assert( Variant(42) > Variant(0) );
1192         assert( Variant(21) == Variant(21) );
1193         assert( Variant(0) != Variant(42) );
1194         assert( Variant("bar") == Variant("bar") );
1195         assert( Variant("foo") != Variant("bar") );
1196 
1197         // Test variants as AA keys
1198         static if(DMDFE_Version != 2065 && DMDFE_Version != 2066)
1199         {
1200             {
1201                 auto v1 = Variant(42);
1202                 auto v2 = Variant("foo");
1203                 auto v3 = Variant(1+2.0i);
1204 
1205                 int[Variant] hash;
1206                 hash[v1] = 0;
1207                 hash[v2] = 1;
1208                 hash[v3] = 2;
1209 
1210                 assert( hash[v1] == 0 );
1211                 assert( hash[v2] == 1 );
1212                 assert( hash[v3] == 2 );
1213             }
1214         }
1215 
1216         // Test AA storage
1217         {
1218             int[char[]] hash;
1219             hash["a"] = 1;
1220             hash["b"] = 2;
1221             hash["c"] = 3;
1222             Variant vhash = hash;
1223 
1224             assert( vhash.get!(int[char[]])["a"] == 1 );
1225             assert( vhash.get!(int[char[]])["b"] == 2 );
1226             assert( vhash.get!(int[char[]])["c"] == 3 );
1227         }
1228     }
1229 
1230     /*
1231      * Vararg tests.
1232      */
1233 
1234     version( EnableVararg )
1235     {
1236         private import tango.core.Vararg;
1237 
1238         unittest
1239         {
1240             class A
1241             {
1242                 @property const(char)[] msg() { return "A"; }
1243             }
1244             class B : A
1245             {
1246                 @property override const(char)[] msg() { return "B"; }
1247             }
1248             interface C
1249             {
1250                 @property const(char)[] name();
1251             }
1252             class D : B, C
1253             {
1254                 @property override const(char)[] msg() { return "D"; }
1255                 @property override const(char)[] name() { return "phil"; }
1256             }
1257 
1258             struct S { int a, b, c, d; }
1259 
1260             Variant[] scoop(...)
1261             {
1262                 return Variant.fromVararg(_arguments, _argptr);
1263             }
1264 
1265             auto va_0 = cast(char)  '?';
1266             auto va_1 = cast(short) 42;
1267             auto va_2 = cast(int)   1701;
1268             auto va_3 = cast(long)  9001;
1269             auto va_4 = cast(float) 3.14;
1270             auto va_5 = cast(double)2.14;
1271             auto va_6 = cast(real)  0.1;
1272             auto va_7 = "abcd"[];
1273             S    va_8 = { 1, 2, 3, 4 };
1274             A    va_9 = new A;
1275             B    va_a = new B;
1276             C    va_b = new D;
1277             D    va_c = new D;
1278 
1279             auto vs = scoop(va_0, va_1, va_2, va_3,
1280                             va_4, va_5, va_6, va_7,
1281                             va_8, va_9, va_a, va_b, va_c);
1282 
1283             assert( vs[0x0].get!(typeof(va_0)) == va_0 );
1284             assert( vs[0x1].get!(typeof(va_1)) == va_1 );
1285             assert( vs[0x2].get!(typeof(va_2)) == va_2 );
1286             assert( vs[0x3].get!(typeof(va_3)) == va_3 );
1287             assert( vs[0x4].get!(typeof(va_4)) == va_4 );
1288             assert( vs[0x5].get!(typeof(va_5)) == va_5 );
1289             assert( vs[0x6].get!(typeof(va_6)) == va_6 );
1290             assert( vs[0x7].get!(typeof(va_7)) == va_7 );
1291             assert( vs[0x8].get!(typeof(va_8)) == va_8 );
1292             assert( vs[0x9].get!(typeof(va_9)) is va_9 );
1293             assert( vs[0xa].get!(typeof(va_a)) is va_a );
1294             assert( vs[0xb].get!(typeof(va_b)) is va_b );
1295             assert( vs[0xc].get!(typeof(va_c)) is va_c );
1296 
1297             assert( vs[0x9].get!(typeof(va_9)).msg == "A" );
1298             assert( vs[0xa].get!(typeof(va_a)).msg == "B" );
1299             assert( vs[0xc].get!(typeof(va_c)).msg == "D" );
1300 
1301             assert( vs[0xb].get!(typeof(va_b)).name == "phil" );
1302             assert( vs[0xc].get!(typeof(va_c)).name == "phil" );
1303 
1304             /+
1305             version (none) version(X86) // TODO toVararg won't work in x86_64 as it is now
1306             {
1307                 TypeInfo[] types;
1308                 void* args;
1309 
1310                 Variant.toVararg(vs, types, args);
1311 
1312                 assert( types[0x0] is typeid(typeof(va_0)) );
1313                 assert( types[0x1] is typeid(typeof(va_1)) );
1314                 assert( types[0x2] is typeid(typeof(va_2)) );
1315                 assert( types[0x3] is typeid(typeof(va_3)) );
1316                 assert( types[0x4] is typeid(typeof(va_4)) );
1317                 assert( types[0x5] is typeid(typeof(va_5)) );
1318                 assert( types[0x6] is typeid(typeof(va_6)) );
1319                 assert( types[0x7] is typeid(typeof(va_7)) );
1320                 assert( types[0x8] is typeid(typeof(va_8)) );
1321                 assert( types[0x9] is typeid(typeof(va_9)) );
1322                 assert( types[0xa] is typeid(typeof(va_a)) );
1323                 assert( types[0xb] is typeid(typeof(va_b)) );
1324                 assert( types[0xc] is typeid(typeof(va_c)) );
1325 
1326                 auto ptr = args;
1327 
1328                 auto vb_0 = va_arg!(typeof(va_0))(ptr);
1329                 auto vb_1 = va_arg!(typeof(va_1))(ptr);
1330                 auto vb_2 = va_arg!(typeof(va_2))(ptr);
1331                 auto vb_3 = va_arg!(typeof(va_3))(ptr);
1332                 auto vb_4 = va_arg!(typeof(va_4))(ptr);
1333                 auto vb_5 = va_arg!(typeof(va_5))(ptr);
1334                 auto vb_6 = va_arg!(typeof(va_6))(ptr);
1335                 auto vb_7 = va_arg!(typeof(va_7))(ptr);
1336                 auto vb_8 = va_arg!(typeof(va_8))(ptr);
1337                 auto vb_9 = va_arg!(typeof(va_9))(ptr);
1338                 auto vb_a = va_arg!(typeof(va_a))(ptr);
1339                 auto vb_b = va_arg!(typeof(va_b))(ptr);
1340                 auto vb_c = va_arg!(typeof(va_c))(ptr);
1341 
1342                 assert( vb_0 == va_0 );
1343                 assert( vb_1 == va_1 );
1344                 assert( vb_2 == va_2 );
1345                 assert( vb_3 == va_3 );
1346                 assert( vb_4 == va_4 );
1347                 assert( vb_5 == va_5 );
1348                 assert( vb_6 == va_6 );
1349                 assert( vb_7 == va_7 );
1350                 assert( vb_8 == va_8 );
1351                 assert( vb_9 is va_9 );
1352                 assert( vb_a is va_a );
1353                 assert( vb_b is va_b );
1354                 assert( vb_c is va_c );
1355 
1356                 assert( vb_9.msg == "A" );
1357                 assert( vb_a.msg == "B" );
1358                 assert( vb_c.msg == "D" );
1359 
1360                 assert( vb_b.name == "phil" );
1361                 assert( vb_c.name == "phil" );
1362             }
1363             +/
1364         }
1365     }
1366 }