1 module nxt.appending; 2 3 /** Append arguments $(args) to `data`. 4 * 5 * See_Also: http://forum.dlang.org/thread/mevnosveagdiswkxtbrv@forum.dlang.org?page=1 6 */ 7 ref R append(R, Args...)(ref R data, 8 auto ref Args args) 9 if (args.length != 0) 10 { 11 import std.range.primitives : ElementType, isRandomAccessRange; 12 13 alias E = ElementType!R; 14 15 import std.traits : isAssignable; 16 enum isElementType(U) = isAssignable!(E, U); 17 18 import std.meta : allSatisfy; 19 20 static if (args.length == 1) 21 { 22 data ~= args[0]; 23 } 24 else static if (isRandomAccessRange!R && 25 allSatisfy!(isElementType, Args)) 26 { 27 data.length += args.length; 28 foreach (i, arg; args) 29 { 30 data[$ - args.length + i] = arg; 31 } 32 } 33 else 34 { 35 static size_t estimateLength(Args args) 36 { 37 size_t result; 38 import std.traits : isArray; 39 foreach (arg; args) 40 { 41 alias A = typeof(arg); 42 import std.range.primitives : hasLength; 43 static if (isArray!A && 44 is(E == ElementType!A) && 45 hasLength!A) 46 { 47 result += arg.length; 48 } 49 else 50 { 51 result += 1; 52 } 53 } 54 // import std.stdio; 55 // writeln(args, ` : `, result); 56 return result; 57 } 58 59 import std.range: appender; 60 auto app = appender!(R)(data); 61 62 app.reserve(data.length + estimateLength(args)); 63 64 foreach (arg; args) 65 { 66 app.put(arg); 67 } 68 data = app.data; 69 } 70 71 return data; 72 } 73 74 /// 75 @safe pure nothrow unittest 76 { 77 int[] data; 78 import std.range: only, iota; 79 80 data.append(-1, 0, only(1, 2, 3), iota(4, 9)); 81 assert(data == [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8]); 82 83 data.append(9, 10); 84 assert(data == [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); 85 86 data.append([11, 12], [13, 14]); 87 assert(data == [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]); 88 89 // int[3] d; 90 // data.append(d, d); 91 92 static assert(!__traits(compiles, { data.append(); })); 93 }