mirror of
https://github.com/dlang/phobos.git
synced 2025-05-06 11:07:39 +03:00
std.array: clean imports
assocArray: updated doc header. add scope import added global import in std.array global import std.algorithm : splitter; in std.arra; update splitter import typetuple import std.algorithm Fix split import std.algorithm fix
This commit is contained in:
parent
858296f87a
commit
3fcf723aa4
2 changed files with 132 additions and 41 deletions
|
@ -7715,7 +7715,7 @@ int cmp(alias pred = "a < b", R1, R2)(R1 r1, R2 r2) if (isSomeString!R1 && isSom
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}()
|
}()
|
||||||
: () @trusted { return core.stdc.string.memcmp(r1.ptr, r2.ptr, len); }();
|
: () @trusted { return memcmp(r1.ptr, r2.ptr, len); }();
|
||||||
if (result) return result;
|
if (result) return result;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
171
std/array.d
171
std/array.d
|
@ -12,10 +12,11 @@ Source: $(PHOBOSSRC std/_array.d)
|
||||||
*/
|
*/
|
||||||
module std.array;
|
module std.array;
|
||||||
|
|
||||||
import core.memory, core.bitop;
|
import std.range;
|
||||||
import std.algorithm, std.ascii, std.conv, std.exception, std.functional,
|
import std.traits;
|
||||||
std.range, std.string, std.traits, std.typecons, std.typetuple, std.utf;
|
import std.typetuple;
|
||||||
version(unittest) import core.exception, std.stdio;
|
import std.functional;
|
||||||
|
import std.algorithm; // FIXME (see alias below)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns a newly-allocated dynamic array consisting of a copy of the
|
Returns a newly-allocated dynamic array consisting of a copy of the
|
||||||
|
@ -38,6 +39,7 @@ if (isIterable!Range && !isNarrowString!Range && !isInfinite!Range)
|
||||||
alias E = ForeachType!Range;
|
alias E = ForeachType!Range;
|
||||||
static if (hasLength!Range)
|
static if (hasLength!Range)
|
||||||
{
|
{
|
||||||
|
import std.conv : emplaceRef;
|
||||||
if(r.length == 0) return null;
|
if(r.length == 0) return null;
|
||||||
|
|
||||||
static auto trustedAllocateArray(size_t n) @trusted nothrow
|
static auto trustedAllocateArray(size_t n) @trusted nothrow
|
||||||
|
@ -74,6 +76,7 @@ if (isIterable!Range && !isNarrowString!Range && !isInfinite!Range)
|
||||||
|
|
||||||
@safe pure nothrow unittest
|
@safe pure nothrow unittest
|
||||||
{
|
{
|
||||||
|
import std.algorithm : equal;
|
||||||
struct Foo
|
struct Foo
|
||||||
{
|
{
|
||||||
int a;
|
int a;
|
||||||
|
@ -84,6 +87,7 @@ if (isIterable!Range && !isNarrowString!Range && !isInfinite!Range)
|
||||||
|
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
|
import std.algorithm : equal;
|
||||||
struct Foo
|
struct Foo
|
||||||
{
|
{
|
||||||
int a;
|
int a;
|
||||||
|
@ -122,12 +126,15 @@ the input.
|
||||||
*/
|
*/
|
||||||
ElementType!String[] array(String)(String str) if (isNarrowString!String)
|
ElementType!String[] array(String)(String str) if (isNarrowString!String)
|
||||||
{
|
{
|
||||||
return to!(typeof(return))(str);
|
import std.utf : toUTF32;
|
||||||
|
return cast(typeof(return)) str.toUTF32;
|
||||||
}
|
}
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
static struct TestArray { int x; string toString() { return .to!string(x); } }
|
import std.conv : to;
|
||||||
|
|
||||||
|
static struct TestArray { int x; string toString() { return to!string(x); } }
|
||||||
|
|
||||||
static struct OpAssign
|
static struct OpAssign
|
||||||
{
|
{
|
||||||
|
@ -165,7 +172,7 @@ unittest
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
this(int y) { x = y; }
|
this(int y) { x = y; }
|
||||||
override string toString() const { return .to!string(x); }
|
override string toString() const { return to!string(x); }
|
||||||
}
|
}
|
||||||
auto c = array([new C(1), new C(2)][]);
|
auto c = array([new C(1), new C(2)][]);
|
||||||
//writeln(c);
|
//writeln(c);
|
||||||
|
@ -226,6 +233,7 @@ unittest
|
||||||
// Bugzilla 10220
|
// Bugzilla 10220
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
|
import std.exception;
|
||||||
import std.algorithm : equal;
|
import std.algorithm : equal;
|
||||||
import std.range : repeat;
|
import std.range : repeat;
|
||||||
|
|
||||||
|
@ -254,12 +262,15 @@ unittest
|
||||||
/**
|
/**
|
||||||
Returns a newly allocated associative array out of elements of the input range,
|
Returns a newly allocated associative array out of elements of the input range,
|
||||||
which must be a range of tuples (Key, Value).
|
which must be a range of tuples (Key, Value).
|
||||||
|
See also: $(XREF typecons, Tuple)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
auto assocArray(Range)(Range r)
|
auto assocArray(Range)(Range r)
|
||||||
if (isInputRange!Range && isTuple!(ElementType!Range) &&
|
if (isInputRange!Range &&
|
||||||
ElementType!Range.length == 2)
|
ElementType!Range.length == 2)
|
||||||
{
|
{
|
||||||
|
import std.typecons : isTuple;
|
||||||
|
static assert(isTuple!(ElementType!Range), "assocArray: argument must be a range of tuples");
|
||||||
alias KeyType = ElementType!Range.Types[0];
|
alias KeyType = ElementType!Range.Types[0];
|
||||||
alias ValueType = ElementType!Range.Types[1];
|
alias ValueType = ElementType!Range.Types[1];
|
||||||
ValueType[KeyType] aa;
|
ValueType[KeyType] aa;
|
||||||
|
@ -271,6 +282,7 @@ auto assocArray(Range)(Range r)
|
||||||
///
|
///
|
||||||
/*@safe*/ pure /*nothrow*/ unittest
|
/*@safe*/ pure /*nothrow*/ unittest
|
||||||
{
|
{
|
||||||
|
import std.typecons;
|
||||||
auto a = assocArray(zip([0, 1, 2], ["a", "b", "c"]));
|
auto a = assocArray(zip([0, 1, 2], ["a", "b", "c"]));
|
||||||
assert(is(typeof(a) == string[int]));
|
assert(is(typeof(a) == string[int]));
|
||||||
assert(a == [0:"a", 1:"b", 2:"c"]);
|
assert(a == [0:"a", 1:"b", 2:"c"]);
|
||||||
|
@ -283,6 +295,7 @@ auto assocArray(Range)(Range r)
|
||||||
/// @@@11053@@@ - Cannot be version(unittest) - recursive instantiation error
|
/// @@@11053@@@ - Cannot be version(unittest) - recursive instantiation error
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
|
import std.typecons;
|
||||||
static assert(!__traits(compiles, [ tuple("foo", "bar", "baz") ].assocArray()));
|
static assert(!__traits(compiles, [ tuple("foo", "bar", "baz") ].assocArray()));
|
||||||
static assert(!__traits(compiles, [ tuple("foo") ].assocArray()));
|
static assert(!__traits(compiles, [ tuple("foo") ].assocArray()));
|
||||||
static assert( __traits(compiles, [ tuple("foo", "bar") ].assocArray()));
|
static assert( __traits(compiles, [ tuple("foo", "bar") ].assocArray()));
|
||||||
|
@ -290,6 +303,7 @@ unittest
|
||||||
|
|
||||||
private template blockAttribute(T)
|
private template blockAttribute(T)
|
||||||
{
|
{
|
||||||
|
import core.memory;
|
||||||
static if (hasIndirections!(T) || is(T == void))
|
static if (hasIndirections!(T) || is(T == void))
|
||||||
{
|
{
|
||||||
enum blockAttribute = 0;
|
enum blockAttribute = 0;
|
||||||
|
@ -301,7 +315,8 @@ private template blockAttribute(T)
|
||||||
}
|
}
|
||||||
version(unittest)
|
version(unittest)
|
||||||
{
|
{
|
||||||
static assert(!(blockAttribute!void & GC.BlkAttr.NO_SCAN));
|
import core.memory : UGC = GC;
|
||||||
|
static assert(!(blockAttribute!void & UGC.BlkAttr.NO_SCAN));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of dimensions in an array T.
|
// Returns the number of dimensions in an array T.
|
||||||
|
@ -339,8 +354,8 @@ if (isDynamicArray!T && allSatisfy!(isIntegral, I))
|
||||||
alias toSize_t(E) = size_t;
|
alias toSize_t(E) = size_t;
|
||||||
|
|
||||||
static assert(allSatisfy!(isSize_t, I),
|
static assert(allSatisfy!(isSize_t, I),
|
||||||
format("Argument types in %s are not all convertible to size_t: %s",
|
"Argument types in "~I.stringof~" are not all convertible to size_t: "
|
||||||
I.stringof, Filter!(templateNot!(isSize_t), I).stringof));
|
~Filter!(templateNot!(isSize_t), I).stringof);
|
||||||
|
|
||||||
//Eagerlly transform non-size_t into size_t to avoid template bloat
|
//Eagerlly transform non-size_t into size_t to avoid template bloat
|
||||||
alias ST = staticMap!(toSize_t, I);
|
alias ST = staticMap!(toSize_t, I);
|
||||||
|
@ -374,9 +389,8 @@ if (isDynamicArray!T && allSatisfy!(isIntegral, I))
|
||||||
alias toSize_t(E) = size_t;
|
alias toSize_t(E) = size_t;
|
||||||
|
|
||||||
static assert(allSatisfy!(isSize_t, I),
|
static assert(allSatisfy!(isSize_t, I),
|
||||||
format("Argument types in %s are not all convertible to size_t: %s",
|
"Argument types in "~I.stringof~" are not all convertible to size_t: "
|
||||||
I.stringof, Filter!(templateNot!(isSize_t), I).stringof));
|
~Filter!(templateNot!(isSize_t), I).stringof);
|
||||||
|
|
||||||
//Eagerlly transform non-size_t into size_t to avoid template bloat
|
//Eagerlly transform non-size_t into size_t to avoid template bloat
|
||||||
alias ST = staticMap!(toSize_t, I);
|
alias ST = staticMap!(toSize_t, I);
|
||||||
|
|
||||||
|
@ -400,7 +414,7 @@ if (isDynamicArray!T && allSatisfy!(isIntegral, I))
|
||||||
private auto arrayAllocImpl(bool minimallyInitialized, T, I...)(I sizes) nothrow
|
private auto arrayAllocImpl(bool minimallyInitialized, T, I...)(I sizes) nothrow
|
||||||
{
|
{
|
||||||
static assert(I.length <= nDimensions!T,
|
static assert(I.length <= nDimensions!T,
|
||||||
format("%s dimensions specified for a %s dimensional array.", I.length, nDimensions!T));
|
I.length.stringof~"dimensions specified for a "~nDimensions!T.stringof~" dimensional array.");
|
||||||
|
|
||||||
alias E = ElementEncodingType!T;
|
alias E = ElementEncodingType!T;
|
||||||
|
|
||||||
|
@ -437,6 +451,7 @@ private auto arrayAllocImpl(bool minimallyInitialized, T, I...)(I sizes) nothrow
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
import core.stdc.string : memset;
|
import core.stdc.string : memset;
|
||||||
|
import core.memory;
|
||||||
auto ptr = cast(E*) GC.malloc(sizes[0] * E.sizeof, blockAttribute!E);
|
auto ptr = cast(E*) GC.malloc(sizes[0] * E.sizeof, blockAttribute!E);
|
||||||
static if (minimallyInitialized && hasIndirections!E)
|
static if (minimallyInitialized && hasIndirections!E)
|
||||||
memset(ptr, 0, size * E.sizeof);
|
memset(ptr, 0, size * E.sizeof);
|
||||||
|
@ -608,7 +623,7 @@ if (isNarrowString!(C[]))
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
import core.bitop;
|
import core.bitop : bsr;
|
||||||
auto msbs = 7 - bsr(~c);
|
auto msbs = 7 - bsr(~c);
|
||||||
if((msbs < 2) | (msbs > 6))
|
if((msbs < 2) | (msbs > 6))
|
||||||
{
|
{
|
||||||
|
@ -761,6 +776,7 @@ if (!isNarrowString!(T[]) && !is(T[] == void[]))
|
||||||
|
|
||||||
@property dchar front(T)(T[] a) @safe pure if (isNarrowString!(T[]))
|
@property dchar front(T)(T[] a) @safe pure if (isNarrowString!(T[]))
|
||||||
{
|
{
|
||||||
|
import std.utf : decode;
|
||||||
assert(a.length, "Attempting to fetch the front of an empty array of " ~ T.stringof);
|
assert(a.length, "Attempting to fetch the front of an empty array of " ~ T.stringof);
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
return decode(a, i);
|
return decode(a, i);
|
||||||
|
@ -801,6 +817,7 @@ dchar).
|
||||||
// Specialization for strings
|
// Specialization for strings
|
||||||
@property dchar back(T)(T[] a) @safe pure if (isNarrowString!(T[]))
|
@property dchar back(T)(T[] a) @safe pure if (isNarrowString!(T[]))
|
||||||
{
|
{
|
||||||
|
import std.utf : decode;
|
||||||
assert(a.length, "Attempting to fetch the back of an empty array of " ~ T.stringof);
|
assert(a.length, "Attempting to fetch the back of an empty array of " ~ T.stringof);
|
||||||
size_t i = a.length - std.utf.strideBack(a, a.length);
|
size_t i = a.length - std.utf.strideBack(a, a.length);
|
||||||
return decode(a, i);
|
return decode(a, i);
|
||||||
|
@ -840,6 +857,7 @@ inout(T)[] overlap(T)(inout(T)[] r1, inout(T)[] r2) @trusted pure nothrow
|
||||||
{
|
{
|
||||||
static void test(L, R)(L l, R r)
|
static void test(L, R)(L l, R r)
|
||||||
{
|
{
|
||||||
|
import std.stdio;
|
||||||
scope(failure) writeln("Types: L %s R %s", L.stringof, R.stringof);
|
scope(failure) writeln("Types: L %s R %s", L.stringof, R.stringof);
|
||||||
|
|
||||||
assert(overlap(l, r) == [ 100, 12 ]);
|
assert(overlap(l, r) == [ 100, 12 ]);
|
||||||
|
@ -908,6 +926,7 @@ T[] insert(T, Range)(T[] array, size_t pos, Range stuff)
|
||||||
{
|
{
|
||||||
static if(hasLength!Range && is(ElementEncodingType!Range : T))
|
static if(hasLength!Range && is(ElementEncodingType!Range : T))
|
||||||
{
|
{
|
||||||
|
import std.algorithm : copy;
|
||||||
auto retval = new Unqual!(T)[](array.length + stuff.length);
|
auto retval = new Unqual!(T)[](array.length + stuff.length);
|
||||||
retval[0 .. pos] = array[0 .. pos];
|
retval[0 .. pos] = array[0 .. pos];
|
||||||
copy(stuff, retval[pos .. pos + stuff.length]);
|
copy(stuff, retval[pos .. pos + stuff.length]);
|
||||||
|
@ -945,6 +964,11 @@ unittest
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
|
import core.exception;
|
||||||
|
import std.conv : to;
|
||||||
|
import std.exception;
|
||||||
|
import std.algorithm;
|
||||||
|
|
||||||
auto a = [1, 2, 3, 4];
|
auto a = [1, 2, 3, 4];
|
||||||
assert(a.insert(0, [6, 7]) == [6, 7, 1, 2, 3, 4]);
|
assert(a.insert(0, [6, 7]) == [6, 7, 1, 2, 3, 4]);
|
||||||
assert(a.insert(2, [6, 7]) == [1, 2, 6, 7, 3, 4]);
|
assert(a.insert(2, [6, 7]) == [1, 2, 6, 7, 3, 4]);
|
||||||
|
@ -1025,6 +1049,8 @@ void insertInPlace(T, U...)(ref T[] array, size_t pos, U stuff)
|
||||||
static if(allSatisfy!(isInputRangeWithLengthOrConvertible!T, U))
|
static if(allSatisfy!(isInputRangeWithLengthOrConvertible!T, U))
|
||||||
{
|
{
|
||||||
import core.stdc.string;
|
import core.stdc.string;
|
||||||
|
import std.conv : emplaceRef;
|
||||||
|
|
||||||
auto trustedAllocateArray(size_t n) @trusted nothrow
|
auto trustedAllocateArray(size_t n) @trusted nothrow
|
||||||
{
|
{
|
||||||
return uninitializedArray!(T[])(n);
|
return uninitializedArray!(T[])(n);
|
||||||
|
@ -1034,7 +1060,6 @@ void insertInPlace(T, U...)(ref T[] array, size_t pos, U stuff)
|
||||||
assert(src.length == dest.length);
|
assert(src.length == dest.length);
|
||||||
if (!__ctfe)
|
if (!__ctfe)
|
||||||
{
|
{
|
||||||
import core.stdc.string : memcpy;
|
|
||||||
memcpy(dest.ptr, src.ptr, src.length * T.sizeof);
|
memcpy(dest.ptr, src.ptr, src.length * T.sizeof);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1093,6 +1118,7 @@ void insertInPlace(T, U...)(ref T[] array, size_t pos, U stuff)
|
||||||
static if(is(Unqual!T == T)
|
static if(is(Unqual!T == T)
|
||||||
&& allSatisfy!(isInputRangeWithLengthOrConvertible!dchar, U))
|
&& allSatisfy!(isInputRangeWithLengthOrConvertible!dchar, U))
|
||||||
{
|
{
|
||||||
|
import std.utf : codeLength;
|
||||||
// mutable, can do in place
|
// mutable, can do in place
|
||||||
//helper function: re-encode dchar to Ts and store at *ptr
|
//helper function: re-encode dchar to Ts and store at *ptr
|
||||||
static T* putDChar(T* ptr, dchar ch)
|
static T* putDChar(T* ptr, dchar ch)
|
||||||
|
@ -1104,6 +1130,7 @@ void insertInPlace(T, U...)(ref T[] array, size_t pos, U stuff)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
import std.utf : encode;
|
||||||
T[dchar.sizeof/T.sizeof] buf;
|
T[dchar.sizeof/T.sizeof] buf;
|
||||||
size_t len = encode(buf, ch);
|
size_t len = encode(buf, ch);
|
||||||
final switch(len)
|
final switch(len)
|
||||||
|
@ -1147,7 +1174,7 @@ void insertInPlace(T, U...)(ref T[] array, size_t pos, U stuff)
|
||||||
ptr = putDChar(ptr, ch);
|
ptr = putDChar(ptr, ch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(ptr == array.ptr + pos + to_insert, text(ptr - array.ptr, " vs ", pos + to_insert ));
|
assert(ptr == array.ptr + pos + to_insert, "(ptr == array.ptr + pos + to_insert) is false");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1202,6 +1229,12 @@ private template isInputRangeOrConvertible(E)
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
|
import core.exception;
|
||||||
|
import std.conv : to;
|
||||||
|
import std.exception;
|
||||||
|
import std.algorithm;
|
||||||
|
|
||||||
|
|
||||||
bool test(T, U, V)(T orig, size_t pos, U toInsert, V result,
|
bool test(T, U, V)(T orig, size_t pos, U toInsert, V result,
|
||||||
string file = __FILE__, size_t line = __LINE__)
|
string file = __FILE__, size_t line = __LINE__)
|
||||||
{
|
{
|
||||||
|
@ -1290,6 +1323,7 @@ unittest
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
|
import std.algorithm : equal;
|
||||||
// insertInPlace interop with postblit
|
// insertInPlace interop with postblit
|
||||||
struct Int
|
struct Int
|
||||||
{
|
{
|
||||||
|
@ -1322,6 +1356,7 @@ unittest
|
||||||
|
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
|
import std.exception;
|
||||||
assertCTFEable!(
|
assertCTFEable!(
|
||||||
{
|
{
|
||||||
int[] a = [1, 2];
|
int[] a = [1, 2];
|
||||||
|
@ -1333,6 +1368,7 @@ unittest
|
||||||
|
|
||||||
unittest // bugzilla 6874
|
unittest // bugzilla 6874
|
||||||
{
|
{
|
||||||
|
import core.memory;
|
||||||
// allocate some space
|
// allocate some space
|
||||||
byte[] a;
|
byte[] a;
|
||||||
a.length = 1;
|
a.length = 1;
|
||||||
|
@ -1436,6 +1472,8 @@ if (isInputRange!S && !isDynamicArray!S)
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
|
import std.conv : to;
|
||||||
|
|
||||||
debug(std_array) printf("array.replicate.unittest\n");
|
debug(std_array) printf("array.replicate.unittest\n");
|
||||||
|
|
||||||
foreach (S; TypeTuple!(string, wstring, dstring, char[], wchar[], dchar[]))
|
foreach (S; TypeTuple!(string, wstring, dstring, char[], wchar[], dchar[]))
|
||||||
|
@ -1493,6 +1531,10 @@ if (isSomeString!S)
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
|
import std.conv : to;
|
||||||
|
import std.string;
|
||||||
|
import std.typecons;
|
||||||
|
|
||||||
static auto makeEntry(S)(string l, string[] r)
|
static auto makeEntry(S)(string l, string[] r)
|
||||||
{return tuple(l.to!S(), r.to!(S[])());}
|
{return tuple(l.to!S(), r.to!(S[])());}
|
||||||
|
|
||||||
|
@ -1521,6 +1563,7 @@ unittest
|
||||||
|
|
||||||
unittest //safety, purity, ctfe ...
|
unittest //safety, purity, ctfe ...
|
||||||
{
|
{
|
||||||
|
import std.exception;
|
||||||
void dg() @safe pure {
|
void dg() @safe pure {
|
||||||
assert(split("hello world"c) == ["hello"c, "world"c]);
|
assert(split("hello world"c) == ["hello"c, "world"c]);
|
||||||
assert(split("hello world"w) == ["hello"w, "world"w]);
|
assert(split("hello world"w) == ["hello"w, "world"w]);
|
||||||
|
@ -1543,37 +1586,29 @@ See also: $(XREF algorithm, splitter) for the lazy version of this operator.
|
||||||
auto split(R, E)(R r, E delim)
|
auto split(R, E)(R r, E delim)
|
||||||
if (isForwardRange!R && is(typeof(ElementType!R.init == E.init)))
|
if (isForwardRange!R && is(typeof(ElementType!R.init == E.init)))
|
||||||
{
|
{
|
||||||
auto spl = std.algorithm.splitter(r, delim);
|
import std.algorithm : splitter;
|
||||||
alias S = typeof(spl.front.init); // "Slice_t"
|
return r.splitter(delim).array;
|
||||||
auto app = appender!(S[])();
|
|
||||||
foreach (e; spl)
|
|
||||||
app.put(e);
|
|
||||||
return app.data;
|
|
||||||
}
|
}
|
||||||
|
///ditto
|
||||||
auto split(R1, R2)(R1 r, R2 delim)
|
auto split(R1, R2)(R1 r, R2 delim)
|
||||||
if (isForwardRange!R1 && isForwardRange!R2 && is(typeof(ElementType!R1.init == ElementType!R2.init)))
|
if (isForwardRange!R1 && isForwardRange!R2 && is(typeof(ElementType!R1.init == ElementType!R2.init)))
|
||||||
{
|
{
|
||||||
auto spl = std.algorithm.splitter(r, delim);
|
import std.algorithm : splitter;
|
||||||
alias S = typeof(spl.front.init); // "Slice_t"
|
return r.splitter(delim).array;
|
||||||
auto app = appender!(S[])();
|
|
||||||
foreach (e; spl)
|
|
||||||
app.put(e);
|
|
||||||
return app.data;
|
|
||||||
}
|
}
|
||||||
///ditto
|
///ditto
|
||||||
auto split(alias isTerminator, R)(R r)
|
auto split(alias isTerminator, R)(R r)
|
||||||
if (isForwardRange!R && is(typeof(unaryFun!isTerminator(r.front))))
|
if (isForwardRange!R && is(typeof(unaryFun!isTerminator(r.front))))
|
||||||
{
|
{
|
||||||
auto spl = std.algorithm.splitter!isTerminator(r);
|
import std.algorithm : splitter;
|
||||||
alias S = typeof(spl.front.init); // "Slice_t"
|
return r.splitter!isTerminator.array;
|
||||||
auto app = appender!(S[])();
|
|
||||||
foreach (e; spl)
|
|
||||||
app.put(e);
|
|
||||||
return app.data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
|
import std.conv;
|
||||||
|
import std.algorithm : cmp;
|
||||||
|
|
||||||
debug(std_array) printf("array.split\n");
|
debug(std_array) printf("array.split\n");
|
||||||
foreach (S; TypeTuple!(string, wstring, dstring,
|
foreach (S; TypeTuple!(string, wstring, dstring,
|
||||||
immutable(string), immutable(wstring), immutable(dstring),
|
immutable(string), immutable(wstring), immutable(dstring),
|
||||||
|
@ -1644,7 +1679,10 @@ ElementEncodingType!(ElementType!RoR)[] join(RoR, R)(RoR ror, R sep)
|
||||||
// and makes sure it has the same string encoding for string types.
|
// and makes sure it has the same string encoding for string types.
|
||||||
static if (isSomeString!RetType &&
|
static if (isSomeString!RetType &&
|
||||||
!is(Unqual!(ElementEncodingType!RetType) == Unqual!(ElementEncodingType!R)))
|
!is(Unqual!(ElementEncodingType!RetType) == Unqual!(ElementEncodingType!R)))
|
||||||
|
{
|
||||||
|
import std.conv : to;
|
||||||
auto sepArr = to!RetType(sep);
|
auto sepArr = to!RetType(sep);
|
||||||
|
}
|
||||||
else static if (!isArray!R)
|
else static if (!isArray!R)
|
||||||
auto sepArr = array(sep);
|
auto sepArr = array(sep);
|
||||||
else
|
else
|
||||||
|
@ -1697,6 +1735,7 @@ ElementEncodingType!(ElementType!RoR)[] join(RoR, E)(RoR ror, E sep)
|
||||||
static if ((is(E == wchar) || is(E == dchar))
|
static if ((is(E == wchar) || is(E == dchar))
|
||||||
&& !is(RetTypeElement == dchar))
|
&& !is(RetTypeElement == dchar))
|
||||||
{
|
{
|
||||||
|
import std.utf : encode;
|
||||||
RetTypeElement[4] encodeSpace;
|
RetTypeElement[4] encodeSpace;
|
||||||
immutable sepArrLength = encode(encodeSpace, sep);
|
immutable sepArrLength = encode(encodeSpace, sep);
|
||||||
}
|
}
|
||||||
|
@ -1736,6 +1775,7 @@ ElementEncodingType!(ElementType!RoR)[] join(RoR)(RoR ror)
|
||||||
auto result = appender!RetType();
|
auto result = appender!RetType();
|
||||||
static if(isForwardRange!RoR && (hasLength!R || isNarrowString!R))
|
static if(isForwardRange!RoR && (hasLength!R || isNarrowString!R))
|
||||||
{
|
{
|
||||||
|
import std.algorithm : reduce;
|
||||||
// Reserve appender length if it can be computed.
|
// Reserve appender length if it can be computed.
|
||||||
immutable resultLen = reduce!("a + b.length")(cast(size_t) 0, ror.save);
|
immutable resultLen = reduce!("a + b.length")(cast(size_t) 0, ror.save);
|
||||||
result.reserve(resultLen);
|
result.reserve(resultLen);
|
||||||
|
@ -1762,6 +1802,8 @@ ElementEncodingType!(ElementType!RoR)[] join(RoR)(RoR ror)
|
||||||
|
|
||||||
@safe pure unittest
|
@safe pure unittest
|
||||||
{
|
{
|
||||||
|
import std.conv : to;
|
||||||
|
|
||||||
assert(join(["hello", "silly", "world"], ' ') == "hello silly world");
|
assert(join(["hello", "silly", "world"], ' ') == "hello silly world");
|
||||||
|
|
||||||
foreach (T; TypeTuple!(string,wstring,dstring))
|
foreach (T; TypeTuple!(string,wstring,dstring))
|
||||||
|
@ -1781,6 +1823,9 @@ ElementEncodingType!(ElementType!RoR)[] join(RoR)(RoR ror)
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
|
import std.conv : to;
|
||||||
|
import std.algorithm;
|
||||||
|
|
||||||
debug(std_array) printf("array.join.unittest\n");
|
debug(std_array) printf("array.join.unittest\n");
|
||||||
|
|
||||||
foreach(R; TypeTuple!(string, wstring, dstring))
|
foreach(R; TypeTuple!(string, wstring, dstring))
|
||||||
|
@ -1885,6 +1930,7 @@ unittest
|
||||||
// Issue 10683
|
// Issue 10683
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
|
import std.range : join;
|
||||||
import std.typecons : tuple;
|
import std.typecons : tuple;
|
||||||
assert([[tuple(1)]].join == [tuple(1)]);
|
assert([[tuple(1)]].join == [tuple(1)]);
|
||||||
assert([[tuple("x")]].join == [tuple("x")]);
|
assert([[tuple("x")]].join == [tuple("x")]);
|
||||||
|
@ -1951,6 +1997,9 @@ if (isOutputRange!(Sink, E) && isDynamicArray!(E[])
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
|
import std.conv : to;
|
||||||
|
import std.algorithm : cmp;
|
||||||
|
|
||||||
debug(std_array) printf("array.replace.unittest\n");
|
debug(std_array) printf("array.replace.unittest\n");
|
||||||
|
|
||||||
foreach (S; TypeTuple!(string, wstring, dstring, char[], wchar[], dchar[]))
|
foreach (S; TypeTuple!(string, wstring, dstring, char[], wchar[], dchar[]))
|
||||||
|
@ -1981,6 +2030,9 @@ unittest
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
|
import std.conv : to;
|
||||||
|
import std.algorithm : skipOver;
|
||||||
|
|
||||||
struct CheckOutput(C)
|
struct CheckOutput(C)
|
||||||
{
|
{
|
||||||
C[] desired;
|
C[] desired;
|
||||||
|
@ -2010,6 +2062,7 @@ T[] replace(T, Range)(T[] subject, size_t from, size_t to, Range stuff)
|
||||||
{
|
{
|
||||||
static if(hasLength!Range && is(ElementEncodingType!Range : T))
|
static if(hasLength!Range && is(ElementEncodingType!Range : T))
|
||||||
{
|
{
|
||||||
|
import std.algorithm : copy;
|
||||||
assert(from <= to);
|
assert(from <= to);
|
||||||
immutable sliceLen = to - from;
|
immutable sliceLen = to - from;
|
||||||
auto retval = new Unqual!(T)[](subject.length - sliceLen + stuff.length);
|
auto retval = new Unqual!(T)[](subject.length - sliceLen + stuff.length);
|
||||||
|
@ -2042,6 +2095,12 @@ unittest
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
|
import core.exception;
|
||||||
|
import std.conv : to;
|
||||||
|
import std.exception;
|
||||||
|
import std.algorithm;
|
||||||
|
|
||||||
|
|
||||||
auto a = [ 1, 2, 3, 4 ];
|
auto a = [ 1, 2, 3, 4 ];
|
||||||
assert(replace(a, 0, 0, [5, 6, 7]) == [5, 6, 7, 1, 2, 3, 4]);
|
assert(replace(a, 0, 0, [5, 6, 7]) == [5, 6, 7, 1, 2, 3, 4]);
|
||||||
assert(replace(a, 0, 2, cast(int[])[]) == [3, 4]);
|
assert(replace(a, 0, 2, cast(int[])[]) == [3, 4]);
|
||||||
|
@ -2118,6 +2177,9 @@ void replaceInPlace(T, Range)(ref T[] array, size_t from, size_t to, Range stuff
|
||||||
!is(T == const T) &&
|
!is(T == const T) &&
|
||||||
!is(T == immutable T))
|
!is(T == immutable T))
|
||||||
{
|
{
|
||||||
|
import std.algorithm : remove;
|
||||||
|
import std.typecons : tuple;
|
||||||
|
|
||||||
if (overlap(array, stuff).length)
|
if (overlap(array, stuff).length)
|
||||||
{
|
{
|
||||||
// use slower/conservative method
|
// use slower/conservative method
|
||||||
|
@ -2175,6 +2237,12 @@ unittest
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
|
import core.exception;
|
||||||
|
import std.conv : to;
|
||||||
|
import std.exception;
|
||||||
|
import std.algorithm;
|
||||||
|
|
||||||
|
|
||||||
bool test(T, U, V)(T orig, size_t from, size_t to, U toReplace, V result,
|
bool test(T, U, V)(T orig, size_t from, size_t to, U toReplace, V result,
|
||||||
string file = __FILE__, size_t line = __LINE__)
|
string file = __FILE__, size_t line = __LINE__)
|
||||||
{
|
{
|
||||||
|
@ -2262,6 +2330,9 @@ if (isDynamicArray!(E[]) &&
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
|
import std.conv : to;
|
||||||
|
import std.algorithm : cmp;
|
||||||
|
|
||||||
debug(std_array) printf("array.replaceFirst.unittest\n");
|
debug(std_array) printf("array.replaceFirst.unittest\n");
|
||||||
|
|
||||||
foreach(S; TypeTuple!(string, wstring, dstring, char[], wchar[], dchar[],
|
foreach(S; TypeTuple!(string, wstring, dstring, char[], wchar[], dchar[],
|
||||||
|
@ -2318,6 +2389,7 @@ body
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
|
import std.algorithm : cmp;
|
||||||
debug(std_array) printf("array.replaceSlice.unittest\n");
|
debug(std_array) printf("array.replaceSlice.unittest\n");
|
||||||
|
|
||||||
string s = "hello";
|
string s = "hello";
|
||||||
|
@ -2337,6 +2409,8 @@ efficient.
|
||||||
struct Appender(A)
|
struct Appender(A)
|
||||||
if (isDynamicArray!A)
|
if (isDynamicArray!A)
|
||||||
{
|
{
|
||||||
|
import core.memory;
|
||||||
|
|
||||||
private alias T = ElementEncodingType!A;
|
private alias T = ElementEncodingType!A;
|
||||||
private struct Data
|
private struct Data
|
||||||
{
|
{
|
||||||
|
@ -2523,12 +2597,15 @@ if (isDynamicArray!A)
|
||||||
* - std.utf.encode
|
* - std.utf.encode
|
||||||
*/
|
*/
|
||||||
// must do some transcoding around here
|
// must do some transcoding around here
|
||||||
|
import std.utf : encode;
|
||||||
Unqual!T[T.sizeof == 1 ? 4 : 2] encoded;
|
Unqual!T[T.sizeof == 1 ? 4 : 2] encoded;
|
||||||
auto len = std.utf.encode(encoded, item);
|
auto len = encode(encoded, item);
|
||||||
put(encoded[0 .. len]);
|
put(encoded[0 .. len]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
import std.conv : emplaceRef;
|
||||||
|
|
||||||
ensureAddable(1);
|
ensureAddable(1);
|
||||||
immutable len = _data.arr.length;
|
immutable len = _data.arr.length;
|
||||||
|
|
||||||
|
@ -2594,6 +2671,7 @@ if (isDynamicArray!A)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
import std.conv : emplaceRef;
|
||||||
foreach (ref it ; bigData[len .. newlen])
|
foreach (ref it ; bigData[len .. newlen])
|
||||||
{
|
{
|
||||||
emplaceRef!T(it, items.front);
|
emplaceRef!T(it, items.front);
|
||||||
|
@ -2662,6 +2740,7 @@ if (isDynamicArray!A)
|
||||||
*/
|
*/
|
||||||
void shrinkTo(size_t newlength) @safe pure
|
void shrinkTo(size_t newlength) @safe pure
|
||||||
{
|
{
|
||||||
|
import std.exception : enforce;
|
||||||
if (_data)
|
if (_data)
|
||||||
{
|
{
|
||||||
enforce(newlength <= _data.arr.length);
|
enforce(newlength <= _data.arr.length);
|
||||||
|
@ -2716,6 +2795,7 @@ unittest
|
||||||
//ret sugLen: A suggested growth.
|
//ret sugLen: A suggested growth.
|
||||||
private size_t appenderNewCapacity(size_t TSizeOf)(size_t curLen, size_t reqLen) @safe pure nothrow
|
private size_t appenderNewCapacity(size_t TSizeOf)(size_t curLen, size_t reqLen) @safe pure nothrow
|
||||||
{
|
{
|
||||||
|
import core.bitop : bsr;
|
||||||
import std.algorithm : max;
|
import std.algorithm : max;
|
||||||
if(curLen == 0)
|
if(curLen == 0)
|
||||||
return max(reqLen,8);
|
return max(reqLen,8);
|
||||||
|
@ -2831,6 +2911,7 @@ Appender!(E[]) appender(A : E[], E)(auto ref A array)
|
||||||
|
|
||||||
@safe pure nothrow unittest
|
@safe pure nothrow unittest
|
||||||
{
|
{
|
||||||
|
import std.exception;
|
||||||
{
|
{
|
||||||
auto app = appender!(char[])();
|
auto app = appender!(char[])();
|
||||||
string b = "abcdefg";
|
string b = "abcdefg";
|
||||||
|
@ -2983,6 +3064,8 @@ Appender!(E[]) appender(A : E[], E)(auto ref A array)
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
|
import std.typecons;
|
||||||
|
import std.algorithm;
|
||||||
//10690
|
//10690
|
||||||
[tuple(1)].filter!(t => true).array; // No error
|
[tuple(1)].filter!(t => true).array; // No error
|
||||||
[tuple("A")].filter!(t => true).array; // error
|
[tuple("A")].filter!(t => true).array; // error
|
||||||
|
@ -3062,6 +3145,7 @@ unittest
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
|
import std.algorithm : map;
|
||||||
//10753
|
//10753
|
||||||
struct Foo {
|
struct Foo {
|
||||||
immutable dchar d;
|
immutable dchar d;
|
||||||
|
@ -3109,6 +3193,7 @@ unittest
|
||||||
|
|
||||||
unittest //Test large allocations (for GC.extend)
|
unittest //Test large allocations (for GC.extend)
|
||||||
{
|
{
|
||||||
|
import std.algorithm : equal;
|
||||||
Appender!(char[]) app;
|
Appender!(char[]) app;
|
||||||
app.reserve(1); //cover reserve on non-initialized
|
app.reserve(1); //cover reserve on non-initialized
|
||||||
foreach(_; 0 .. 100_000)
|
foreach(_; 0 .. 100_000)
|
||||||
|
@ -3193,6 +3278,7 @@ RefAppender!(E[]) appender(A : E[]*, E)(A array)
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
|
import std.exception;
|
||||||
{
|
{
|
||||||
auto arr = new char[0];
|
auto arr = new char[0];
|
||||||
auto app = appender(&arr);
|
auto app = appender(&arr);
|
||||||
|
@ -3274,11 +3360,13 @@ use yet.
|
||||||
*/
|
*/
|
||||||
struct SimpleSlice(T)
|
struct SimpleSlice(T)
|
||||||
{
|
{
|
||||||
|
import core.memory;
|
||||||
|
|
||||||
private T * _b, _e;
|
private T * _b, _e;
|
||||||
|
|
||||||
this(U...)(U values)
|
this(U...)(U values)
|
||||||
{
|
{
|
||||||
_b = cast(T*) core.memory.GC.malloc(U.length * T.sizeof);
|
_b = cast(T*) GC.malloc(U.length * T.sizeof);
|
||||||
_e = _b + U.length;
|
_e = _b + U.length;
|
||||||
foreach (i, Unused; U) _b[i] = values[i];
|
foreach (i, Unused; U) _b[i] = values[i];
|
||||||
}
|
}
|
||||||
|
@ -3295,6 +3383,7 @@ struct SimpleSlice(T)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
import std.exception : enforce;
|
||||||
// assign another slice to this
|
// assign another slice to this
|
||||||
enforce(anotherSlice.length == length);
|
enforce(anotherSlice.length == length);
|
||||||
auto p = _b;
|
auto p = _b;
|
||||||
|
@ -3376,6 +3465,7 @@ struct SimpleSlice(T)
|
||||||
/// Ditto
|
/// Ditto
|
||||||
SimpleSliceLvalue!T opSlice(size_t x, size_t y)
|
SimpleSliceLvalue!T opSlice(size_t x, size_t y)
|
||||||
{
|
{
|
||||||
|
import std.exception : enforce;
|
||||||
enforce(x <= y && y <= length);
|
enforce(x <= y && y <= length);
|
||||||
typeof(return) result = { _b + x, _b + y };
|
typeof(return) result = { _b + x, _b + y };
|
||||||
return result;
|
return result;
|
||||||
|
@ -3396,7 +3486,7 @@ struct SimpleSlice(T)
|
||||||
void length(size_t newLength)
|
void length(size_t newLength)
|
||||||
{
|
{
|
||||||
immutable oldLength = length;
|
immutable oldLength = length;
|
||||||
_b = cast(T*) core.memory.GC.realloc(_b, newLength * T.sizeof);
|
_b = cast(T*) GC.realloc(_b, newLength * T.sizeof);
|
||||||
_e = _b + newLength;
|
_e = _b + newLength;
|
||||||
this[oldLength .. $] = T.init;
|
this[oldLength .. $] = T.init;
|
||||||
}
|
}
|
||||||
|
@ -3408,7 +3498,7 @@ struct SimpleSlice(T)
|
||||||
immutable newLen = length + another.length;
|
immutable newLen = length + another.length;
|
||||||
typeof(return) result = void;
|
typeof(return) result = void;
|
||||||
result._b = cast(T*)
|
result._b = cast(T*)
|
||||||
core.memory.GC.malloc(newLen * T.sizeof);
|
GC.malloc(newLen * T.sizeof);
|
||||||
result._e = result._b + newLen;
|
result._e = result._b + newLen;
|
||||||
result[0 .. this.length] = this;
|
result[0 .. this.length] = this;
|
||||||
result[this.length .. result.length] = another;
|
result[this.length .. result.length] = another;
|
||||||
|
@ -3441,6 +3531,7 @@ struct SimpleSliceLvalue(T)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
import std.exception : enforce;
|
||||||
// assign another slice to this
|
// assign another slice to this
|
||||||
enforce(anotherSlice.length == length);
|
enforce(anotherSlice.length == length);
|
||||||
auto p = _b;
|
auto p = _b;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue