1 /** 2 Miscelleanous functions that assist in type conversions. 3 */ 4 module xlld.conv.misc; 5 6 import xlld.from; 7 8 /// 9 template isUserStruct(T) { 10 import xlld.any: Any; 11 import std.datetime: DateTime; 12 import std.typecons: Tuple; 13 import std.traits: Unqual; 14 15 enum isUserStruct = 16 is(T == struct) && 17 !is(Unqual!T == Any) && 18 !is(Unqual!T == DateTime) && 19 !is(Unqual!T: Tuple!A, A...) 20 ; 21 } 22 23 24 /// 25 __gshared immutable gDupMemoryException = new Exception("Failed to allocate memory in dup"); 26 27 28 /** 29 Deep copy of an oper 30 */ 31 from!"xlld.sdk.xlcall".XLOPER12 dup(A)(from!"xlld.sdk.xlcall".XLOPER12 oper, ref A allocator) @safe { 32 33 import xlld.sdk.xlcall: XLOPER12, XlType; 34 import std.experimental.allocator: makeArray; 35 36 XLOPER12 ret; 37 38 ret.xltype = oper.xltype; 39 40 switch(stripMemoryBitmask(oper.xltype)) with(XlType) { 41 42 default: 43 ret = oper; 44 return ret; 45 46 case xltypeStr: 47 const length = operStringLength(oper) + 1; 48 49 () @trusted { 50 ret.val.str = allocator.makeArray!wchar(length).ptr; 51 if(ret.val.str is null) 52 throw gDupMemoryException; 53 }(); 54 55 () @trusted { ret.val.str[0 .. length] = oper.val.str[0 .. length]; }(); 56 return ret; 57 58 case xltypeMulti: 59 () @trusted { 60 ret.val.array.rows = oper.val.array.rows; 61 ret.val.array.columns = oper.val.array.columns; 62 const length = oper.val.array.rows * oper.val.array.columns; 63 ret.val.array.lparray = allocator.makeArray!XLOPER12(length).ptr; 64 65 if(ret.val.array.lparray is null) 66 throw gDupMemoryException; 67 68 foreach(i; 0 .. length) { 69 ret.val.array.lparray[i] = oper.val.array.lparray[i].dup(allocator); 70 } 71 }(); 72 73 return ret; 74 } 75 76 assert(0); 77 } 78 79 80 81 from!"xlld.sdk.xlcall".XlType stripMemoryBitmask(in from!"xlld.sdk.xlcall".XlType type) @safe @nogc pure nothrow { 82 import xlld.sdk.xlcall: XlType, xlbitXLFree, xlbitDLLFree; 83 return cast(XlType)(type & ~(xlbitXLFree | xlbitDLLFree)); 84 } 85 86 /// 87 ushort operStringLength(T)(in T value) { 88 import xlld.sdk.xlcall: XlType; 89 import nogc.exception: enforce; 90 91 enforce(value.xltype == XlType.xltypeStr, 92 "Cannot calculate string length for oper of type ", value.xltype); 93 94 return cast(ushort)value.val.str[0]; 95 } 96 97 98 // can't be pure because to!double isn't pure 99 string toString(in from!"xlld.sdk.xlcall".XLOPER12 oper) @safe { 100 import xlld.sdk.xlcall: XlType; 101 import xlld.conv.misc: stripMemoryBitmask; 102 import std.conv: text; 103 import std.format: format; 104 105 string ret; 106 107 ret ~= "XLOPER12("; 108 switch(stripMemoryBitmask(oper.xltype)) { 109 default: 110 ret ~= oper.xltype.stripMemoryBitmask.text; 111 break; 112 113 case XlType.xltypeSRef: 114 import xlld.func.xl: Coerced; 115 auto coerced = () @trusted { return Coerced(&oper); }(); 116 return "SRef[ " ~ coerced.toString ~ " ]"; 117 118 case XlType.xltypeNum: 119 ret ~= format!"%.6f"(oper.val.num); 120 break; 121 122 case XlType.xltypeStr: 123 ret ~= `"`; 124 () @trusted { 125 const ulong length = oper.val.str[0]; 126 ret ~= text(oper.val.str[1 .. 1 + length]); 127 }(); 128 ret ~= `"`; 129 break; 130 131 case XlType.xltypeInt: 132 ret ~= text(oper.val.w); 133 break; 134 135 case XlType.xltypeBool: 136 ret ~= text(oper.val.bool_); 137 break; 138 139 case XlType.xltypeErr: 140 ret ~= "ERROR"; 141 break; 142 143 case XlType.xltypeBigData: 144 () @trusted { 145 ret ~= "BIG("; 146 ret ~= text(oper.val.bigdata.h.hdata); 147 ret ~= ", "; 148 ret ~= text(oper.val.bigdata.cbData); 149 ret ~= ")"; 150 }(); 151 } 152 ret ~= ")"; 153 return ret; 154 } 155 156 /// 157 __gshared immutable multiMemoryException = new Exception("Failed to allocate memory for multi oper"); 158 159 from!"xlld.sdk.xlcall".XLOPER12 multi(A)(int rows, int cols, ref A allocator) @trusted { 160 import xlld.sdk.xlcall: XLOPER12, XlType; 161 162 auto ret = XLOPER12(); 163 164 ret.xltype = XlType.xltypeMulti; 165 ret.val.array.rows = rows; 166 ret.val.array.columns = cols; 167 168 ret.val.array.lparray = cast(XLOPER12*)allocator.allocate(rows * cols * ret.sizeof).ptr; 169 if(ret.val.array.lparray is null) 170 throw multiMemoryException; 171 172 return ret; 173 }