From aabb4fb534184497e48c2d7e050753d555615f47 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Wed, 29 Mar 2017 10:35:45 +0200 Subject: [PATCH] Add SList.opAssign --- source/tanya/container/list.d | 130 ++++++++++++++++++++++++++++---- source/tanya/container/vector.d | 95 +++++++++++++---------- 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[]); } ///