mirror of
https://github.com/dlang/phobos.git
synced 2025-04-28 22:21:09 +03:00
Another attempt to generalize insertInPlace.
This commit is contained in:
parent
2ef493e6c3
commit
6c7b9a0697
2 changed files with 102 additions and 19 deletions
119
std/array.d
119
std/array.d
|
@ -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"));
|
||||
}
|
||||
|
||||
/++
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue