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...)(return ref R data, 8 auto ref Args args) 9 if (args.length != 0) { 10 import std.range.primitives : ElementType, isRandomAccessRange, isInputRange; 11 12 alias E = ElementType!R; 13 14 import std.traits : isAssignable; 15 enum isScalarAssignable(U) = isAssignable!(E, U); 16 17 import std.meta : allSatisfy; 18 19 static if (args.length == 1) { 20 data ~= args[0]; 21 } 22 else static if (isRandomAccessRange!R && /+ TODO: generalize to is(typeof(data.length += 0)) +/ 23 allSatisfy!(isScalarAssignable, Args)) { 24 data.length += args.length; 25 foreach (i, arg; args) 26 data[$ - args.length + i] = arg; 27 } 28 else /+ TODO: only when all `args' has length +/ 29 { 30 /// Returns: sum of lengths of `args`. 31 static size_t totalLength(scope Args args) { 32 import std.traits : isArray; 33 import std.range.primitives : hasLength; 34 size_t result; 35 foreach (i, arg; args) { 36 alias Arg = typeof(arg); 37 static if (isScalarAssignable!Arg) 38 result += 1; 39 else static if (isArray!Arg && /+ TODO: generalize to hasIndexing +/ 40 is(E == ElementType!Arg) && 41 hasLength!Arg) 42 result += arg.length; 43 else static if (isInputRange!Arg && 44 hasLength!Arg && 45 isAssignable!(E, ElementType!Arg)) 46 result += arg.length; 47 else 48 static assert(0, i.stringof ~ ": cannot append arg of type " ~ Arg.stringof ~ " to " ~ R.stringof ~ " " ~ isScalarAssignable!Arg.stringof); 49 } 50 return result; 51 } 52 53 /+ TODO: add case for when data += length +/ 54 55 import std.range: appender; 56 auto app = appender!(R)(data); 57 58 app.reserve(data.length + totalLength(args)); 59 60 foreach (arg; args) 61 app.put(arg); 62 63 data = app.data; 64 } 65 66 return data; 67 } 68 69 /// 70 pure nothrow @safe unittest { 71 int[] data; 72 import std.range: only, iota; 73 74 data.append(-1, 0, only(1, 2, 3), iota(4, 9)); 75 assert(data == [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8]); 76 77 data.append(9, 10); 78 assert(data == [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); 79 80 data.append([11, 12], [13, 14]); 81 assert(data == [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]); 82 83 // int[3] d; 84 // data.append(d, d); 85 86 static assert(!__traits(compiles, { data.append(); })); 87 }