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, isInputRange; 12 13 alias E = ElementType!R; 14 15 import std.traits : isAssignable; 16 enum isScalarAssignable(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 && // TODO: generalize to is(typeof(data.length += 0)) 25 allSatisfy!(isScalarAssignable, Args)) 26 { 27 data.length += args.length; 28 foreach (i, arg; args) 29 data[$ - args.length + i] = arg; 30 } 31 else // TODO: only when all `args' has length 32 { 33 /// Returns: sum of lengths of `args`. 34 static size_t totalLength(scope Args args) 35 { 36 import std.traits : isArray; 37 import std.range.primitives : hasLength; 38 size_t result; 39 foreach (i, arg; args) 40 { 41 alias Arg = typeof(arg); 42 static if (isScalarAssignable!Arg) 43 result += 1; 44 else static if (isArray!Arg && // TODO: generalize to hasIndexing 45 is(E == ElementType!Arg) && 46 hasLength!Arg) 47 result += arg.length; 48 else static if (isInputRange!Arg && 49 hasLength!Arg && 50 isAssignable!(E, ElementType!Arg)) 51 result += arg.length; 52 else 53 static assert(0, i.stringof ~ ": cannot append arg of type " ~ Arg.stringof ~ " to " ~ R.stringof ~ " " ~ isScalarAssignable!Arg.stringof); 54 } 55 return result; 56 } 57 58 // TODO: add case for when data += length 59 60 import std.range: appender; 61 auto app = appender!(R)(data); 62 63 app.reserve(data.length + totalLength(args)); 64 65 foreach (arg; args) 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 }