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