summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--source/tanya/algorithm/mutation.d164
-rw-r--r--source/tanya/algorithm/package.d17
-rw-r--r--source/tanya/container/array.d10
-rw-r--r--source/tanya/container/list.d4
-rw-r--r--source/tanya/container/queue.d2
-rw-r--r--source/tanya/container/set.d3
-rw-r--r--source/tanya/container/string.d3
-rw-r--r--source/tanya/math/mp.d14
9 files changed, 209 insertions, 10 deletions
diff --git a/README.md b/README.md
index fc8c053..df6181b 100644
--- a/README.md
+++ b/README.md
@@ -15,7 +15,6 @@ Garbage Collector heap. Everything in the library is usable in @nogc code.
Tanya extends Phobos functionality and provides alternative implementations for
data structures and utilities that depend on the Garbage Collector in Phobos.
-* [Bug tracker](https://issues.caraus.io/projects/tanya/issues)
* [API Documentation](https://docs.caraus.io/tanya)
* [Contribution guidelines](CONTRIBUTING.md)
@@ -24,6 +23,7 @@ data structures and utilities that depend on the Garbage Collector in Phobos.
Tanya consists of the following packages and (top-level) modules:
+* `algorithm`: Collection of generic algorithms.
* `async`: Event loop (epoll, kqueue and IOCP).
* `container`: Queue, Array, Singly and doubly linked lists, Buffers, UTF-8
string, Hash set.
diff --git a/source/tanya/algorithm/mutation.d b/source/tanya/algorithm/mutation.d
new file mode 100644
index 0000000..698dfdf
--- /dev/null
+++ b/source/tanya/algorithm/mutation.d
@@ -0,0 +1,164 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * Algorithms that modify its arguments.
+ *
+ * Copyright: Eugene Wissner 2017.
+ * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
+ * Mozilla Public License, v. 2.0).
+ * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
+ * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/algorithm/mutation.d,
+ * tanya/algorithm/mutation.d)
+ */
+module tanya.algorithm.mutation;
+
+import tanya.memory.op;
+import tanya.meta.trait;
+
+/**
+ * Moves $(D_PARAM source) into $(D_PARAM target) assuming that
+ * $(D_PARAM target) isn't initialized.
+ *
+ * Moving the $(D_PARAM source) copies it into the $(D_PARAM target) and places
+ * the $(D_PARAM source) into a valid but unspecified state, which means that
+ * after moving $(D_PARAM source) can be destroyed or assigned a new value, but
+ * accessing it yields an unspecified value. No postblits or destructors are
+ * called. If the $(D_PARAM target) should be destroyed before, use
+ * $(D_PSYMBOL move).
+ *
+ * $(D_PARAM source) and $(D_PARAM target) must be different objects.
+ *
+ * Params:
+ * T = Object type.
+ * source = Source object.
+ * target = Target object.
+ *
+ * See_Also: $(D_PSYMBOL move),
+ * $(D_PSYMBOL hasElaborateCopyConstructor),
+ * $(D_PSYMBOL hasElaborateDestructor).
+ *
+ * Precondition: `&source !is &target`.
+ */
+void moveEmplace(T)(ref T source, ref T target) @system
+in
+{
+ assert(&source !is &target, "Source and target must be different");
+}
+body
+{
+ static if (is(T == struct))
+ {
+ copy((&source)[0 .. 1], (&target)[0 .. 1]);
+
+ static if (hasElaborateCopyConstructor!T || hasElaborateDestructor!T)
+ {
+ static const T init = T.init;
+
+ static if (isNested!T)
+ {
+ // Don't override the context pointer.
+ enum size_t size = T.sizeof - (void*).sizeof;
+ copy((cast(void*) &init)[0 .. size], (&source)[0 .. 1]);
+ }
+ else
+ {
+ copy((&init)[0 .. 1], (&source)[0 .. 1]);
+ }
+ }
+ }
+ else
+ {
+ target = source;
+ }
+}
+
+///
+@nogc nothrow pure @system unittest
+{
+ static struct S
+ {
+ int member = 5;
+
+ this(this) @nogc nothrow pure @safe
+ {
+ assert(false);
+ }
+ }
+ S source, target = void;
+ moveEmplace(source, target);
+ assert(target.member == 5);
+
+ int x1 = 5, x2;
+ moveEmplace(x1, x2);
+ assert(x2 == 5);
+}
+
+/**
+ * Moves $(D_PARAM source) into $(D_PARAM target) assuming that
+ * $(D_PARAM target) isn't initialized.
+ *
+ * Moving the $(D_PARAM source) copies it into the $(D_PARAM target) and places
+ * the $(D_PARAM source) into a valid but unspecified state, which means that
+ * after moving $(D_PARAM source) can be destroyed or assigned a new value, but
+ * accessing it yields an unspecified value. $(D_PARAM target) is destroyed before
+ * the new value is assigned. If $(D_PARAM target) isn't initialized and
+ * therefore shouldn't be destroyed, $(D_PSYMBOL moveEmplace) can be used.
+ *
+ * If $(D_PARAM target) isn't specified, $(D_PSYMBOL move) returns the source
+ * as rvalue without calling its copy constructor or destructor.
+ *
+ * $(D_PARAM source) and $(D_PARAM target) are the same object,
+ * $(D_PSYMBOL move) does nothing.
+ *
+ * Params:
+ * T = Object type.
+ * source = Source object.
+ * target = Target object.
+ *
+ * See_Also: $(D_PSYMBOL moveEmplace).
+ */
+void move(T)(ref T source, ref T target)
+{
+ if ((() @trusted => &source is &target)())
+ {
+ return;
+ }
+ static if (hasElaborateDestructor!T)
+ {
+ target.__xdtor();
+ }
+ (() @trusted => moveEmplace(source, target))();
+}
+
+/// ditto
+T move(T)(ref T source)
+{
+ T target = void;
+ (() @trusted => moveEmplace(source, target))();
+ return target;
+}
+
+///
+@nogc nothrow pure @safe unittest
+{
+ static struct S
+ {
+ int member = 5;
+
+ this(this) @nogc nothrow pure @safe
+ {
+ assert(false);
+ }
+ }
+ S source, target = void;
+ move(source, target);
+ assert(target.member == 5);
+ assert(move(target).member == 5);
+
+ int x1 = 5, x2;
+ move(x1, x2);
+ assert(x2 == 5);
+ assert(move(x2) == 5);
+}
diff --git a/source/tanya/algorithm/package.d b/source/tanya/algorithm/package.d
new file mode 100644
index 0000000..e147073
--- /dev/null
+++ b/source/tanya/algorithm/package.d
@@ -0,0 +1,17 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * Collection of generic algorithms.
+ *
+ * Copyright: Eugene Wissner 2017.
+ * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
+ * Mozilla Public License, v. 2.0).
+ * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
+ * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/algorithm/package.d,
+ * tanya/algorithm/package.d)
+ */
+module tanya.algorithm;
+
+public import tanya.algorithm.mutation;
diff --git a/source/tanya/container/array.d b/source/tanya/container/array.d
index 0af61c7..4891588 100644
--- a/source/tanya/container/array.d
+++ b/source/tanya/container/array.d
@@ -16,8 +16,16 @@ module tanya.container.array;
import core.checkedint;
import std.algorithm.comparison;
-import std.algorithm.mutation;
+import std.algorithm.mutation : bringToFront,
+ copy,
+ fill,
+ initializeAll,
+ moveEmplaceAll,
+ moveAll,
+ swap,
+ uninitializedFill;
import std.meta;
+import tanya.algorithm.mutation;
import tanya.exception;
import tanya.memory;
import tanya.meta.trait;
diff --git a/source/tanya/container/list.d b/source/tanya/container/list.d
index aa338d0..696d1e9 100644
--- a/source/tanya/container/list.d
+++ b/source/tanya/container/list.d
@@ -15,11 +15,13 @@
module tanya.container.list;
import std.algorithm.comparison;
-import std.algorithm.mutation;
+import std.algorithm.mutation : swap;
import std.algorithm.searching;
+import tanya.algorithm.mutation;
import tanya.container.entry;
import tanya.memory;
import tanya.meta.trait;
+import tanya.meta.transform;
import tanya.range.array;
import tanya.range.primitive;
diff --git a/source/tanya/container/queue.d b/source/tanya/container/queue.d
index 33144c0..7a42e85 100644
--- a/source/tanya/container/queue.d
+++ b/source/tanya/container/queue.d
@@ -14,7 +14,7 @@
*/
module tanya.container.queue;
-import std.algorithm.mutation;
+import tanya.algorithm.mutation;
import tanya.container.entry;
import tanya.exception;
import tanya.memory;
diff --git a/source/tanya/container/set.d b/source/tanya/container/set.d
index ad77ee9..3bf0dc5 100644
--- a/source/tanya/container/set.d
+++ b/source/tanya/container/set.d
@@ -15,7 +15,8 @@
*/
module tanya.container.set;
-import std.algorithm.mutation;
+import std.algorithm.mutation : swap;
+import tanya.algorithm.mutation;
import tanya.container;
import tanya.container.entry;
import tanya.memory;
diff --git a/source/tanya/container/string.d b/source/tanya/container/string.d
index 1873af1..ca5b946 100644
--- a/source/tanya/container/string.d
+++ b/source/tanya/container/string.d
@@ -27,9 +27,10 @@
module tanya.container.string;
import std.algorithm.comparison;
-import std.algorithm.mutation;
+import std.algorithm.mutation : bringToFront, copy, swap;
import std.algorithm.searching;
static import std.range;
+import tanya.algorithm.mutation;
import tanya.memory;
import tanya.meta.trait;
import tanya.meta.transform;
diff --git a/source/tanya/math/mp.d b/source/tanya/math/mp.d
index f7d4b76..6980a29 100644
--- a/source/tanya/math/mp.d
+++ b/source/tanya/math/mp.d
@@ -14,11 +14,13 @@
*/
module tanya.math.mp;
-import std.algorithm;
+import std.algorithm.comparison;
+import std.algorithm.mutation;
import std.range;
import tanya.container.array;
import tanya.encoding.ascii;
import tanya.memory;
+static import tanya.memory.op;
import tanya.meta.trait;
import tanya.meta.transform;
@@ -207,7 +209,7 @@ struct Integer
this(this) @nogc nothrow pure @safe
{
auto tmp = allocator.resize!digit(null, this.size);
- this.rep[0 .. this.size].copy(tmp);
+ tanya.memory.op.copy(this.rep[0 .. this.size], tmp);
this.rep = tmp;
}
@@ -340,7 +342,8 @@ struct Integer
if (is(Unqual!T == Integer))
{
this.rep = allocator.resize(this.rep, value.size);
- value.rep[0 .. value.size].copy(this.rep[0 .. value.size]);
+ tanya.memory.op.copy(value.rep[0 .. value.size],
+ this.rep[0 .. value.size]);
this.size = value.size;
this.sign = value.sign;
@@ -1023,7 +1026,10 @@ struct Integer
Integer opUnary(string op : "~")() const
{
auto ret = Integer(this, allocator);
- ret.rep[0 .. ret.size].each!((ref a) => a = ~a & mask);
+ foreach (ref a; ret.rep[0 .. ret.size])
+ {
+ a = ~a & mask;
+ }
return ret;
}