mirror of
https://github.com/dlang/phobos.git
synced 2025-04-30 07:00:37 +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
|
@ -1,7 +1,7 @@
|
||||||
$(VERSION 054, ddd mm, 2011, =================================================,
|
$(VERSION 054, ddd mm, 2011, =================================================,
|
||||||
|
|
||||||
$(WHATSNEW
|
$(WHATSNEW
|
||||||
$(LI Your news here)
|
$(LI std.aray.insertInPlace supports inserting of multiple ranges/elements in one go)
|
||||||
)
|
)
|
||||||
|
|
||||||
$(LIBBUGSFIXED
|
$(LIBBUGSFIXED
|
||||||
|
|
119
std/array.d
119
std/array.d
|
@ -14,9 +14,9 @@ module std.array;
|
||||||
|
|
||||||
import core.memory, core.bitop;
|
import core.memory, core.bitop;
|
||||||
import std.algorithm, std.conv, std.ctype, std.encoding, std.exception,
|
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;
|
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
|
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
|
Inserts $(D stuff) that must consist of input ranges or a implicitly
|
||||||
implicitly convertible items) in $(D array) at position $(D pos).
|
convertible items in $(D array) at position $(D pos).
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
---
|
---
|
||||||
|
@ -614,23 +614,100 @@ void insertInPlace(T, Range)(ref T[] array, size_t pos, Range stuff)
|
||||||
|
|
||||||
/++ Ditto +/
|
/++ Ditto +/
|
||||||
void insertInPlace(T, U...)(ref T[] array, size_t pos, U stuff)
|
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;
|
dchar[staticConvertible!(dchar, U)] stackSpace = void;
|
||||||
foreach(i, v; stuff)
|
auto range = chain(makeRangeTuple(stackSpace[], stuff).expand);
|
||||||
emplace!T(&data[i], v);
|
insertInPlaceImpl(array, pos, range);
|
||||||
insertInPlaceImpl(array, pos, data[]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/++ Ditto +/
|
/++ Ditto +/
|
||||||
void insertInPlace(T, U...)(ref T[] array, size_t pos, U stuff)
|
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;
|
T[staticConvertible!(T, U)] stackSpace = void;
|
||||||
foreach(i, v; stuff)
|
auto range = chain(makeRangeTuple(stackSpace[], stuff).expand);
|
||||||
data[i] = v;
|
insertInPlaceImpl(array, pos, range);
|
||||||
insertInPlaceImpl(array, pos, data[]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
private void insertInPlaceImpl(T, Range)(ref T[] array, size_t pos, Range stuff)
|
||||||
if(isInputRange!Range &&
|
if(isInputRange!Range &&
|
||||||
(is(ElementType!Range : T) ||
|
(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([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], 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([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([1L, 2, 3, 4], 4, [10, 11], 40L, 42L,
|
||||||
assert(testVar("t"w.idup, 1, cast(wchar)'e', cast(dchar)'s', 't', "test"));
|
[1, 2, 3, 4, 10, 11, 40, 42]));
|
||||||
assert(testVar("t"d.idup, 0, 't', cast(dchar)'e', cast(wchar)'s', "test"));
|
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