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