1 /** 2 Only exists to test the wrapping functionality Contains functions 3 with regular D types that will get wrapped so they can be called by 4 the spreadsheet. 5 */ 6 7 module xlld.test_d_funcs; 8 9 version(unittest): 10 11 import xlld; 12 13 14 @Register(ArgumentText("Array to add"), 15 HelpTopic("Adds all cells in an array"), 16 FunctionHelp("Adds all cells in an array"), 17 ArgumentHelp(["The array to add"])) 18 double FuncAddEverything(double[][] args) nothrow @nogc { 19 import std.algorithm: fold; 20 import std.math: isNaN; 21 22 double ret = 0; 23 foreach(row; args) 24 ret += row.fold!((a, b) => b.isNaN ? 0.0 : a + b)(0.0); 25 return ret; 26 } 27 28 double[][] FuncTripleEverything(double[][] args) nothrow { 29 double[][] ret; 30 ret.length = args.length; 31 foreach(i; 0 .. args.length) { 32 ret[i].length = args[i].length; 33 foreach(j; 0 .. args[i].length) 34 ret[i][j] = args[i][j] * 3; 35 } 36 37 return ret; 38 } 39 40 double FuncAllLengths(string[][] args) nothrow @nogc { 41 import std.algorithm: fold; 42 43 double ret = 0; 44 foreach(row; args) 45 ret += row.fold!((a, b) => a + b.length)(0.0); 46 return ret; 47 } 48 49 double[][] FuncLengths(string[][] args) nothrow { 50 double[][] ret; 51 52 ret.length = args.length; 53 foreach(i; 0 .. args.length) { 54 ret[i].length = args[i].length; 55 foreach(j; 0 .. args[i].length) 56 ret[i][j] = args[i][j].length; 57 } 58 59 return ret; 60 } 61 62 63 string[][] FuncBob(string[][] args) nothrow { 64 string[][] ret; 65 66 ret.length = args.length; 67 foreach(i; 0 .. args.length) { 68 ret[i].length = args[i].length; 69 foreach(j; 0 .. args[i].length) 70 ret[i][j] = args[i][j] ~ "bob"; 71 } 72 73 return ret; 74 } 75 76 77 double FuncDoubleSlice(double[] arg) nothrow @nogc { 78 return arg.length; 79 } 80 81 double FuncStringSlice(string[] arg) nothrow @nogc { 82 return arg.length; 83 } 84 85 double[] FuncSliceTimes3(double[] arg) nothrow { 86 import std.algorithm; 87 import std.array; 88 return arg.map!(a => a * 3).array; 89 } 90 91 string[] StringsToStrings(string[] args) nothrow { 92 import std.algorithm; 93 import std.array; 94 return args.map!(a => a ~ "foo").array; 95 } 96 97 string StringsToString(string[] args) nothrow { 98 import std.string; 99 return args.join(", "); 100 } 101 102 string StringToString(string arg) nothrow { 103 return arg ~ "bar"; 104 } 105 106 private string shouldNotBeAProblem(string, string[]) nothrow { 107 return ""; 108 } 109 110 string ManyToString(string arg0, string arg1, string arg2) nothrow { 111 return arg0 ~ arg1 ~ arg2; 112 } 113 114 // shouldn't get wrapped 115 double FuncThrows(double) { 116 throw new Exception("oops"); 117 } 118 119 120 // @Dispose is used to tell the framework how to free memory that is dynamically 121 // allocated by the D function. After returning, the value is converted to an 122 // Excel type sand the D value is freed using the lambda defined here. 123 // In this example we're using TestAllocator to make sure that there are no 124 // memory leaks. 125 @Dispose!((ret) { 126 import xlld.test_util: gTestAllocator; 127 import std.experimental.allocator: dispose; 128 gTestAllocator.dispose(ret); 129 }) 130 double[] FuncReturnArrayNoGc(double[] numbers) @nogc @safe nothrow { 131 import xlld.test_util: gTestAllocator; 132 import std.experimental.allocator: makeArray; 133 import std.algorithm: map; 134 135 try { 136 return () @trusted { return gTestAllocator.makeArray(numbers.map!(a => a * 2)); }(); 137 } catch(Exception _) { 138 return []; 139 } 140 } 141 142 143 Any[][] DoubleArrayToAnyArray(double[][] values) @safe nothrow { 144 import std.experimental.allocator.mallocator: Mallocator; 145 import std.conv: to; 146 147 alias allocator = Mallocator.instance; 148 149 string third, fourth; 150 try { 151 third = values[1][0].to!string; 152 fourth = values[1][1].to!string; 153 } catch(Exception ex) { 154 third = "oops"; 155 fourth = "oops"; 156 } 157 158 return () @trusted { 159 with(allocatorContext(allocator)) { 160 try 161 return [ 162 [any(values[0][0] * 2), any(values[0][1] * 3)], 163 [any(third ~ "quux"), any(fourth ~ "toto")], 164 ]; 165 catch(Exception _) { 166 Any[][] empty; 167 return empty; 168 } 169 } 170 }(); 171 } 172 173 174 double[] AnyArrayToDoubleArray(Any[][] values) nothrow { 175 return [values.length, values.length ? values[0].length : 0]; 176 } 177 178 179 Any[][] AnyArrayToAnyArray(Any[][] values) nothrow { 180 return values; 181 } 182 183 Any[][] FirstOfTwoAnyArrays(Any[][] a, Any[][]) nothrow { 184 return a; 185 } 186 187 string[] EmptyStrings1D(Any) nothrow { 188 string[] empty; 189 return empty; 190 } 191 192 193 string[][] EmptyStrings2D(Any) nothrow { 194 string[][] empty; 195 return empty; 196 } 197 198 string[][] EmptyStringsHalfEmpty2D(Any) nothrow { 199 string[][] empty; 200 empty.length = 1; 201 assert(empty[0].length == 0); 202 return empty; 203 } 204 205 int Twice(int i) @safe nothrow { 206 return i * 2; 207 }