summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2017-01-22 10:48:34 +0100
committerEugen Wissner <belka@caraus.de>2017-01-22 10:48:34 +0100
commita7206cbd02e57fd74f43764826dbc303c6d84e73 (patch)
treeb715b54b21290a7b26c87eab6616876fbf31de75 /source
parent1450a6adfe83e62dc5ce9fce6045f196d455bf02 (diff)
downloadtanya-a7206cbd02e57fd74f43764826dbc303c6d84e73.tar.gz
Fix #4
Diffstat (limited to 'source')
-rw-r--r--source/tanya/container/entry.d4
-rw-r--r--source/tanya/container/list.d4
-rw-r--r--source/tanya/container/queue.d14
-rw-r--r--source/tanya/container/vector.d315
4 files changed, 258 insertions, 79 deletions
diff --git a/source/tanya/container/entry.d b/source/tanya/container/entry.d
index 6fec435..1194f6b 100644
--- a/source/tanya/container/entry.d
+++ b/source/tanya/container/entry.d
@@ -12,11 +12,11 @@
*/
module tanya.container.entry;
-package struct Entry(T)
+package struct SEntry(T)
{
/// Item content.
T content;
/// Next item.
- Entry* next;
+ SEntry* next;
}
diff --git a/source/tanya/container/list.d b/source/tanya/container/list.d
index 0c916c1..9000e74 100644
--- a/source/tanya/container/list.d
+++ b/source/tanya/container/list.d
@@ -72,7 +72,7 @@ struct SList(T)
*/
void insertFront(ref T x)
{
- auto temp = allocator.make!(Entry!T);
+ auto temp = allocator.make!(SEntry!T);
temp.content = x;
temp.next = first.next;
@@ -233,7 +233,7 @@ struct SList(T)
}
/// 0th element of the list.
- private Entry!T first;
+ private SEntry!T first;
mixin DefaultAllocator;
}
diff --git a/source/tanya/container/queue.d b/source/tanya/container/queue.d
index cb285e1..d94486d 100644
--- a/source/tanya/container/queue.d
+++ b/source/tanya/container/queue.d
@@ -44,7 +44,7 @@ struct Queue(T)
size_t length() const
{
size_t len;
- for (const(Entry!T)* i = first; i !is null; i = i.next)
+ for (const(SEntry!T)* i = first; i !is null; i = i.next)
{
++len;
}
@@ -72,7 +72,7 @@ struct Queue(T)
assert(q.length == 0);
}
- private void enqueueEntry(ref Entry!T* entry)
+ private void enqueueEntry(ref SEntry!T* entry)
{
if (empty)
{
@@ -85,9 +85,9 @@ struct Queue(T)
}
}
- private Entry!T* allocateEntry()
+ private SEntry!T* allocateEntry()
{
- auto temp = cast(Entry!T*) allocator.allocate(Entry!T.sizeof);
+ auto temp = cast(SEntry!T*) allocator.allocate(SEntry!T.sizeof);
if (temp is null)
{
onOutOfMemoryError();
@@ -107,7 +107,7 @@ struct Queue(T)
{
auto temp = allocateEntry();
- *temp = Entry!T.init;
+ *temp = SEntry!T.init;
temp.content = x;
enqueueEntry(temp);
@@ -256,8 +256,8 @@ struct Queue(T)
assert(q.empty);
}
- private Entry!T* first;
- private Entry!T* rear;
+ private SEntry!T* first;
+ private SEntry!T* rear;
mixin DefaultAllocator;
}
diff --git a/source/tanya/container/vector.d b/source/tanya/container/vector.d
index 18fe6e0..077a92b 100644
--- a/source/tanya/container/vector.d
+++ b/source/tanya/container/vector.d
@@ -169,10 +169,10 @@ struct Vector(T)
* to generate a list.
* allocator = Allocator.
*/
- this(size_t R)(in T[R] init, shared Allocator allocator = defaultAllocator)
+ this(size_t R)(T[R] init, shared Allocator allocator = defaultAllocator)
{
this(allocator);
- insertBack(init);
+ insertBack!(T[])(init[]);
}
/// Ditto.
@@ -229,12 +229,7 @@ struct Vector(T)
{
// Move each element.
reserve(init.length);
-
- const T* end = vector + init.length;
- for (T* src = init.vector, dest = vector; dest != end; ++src, ++dest)
- {
- moveEmplace(*src, *dest);
- }
+ moveEmplaceAll(init.vector[0 .. init.length_], vector[0 .. init.length_]);
length_ = init.length;
// Destructor of init should destroy it here.
}
@@ -335,21 +330,21 @@ struct Vector(T)
/**
* Destroys this $(D_PSYMBOL Vector).
*/
- ~this()
+ ~this() @trusted
{
- length = 0;
- shrink(0);
+ clear();
+ allocator.deallocate(vector[0 .. capacity_]);
}
/**
* Copies the vector.
*/
- this(this) @trusted
+ this(this)
{
- auto buf = vector;
- immutable oldLen = length_;
+ auto buf = opIndex();
length_ = capacity_ = 0;
- insertBack(buf[0 .. oldLen]);
+ vector = null;
+ insertBack(buf);
}
/**
@@ -357,7 +352,7 @@ struct Vector(T)
*/
void clear()
{
- length_ = 0;
+ length = 0;
}
///
@@ -399,11 +394,11 @@ struct Vector(T)
*/
@property void length(in size_t len) @trusted
{
- if (len == length_)
+ if (len == length)
{
return;
}
- else if (len > length_)
+ else if (len > length)
{
reserve(len);
initializeAll(vector[length_ .. len]);
@@ -597,70 +592,71 @@ struct Vector(T)
Range!T remove(Range!T r) @trusted
in
{
- assert(r.begin >= vector && r.end <= vector + length_);
+ assert(r.begin >= vector);
+ assert(r.end <= vector + length_);
}
body
{
- const T* end = vector + length_;
- T* a = r.begin;
- for (T* b = r.end; b != end; ++a, ++b)
- {
- *a = *b;
- }
- for (; a != end; ++a)
- {
- static if (hasElaborateDestructor!T)
- {
- destroy(*a);
- }
- --length_;
- }
+ auto end = vector + length_;
+ moveAll(Range!T(r.end, end), Range!T(r.begin, end));
+ length = length - r.length;
return r;
}
///
- unittest
+ @safe @nogc unittest
{
auto v = Vector!int([5, 18, 17, 2, 4, 6, 1]);
- v.remove(v[1..3]);
- assert(v == Vector!int([5, 2, 4, 6, 1]));
+ assert(v.remove(v[1 .. 3]).length == 2);
+ assert(v[0] == 5 && v[1] == 2 && v[2] == 4 && v[3] == 6 && v[4] == 1);
+ assert(v.length == 5);
- v.remove(v[4..4]);
- assert(v == Vector!int([5, 2, 4, 6, 1]));
+ assert(v.remove(v[4 .. 4]).length == 0);
+ assert(v[0] == 5 && v[1] == 2 && v[2] == 4 && v[3] == 6 && v[4] == 1);
+ assert(v.length == 5);
- v.remove(v[4..5]);
- assert(v == Vector!int([5, 2, 4, 6]));
+ assert(v.remove(v[4 .. 5]).length == 1);
+ assert(v[0] == 5 && v[1] == 2 && v[2] == 4 && v[3] == 6);
+ assert(v.length == 4);
- v.remove(v[]);
+ assert(v.remove(v[]).length == 4);
assert(v.empty);
- v.remove(v[]);
+ assert(v.remove(v[]).length == 0);
assert(v.empty);
}
+ private void moveBack(R)(ref R el) @trusted
+ if (isImplicitlyConvertible!(R, T))
+ {
+ reserve(length + 1);
+ moveEmplace(el, *(vector + length_));
+ ++length_;
+ }
+
/**
* Inserts the $(D_PARAM el) into the vector.
*
* Params:
- * R = Parameter type (single value, range or static array).
- * el = Values should be inserted.
+ * R = Type of the inserted value(s) (single value, range or static array).
+ * el = Value(s) should be inserted.
*
* Returns: The number of elements inserted.
*/
size_t insertBack(R)(auto ref R el) @trusted
if (isImplicitlyConvertible!(R, T))
{
- reserve(length_ + 1);
static if (__traits(isRef, el))
{
+ reserve(length + 1);
emplace(vector + length_, el);
+ ++length_;
}
else
{
- moveEmplace(el, *(vector + length_));
+ moveBack(el);
}
- ++length_;
return 1;
}
@@ -672,7 +668,7 @@ struct Vector(T)
{
static if (hasLength!R)
{
- reserve(length_ + el.length);
+ reserve(length + el.length);
}
size_t retLength;
foreach (e; el)
@@ -683,14 +679,9 @@ struct Vector(T)
}
/// Ditto.
- size_t insertBack(size_t R)(in T[R] el)
+ size_t insertBack(size_t R)(T[R] el)
{
- reserve(length_ + el.length);
- foreach (e; el)
- {
- insertBack(e);
- }
- return el.length;
+ return insertBack!(T[])(el[]);
}
/// Ditto.
@@ -731,14 +722,192 @@ struct Vector(T)
assert(v1.capacity == 4);
assert(v1[0] == 5 && v1[1] == 6 && v1[2] == 4 && v1[3] == 2);
- auto v2 = Vector!int([34, 234]);
- assert(v1.insertBack(v2[]) == 2);
+ assert(v1.insertBack([34, 234]) == 2);
assert(v1.length == 6);
assert(v1.capacity == 6);
assert(v1[4] == 34 && v1[5] == 234);
}
/**
+ * Inserts $(D_PARAM el) before or after $(D_PARAM r).
+ *
+ * Params:
+ * R = Type of the inserted value(s) (single value, range or static array).
+ * r = Range originally obtained from this vector.
+ * el = Value(s) should be inserted.
+ *
+ * Returns: The number of elements inserted.
+ */
+ size_t insertAfter(R)(Range!T r, R el)
+ if (!isInfinite!R
+ && isInputRange!R
+ && isImplicitlyConvertible!(ElementType!R, T))
+ in
+ {
+ assert(r.begin >= vector);
+ assert(r.end <= vector + length_);
+ }
+ body
+ {
+ immutable oldLen = length;
+ immutable offset = r.end - vector;
+ immutable inserted = insertBack(el);
+ bringToFront(vector[offset .. oldLen], vector[oldLen .. length]);
+ return inserted;
+ }
+
+ /// Ditto.
+ size_t insertAfter(size_t R)(Range!T r, T[R] el)
+ {
+ return insertAfter!(T[])(r, el[]);
+ }
+
+ /// Ditto.
+ size_t insertAfter(R)(Range!T r, auto ref R el)
+ if (isImplicitlyConvertible!(R, T))
+ in
+ {
+ assert(r.begin >= vector);
+ assert(r.end <= vector + length_);
+ }
+ body
+ {
+ immutable oldLen = length;
+ immutable offset = r.end - vector;
+
+ static if (__traits(isRef, el))
+ {
+ insertBack(el);
+ }
+ else
+ {
+ moveBack(el);
+ }
+ bringToFront(vector[offset .. oldLen], vector[oldLen .. length_]);
+
+ return 1;
+ }
+
+ /// Ditto.
+ size_t insertBefore(R)(Range!T r, R el)
+ if (!isInfinite!R
+ && isInputRange!R
+ && isImplicitlyConvertible!(ElementType!R, T))
+ in
+ {
+ assert(r.begin >= vector);
+ assert(r.end <= vector + length_);
+ }
+ body
+ {
+ return insertAfter(Range!T(vector, r.begin), el);
+ }
+
+ /// Ditto.
+ size_t insertBefore(size_t R)(Range!T r, T[R] el)
+ {
+ return insertBefore!(T[])(r, el[]);
+ }
+
+ /// Ditto.
+ size_t insertBefore(R)(Range!T r, auto ref R el)
+ if (isImplicitlyConvertible!(R, T))
+ in
+ {
+ assert(r.begin >= vector);
+ assert(r.end <= vector + length_);
+ }
+ body
+ {
+ immutable oldLen = length;
+ immutable offset = r.begin - vector;
+
+ static if (__traits(isRef, el))
+ {
+ insertBack(el);
+ }
+ else
+ {
+ moveBack(el);
+ }
+ bringToFront(vector[offset .. oldLen], vector[oldLen .. length_]);
+
+ return 1;
+ }
+
+ ///
+ unittest
+ {
+ Vector!int v1;
+ v1.insertAfter(v1[], [2, 8]);
+ assert(v1[0] == 2);
+ assert(v1[1] == 8);
+ assert(v1.length == 2);
+
+ v1.insertAfter(v1[], [1, 2]);
+ assert(v1[0] == 2);
+ assert(v1[1] == 8);
+ assert(v1[2] == 1);
+ assert(v1[3] == 2);
+ assert(v1.length == 4);
+
+ v1.insertAfter(v1[0 .. 0], [1, 2]);
+ assert(v1[0] == 1);
+ assert(v1[1] == 2);
+ assert(v1[2] == 2);
+ assert(v1[3] == 8);
+ assert(v1[4] == 1);
+ assert(v1[5] == 2);
+ assert(v1.length == 6);
+
+ v1.insertAfter(v1[0 .. 4], 9);
+ assert(v1[0] == 1);
+ assert(v1[1] == 2);
+ assert(v1[2] == 2);
+ assert(v1[3] == 8);
+ assert(v1[4] == 9);
+ assert(v1[5] == 1);
+ assert(v1[6] == 2);
+ assert(v1.length == 7);
+ }
+
+ ///
+ unittest
+ {
+ Vector!int v1;
+ v1.insertBefore(v1[], [2, 8]);
+ assert(v1[0] == 2);
+ assert(v1[1] == 8);
+ assert(v1.length == 2);
+
+ v1.insertBefore(v1[], [1, 2]);
+ assert(v1[0] == 1);
+ assert(v1[1] == 2);
+ assert(v1[2] == 2);
+ assert(v1[3] == 8);
+ assert(v1.length == 4);
+
+ v1.insertBefore(v1[0 .. 1], [1, 2]);
+ assert(v1[0] == 1);
+ assert(v1[1] == 2);
+ assert(v1[2] == 1);
+ assert(v1[3] == 2);
+ assert(v1[4] == 2);
+ assert(v1[5] == 8);
+ assert(v1.length == 6);
+
+ v1.insertBefore(v1[2 .. $], 9);
+ assert(v1[0] == 1);
+ assert(v1[1] == 2);
+ assert(v1[2] == 9);
+ assert(v1[3] == 1);
+ assert(v1[4] == 2);
+ assert(v1[5] == 2);
+ assert(v1[6] == 8);
+ assert(v1.length == 7);
+ }
+
+ /**
* Assigns a value to the element with the index $(D_PARAM pos).
*
* Params:
@@ -841,13 +1010,13 @@ struct Vector(T)
* Returns: Random access range that iterates over elements of the vector, in
* forward order.
*/
- Range!T opIndex()
+ Range!T opIndex() @trusted
{
return typeof(return)(vector, vector + length_);
}
/// Ditto.
- Range!(const T) opIndex() const
+ Range!(const T) opIndex() const @trusted
{
return typeof(return)(vector, vector + length_);
}
@@ -874,15 +1043,15 @@ struct Vector(T)
* Returns: $(D_KEYWORD true) if the vectors are equal, $(D_KEYWORD false)
* otherwise.
*/
- bool opEquals()(auto ref typeof(this) v)
+ bool opEquals()(auto ref typeof(this) v) @trusted
{
- return equal(opIndex(), v[]);
+ return equal(vector[0 .. length_], v.vector[0 .. v.length_]);
}
/// Ditto.
- bool opEquals()(in auto ref typeof(this) v) const
+ bool opEquals()(in auto ref typeof(this) v) const @trusted
{
- return equal(opIndex(), v[]);
+ return equal(vector[0 .. length_], v.vector[0 .. length_]);
}
/// Ditto.
@@ -1185,8 +1354,9 @@ struct Vector(T)
* Precondition: $(D_INLINECODE i <= j && j <= length
* && value.length == j - i)
*/
- Range!T opSliceAssign(R)(R value, in size_t i, in size_t j)
- if (!isInfinite!R && isInputRange!R
+ Range!T opSliceAssign(R)(R value, in size_t i, in size_t j) @trusted
+ if (!isInfinite!R
+ && isInputRange!R
&& isImplicitlyConvertible!(ElementType!R, T))
in
{
@@ -1196,7 +1366,7 @@ struct Vector(T)
}
body
{
- copy(value, opSlice(i, j));
+ copy(value, vector[i .. j]);
return opSlice(i, j);
}
@@ -1207,7 +1377,7 @@ struct Vector(T)
}
/// Ditto.
- Range!T opSliceAssign(ref T value, in size_t i, in size_t j)
+ Range!T opSliceAssign(ref T value, in size_t i, in size_t j) @trusted
in
{
assert(i <= j);
@@ -1215,7 +1385,7 @@ struct Vector(T)
}
body
{
- fill(opSlice(i, j), value);
+ fill(vector[i .. j], value);
return opSlice(i, j);
}
@@ -1392,3 +1562,12 @@ unittest
}
auto v = Vector!SWithDtor(); // Destructor can destroy empty vectors.
}
+
+unittest
+{
+ class A
+ {
+ }
+ A a1, a2;
+ auto v1 = Vector!A([a1, a2]);
+}