Implement opApply for the Queue

This commit is contained in:
Eugen Wissner 2016-12-02 17:31:57 +01:00
parent c53d319337
commit 1123d01e6c
3 changed files with 143 additions and 67 deletions

View File

@ -111,7 +111,7 @@ class SList(T)
/** /**
* Returns: $(D_KEYWORD true) if the list is empty. * Returns: $(D_KEYWORD true) if the list is empty.
*/ */
@property bool empty() const @property bool empty() inout const
{ {
return first.next is null; return first.next is null;
} }

View File

@ -6,7 +6,7 @@
* Copyright: Eugene Wissner 2016. * Copyright: Eugene Wissner 2016.
* 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:belka@caraus.de, Eugene Wissner)
*/ */
module tanya.container.queue; module tanya.container.queue;
@ -37,19 +37,38 @@ class Queue(T)
*/ */
~this() ~this()
{ {
foreach (e; this) clear();
}
/**
* Removes all elements from the queue.
*/
void clear()
{
while (!empty)
{ {
static if (isFinalizable!T) popFront();
{
dispose(allocator, e);
}
} }
} }
///
unittest
{
auto q = theAllocator.make!(Queue!int);
assert(q.empty);
q.insertBack(8);
q.insertBack(9);
q.clear();
assert(q.empty);
theAllocator.dispose(q);
}
/** /**
* Returns: First element. * Returns: First element.
*/ */
@property ref T front() @property ref inout(T) front() inout
in in
{ {
assert(!empty); assert(!empty);
@ -64,10 +83,8 @@ class Queue(T)
* *
* Params: * Params:
* x = New element. * x = New element.
*
* Returns: $(D_KEYWORD this).
*/ */
typeof(this) insertBack(T x) void insertBack(T x)
{ {
Entry* temp = make!Entry(allocator); Entry* temp = make!Entry(allocator);
@ -82,52 +99,21 @@ class Queue(T)
rear.next = temp; rear.next = temp;
rear = rear.next; rear = rear.next;
} }
return this;
} }
/// Ditto.
alias insert = insertBack; alias insert = insertBack;
/// ///
unittest unittest
{ {
auto q = make!(Queue!int)(theAllocator); auto q = make!(Queue!int)(theAllocator);
int[2] values = [8, 9];
q.insertBack(values[0]);
assert(q.front is values[0]);
q.insertBack(values[1]);
assert(q.front is values[0]);
dispose(theAllocator, q);
}
/**
* Inserts a new element.
*
* Params:
* x = New element.
*
* Returns: $(D_KEYWORD this).
*/
typeof(this) opOpAssign(string Op)(ref T x)
if (Op == "~")
{
return insertBack(x);
}
///
unittest
{
auto q = make!(Queue!int)(theAllocator);
int value = 5;
assert(q.empty); assert(q.empty);
q.insertBack(8);
q ~= value; assert(q.front == 8);
q.insertBack(9);
assert(q.front == value); assert(q.front == 8);
assert(!q.empty);
dispose(theAllocator, q); dispose(theAllocator, q);
} }
@ -135,7 +121,7 @@ class Queue(T)
/** /**
* Returns: $(D_KEYWORD true) if the queue is empty. * Returns: $(D_KEYWORD true) if the queue is empty.
*/ */
@property bool empty() const @safe pure nothrow @property bool empty() inout const
{ {
return first.next is null; return first.next is null;
} }
@ -154,11 +140,9 @@ class Queue(T)
} }
/** /**
* Move position to the next element. * Move the position to the next element.
*
* Returns: $(D_KEYWORD this).
*/ */
typeof(this) popFront() void popFront()
in in
{ {
assert(!empty); assert(!empty);
@ -169,21 +153,91 @@ class Queue(T)
dispose(allocator, first.next); dispose(allocator, first.next);
first.next = n; first.next = n;
return this;
} }
/// ///
unittest unittest
{ {
auto q = make!(Queue!int)(theAllocator); auto q = make!(Queue!int)(theAllocator);
int[2] values = [8, 9];
q.insertBack(values[0]); q.insertBack(8);
q.insertBack(values[1]); q.insertBack(9);
assert(q.front is values[0]); assert(q.front == 8);
q.popFront(); q.popFront();
assert(q.front is values[1]); assert(q.front == 9);
dispose(theAllocator, q);
}
/**
* $(D_KEYWORD foreach) iteration.
*
* Params:
* dg = $(D_KEYWORD foreach) body.
*/
int opApply(scope int delegate(ref size_t i, ref T) dg)
{
int result;
for (size_t i = 0; !empty; ++i)
{
if ((result = dg(i, front)) != 0)
{
return result;
}
popFront();
}
return result;
}
/// Ditto.
int opApply(scope int delegate(ref T) dg)
{
int result;
while (!empty)
{
if ((result = dg(front)) != 0)
{
return result;
}
popFront();
}
return result;
}
///
unittest
{
auto q = theAllocator.make!(Queue!int);
size_t j;
q.insertBack(5);
q.insertBack(4);
q.insertBack(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.insertBack(5);
q.insertBack(4);
q.insertBack(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);
dispose(theAllocator, q); dispose(theAllocator, q);
} }
@ -206,13 +260,33 @@ class Queue(T)
/// The last element of the list. /// The last element of the list.
protected Entry* rear; protected Entry* rear;
private IAllocator allocator; /// The allocator.
protected IAllocator allocator;
} }
/// ///
unittest unittest
{ {
auto q = make!(Queue!int)(theAllocator); auto q = theAllocator.make!(Queue!int);
dispose(theAllocator, q); q.insertBack(5);
assert(!q.empty);
q.insertBack(4);
assert(q.front == 5);
q.insertBack(9);
assert(q.front == 5);
q.popFront();
assert(q.front == 4);
foreach (i, ref e; q)
{
assert(i != 0 || e == 4);
assert(i != 1 || e == 9);
}
assert(q.empty);
theAllocator.dispose(q);
} }

View File

@ -55,12 +55,12 @@ class Vector(T)
return this; return this;
} }
@property bool empty() const @property bool empty() inout const
{ {
return start >= end; return start >= end;
} }
@property size_t length() const @property size_t length() inout const
{ {
return end - start; return end - start;
} }
@ -261,13 +261,13 @@ class Vector(T)
/** /**
* Returns: Vector length. * Returns: Vector length.
*/ */
@property size_t length() const @property size_t length() inout const
{ {
return vector.length; return vector.length;
} }
/// Ditto. /// Ditto.
size_t opDollar() const size_t opDollar() inout const
{ {
return length; return length;
} }
@ -301,7 +301,7 @@ class Vector(T)
/** /**
* Returns: $(D_KEYWORD true) if the vector is empty. * Returns: $(D_KEYWORD true) if the vector is empty.
*/ */
@property bool empty() const @property bool empty() inout const
{ {
return vector.length == 0; return vector.length == 0;
} }
@ -776,4 +776,6 @@ unittest
assert(v.front == 5); assert(v.front == 5);
assert(v[1] == 15); assert(v[1] == 15);
assert(v.back == 8); assert(v.back == 8);
theAllocator.dispose(v);
} }