Compare commits
17 Commits
Author | SHA1 | Date | |
---|---|---|---|
3567a6608e | |||
520bd399a3 | |||
d38e33593e | |||
34b79ad46e | |||
515bf619e8 | |||
617eaab9a2 | |||
d946b598fd | |||
e9d7e9eb73 | |||
4dbfbe9874 | |||
25d59ffdda | |||
2c064eb05b | |||
c9a4a2f651 | |||
0e99effaeb | |||
0f1e53b4b9 | |||
666d59c231 | |||
ce90b4865b | |||
beb5d6963b |
2
.gitignore
vendored
2
.gitignore
vendored
@ -6,7 +6,7 @@
|
||||
.dub
|
||||
__test__*__
|
||||
__test__*__.core
|
||||
/tanya-test-library*
|
||||
/tanya-test-*
|
||||
|
||||
/docs/
|
||||
/docs.json
|
||||
|
@ -7,6 +7,7 @@ os:
|
||||
language: d
|
||||
|
||||
d:
|
||||
- dmd-2.076.0
|
||||
- dmd-2.075.1
|
||||
- dmd-2.074.1
|
||||
- dmd-2.073.2
|
||||
@ -22,7 +23,7 @@ addons:
|
||||
- gcc-multilib
|
||||
|
||||
before_script:
|
||||
- if [ "$PS1" = '(dmd-2.075.1)' ]; then
|
||||
- if [ "$PS1" = '(dmd-2.076.0)' ]; then
|
||||
export UNITTEST="unittest-cov";
|
||||
fi
|
||||
|
||||
|
@ -16,7 +16,7 @@ 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)
|
||||
* [Documentation](https://docs.caraus.io/tanya)
|
||||
* [API Documentation](https://docs.caraus.io/tanya)
|
||||
* [Contribution guidelines](CONTRIBUTING.md)
|
||||
|
||||
|
||||
@ -30,11 +30,16 @@ string, Hash set.
|
||||
* `format`: Formatting and conversion functions.
|
||||
* `math`: Arbitrary precision integer and a set of functions.
|
||||
* `memory`: Tools for manual memory management (allocators, smart pointers).
|
||||
* `meta`: Template metaprogramming. This package contains utilities to acquire
|
||||
type information at compile-time, to transform from one type to another. It has
|
||||
also different algorithms for iterating, searching and modifying template
|
||||
arguments.
|
||||
* `net`: URL-Parsing, network programming.
|
||||
* `network`: Socket implementation. `network` is currently under rework.
|
||||
After finishing the new socket implementation will land in the `net` package and
|
||||
`network` will be deprecated.
|
||||
* `os`: Platform-independent interfaces to operating system functionality.
|
||||
* `range`: Generic functions and templates for D ranges.
|
||||
* `typecons`: Templates that allow to build new types based on the available
|
||||
ones.
|
||||
|
||||
@ -139,6 +144,7 @@ There are more containers in the `tanya.container` package.
|
||||
|
||||
| dmd |
|
||||
|:-------:|
|
||||
| 2.076.0 |
|
||||
| 2.075.1 |
|
||||
| 2.074.1 |
|
||||
| 2.073.2 |
|
||||
|
@ -3,6 +3,12 @@ os: Visual Studio 2015
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- DC: dmd
|
||||
DVersion: 2.076.0
|
||||
arch: x64
|
||||
- DC: dmd
|
||||
DVersion: 2.076.0
|
||||
arch: x86
|
||||
- DC: dmd
|
||||
DVersion: 2.075.1
|
||||
arch: x64
|
||||
|
11
dub.json
11
dub.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "tanya",
|
||||
"description": "General purpose, @nogc library. Containers, networking, memory management, utilities",
|
||||
"description": "General purpose, @nogc library. Containers, networking, metaprogramming, memory management, utilities",
|
||||
"license": "MPL-2.0",
|
||||
"copyright": "(c) Eugene Wissner <info@caraus.de>",
|
||||
"authors": [
|
||||
@ -11,7 +11,14 @@
|
||||
|
||||
"configurations": [
|
||||
{
|
||||
"name": "library"
|
||||
"name": "library",
|
||||
"targetType": "library",
|
||||
"versions": ["TanyaPhobos"]
|
||||
},
|
||||
{
|
||||
"name": "native",
|
||||
"targetType": "library",
|
||||
"platforms": ["linux-x86_64"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -21,8 +21,9 @@ import std.algorithm.mutation;
|
||||
import std.conv;
|
||||
import std.range.primitives;
|
||||
import std.meta;
|
||||
import std.traits;
|
||||
import tanya.memory;
|
||||
import tanya.meta.trait;
|
||||
import tanya.meta.transform;
|
||||
|
||||
/**
|
||||
* Random-access range for the $(D_PSYMBOL Array).
|
||||
|
@ -14,8 +14,8 @@
|
||||
*/
|
||||
module tanya.container.buffer;
|
||||
|
||||
import std.traits;
|
||||
import tanya.memory;
|
||||
import tanya.meta.trait;
|
||||
|
||||
version (unittest)
|
||||
{
|
||||
|
@ -14,7 +14,7 @@
|
||||
*/
|
||||
module tanya.container.entry;
|
||||
|
||||
import std.traits;
|
||||
import tanya.meta.trait;
|
||||
import tanya.typecons;
|
||||
|
||||
package struct SEntry(T)
|
||||
|
@ -18,9 +18,9 @@ import std.algorithm.comparison;
|
||||
import std.algorithm.mutation;
|
||||
import std.algorithm.searching;
|
||||
import std.range.primitives;
|
||||
import std.traits;
|
||||
import tanya.container.entry;
|
||||
import tanya.memory;
|
||||
import tanya.meta.trait;
|
||||
|
||||
/**
|
||||
* Forward range for the $(D_PSYMBOL SList).
|
||||
|
@ -15,10 +15,10 @@
|
||||
module tanya.container.queue;
|
||||
|
||||
import core.exception;
|
||||
import std.traits;
|
||||
import std.algorithm.mutation;
|
||||
import tanya.container.entry;
|
||||
import tanya.memory;
|
||||
import tanya.meta.trait;
|
||||
|
||||
/**
|
||||
* FIFO queue.
|
||||
|
@ -16,10 +16,11 @@
|
||||
module tanya.container.set;
|
||||
|
||||
import std.algorithm.mutation;
|
||||
import std.traits;
|
||||
import tanya.container;
|
||||
import tanya.container.entry;
|
||||
import tanya.memory;
|
||||
import tanya.meta.trait;
|
||||
import tanya.meta.transform;
|
||||
|
||||
/**
|
||||
* Bidirectional range that iterates over the $(D_PSYMBOL Set)'s values.
|
||||
|
@ -30,31 +30,12 @@ import core.exception;
|
||||
import std.algorithm.comparison;
|
||||
import std.algorithm.mutation;
|
||||
import std.algorithm.searching;
|
||||
import std.range;
|
||||
import std.traits;
|
||||
import std.range : isInfinite, isInputRange, ElementEncodingType, hasLength,
|
||||
popFrontN, empty;
|
||||
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.meta.trait;
|
||||
import tanya.meta.transform;
|
||||
import tanya.range.array;
|
||||
|
||||
/**
|
||||
* Thrown on encoding errors.
|
||||
@ -790,7 +771,7 @@ struct String
|
||||
}
|
||||
dchar d = (range[0] - 0xd800) | ((range[1] - 0xdc00) >> 10);
|
||||
|
||||
range.popFront(2);
|
||||
range.popFrontN(2);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -8,15 +8,17 @@
|
||||
* 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)
|
||||
* Authors: Jeff Roberts, $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/format/conv.d,
|
||||
* tanya/format/conv.d)
|
||||
*/
|
||||
module tanya.format.conv;
|
||||
|
||||
import std.traits;
|
||||
import tanya.container.string;
|
||||
import tanya.memory;
|
||||
import tanya.memory.op;
|
||||
import tanya.meta.trait;
|
||||
import tanya.meta.transform;
|
||||
|
||||
/**
|
||||
* Thrown if a type conversion fails.
|
||||
@ -610,13 +612,15 @@ private @nogc unittest
|
||||
defaultAllocator.dispose(exception);
|
||||
}
|
||||
|
||||
package char[] number2String(T)(const T number, char[] buffer)
|
||||
// Returns the last part of buffer with converted number.
|
||||
package(tanya) char[] number2String(T)(const T number,
|
||||
return ref char[21] buffer)
|
||||
if (isIntegral!T)
|
||||
{
|
||||
// abs the integer.
|
||||
ulong n64 = number < 0 ? -cast(long) number : number;
|
||||
|
||||
char[20] rightAligned;
|
||||
char* start = rightAligned.ptr + rightAligned.sizeof;
|
||||
char* start = buffer[].ptr + buffer.sizeof - 1;
|
||||
|
||||
while (true)
|
||||
{
|
||||
@ -644,7 +648,7 @@ package char[] number2String(T)(const T number, char[] buffer)
|
||||
if (n64 == 0)
|
||||
{
|
||||
if ((start[0] == '0')
|
||||
&& (start != (rightAligned.ptr + rightAligned.sizeof)))
|
||||
&& (start != (buffer[].ptr + buffer.sizeof -1)))
|
||||
{
|
||||
++start;
|
||||
}
|
||||
@ -658,47 +662,24 @@ package char[] number2String(T)(const T number, char[] buffer)
|
||||
}
|
||||
}
|
||||
|
||||
// Get the length that we copied.
|
||||
auto l = cast(uint) ((rightAligned.ptr + rightAligned.sizeof) - start);
|
||||
// Get the length that we have copied.
|
||||
uint l = cast(uint) ((buffer[].ptr + buffer.sizeof - 1) - start);
|
||||
if (l == 0)
|
||||
{
|
||||
*--start = '0';
|
||||
l = 1;
|
||||
}
|
||||
|
||||
// Write the string.
|
||||
char* bp = buffer.ptr;
|
||||
|
||||
// Set sign.
|
||||
if (number < 0)
|
||||
else if (number < 0) // Set the sign.
|
||||
{
|
||||
*bp++ = '-';
|
||||
*--start = '-';
|
||||
++l;
|
||||
}
|
||||
|
||||
// Copy the string into the target buffer.
|
||||
uint n = l;
|
||||
while (n)
|
||||
{
|
||||
int i = n;
|
||||
n -= i;
|
||||
|
||||
while (i >= 4)
|
||||
{
|
||||
*cast(uint*) bp = *cast(uint*) start;
|
||||
bp += 4;
|
||||
start += 4;
|
||||
i -= 4;
|
||||
}
|
||||
while (i)
|
||||
{
|
||||
*bp++ = *start++;
|
||||
--i;
|
||||
}
|
||||
}
|
||||
return buffer[0 .. bp - buffer.ptr];
|
||||
return buffer[$ - l - 1 .. $ - 1];
|
||||
}
|
||||
|
||||
private @nogc unittest
|
||||
// Converting an integer to string.
|
||||
private pure nothrow @system @nogc unittest
|
||||
{
|
||||
char[21] buf;
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -17,9 +17,10 @@ module tanya.math.mp;
|
||||
import std.algorithm;
|
||||
import std.ascii;
|
||||
import std.range;
|
||||
import std.traits;
|
||||
import tanya.container.array;
|
||||
import tanya.memory;
|
||||
import tanya.meta.trait;
|
||||
import tanya.meta.transform;
|
||||
|
||||
/**
|
||||
* Algebraic sign.
|
||||
|
@ -14,9 +14,9 @@
|
||||
*/
|
||||
module tanya.math;
|
||||
|
||||
import std.traits;
|
||||
public import tanya.math.mp;
|
||||
public import tanya.math.random;
|
||||
import tanya.meta.trait;
|
||||
|
||||
version (unittest)
|
||||
{
|
||||
|
@ -14,6 +14,8 @@
|
||||
*/
|
||||
module tanya.memory.mallocator;
|
||||
|
||||
version (TanyaPhobos):
|
||||
|
||||
import core.stdc.stdlib;
|
||||
import tanya.memory.allocator;
|
||||
|
||||
|
@ -19,9 +19,9 @@ import std.algorithm.iteration;
|
||||
import std.algorithm.mutation;
|
||||
import std.conv;
|
||||
import std.range;
|
||||
import std.traits;
|
||||
public import tanya.memory.allocator;
|
||||
import tanya.memory.mmappool;
|
||||
import tanya.meta.trait;
|
||||
|
||||
/**
|
||||
* The mixin generates common methods for classes and structs using
|
||||
@ -137,17 +137,6 @@ body
|
||||
.allocator = allocator;
|
||||
}
|
||||
|
||||
private nothrow @nogc unittest
|
||||
{
|
||||
import tanya.memory.mallocator;
|
||||
|
||||
auto oldAllocator = defaultAllocator;
|
||||
defaultAllocator = Mallocator.instance;
|
||||
assert(defaultAllocator is Mallocator.instance);
|
||||
|
||||
defaultAllocator = oldAllocator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size in bytes of the state that needs to be allocated to hold an
|
||||
* object of type $(D_PARAM T).
|
||||
|
@ -22,8 +22,8 @@ import std.algorithm.comparison;
|
||||
import std.algorithm.mutation;
|
||||
import std.conv;
|
||||
import std.range;
|
||||
import std.traits;
|
||||
import tanya.memory;
|
||||
import tanya.meta.trait;
|
||||
|
||||
private template Payload(T)
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -5,6 +5,10 @@
|
||||
/**
|
||||
* Template metaprogramming.
|
||||
*
|
||||
* This package contains utilities to acquire type information at compile-time,
|
||||
* to transform from one type to another. It has also different algorithms for
|
||||
* iterating, searching and modifying template arguments.
|
||||
*
|
||||
* Copyright: Eugene Wissner 2017.
|
||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||
* Mozilla Public License, v. 2.0).
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -6,7 +6,8 @@
|
||||
* Type transformations.
|
||||
*
|
||||
* Templates in this module can be used to modify type qualifiers or transform
|
||||
* types.
|
||||
* types. They take some type as argument and return a different type after
|
||||
* perfoming the specified transformation.
|
||||
*
|
||||
* Copyright: Eugene Wissner 2017.
|
||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||
@ -17,6 +18,28 @@
|
||||
*/
|
||||
module tanya.meta.transform;
|
||||
|
||||
version (TanyaPhobos)
|
||||
{
|
||||
public import std.traits : Unqual,
|
||||
OriginalType,
|
||||
CopyConstness,
|
||||
CopyTypeQualifiers,
|
||||
Unsigned,
|
||||
Signed,
|
||||
PointerTarget,
|
||||
KeyType,
|
||||
ValueType,
|
||||
Promoted,
|
||||
InoutOf,
|
||||
ConstOf,
|
||||
SharedOf,
|
||||
SharedInoutOf,
|
||||
SharedConstOf,
|
||||
ImmutableOf,
|
||||
QualifierOf;
|
||||
}
|
||||
else:
|
||||
|
||||
import tanya.meta.trait;
|
||||
|
||||
/**
|
||||
@ -473,3 +496,246 @@ pure nothrow @safe @nogc unittest
|
||||
static assert(is(Promoted!(const bool) == const int));
|
||||
static assert(is(Promoted!(shared bool) == shared int));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds $(D_KEYWORD inout) qualifier to the type $(D_PARAM T).
|
||||
*
|
||||
* Params:
|
||||
* T = A type.
|
||||
*
|
||||
* Returns: $(D_INLINECODE inout(T)).
|
||||
*/
|
||||
alias InoutOf(T) = inout(T);
|
||||
|
||||
///
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
static assert(is(InoutOf!int == inout int));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds $(D_KEYWORD inout) qualifier to the type $(D_PARAM T).
|
||||
*
|
||||
* Params:
|
||||
* T = A type.
|
||||
*
|
||||
* Returns: $(D_INLINECODE inout(T)).
|
||||
*/
|
||||
alias ConstOf(T) = const(T);
|
||||
|
||||
///
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
static assert(is(ConstOf!int == const int));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds $(D_KEYWORD inout) qualifier to the type $(D_PARAM T).
|
||||
*
|
||||
* Params:
|
||||
* T = A type.
|
||||
*
|
||||
* Returns: $(D_INLINECODE inout(T)).
|
||||
*/
|
||||
alias SharedOf(T) = shared(T);
|
||||
|
||||
///
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
static assert(is(SharedOf!int == shared int));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds $(D_KEYWORD inout) qualifier to the type $(D_PARAM T).
|
||||
*
|
||||
* Params:
|
||||
* T = A type.
|
||||
*
|
||||
* Returns: $(D_INLINECODE inout(T)).
|
||||
*/
|
||||
alias SharedInoutOf(T) = shared(inout T);
|
||||
|
||||
///
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
static assert(is(SharedInoutOf!int == shared inout int));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds $(D_KEYWORD shared const) qualifier to the type $(D_PARAM T).
|
||||
*
|
||||
* Params:
|
||||
* T = A type.
|
||||
*
|
||||
* Returns: $(D_INLINECODE shared(const T)).
|
||||
*/
|
||||
alias SharedConstOf(T) = shared(const T);
|
||||
|
||||
///
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
static assert(is(SharedConstOf!int == shared const int));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds $(D_KEYWORD immutable) qualifier to the type $(D_PARAM T).
|
||||
*
|
||||
* Params:
|
||||
* T = A type.
|
||||
*
|
||||
* Returns: $(D_INLINECODE immutable(T)).
|
||||
*/
|
||||
alias ImmutableOf(T) = immutable(T);
|
||||
|
||||
///
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
static assert(is(ImmutableOf!int == immutable int));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds $(D_KEYWORD inout const) qualifier to the type $(D_PARAM T).
|
||||
*
|
||||
* Params:
|
||||
* T = A type.
|
||||
*
|
||||
* Returns: $(D_INLINECODE inout(const T)).
|
||||
*/
|
||||
alias InoutConstOf(T) = inout(const T);
|
||||
|
||||
///
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
static assert(is(InoutConstOf!int == inout const int));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds $(D_KEYWORD shared inout const) qualifier to the type $(D_PARAM T).
|
||||
*
|
||||
* Params:
|
||||
* T = A type.
|
||||
*
|
||||
* Returns: $(D_INLINECODE shared(inout const T)).
|
||||
*/
|
||||
alias SharedInoutConstOf(T) = shared(inout const T);
|
||||
|
||||
///
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
static assert(is(SharedInoutConstOf!int == shared inout const int));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a template with one argument which applies all qualifiers of
|
||||
* $(D_PARAM T) on its argument if instantiated.
|
||||
*
|
||||
* Params:
|
||||
* T = A type.
|
||||
*
|
||||
* Returns: $(D_INLINECODE shared(inout const T)).
|
||||
*/
|
||||
template QualifierOf(T)
|
||||
{
|
||||
static if (is(T U == const U))
|
||||
{
|
||||
alias QualifierOf = ConstOf;
|
||||
}
|
||||
else static if (is(T U == immutable U))
|
||||
{
|
||||
alias QualifierOf = ImmutableOf;
|
||||
}
|
||||
else static if (is(T U == inout U))
|
||||
{
|
||||
alias QualifierOf = InoutOf;
|
||||
}
|
||||
else static if (is(T U == inout const U))
|
||||
{
|
||||
alias QualifierOf = InoutConstOf;
|
||||
}
|
||||
else static if (is(T U == shared U))
|
||||
{
|
||||
alias QualifierOf = SharedOf;
|
||||
}
|
||||
else static if (is(T U == shared const U))
|
||||
{
|
||||
alias QualifierOf = SharedConstOf;
|
||||
}
|
||||
else static if (is(T U == shared inout U))
|
||||
{
|
||||
alias QualifierOf = SharedInoutOf;
|
||||
}
|
||||
else static if (is(T U == shared inout const U))
|
||||
{
|
||||
alias QualifierOf = SharedInoutConstOf;
|
||||
}
|
||||
else
|
||||
{
|
||||
alias QualifierOf(T) = T;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
alias MutableOf = QualifierOf!int;
|
||||
static assert(is(MutableOf!uint == uint));
|
||||
|
||||
alias ConstOf = QualifierOf!(const int);
|
||||
static assert(is(ConstOf!uint == const uint));
|
||||
|
||||
alias InoutOf = QualifierOf!(inout int);
|
||||
static assert(is(InoutOf!uint == inout uint));
|
||||
|
||||
alias InoutConstOf = QualifierOf!(inout const int);
|
||||
static assert(is(InoutConstOf!uint == inout const uint));
|
||||
|
||||
alias ImmutableOf = QualifierOf!(immutable int);
|
||||
static assert(is(ImmutableOf!uint == immutable uint));
|
||||
|
||||
alias SharedOf = QualifierOf!(shared int);
|
||||
static assert(is(SharedOf!uint == shared uint));
|
||||
|
||||
alias SharedConstOf = QualifierOf!(shared const int);
|
||||
static assert(is(SharedConstOf!uint == shared const uint));
|
||||
|
||||
alias SharedInoutOf = QualifierOf!(shared inout int);
|
||||
static assert(is(SharedInoutOf!uint == shared inout uint));
|
||||
|
||||
alias SharedInoutConstOf = QualifierOf!(shared inout const int);
|
||||
static assert(is(SharedInoutConstOf!uint == shared inout const uint));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the type of $(D_PARAM T). If $(D_PARAM T) is already a type,
|
||||
* $(D_PSYMBOL TypeOf) aliases itself to $(D_PARAM T).
|
||||
*
|
||||
* $(D_PSYMBOL TypeOf) evaluates to $(D_KEYWORD void) for template arguments.
|
||||
*
|
||||
* The symbols that don't have a type and aren't types cannot be used as
|
||||
* arguments to $(D_PSYMBOL TypeOf).
|
||||
*
|
||||
* Params:
|
||||
* T = Expression, type or template.
|
||||
*
|
||||
* Returns: The type of $(D_PARAM T).
|
||||
*/
|
||||
alias TypeOf(T) = T;
|
||||
|
||||
/// Ditto.
|
||||
template TypeOf(alias T)
|
||||
if (isExpressions!T || isTemplate!T)
|
||||
{
|
||||
alias TypeOf = typeof(T);
|
||||
}
|
||||
|
||||
///
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
struct S(T)
|
||||
{
|
||||
}
|
||||
static assert(is(TypeOf!S == void));
|
||||
static assert(is(TypeOf!int == int));
|
||||
static assert(is(TypeOf!true == bool));
|
||||
static assert(!is(TypeOf!(tanya.meta)));
|
||||
}
|
||||
|
@ -16,21 +16,8 @@ module tanya.net.inet;
|
||||
|
||||
import std.math;
|
||||
import std.range.primitives;
|
||||
import std.traits;
|
||||
|
||||
version (unittest)
|
||||
{
|
||||
version (Windows)
|
||||
{
|
||||
import core.sys.windows.winsock2;
|
||||
version = PlattformUnittest;
|
||||
}
|
||||
else version (Posix)
|
||||
{
|
||||
import core.sys.posix.arpa.inet;
|
||||
version = PlattformUnittest;
|
||||
}
|
||||
}
|
||||
import tanya.meta.trait;
|
||||
import tanya.meta.transform;
|
||||
|
||||
/**
|
||||
* Represents an unsigned integer as an $(D_KEYWORD ubyte) range.
|
||||
@ -212,79 +199,6 @@ private unittest
|
||||
static assert(!is(NetworkOrder!1));
|
||||
}
|
||||
|
||||
// Tests against the system's htonl, htons.
|
||||
version (PlattformUnittest)
|
||||
{
|
||||
private unittest
|
||||
{
|
||||
for (uint counter; counter <= 8 * uint.sizeof; ++counter)
|
||||
{
|
||||
const value = pow(2, counter) - 1;
|
||||
const inNetworkOrder = htonl(value);
|
||||
const p = cast(ubyte*) &inNetworkOrder;
|
||||
auto networkOrder = NetworkOrder!4(value);
|
||||
|
||||
assert(networkOrder.length == 4);
|
||||
assert(!networkOrder.empty);
|
||||
assert(networkOrder.front == *p);
|
||||
assert(networkOrder.back == *(p + 3));
|
||||
|
||||
networkOrder.popBack();
|
||||
assert(networkOrder.length == 3);
|
||||
assert(networkOrder.front == *p);
|
||||
assert(networkOrder.back == *(p + 2));
|
||||
|
||||
networkOrder.popFront();
|
||||
assert(networkOrder.length == 2);
|
||||
assert(networkOrder.front == *(p + 1));
|
||||
assert(networkOrder.back == *(p + 2));
|
||||
|
||||
networkOrder.popFront();
|
||||
assert(networkOrder.length == 1);
|
||||
assert(networkOrder.front == *(p + 2));
|
||||
assert(networkOrder.back == *(p + 2));
|
||||
|
||||
networkOrder.popBack();
|
||||
assert(networkOrder.length == 0);
|
||||
assert(networkOrder.empty);
|
||||
}
|
||||
|
||||
for (ushort counter; counter <= 8 * ushort.sizeof; ++counter)
|
||||
{
|
||||
const value = cast(ushort) (pow(2, counter) - 1);
|
||||
const inNetworkOrder = htons(value);
|
||||
const p = cast(ubyte*) &inNetworkOrder;
|
||||
|
||||
auto networkOrder = NetworkOrder!2(value);
|
||||
|
||||
assert(networkOrder.length == 2);
|
||||
assert(!networkOrder.empty);
|
||||
assert(networkOrder.front == *p);
|
||||
assert(networkOrder.back == *(p + 1));
|
||||
|
||||
networkOrder.popBack();
|
||||
assert(networkOrder.length == 1);
|
||||
assert(networkOrder.front == *p);
|
||||
assert(networkOrder.back == *p);
|
||||
|
||||
networkOrder.popBack();
|
||||
assert(networkOrder.length == 0);
|
||||
assert(networkOrder.empty);
|
||||
|
||||
networkOrder = NetworkOrder!2(value);
|
||||
|
||||
networkOrder.popFront();
|
||||
assert(networkOrder.length == 1);
|
||||
assert(networkOrder.front == *(p + 1));
|
||||
assert(networkOrder.back == *(p + 1));
|
||||
|
||||
networkOrder.popFront();
|
||||
assert(networkOrder.length == 0);
|
||||
assert(networkOrder.empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the $(D_KEYWORD ubyte) input range $(D_PARAM range) to
|
||||
* $(D_PARAM T).
|
||||
@ -330,29 +244,3 @@ pure nothrow @safe @nogc unittest
|
||||
auto networkOrder = NetworkOrder!4(value);
|
||||
assert(networkOrder.toHostOrder() == value);
|
||||
}
|
||||
|
||||
// Tests against the system's htonl, htons.
|
||||
version (PlattformUnittest)
|
||||
{
|
||||
private unittest
|
||||
{
|
||||
for (uint counter; counter <= 8 * uint.sizeof; ++counter)
|
||||
{
|
||||
const value = pow(2, counter) - 1;
|
||||
const inNetworkOrder = htonl(value);
|
||||
const p = cast(ubyte*) &inNetworkOrder;
|
||||
auto networkOrder = NetworkOrder!4(value);
|
||||
|
||||
assert(p[0 .. uint.sizeof].toHostOrder() == value);
|
||||
}
|
||||
for (ushort counter; counter <= 8 * ushort.sizeof; ++counter)
|
||||
{
|
||||
const value = cast(ushort) (pow(2, counter) - 1);
|
||||
const inNetworkOrder = htons(value);
|
||||
const p = cast(ubyte*) &inNetworkOrder;
|
||||
auto networkOrder = NetworkOrder!2(value);
|
||||
|
||||
assert(p[0 .. ushort.sizeof].toHostOrder() == value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
220
source/tanya/range/array.d
Normal file
220
source/tanya/range/array.d
Normal file
@ -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);
|
||||
}
|
18
source/tanya/range/package.d
Normal file
18
source/tanya/range/package.d
Normal file
@ -0,0 +1,18 @@
|
||||
/* 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/. */
|
||||
|
||||
/**
|
||||
* This package contains generic function and templates to be used with D
|
||||
* ranges.
|
||||
*
|
||||
* 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;
|
@ -17,7 +17,7 @@
|
||||
*/
|
||||
module tanya.typecons;
|
||||
|
||||
import std.meta;
|
||||
import tanya.meta.metafunction;
|
||||
|
||||
/**
|
||||
* $(D_PSYMBOL Pair) can store two heterogeneous objects.
|
||||
|
Reference in New Issue
Block a user