12 Commits

Author SHA1 Message Date
964a7af32f Fix list assertions for release build 2018-04-18 14:23:12 +02:00
40c961867e Remove deprecated traits and queue 2018-04-18 06:34:28 +02:00
3fee712c6c Implement DList.popFirstOf and DList.popLastOf
Fix #37.
2018-04-17 14:46:12 +02:00
012c2d4c18 Remove support for dmd 2.076.1 2018-04-15 06:50:37 +02:00
d267a9cc64 Implement SList.popFirstOf
Fix #36.

Slicing for the SList on top of the existing SRange would be inefficent.
There would be two cases:
- Range iterates till the end of the list.
- Range iterates till some element "end".

If both cases are implemented in the same range, this range should check
for both conditions (end of the list and "begin == end") instead of only
one (end of the list).

Introducing a different range is undesirable since all containers have
currently only one range.
2018-04-14 16:15:35 +02:00
ddb02e41eb Add dscanner style check to CI
Fix #38.
2018-04-12 17:14:22 +02:00
d157e88b7a Fix import order in math.random 2018-04-08 05:59:14 +02:00
d5064fa2b2 Add missing tail isn't null assertion 2018-04-07 19:20:08 +02:00
f15a90543f Remove support for moveFront/moveBack/moveAt
Range elements are movable (mobile) if they are returned by reference
and can be moved or if the elements doesn't define an elaborate postblit
constructor. Allowing to define custom moveFront/moveBack/moveAt makes
the range definition more complex (particulary writing range adapters)
without a good reason.
2018-04-03 21:44:50 +02:00
a0ac8355f9 Fix #29 2018-04-01 10:34:18 +02:00
9b1f72472f Deprecate SList.length and DList.length
As they have O(n) complexity. The lists length is unknown without
iterating.
2018-03-31 08:21:15 +02:00
af45de842e Take MmapPool from the standard builds 2018-03-29 16:54:56 +02:00
27 changed files with 428 additions and 973 deletions

View File

@ -7,10 +7,9 @@ os:
language: d
d:
- dmd-2.079.0
- dmd-2.079.1
- dmd-2.078.3
- dmd-2.077.1
- dmd-2.076.1
env:
matrix:
@ -23,12 +22,17 @@ addons:
- gcc-multilib
before_script:
- if [ "$PS1" = '(dmd-2.079.0)' ]; then
- if [ "`$DC --version | head -n 1 | grep 'v2.079.1'`" ]; then
export UNITTEST="unittest-cov";
fi
script:
- dub test -b ${UNITTEST:-unittest} --arch=$ARCH --compiler=$DC
- if [ "$UNITTEST" ] && [ "$ARCH" = "x86_64" ] && [ "$TRAVIS_OS_NAME" = "linux" ];
then
dub fetch dscanner;
dub run dscanner -- --styleCheck ./source/;
fi
after_success:
- test "$UNITTEST" = "unittest-cov" && bash <(curl -s https://codecov.io/bash)
- test "$UNITTEST" && bash <(curl -s https://codecov.io/bash)

View File

@ -172,10 +172,9 @@ parameter is used)
| DMD | GCC |
|:-------:|:---------:|
| 2.079.0 | *master* |
| 2.079.1 | *master* |
| 2.078.3 | |
| 2.077.1 | |
| 2.076.1 | |
### Current status

View File

@ -4,10 +4,10 @@ os: Visual Studio 2015
environment:
matrix:
- DC: dmd
DVersion: 2.079.0
DVersion: 2.079.1
arch: x64
- DC: dmd
DVersion: 2.079.0
DVersion: 2.079.1
arch: x86
- DC: dmd
DVersion: 2.078.3
@ -21,12 +21,6 @@ environment:
- DC: dmd
DVersion: 2.077.1
arch: x86
- DC: dmd
DVersion: 2.076.1
arch: x64
- DC: dmd
DVersion: 2.076.1
arch: x86
skip_tags: true

View File

@ -279,7 +279,7 @@ struct Array(T)
}
///
@trusted @nogc unittest
@nogc nothrow pure @safe unittest
{
auto v1 = Array!int([1, 2, 3]);
auto v2 = Array!int(v1);
@ -291,19 +291,6 @@ struct Array(T)
assert(v3.capacity == 3);
}
private @trusted @nogc unittest // const constructor tests
{
auto v1 = const Array!int([1, 2, 3]);
auto v2 = Array!int(v1);
assert(v1.data !is v2.data);
assert(v1 == v2);
auto v3 = const Array!int(Array!int([1, 2, 3]));
assert(v1 == v3);
assert(v3.length == 3);
assert(v3.capacity == 3);
}
/**
* Creates a new $(D_PSYMBOL Array).
*
@ -339,7 +326,7 @@ struct Array(T)
}
///
unittest
@nogc nothrow pure @safe unittest
{
auto v = Array!int([3, 8, 2]);
@ -349,7 +336,7 @@ struct Array(T)
}
///
unittest
@nogc nothrow pure @safe unittest
{
auto v = Array!int(3, 5);
@ -358,11 +345,6 @@ struct Array(T)
assert(v[0] == 5 && v[1] == 5 && v[2] == 5);
}
@safe unittest
{
auto v1 = Array!int(defaultAllocator);
}
/**
* Destroys this $(D_PSYMBOL Array).
*/
@ -392,7 +374,7 @@ struct Array(T)
}
///
unittest
@nogc nothrow pure @safe unittest
{
auto v = Array!int([18, 20, 15]);
v.clear();
@ -409,7 +391,7 @@ struct Array(T)
}
///
@safe @nogc unittest
@nogc nothrow pure @safe unittest
{
auto v = Array!int(4);
assert(v.capacity == 4);
@ -461,7 +443,7 @@ struct Array(T)
}
///
unittest
@nogc nothrow pure @safe unittest
{
Array!int v;
@ -529,7 +511,7 @@ struct Array(T)
}
///
@nogc @safe unittest
@nogc nothrow pure @safe unittest
{
Array!int v;
assert(v.capacity == 0);
@ -564,7 +546,7 @@ struct Array(T)
}
///
@nogc @safe unittest
@nogc nothrow pure @safe unittest
{
Array!int v;
assert(v.capacity == 0);
@ -629,7 +611,7 @@ struct Array(T)
}
///
unittest
@nogc nothrow pure @safe unittest
{
auto v = Array!int([5, 18, 17]);
@ -674,7 +656,7 @@ struct Array(T)
}
///
@safe @nogc unittest
@nogc nothrow pure @safe unittest
{
auto v = Array!int([5, 18, 17, 2, 4, 6, 1]);
@ -759,7 +741,7 @@ struct Array(T)
alias insert = insertBack;
///
unittest
@nogc nothrow pure @safe unittest
{
struct TestRange
{
@ -927,7 +909,7 @@ struct Array(T)
}
///
unittest
@nogc nothrow pure unittest
{
Array!int v1;
v1.insertAfter(v1[], [2, 8]);
@ -963,7 +945,7 @@ struct Array(T)
}
///
unittest
@nogc nothrow pure unittest
{
Array!int v1;
v1.insertBefore(v1[], [2, 8]);
@ -1022,7 +1004,7 @@ struct Array(T)
}
///
nothrow @safe @nogc unittest
@nogc nothrow pure @safe unittest
{
Array!int a = Array!int(1);
a[0] = 5;
@ -1052,7 +1034,7 @@ struct Array(T)
}
///
@nogc unittest
@nogc nothrow pure @safe unittest
{
auto v1 = Array!int([12, 1, 7]);
@ -1101,7 +1083,7 @@ struct Array(T)
}
///
unittest
@nogc nothrow pure @safe unittest
{
const v1 = Array!int([6, 123, 34, 5]);
@ -1156,7 +1138,7 @@ struct Array(T)
}
///
unittest
@nogc nothrow pure @safe unittest
{
Array!int v1, v2;
assert(v1 == v2);
@ -1191,7 +1173,7 @@ struct Array(T)
}
///
@safe unittest
@nogc nothrow pure @safe unittest
{
auto v = Array!int([5]);
@ -1218,7 +1200,7 @@ struct Array(T)
}
///
unittest
@nogc nothrow pure @safe unittest
{
auto v = Array!int([5]);
@ -1263,16 +1245,7 @@ struct Array(T)
}
///
unittest
{
Array!int v;
auto r = v[];
assert(r.length == 0);
assert(r.empty);
}
///
unittest
@nogc nothrow pure @safe unittest
{
auto v = Array!int([1, 2, 3]);
auto r = v[];
@ -1290,7 +1263,7 @@ struct Array(T)
}
///
unittest
@nogc nothrow pure @safe unittest
{
auto v = Array!int([1, 2, 3, 4]);
auto r = v[1 .. 4];
@ -1363,7 +1336,7 @@ struct Array(T)
}
///
@nogc @safe unittest
@nogc nothrow pure @safe unittest
{
auto v1 = Array!int([3, 3, 3]);
auto v2 = Array!int([1, 2]);
@ -1397,7 +1370,7 @@ struct Array(T)
}
///
unittest
@nogc nothrow pure @safe unittest
{
auto v = Array!int([1, 2, 4]);
auto data = v.get();
@ -1464,7 +1437,7 @@ struct Array(T)
}
///
@safe @nogc unittest
@nogc nothrow pure @safe unittest
{
auto v1 = const Array!int([5, 15, 8]);
Array!int v2;
@ -1472,22 +1445,6 @@ struct Array(T)
assert(v1 == v2);
}
///
@safe @nogc unittest
{
auto v1 = const Array!int([5, 15, 8]);
Array!int v2;
v2 = v1[0 .. 2];
assert(equal(v1[0 .. 2], v2[]));
}
// Move assignment.
private @safe @nogc unittest
{
Array!int v1;
v1 = Array!int([5, 15, 8]);
}
/**
* Assigns a static array.
*
@ -1503,7 +1460,7 @@ struct Array(T)
}
///
@safe @nogc unittest
@nogc nothrow pure @safe unittest
{
auto v1 = Array!int([5, 15, 8]);
Array!int v2;
@ -1516,7 +1473,7 @@ struct Array(T)
}
///
unittest
@nogc nothrow pure @safe unittest
{
auto v = Array!int([5, 15, 8]);
@ -1530,7 +1487,7 @@ unittest
assert(r.front == v.front);
}
@nogc unittest
@nogc nothrow pure @safe unittest
{
const v1 = Array!int();
const Array!int v2;
@ -1538,7 +1495,7 @@ unittest
static assert(is(PointerTarget!(typeof(v3.data)) == const(int)));
}
@nogc unittest
@nogc nothrow pure @safe unittest
{
// Test that const arrays return usable ranges.
auto v = const Array!int([1, 2, 4]);
@ -1559,7 +1516,7 @@ unittest
static assert(is(typeof(r2[])));
}
@nogc unittest
@nogc nothrow pure @safe unittest
{
Array!int v1;
const Array!int v2;
@ -1581,18 +1538,18 @@ unittest
assert(!v1[].equal(v2[]));
}
@nogc unittest
@nogc nothrow pure @safe unittest
{
struct MutableEqualsStruct
{
int opEquals(typeof(this) that) @nogc
int opEquals(typeof(this) that) @nogc nothrow pure @safe
{
return true;
}
}
struct ConstEqualsStruct
{
int opEquals(const typeof(this) that) const @nogc
int opEquals(const typeof(this) that) const @nogc nothrow pure @safe
{
return true;
}
@ -1619,18 +1576,18 @@ unittest
assert(v7[].equal(v8[]));
}
@nogc unittest
@nogc nothrow pure @safe unittest
{
struct SWithDtor
{
~this() @nogc
~this() @nogc nothrow pure @safe
{
}
}
auto v = Array!SWithDtor(); // Destructor can destroy empty arrays.
}
private unittest
@nogc nothrow pure @safe unittest
{
class A
{
@ -1642,7 +1599,7 @@ private unittest
static assert(is(Array!(A*)));
}
private @safe @nogc unittest
@nogc nothrow pure @safe unittest
{
auto v = Array!int([5, 15, 8]);
{
@ -1670,3 +1627,45 @@ private @safe @nogc unittest
assert(i == 0);
}
}
// const constructor tests
@nogc nothrow pure @safe unittest
{
auto v1 = const Array!int([1, 2, 3]);
auto v2 = Array!int(v1);
assert(v1.data !is v2.data);
assert(v1 == v2);
auto v3 = const Array!int(Array!int([1, 2, 3]));
assert(v1 == v3);
assert(v3.length == 3);
assert(v3.capacity == 3);
}
@nogc nothrow pure @safe unittest
{
auto v1 = Array!int(defaultAllocator);
}
@nogc nothrow pure @safe unittest
{
Array!int v;
auto r = v[];
assert(r.length == 0);
assert(r.empty);
}
@nogc nothrow pure @safe unittest
{
auto v1 = const Array!int([5, 15, 8]);
Array!int v2;
v2 = v1[0 .. 2];
assert(equal(v1[0 .. 2], v2[]));
}
// Move assignment
@nogc nothrow pure @safe unittest
{
Array!int v1;
v1 = Array!int([5, 15, 8]);
}

View File

@ -120,7 +120,7 @@ struct ReadBuffer(T = ubyte)
}
///
unittest
@nogc nothrow pure @safe unittest
{
ReadBuffer!ubyte b;
assert(b.capacity == 0);
@ -165,7 +165,7 @@ struct ReadBuffer(T = ubyte)
}
///
unittest
@nogc nothrow pure unittest
{
ReadBuffer!ubyte b;
size_t numberRead;
@ -197,7 +197,7 @@ struct ReadBuffer(T = ubyte)
}
///
unittest
@nogc nothrow pure unittest
{
ReadBuffer!ubyte b;
size_t numberRead;
@ -272,7 +272,7 @@ struct ReadBuffer(T = ubyte)
}
///
unittest
@nogc nothrow pure unittest
{
ReadBuffer!ubyte b;
size_t numberRead;
@ -293,7 +293,7 @@ struct ReadBuffer(T = ubyte)
mixin DefaultAllocator;
}
private unittest
@nogc nothrow pure @safe unittest
{
static assert(is(ReadBuffer!int));
}
@ -399,7 +399,7 @@ struct WriteBuffer(T = ubyte)
alias opDollar = length;
///
unittest
@nogc nothrow pure unittest
{
auto b = WriteBuffer!ubyte(4);
ubyte[3] buf = [48, 23, 255];
@ -498,42 +498,6 @@ struct WriteBuffer(T = ubyte)
return this;
}
///
unittest
{
auto b = WriteBuffer!ubyte(4);
ubyte[3] buf = [48, 23, 255];
b ~= buf;
assert(b.capacity == 4);
assert(b.buffer_[0] == 48 && b.buffer_[1] == 23 && b.buffer_[2] == 255);
b += 2;
b ~= buf;
assert(b.capacity == 4);
assert(b.buffer_[0] == 23 && b.buffer_[1] == 255
&& b.buffer_[2] == 255 && b.buffer_[3] == 48);
b += 2;
b ~= buf;
assert(b.capacity == 8);
assert(b.buffer_[0] == 23 && b.buffer_[1] == 255
&& b.buffer_[2] == 48 && b.buffer_[3] == 23 && b.buffer_[4] == 255);
}
///
unittest
{
auto b = WriteBuffer!ubyte(2);
ubyte[3] buf = [48, 23, 255];
b ~= buf;
assert(b.start == 0);
assert(b.capacity == 4);
assert(b.ring == 3);
assert(b.position == 3);
}
/**
* Sets how many bytes were written. It will shrink the buffer
* appropriately. Always call it after $(D_PSYMBOL opIndex).
@ -607,7 +571,7 @@ struct WriteBuffer(T = ubyte)
}
///
unittest
@nogc nothrow pure unittest
{
auto b = WriteBuffer!ubyte(6);
ubyte[6] buf = [23, 23, 255, 128, 127, 9];
@ -648,7 +612,7 @@ struct WriteBuffer(T = ubyte)
}
///
unittest
@nogc nothrow pure unittest
{
auto b = WriteBuffer!ubyte(6);
ubyte[6] buf = [23, 23, 255, 128, 127, 9];
@ -686,7 +650,41 @@ struct WriteBuffer(T = ubyte)
mixin DefaultAllocator;
}
private unittest
@nogc nothrow pure @safe unittest
{
static assert(is(typeof(WriteBuffer!int(5))));
}
@nogc nothrow pure unittest
{
auto b = WriteBuffer!ubyte(4);
ubyte[3] buf = [48, 23, 255];
b ~= buf;
assert(b.capacity == 4);
assert(b.buffer_[0] == 48 && b.buffer_[1] == 23 && b.buffer_[2] == 255);
b += 2;
b ~= buf;
assert(b.capacity == 4);
assert(b.buffer_[0] == 23 && b.buffer_[1] == 255
&& b.buffer_[2] == 255 && b.buffer_[3] == 48);
b += 2;
b ~= buf;
assert(b.capacity == 8);
assert(b.buffer_[0] == 23 && b.buffer_[1] == 255
&& b.buffer_[2] == 48 && b.buffer_[3] == 23 && b.buffer_[4] == 255);
}
@nogc nothrow pure unittest
{
auto b = WriteBuffer!ubyte(2);
ubyte[3] buf = [48, 23, 255];
b ~= buf;
assert(b.start == 0);
assert(b.capacity == 4);
assert(b.ring == 3);
assert(b.position == 3);
}

View File

@ -156,7 +156,8 @@ struct SList(T)
* init = Initial value to fill the list with.
* allocator = Allocator.
*/
this(const size_t len, T init, shared Allocator allocator = defaultAllocator) @trusted
this(size_t len, T init, shared Allocator allocator = defaultAllocator)
@trusted
{
this(allocator);
if (len == 0)
@ -181,7 +182,7 @@ struct SList(T)
}
/// ditto
this(const size_t len, shared Allocator allocator = defaultAllocator)
this(size_t len, shared Allocator allocator = defaultAllocator)
{
this(len, T.init, allocator);
}
@ -434,15 +435,19 @@ struct SList(T)
assert(l2.front == 9);
}
version (assert)
private bool checkRangeBelonging(ref const Range r) const
{
private bool checkRangeBelonging(ref Range r) const
version (assert)
{
const(Entry*)* pos = &this.head;
for (; pos != r.head && *pos !is null; pos = &(*pos).next)
const(Entry)* pos = this.head;
for (; pos !is *r.head && pos !is null; pos = pos.next)
{
}
return pos == r.head;
return pos is *r.head;
}
else
{
return true;
}
}
@ -560,28 +565,12 @@ struct SList(T)
assert(l1 == l2);
}
/**
* Returns: How many elements are in the list.
*/
deprecated
@property size_t length() const
{
return count(this[]);
}
///
@nogc nothrow pure @safe unittest
{
SList!int l;
l.insertFront(8);
l.insertFront(9);
assert(l.length == 2);
l.removeFront();
assert(l.length == 1);
l.removeFront();
assert(l.length == 0);
}
/**
* Comparison for equality.
*
@ -672,7 +661,7 @@ struct SList(T)
*
* Returns: The number of elements removed.
*/
size_t removeFront(const size_t howMany)
size_t removeFront(size_t howMany)
out (removed)
{
assert(removed <= howMany);
@ -735,6 +724,50 @@ struct SList(T)
assert(l1 == l2);
}
/**
* Removes the front element of the $(D_PARAM range) from the list.
*
* Params:
* range = Range whose front element should be removed.
*
* Returns: $(D_PSYMBOL range) with its front element removed.
*
* Precondition: $(D_INLINECODE !range.empty).
* $(D_PARAM range) is extracted from this list.
*/
Range popFirstOf(Range range)
in
{
assert(!range.empty);
assert(checkRangeBelonging(range));
}
do
{
auto next = (*range.head).next;
allocator.dispose(*range.head);
*range.head = next;
return range;
}
///
@nogc nothrow pure @safe unittest
{
auto list = SList!int([5, 234, 30]);
auto range = list[];
range.popFront();
assert(list.popFirstOf(range).front == 30);
range = list[];
assert(range.front == 5);
range.popFront;
assert(range.front == 30);
range.popFront;
assert(range.empty);
}
/**
* Returns: Range that iterates over all elements of the container, in
* forward order.
@ -941,6 +974,7 @@ struct DRange(L)
invariant
{
assert(this.head !is null);
assert(this.tail !is null);
}
private this(ref EntryPointer head, ref EntryPointer tail) @trusted
@ -1096,7 +1130,8 @@ struct DList(T)
* init = Initial value to fill the list with.
* allocator = Allocator.
*/
this(const size_t len, T init, shared Allocator allocator = defaultAllocator) @trusted
this(size_t len, T init, shared Allocator allocator = defaultAllocator)
@trusted
{
this(allocator);
if (len == 0)
@ -1124,7 +1159,7 @@ struct DList(T)
}
/// ditto
this(const size_t len, shared Allocator allocator = defaultAllocator)
this(size_t len, shared Allocator allocator = defaultAllocator)
{
this(len, T.init, allocator);
}
@ -1571,15 +1606,19 @@ struct DList(T)
/// ditto
alias insert = insertBack;
version (assert)
private bool checkRangeBelonging(ref const Range r) const
{
private bool checkRangeBelonging(ref Range r) const
version (assert)
{
const(Entry*)* pos = &this.head;
for (; pos != r.head && *pos !is null; pos = &(*pos).next)
const(Entry)* pos = this.head;
for (; pos !is *r.head && pos !is null; pos = pos.next)
{
}
return pos == r.head;
return pos is *r.head;
}
else
{
return true;
}
}
@ -1815,28 +1854,12 @@ struct DList(T)
return insertAfter!(T[])(r, el[]);
}
/**
* Returns: How many elements are in the list.
*/
deprecated
@property size_t length() const
{
return count(this[]);
}
///
@nogc nothrow pure @safe unittest
{
DList!int l;
l.insertFront(8);
l.insertFront(9);
assert(l.length == 2);
l.removeFront();
assert(l.length == 1);
l.removeFront();
assert(l.length == 0);
}
/**
* Comparison for equality.
*
@ -1897,7 +1920,7 @@ struct DList(T)
{
auto n = this.head.next;
this.allocator_.dispose(this.head);
allocator.dispose(this.head);
this.head = n;
if (this.head is null)
{
@ -1970,7 +1993,7 @@ struct DList(T)
*
* Returns: The number of elements removed.
*/
size_t removeFront(const size_t howMany)
size_t removeFront(size_t howMany)
out (removed)
{
assert(removed <= howMany);
@ -1997,7 +2020,7 @@ struct DList(T)
}
/// ditto
size_t removeBack(const size_t howMany)
size_t removeBack(size_t howMany)
out (removed)
{
assert(removed <= howMany);
@ -2057,11 +2080,7 @@ struct DList(T)
while (e !is *tailNext)
{
auto next = e.next;
/* Workaround for dmd 2.076.1 bug on OSX. Invariants fail when
the allocator is called. Here it should be safe to use
allocator_ directory, since the list isn't empty.
See also removeFront. */
this.allocator_.dispose(e);
allocator.dispose(e);
e = next;
}
@ -2101,6 +2120,57 @@ struct DList(T)
assert(l1 == l2);
}
/**
* Removes the front or back element of the $(D_PARAM range) from the list
* respectively.
*
* Params:
* range = Range whose element should be removed.
*
* Returns: $(D_PSYMBOL range) with its front or back element removed.
*
* Precondition: $(D_INLINECODE !range.empty).
* $(D_PARAM range) is extracted from this list.
*/
Range popFirstOf(Range range)
in
{
assert(!range.empty);
}
do
{
remove(Range(*range.head, *range.head));
return range;
}
/// ditto
Range popLastOf(Range range)
in
{
assert(!range.empty);
}
do
{
remove(Range(*range.tail, *range.tail));
return range;
}
///
@nogc nothrow pure @safe unittest
{
auto list = DList!int([5, 234, 30]);
auto range = list[];
range.popFront();
range = list.popFirstOf(range);
assert(range.front == 30);
assert(range.back == 30);
assert(list.popLastOf(range).empty);
assert(list[].front == 5);
assert(list[].back == 5);
}
/**
* Returns: Range that iterates over all elements of the container, in
* forward order.

View File

@ -17,7 +17,6 @@ module tanya.container;
public import tanya.container.array;
public import tanya.container.buffer;
public import tanya.container.list;
public import tanya.container.queue;
public import tanya.container.set;
public import tanya.container.string;

View File

@ -1,291 +0,0 @@
/* 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/. */
/**
* FIFO queue.
*
* Copyright: Eugene Wissner 2016-2018.
* 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/container/queue.d,
* tanya/container/queue.d)
*/
deprecated("Use tanya.container.list.DList instead")
module tanya.container.queue;
import tanya.algorithm.mutation;
import tanya.container.entry;
import tanya.exception;
import tanya.memory;
import tanya.meta.trait;
/**
* FIFO queue.
*
* Params:
* T = Content type.
*/
struct Queue(T)
{
/**
* Removes all elements from the queue.
*/
~this()
{
while (!empty)
{
dequeue();
}
}
/**
* Returns how many elements are in the queue. It iterates through the queue
* to count the elements.
*
* Returns: How many elements are in the queue.
*/
size_t length() const
{
size_t len;
for (const(SEntry!T)* i = first; i !is null; i = i.next)
{
++len;
}
return len;
}
///
unittest
{
Queue!int q;
assert(q.length == 0);
q.enqueue(5);
assert(q.length == 1);
q.enqueue(4);
assert(q.length == 2);
q.enqueue(9);
assert(q.length == 3);
q.dequeue();
assert(q.length == 2);
q.dequeue();
assert(q.length == 1);
q.dequeue();
assert(q.length == 0);
}
private void enqueueEntry(ref SEntry!T* entry)
{
if (empty)
{
first = rear = entry;
}
else
{
rear.next = entry;
rear = rear.next;
}
}
private SEntry!T* allocateEntry()
{
auto temp = cast(SEntry!T*) allocator.allocate(SEntry!T.sizeof);
if (temp is null)
{
onOutOfMemoryError();
}
return temp;
}
/**
* Inserts a new element.
*
* Params:
* x = New element.
*/
void enqueue(ref T x)
{
auto temp = allocateEntry();
*temp = SEntry!T.init;
temp.content = x;
enqueueEntry(temp);
}
/// ditto
void enqueue(T x)
{
auto temp = allocateEntry();
moveEmplace(x, (*temp).content);
(*temp).next = null;
enqueueEntry(temp);
}
///
unittest
{
Queue!int q;
assert(q.empty);
q.enqueue(8);
q.enqueue(9);
assert(q.dequeue() == 8);
assert(q.dequeue() == 9);
}
/**
* Returns: $(D_KEYWORD true) if the queue is empty.
*/
@property bool empty() const
{
return first is null;
}
///
unittest
{
Queue!int q;
int value = 7;
assert(q.empty);
q.enqueue(value);
assert(!q.empty);
}
/**
* Move the position to the next element.
*
* Returns: Dequeued element.
*/
T dequeue()
in
{
assert(!empty);
}
do
{
auto n = first.next;
T ret = move(first.content);
allocator.dispose(first);
first = n;
return ret;
}
///
unittest
{
Queue!int q;
q.enqueue(8);
q.enqueue(9);
assert(q.dequeue() == 8);
assert(q.dequeue() == 9);
}
/**
* $(D_KEYWORD foreach) iteration. The elements will be automatically
* dequeued.
*
* Params:
* dg = $(D_KEYWORD foreach) body.
*
* Returns: The value returned from $(D_PARAM dg).
*/
int opApply(scope int delegate(ref size_t i, ref T) @nogc dg)
{
int result;
for (size_t i; !empty; ++i)
{
auto e = dequeue();
if ((result = dg(i, e)) != 0)
{
return result;
}
}
return result;
}
/// ditto
int opApply(scope int delegate(ref T) @nogc dg)
{
int result;
while (!empty)
{
auto e = dequeue();
if ((result = dg(e)) != 0)
{
return result;
}
}
return result;
}
///
unittest
{
Queue!int q;
size_t j;
q.enqueue(5);
q.enqueue(4);
q.enqueue(9);
foreach (i, e; q)
{
assert(i != 2 || e == 9);
assert(i != 1 || e == 4);
assert(i != 0 || e == 5);
++j;
}
assert(j == 3);
assert(q.empty);
j = 0;
q.enqueue(5);
q.enqueue(4);
q.enqueue(9);
foreach (e; q)
{
assert(j != 2 || e == 9);
assert(j != 1 || e == 4);
assert(j != 0 || e == 5);
++j;
}
assert(j == 3);
assert(q.empty);
}
private SEntry!T* first;
private SEntry!T* rear;
mixin DefaultAllocator;
}
///
unittest
{
Queue!int q;
q.enqueue(5);
assert(!q.empty);
q.enqueue(4);
q.enqueue(9);
assert(q.dequeue() == 5);
foreach (i, ref e; q)
{
assert(i != 0 || e == 4);
assert(i != 1 || e == 9);
}
assert(q.empty);
}

View File

@ -5,7 +5,7 @@
/**
* Arbitrary precision arithmetic.
*
* Copyright: Eugene Wissner 2016-2017.
* Copyright: Eugene Wissner 2016-2018.
* 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)

View File

@ -5,7 +5,7 @@
/**
* Number theory.
*
* Copyright: Eugene Wissner 2017.
* Copyright: Eugene Wissner 2017-2018.
* 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)

View File

@ -12,7 +12,7 @@
* be found in its submodules. $(D_PSYMBOL tanya.math) doesn't import any
* submodules publically, they should be imported explicitly.
*
* Copyright: Eugene Wissner 2016-2017.
* Copyright: Eugene Wissner 2016-2018.
* 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)

View File

@ -5,7 +5,7 @@
/**
* Random number generator.
*
* Copyright: Eugene Wissner 2016.
* Copyright: Eugene Wissner 2016-2018.
* 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)
@ -234,9 +234,12 @@ else version (SecureARC4Random)
else version (Windows)
{
import core.sys.windows.basetsd : ULONG_PTR;
import core.sys.windows.windef : BOOL, DWORD, PBYTE;
import core.sys.windows.winnt : LPCSTR, LPCWSTR;
import core.sys.windows.winbase : GetLastError;
import core.sys.windows.wincrypt;
import core.sys.windows.windef : BOOL, DWORD, PBYTE;
import core.sys.windows.winerror : NTE_BAD_KEYSET;
import core.sys.windows.winnt : LPCSTR, LPCWSTR;
private extern(Windows) @nogc nothrow
{
BOOL CryptGenRandom(HCRYPTPROV, DWORD, PBYTE);
@ -247,9 +250,6 @@ else version (Windows)
private bool initCryptGenRandom(scope ref HCRYPTPROV hProvider) @nogc nothrow @trusted
{
import core.sys.windows.winbase : GetLastError;
import core.sys.windows.winerror : NTE_BAD_KEYSET;
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa379886(v=vs.85).aspx
// For performance reasons, we recommend that you set the pszContainer
// parameter to NULL and the dwFlags parameter to CRYPT_VERIFYCONTEXT

View File

@ -8,7 +8,7 @@
* Allocators are classes encapsulating memory allocation strategy. This allows
* to decouple memory management from the algorithms and the data.
*
* Copyright: Eugene Wissner 2016-2017.
* Copyright: Eugene Wissner 2016-2018.
* 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)

View File

@ -5,7 +5,7 @@
/**
* Allocator based on $(D_PSYMBOL malloc), $(D_PSYMBOL realloc) and $(D_PSYMBOL free).
*
* Copyright: Eugene Wissner 2017.
* Copyright: Eugene Wissner 2017-2018.
* 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)

View File

@ -3,9 +3,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* Native allocator for Posix and Windows.
* Native allocator.
*
* Copyright: Eugene Wissner 2016-2017.
* Copyright: Eugene Wissner 2016-2018.
* 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)
@ -18,68 +18,41 @@ import std.algorithm.comparison;
import tanya.memory.allocator;
import tanya.memory.op;
version (Posix)
version (TanyaNative):
import core.sys.posix.sys.mman : MAP_ANON,
MAP_FAILED,
MAP_PRIVATE,
PROT_READ,
PROT_WRITE;
import core.sys.posix.unistd;
extern(C)
private void* mmap(void* addr,
size_t len,
int prot,
int flags,
int fd,
off_t offset) pure nothrow @system @nogc;
extern(C)
private int munmap(void* addr, size_t len) pure nothrow @system @nogc;
private void* mapMemory(const size_t len) pure nothrow @system @nogc
{
import core.sys.posix.sys.mman : MAP_ANON,
MAP_FAILED,
MAP_PRIVATE,
PROT_READ,
PROT_WRITE;
import core.sys.posix.unistd;
extern(C)
private void* mmap(void* addr,
size_t len,
int prot,
int flags,
int fd,
off_t offset) pure nothrow @system @nogc;
extern(C)
private int munmap(void* addr, size_t len) pure nothrow @system @nogc;
private void* mapMemory(const size_t len) pure nothrow @system @nogc
{
void* p = mmap(null,
len,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON,
-1,
0);
return p is MAP_FAILED ? null : p;
}
private bool unmapMemory(shared void* addr, const size_t len)
pure nothrow @system @nogc
{
return munmap(cast(void*) addr, len) == 0;
}
void* p = mmap(null,
len,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON,
-1,
0);
return p is MAP_FAILED ? null : p;
}
else version (Windows)
private bool unmapMemory(shared void* addr, const size_t len)
pure nothrow @system @nogc
{
import core.sys.windows.winbase : GetSystemInfo, SYSTEM_INFO;
extern(Windows)
private void* VirtualAlloc(void*, size_t, uint, uint)
pure nothrow @system @nogc;
extern(Windows)
private int VirtualFree(void* addr, size_t len, uint)
pure nothrow @system @nogc;
private void* mapMemory(const size_t len) pure nothrow @system @nogc
{
return VirtualAlloc(null,
len,
0x00001000, // MEM_COMMIT
0x04); // PAGE_READWRITE
}
private bool unmapMemory(shared void* addr, const size_t len)
pure nothrow @system @nogc
{
return VirtualFree(cast(void*) addr, 0, 0x8000) == 0;
}
return munmap(cast(void*) addr, len) == 0;
}
/*
@ -106,7 +79,6 @@ else version (Windows)
* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* </pre>
*/
deprecated("Use tanya.memory.mallocator instead")
final class MmapPool : Allocator
{
version (none)
@ -156,7 +128,7 @@ final class MmapPool : Allocator
return data is null ? null : data[0 .. size];
}
version (TanyaNative) @nogc nothrow pure unittest
@nogc nothrow pure unittest
{
auto p = MmapPool.instance.allocate(20);
assert(p);
@ -167,7 +139,7 @@ final class MmapPool : Allocator
}
// Issue 245: https://issues.caraus.io/issues/245.
version (TanyaNative) @nogc nothrow pure unittest
@nogc nothrow pure unittest
{
// allocate() check.
size_t tooMuchMemory = size_t.max
@ -299,7 +271,7 @@ final class MmapPool : Allocator
return true;
}
version (TanyaNative) @nogc nothrow pure unittest
@nogc nothrow pure unittest
{
auto p = MmapPool.instance.allocate(20);
@ -382,7 +354,7 @@ final class MmapPool : Allocator
return true;
}
version (TanyaNative) @nogc nothrow pure unittest
@nogc nothrow pure unittest
{
void[] p;
assert(!MmapPool.instance.reallocateInPlace(p, 5));
@ -447,7 +419,7 @@ final class MmapPool : Allocator
return true;
}
version (TanyaNative) @nogc nothrow pure unittest
@nogc nothrow pure unittest
{
void[] p;
MmapPool.instance.reallocate(p, 10 * int.sizeof);
@ -480,19 +452,10 @@ final class MmapPool : Allocator
if (instance_ is null)
{
// Get system dependend page size.
version (Posix)
size_t pageSize = sysconf(_SC_PAGE_SIZE);
if (pageSize < 65536)
{
size_t pageSize = sysconf(_SC_PAGE_SIZE);
if (pageSize < 65536)
{
pageSize = pageSize * 65536 / pageSize;
}
}
else version (Windows)
{
SYSTEM_INFO si;
GetSystemInfo(&si);
size_t pageSize = si.dwPageSize;
pageSize = pageSize * 65536 / pageSize;
}
const instanceSize = addAlignment(__traits(classInstanceSize,
@ -521,7 +484,7 @@ final class MmapPool : Allocator
return (cast(GetPureInstance!MmapPool) &instantiate)();
}
version (TanyaNative) @nogc nothrow pure unittest
@nogc nothrow pure unittest
{
assert(instance is instance);
}
@ -626,7 +589,7 @@ final class MmapPool : Allocator
return alignment_;
}
version (TanyaNative) @nogc nothrow pure unittest
@nogc nothrow pure unittest
{
assert(MmapPool.instance.alignment == MmapPool.alignment_);
}
@ -657,8 +620,6 @@ final class MmapPool : Allocator
private alias Block = shared BlockEntry*;
}
version (TanyaNative):
// A lot of allocations/deallocations, but it is the minimum caused a
// segmentation fault because MmapPool reallocateInPlace moves a block wrong.
@nogc nothrow pure unittest

View File

@ -5,7 +5,7 @@
/**
* Set of operations on memory blocks.
*
* Copyright: Eugene Wissner 2017.
* Copyright: Eugene Wissner 2017-2018.
* 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)

View File

@ -5,7 +5,7 @@
/**
* Dynamic memory management.
*
* Copyright: Eugene Wissner 2016-2017.
* Copyright: Eugene Wissner 2016-2018.
* 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)

View File

@ -14,7 +14,7 @@
* $(LI Unique ownership)
* )
*
* Copyright: Eugene Wissner 2016-2017.
* Copyright: Eugene Wissner 2016-2018.
* 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)

View File

@ -44,7 +44,7 @@ import tanya.meta.transform;
* See_Also: $(D_PSYMBOL isLess).
*/
template Min(alias pred, Args...)
if (Args.length > 0 && isTemplate!pred)
if (Args.length > 0 && __traits(isTemplate, pred))
{
static if (Args.length == 1)
{
@ -91,7 +91,7 @@ if (Args.length > 0 && isTemplate!pred)
* See_Also: $(D_PSYMBOL isLess).
*/
template Max(alias pred, Args...)
if (Args.length > 0 && isTemplate!pred)
if (Args.length > 0 && __traits(isTemplate, pred))
{
static if (Args.length == 1)
{
@ -148,7 +148,7 @@ if (Args.length > 0 && isTemplate!pred)
*/
template ZipWith(alias f, Tuples...)
if (Tuples.length > 0
&& isTemplate!f
&& __traits(isTemplate, f)
&& allSatisfy!(ApplyLeft!(isInstanceOf, Tuple), Tuples))
{
private template GetIth(size_t i, Args...)
@ -448,7 +448,7 @@ if (isInstanceOf!(Set, S1) && isInstanceOf!(Set, S2))
* to $(D_INLINECODE Args[1]), $(D_KEYWORD false) otherwise.
*/
template isLessEqual(alias cmp, Args...)
if (Args.length == 2 && isTemplate!cmp)
if (Args.length == 2 && __traits(isTemplate, cmp))
{
private enum result = cmp!(Args[1], Args[0]);
static if (is(typeof(result) == bool))
@ -495,7 +495,7 @@ if (Args.length == 2 && isTemplate!cmp)
* equal to $(D_INLINECODE Args[1]), $(D_KEYWORD false) otherwise.
*/
template isGreaterEqual(alias cmp, Args...)
if (Args.length == 2 && isTemplate!cmp)
if (Args.length == 2 && __traits(isTemplate, cmp))
{
private enum result = cmp!Args;
static if (is(typeof(result) == bool))
@ -542,7 +542,7 @@ if (Args.length == 2 && isTemplate!cmp)
* $(D_INLINECODE Args[1]), $(D_KEYWORD false) otherwise.
*/
template isLess(alias cmp, Args...)
if (Args.length == 2 && isTemplate!cmp)
if (Args.length == 2 && __traits(isTemplate, cmp))
{
private enum result = cmp!Args;
static if (is(typeof(result) == bool))
@ -589,7 +589,7 @@ if (Args.length == 2 && isTemplate!cmp)
* $(D_INLINECODE Args[1]), $(D_KEYWORD false) otherwise.
*/
template isGreater(alias cmp, Args...)
if (Args.length == 2 && isTemplate!cmp)
if (Args.length == 2 && __traits(isTemplate, cmp))
{
private enum result = cmp!Args;
static if (is(typeof(result) == bool))
@ -637,7 +637,7 @@ if (Args.length == 2)
{
static if ((is(typeof(Args[0] == Args[1])) && (Args[0] == Args[1]))
|| (isTypeTuple!Args && is(Args[0] == Args[1]))
|| isSame!Args)
|| __traits(isSame, Args[0], Args[1]))
{
enum bool isEqual = true;
}
@ -804,7 +804,7 @@ alias AliasSeq(Args...) = Args;
* $(D_PARAM F), $(D_KEYWORD false) otherwise.
*/
template allSatisfy(alias F, L...)
if (isTemplate!F)
if (__traits(isTemplate, F))
{
static if (L.length == 0)
{
@ -842,7 +842,7 @@ if (isTemplate!F)
* $(D_PARAM F), $(D_KEYWORD false) otherwise.
*/
template anySatisfy(alias F, L...)
if (isTemplate!F)
if (__traits(isTemplate, F))
{
static if (L.length == 0)
{
@ -945,6 +945,32 @@ template canFind(alias T, L...)
static assert(canFind!(3, () {}, uint, 5, 3));
}
/*
* Tests whether $(D_PARAM T) is a template.
*
* $(D_PSYMBOL isTemplate) isn't $(D_KEYWORD true) for template instances,
* since the latter already represent some type. Only not instantiated
* templates, i.e. that accept some template parameters, are considered
* templates.
*
* Params:
* T = A symbol.
*
* Returns: $(D_KEYWORD true) if $(D_PARAM T) is a template,
* $(D_KEYWORD false) otherwise.
*/
private enum bool isTemplate(alias T) = __traits(isTemplate, T);
///
@nogc nothrow pure @safe unittest
{
static struct S(T)
{
}
static assert(isTemplate!S);
static assert(!isTemplate!(S!int));
}
/**
* Combines multiple templates with logical AND. So $(D_PSYMBOL templateAnd)
* evaluates to $(D_INLINECODE Preds[0] && Preds[1] && Preds[2]) and so on.
@ -1049,7 +1075,7 @@ if (allSatisfy!(isTemplate, Preds))
* Returns: Negated $(D_PARAM pred).
*/
template templateNot(alias pred)
if (isTemplate!pred)
if (__traits(isTemplate, pred))
{
enum bool templateNot(T...) = !pred!T;
}
@ -1083,7 +1109,7 @@ if (isTemplate!pred)
* if not.
*/
template isSorted(alias cmp, L...)
if (isTemplate!cmp)
if (__traits(isTemplate, cmp))
{
static if (L.length <= 1)
{
@ -1359,7 +1385,7 @@ template Reverse(L...)
* Returns: Elements $(D_PARAM T) after applying $(D_PARAM F) to them.
*/
template Map(alias F, T...)
if (isTemplate!F)
if (__traits(isTemplate, F))
{
static if (T.length == 0)
{
@ -1401,7 +1427,7 @@ if (isTemplate!F)
* See_Also: $(LINK2 https://en.wikipedia.org/wiki/Merge_sort, Merge sort).
*/
template Sort(alias cmp, L...)
if (isTemplate!cmp)
if (__traits(isTemplate, cmp))
{
private template merge(size_t A, size_t B)
{

View File

@ -150,137 +150,7 @@ enum bool isComplex(T) = is(Unqual!(OriginalType!T) == cfloat)
static assert(!isComplex!real);
}
/**
* POD (Plain Old Data) is a $(D_KEYWORD struct) without constructors,
* destructors and member functions.
*
* Params:
* T = A type.
*
* Returns: $(D_KEYWORD true) if $(D_PARAM T) is a POD type,
* $(D_KEYWORD false) otherwise.
*/
deprecated("Use __traits(isPOD) instead")
enum bool isPOD(T) = __traits(isPOD, T);
///
@nogc nothrow pure @safe unittest
{
struct S1
{
void method()
{
}
}
static assert(!isPOD!S1);
struct S2
{
void function() val; // Function pointer, not a member function.
}
static assert(isPOD!S2);
struct S3
{
this(this)
{
}
}
static assert(!isPOD!S3);
}
/**
* Returns size of the type $(D_PARAM T).
*
* Params:
* T = A type.
*
* Returns: Size of the type $(D_PARAM T).
*/
deprecated("Use T.sizeof instead")
enum size_t sizeOf(T) = T.sizeof;
///
@nogc nothrow pure @safe unittest
{
static assert(sizeOf!(bool function()) == size_t.sizeof);
static assert(sizeOf!bool == 1);
static assert(sizeOf!short == 2);
static assert(sizeOf!int == 4);
static assert(sizeOf!long == 8);
static assert(sizeOf!(void[16]) == 16);
}
/**
* Returns the alignment of the type $(D_PARAM T).
*
* Params:
* T = A type.
*
* Returns: Alignment of the type $(D_PARAM T).
*/
deprecated("Use T.alignof instead")
enum size_t alignOf(T) = T.alignof;
///
@nogc nothrow pure @safe unittest
{
static assert(alignOf!bool == bool.alignof);
static assert(is(typeof(alignOf!bool) == typeof(bool.alignof)));
}
/**
* Tests whether $(D_INLINECODE Args[0]) and $(D_INLINECODE Args[1]) are the
* same symbol.
*
* Params:
* Args = Two symbols to be tested.
*
* Returns: $(D_KEYWORD true) if $(D_PARAM Args) are the same symbol,
* $(D_KEYWORD false) otherwise.
*/
deprecated("Use __traits(isSame) instead")
template isSame(Args...)
if (Args.length == 2)
{
enum bool isSame = __traits(isSame, Args[0], Args[1]);
}
///
@nogc nothrow pure @safe unittest
{
static assert(isSame!("string", "string"));
static assert(!isSame!(string, immutable(char)[]));
}
/**
* Tests whether $(D_PARAM T) is a template.
*
* $(D_PSYMBOL isTemplate) isn't $(D_KEYWORD true) for template instances,
* since the latter already represent some type. Only not instantiated
* templates, i.e. that accept some template parameters, are considered
* templates.
*
* Params:
* T = A symbol.
*
* Returns: $(D_KEYWORD true) if $(D_PARAM T) is a template,
* $(D_KEYWORD false) otherwise.
*/
deprecated("Use __traits(isTemplate) instead")
enum bool isTemplate(alias T) = __traits(isTemplate, T);
///
@nogc nothrow pure @safe unittest
{
static struct S(T)
{
}
static assert(isTemplate!S);
static assert(!isTemplate!(S!int));
}
/**
/*
* Tests whether $(D_PARAM T) is an interface.
*
* Params:
@ -289,44 +159,7 @@ enum bool isTemplate(alias T) = __traits(isTemplate, T);
* Returns: $(D_KEYWORD true) if $(D_PARAM T) is an interface,
* $(D_KEYWORD false) otherwise.
*/
deprecated("Use is(T == interface) instead")
enum bool isInterface(T) = is(T == interface);
/**
* Tests whether $(D_PARAM T) is a class.
*
* Params:
* T = A type.
*
* Returns: $(D_KEYWORD true) if $(D_PARAM T) is a class,
* $(D_KEYWORD false) otherwise.
*/
deprecated("Use is(T == class) instead")
enum bool isClass(T) = is(T == class);
/**
* Tests whether $(D_PARAM T) is a struct.
*
* Params:
* T = A type.
*
* Returns: $(D_KEYWORD true) if $(D_PARAM T) is a struct,
* $(D_KEYWORD false) otherwise.
*/
deprecated("Use is(T == struct) instead")
enum bool isStruct(T) = is(T == struct);
/**
* Tests whether $(D_PARAM T) is a enum.
*
* Params:
* T = A type.
*
* Returns: $(D_KEYWORD true) if $(D_PARAM T) is an enum,
* $(D_KEYWORD false) otherwise.
*/
deprecated("Use is(T == enum) instead")
enum bool isEnum(T) = is(T == enum);
private enum bool isInterface(T) = is(T == interface);
/**
* Determines whether $(D_PARAM T) is a polymorphic type, i.e. a
@ -2007,17 +1840,17 @@ alias TemplateOf(alias T : Base!Args, alias Base, Args...) = Base;
static struct S(T)
{
}
static assert(isSame!(TemplateOf!(S!int), S));
static assert(__traits(isSame, TemplateOf!(S!int), S));
static void func(T)()
{
}
static assert(isSame!(TemplateOf!(func!int), func));
static assert(__traits(isSame, TemplateOf!(func!int), func));
template T(U)
{
}
static assert(isSame!(TemplateOf!(T!int), T));
static assert(__traits(isSame, TemplateOf!(T!int), T));
}
/**
@ -2049,7 +1882,7 @@ template isInstanceOf(alias T, alias I)
{
static if (is(typeof(TemplateOf!I)))
{
enum bool isInstanceOf = isSame!(TemplateOf!I, T);
enum bool isInstanceOf = __traits(isSame, TemplateOf!I, T);
}
else
{

View File

@ -701,7 +701,7 @@ alias TypeOf(T) = T;
/// ditto
template TypeOf(alias T)
if (isExpressions!T || isTemplate!T)
if (isExpressions!T || __traits(isTemplate, T))
{
alias TypeOf = typeof(T);
}

View File

@ -5,7 +5,7 @@
/**
* Internet utilities.
*
* Copyright: Eugene Wissner 2016-2017.
* Copyright: Eugene Wissner 2016-2018.
* 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)
@ -170,7 +170,7 @@ struct NetworkOrder(uint L)
}
///
pure nothrow @safe @nogc unittest
@nogc nothrow pure @safe unittest
{
auto networkOrder = NetworkOrder!3(0xae34e2u);
assert(!networkOrder.empty);
@ -190,8 +190,8 @@ pure nothrow @safe @nogc unittest
assert(networkOrder.empty);
}
// Static.
private unittest
// Static tests
@nogc nothrow pure @safe unittest
{
static assert(isBidirectionalRange!(NetworkOrder!4));
static assert(isBidirectionalRange!(NetworkOrder!8));
@ -238,7 +238,7 @@ T toHostOrder(T = size_t, R)(R range)
}
///
pure nothrow @safe @nogc unittest
@nogc nothrow pure @safe unittest
{
const value = 0xae34e2u;
auto networkOrder = NetworkOrder!4(value);

View File

@ -5,7 +5,7 @@
/**
* Network programming.
*
* Copyright: Eugene Wissner 2017.
* Copyright: Eugene Wissner 2017-2018.
* 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)

View File

@ -5,7 +5,7 @@
/**
* URL parser.
*
* Copyright: Eugene Wissner 2017.
* Copyright: Eugene Wissner 2017-2018.
* 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)
@ -460,7 +460,6 @@ struct URL
assertThrown!URIException(() => URL("http://blah.com:66000"));
}
// Issue 254: https://issues.caraus.io/issues/254.
@nogc pure @system unittest
{
auto u = URL("ftp://");

View File

@ -31,7 +31,7 @@
* (D_INLINECODE dchar[])) are treated as any other normal array, they aren't
* auto-decoded.
*
* Copyright: Eugene Wissner 2017.
* Copyright: Eugene Wissner 2017-2018.
* 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)

View File

@ -6,7 +6,7 @@
* This package contains generic functions and templates to be used with D
* ranges.
*
* Copyright: Eugene Wissner 2017.
* Copyright: Eugene Wissner 2017-2018.
* 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)

View File

@ -5,7 +5,7 @@
/**
* This module defines primitives for working with ranges.
*
* Copyright: Eugene Wissner 2017.
* Copyright: Eugene Wissner 2017-2018.
* 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)
@ -1464,11 +1464,7 @@ if (isBidirectionalRange!R)
ElementType!R moveFront(R)(R range)
if (isInputRange!R)
{
static if (__traits(hasMember, R, "moveFront"))
{
return range.moveFront();
}
else static if (!hasElaborateCopyConstructor!(ElementType!R))
static if (!hasElaborateCopyConstructor!(ElementType!R))
{
return range.front;
}
@ -1485,48 +1481,24 @@ if (isInputRange!R)
///
@nogc nothrow pure @safe unittest
{
// Defines moveFront.
static struct R1
{
enum bool empty = false;
int moveFront() @nogc nothrow pure @safe
{
return 5;
}
alias front = moveFront;
void popFront() @nogc nothrow pure @safe
{
}
}
assert(moveFront(R1()) == 5);
// Has elements without a postblit constructor.
static struct R2
{
enum bool empty = false;
int[2] a = 5;
int front() const @nogc nothrow pure @safe
{
return 5;
}
void popFront() @nogc nothrow pure @safe
{
}
}
assert(moveFront(R2()) == 5);
assert(moveFront(a[]) == 5);
}
@nogc nothrow pure @safe unittest
{
static struct Element
{
this(this)
this(this) @nogc nothrow pure @safe
{
assert(false);
}
}
// Returns its elements by reference.
static struct R3
static struct R1
{
Element element;
enum bool empty = false;
@ -1540,10 +1512,10 @@ if (isInputRange!R)
{
}
}
static assert(is(typeof(moveFront(R3()))));
static assert(is(typeof(moveFront(R1()))));
// Returns elements with a postblit constructor by value. moveFront fails.
static struct R4
static struct R2
{
enum bool empty = false;
@ -1556,7 +1528,7 @@ if (isInputRange!R)
{
}
}
static assert(!is(typeof(moveFront(R4()))));
static assert(!is(typeof(moveFront(R2()))));
}
/**
@ -1577,11 +1549,7 @@ if (isInputRange!R)
ElementType!R moveBack(R)(R range)
if (isBidirectionalRange!R)
{
static if (__traits(hasMember, R, "moveBack"))
{
return range.moveBack();
}
else static if (!hasElaborateCopyConstructor!(ElementType!R))
static if (!hasElaborateCopyConstructor!(ElementType!R))
{
return range.back;
}
@ -1598,62 +1566,24 @@ if (isBidirectionalRange!R)
///
@nogc nothrow pure @safe unittest
{
// Defines moveBack.
static struct R1
{
enum bool empty = false;
int moveBack() @nogc nothrow pure @safe
{
return 5;
}
alias back = moveBack;
alias front = moveBack;
void popBack() @nogc nothrow pure @safe
{
}
alias popFront = popBack;
R1 save() @nogc nothrow pure @safe
{
return this;
}
}
assert(moveBack(R1()) == 5);
// Has elements without a postblit constructor.
static struct R2
{
enum bool empty = false;
int[2] a = 5;
int back() const @nogc nothrow pure @safe
{
return 5;
}
alias front = back;
void popBack() @nogc nothrow pure @safe
{
}
alias popFront = popBack;
R2 save() @nogc nothrow pure @safe
{
return this;
}
}
assert(moveBack(R2()) == 5);
assert(moveBack(a[]) == 5);
}
@nogc nothrow pure @safe unittest
{
static struct Element
{
this(this)
this(this) @nogc nothrow pure @safe
{
assert(false);
}
}
// Returns its elements by reference.
static struct R3
static struct R1
{
Element element;
enum bool empty = false;
@ -1669,15 +1599,15 @@ if (isBidirectionalRange!R)
}
alias popFront = popBack;
R3 save() @nogc nothrow pure @safe
R1 save() @nogc nothrow pure @safe
{
return this;
}
}
static assert(is(typeof(moveBack(R3()))));
static assert(is(typeof(moveBack(R1()))));
// Returns elements with a postblit constructor by value. moveBack fails.
static struct R4
static struct R2
{
enum bool empty = false;
@ -1692,12 +1622,12 @@ if (isBidirectionalRange!R)
}
alias popFront = popBack;
R4 save() @nogc nothrow pure @safe
R2 save() @nogc nothrow pure @safe
{
return this;
}
}
static assert(!is(typeof(moveBack(R4()))));
static assert(!is(typeof(moveBack(R2()))));
}
/**
@ -1717,11 +1647,7 @@ if (isBidirectionalRange!R)
ElementType!R moveAt(R)(R range, size_t n)
if (isRandomAccessRange!R)
{
static if (__traits(hasMember, R, "moveAt"))
{
return range.moveAt(n);
}
else static if (!hasElaborateCopyConstructor!(ElementType!R))
static if (!hasElaborateCopyConstructor!(ElementType!R))
{
return range[n];
}
@ -1731,65 +1657,31 @@ if (isRandomAccessRange!R)
}
else
{
static assert(false, "Back element cannot be moved");
static assert(false, "Random element cannot be moved");
}
}
///
@nogc nothrow pure @safe unittest
{
// Defines moveAt.
static struct R1
{
enum bool empty = false;
int front() @nogc nothrow pure @safe
{
return 5;
}
void popFront() @nogc nothrow pure @safe
{
}
int moveAt(size_t) @nogc nothrow pure @safe
{
return 5;
}
alias opIndex = moveAt;
}
assert(moveAt(R1(), 0) == 5);
// Has elements without a postblit constructor.
static struct R2
{
enum bool empty = false;
int[3] a = 5;
int front() const @nogc nothrow pure @safe
{
return 5;
}
void popFront() @nogc nothrow pure @safe
{
}
int opIndex(size_t) const @nogc nothrow pure @safe
{
return 5;
}
}
assert(moveAt(R2(), 0) == 5);
assert(moveAt(a[], 1) == 5);
}
@nogc nothrow pure @safe unittest
{
static struct Element
{
this(this)
this(this) @nogc nothrow pure @safe
{
assert(false);
}
}
// Returns its elements by reference.
static struct R3
static struct R1
{
Element element;
enum bool empty = false;
@ -1808,10 +1700,10 @@ if (isRandomAccessRange!R)
return element;
}
}
static assert(is(typeof(moveAt(R3(), 0))));
static assert(is(typeof(moveAt(R1(), 0))));
// Returns elements with a postblit constructor by value. moveAt fails.
static struct R4
static struct R2
{
enum bool empty = false;
@ -1829,7 +1721,7 @@ if (isRandomAccessRange!R)
return Element();
}
}
static assert(!is(typeof(moveAt(R4(), 0))));
static assert(!is(typeof(moveAt(R2(), 0))));
}
/**
@ -1871,32 +1763,20 @@ template hasMobileElements(R)
///
@nogc nothrow pure @safe unittest
{
// Input range with elements without a postblit constructor.
// These can be moved.
static struct InputRange
{
enum bool empty = false;
int front() @nogc nothrow pure @safe
{
return 5;
}
void popFront() @nogc nothrow pure @safe
{
}
}
static assert(hasMobileElements!InputRange);
static assert(hasMobileElements!(int[]));
}
///
@nogc nothrow pure @safe unittest
{
static struct Element
{
this(this)
this(this) @nogc nothrow pure @safe
{
}
}
// Bidirectional range, whose elements cannot be moved. The range defines
// only moveFront, but not moveBack. So it doesn't have mobile elements.
static struct BidirectionalRange
static struct R1
{
enum bool empty = false;
@ -1904,44 +1784,28 @@ template hasMobileElements(R)
{
return Element();
}
alias back = front;
alias moveFront = front;
void popFront() @nogc nothrow pure @safe
{
}
alias popBack = popFront;
BidirectionalRange save() @nogc nothrow pure @safe
{
return this;
}
}
static assert(!hasMobileElements!BidirectionalRange);
static assert(!hasMobileElements!R1);
// Access-random range, whose elements cannot be moved, but the range
// defines both, moveFront and moveAt.
static struct RandomAccessRange
static struct R2
{
enum bool empty = false;
private Element front_;
Element front() @nogc nothrow pure @safe
ref Element front() @nogc nothrow pure @safe
{
return Element();
return front_;
}
alias moveFront = front;
void popFront() @nogc nothrow pure @safe
{
}
Element opIndex(size_t) @nogc nothrow pure @safe
{
return Element();
}
alias moveAt = opIndex;
}
static assert(hasMobileElements!RandomAccessRange);
static assert(hasMobileElements!R2);
}
/**