From a48d9cb739cfd5ff723e7d8258e2bb56a154df4f Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Tue, 24 Jan 2017 08:20:07 +0100 Subject: [PATCH] Add range support for SList --- source/tanya/container/list.d | 117 ++++++++++++++++++++++++++------ source/tanya/container/vector.d | 44 +++++++++--- 2 files changed, 129 insertions(+), 32 deletions(-) diff --git a/source/tanya/container/list.d b/source/tanya/container/list.d index 9000e74..d482df8 100644 --- a/source/tanya/container/list.d +++ b/source/tanya/container/list.d @@ -10,9 +10,63 @@ */ module tanya.container.list; +import std.traits; import tanya.container.entry; import tanya.memory; +private struct Range(E) + if (__traits(isSame, TemplateOf!E, SEntry)) +{ + private alias T = typeof(E.content); + + private E* head; + + private this(E* head) + { + this.head = head; + } + + @property Range save() + { + return this; + } + + @property bool empty() const + { + return head is null; + } + + @property ref inout(T) front() inout + in + { + assert(!empty); + } + body + { + return head.content; + } + + void popFront() + in + { + assert(!empty); + } + body + { + head = head.next; + } + + Range opIndex() + { + return typeof(return)(head); + } + + Range!(const E) opIndex() const + { + return typeof(return)(head); + } +} + /** * Singly-linked list. * @@ -21,6 +75,11 @@ import tanya.memory; */ struct SList(T) { + private alias Entry = SEntry!T; + + // 0th element of the list. + private Entry* head; + /** * Removes all elements from the list. */ @@ -36,7 +95,7 @@ struct SList(T) { while (!empty) { - popFront(); + removeFront(); } } @@ -61,7 +120,7 @@ struct SList(T) } body { - return first.next.content; + return head.content; } /** @@ -72,11 +131,11 @@ struct SList(T) */ void insertFront(ref T x) { - auto temp = allocator.make!(SEntry!T); + auto temp = allocator.make!Entry; temp.content = x; - temp.next = first.next; - first.next = temp; + temp.next = head; + head = temp; } /// Ditto. @@ -104,25 +163,27 @@ struct SList(T) */ @property bool empty() const { - return first.next is null; + return head is null; } /** * Returns the first element and moves to the next one. * * Returns: The first element. + * + * Precondition: $(D_INLINECODE !empty) */ - void popFront() + void removeFront() in { assert(!empty); } body { - auto n = first.next.next; + auto n = head.next; - allocator.dispose(first.next); - first.next = n; + allocator.dispose(head); + head = n; } /// @@ -133,14 +194,16 @@ struct SList(T) l.insertFront(8); l.insertFront(9); assert(l.front == 9); - l.popFront(); + l.removeFront(); assert(l.front == 8); + l.removeFront(); + assert(l.empty); } /** * Removes $(D_PARAM howMany) elements from the list. * - * Unlike $(D_PSYMBOL popFront()), this method doesn't fail, if it could not + * Unlike $(D_PSYMBOL removeFront()), this method doesn't fail, if it could not * remove $(D_PARAM howMany) elements. Instead, if $(D_PARAM howMany) is * greater than the list length, all elements are removed. * @@ -149,12 +212,17 @@ struct SList(T) * * Returns: The number of elements removed. */ - size_t removeFront(in size_t howMany = 1) + size_t removeFront(in size_t howMany) + out (removed) + { + assert(removed <= howMany); + } + body { size_t i; for (; i < howMany && !empty; ++i) { - popFront(); + removeFront(); } return i; } @@ -182,12 +250,12 @@ struct SList(T) * Params: * dg = $(D_KEYWORD foreach) body. */ - int opApply(scope int delegate(ref size_t i, ref T) dg) + int opApply(scope int delegate(ref size_t i, ref T) @nogc dg) { int result; size_t i; - for (auto pos = first.next; pos; pos = pos.next, ++i) + for (auto pos = head; pos; pos = pos.next, ++i) { result = dg(i, pos.content); @@ -200,11 +268,11 @@ struct SList(T) } /// Ditto. - int opApply(scope int delegate(ref T) dg) + int opApply(scope int delegate(ref T) @nogc dg) { int result; - for (auto pos = first.next; pos; pos = pos.next) + for (auto pos = head; pos; pos = pos.next) { result = dg(pos.content); @@ -232,8 +300,15 @@ struct SList(T) } } - /// 0th element of the list. - private SEntry!T first; + Range!Entry opIndex() + { + return typeof(return)(head); + } + + Range!(const Entry) opIndex() const + { + return typeof(return)(head); + } mixin DefaultAllocator; } @@ -257,7 +332,7 @@ unittest assert(i == 3); } -private unittest +unittest { interface Stuff { diff --git a/source/tanya/container/vector.d b/source/tanya/container/vector.d index 077a92b..e6dc861 100644 --- a/source/tanya/container/vector.d +++ b/source/tanya/container/vector.d @@ -547,6 +547,23 @@ struct Vector(T) return length == 0; } + /** + * Removes the value at the back of the vector. + * + * Returns: The number of elements removed + * + * Precondition: $(D_INLINECODE !empty) + */ + void removeBack() + in + { + assert(!empty); + } + body + { + length = length - 1; + } + /** * Removes $(D_PARAM howMany) elements from the vector. * @@ -559,11 +576,16 @@ struct Vector(T) * * Returns: The number of elements removed */ - size_t removeBack(in size_t howMany = 1) + size_t removeBack(in size_t howMany) + out (removed) { - immutable toRemove = min(howMany, length_); + assert(removed <= howMany); + } + body + { + immutable toRemove = min(howMany, length); - length = length_ - toRemove; + length = length - toRemove; return toRemove; } @@ -1119,9 +1141,9 @@ struct Vector(T) /// Ditto. int opApply(scope int delegate(ref size_t i, ref T) @nogc dg) { - for (size_t i = 0; i < length_; ++i) + for (size_t i = 0; i < length; ++i) { - assert(i < length_); + assert(i < length); int result = dg(i, *(vector + i)); if (result != 0) @@ -1135,7 +1157,7 @@ struct Vector(T) /// Ditto. int opApplyReverse(scope int delegate(ref T) dg) { - for (T* end = vector + length_ - 1; vector != end; --end) + for (T* end = vector + length - 1; vector != end; --end) { int result = dg(*end); if (result != 0) @@ -1149,13 +1171,13 @@ struct Vector(T) /// Ditto. int opApplyReverse(scope int delegate(ref size_t i, ref T) dg) { - if (length_ > 0) + if (length > 0) { - size_t i = length_; + size_t i = length; do { --i; - assert(i < length_); + assert(i < length); int result = dg(i, *(vector + i)); if (result != 0) @@ -1211,7 +1233,7 @@ struct Vector(T) /** * Returns: The first element. * - * Precondition: $(D_INLINECODE length > 0) + * Precondition: $(D_INLINECODE !empty) */ @property ref inout(T) front() inout in @@ -1238,7 +1260,7 @@ struct Vector(T) /** * Returns: The last element. * - * Precondition: $(D_INLINECODE length > 0) + * Precondition: $(D_INLINECODE !empty) */ @property ref inout(T) back() inout @trusted in