summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2017-08-21 06:49:02 +0200
committerEugen Wissner <belka@caraus.de>2017-08-21 06:49:02 +0200
commitce90b4865b2eb56d3466ca3a4731915c634145b1 (patch)
tree7c97b948460d5756e3288be3d9159ea7ede7904a /source
parentbeb5d6963bb13470325aa05fa5523e5ec508765f (diff)
downloadtanya-ce90b4865b2eb56d3466ca3a4731915c634145b1.tar.gz
Make front and popFront for arrays public
This commit adds tanya.range.array module which contains functions to make the arrays act as ranges. These functions don't do any auto-decoding for strings.
Diffstat (limited to 'source')
-rw-r--r--source/tanya/container/string.d28
-rw-r--r--source/tanya/range/array.d220
-rw-r--r--source/tanya/range/package.d15
3 files changed, 239 insertions, 24 deletions
diff --git a/source/tanya/container/string.d b/source/tanya/container/string.d
index c910562..68c258b 100644
--- a/source/tanya/container/string.d
+++ b/source/tanya/container/string.d
@@ -30,31 +30,11 @@ import core.exception;
import std.algorithm.comparison;
import std.algorithm.mutation;
import std.algorithm.searching;
-import std.range;
+import std.range : isInfinite, isInputRange, ElementEncodingType, hasLength,
+ popFrontN, empty;
import std.traits;
import tanya.memory;
-
-private ref const(wchar) front(const wchar[] str)
-pure nothrow @safe @nogc
-in
-{
- assert(str.length > 0);
-}
-body
-{
- return str[0];
-}
-
-private void popFront(ref const(wchar)[] str, const size_t s = 1)
-pure nothrow @safe @nogc
-in
-{
- assert(str.length >= s);
-}
-body
-{
- str = str[s .. $];
-}
+import tanya.range.array;
/**
* Thrown on encoding errors.
@@ -790,7 +770,7 @@ struct String
}
dchar d = (range[0] - 0xd800) | ((range[1] - 0xdc00) >> 10);
- range.popFront(2);
+ range.popFrontN(2);
}
else
{
diff --git a/source/tanya/range/array.d b/source/tanya/range/array.d
new file mode 100644
index 0000000..35483a0
--- /dev/null
+++ b/source/tanya/range/array.d
@@ -0,0 +1,220 @@
+/* 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/. */
+
+/**
+ * $(D_PSYMBOL tanya.range.array) implements range primitives for built-in arrays.
+ *
+ * This module is a submodule of
+ * $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/range/package.d, tanya.range).
+ *
+ * After importing of
+ * $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/range/array.d, tanya/range/array.d)
+ * built-in arrays can act as bidirectional ranges. For that to work the module
+ * defines a set of functions that accept a built-in array of any type as their
+ * first argument, so thanks to UFCS (Uniform Function Call Syntax) they can be
+ * called as if they were array member functions. For example the arrays the
+ * `.length`-property, but no `.empty` property. So here can be find the
+ * $(D_PSYMBOL empty) function. Since $(D_INLINECODE empty(array)) and
+ * $(D_INLINECODE array.empty) are equal for the arrays, arrays get a faked
+ * property `empty`.
+ *
+ * The functions in this module don't change array elements or its underlying
+ * storage, but some functions alter the slice. Each array maintains a pointer
+ * to its data and the length and there can be several pointers which point to
+ * the same data. Array pointer can be advanced and the length can be reduced
+ * without changing the underlying storage. So slices offer the possibility to
+ * have multiple views into the same array, point to different positions inside
+ * it.
+ *
+ * Strings ($(D_INLINECODE char[]), (D_INLINECODE wchar[]) and
+ * (D_INLINECODE dchar[])) are treated as any other normal array, they aren't
+ * auto-decoded.
+ *
+ * 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/range/array.d,
+ * tanya/range/array.d)
+ */
+module tanya.range.array;
+
+/**
+ * Returns the first element of the $(D_PARAM array).
+ *
+ * The element is returned by reference, so $(D_PSYMBOL front) can be also used
+ * to change the first element of $(D_PARAM array) if it is mutable.
+ *
+ * Params:
+ * T = Element type of $(D_PARAM array).
+ * array = Built-in array.
+ *
+ * Returns: First element.
+ *
+ * Precondition: $(D_INLINECODE array.length > 0).
+ */
+@property ref T front(T)(T[] array)
+in
+{
+ assert(array.length > 0);
+}
+body
+{
+ return array[0];
+}
+
+///
+pure nothrow @safe @nogc unittest
+{
+ string s = "Wenn die Wunde nicht mehr wehtut, schmerzt die Narbe";
+ static assert(is(typeof(s.front) == immutable char));
+ assert(s.front == 'W');
+
+ wstring w = "Волны несутся, гремя и сверкая";
+ static assert(is(typeof(w.front) == immutable wchar));
+ assert(w.front == 'В');
+
+ dstring d = "Для писателя память - это почти все";
+ static assert(is(typeof(d.front) == immutable dchar));
+ assert(d.front == 'Д');
+}
+
+/**
+ * Returns the last element of the $(D_PARAM array).
+ *
+ * The element is returned by reference, so $(D_PSYMBOL back) can be also used
+ * to change the last element of $(D_PARAM array) if it is mutable.
+ *
+ * Params:
+ * T = Element type of $(D_PARAM array).
+ * array = Built-in array.
+ *
+ * Returns: Last element.
+ *
+ * Precondition: $(D_INLINECODE array.length > 0).
+ */
+@property ref T back(T)(T[] array)
+in
+{
+ assert(array.length > 0);
+}
+body
+{
+ return array[$ - 1];
+}
+
+///
+pure nothrow @safe @nogc unittest
+{
+ string s = "Brecht";
+ static assert(is(typeof(s.back) == immutable char));
+ assert(s.back == 't');
+
+ wstring w = "Тютчев";
+ static assert(is(typeof(w.back) == immutable wchar));
+ assert(w.back == 'в');
+
+ dstring d = "Паустовский";
+ static assert(is(typeof(d.back) == immutable dchar));
+ assert(d.back == 'й');
+}
+
+/**
+ * $(D_PSYMBOL popFront) and $(D_PSYMBOL popBack) advance the $(D_PARAM array)
+ * and remove one element from its back, respectively.
+ *
+ * $(D_PSYMBOL popFront) and $(D_PSYMBOL popBack) don't alter the array
+ * storage, they only narrow the view into the array.
+ *
+ * Params:
+ * T = Element type of $(D_PARAM array).
+ * array = Built-in array.
+ *
+ * Precondition: $(D_INLINECODE array.length > 0).
+ */
+void popFront(T)(ref T[] array)
+in
+{
+ assert(array.length > 0);
+}
+body
+{
+ array = array[1 .. $];
+}
+
+/// Ditto.
+void popBack(T)(ref T[] array)
+in
+{
+ assert(array.length > 0);
+}
+body
+{
+ array = array[0 .. $ - 1];
+}
+
+///
+pure nothrow @safe @nogc unittest
+{
+ wstring array = "Der finstere Ozean der Metaphysik. Nietzsche";
+
+ array.popFront();
+ assert(array.length == 43);
+ assert(array.front == 'e');
+
+ array.popBack();
+ assert(array.length == 42);
+ assert(array.back == 'h');
+}
+
+/**
+ * Tests whether $(D_PARAM array) is empty.
+ *
+ * Params:
+ * T = Element type of $(D_PARAM array).
+ * array = Built-in array.
+ *
+ * Returns: $(D_KEYWORD true) if $(D_PARAM array) has no elements,
+ * $(D_KEYWORD false) otherwise.
+ */
+@property bool empty(T)(const T[] array)
+{
+ return array.length == 0;
+}
+
+///
+pure nothrow @safe @nogc unittest
+{
+ int[1] array;
+ assert(!array.empty);
+ assert(array[1 .. 1].empty);
+}
+
+/**
+ * Returns a copy of the slice $(D_PARAM array).
+ *
+ * $(D_PSYMBOL save) doesn't copy the array itself, but only the data pointer
+ * and the length.
+ *
+ * Params:
+ * T = Element type of $(D_PARAM array).
+ * array = Built-in array.
+ *
+ * Returns: A copy of the slice $(D_PARAM array).
+ */
+@property T[] save(T)(T[] array)
+{
+ return array;
+}
+
+///
+pure nothrow @safe @nogc unittest
+{
+ ubyte[8] array;
+ auto slice = array.save;
+
+ assert(slice.length == array.length);
+ slice.popFront();
+ assert(slice.length < array.length);
+}
diff --git a/source/tanya/range/package.d b/source/tanya/range/package.d
new file mode 100644
index 0000000..d291cd1
--- /dev/null
+++ b/source/tanya/range/package.d
@@ -0,0 +1,15 @@
+/* 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/. */
+
+/**
+ * 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/range/package.d,
+ * tanya/range/package.d)
+ */
+module tanya.range;
+
+public import tanya.range.array;