From 093d499729c23ca64d0742092993a8849992cc4b Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Wed, 8 Mar 2017 07:12:23 +0100 Subject: [PATCH] Fix element order inserted from a range into list --- source/tanya/container/list.d | 149 ++++++++++++++++++++++++++++++-- source/tanya/container/vector.d | 37 ++++---- 2 files changed, 159 insertions(+), 27 deletions(-) diff --git a/source/tanya/container/list.d b/source/tanya/container/list.d index 34a20a1..e318a27 100644 --- a/source/tanya/container/list.d +++ b/source/tanya/container/list.d @@ -91,6 +91,105 @@ struct SList(T) // 0th element of the list. private Entry* head; + /** + * Creates a new $(D_PSYMBOL SList) with the elements from a static array. + * + * Params: + * R = Static array size. + * init = Values to initialize the list with. + * allocator = Allocator. + */ + this(size_t R)(T[R] init, shared Allocator allocator = defaultAllocator) + { + this(allocator); + insertFront(init[]); + } + + /// + @safe @nogc unittest + { + auto l = SList!int([5, 8, 15]); + assert(l.front == 5); + } + + /** + * Creates a new $(D_PSYMBOL SList) with the elements from an input range. + * + * Params: + * R = Type of the initial range. + * init = Values to initialize the list with. + * allocator = Allocator. + */ + this(R)(R init, shared Allocator allocator = defaultAllocator) + if (!isInfinite!R + && isInputRange!R + && isImplicitlyConvertible!(ElementType!R, T)) + { + this(allocator); + insertFront(init); + } + + /** + * Creates a new $(D_PSYMBOL SList). + * + * Params: + * len = Initial length of the list. + * init = Initial value to fill the list with. + * allocator = Allocator. + */ + this(in size_t len, T init, shared Allocator allocator = defaultAllocator) @trusted + { + this(allocator); + + Entry* next; + foreach (i; 0 .. len) + { + if (next is null) + { + next = allocator.make!Entry(init); + head = next; + } + else + { + next.next = allocator.make!Entry(init); + next = next.next; + } + } + } + + /// + @safe @nogc unittest + { + auto l = SList!int(2, 3); + assert(l.length == 2); + assert(l.front == 3); + } + + /// Ditto. + this(in size_t len, shared Allocator allocator = defaultAllocator) + { + this(len, T.init, allocator); + } + + /// + @safe @nogc unittest + { + auto l = SList!int(2); + assert(l.length == 2); + assert(l.front == 0); + } + + /// Ditto. + this(shared Allocator allocator) + in + { + assert(allocator !is null); + } + body + { + this.allocator_ = allocator; + } + /** * Removes all elements from the list. */ @@ -99,6 +198,24 @@ struct SList(T) clear(); } + /** + * Copies the list. + */ + this(this) + { + auto buf = opIndex(); + head = null; + insertFront(buf); + } + + /// + unittest + { + auto l1 = SList!int([5, 1, 234]); + auto l2 = l1; + assert(l1 == l2); + } + /** * Removes all contents from the list. */ @@ -113,10 +230,9 @@ struct SList(T) /// unittest { - SList!int l; + SList!int l = SList!int([8, 5]); - l.insertFront(8); - l.insertFront(5); + assert(!l.empty); l.clear(); assert(l.empty); } @@ -164,15 +280,32 @@ struct SList(T) } /// Ditto. - size_t insertFront(R)(R el) + size_t insertFront(R)(R el) @trusted if (!isInfinite!R && isInputRange!R && isImplicitlyConvertible!(ElementType!R, T)) { size_t retLength; - foreach (e; el) + Entry* next, newHead; + + foreach (ref e; el) { - retLength += insertFront(e); + if (next is null) + { + next = allocator.make!Entry(e); + newHead = next; + } + else + { + next.next = allocator.make!Entry(e); + next = next.next; + } + ++retLength; + } + if (newHead !is null) + { + next.next = head; + head = newHead; } return retLength; } @@ -198,11 +331,11 @@ struct SList(T) SList!int l2; assert(l2.insertFront([25, 30, 15]) == 3); - assert(l2.front == 15); + assert(l2.front == 25); l2.insertFront(l1[]); assert(l2.length == 5); - assert(l2.front == 8); + assert(l2.front == 9); } /** diff --git a/source/tanya/container/vector.d b/source/tanya/container/vector.d index 0f3dc00..3010955 100644 --- a/source/tanya/container/vector.d +++ b/source/tanya/container/vector.d @@ -162,13 +162,11 @@ struct Vector(T) } /** - * Creates a new $(D_PSYMBOL Vector) with the elements from another input - * range or a static array $(D_PARAM init). + * Creates a new $(D_PSYMBOL Vector) with the elements from a static array. * * Params: - * R = Type of the initial range or size of the static array. - * init = Values to initialize the array with. - * to generate a list. + * R = Static array size. + * init = Values to initialize the vector with. * allocator = Allocator. */ this(size_t R)(T[R] init, shared Allocator allocator = defaultAllocator) @@ -177,7 +175,14 @@ struct Vector(T) insertBack!(T[])(init[]); } - /// Ditto. + /** + * Creates a new $(D_PSYMBOL Vector) with the elements from an input range. + * + * Params: + * R = Type of the initial range. + * init = Values to initialize the vector with. + * allocator = Allocator. + */ this(R)(R init, shared Allocator allocator = defaultAllocator) if (!isInfinite!R && isInputRange!R @@ -264,19 +269,6 @@ struct Vector(T) assert(v3.capacity == 3); } - /** - * Creates a new $(D_PSYMBOL Vector). - * - * Params: - * len = Initial length of the vector. - * allocator = Allocator. - */ - this(in size_t len, shared Allocator allocator = defaultAllocator) - { - this(allocator); - length = len; - } - /** * Creates a new $(D_PSYMBOL Vector). * @@ -293,6 +285,13 @@ struct Vector(T) length_ = len; } + /// Ditto. + this(in size_t len, shared Allocator allocator = defaultAllocator) + { + this(allocator); + length = len; + } + /// Ditto. this(shared Allocator allocator) in