From bc618090502e9c6a632cdeea4491ef33812f6214 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Tue, 16 May 2017 13:16:18 +0200 Subject: [PATCH] Implement DList.insertBack --- source/tanya/container/list.d | 163 +++++++++++++++++++++++++++++++--- 1 file changed, 151 insertions(+), 12 deletions(-) diff --git a/source/tanya/container/list.d b/source/tanya/container/list.d index 942fc3e..1e6cd7a 100644 --- a/source/tanya/container/list.d +++ b/source/tanya/container/list.d @@ -348,6 +348,20 @@ struct SList(T) return 1; } + /// + unittest + { + SList!int l; + int value = 5; + + l.insertFront(value); + assert(l.front == value); + + value = 8; + l.insertFront(value); + assert(l.front == 8); + } + /// Ditto. size_t insertFront(R)(R el) @trusted if (!isInfinite!R @@ -1219,20 +1233,19 @@ struct DList(T) el.moveEmplace(temp.content); temp.next = head; temp.prev = null; - setTailIfNull(temp); + if (this.tail is null) + { + this.tail = temp; + } + else + { + head.prev = temp; + } head = temp; return 1; } - private void setTailIfNull(ref Entry* tail = this.tail) - { - if (this.tail is null) - { - this.tail = tail; - } - } - /** * Inserts a new element at the beginning. * @@ -1252,11 +1265,34 @@ struct DList(T) size_t insertFront(R)(ref R el) @trusted if (isImplicitlyConvertible!(R, T)) { - this.head = allocator.make!Entry(el, this.head); - setTailIfNull(); + if (this.tail is null) + { + this.head = this.tail = allocator.make!Entry(el); + } + else + { + this.head.prev = allocator.make!Entry(el, this.head); + this.head = this.head.prev; + } return 1; } + /// + unittest + { + DList!int l; + int value = 5; + + l.insertFront(value); + assert(l.front == value); + assert(l.back == value); + + value = 8; + l.insertFront(value); + assert(l.front == 8); + assert(l.back == 5); + } + /// Ditto. size_t insertFront(R)(R el) @trusted if (!isInfinite!R @@ -1299,7 +1335,7 @@ struct DList(T) } /// Ditto. - alias insert = insertFront; + alias insert = insertBack; /// @safe @nogc unittest @@ -1320,6 +1356,109 @@ struct DList(T) assert(l2.front == 9); } + /** + * Inserts a new element at the end. + * + * Params: + * R = Type of the inserted value(s). + * el = New element(s). + * + * Returns: The number of elements inserted. + */ + size_t insertBack(R)(R el) @trusted + if (isImplicitlyConvertible!(R, T)) + { + auto temp = cast(Entry*) allocator.allocate(Entry.sizeof); + + el.moveEmplace(temp.content); + temp.next = null; + temp.prev = tail; + if (this.head is null) + { + this.head = temp; + } + else + { + this.tail.next = temp; + } + + this.tail = temp; + return 1; + } + + /// Ditto. + size_t insertBack(R)(ref R el) @trusted + if (isImplicitlyConvertible!(R, T)) + { + if (this.tail is null) + { + this.head = this.tail = allocator.make!Entry(el); + } + else + { + this.tail.next = allocator.make!Entry(el, null, this.tail); + this.tail = this.tail.next; + } + return 1; + } + + /// + unittest + { + DList!int l; + int value = 5; + + l.insertBack(value); + assert(l.front == value); + assert(l.back == value); + + value = 8; + l.insertBack(value); + assert(l.front == 5); + assert(l.back == value); + } + + /// Ditto. + size_t insertBack(R)(R el) @trusted + if (!isInfinite!R + && isInputRange!R + && isImplicitlyConvertible!(ElementType!R, T)) + { + size_t inserted; + + foreach (ref e; el) + { + inserted += insertBack(e); + } + + return inserted; + } + + /// Ditto. + size_t insertBack(size_t R)(T[R] el) + { + return insertBack!(T[])(el[]); + } + + /// + @safe @nogc unittest + { + DList!int l1; + + assert(l1.insertBack(8) == 1); + assert(l1.back == 8); + assert(l1.insertBack(9) == 1); + assert(l1.back == 9); + + DList!int l2; + assert(l2.insertBack([25, 30, 15]) == 3); + assert(l2.back == 15); + + l2.insertBack(l1[]); + assert(l2.length == 5); + assert(l2.back == 9); + } + version (assert) { private bool checkRangeBelonging(ref DRange!T r) const