// Written in the D programming language./**Functions and types that manipulate built-in arrays and associative arrays. This module provides all kinds of functions to create, manipulate or convert arrays: $(SCRIPT inhibitQuickIndex = 1;)$(DIVC quickindex,$(BOOKTABLE ,$(TR $(TH Function Name) $(TH Description)) $(TR $(TD $(LREF array)) $(TD Returns a copy of the input in a newly allocated dynamic array. )) $(TR $(TD $(LREF appender)) $(TD Returns a new $(LREF Appender) or $(LREF RefAppender) initialized with a given array. )) $(TR $(TD $(LREF assocArray)) $(TD Returns a newly allocated associative array from a range/ranges of keys and values. )) $(TR $(TD $(LREF byPair)) $(TD Construct a range iterating over an associative array by key/value tuples. )) $(TR $(TD $(LREF insertInPlace)) $(TD Inserts into an existing array at a given position. )) $(TR $(TD $(LREF join)) $(TD Concatenates a range of ranges into one array. )) $(TR $(TD $(LREF minimallyInitializedArray)) $(TD Returns a new array of type `T`. )) $(TR $(TD $(LREF replace)) $(TD Returns a new array with all occurrences of a certain subrange replaced. )) $(TR $(TD $(LREF replaceFirst)) $(TD Returns a new array with the first occurrence of a certain subrange replaced. )) $(TR $(TD $(LREF replaceInPlace)) $(TD Replaces all occurrences of a certain subrange and puts the result into a given array. )) $(TR $(TD $(LREF replaceInto)) $(TD Replaces all occurrences of a certain subrange and puts the result into an output range. )) $(TR $(TD $(LREF replaceLast)) $(TD Returns a new array with the last occurrence of a certain subrange replaced. )) $(TR $(TD $(LREF replaceSlice)) $(TD Returns a new array with a given slice replaced. )) $(TR $(TD $(LREF replicate)) $(TD Creates a new array out of several copies of an input array or range. )) $(TR $(TD $(LREF sameHead)) $(TD Checks if the initial segments of two arrays refer to the same place in memory. )) $(TR $(TD $(LREF sameTail)) $(TD Checks if the final segments of two arrays refer to the same place in memory. )) $(TR $(TD $(LREF split)) $(TD Eagerly split a range or string into an array. )) $(TR $(TD $(LREF staticArray)) $(TD Creates a new static array from given data. )) $(TR $(TD $(LREF uninitializedArray)) $(TD Returns a new array of type `T` without initializing its elements. )))) Copyright: Copyright Andrei Alexandrescu 2008- and Jonathan M Davis 2011-. License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0). Authors: $(HTTP erdani.org, Andrei Alexandrescu) and $(HTTP jmdavisprog.com, Jonathan M Davis) Source: $(PHOBOSSRC std/array.d)*/module std.array; import std.functional;import std.meta;import std.traits; import std.range.primitives;public import std.range.primitives : save, empty, popFront, popBack, front, back; /** * Allocates an array and initializes it with copies of the elements * of range `r`. * * Narrow strings are handled as follows: * - If autodecoding is turned on (default), then they are handled as a separate overload. * - If autodecoding is turned off, then this is equivalent to duplicating the array. * * Params: * r = range (or aggregate with `opApply` function) whose elements are copied into the allocated array * Returns: * allocated and initialized array */ForeachType!Range[] array(Range)(Range r)if (isIterable!Range && !isAutodecodableString!Range && !isInfinite!Range){ if (__ctfe) { // Compile-time version to avoid memcpy calls. // Also used to infer attributes of array(). typeof(return) result; foreach (e; r) result ~= e; return result; } alias E = ForeachType!Range; static if (hasLength!Range) { const length = r.length; if (length == 0) return null; import core.internal.lifetime : emplaceRef; auto result = (() @trusted => uninitializedArray!(Unqual!E[])(length))(); // Every element of the uninitialized array must be initialized size_t cnt; //Number of elements that have been initialized try { foreach (e; r) { emplaceRef!E(result[cnt], e); ++cnt; } } catch (Exception e) { //https://issues.dlang.org/show_bug.cgi?id=22185 //Make any uninitialized elements safely destructible. foreach (ref elem; result[cnt..$]) { import core.internal.lifetime : emplaceInitializer; emplaceInitializer(elem); } throw e; } /* https://issues.dlang.org/show_bug.cgi?id=22673 We preallocated an array, we should ensure that enough range elements were gathered such that every slot in the array is filled. If not, the GC will collect the allocated array, leading to the `length - cnt` left over elements being collected too - despite their contents having no guarantee of destructibility. */ assert(length == cnt, "Range .length property was not equal to the length yielded by the range before becoming empty"); return (() @trusted => cast(E[]) result)(); } else { auto a = appender!(E[])(); foreach (e; r) { a.put(e); } return a.data; }} /// dittoForeachType!(typeof((*Range).init))[] array(Range)(Range r)if (is(Range == U*, U) && isIterable!U && !isAutodecodableString!Range && !isInfinite!Range){ return array(*r);} ///@safe pure nothrow unittest{ auto a = array([1, 2, 3, 4, 5][]); assert(a == [ 1, 2, 3, 4, 5 ]);} @safe pure nothrow unittest{ import std.algorithm.comparison : equal; struct Foo { int a; } auto a = array([Foo(1), Foo(2), Foo(3), Foo(4), Foo(5)][]); assert(equal(a, [Foo(1), Foo(2), Foo(3), Foo(4), Foo(5)]));} @safe pure nothrow unittest{ struct MyRange { enum front = 123; enum empty = true; void popFront() {} } auto arr = (new MyRange).array; assert(arr.empty);} @safe pure nothrow unittest{ immutable int[] a = [1, 2, 3, 4]; auto b = (&a).array; assert(b == a);} @safe pure nothrow unittest{ import std.algorithm.comparison : equal; struct Foo { int a; noreturn opAssign(Foo) { assert(0); } auto opEquals(Foo foo) { return a == foo.a; } } auto a = array([Foo(1), Foo(2), Foo(3), Foo(4), Foo(5)][]); assert(equal(a, [Foo(1), Foo(2), Foo(3), Foo(4), Foo(5)]));} // https://issues.dlang.org/show_bug.cgi?id=12315@safe pure nothrow unittest{ static struct Bug12315 { immutable int i; } enum bug12315 = [Bug12315(123456789)].array(); static assert(bug12315[0].i == 123456789);} @safe pure nothrow unittest{ import std.range; static struct S{int* p;} auto a = array(immutable(S).init.repeat(5)); assert(a.length == 5);} // https://issues.dlang.org/show_bug.cgi?id=18995@system unittest{ import core.memory : __delete; int nAlive = 0; struct S { bool alive; this(int) { alive = true; ++nAlive; } this(this) { nAlive += alive; } ~this() { nAlive -= alive; alive = false; } } import std.algorithm.iteration : map; import std.range : iota; auto arr = iota(3).map!(a => S(a)).array; assert(nAlive == 3); // No good way to ensure the GC frees this, just call the lifetime function // directly. __delete(arr); assert(nAlive == 0);} @safe pure nothrow @nogc unittest{ //Turn down infinity: static assert(!is(typeof( repeat(1).array() )));} // https://issues.dlang.org/show_bug.cgi?id=20937@safe pure nothrow unittest{ struct S {int* x;} struct R { immutable(S) front; bool empty; @safe pure nothrow void popFront(){empty = true;} } R().array;} // Test that `array(scope InputRange r)` returns a non-scope array// https://issues.dlang.org/show_bug.cgi?id=23300@safe pure nothrow unittest{ @safe int[] fun() { import std.algorithm.iteration : map; int[3] arr = [1, 2, 3]; scope r = arr[].map!(x => x + 3); return r.array; }} /**Convert a narrow autodecoding string to an array type that fully supportsrandom access. This is handled as a special case and always returns an arrayof `dchar` NOTE: This function is never used when autodecoding is turned off. Params: str = `isNarrowString` to be converted to an array of `dchar`Returns: a `dchar[]`, `const(dchar)[]`, or `immutable(dchar)[]` depending on the constness of the input.*/CopyTypeQualifiers!(ElementType!String,dchar)[] array(String)(scope String str)if (isAutodecodableString!String){ import std.utf : toUTF32; auto temp = str.toUTF32; /* Unsafe cast. Allowed because toUTF32 makes a new array and copies all the elements. */ return () @trusted { return cast(CopyTypeQualifiers!(ElementType!String, dchar)[]) temp; } ();} ///@safe pure nothrow unittest{ import std.range.primitives : isRandomAccessRange; import std.traits : isAutodecodableString; // note that if autodecoding is turned off, `array` will not transcode these. static if (isAutodecodableString!string) assert("Hello D".array == "Hello D"d); else assert("Hello D".array == "Hello D"); static if (isAutodecodableString!wstring) assert("Hello D"w.array == "Hello D"d); else assert("Hello D"w.array == "Hello D"w); static assert(isRandomAccessRange!dstring == true);} @safe unittest{ import std.conv : to; static struct TestArray { int x; string toString() @safe { return to!string(x); } } static struct OpAssign { uint num; this(uint num) { this.num = num; } // Templating opAssign to make sure the bugs with opAssign being // templated are fixed. void opAssign(T)(T rhs) { this.num = rhs.num; } } static struct OpApply { int opApply(scope int delegate(ref int) @safe dg) { int res; foreach (i; 0 .. 10) { res = dg(i); if (res) break; } return res; } } auto a = array([1, 2, 3, 4, 5][]); assert(a == [ 1, 2, 3, 4, 5 ]); auto b = array([TestArray(1), TestArray(2)][]); assert(b == [TestArray(1), TestArray(2)]); class C { int x; this(int y) { x = y; } override string toString() const @safe { return to!string(x); } } auto c = array([new C(1), new C(2)][]); assert(c[0].x == 1); assert(c[1].x == 2); auto d = array([1.0, 2.2, 3][]); assert(is(typeof(d) == double[])); assert(d == [1.0, 2.2, 3]); auto e = [OpAssign(1), OpAssign(2)]; auto f = array(e); assert(e == f); assert(array(OpApply.init) == [0,1,2,3,4,5,6,7,8,9]); static if (isAutodecodableString!string) { assert(array("ABC") == "ABC"d); assert(array("ABC".dup) == "ABC"d.dup); }} // https://issues.dlang.org/show_bug.cgi?id=8233@safe pure nothrow unittest{ assert(array("hello world"d) == "hello world"d); immutable a = [1, 2, 3, 4, 5]; assert(array(a) == a); const b = a; assert(array(b) == a); //To verify that the opAssign branch doesn't get screwed up by using Unqual. //EDIT: array no longer calls opAssign. struct S { ref S opAssign(S)(const ref S rhs) { assert(0); } int i; } static foreach (T; AliasSeq!(S, const S, immutable S)) {{ auto arr = [T(1), T(2), T(3), T(4)]; assert(array(arr) == arr); }}} // https://issues.dlang.org/show_bug.cgi?id=9824@safe pure nothrow unittest{ static struct S { @disable void opAssign(S); int i; } auto arr = [S(0), S(1), S(2)]; arr.array();} // https://issues.dlang.org/show_bug.cgi?id=10220@safe pure nothrow unittest{ import std.algorithm.comparison : equal; import std.exception; import std.range : repeat; static struct S { int val; @disable this(); this(int v) { val = v; } } assertCTFEable!( { auto r = S(1).repeat(2).array(); assert(equal(r, [S(1), S(1)])); });}//https://issues.dlang.org/show_bug.cgi?id=22673@system unittest{ struct LyingRange { enum size_t length = 100; enum theRealLength = 50; size_t idx = 0; bool empty() { return idx <= theRealLength; } void popFront() { ++idx; } size_t front() { return idx; } } static assert(hasLength!LyingRange); LyingRange rng;Lines 1–500 of 5152. Load more
// Written in the D programming language. /** Functions and types that manipulate built-in arrays and associative arrays. This module provides all kinds of functions to create, manipulate or convert arrays: $(SCRIPT inhibitQuickIndex = 1;) $(DIVC quickindex, $(BOOKTABLE , $(TR $(TH Function Name) $(TH Description) ) $(TR $(TD $(LREF array)) $(TD Returns a copy of the input in a newly allocated dynamic array. )) $(TR $(TD $(LREF appender)) $(TD Returns a new $(LREF Appender) or $(LREF RefAppender) initialized with a given array. )) $(TR $(TD $(LREF assocArray)) $(TD Returns a newly allocated associative array from a range/ranges of keys and values. )) $(TR $(TD $(LREF byPair)) $(TD Construct a range iterating over an associative array by key/value tuples. )) $(TR $(TD $(LREF insertInPlace)) $(TD Inserts into an existing array at a given position. )) $(TR $(TD $(LREF join)) $(TD Concatenates a range of ranges into one array. )) $(TR $(TD $(LREF minimallyInitializedArray)) $(TD Returns a new array of type `T`. )) $(TR $(TD $(LREF replace)) $(TD Returns a new array with all occurrences of a certain subrange replaced. )) $(TR $(TD $(LREF replaceFirst)) $(TD Returns a new array with the first occurrence of a certain subrange replaced. )) $(TR $(TD $(LREF replaceInPlace)) $(TD Replaces all occurrences of a certain subrange and puts the result into a given array. )) $(TR $(TD $(LREF replaceInto)) $(TD Replaces all occurrences of a certain subrange and puts the result into an output range. )) $(TR $(TD $(LREF replaceLast)) $(TD Returns a new array with the last occurrence of a certain subrange replaced. )) $(TR $(TD $(LREF replaceSlice)) $(TD Returns a new array with a given slice replaced. )) $(TR $(TD $(LREF replicate)) $(TD Creates a new array out of several copies of an input array or range. )) $(TR $(TD $(LREF sameHead)) $(TD Checks if the initial segments of two arrays refer to the same place in memory. )) $(TR $(TD $(LREF sameTail)) $(TD Checks if the final segments of two arrays refer to the same place in memory. )) $(TR $(TD $(LREF split)) $(TD Eagerly split a range or string into an array. )) $(TR $(TD $(LREF staticArray)) $(TD Creates a new static array from given data. )) $(TR $(TD $(LREF uninitializedArray)) $(TD Returns a new array of type `T` without initializing its elements. )) )) Copyright: Copyright Andrei Alexandrescu 2008- and Jonathan M Davis 2011-. License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0). Authors: $(HTTP erdani.org, Andrei Alexandrescu) and $(HTTP jmdavisprog.com, Jonathan M Davis) Source: $(PHOBOSSRC std/array.d) */ module std.array; import std.functional; import std.meta; import std.traits; import std.range.primitives; public import std.range.primitives : save, empty, popFront, popBack, front, back; /** * Allocates an array and initializes it with copies of the elements * of range `r`. * * Narrow strings are handled as follows: * - If autodecoding is turned on (default), then they are handled as a separate overload. * - If autodecoding is turned off, then this is equivalent to duplicating the array. * * Params: * r = range (or aggregate with `opApply` function) whose elements are copied into the allocated array * Returns: * allocated and initialized array */ ForeachType!Range[] array(Range)(Range r) if (isIterable!Range && !isAutodecodableString!Range && !isInfinite!Range) { if (__ctfe) { // Compile-time version to avoid memcpy calls. // Also used to infer attributes of array(). typeof(return) result; foreach (e; r) result ~= e; return result; } alias E = ForeachType!Range; static if (hasLength!Range) { const length = r.length; if (length == 0) return null; import core.internal.lifetime : emplaceRef; auto result = (() @trusted => uninitializedArray!(Unqual!E[])(length))(); // Every element of the uninitialized array must be initialized size_t cnt; //Number of elements that have been initialized try { foreach (e; r) { emplaceRef!E(result[cnt], e); ++cnt; } } catch (Exception e) { //https://issues.dlang.org/show_bug.cgi?id=22185 //Make any uninitialized elements safely destructible. foreach (ref elem; result[cnt..$]) { import core.internal.lifetime : emplaceInitializer; emplaceInitializer(elem); } throw e; } /* https://issues.dlang.org/show_bug.cgi?id=22673 We preallocated an array, we should ensure that enough range elements were gathered such that every slot in the array is filled. If not, the GC will collect the allocated array, leading to the `length - cnt` left over elements being collected too - despite their contents having no guarantee of destructibility. */ assert(length == cnt, "Range .length property was not equal to the length yielded by the range before becoming empty"); return (() @trusted => cast(E[]) result)(); } else { auto a = appender!(E[])(); foreach (e; r) { a.put(e); } return a.data; } } /// ditto ForeachType!(typeof((*Range).init))[] array(Range)(Range r) if (is(Range == U*, U) && isIterable!U && !isAutodecodableString!Range && !isInfinite!Range) { return array(*r); } /// @safe pure nothrow unittest { auto a = array([1, 2, 3, 4, 5][]); assert(a == [ 1, 2, 3, 4, 5 ]); } @safe pure nothrow unittest { import std.algorithm.comparison : equal; struct Foo { int a; } auto a = array([Foo(1), Foo(2), Foo(3), Foo(4), Foo(5)][]); assert(equal(a, [Foo(1), Foo(2), Foo(3), Foo(4), Foo(5)])); } @safe pure nothrow unittest { struct MyRange { enum front = 123; enum empty = true; void popFront() {} } auto arr = (new MyRange).array; assert(arr.empty); } @safe pure nothrow unittest { immutable int[] a = [1, 2, 3, 4]; auto b = (&a).array; assert(b == a); } @safe pure nothrow unittest { import std.algorithm.comparison : equal; struct Foo { int a; noreturn opAssign(Foo) { assert(0); } auto opEquals(Foo foo) { return a == foo.a; } } auto a = array([Foo(1), Foo(2), Foo(3), Foo(4), Foo(5)][]); assert(equal(a, [Foo(1), Foo(2), Foo(3), Foo(4), Foo(5)])); } // https://issues.dlang.org/show_bug.cgi?id=12315 @safe pure nothrow unittest { static struct Bug12315 { immutable int i; } enum bug12315 = [Bug12315(123456789)].array(); static assert(bug12315[0].i == 123456789); } @safe pure nothrow unittest { import std.range; static struct S{int* p;} auto a = array(immutable(S).init.repeat(5)); assert(a.length == 5); } // https://issues.dlang.org/show_bug.cgi?id=18995 @system unittest { import core.memory : __delete; int nAlive = 0; struct S { bool alive; this(int) { alive = true; ++nAlive; } this(this) { nAlive += alive; } ~this() { nAlive -= alive; alive = false; } } import std.algorithm.iteration : map; import std.range : iota; auto arr = iota(3).map!(a => S(a)).array; assert(nAlive == 3); // No good way to ensure the GC frees this, just call the lifetime function // directly. __delete(arr); assert(nAlive == 0); } @safe pure nothrow @nogc unittest { //Turn down infinity: static assert(!is(typeof( repeat(1).array() ))); } // https://issues.dlang.org/show_bug.cgi?id=20937 @safe pure nothrow unittest { struct S {int* x;} struct R { immutable(S) front; bool empty; @safe pure nothrow void popFront(){empty = true;} } R().array; } // Test that `array(scope InputRange r)` returns a non-scope array // https://issues.dlang.org/show_bug.cgi?id=23300 @safe pure nothrow unittest { @safe int[] fun() { import std.algorithm.iteration : map; int[3] arr = [1, 2, 3]; scope r = arr[].map!(x => x + 3); return r.array; } } /** Convert a narrow autodecoding string to an array type that fully supports random access. This is handled as a special case and always returns an array of `dchar` NOTE: This function is never used when autodecoding is turned off. Params: str = `isNarrowString` to be converted to an array of `dchar` Returns: a `dchar[]`, `const(dchar)[]`, or `immutable(dchar)[]` depending on the constness of the input. */ CopyTypeQualifiers!(ElementType!String,dchar)[] array(String)(scope String str) if (isAutodecodableString!String) { import std.utf : toUTF32; auto temp = str.toUTF32; /* Unsafe cast. Allowed because toUTF32 makes a new array and copies all the elements. */ return () @trusted { return cast(CopyTypeQualifiers!(ElementType!String, dchar)[]) temp; } (); } /// @safe pure nothrow unittest { import std.range.primitives : isRandomAccessRange; import std.traits : isAutodecodableString; // note that if autodecoding is turned off, `array` will not transcode these. static if (isAutodecodableString!string) assert("Hello D".array == "Hello D"d); else assert("Hello D".array == "Hello D"); static if (isAutodecodableString!wstring) assert("Hello D"w.array == "Hello D"d); else assert("Hello D"w.array == "Hello D"w); static assert(isRandomAccessRange!dstring == true); } @safe unittest { import std.conv : to; static struct TestArray { int x; string toString() @safe { return to!string(x); } } static struct OpAssign { uint num; this(uint num) { this.num = num; } // Templating opAssign to make sure the bugs with opAssign being // templated are fixed. void opAssign(T)(T rhs) { this.num = rhs.num; } } static struct OpApply { int opApply(scope int delegate(ref int) @safe dg) { int res; foreach (i; 0 .. 10) { res = dg(i); if (res) break; } return res; } } auto a = array([1, 2, 3, 4, 5][]); assert(a == [ 1, 2, 3, 4, 5 ]); auto b = array([TestArray(1), TestArray(2)][]); assert(b == [TestArray(1), TestArray(2)]); class C { int x; this(int y) { x = y; } override string toString() const @safe { return to!string(x); } } auto c = array([new C(1), new C(2)][]); assert(c[0].x == 1); assert(c[1].x == 2); auto d = array([1.0, 2.2, 3][]); assert(is(typeof(d) == double[])); assert(d == [1.0, 2.2, 3]); auto e = [OpAssign(1), OpAssign(2)]; auto f = array(e); assert(e == f); assert(array(OpApply.init) == [0,1,2,3,4,5,6,7,8,9]); static if (isAutodecodableString!string) { assert(array("ABC") == "ABC"d); assert(array("ABC".dup) == "ABC"d.dup); } } // https://issues.dlang.org/show_bug.cgi?id=8233 @safe pure nothrow unittest { assert(array("hello world"d) == "hello world"d); immutable a = [1, 2, 3, 4, 5]; assert(array(a) == a); const b = a; assert(array(b) == a); //To verify that the opAssign branch doesn't get screwed up by using Unqual. //EDIT: array no longer calls opAssign. struct S { ref S opAssign(S)(const ref S rhs) { assert(0); } int i; } static foreach (T; AliasSeq!(S, const S, immutable S)) {{ auto arr = [T(1), T(2), T(3), T(4)]; assert(array(arr) == arr); }} } // https://issues.dlang.org/show_bug.cgi?id=9824 @safe pure nothrow unittest { static struct S { @disable void opAssign(S); int i; } auto arr = [S(0), S(1), S(2)]; arr.array(); } // https://issues.dlang.org/show_bug.cgi?id=10220 @safe pure nothrow unittest { import std.algorithm.comparison : equal; import std.exception; import std.range : repeat; static struct S { int val; @disable this(); this(int v) { val = v; } } assertCTFEable!( { auto r = S(1).repeat(2).array(); assert(equal(r, [S(1), S(1)])); }); } //https://issues.dlang.org/show_bug.cgi?id=22673 @system unittest { struct LyingRange { enum size_t length = 100; enum theRealLength = 50; size_t idx = 0; bool empty() { return idx <= theRealLength; } void popFront() { ++idx; } size_t front() { return idx; } } static assert(hasLength!LyingRange); LyingRange rng;