10 Commits

Author SHA1 Message Date
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
22 changed files with 371 additions and 491 deletions

View File

@ -7,12 +7,11 @@ os:
language: d language: d
d: d:
- dmd-2.079.0 - dmd-2.079.1
- dmd-2.078.3 - dmd-2.078.3
- dmd-2.077.1 - dmd-2.077.1
- dmd-2.076.1
env: env:
matrix: matrix:
- ARCH=x86_64 - ARCH=x86_64
- ARCH=x86 - ARCH=x86
@ -23,12 +22,17 @@ addons:
- gcc-multilib - gcc-multilib
before_script: before_script:
- if [ "$PS1" = '(dmd-2.079.0)' ]; then - if [ "`$DC --version | head -n 1 | grep 'v2.079.1'`" ]; then
export UNITTEST="unittest-cov"; export UNITTEST="unittest-cov";
fi fi
script: script:
- dub test -b ${UNITTEST:-unittest} --arch=$ARCH --compiler=$DC - 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: 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 | | DMD | GCC |
|:-------:|:---------:| |:-------:|:---------:|
| 2.079.0 | *master* | | 2.079.1 | *master* |
| 2.078.3 | | | 2.078.3 | |
| 2.077.1 | | | 2.077.1 | |
| 2.076.1 | |
### Current status ### Current status

View File

@ -4,10 +4,10 @@ os: Visual Studio 2015
environment: environment:
matrix: matrix:
- DC: dmd - DC: dmd
DVersion: 2.079.0 DVersion: 2.079.1
arch: x64 arch: x64
- DC: dmd - DC: dmd
DVersion: 2.079.0 DVersion: 2.079.1
arch: x86 arch: x86
- DC: dmd - DC: dmd
DVersion: 2.078.3 DVersion: 2.078.3
@ -21,12 +21,6 @@ environment:
- DC: dmd - DC: dmd
DVersion: 2.077.1 DVersion: 2.077.1
arch: x86 arch: x86
- DC: dmd
DVersion: 2.076.1
arch: x64
- DC: dmd
DVersion: 2.076.1
arch: x86
skip_tags: true 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 v1 = Array!int([1, 2, 3]);
auto v2 = Array!int(v1); auto v2 = Array!int(v1);
@ -291,19 +291,6 @@ struct Array(T)
assert(v3.capacity == 3); 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). * 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]); 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); auto v = Array!int(3, 5);
@ -358,11 +345,6 @@ struct Array(T)
assert(v[0] == 5 && v[1] == 5 && v[2] == 5); assert(v[0] == 5 && v[1] == 5 && v[2] == 5);
} }
@safe unittest
{
auto v1 = Array!int(defaultAllocator);
}
/** /**
* Destroys this $(D_PSYMBOL Array). * 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]); auto v = Array!int([18, 20, 15]);
v.clear(); v.clear();
@ -409,7 +391,7 @@ struct Array(T)
} }
/// ///
@safe @nogc unittest @nogc nothrow pure @safe unittest
{ {
auto v = Array!int(4); auto v = Array!int(4);
assert(v.capacity == 4); assert(v.capacity == 4);
@ -461,7 +443,7 @@ struct Array(T)
} }
/// ///
unittest @nogc nothrow pure @safe unittest
{ {
Array!int v; Array!int v;
@ -529,7 +511,7 @@ struct Array(T)
} }
/// ///
@nogc @safe unittest @nogc nothrow pure @safe unittest
{ {
Array!int v; Array!int v;
assert(v.capacity == 0); assert(v.capacity == 0);
@ -564,7 +546,7 @@ struct Array(T)
} }
/// ///
@nogc @safe unittest @nogc nothrow pure @safe unittest
{ {
Array!int v; Array!int v;
assert(v.capacity == 0); assert(v.capacity == 0);
@ -629,7 +611,7 @@ struct Array(T)
} }
/// ///
unittest @nogc nothrow pure @safe unittest
{ {
auto v = Array!int([5, 18, 17]); 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]); auto v = Array!int([5, 18, 17, 2, 4, 6, 1]);
@ -759,7 +741,7 @@ struct Array(T)
alias insert = insertBack; alias insert = insertBack;
/// ///
unittest @nogc nothrow pure @safe unittest
{ {
struct TestRange struct TestRange
{ {
@ -927,7 +909,7 @@ struct Array(T)
} }
/// ///
unittest @nogc nothrow pure unittest
{ {
Array!int v1; Array!int v1;
v1.insertAfter(v1[], [2, 8]); v1.insertAfter(v1[], [2, 8]);
@ -963,7 +945,7 @@ struct Array(T)
} }
/// ///
unittest @nogc nothrow pure unittest
{ {
Array!int v1; Array!int v1;
v1.insertBefore(v1[], [2, 8]); 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); Array!int a = Array!int(1);
a[0] = 5; a[0] = 5;
@ -1052,7 +1034,7 @@ struct Array(T)
} }
/// ///
@nogc unittest @nogc nothrow pure @safe unittest
{ {
auto v1 = Array!int([12, 1, 7]); 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]); 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; Array!int v1, v2;
assert(v1 == v2); assert(v1 == v2);
@ -1191,7 +1173,7 @@ struct Array(T)
} }
/// ///
@safe unittest @nogc nothrow pure @safe unittest
{ {
auto v = Array!int([5]); auto v = Array!int([5]);
@ -1218,7 +1200,7 @@ struct Array(T)
} }
/// ///
unittest @nogc nothrow pure @safe unittest
{ {
auto v = Array!int([5]); auto v = Array!int([5]);
@ -1263,16 +1245,7 @@ struct Array(T)
} }
/// ///
unittest @nogc nothrow pure @safe unittest
{
Array!int v;
auto r = v[];
assert(r.length == 0);
assert(r.empty);
}
///
unittest
{ {
auto v = Array!int([1, 2, 3]); auto v = Array!int([1, 2, 3]);
auto r = v[]; 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 v = Array!int([1, 2, 3, 4]);
auto r = v[1 .. 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 v1 = Array!int([3, 3, 3]);
auto v2 = Array!int([1, 2]); 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 v = Array!int([1, 2, 4]);
auto data = v.get(); 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]); auto v1 = const Array!int([5, 15, 8]);
Array!int v2; Array!int v2;
@ -1472,22 +1445,6 @@ struct Array(T)
assert(v1 == v2); 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. * 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]); auto v1 = Array!int([5, 15, 8]);
Array!int v2; Array!int v2;
@ -1516,7 +1473,7 @@ struct Array(T)
} }
/// ///
unittest @nogc nothrow pure @safe unittest
{ {
auto v = Array!int([5, 15, 8]); auto v = Array!int([5, 15, 8]);
@ -1530,7 +1487,7 @@ unittest
assert(r.front == v.front); assert(r.front == v.front);
} }
@nogc unittest @nogc nothrow pure @safe unittest
{ {
const v1 = Array!int(); const v1 = Array!int();
const Array!int v2; const Array!int v2;
@ -1538,7 +1495,7 @@ unittest
static assert(is(PointerTarget!(typeof(v3.data)) == const(int))); static assert(is(PointerTarget!(typeof(v3.data)) == const(int)));
} }
@nogc unittest @nogc nothrow pure @safe unittest
{ {
// Test that const arrays return usable ranges. // Test that const arrays return usable ranges.
auto v = const Array!int([1, 2, 4]); auto v = const Array!int([1, 2, 4]);
@ -1559,7 +1516,7 @@ unittest
static assert(is(typeof(r2[]))); static assert(is(typeof(r2[])));
} }
@nogc unittest @nogc nothrow pure @safe unittest
{ {
Array!int v1; Array!int v1;
const Array!int v2; const Array!int v2;
@ -1581,18 +1538,18 @@ unittest
assert(!v1[].equal(v2[])); assert(!v1[].equal(v2[]));
} }
@nogc unittest @nogc nothrow pure @safe unittest
{ {
struct MutableEqualsStruct struct MutableEqualsStruct
{ {
int opEquals(typeof(this) that) @nogc int opEquals(typeof(this) that) @nogc nothrow pure @safe
{ {
return true; return true;
} }
} }
struct ConstEqualsStruct struct ConstEqualsStruct
{ {
int opEquals(const typeof(this) that) const @nogc int opEquals(const typeof(this) that) const @nogc nothrow pure @safe
{ {
return true; return true;
} }
@ -1619,18 +1576,18 @@ unittest
assert(v7[].equal(v8[])); assert(v7[].equal(v8[]));
} }
@nogc unittest @nogc nothrow pure @safe unittest
{ {
struct SWithDtor struct SWithDtor
{ {
~this() @nogc ~this() @nogc nothrow pure @safe
{ {
} }
} }
auto v = Array!SWithDtor(); // Destructor can destroy empty arrays. auto v = Array!SWithDtor(); // Destructor can destroy empty arrays.
} }
private unittest @nogc nothrow pure @safe unittest
{ {
class A class A
{ {
@ -1642,7 +1599,7 @@ private unittest
static assert(is(Array!(A*))); static assert(is(Array!(A*)));
} }
private @safe @nogc unittest @nogc nothrow pure @safe unittest
{ {
auto v = Array!int([5, 15, 8]); auto v = Array!int([5, 15, 8]);
{ {
@ -1670,3 +1627,45 @@ private @safe @nogc unittest
assert(i == 0); 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; ReadBuffer!ubyte b;
assert(b.capacity == 0); assert(b.capacity == 0);
@ -165,7 +165,7 @@ struct ReadBuffer(T = ubyte)
} }
/// ///
unittest @nogc nothrow pure unittest
{ {
ReadBuffer!ubyte b; ReadBuffer!ubyte b;
size_t numberRead; size_t numberRead;
@ -197,7 +197,7 @@ struct ReadBuffer(T = ubyte)
} }
/// ///
unittest @nogc nothrow pure unittest
{ {
ReadBuffer!ubyte b; ReadBuffer!ubyte b;
size_t numberRead; size_t numberRead;
@ -272,7 +272,7 @@ struct ReadBuffer(T = ubyte)
} }
/// ///
unittest @nogc nothrow pure unittest
{ {
ReadBuffer!ubyte b; ReadBuffer!ubyte b;
size_t numberRead; size_t numberRead;
@ -293,7 +293,7 @@ struct ReadBuffer(T = ubyte)
mixin DefaultAllocator; mixin DefaultAllocator;
} }
private unittest @nogc nothrow pure @safe unittest
{ {
static assert(is(ReadBuffer!int)); static assert(is(ReadBuffer!int));
} }
@ -399,7 +399,7 @@ struct WriteBuffer(T = ubyte)
alias opDollar = length; alias opDollar = length;
/// ///
unittest @nogc nothrow pure unittest
{ {
auto b = WriteBuffer!ubyte(4); auto b = WriteBuffer!ubyte(4);
ubyte[3] buf = [48, 23, 255]; ubyte[3] buf = [48, 23, 255];
@ -498,42 +498,6 @@ struct WriteBuffer(T = ubyte)
return this; 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 * Sets how many bytes were written. It will shrink the buffer
* appropriately. Always call it after $(D_PSYMBOL opIndex). * 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); auto b = WriteBuffer!ubyte(6);
ubyte[6] buf = [23, 23, 255, 128, 127, 9]; 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); auto b = WriteBuffer!ubyte(6);
ubyte[6] buf = [23, 23, 255, 128, 127, 9]; ubyte[6] buf = [23, 23, 255, 128, 127, 9];
@ -686,7 +650,41 @@ struct WriteBuffer(T = ubyte)
mixin DefaultAllocator; mixin DefaultAllocator;
} }
private unittest @nogc nothrow pure @safe unittest
{ {
static assert(is(typeof(WriteBuffer!int(5)))); 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. * init = Initial value to fill the list with.
* allocator = Allocator. * 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); this(allocator);
if (len == 0) if (len == 0)
@ -181,7 +182,7 @@ struct SList(T)
} }
/// ditto /// ditto
this(const size_t len, shared Allocator allocator = defaultAllocator) this(size_t len, shared Allocator allocator = defaultAllocator)
{ {
this(len, T.init, allocator); this(len, T.init, allocator);
} }
@ -436,13 +437,13 @@ struct SList(T)
version (assert) version (assert)
{ {
private bool checkRangeBelonging(ref Range r) const private bool checkRangeBelonging(ref const Range r) const
{ {
const(Entry*)* pos = &this.head; const(Entry)* pos = this.head;
for (; pos != r.head && *pos !is null; pos = &(*pos).next) for (; pos !is *r.head && pos !is null; pos = pos.next)
{ {
} }
return pos == r.head; return pos is *r.head;
} }
} }
@ -560,28 +561,12 @@ struct SList(T)
assert(l1 == l2); assert(l1 == l2);
} }
/** deprecated
* Returns: How many elements are in the list.
*/
@property size_t length() const @property size_t length() const
{ {
return count(this[]); 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. * Comparison for equality.
* *
@ -672,7 +657,7 @@ struct SList(T)
* *
* Returns: The number of elements removed. * Returns: The number of elements removed.
*/ */
size_t removeFront(const size_t howMany) size_t removeFront(size_t howMany)
out (removed) out (removed)
{ {
assert(removed <= howMany); assert(removed <= howMany);
@ -735,6 +720,50 @@ struct SList(T)
assert(l1 == l2); 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 * Returns: Range that iterates over all elements of the container, in
* forward order. * forward order.
@ -941,6 +970,7 @@ struct DRange(L)
invariant invariant
{ {
assert(this.head !is null); assert(this.head !is null);
assert(this.tail !is null);
} }
private this(ref EntryPointer head, ref EntryPointer tail) @trusted private this(ref EntryPointer head, ref EntryPointer tail) @trusted
@ -1096,7 +1126,8 @@ struct DList(T)
* init = Initial value to fill the list with. * init = Initial value to fill the list with.
* allocator = Allocator. * 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); this(allocator);
if (len == 0) if (len == 0)
@ -1124,7 +1155,7 @@ struct DList(T)
} }
/// ditto /// ditto
this(const size_t len, shared Allocator allocator = defaultAllocator) this(size_t len, shared Allocator allocator = defaultAllocator)
{ {
this(len, T.init, allocator); this(len, T.init, allocator);
} }
@ -1573,13 +1604,13 @@ struct DList(T)
version (assert) version (assert)
{ {
private bool checkRangeBelonging(ref Range r) const private bool checkRangeBelonging(ref const Range r) const
{ {
const(Entry*)* pos = &this.head; const(Entry)* pos = this.head;
for (; pos != r.head && *pos !is null; pos = &(*pos).next) for (; pos !is *r.head && pos !is null; pos = pos.next)
{ {
} }
return pos == r.head; return pos is *r.head;
} }
} }
@ -1815,28 +1846,12 @@ struct DList(T)
return insertAfter!(T[])(r, el[]); return insertAfter!(T[])(r, el[]);
} }
/** deprecated
* Returns: How many elements are in the list.
*/
@property size_t length() const @property size_t length() const
{ {
return count(this[]); 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. * Comparison for equality.
* *
@ -1897,7 +1912,7 @@ struct DList(T)
{ {
auto n = this.head.next; auto n = this.head.next;
this.allocator_.dispose(this.head); allocator.dispose(this.head);
this.head = n; this.head = n;
if (this.head is null) if (this.head is null)
{ {
@ -1970,7 +1985,7 @@ struct DList(T)
* *
* Returns: The number of elements removed. * Returns: The number of elements removed.
*/ */
size_t removeFront(const size_t howMany) size_t removeFront(size_t howMany)
out (removed) out (removed)
{ {
assert(removed <= howMany); assert(removed <= howMany);
@ -1997,7 +2012,7 @@ struct DList(T)
} }
/// ditto /// ditto
size_t removeBack(const size_t howMany) size_t removeBack(size_t howMany)
out (removed) out (removed)
{ {
assert(removed <= howMany); assert(removed <= howMany);
@ -2057,11 +2072,7 @@ struct DList(T)
while (e !is *tailNext) while (e !is *tailNext)
{ {
auto next = e.next; auto next = e.next;
/* Workaround for dmd 2.076.1 bug on OSX. Invariants fail when allocator.dispose(e);
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);
e = next; e = next;
} }
@ -2101,6 +2112,57 @@ struct DList(T)
assert(l1 == l2); 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 * Returns: Range that iterates over all elements of the container, in
* forward order. * forward order.

View File

@ -5,7 +5,7 @@
/** /**
* Arbitrary precision arithmetic. * Arbitrary precision arithmetic.
* *
* Copyright: Eugene Wissner 2016-2017. * Copyright: Eugene Wissner 2016-2018.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)

View File

@ -5,7 +5,7 @@
/** /**
* Number theory. * Number theory.
* *
* Copyright: Eugene Wissner 2017. * Copyright: Eugene Wissner 2017-2018.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * 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 * be found in its submodules. $(D_PSYMBOL tanya.math) doesn't import any
* submodules publically, they should be imported explicitly. * 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/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)

View File

@ -5,7 +5,7 @@
/** /**
* Random number generator. * Random number generator.
* *
* Copyright: Eugene Wissner 2016. * Copyright: Eugene Wissner 2016-2018.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
@ -234,9 +234,12 @@ else version (SecureARC4Random)
else version (Windows) else version (Windows)
{ {
import core.sys.windows.basetsd : ULONG_PTR; import core.sys.windows.basetsd : ULONG_PTR;
import core.sys.windows.windef : BOOL, DWORD, PBYTE; import core.sys.windows.winbase : GetLastError;
import core.sys.windows.winnt : LPCSTR, LPCWSTR;
import core.sys.windows.wincrypt; 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 private extern(Windows) @nogc nothrow
{ {
BOOL CryptGenRandom(HCRYPTPROV, DWORD, PBYTE); BOOL CryptGenRandom(HCRYPTPROV, DWORD, PBYTE);
@ -247,9 +250,6 @@ else version (Windows)
private bool initCryptGenRandom(scope ref HCRYPTPROV hProvider) @nogc nothrow @trusted 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 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa379886(v=vs.85).aspx
// For performance reasons, we recommend that you set the pszContainer // For performance reasons, we recommend that you set the pszContainer
// parameter to NULL and the dwFlags parameter to CRYPT_VERIFYCONTEXT // 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 * Allocators are classes encapsulating memory allocation strategy. This allows
* to decouple memory management from the algorithms and the data. * 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/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * 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). * 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/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * 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/. */ * 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/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
@ -18,68 +18,41 @@ import std.algorithm.comparison;
import tanya.memory.allocator; import tanya.memory.allocator;
import tanya.memory.op; 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, void* p = mmap(null,
MAP_FAILED, len,
MAP_PRIVATE, PROT_READ | PROT_WRITE,
PROT_READ, MAP_PRIVATE | MAP_ANON,
PROT_WRITE; -1,
import core.sys.posix.unistd; 0);
return p is MAP_FAILED ? null : p;
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;
}
} }
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; return munmap(cast(void*) addr, len) == 0;
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;
}
} }
/* /*
@ -106,7 +79,6 @@ else version (Windows)
* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* </pre> * </pre>
*/ */
deprecated("Use tanya.memory.mallocator instead")
final class MmapPool : Allocator final class MmapPool : Allocator
{ {
version (none) version (none)
@ -156,7 +128,7 @@ final class MmapPool : Allocator
return data is null ? null : data[0 .. size]; return data is null ? null : data[0 .. size];
} }
version (TanyaNative) @nogc nothrow pure unittest @nogc nothrow pure unittest
{ {
auto p = MmapPool.instance.allocate(20); auto p = MmapPool.instance.allocate(20);
assert(p); assert(p);
@ -167,7 +139,7 @@ final class MmapPool : Allocator
} }
// Issue 245: https://issues.caraus.io/issues/245. // Issue 245: https://issues.caraus.io/issues/245.
version (TanyaNative) @nogc nothrow pure unittest @nogc nothrow pure unittest
{ {
// allocate() check. // allocate() check.
size_t tooMuchMemory = size_t.max size_t tooMuchMemory = size_t.max
@ -299,7 +271,7 @@ final class MmapPool : Allocator
return true; return true;
} }
version (TanyaNative) @nogc nothrow pure unittest @nogc nothrow pure unittest
{ {
auto p = MmapPool.instance.allocate(20); auto p = MmapPool.instance.allocate(20);
@ -382,7 +354,7 @@ final class MmapPool : Allocator
return true; return true;
} }
version (TanyaNative) @nogc nothrow pure unittest @nogc nothrow pure unittest
{ {
void[] p; void[] p;
assert(!MmapPool.instance.reallocateInPlace(p, 5)); assert(!MmapPool.instance.reallocateInPlace(p, 5));
@ -447,7 +419,7 @@ final class MmapPool : Allocator
return true; return true;
} }
version (TanyaNative) @nogc nothrow pure unittest @nogc nothrow pure unittest
{ {
void[] p; void[] p;
MmapPool.instance.reallocate(p, 10 * int.sizeof); MmapPool.instance.reallocate(p, 10 * int.sizeof);
@ -480,19 +452,10 @@ final class MmapPool : Allocator
if (instance_ is null) if (instance_ is null)
{ {
// Get system dependend page size. // Get system dependend page size.
version (Posix) size_t pageSize = sysconf(_SC_PAGE_SIZE);
if (pageSize < 65536)
{ {
size_t pageSize = sysconf(_SC_PAGE_SIZE); pageSize = pageSize * 65536 / pageSize;
if (pageSize < 65536)
{
pageSize = pageSize * 65536 / pageSize;
}
}
else version (Windows)
{
SYSTEM_INFO si;
GetSystemInfo(&si);
size_t pageSize = si.dwPageSize;
} }
const instanceSize = addAlignment(__traits(classInstanceSize, const instanceSize = addAlignment(__traits(classInstanceSize,
@ -521,7 +484,7 @@ final class MmapPool : Allocator
return (cast(GetPureInstance!MmapPool) &instantiate)(); return (cast(GetPureInstance!MmapPool) &instantiate)();
} }
version (TanyaNative) @nogc nothrow pure unittest @nogc nothrow pure unittest
{ {
assert(instance is instance); assert(instance is instance);
} }
@ -626,7 +589,7 @@ final class MmapPool : Allocator
return alignment_; return alignment_;
} }
version (TanyaNative) @nogc nothrow pure unittest @nogc nothrow pure unittest
{ {
assert(MmapPool.instance.alignment == MmapPool.alignment_); assert(MmapPool.instance.alignment == MmapPool.alignment_);
} }
@ -657,8 +620,6 @@ final class MmapPool : Allocator
private alias Block = shared BlockEntry*; private alias Block = shared BlockEntry*;
} }
version (TanyaNative):
// A lot of allocations/deallocations, but it is the minimum caused a // A lot of allocations/deallocations, but it is the minimum caused a
// segmentation fault because MmapPool reallocateInPlace moves a block wrong. // segmentation fault because MmapPool reallocateInPlace moves a block wrong.
@nogc nothrow pure unittest @nogc nothrow pure unittest

View File

@ -5,7 +5,7 @@
/** /**
* Set of operations on memory blocks. * 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/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)

View File

@ -5,7 +5,7 @@
/** /**
* Dynamic memory management. * Dynamic memory management.
* *
* Copyright: Eugene Wissner 2016-2017. * Copyright: Eugene Wissner 2016-2018.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)

View File

@ -14,7 +14,7 @@
* $(LI Unique ownership) * $(LI Unique ownership)
* ) * )
* *
* Copyright: Eugene Wissner 2016-2017. * Copyright: Eugene Wissner 2016-2018.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)

View File

@ -5,7 +5,7 @@
/** /**
* Internet utilities. * Internet utilities.
* *
* Copyright: Eugene Wissner 2016-2017. * Copyright: Eugene Wissner 2016-2018.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * 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); auto networkOrder = NetworkOrder!3(0xae34e2u);
assert(!networkOrder.empty); assert(!networkOrder.empty);
@ -190,8 +190,8 @@ pure nothrow @safe @nogc unittest
assert(networkOrder.empty); assert(networkOrder.empty);
} }
// Static. // Static tests
private unittest @nogc nothrow pure @safe unittest
{ {
static assert(isBidirectionalRange!(NetworkOrder!4)); static assert(isBidirectionalRange!(NetworkOrder!4));
static assert(isBidirectionalRange!(NetworkOrder!8)); 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; const value = 0xae34e2u;
auto networkOrder = NetworkOrder!4(value); auto networkOrder = NetworkOrder!4(value);

View File

@ -5,7 +5,7 @@
/** /**
* Network programming. * Network programming.
* *
* Copyright: Eugene Wissner 2017. * Copyright: Eugene Wissner 2017-2018.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)

View File

@ -5,7 +5,7 @@
/** /**
* URL parser. * URL parser.
* *
* Copyright: Eugene Wissner 2017. * Copyright: Eugene Wissner 2017-2018.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
@ -460,7 +460,6 @@ struct URL
assertThrown!URIException(() => URL("http://blah.com:66000")); assertThrown!URIException(() => URL("http://blah.com:66000"));
} }
// Issue 254: https://issues.caraus.io/issues/254.
@nogc pure @system unittest @nogc pure @system unittest
{ {
auto u = URL("ftp://"); auto u = URL("ftp://");

View File

@ -31,7 +31,7 @@
* (D_INLINECODE dchar[])) are treated as any other normal array, they aren't * (D_INLINECODE dchar[])) are treated as any other normal array, they aren't
* auto-decoded. * auto-decoded.
* *
* Copyright: Eugene Wissner 2017. * Copyright: Eugene Wissner 2017-2018.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * 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 * This package contains generic functions and templates to be used with D
* ranges. * ranges.
* *
* Copyright: Eugene Wissner 2017. * Copyright: Eugene Wissner 2017-2018.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)

View File

@ -5,7 +5,7 @@
/** /**
* This module defines primitives for working with ranges. * 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/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
@ -1464,11 +1464,7 @@ if (isBidirectionalRange!R)
ElementType!R moveFront(R)(R range) ElementType!R moveFront(R)(R range)
if (isInputRange!R) if (isInputRange!R)
{ {
static if (__traits(hasMember, R, "moveFront")) static if (!hasElaborateCopyConstructor!(ElementType!R))
{
return range.moveFront();
}
else static if (!hasElaborateCopyConstructor!(ElementType!R))
{ {
return range.front; return range.front;
} }
@ -1485,48 +1481,24 @@ if (isInputRange!R)
/// ///
@nogc nothrow pure @safe unittest @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. // Has elements without a postblit constructor.
static struct R2 int[2] a = 5;
{
enum bool empty = false;
int front() const @nogc nothrow pure @safe assert(moveFront(a[]) == 5);
{ }
return 5;
}
void popFront() @nogc nothrow pure @safe
{
}
}
assert(moveFront(R2()) == 5);
@nogc nothrow pure @safe unittest
{
static struct Element static struct Element
{ {
this(this) this(this) @nogc nothrow pure @safe
{ {
assert(false); assert(false);
} }
} }
// Returns its elements by reference. // Returns its elements by reference.
static struct R3 static struct R1
{ {
Element element; Element element;
enum bool empty = false; 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. // Returns elements with a postblit constructor by value. moveFront fails.
static struct R4 static struct R2
{ {
enum bool empty = false; 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) ElementType!R moveBack(R)(R range)
if (isBidirectionalRange!R) if (isBidirectionalRange!R)
{ {
static if (__traits(hasMember, R, "moveBack")) static if (!hasElaborateCopyConstructor!(ElementType!R))
{
return range.moveBack();
}
else static if (!hasElaborateCopyConstructor!(ElementType!R))
{ {
return range.back; return range.back;
} }
@ -1598,62 +1566,24 @@ if (isBidirectionalRange!R)
/// ///
@nogc nothrow pure @safe unittest @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. // Has elements without a postblit constructor.
static struct R2 int[2] a = 5;
{
enum bool empty = false;
int back() const @nogc nothrow pure @safe assert(moveBack(a[]) == 5);
{ }
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);
@nogc nothrow pure @safe unittest
{
static struct Element static struct Element
{ {
this(this) this(this) @nogc nothrow pure @safe
{ {
assert(false); assert(false);
} }
} }
// Returns its elements by reference. // Returns its elements by reference.
static struct R3 static struct R1
{ {
Element element; Element element;
enum bool empty = false; enum bool empty = false;
@ -1669,15 +1599,15 @@ if (isBidirectionalRange!R)
} }
alias popFront = popBack; alias popFront = popBack;
R3 save() @nogc nothrow pure @safe R1 save() @nogc nothrow pure @safe
{ {
return this; return this;
} }
} }
static assert(is(typeof(moveBack(R3())))); static assert(is(typeof(moveBack(R1()))));
// Returns elements with a postblit constructor by value. moveBack fails. // Returns elements with a postblit constructor by value. moveBack fails.
static struct R4 static struct R2
{ {
enum bool empty = false; enum bool empty = false;
@ -1692,12 +1622,12 @@ if (isBidirectionalRange!R)
} }
alias popFront = popBack; alias popFront = popBack;
R4 save() @nogc nothrow pure @safe R2 save() @nogc nothrow pure @safe
{ {
return this; 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) ElementType!R moveAt(R)(R range, size_t n)
if (isRandomAccessRange!R) if (isRandomAccessRange!R)
{ {
static if (__traits(hasMember, R, "moveAt")) static if (!hasElaborateCopyConstructor!(ElementType!R))
{
return range.moveAt(n);
}
else static if (!hasElaborateCopyConstructor!(ElementType!R))
{ {
return range[n]; return range[n];
} }
@ -1731,65 +1657,31 @@ if (isRandomAccessRange!R)
} }
else else
{ {
static assert(false, "Back element cannot be moved"); static assert(false, "Random element cannot be moved");
} }
} }
/// ///
@nogc nothrow pure @safe unittest @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. // Has elements without a postblit constructor.
static struct R2 int[3] a = 5;
{
enum bool empty = false;
int front() const @nogc nothrow pure @safe assert(moveAt(a[], 1) == 5);
{ }
return 5;
}
void popFront() @nogc nothrow pure @safe
{
}
int opIndex(size_t) const @nogc nothrow pure @safe
{
return 5;
}
}
assert(moveAt(R2(), 0) == 5);
@nogc nothrow pure @safe unittest
{
static struct Element static struct Element
{ {
this(this) this(this) @nogc nothrow pure @safe
{ {
assert(false); assert(false);
} }
} }
// Returns its elements by reference. // Returns its elements by reference.
static struct R3 static struct R1
{ {
Element element; Element element;
enum bool empty = false; enum bool empty = false;
@ -1808,10 +1700,10 @@ if (isRandomAccessRange!R)
return element; 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. // Returns elements with a postblit constructor by value. moveAt fails.
static struct R4 static struct R2
{ {
enum bool empty = false; enum bool empty = false;
@ -1829,7 +1721,7 @@ if (isRandomAccessRange!R)
return Element(); 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 @nogc nothrow pure @safe unittest
{ {
// Input range with elements without a postblit constructor. static assert(hasMobileElements!(int[]));
// 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);
///
@nogc nothrow pure @safe unittest
{
static struct Element 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 R1
static struct BidirectionalRange
{ {
enum bool empty = false; enum bool empty = false;
@ -1904,44 +1784,28 @@ template hasMobileElements(R)
{ {
return Element(); return Element();
} }
alias back = front;
alias moveFront = front;
void popFront() @nogc nothrow pure @safe 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 static struct R2
// defines both, moveFront and moveAt.
static struct RandomAccessRange
{ {
enum bool empty = false; 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 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);
} }
/** /**