1 /**
2    Any type
3  */
4 module xlld.any;
5 
6 
7 version(testingExcelD) {
8     import unit_threaded;
9     import std.experimental.allocator.gc_allocator: GCAllocator;
10     alias theGC = GCAllocator.instance;
11 }
12 
13 ///
14 struct Any {
15     import xlld.sdk.xlcall: XLOPER12;
16 
17     ///
18     XLOPER12 _impl;
19     alias _impl this;
20 
21     ///
22     bool opEquals(Any other) @trusted const {
23         import xlld.sdk.xlcall: XlType;
24         import xlld.conv.from: fromXlOper;
25 
26         switch(_impl.xltype) {
27 
28         default:
29             return _impl == other._impl;
30 
31         case XlType.xltypeStr:
32 
33             import std.experimental.allocator.gc_allocator: GCAllocator;
34             return _impl.fromXlOper!string(GCAllocator.instance) ==
35                 other._impl.fromXlOper!string(GCAllocator.instance);
36 
37         case XlType.xltypeMulti:
38 
39             if(_impl.val.array.rows != other._impl.val.array.rows) return false;
40             if(_impl.val.array.columns != other._impl.val.array.columns) return false;
41 
42             int i;
43             foreach(r; 0 .. _impl.val.array.rows) {
44                 foreach(c; 0 .. _impl.val.array.columns) {
45                     if(Any(cast(XLOPER12)_impl.val.array.lparray[i]) !=
46                        Any(cast(XLOPER12)other._impl.val.array.lparray[i]))
47                         return false;
48                     ++i;
49                 }
50             }
51 
52             return true;
53         }
54     }
55 
56 
57     @("opEquals str")
58     unittest {
59         any("foo", theGC).shouldEqual(any("foo", theGC));
60         any("foo", theGC).shouldNotEqual(any("bar", theGC));
61         any("foo", theGC).shouldNotEqual(any(33.3, theGC));
62     }
63 
64     @("opEquals multi")
65     unittest {
66         any([1.0, 2.0], theGC).shouldEqual(any([1.0, 2.0], theGC));
67         any([1.0, 2.0], theGC).shouldNotEqual(any("foo", theGC));
68         any([1.0, 2.0], theGC).shouldNotEqual(any([2.0, 2.0], theGC));
69     }
70 
71     ///
72     string toString() @safe const {
73         import std.conv: text;
74         import xlld.sdk.xlcall: XlType;
75         import xlld.conv.from: fromXlOper;
76         import xlld.sdk.xlcall: xlbitXLFree, xlbitDLLFree;
77         import std.experimental.allocator.gc_allocator: GCAllocator;
78 
79         alias allocator = GCAllocator.instance;
80 
81         string ret = text("Any(", );
82         const type = _impl.xltype & ~(xlbitXLFree | xlbitDLLFree);
83         switch(type) {
84         default:
85             ret ~= type.text;
86             break;
87         case XlType.xltypeStr:
88             ret ~= () @trusted { return text(`"`, _impl.fromXlOper!string(allocator), `"`); }();
89             break;
90         case XlType.xltypeNum:
91             ret ~= () @trusted { return _impl.fromXlOper!double(allocator).text; }();
92             break;
93         case XlType.xltypeInt:
94             ret ~= () @trusted { return _impl.fromXlOper!int(allocator).text; }();
95             break;
96         case XlType.xltypeMulti:
97             int i;
98             ret ~= `[`;
99             const rows = () @trusted { return _impl.val.array.rows; }();
100             const cols = () @trusted { return _impl.val.array.columns; }();
101             foreach(r; 0 .. rows) {
102                 ret ~= `[`;
103                 foreach(c; 0 .. cols) {
104                     auto oper = () @trusted { return _impl.val.array.lparray[i++]; }();
105                     ret ~= text(Any(cast(XLOPER12)oper), `, `);
106                 }
107                 ret ~= `]`;
108             }
109             ret ~= `]`;
110             break;
111         }
112         return ret ~ ")";
113     }
114 
115 }
116 
117 
118 ///
119 auto any(T, A)(auto ref T value, auto ref A allocator, in string file = __FILE__, in size_t line = __LINE__) @trusted {
120     import xlld.conv: toXlOper;
121     static if(__traits(compiles, Any(value.toXlOper(allocator, file, line))))
122         return Any(value.toXlOper(allocator, file, line));
123     else
124         return Any(value.toXlOper(allocator));
125 }