summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2017-01-24 08:20:07 +0100
committerEugen Wissner <belka@caraus.de>2017-01-24 08:20:07 +0100
commita48d9cb739cfd5ff723e7d8258e2bb56a154df4f (patch)
treef349923e8fea25355964bd153275fcc34c322c55
parenta7206cbd02e57fd74f43764826dbc303c6d84e73 (diff)
downloadtanya-a48d9cb739cfd5ff723e7d8258e2bb56a154df4f.tar.gz
Add range support for SList
-rw-r--r--source/tanya/container/list.d117
-rw-r--r--source/tanya/container/vector.d44
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
@@ -548,6 +548,23 @@ struct Vector(T)
}
/**
+ * 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.
*
* This method doesn't fail if it could not remove $(D_PARAM howMany)
@@ -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)
+ {
+ assert(removed <= howMany);
+ }
+ body
{
- immutable toRemove = min(howMany, length_);
+ 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