Fix #4
This commit is contained in:
parent
1450a6adfe
commit
a7206cbd02
@ -12,11 +12,11 @@
|
||||
*/
|
||||
module tanya.container.entry;
|
||||
|
||||
package struct Entry(T)
|
||||
package struct SEntry(T)
|
||||
{
|
||||
/// Item content.
|
||||
T content;
|
||||
|
||||
/// Next item.
|
||||
Entry* next;
|
||||
SEntry* next;
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ struct SList(T)
|
||||
*/
|
||||
void insertFront(ref T x)
|
||||
{
|
||||
auto temp = allocator.make!(Entry!T);
|
||||
auto temp = allocator.make!(SEntry!T);
|
||||
|
||||
temp.content = x;
|
||||
temp.next = first.next;
|
||||
@ -233,7 +233,7 @@ struct SList(T)
|
||||
}
|
||||
|
||||
/// 0th element of the list.
|
||||
private Entry!T first;
|
||||
private SEntry!T first;
|
||||
|
||||
mixin DefaultAllocator;
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ struct Queue(T)
|
||||
size_t length() const
|
||||
{
|
||||
size_t len;
|
||||
for (const(Entry!T)* i = first; i !is null; i = i.next)
|
||||
for (const(SEntry!T)* i = first; i !is null; i = i.next)
|
||||
{
|
||||
++len;
|
||||
}
|
||||
@ -72,7 +72,7 @@ struct Queue(T)
|
||||
assert(q.length == 0);
|
||||
}
|
||||
|
||||
private void enqueueEntry(ref Entry!T* entry)
|
||||
private void enqueueEntry(ref SEntry!T* entry)
|
||||
{
|
||||
if (empty)
|
||||
{
|
||||
@ -85,9 +85,9 @@ struct Queue(T)
|
||||
}
|
||||
}
|
||||
|
||||
private Entry!T* allocateEntry()
|
||||
private SEntry!T* allocateEntry()
|
||||
{
|
||||
auto temp = cast(Entry!T*) allocator.allocate(Entry!T.sizeof);
|
||||
auto temp = cast(SEntry!T*) allocator.allocate(SEntry!T.sizeof);
|
||||
if (temp is null)
|
||||
{
|
||||
onOutOfMemoryError();
|
||||
@ -107,7 +107,7 @@ struct Queue(T)
|
||||
{
|
||||
auto temp = allocateEntry();
|
||||
|
||||
*temp = Entry!T.init;
|
||||
*temp = SEntry!T.init;
|
||||
temp.content = x;
|
||||
|
||||
enqueueEntry(temp);
|
||||
@ -256,8 +256,8 @@ struct Queue(T)
|
||||
assert(q.empty);
|
||||
}
|
||||
|
||||
private Entry!T* first;
|
||||
private Entry!T* rear;
|
||||
private SEntry!T* first;
|
||||
private SEntry!T* rear;
|
||||
|
||||
mixin DefaultAllocator;
|
||||
}
|
||||
|
@ -169,10 +169,10 @@ struct Vector(T)
|
||||
* to generate a list.
|
||||
* allocator = Allocator.
|
||||
*/
|
||||
this(size_t R)(in T[R] init, shared Allocator allocator = defaultAllocator)
|
||||
this(size_t R)(T[R] init, shared Allocator allocator = defaultAllocator)
|
||||
{
|
||||
this(allocator);
|
||||
insertBack(init);
|
||||
insertBack!(T[])(init[]);
|
||||
}
|
||||
|
||||
/// Ditto.
|
||||
@ -229,12 +229,7 @@ struct Vector(T)
|
||||
{
|
||||
// Move each element.
|
||||
reserve(init.length);
|
||||
|
||||
const T* end = vector + init.length;
|
||||
for (T* src = init.vector, dest = vector; dest != end; ++src, ++dest)
|
||||
{
|
||||
moveEmplace(*src, *dest);
|
||||
}
|
||||
moveEmplaceAll(init.vector[0 .. init.length_], vector[0 .. init.length_]);
|
||||
length_ = init.length;
|
||||
// Destructor of init should destroy it here.
|
||||
}
|
||||
@ -335,21 +330,21 @@ struct Vector(T)
|
||||
/**
|
||||
* Destroys this $(D_PSYMBOL Vector).
|
||||
*/
|
||||
~this()
|
||||
~this() @trusted
|
||||
{
|
||||
length = 0;
|
||||
shrink(0);
|
||||
clear();
|
||||
allocator.deallocate(vector[0 .. capacity_]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the vector.
|
||||
*/
|
||||
this(this) @trusted
|
||||
this(this)
|
||||
{
|
||||
auto buf = vector;
|
||||
immutable oldLen = length_;
|
||||
auto buf = opIndex();
|
||||
length_ = capacity_ = 0;
|
||||
insertBack(buf[0 .. oldLen]);
|
||||
vector = null;
|
||||
insertBack(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -357,7 +352,7 @@ struct Vector(T)
|
||||
*/
|
||||
void clear()
|
||||
{
|
||||
length_ = 0;
|
||||
length = 0;
|
||||
}
|
||||
|
||||
///
|
||||
@ -399,11 +394,11 @@ struct Vector(T)
|
||||
*/
|
||||
@property void length(in size_t len) @trusted
|
||||
{
|
||||
if (len == length_)
|
||||
if (len == length)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (len > length_)
|
||||
else if (len > length)
|
||||
{
|
||||
reserve(len);
|
||||
initializeAll(vector[length_ .. len]);
|
||||
@ -597,70 +592,71 @@ struct Vector(T)
|
||||
Range!T remove(Range!T r) @trusted
|
||||
in
|
||||
{
|
||||
assert(r.begin >= vector && r.end <= vector + length_);
|
||||
assert(r.begin >= vector);
|
||||
assert(r.end <= vector + length_);
|
||||
}
|
||||
body
|
||||
{
|
||||
const T* end = vector + length_;
|
||||
T* a = r.begin;
|
||||
for (T* b = r.end; b != end; ++a, ++b)
|
||||
{
|
||||
*a = *b;
|
||||
}
|
||||
for (; a != end; ++a)
|
||||
{
|
||||
static if (hasElaborateDestructor!T)
|
||||
{
|
||||
destroy(*a);
|
||||
}
|
||||
--length_;
|
||||
}
|
||||
auto end = vector + length_;
|
||||
moveAll(Range!T(r.end, end), Range!T(r.begin, end));
|
||||
length = length - r.length;
|
||||
return r;
|
||||
}
|
||||
|
||||
///
|
||||
unittest
|
||||
@safe @nogc unittest
|
||||
{
|
||||
auto v = Vector!int([5, 18, 17, 2, 4, 6, 1]);
|
||||
|
||||
v.remove(v[1..3]);
|
||||
assert(v == Vector!int([5, 2, 4, 6, 1]));
|
||||
assert(v.remove(v[1 .. 3]).length == 2);
|
||||
assert(v[0] == 5 && v[1] == 2 && v[2] == 4 && v[3] == 6 && v[4] == 1);
|
||||
assert(v.length == 5);
|
||||
|
||||
v.remove(v[4..4]);
|
||||
assert(v == Vector!int([5, 2, 4, 6, 1]));
|
||||
assert(v.remove(v[4 .. 4]).length == 0);
|
||||
assert(v[0] == 5 && v[1] == 2 && v[2] == 4 && v[3] == 6 && v[4] == 1);
|
||||
assert(v.length == 5);
|
||||
|
||||
v.remove(v[4..5]);
|
||||
assert(v == Vector!int([5, 2, 4, 6]));
|
||||
assert(v.remove(v[4 .. 5]).length == 1);
|
||||
assert(v[0] == 5 && v[1] == 2 && v[2] == 4 && v[3] == 6);
|
||||
assert(v.length == 4);
|
||||
|
||||
v.remove(v[]);
|
||||
assert(v.remove(v[]).length == 4);
|
||||
assert(v.empty);
|
||||
|
||||
v.remove(v[]);
|
||||
assert(v.remove(v[]).length == 0);
|
||||
assert(v.empty);
|
||||
}
|
||||
|
||||
private void moveBack(R)(ref R el) @trusted
|
||||
if (isImplicitlyConvertible!(R, T))
|
||||
{
|
||||
reserve(length + 1);
|
||||
moveEmplace(el, *(vector + length_));
|
||||
++length_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the $(D_PARAM el) into the vector.
|
||||
*
|
||||
* Params:
|
||||
* R = Parameter type (single value, range or static array).
|
||||
* el = Values should be inserted.
|
||||
* R = Type of the inserted value(s) (single value, range or static array).
|
||||
* el = Value(s) should be inserted.
|
||||
*
|
||||
* Returns: The number of elements inserted.
|
||||
*/
|
||||
size_t insertBack(R)(auto ref R el) @trusted
|
||||
if (isImplicitlyConvertible!(R, T))
|
||||
{
|
||||
reserve(length_ + 1);
|
||||
static if (__traits(isRef, el))
|
||||
{
|
||||
reserve(length + 1);
|
||||
emplace(vector + length_, el);
|
||||
++length_;
|
||||
}
|
||||
else
|
||||
{
|
||||
moveEmplace(el, *(vector + length_));
|
||||
moveBack(el);
|
||||
}
|
||||
++length_;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -672,7 +668,7 @@ struct Vector(T)
|
||||
{
|
||||
static if (hasLength!R)
|
||||
{
|
||||
reserve(length_ + el.length);
|
||||
reserve(length + el.length);
|
||||
}
|
||||
size_t retLength;
|
||||
foreach (e; el)
|
||||
@ -683,14 +679,9 @@ struct Vector(T)
|
||||
}
|
||||
|
||||
/// Ditto.
|
||||
size_t insertBack(size_t R)(in T[R] el)
|
||||
size_t insertBack(size_t R)(T[R] el)
|
||||
{
|
||||
reserve(length_ + el.length);
|
||||
foreach (e; el)
|
||||
{
|
||||
insertBack(e);
|
||||
}
|
||||
return el.length;
|
||||
return insertBack!(T[])(el[]);
|
||||
}
|
||||
|
||||
/// Ditto.
|
||||
@ -731,13 +722,191 @@ struct Vector(T)
|
||||
assert(v1.capacity == 4);
|
||||
assert(v1[0] == 5 && v1[1] == 6 && v1[2] == 4 && v1[3] == 2);
|
||||
|
||||
auto v2 = Vector!int([34, 234]);
|
||||
assert(v1.insertBack(v2[]) == 2);
|
||||
assert(v1.insertBack([34, 234]) == 2);
|
||||
assert(v1.length == 6);
|
||||
assert(v1.capacity == 6);
|
||||
assert(v1[4] == 34 && v1[5] == 234);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts $(D_PARAM el) before or after $(D_PARAM r).
|
||||
*
|
||||
* Params:
|
||||
* R = Type of the inserted value(s) (single value, range or static array).
|
||||
* r = Range originally obtained from this vector.
|
||||
* el = Value(s) should be inserted.
|
||||
*
|
||||
* Returns: The number of elements inserted.
|
||||
*/
|
||||
size_t insertAfter(R)(Range!T r, R el)
|
||||
if (!isInfinite!R
|
||||
&& isInputRange!R
|
||||
&& isImplicitlyConvertible!(ElementType!R, T))
|
||||
in
|
||||
{
|
||||
assert(r.begin >= vector);
|
||||
assert(r.end <= vector + length_);
|
||||
}
|
||||
body
|
||||
{
|
||||
immutable oldLen = length;
|
||||
immutable offset = r.end - vector;
|
||||
immutable inserted = insertBack(el);
|
||||
bringToFront(vector[offset .. oldLen], vector[oldLen .. length]);
|
||||
return inserted;
|
||||
}
|
||||
|
||||
/// Ditto.
|
||||
size_t insertAfter(size_t R)(Range!T r, T[R] el)
|
||||
{
|
||||
return insertAfter!(T[])(r, el[]);
|
||||
}
|
||||
|
||||
/// Ditto.
|
||||
size_t insertAfter(R)(Range!T r, auto ref R el)
|
||||
if (isImplicitlyConvertible!(R, T))
|
||||
in
|
||||
{
|
||||
assert(r.begin >= vector);
|
||||
assert(r.end <= vector + length_);
|
||||
}
|
||||
body
|
||||
{
|
||||
immutable oldLen = length;
|
||||
immutable offset = r.end - vector;
|
||||
|
||||
static if (__traits(isRef, el))
|
||||
{
|
||||
insertBack(el);
|
||||
}
|
||||
else
|
||||
{
|
||||
moveBack(el);
|
||||
}
|
||||
bringToFront(vector[offset .. oldLen], vector[oldLen .. length_]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// Ditto.
|
||||
size_t insertBefore(R)(Range!T r, R el)
|
||||
if (!isInfinite!R
|
||||
&& isInputRange!R
|
||||
&& isImplicitlyConvertible!(ElementType!R, T))
|
||||
in
|
||||
{
|
||||
assert(r.begin >= vector);
|
||||
assert(r.end <= vector + length_);
|
||||
}
|
||||
body
|
||||
{
|
||||
return insertAfter(Range!T(vector, r.begin), el);
|
||||
}
|
||||
|
||||
/// Ditto.
|
||||
size_t insertBefore(size_t R)(Range!T r, T[R] el)
|
||||
{
|
||||
return insertBefore!(T[])(r, el[]);
|
||||
}
|
||||
|
||||
/// Ditto.
|
||||
size_t insertBefore(R)(Range!T r, auto ref R el)
|
||||
if (isImplicitlyConvertible!(R, T))
|
||||
in
|
||||
{
|
||||
assert(r.begin >= vector);
|
||||
assert(r.end <= vector + length_);
|
||||
}
|
||||
body
|
||||
{
|
||||
immutable oldLen = length;
|
||||
immutable offset = r.begin - vector;
|
||||
|
||||
static if (__traits(isRef, el))
|
||||
{
|
||||
insertBack(el);
|
||||
}
|
||||
else
|
||||
{
|
||||
moveBack(el);
|
||||
}
|
||||
bringToFront(vector[offset .. oldLen], vector[oldLen .. length_]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
///
|
||||
unittest
|
||||
{
|
||||
Vector!int v1;
|
||||
v1.insertAfter(v1[], [2, 8]);
|
||||
assert(v1[0] == 2);
|
||||
assert(v1[1] == 8);
|
||||
assert(v1.length == 2);
|
||||
|
||||
v1.insertAfter(v1[], [1, 2]);
|
||||
assert(v1[0] == 2);
|
||||
assert(v1[1] == 8);
|
||||
assert(v1[2] == 1);
|
||||
assert(v1[3] == 2);
|
||||
assert(v1.length == 4);
|
||||
|
||||
v1.insertAfter(v1[0 .. 0], [1, 2]);
|
||||
assert(v1[0] == 1);
|
||||
assert(v1[1] == 2);
|
||||
assert(v1[2] == 2);
|
||||
assert(v1[3] == 8);
|
||||
assert(v1[4] == 1);
|
||||
assert(v1[5] == 2);
|
||||
assert(v1.length == 6);
|
||||
|
||||
v1.insertAfter(v1[0 .. 4], 9);
|
||||
assert(v1[0] == 1);
|
||||
assert(v1[1] == 2);
|
||||
assert(v1[2] == 2);
|
||||
assert(v1[3] == 8);
|
||||
assert(v1[4] == 9);
|
||||
assert(v1[5] == 1);
|
||||
assert(v1[6] == 2);
|
||||
assert(v1.length == 7);
|
||||
}
|
||||
|
||||
///
|
||||
unittest
|
||||
{
|
||||
Vector!int v1;
|
||||
v1.insertBefore(v1[], [2, 8]);
|
||||
assert(v1[0] == 2);
|
||||
assert(v1[1] == 8);
|
||||
assert(v1.length == 2);
|
||||
|
||||
v1.insertBefore(v1[], [1, 2]);
|
||||
assert(v1[0] == 1);
|
||||
assert(v1[1] == 2);
|
||||
assert(v1[2] == 2);
|
||||
assert(v1[3] == 8);
|
||||
assert(v1.length == 4);
|
||||
|
||||
v1.insertBefore(v1[0 .. 1], [1, 2]);
|
||||
assert(v1[0] == 1);
|
||||
assert(v1[1] == 2);
|
||||
assert(v1[2] == 1);
|
||||
assert(v1[3] == 2);
|
||||
assert(v1[4] == 2);
|
||||
assert(v1[5] == 8);
|
||||
assert(v1.length == 6);
|
||||
|
||||
v1.insertBefore(v1[2 .. $], 9);
|
||||
assert(v1[0] == 1);
|
||||
assert(v1[1] == 2);
|
||||
assert(v1[2] == 9);
|
||||
assert(v1[3] == 1);
|
||||
assert(v1[4] == 2);
|
||||
assert(v1[5] == 2);
|
||||
assert(v1[6] == 8);
|
||||
assert(v1.length == 7);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns a value to the element with the index $(D_PARAM pos).
|
||||
*
|
||||
@ -841,13 +1010,13 @@ struct Vector(T)
|
||||
* Returns: Random access range that iterates over elements of the vector, in
|
||||
* forward order.
|
||||
*/
|
||||
Range!T opIndex()
|
||||
Range!T opIndex() @trusted
|
||||
{
|
||||
return typeof(return)(vector, vector + length_);
|
||||
}
|
||||
|
||||
/// Ditto.
|
||||
Range!(const T) opIndex() const
|
||||
Range!(const T) opIndex() const @trusted
|
||||
{
|
||||
return typeof(return)(vector, vector + length_);
|
||||
}
|
||||
@ -874,15 +1043,15 @@ struct Vector(T)
|
||||
* Returns: $(D_KEYWORD true) if the vectors are equal, $(D_KEYWORD false)
|
||||
* otherwise.
|
||||
*/
|
||||
bool opEquals()(auto ref typeof(this) v)
|
||||
bool opEquals()(auto ref typeof(this) v) @trusted
|
||||
{
|
||||
return equal(opIndex(), v[]);
|
||||
return equal(vector[0 .. length_], v.vector[0 .. v.length_]);
|
||||
}
|
||||
|
||||
/// Ditto.
|
||||
bool opEquals()(in auto ref typeof(this) v) const
|
||||
bool opEquals()(in auto ref typeof(this) v) const @trusted
|
||||
{
|
||||
return equal(opIndex(), v[]);
|
||||
return equal(vector[0 .. length_], v.vector[0 .. length_]);
|
||||
}
|
||||
|
||||
/// Ditto.
|
||||
@ -1185,8 +1354,9 @@ struct Vector(T)
|
||||
* Precondition: $(D_INLINECODE i <= j && j <= length
|
||||
* && value.length == j - i)
|
||||
*/
|
||||
Range!T opSliceAssign(R)(R value, in size_t i, in size_t j)
|
||||
if (!isInfinite!R && isInputRange!R
|
||||
Range!T opSliceAssign(R)(R value, in size_t i, in size_t j) @trusted
|
||||
if (!isInfinite!R
|
||||
&& isInputRange!R
|
||||
&& isImplicitlyConvertible!(ElementType!R, T))
|
||||
in
|
||||
{
|
||||
@ -1196,7 +1366,7 @@ struct Vector(T)
|
||||
}
|
||||
body
|
||||
{
|
||||
copy(value, opSlice(i, j));
|
||||
copy(value, vector[i .. j]);
|
||||
return opSlice(i, j);
|
||||
}
|
||||
|
||||
@ -1207,7 +1377,7 @@ struct Vector(T)
|
||||
}
|
||||
|
||||
/// Ditto.
|
||||
Range!T opSliceAssign(ref T value, in size_t i, in size_t j)
|
||||
Range!T opSliceAssign(ref T value, in size_t i, in size_t j) @trusted
|
||||
in
|
||||
{
|
||||
assert(i <= j);
|
||||
@ -1215,7 +1385,7 @@ struct Vector(T)
|
||||
}
|
||||
body
|
||||
{
|
||||
fill(opSlice(i, j), value);
|
||||
fill(vector[i .. j], value);
|
||||
return opSlice(i, j);
|
||||
}
|
||||
|
||||
@ -1392,3 +1562,12 @@ unittest
|
||||
}
|
||||
auto v = Vector!SWithDtor(); // Destructor can destroy empty vectors.
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
class A
|
||||
{
|
||||
}
|
||||
A a1, a2;
|
||||
auto v1 = Vector!A([a1, a2]);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user