summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2017-07-08 05:41:04 +0200
committerEugen Wissner <belka@caraus.de>2017-07-08 05:41:04 +0200
commit4ac890d7d3278bf76591b4e3f67c85c4d48d27f8 (patch)
treeebedd43b19cf6e2023989384ccc1d5b6b7848751
parentb79657f0d27a408f9c2463ded48d3707102997c5 (diff)
downloadtanya-4ac890d7d3278bf76591b4e3f67c85c4d48d27f8.tar.gz
Fix #260
DList invariant fails.
-rw-r--r--source/tanya/container/list.d60
1 files changed, 49 insertions, 11 deletions
diff --git a/source/tanya/container/list.d b/source/tanya/container/list.d
index 0fd9e0d..2bd033a 100644
--- a/source/tanya/container/list.d
+++ b/source/tanya/container/list.d
@@ -1361,6 +1361,7 @@ struct DList(T)
foreach (ref e; el)
{
next.next = allocator.make!Entry(e);
+ next.next.prev = next;
next = next.next;
++retLength;
}
@@ -1377,6 +1378,12 @@ struct DList(T)
return retLength;
}
+ private @safe @nogc unittest
+ {
+ auto l1 = DList!int([5, 234]);
+ assert(l1.head is l1.head.next.prev);
+ }
+
/// Ditto.
size_t insertFront(size_t R)(T[R] el)
{
@@ -1709,7 +1716,7 @@ struct DList(T)
{
auto n = this.head.next;
- this.allocator.dispose(this.head);
+ allocator.dispose(this.head);
this.head = n;
if (this.head is null)
{
@@ -1775,7 +1782,7 @@ struct DList(T)
* Params:
* r = The range to remove.
*
- * Returns: An empty range.
+ * Returns: Range spanning the elements just after $(D_PARAM r).
*
* Precondition: $(D_PARAM r) is extracted from this list.
*/
@@ -1786,19 +1793,34 @@ struct DList(T)
}
body
{
- auto outOfScopeList = typeof(this)(allocator);
- outOfScopeList.head = *r.head;
- outOfScopeList.tail = r.tail;
- if (r.tail is null)
+ // Save references to the elements before and after the range.
+ Entry* tailNext, headPrev;
+ if (r.tail !is null && r.tail.next !is null)
{
- *r.head = null;
+ tailNext = r.tail.next;
}
- else
+ if (*r.head !is null)
{
- outOfScopeList.tail.next = null;
- *r.head = r.tail.next;
+ headPrev = (*r.head).prev;
}
-
+
+ // Remove the elements.
+ Entry* e = *r.head;
+ while (e !is tailNext)
+ {
+ auto next = e.next;
+ allocator.dispose(e);
+ e = next;
+ }
+
+ // Connect the elements before and after the removed range.
+ if (tailNext !is null)
+ {
+ tailNext.prev = headPrev;
+ }
+ *r.head = tailNext;
+ r.tail = tail;
+
return r;
}
@@ -1815,6 +1837,22 @@ struct DList(T)
assert(l1 == l2);
}
+ // Issue 260: https://issues.caraus.io/issues/260.
+ private @safe @nogc unittest
+ {
+ auto l1 = DList!int([5, 234, 30, 1]);
+ auto l2 = DList!int([5, 1]);
+ auto r = l1[];
+
+ r.popFront();
+ r.popBack();
+ assert(r.front == 234);
+ assert(r.back == 30);
+
+ assert(!l1.remove(r).empty);
+ assert(l1 == l2);
+ }
+
/**
* Returns: Range that iterates over all elements of the container, in
* forward order.