summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2017-03-29 10:35:45 +0200
committerEugen Wissner <belka@caraus.de>2017-03-29 10:35:45 +0200
commitaabb4fb534184497e48c2d7e050753d555615f47 (patch)
tree0a563ab04b52f667a17bd870de4aeb37fcacc465
parent4d8b95812ebb3415bf77f4f2e32e7e58f77d6ab8 (diff)
downloadtanya-aabb4fb534184497e48c2d7e050753d555615f47.tar.gz
Add SList.opAssign
-rw-r--r--source/tanya/container/list.d130
-rw-r--r--source/tanya/container/vector.d95
2 files changed, 171 insertions, 54 deletions
diff --git a/source/tanya/container/list.d b/source/tanya/container/list.d
index 491b31b..47453ed 100644
--- a/source/tanya/container/list.d
+++ b/source/tanya/container/list.d
@@ -356,18 +356,17 @@ struct SList(T)
size_t retLength;
Entry* next, newHead;
+ if (!el.empty)
+ {
+ next = allocator.make!Entry(el.front);
+ newHead = next;
+ el.popFront();
+ retLength = 1;
+ }
foreach (ref e; el)
{
- if (next is null)
- {
- next = allocator.make!Entry(e);
- newHead = next;
- }
- else
- {
- next.next = allocator.make!Entry(e);
- next = next.next;
- }
+ next.next = allocator.make!Entry(e);
+ next = next.next;
++retLength;
}
if (newHead !is null)
@@ -406,13 +405,16 @@ struct SList(T)
assert(l2.front == 9);
}
- private bool checkRangeBelonging(ref Range!Entry r) const
+ version (assert)
{
- const(Entry*)* pos;
- for (pos = &head; pos != r.head && *pos !is null; pos = &(*pos).next)
+ private bool checkRangeBelonging(ref Range!Entry r) const
{
+ const(Entry*)* pos;
+ for (pos = &head; pos != r.head && *pos !is null; pos = &(*pos).next)
+ {
+ }
+ return pos == r.head;
}
- return pos == r.head;
}
/**
@@ -741,16 +743,116 @@ struct SList(T)
}
}
+ /**
+ * Returns: Range that iterates over all elements of the container, in
+ * forward order.
+ */
Range!Entry opIndex()
{
return typeof(return)(head);
}
+ /// Ditto.
Range!(const Entry) opIndex() const
{
return typeof(return)(head);
}
+ /**
+ * Assigns another list.
+ *
+ * If $(D_PARAM that) is passed by value, it won't be copied, but moved.
+ * This list will take the ownership over $(D_PARAM that)'s storage and
+ * the allocator.
+ *
+ * If $(D_PARAM that) is passed by reference, it will be copied.
+ *
+ * Params:
+ * R = Content type.
+ * that = The value should be assigned.
+ *
+ * Returns: $(D_KEYWORD this).
+ */
+ ref typeof(this) opAssign(R)(const ref R that)
+ if (is(Unqual!R == SList))
+ {
+ return this = that[];
+ }
+
+ /// Ditto.
+ ref typeof(this) opAssign(R)(const ref R that)
+ if (is(Unqual!R == SList))
+ {
+ swap(this.head, that.head);
+ swap(this.allocator_, that.allocator_);
+ }
+
+ /**
+ * Assigns an input range.
+ *
+ * Params:
+ * R = Type of the initial range.
+ * that = Values to initialize the list with.
+ *
+ * Returns: $(D_KEYWORD this).
+ */
+ ref typeof(this) opAssign(R)(R that) @trusted
+ if (!isInfinite!R
+ && isInputRange!R
+ && isImplicitlyConvertible!(ElementType!R, T))
+ {
+ Entry** next = &head;
+
+ foreach (ref e; that)
+ {
+ if (*next is null)
+ {
+ *next = allocator.make!Entry(e);
+ }
+ else
+ {
+ (*next).content = e;
+ }
+ next = &(*next).next;
+ }
+ remove(Range!Entry(*next));
+
+ return this;
+ }
+
+ ///
+ @safe @nogc unittest
+ {
+ auto l1 = SList!int([5, 4, 9]);
+ auto l2 = SList!int([9, 4]);
+ l1 = l2[];
+ assert(l1 == l2);
+ }
+
+ /**
+ * Assigns a static array.
+ *
+ * Params:
+ * R = Static array size.
+ * that = Values to initialize the vector with.
+ *
+ * Returns: $(D_KEYWORD this).
+ */
+ ref typeof(this) opAssign(size_t R)(T[R] that)
+ {
+ return opAssign!(T[])(that[]);
+ }
+
+ ///
+ @safe @nogc unittest
+ {
+ auto l1 = SList!int([5, 4, 9]);
+ auto l2 = SList!int([9, 4]);
+ l1 = [9, 4];
+ assert(l1 == l2);
+ }
+
+
mixin DefaultAllocator;
}
diff --git a/source/tanya/container/vector.d b/source/tanya/container/vector.d
index b8b2bba..4a7b5c3 100644
--- a/source/tanya/container/vector.d
+++ b/source/tanya/container/vector.d
@@ -221,11 +221,29 @@ struct Vector(T)
if (is(R == Vector))
{
this(allocator);
- moveAssign(init);
+ if (allocator is init.allocator)
+ {
+ // Just steal all references and the allocator.
+ vector = init.vector;
+ length_ = init.length_;
+ capacity_ = init.capacity_;
+
+ // Reset the source vector, so it can't destroy the moved storage.
+ init.length_ = init.capacity_ = 0;
+ init.vector = null;
+ }
+ else
+ {
+ // Move each element.
+ reserve(init.length);
+ moveEmplaceAll(init.vector[0 .. init.length_], vector[0 .. init.length_]);
+ length_ = init.length;
+ // Destructor of init should destroy it here.
+ }
}
///
- unittest
+ @trusted @nogc unittest
{
auto v1 = Vector!int([1, 2, 3]);
auto v2 = Vector!int(v1);
@@ -238,7 +256,7 @@ struct Vector(T)
assert(v3.capacity == 3);
}
- unittest // const constructor tests
+ private @trusted @nogc unittest // const constructor tests
{
auto v1 = const Vector!int([1, 2, 3]);
auto v2 = Vector!int(v1);
@@ -1455,58 +1473,54 @@ struct Vector(T)
assert(data.length == 1);
}
- private void moveAssign(ref Vector v) @trusted
- {
- if (allocator is v.allocator)
- {
- // Just steal all references and the allocator.
- vector = v.vector;
- length_ = v.length_;
- capacity_ = v.capacity_;
-
- // Reset the source vector, so it can't destroy the moved storage.
- v.length_ = v.capacity_ = 0;
- v.vector = null;
- }
- else
- {
- // Move each element.
- reserve(v.length);
- moveEmplaceAll(v.vector[0 .. v.length_], vector[0 .. v.length_]);
- length_ = v.length;
- // Destructor of v should destroy it here.
- }
- }
-
/**
- * Assigns content to the vector.
+ * Assigns another vector.
+ *
+ * If $(D_PARAM that) is passed by value, it won't be copied, but moved.
+ * This vector will take the ownership over $(D_PARAM that)'s storage and
+ * the allocator.
+ *
+ * If $(D_PARAM that) is passed by reference, it will be copied.
*
* Params:
* R = Content type.
- * init = The value should be assigned.
+ * that = The value should be assigned.
+ *
+ * Returns: $(D_KEYWORD this).
*/
- ref typeof(this) opAssign(R)(const ref R init)
+ ref typeof(this) opAssign(R)(const ref R that)
if (is(Unqual!R == Vector))
{
- insertBack(init[]);
- return this;
+ return this = that[];
}
/// Ditto.
- ref typeof(this) opAssign(R)(R init)
+ ref typeof(this) opAssign(R)(R that) @trusted
if (is(R == Vector))
{
- moveAssign(init);
+ swap(this.vector, that.vector);
+ swap(this.length_, that.length_);
+ swap(this.capacity_, that.capacity_);
+ swap(this.allocator_, that.allocator_);
return this;
}
- /// Ditto.
- ref typeof(this) opAssign(R)(R init)
+ /**
+ * Assigns a range to the vector.
+ *
+ * Params:
+ * R = Content type.
+ * that = The value should be assigned.
+ *
+ * Returns: $(D_KEYWORD this).
+ */
+ ref typeof(this) opAssign(R)(R that)
if (!isInfinite!R
&& isInputRange!R
&& isImplicitlyConvertible!(ElementType!R, T))
{
- insertBack(init);
+ this.length = 0;
+ insertBack(that);
return this;
}
@@ -1540,12 +1554,13 @@ struct Vector(T)
*
* Params:
* R = Static array size.
- * init = Values to initialize the vector with.
+ * that = Values to initialize the vector with.
+ *
+ * Returns: $(D_KEYWORD this).
*/
- ref typeof(this) opAssign(size_t R)(T[R] init)
+ ref typeof(this) opAssign(size_t R)(T[R] that)
{
- insertBack!(T[])(init[]);
- return this;
+ return opAssign!(T[])(that[]);
}
///