PageRenderTime 116ms CodeModel.GetById 19ms app.highlight 89ms RepoModel.GetById 1ms app.codeStats 0ms

/core/variant.d

http://github.com/wilkie/djehuty
D | 1209 lines | 1043 code | 132 blank | 34 comment | 234 complexity | 6450b0a2da0fbf82cd77fd8988e0a8fc MD5 | raw file
   1/*
   2 * variant.d
   3 *
   4 * This module contains code for use with a variant type and variadics.
   5 *
   6 * Author: Dave Wilkinson
   7 * Originated: September 10th, 2009
   8 *
   9 */
  10
  11module core.variant;
  12
  13import core.string;
  14import core.definitions;
  15import core.unicode;
  16
  17import io.console;
  18
  19// Imposed variadic
  20version(LDC) {
  21	public import ldc.vararg;
  22	public import C = ldc.cstdarg;
  23}
  24else {
  25	public import std.stdarg;
  26	public import C = std.c.stdarg;
  27}
  28
  29//import std.stdio;
  30
  31enum Type {
  32
  33	// Integer Types
  34	Byte,
  35	Short,
  36	Int,
  37	Long,
  38	Ubyte,
  39	Ushort,
  40	Uint,
  41	Ulong,
  42
  43	// Floating Point
  44	Real,
  45	Double,
  46	Float,
  47	Ireal,
  48	Idouble,
  49	Ifloat,
  50	Creal,
  51	Cdouble,
  52	Cfloat,
  53
  54	// Char
  55	Char,
  56	Wchar,
  57	Dchar,
  58
  59	// Boolean
  60	Bool,
  61
  62	// Abstract Data Types
  63	Struct,
  64	Reference,
  65	Pointer,
  66}
  67
  68struct Variant {
  69
  70	Type type() {
  71		return _type;
  72	}
  73
  74	bool isArray() {
  75		return _isArray;
  76	}
  77
  78	bool isAssociative() {
  79		return _isHash;
  80	}
  81
  82	Variant opAssign(byte from) {
  83		_type = Type.Byte;
  84		_data.b = from;
  85		_isArray = false;
  86		_depth = 0;
  87		return *this;
  88	}
  89
  90	Variant opAssign(ubyte from) {
  91		_type = Type.Ubyte;
  92		_data.ub = from;
  93		_isArray = false;
  94		_depth = 0;
  95		return *this;
  96	}
  97	
  98	Variant opAssign(short from) {
  99		_type = Type.Short;
 100		_data.s = from;
 101		_isArray = false;
 102		_depth = 0;
 103		return *this;
 104	}
 105
 106	Variant opAssign(ushort from) {
 107		_type = Type.Ushort;
 108		_data.us = from;
 109		_isArray = false;
 110		_depth = 0;
 111		return *this;
 112	}
 113
 114	Variant opAssign(int from) {
 115		_type = Type.Int;
 116		_data.i = from;
 117		_isArray = false;
 118		_depth = 0;
 119		return *this;
 120	}
 121
 122	Variant opAssign(uint from) {
 123		_type = Type.Uint;
 124		_data.ui = from;
 125		_isArray = false;
 126		_depth = 0;
 127		return *this;
 128	}
 129
 130	Variant opAssign(long from) {
 131		_type = Type.Long;
 132		_data.l = from;
 133		_isArray = false;
 134		_depth = 0;
 135		return *this;
 136	}
 137
 138	Variant opAssign(ulong from) {
 139		_type = Type.Ulong;
 140		_data.ul = from;
 141		_isArray = false;
 142		_depth = 0;
 143		return *this;
 144	}
 145
 146	Variant opAssign(float from) {
 147		_type = Type.Float;
 148		_data.f = from;
 149		_isArray = false;
 150		_depth = 0;
 151		return *this;
 152	}
 153
 154	Variant opAssign(double from) {
 155		_type = Type.Double;
 156		_data.d = from;
 157		_isArray = false;
 158		_depth = 0;
 159		return *this;
 160	}
 161
 162	Variant opAssign(real from) {
 163		_type = Type.Real;
 164		_data.r = from;
 165		_isArray = false;
 166		_depth = 0;
 167		return *this;
 168	}
 169
 170	Variant opAssign(ifloat from) {
 171		_type = Type.Ifloat;
 172		_data.fi = from;
 173		_isArray = false;
 174		_depth = 0;
 175		return *this;
 176	}
 177
 178	Variant opAssign(idouble from) {
 179		_type = Type.Idouble;
 180		_data.di = from;
 181		_isArray = false;
 182		_depth = 0;
 183		return *this;
 184	}
 185
 186	Variant opAssign(ireal from) {
 187		_type = Type.Ireal;
 188		_data.ri = from;
 189		_isArray = false;
 190		_depth = 0;
 191		return *this;
 192	}
 193
 194	Variant opAssign(cfloat from) {
 195		_type = Type.Cfloat;
 196		_data.fc = from;
 197		_isArray = false;
 198		_depth = 0;
 199		return *this;
 200	}
 201
 202	Variant opAssign(cdouble from) {
 203		_type = Type.Cdouble;
 204		_data.dc = from;
 205		_isArray = false;
 206		_depth = 0;
 207		return *this;
 208	}
 209
 210	Variant opAssign(creal from) {
 211		_type = Type.Creal;
 212		_data.rc = from;
 213		_isArray = false;
 214		_depth = 0;
 215		return *this;
 216	}
 217
 218	Variant opAssign(char from) {
 219		_type = Type.Char;
 220		_data.cc = from;
 221		_isArray = false;
 222		_depth = 0;
 223		return *this;
 224	}
 225
 226	Variant opAssign(wchar from) {
 227		_type = Type.Wchar;
 228		_data.cw = from;
 229		_isArray = false;
 230		_depth = 0;
 231		return *this;
 232	}
 233
 234	Variant opAssign(dchar from) {
 235		_type = Type.Dchar;
 236		_data.cd = from;
 237		_isArray = false;
 238		_depth = 0;
 239		return *this;
 240	}
 241
 242	Variant opAssign(string from) {
 243		_type = Type.Char;
 244		_data.cs = from.dup;
 245		_isArray = true;
 246		_depth = 1;
 247		return *this;
 248	}
 249
 250	Variant opAssign(Object from) {
 251		_type = Type.Reference;
 252		_data.reference = from;
 253		_isArray = false;
 254		_depth = 0;
 255		return *this;
 256	}
 257
 258	bool opEquals(byte var) {
 259		auto cmp = to!(byte);
 260		return cmp == var;
 261	}
 262
 263	bool opEquals(ubyte var) {
 264		auto cmp = to!(ubyte);
 265		return cmp == var;
 266	}
 267
 268	bool opEquals(short var) {
 269		auto cmp = to!(short);
 270		return cmp == var;
 271	}
 272
 273	bool opEquals(ushort var) {
 274		auto cmp = to!(ushort);
 275		return cmp == var;
 276	}
 277
 278	bool opEquals(int var) {
 279		int cmp = to!(int);
 280		return cmp == var;
 281	}
 282
 283	bool opEquals(uint var) {
 284		auto cmp = to!(uint);
 285		return cmp == var;
 286	}
 287
 288	bool opEquals(long var) {
 289		auto cmp = to!(ulong);
 290		return cmp == var;
 291	}
 292
 293	bool opEquals(ulong var) {
 294		auto cmp = to!(ulong);
 295		return cmp == var;
 296	}
 297
 298	bool opEquals(string var) {
 299		string cmp = to!(string);
 300		return cmp == var;
 301	}
 302
 303	bool opEquals(Object var) {
 304		Object cmp = to!(Object);
 305		return cmp is var;
 306	}
 307
 308	bool opEquals(float var) {
 309		auto cmp = to!(float);
 310		return cmp == var;
 311	}
 312
 313	bool opEquals(double var) {
 314		auto cmp = to!(double);
 315		return cmp == var;
 316	}
 317
 318	template to(T) {
 319		T to() {
 320			static if (is(T == struct) || is(T == union)) {
 321				T* s = cast(T*)_data.blob.ptr;
 322				return *s;
 323			}
 324			else static if (is(T == class)) {
 325				Object o = _data.reference;
 326				T* c = cast(T*)&o;
 327				return *c;
 328			}
 329			else static if (is(T == void*)) {
 330				return _data.pointer.address;
 331			}
 332			else static if (is(T == char[])) {
 333				return toString();
 334			}
 335			else {
 336				if (_type == Type.Float) {
 337					return cast(T)_data.f;
 338				}
 339				else if (_type == Type.Double) {
 340					return cast(T)_data.d;
 341				}
 342				else if (_type == Type.Real) {
 343					return cast(T)_data.r;
 344				}
 345				else if (_type == Type.Cfloat) {
 346					return cast(T)_data.fc;
 347				}
 348				else if (_type == Type.Cdouble) {
 349					return cast(T)_data.dc;
 350				}
 351				else if (_type == Type.Creal) {
 352					return cast(T)_data.rc;
 353				}
 354				else if (_type == Type.Int) {
 355					return cast(T)_data.i;
 356				}
 357				else if (_type == Type.Uint) {
 358					return cast(T)_data.ui;
 359				}
 360				else if (_type == Type.Byte) {
 361					return cast(T)_data.b;
 362				}
 363				else if (_type == Type.Ubyte) {
 364					return cast(T)_data.ub;
 365				}
 366				else if (_type == Type.Short) {
 367					return cast(T)_data.s;
 368				}
 369				else if (_type == Type.Ushort) {
 370					return cast(T)_data.us;
 371				}
 372				else if ((_type == Type.Ifloat) || (_type == Type.Idouble) || (_type == Type.Ireal)) {
 373					return cast(T)0.0; // It is 0.0 for the real part
 374				}
 375				else if (_type == Type.Long) {
 376					return cast(T)_data.l;
 377				}
 378				else if (_type == Type.Ulong) {
 379					return cast(T)_data.ul;
 380				}
 381				else if (_type == Type.Pointer) {
 382					return *cast(T*)_data.pointer.address;
 383				}
 384				else {
 385					return *(cast(T*)&_data.b);
 386				}
 387			}
 388		}
 389	}
 390
 391	string toString() {
 392		if (_isArray) {
 393			if (_type == Type.Char && _depth == 1) {
 394				// string
 395				return _data.cs;
 396			}
 397			else if (_type == Type.Wchar && _depth == 1) {
 398				// string
 399				return Unicode.toUtf8(_data.ws);
 400			}
 401			else if (_type == Type.Dchar && _depth == 1) {
 402				// string
 403				return Unicode.toUtf8(_data.ds);
 404			}
 405			else if (_data.array !is null) {
 406				string ret = "[";
 407				foreach(int i, item; _data.array) {
 408					ret ~= item.toString();
 409					if (i < _data.array.length-1) {
 410						ret ~= ",";
 411					}
 412				}
 413				ret ~= "]";
 414				return ret;
 415			}
 416			else {
 417				return "[]";
 418			}
 419		}
 420
 421		switch (_type) {
 422			case Type.Reference:
 423				if (_data.reference is null) {
 424					return "null";
 425				}
 426				return _data.reference.toString();
 427			case Type.Struct:
 428				if (_data.blob is null) {
 429					return "null";
 430				}
 431				else {
 432					TypeInfo_Struct tis = cast(TypeInfo_Struct)_ti;
 433					if (tis.xtoString !is null) {
 434						string delegate() XToStringFunc;
 435						XToStringFunc.ptr = _data.blob.ptr;
 436						XToStringFunc.funcptr = cast(string function())tis.xtoString;
 437						return XToStringFunc();
 438					}
 439				}
 440				break;
 441			case Type.Char:
 442				return [_data.cc];
 443			case Type.Wchar:
 444				return Unicode.toUtf8([_data.cw]);
 445			case Type.Dchar:
 446				return Unicode.toUtf8([_data.cd]);
 447			case Type.Byte:
 448				return "{d}".format(_data.b);
 449			case Type.Ubyte:
 450				return "{d}".format(_data.ub);
 451			case Type.Short:
 452				return "{d}".format(_data.s);
 453			case Type.Ushort:
 454				return "{d}".format(_data.us);
 455			case Type.Int:
 456				return "{d}".format(_data.i);
 457			case Type.Uint:
 458				return "{d}".format(_data.ui);
 459			case Type.Long:
 460				return "{d}".format(_data.l);
 461			case Type.Ulong:
 462				return "{d}".format(_data.ul);
 463			case Type.Bool:
 464				if (_data.truth) {
 465					return "true";
 466				}
 467				return "false";
 468			case Type.Float:
 469				return "{d}".format(cast(float)_data.f);
 470			case Type.Double:
 471				return "{d}".format(cast(double)_data.d);
 472			case Type.Real:
 473				return "{real}";
 474			case Type.Pointer:
 475				return "0x{x}".format(cast(ulong)_data.pointer.address);
 476			default:
 477				break;
 478		}
 479		return "foo";
 480	}
 481
 482private:
 483	Type _type = Type.Reference;
 484
 485	bool _isArray = false;
 486	uint _depth = 0;
 487
 488	bool _isHash = false;
 489	size_t _size = null.sizeof;
 490
 491	TypeInfo _tiRoot;
 492	TypeInfo _ti;
 493
 494	VariantData _data = {reference:null};
 495}
 496
 497union VariantData {
 498	byte b;
 499	ubyte ub;
 500	int i;
 501	uint ui;
 502	short s;
 503	ushort us;
 504	long l;
 505	ulong ul;
 506
 507	float f;
 508	double d;
 509	real r;
 510
 511	ifloat fi;
 512	idouble di;
 513	ireal ri;
 514
 515	cfloat fc;
 516	cdouble dc;
 517	creal rc;
 518
 519	char cc;
 520	wchar cw;
 521	dchar cd;
 522
 523	string cs;
 524	wstring ws;
 525	dstring ds;
 526
 527	Object reference;
 528	ubyte[] blob;
 529
 530	bool truth;
 531
 532	Variant[] array;
 533
 534	struct VariantPointerData {
 535		void* address;
 536		Variant* next;
 537	}
 538	VariantPointerData pointer;
 539}
 540
 541class Variadic {
 542	this(TypeInfo[] args, void* ptr) {
 543		_args = args;
 544		_ptr = ptr;
 545		_originalPtr = _ptr;
 546	}
 547
 548	bool hasNext() {
 549		if (_idx == length()) {
 550			return false;
 551		}
 552		return true;
 553	}
 554
 555	Variant next() {
 556		Variant ret = _variantForTypeInfo(_args[_idx], _ptr);
 557		_ptr += argPtrSize(_args[_idx]);
 558		_idx++;
 559		return ret;
 560	}
 561
 562	Variant[] rest() {
 563		Variant[] ret;
 564		foreach(arg; _args[_idx..$]) {
 565			Variant var = _variantForTypeInfo(arg, _ptr);
 566			_ptr += argPtrSize(arg);
 567			ret ~= var;
 568		}
 569		return ret;
 570	}
 571
 572	Variant peek() {
 573		Variant ret = _variantForTypeInfo(_args[_idx], _ptr);
 574		return ret;
 575	}
 576
 577	Variant peekAt(size_t index) {
 578		Variant ret;
 579		void* ptr = _originalPtr;
 580		uint startIndex = 0;
 581		if (index > _idx) {
 582			startIndex = _idx;
 583			ptr = _ptr;
 584		}
 585		for ( ; startIndex < index; startIndex++) {
 586			ptr += argPtrSize(_args[index]);
 587		}
 588		ret = _variantForTypeInfo(_args[index], ptr);
 589		return ret;
 590	}
 591
 592	Variant[] array() {
 593		Variant[] ret;
 594		void* ptr = _originalPtr;
 595		foreach(arg; _args) {
 596			Variant var = _variantForTypeInfo(arg, ptr);
 597			ptr += argPtrSize(arg);
 598			ret ~= var;
 599		}
 600		return ret;
 601	}
 602
 603	size_t length() {
 604		return _args.length;
 605	}
 606
 607	void retain() {
 608		if (_data !is null) {
 609			return;
 610		}
 611
 612		_args = _args.dup;
 613
 614		// get _size
 615		foreach(arg; _args) {
 616			_size += arg.tsize();
 617		}
 618
 619		// copy
 620		ubyte* dataptr = cast(ubyte*)_originalPtr;
 621		_data = new ubyte[_size];
 622		_data[0.._size] = dataptr[0.._size];
 623		_ptr = _data.ptr;
 624		_originalPtr = _ptr;
 625	}
 626
 627	int opApply(int delegate(ref Variant) loopFunc) {
 628		int ret;
 629
 630		_ptr = _originalPtr;
 631		foreach(i, arg; _args) {
 632			Variant var = _variantForTypeInfo(arg, _ptr);
 633			ret = loopFunc(var);
 634			_ptr += argPtrSize(arg);
 635			if (ret) { break; }
 636		}
 637
 638		return ret;
 639	}
 640
 641	int opApply(int delegate(ref size_t, ref Variant) loopFunc) {
 642		int ret;
 643
 644		_ptr = _originalPtr;
 645		foreach(size_t i, arg; _args) {
 646			Variant var = _variantForTypeInfo(arg, _ptr);
 647			ret = loopFunc(i,var);
 648			_ptr += argPtrSize(arg);
 649			if (ret) { break; }
 650		}
 651
 652		return ret;
 653	}
 654
 655	Variant opIndex(size_t i1) {
 656		return peekAt(i1);
 657	}
 658
 659protected:
 660
 661	TypeInfo[] _args;
 662	void* _ptr;
 663	void* _originalPtr;
 664	ubyte[] _data;
 665	size_t _size;
 666
 667	size_t _idx;
 668
 669	size_t argPtrSize(TypeInfo _ti) {
 670		return (_ti.tsize() + size_t.sizeof - 1) & ~(size_t.sizeof - 1);
 671	}
 672
 673	Variant _variantForTypeInfo(TypeInfo _ti, void* ptr) {
 674		Variant ret;
 675		void[] arr;
 676
 677		if ((cast(TypeInfo_Typedef)_ti) !is null ) {
 678			_ti = _ti.next;
 679		}
 680
 681		ret._tiRoot = _ti;
 682
 683		ret._size = _ti.tsize();
 684
 685		string cmp = _ti.classinfo.name[9..$];
 686
 687		/*while (cmp == "Array") {
 688			Console.putln("Array TI Size: ", _ti.tsize());
 689			ret._depth++;
 690			TypeInfo_Array tia = cast(TypeInfo_Array)_ti;
 691			_ti = tia.value;
 692			cmp = _ti.classinfo.name[9..$];
 693		}*/
 694
 695		// check for array
 696		if (cmp[0] == 'A' && cmp != "Array") {
 697			ret._depth++;
 698			ret._isArray = true;
 699
 700			if (ptr !is null) {
 701				arr = va_arg!(void[])(ptr);
 702			}
 703			ret._data.array = new Variant[arr.length];
 704
 705			cmp = cmp[1..$];
 706		}
 707
 708		// get base _type
 709		switch (cmp) {
 710			case "Array":
 711				arr = va_arg!(void[])(ptr);
 712
 713				ret._isArray = true;
 714				ret._depth = 1;
 715
 716				ret._data.array = new Variant[arr.length];
 717
 718				TypeInfo_Array tia = cast(TypeInfo_Array)_ti;
 719
 720				void* arrPtr = cast(void*)arr.ptr;
 721				Variant sub;
 722				for (uint i; i < arr.length; i++) {
 723					sub = _variantForTypeInfo(tia.value, arrPtr);
 724					if (arrPtr !is null) {
 725						va_arg!(void[])(arrPtr);
 726					}
 727					ret._data.array[i] = sub;
 728				}
 729
 730				if (sub._isArray) {
 731					ret._depth += sub._depth;
 732				}
 733				ret._type = sub._type;
 734				break;
 735			case "Class":
 736				ret._type = Type.Reference;
 737				if (ptr !is null) {
 738					ret._data.reference = va_arg!(Object)(ptr);
 739				}
 740				break;
 741			case "Struct":
 742				ret._type = Type.Struct;
 743
 744				if (ptr !is null) {
 745					ubyte[] foo = new ubyte[ret._size];
 746					foo[0..$] = (cast(ubyte*)ptr)[0..ret._size];
 747					ret._data.blob = foo;
 748				}
 749
 750				ret._ti = cast(TypeInfo_Struct)_ti;
 751				break;
 752			case "g":	// byte
 753				ret._type = Type.Byte;
 754				if (!ret._isArray) {
 755					if (ptr !is null) {
 756						ret._data.b = va_arg!(byte)(ptr);
 757					}
 758				}
 759				else {
 760					byte* arrPtr = cast(byte*)arr.ptr;
 761
 762					for (uint i; i < arr.length; i++) {
 763						Variant val;
 764						val._type = Type.Byte;
 765						if (ptr !is null) {
 766							val._data.b = *arrPtr;
 767							arrPtr++;
 768						}
 769						ret._data.array[i] = val;
 770					}
 771				}
 772				break;
 773			case "h":	// ubyte
 774				ret._type = Type.Ubyte;
 775				if (!ret._isArray) {
 776					if (ptr !is null) {
 777						ret._data.ub = va_arg!(ubyte)(ptr);
 778					}
 779				}
 780				else {
 781					ubyte* arrPtr = cast(ubyte*)arr.ptr;
 782
 783					for (uint i; i < arr.length; i++) {
 784						Variant val;
 785						val._type = Type.Ubyte;
 786						if (ptr !is null) {
 787							val._data.ub = *arrPtr;
 788							arrPtr++;
 789						}
 790						ret._data.array[i] = val;
 791					}
 792				}
 793				break;
 794			case "s":	// short
 795				ret._type = Type.Short;
 796				if (!ret._isArray) {
 797					if (ptr !is null) {
 798						ret._data.s = va_arg!(short)(ptr);
 799					}
 800				}
 801				else {
 802					short* arrPtr = cast(short*)arr.ptr;
 803
 804					for (uint i; i < arr.length; i++) {
 805						Variant val;
 806						val._type = Type.Short;
 807						if (ptr !is null) {
 808							val._data.s = *arrPtr;
 809							arrPtr++;
 810						}
 811						ret._data.array[i] = val;
 812					}
 813				}
 814				break;
 815			case "t":	// ushort
 816				ret._type = Type.Ushort;
 817				if (!ret._isArray) {
 818					if (ptr !is null) {
 819						ret._data.us = va_arg!(ushort)(ptr);
 820					}
 821				}
 822				else {
 823					ushort* arrPtr = cast(ushort*)arr.ptr;
 824
 825					for (uint i; i < arr.length; i++) {
 826						Variant val;
 827						val._type = Type.Ushort;
 828						if (ptr !is null) {
 829							val._data.us = *arrPtr;
 830							arrPtr++;
 831						}
 832						ret._data.array[i] = val;
 833					}
 834				}
 835				break;
 836			case "i":	// int
 837				ret._type = Type.Int;
 838				if (!ret._isArray) {
 839					if (ptr !is null) {
 840						ret._data.i = va_arg!(int)(ptr);
 841					}
 842				}
 843				else {
 844					int* arrPtr = cast(int*)arr.ptr;
 845
 846					for (uint i; i < arr.length; i++) {
 847						Variant val;
 848						val._type = Type.Int;
 849						if (ptr !is null) {
 850							val._data.i = *arrPtr;
 851							arrPtr++;
 852						}
 853						ret._data.array[i] = val;
 854					}
 855				}
 856				break;
 857			case "k":	// uint
 858				ret._type = Type.Uint;
 859				if (!ret._isArray) {
 860					if (ptr !is null) {
 861						ret._data.ui = va_arg!(uint)(ptr);
 862					}
 863				}
 864				else {
 865					uint* arrPtr = cast(uint*)arr.ptr;
 866
 867					for (uint i; i < arr.length; i++) {
 868						Variant val;
 869						val._type = Type.Uint;
 870						if (ptr !is null) {
 871							val._data.ui = *arrPtr;
 872							arrPtr++;
 873						}
 874						ret._data.array[i] = val;
 875					}
 876				}
 877				break;
 878			case "l":	// long
 879				ret._type = Type.Long;
 880				if (!ret._isArray) {
 881					if (ptr !is null) {
 882						ret._data.l = va_arg!(long)(ptr);
 883					}
 884				}
 885				else {
 886					long* arrPtr = cast(long*)arr.ptr;
 887
 888					for (uint i; i < arr.length; i++) {
 889						Variant val;
 890						val._type = Type.Long;
 891						if (ptr !is null) {
 892							val._data.l = *arrPtr;
 893							arrPtr++;
 894						}
 895						ret._data.array[i] = val;
 896					}
 897				}
 898				break;
 899			case "m":	// ulong
 900				ret._type = Type.Ulong;
 901				if (!ret._isArray) {
 902					if (ptr !is null) {
 903						ret._data.ul = va_arg!(ulong)(ptr);
 904					}
 905				}
 906				else {
 907					ulong* arrPtr = cast(ulong*)arr.ptr;
 908
 909					for (uint i; i < arr.length; i++) {
 910						Variant val;
 911						val._type = Type.Ulong;
 912						if (ptr !is null) {
 913							val._data.ul = *arrPtr;
 914							arrPtr++;
 915						}
 916						ret._data.array[i] = val;
 917					}
 918				}
 919				break;
 920			case "f":	// float
 921				ret._type = Type.Float;
 922				if (!ret._isArray) {
 923					if (ptr !is null) {
 924						ret._data.f = va_arg!(float)(ptr);
 925					}
 926				}
 927				else {
 928					void* arrPtr = cast(void*)arr.ptr;
 929
 930					for (uint i; i < arr.length; i++) {
 931						Variant val;
 932						val._type = Type.Float;
 933						if (ptr !is null) {
 934							val._data.f = va_arg!(float)(arrPtr);
 935						}
 936						ret._data.array[i] = val;
 937					}
 938				}
 939				break;
 940			case "d":	// double
 941				ret._type = Type.Double;
 942				if (!ret._isArray) {
 943					if (ptr !is null) {
 944						ret._data.d = va_arg!(double)(ptr);
 945					}
 946				}
 947				else {
 948					void* arrPtr = cast(void*)arr.ptr;
 949
 950					for (uint i; i < arr.length; i++) {
 951						Variant val;
 952						val._type = Type.Double;
 953						if (ptr !is null) {
 954							val._data.d = va_arg!(double)(arrPtr);
 955						}
 956						ret._data.array[i] = val;
 957					}
 958				}
 959				break;
 960			case "e":	// real
 961				ret._type = Type.Real;
 962				if (!ret._isArray) {
 963					if (ptr !is null) {
 964						ret._data.r = va_arg!(real)(ptr);
 965					}
 966				}
 967				else {
 968					void* arrPtr = cast(void*)arr.ptr;
 969
 970					for (uint i; i < arr.length; i++) {
 971						Variant val;
 972						val._type = Type.Real;
 973						if (ptr !is null) {
 974							val._data.r = va_arg!(real)(arrPtr);
 975						}
 976						ret._data.array[i] = val;
 977					}
 978				}
 979				break;
 980			case "o":	// ifloat
 981				ret._type = Type.Ifloat;
 982				if (!ret._isArray) {
 983					if (ptr !is null) {
 984						ret._data.fi = va_arg!(ifloat)(ptr);
 985					}
 986				}
 987				else {
 988					void* arrPtr = cast(void*)arr.ptr;
 989
 990					for (uint i; i < arr.length; i++) {
 991						Variant val;
 992						val._type = Type.Ifloat;
 993						if (ptr !is null) {
 994							val._data.fi = va_arg!(ifloat)(arrPtr);
 995						}
 996						ret._data.array[i] = val;
 997					}
 998				}
 999				break;
1000			case "p":	// idouble
1001				ret._type = Type.Idouble;
1002				if (!ret._isArray) {
1003					if (ptr !is null) {
1004						ret._data.di = va_arg!(idouble)(ptr);
1005					}
1006				}
1007				else {
1008					void* arrPtr = cast(void*)arr.ptr;
1009
1010					for (uint i; i < arr.length; i++) {
1011						Variant val;
1012						val._type = Type.Idouble;
1013						if (ptr !is null) {
1014							val._data.di = va_arg!(idouble)(arrPtr);
1015						}
1016						ret._data.array[i] = val;
1017					}
1018				}
1019				break;
1020			case "j":	// ireal
1021				ret._type = Type.Ireal;
1022				if (!ret._isArray) {
1023					if (ptr !is null) {
1024						ret._data.ri = va_arg!(ireal)(ptr);
1025					}
1026				}
1027				else {
1028					void* arrPtr = cast(void*)arr.ptr;
1029
1030					for (uint i; i < arr.length; i++) {
1031						Variant val;
1032						val._type = Type.Ireal;
1033						if (ptr !is null) {
1034							val._data.ri = va_arg!(ireal)(arrPtr);
1035						}
1036						ret._data.array[i] = val;
1037					}
1038				}
1039				break;
1040			case "a":	// char
1041				ret._type = Type.Char;
1042				if (!ret._isArray) {
1043					if (ptr !is null) {
1044						ret._data.cc = va_arg!(char)(ptr);
1045					}
1046				}
1047				else {
1048					// string
1049					if (ptr !is null) {
1050						ret._data.cs = (cast(char*)arr.ptr)[0..arr.length];
1051					}
1052				}
1053				break;
1054			case "u":	// wchar
1055				ret._type = Type.Wchar;
1056				if (!ret._isArray) {
1057					if (ptr !is null) {
1058						ret._data.cw = va_arg!(wchar)(ptr);
1059					}
1060				}
1061				else {
1062					// string
1063					if (ptr !is null) {
1064						ret._data.ws = (cast(wchar*)arr.ptr)[0..arr.length];
1065					}
1066				}
1067				break;
1068			case "w":	// wchar
1069				ret._type = Type.Dchar;
1070				if (!ret._isArray) {
1071					if (ptr !is null) {
1072						ret._data.cd = va_arg!(dchar)(ptr);
1073					}
1074				}
1075				else {
1076					// string
1077					if (ptr !is null) {
1078						ret._data.ds = (cast(dchar*)arr.ptr)[0..arr.length];
1079					}
1080				}
1081				break;
1082			case "b":	// bool
1083				ret._type = Type.Bool;
1084				if (!ret._isArray) {
1085					if (ptr !is null) {
1086						ret._data.truth = va_arg!(bool)(ptr);
1087					}
1088				}
1089				else {
1090					bool* arrPtr = cast(bool*)arr.ptr;
1091
1092					for (size_t i; i < arr.length; i++) {
1093						Variant val;
1094						val._type = Type.Bool;
1095						if (ptr !is null) {
1096							val._data.truth = *arrPtr;
1097							arrPtr++;
1098						}
1099						ret._data.array[i] = val;
1100					}
1101				}
1102				break;
1103			case "q":	// cfloat
1104				ret._type = Type.Cfloat;
1105				if (!ret._isArray) {
1106					if (ptr !is null) {
1107						ret._data.fc = va_arg!(cfloat)(ptr);
1108					}
1109				}
1110				else {
1111					void* arrPtr = cast(void*)arr.ptr;
1112
1113					for (uint i; i < arr.length; i++) {
1114						Variant val;
1115						val._type = Type.Cfloat;
1116						if (ptr !is null) {
1117							val._data.fc = va_arg!(cfloat)(arrPtr);
1118						}
1119						ret._data.array[i] = val;
1120					}
1121				}
1122				break;
1123			case "r":	// cdouble
1124				ret._type = Type.Cdouble;
1125				if (!ret._isArray) {
1126					if (ptr !is null) {
1127						ret._data.dc = va_arg!(cdouble)(ptr);
1128					}
1129				}
1130				else {
1131					void* arrPtr = cast(void*)arr.ptr;
1132
1133					for (uint i; i < arr.length; i++) {
1134						Variant val;
1135						val._type = Type.Cdouble;
1136						if (ptr !is null) {
1137							val._data.dc = va_arg!(cdouble)(arrPtr);
1138						}
1139						ret._data.array[i] = val;
1140					}
1141				}
1142				break;
1143			case "c":	// creal
1144				ret._type = Type.Creal;
1145				if (!ret._isArray) {
1146					if (ptr !is null) {
1147						ret._data.rc = va_arg!(creal)(ptr);
1148					}
1149				}
1150				else {
1151					void* arrPtr = cast(void*)arr.ptr;
1152
1153					for (uint i; i < arr.length; i++) {
1154						Variant val;
1155						val._type = Type.Creal;
1156						if (ptr !is null) {
1157							val._data.rc = va_arg!(creal)(arrPtr);
1158						}
1159						ret._data.array[i] = val;
1160					}
1161				}
1162				break;
1163			case "Pointer":
1164				ret._type = Type.Pointer;
1165				if (ptr !is null) {
1166					ret._data.pointer.address = va_arg!(void*)(ptr);
1167				}
1168				Variant foo;
1169				TypeInfo_Pointer tip = cast(TypeInfo_Pointer)_ti;
1170				foo = _variantForTypeInfo(tip.next, null);
1171				ret._data.pointer.next = &foo;
1172				break;
1173			default:
1174				break;
1175		}
1176		//Console.putln(cmp, " : ", ret._size);
1177		return ret;
1178	}
1179}
1180
1181private:
1182
1183long atoi(string value, uint base = 10) {
1184	bool negative;
1185	uint i;
1186	if (value is null || value.length == 0) {
1187		return 0;
1188	}
1189	if (value[i] == '-') {
1190		negative = true;
1191		i++;
1192	}
1193
1194	long ret;
1195
1196	for (; i < value.length; i++) {
1197		if (value[i] >= '0' && value[i] <= '9') {
1198			ret *= 10;
1199			ret += cast(int)value[i] - cast(int)'0';
1200		}
1201	}
1202
1203	if (negative) {
1204		ret = -ret;
1205	}
1206
1207	return ret;
1208}
1209