Another attempt to generalize insertInPlace.

This commit is contained in:
Dmitry Olshansky 2011-06-15 01:17:09 +04:00
parent 2ef493e6c3
commit 6c7b9a0697
2 changed files with 102 additions and 19 deletions

View file

@ -14,9 +14,9 @@ module std.array;
import core.memory, core.bitop;
import std.algorithm, std.conv, std.ctype, std.encoding, std.exception,
std.range, std.string, std.traits, std.typecons, std.utf;
std.range, std.string, std.traits, std.typecons, std.utf, std.typetuple;
import std.c.string : memcpy;
version(unittest) import core.exception, std.stdio, std.typetuple;
version(unittest) import core.exception, std.stdio;
/**
Returns a newly-allocated dynamic array consisting of a copy of the
@ -592,8 +592,8 @@ unittest
+/
/++
Inserts $(D stuff) (which must be an input range or any number of
implicitly convertible items) in $(D array) at position $(D pos).
Inserts $(D stuff) that must consist of input ranges or a implicitly
convertible items in $(D array) at position $(D pos).
Example:
---
@ -614,23 +614,100 @@ void insertInPlace(T, Range)(ref T[] array, size_t pos, Range stuff)
/++ Ditto +/
void insertInPlace(T, U...)(ref T[] array, size_t pos, U stuff)
if((!isSomeString!(T[]) && isImplicitlyConvertible!(CommonType!(U),T)))
if(isSomeString!(T[]) && allSatisfy!(isCharOrString, U))
{
T[staticLength!(U)] data = void;
foreach(i, v; stuff)
emplace!T(&data[i], v);
insertInPlaceImpl(array, pos, data[]);
dchar[staticConvertible!(dchar, U)] stackSpace = void;
auto range = chain(makeRangeTuple(stackSpace[], stuff).expand);
insertInPlaceImpl(array, pos, range);
}
/++ Ditto +/
void insertInPlace(T, U...)(ref T[] array, size_t pos, U stuff)
if(isSomeString!(T[]) && is(CommonType!(U) : dchar))
if(!isSomeString!(T[]) && allSatisfy!(isInputRangeOrConvertible!T, U))
{
dchar[staticLength!(U)] data = void;
foreach(i, v; stuff)
data[i] = v;
insertInPlaceImpl(array, pos, data[]);
T[staticConvertible!(T, U)] stackSpace = void;
auto range = chain(makeRangeTuple(stackSpace[], stuff).expand);
insertInPlaceImpl(array, pos, range);
}
private template staticFrontConvertible(E, U...)
{
static if(U.length == 0)
{
enum staticFrontConvertible = 0;
}
else static if(isImplicitlyConvertible!(U[0],E))
{
enum staticFrontConvertible = 1 + staticFrontConvertible!(E, U[1..$]);
}
else
{
enum staticFrontConvertible = 0;
}
}
private template staticConvertible(E, U...)
{
static if (U.length == 0)
{
enum staticConvertible = 0;
}
else static if(isImplicitlyConvertible!(U[0], E))
{
enum staticConvertible = 1 + staticConvertible!(E, U[1..$]);
}
else
{
enum staticConvertible = staticConvertible!(E, U[1..$]);
}
}
private template isCharOrString(T)
{
enum isCharOrString = isSomeString!T || isSomeChar!T;
}
private template isInputRangeOrConvertible(E)
{
template isInputRangeOrConvertible(R)
{
enum isInputRangeOrConvertible =
(isInputRange!R && is(ElementType!R : E)) || is(R : E);
}
}
//packs individual convertible elements into provided slack array,
//and chains them with the rest into a tuple
private auto makeRangeTuple(E, U...)(E[] place, U stuff)
if(U.length > 0 && is(U[0] : E) )
{
enum toPack = staticFrontConvertible!(E, U);
foreach(i, v; stuff[0..toPack])
emplace!E(&place[i], v);
assert(place.length >= toPack);
static if(U.length != staticFrontConvertible!(E,U))
{
return tuple(place[0..toPack],
makeRangeTuple(place[toPack..$], stuff[toPack..$]).expand);
}
else
return tuple(place[0..toPack]);
}
//ditto
private auto makeRangeTuple(E, U...)(E[] place, U stuff)
if(isInputRange!(U[0]) && is(ElementType!(U[0]) : E))
{
static if(U.length == 1)
{
return tuple(stuff[0]);
}
else
{
return tuple(stuff[0],makeRangeTuple(place, stuff[1..$]).expand);
}
}
private void insertInPlaceImpl(T, Range)(ref T[] array, size_t pos, Range stuff)
if(isInputRange!Range &&
(is(ElementType!Range : T) ||
@ -757,10 +834,16 @@ unittest
assert(testVar([1, 2, 3, 4], 0, 6, 7u, [6, 7, 1, 2, 3, 4]));
assert(testVar([1L, 2, 3, 4], 2, 8, 9L, [1, 2, 8, 9, 3, 4]));
assert(testVar([1L, 2, 3, 4], 4, 10L, 11, [1, 2, 3, 4, 10, 11]));
assert(testVar("t".idup, 1, cast(dchar)'e', cast(wchar)'s', 't', "test"));
assert(testVar("t"w.idup, 1, cast(wchar)'e', cast(dchar)'s', 't', "test"));
assert(testVar("t"d.idup, 0, 't', cast(dchar)'e', cast(wchar)'s', "test"));
assert(testVar([1L, 2, 3, 4], 4, [10, 11], 40L, 42L,
[1, 2, 3, 4, 10, 11, 40, 42]));
assert(testVar([1L, 2, 3, 4], 4, 10, 11, [40L, 42],
[1, 2, 3, 4, 10, 11, 40, 42]));
assert(testVar("t".idup, 1, 'e', 's', 't', "test"));
assert(testVar("!!"w.idup, 1, "\u00e9ll\u00f4", 'x', "TTT"w, 'y',
"!\u00e9ll\u00f4xTTTy!"));
assert(testVar("flipflop"d.idup, 4, '_',
"xyz"w, '\U00010143', '_', "abc"d, "__",
"flip_xyz\U00010143_abc__flop"));
}
/++