Add length and opCmp to the Queue

This commit is contained in:
2016-12-19 16:33:16 +01:00
parent 40857e69b7
commit f1bc4dc2e2
8 changed files with 248 additions and 121 deletions

View File

@ -6,32 +6,22 @@
* Copyright: Eugene Wissner 2016.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:belka@caraus.de, Eugene Wissner)
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
*/
module tanya.container.queue;
import tanya.container.entry;
import std.traits;
import tanya.memory;
/**
* Queue.
* FIFO queue.
*
* Params:
* T = Content type.
*/
struct Queue(T)
{
/**
* Creates a new $(D_PSYMBOL Queue).
*
* Params:
* allocator = The allocator should be used for the element
* allocations.
*/
this(shared Allocator allocator)
{
this.allocator = allocator;
}
/**
* Removes all elements from the queue.
*/
@ -54,15 +44,147 @@ struct Queue(T)
///
unittest
{
auto q = defaultAllocator.make!(Queue!int);
Queue!int q;
assert(q.empty);
q.insertBack(8);
q.insertBack(9);
q.clear();
assert(q.empty);
}
defaultAllocator.dispose(q);
/**
* 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(Entry!T)* i = first.next; i !is null; i = i.next)
{
++len;
}
return len;
}
///
unittest
{
Queue!int q;
assert(q.length == 0);
q.insertBack(5);
assert(q.length == 1);
q.insertBack(4);
assert(q.length == 2);
q.insertBack(9);
assert(q.length == 3);
q.popFront();
assert(q.length == 2);
q.popFront();
assert(q.length == 1);
q.popFront();
assert(q.length == 0);
}
version (D_Ddoc)
{
/**
* Compares two queues. Checks if all elements of the both queues are equal.
*
* Returns: Whether $(D_KEYWORD this) and $(D_PARAM that) are equal.
*/
int opEquals(ref typeof(this) that);
/// Ditto.
int opEquals(typeof(this) that);
}
else static if (!hasMember!(T, "opEquals")
|| (functionAttributes!(T.opEquals) & FunctionAttribute.const_))
{
bool opEquals(in ref typeof(this) that) const
{
const(Entry!T)* i = first.next;
const(Entry!T)* j = that.first.next;
while (i !is null && j !is null)
{
if (i.content != j.content)
{
return false;
}
i = i.next;
j = j.next;
}
return i is null && j is null;
}
/// Ditto.
bool opEquals(in typeof(this) that) const
{
return opEquals(that);
}
}
else
{
/**
* Compares two queues. Checks if all elements of the both queues are equal.
*
* Returns: How many elements are in the queue.
*/
bool opEquals(ref typeof(this) that)
{
Entry!T* i = first.next;
Entry!T* j = that.first.next;
while (i !is null && j !is null)
{
if (i.content != j.content)
{
return false;
}
i = i.next;
j = j.next;
}
return i is null && j is null;
}
/// Ditto.
bool opEquals(typeof(this) that)
{
return opEquals(that);
}
}
///
unittest
{
Queue!int q1, q2;
q1.insertBack(5);
q1.insertBack(4);
q2.insertBack(5);
assert(q1 != q2);
q2.insertBack(4);
assert(q1 == q2);
q2.popFront();
assert(q1 != q2);
q1.popFront();
assert(q1 == q2);
q1.popFront();
q2.popFront();
assert(q1 == q2);
}
private unittest
{
static assert(is(Queue!ConstEqualsStruct));
static assert(is(Queue!MutableEqualsStruct));
static assert(is(Queue!NoEqualsStruct));
}
/**
@ -84,13 +206,9 @@ struct Queue(T)
* Params:
* x = New element.
*/
void insertBack(T x)
void insertBack(ref T x)
{
if (allocator is null)
{
allocator = defaultAllocator;
}
Entry* temp = make!Entry(allocator);
auto temp = allocator.make!(Entry!T);
temp.content = x;
@ -105,27 +223,31 @@ struct Queue(T)
}
}
/// Ditto.
void insertBack(T x)
{
insertBack(x);
}
/// Ditto.
alias insert = insertBack;
///
unittest
{
auto q = make!(Queue!int)(defaultAllocator);
Queue!int q;
assert(q.empty);
q.insertBack(8);
assert(q.front == 8);
q.insertBack(9);
assert(q.front == 8);
dispose(defaultAllocator, q);
}
/**
* Returns: $(D_KEYWORD true) if the queue is empty.
*/
@property bool empty() inout const pure nothrow @safe
@property bool empty() const
{
return first.next is null;
}
@ -133,14 +255,12 @@ struct Queue(T)
///
unittest
{
auto q = make!(Queue!int)(defaultAllocator);
Queue!int q;
int value = 7;
assert(q.empty);
q.insertBack(value);
assert(!q.empty);
dispose(defaultAllocator, q);
}
/**
@ -163,15 +283,13 @@ struct Queue(T)
///
unittest
{
auto q = make!(Queue!int)(defaultAllocator);
Queue!int q;
q.insertBack(8);
q.insertBack(9);
assert(q.front == 8);
q.popFront();
assert(q.front == 9);
dispose(defaultAllocator, q);
}
/**
@ -215,7 +333,7 @@ struct Queue(T)
///
unittest
{
auto q = Queue!int(defaultAllocator);
Queue!int q;
size_t j;
q.insertBack(5);
@ -246,32 +364,19 @@ struct Queue(T)
assert(q.empty);
}
/**
* Queue entry.
*/
protected struct Entry
{
/// Queue item content.
T content;
/// Next list item.
Entry* next;
}
/// The first element of the list.
protected Entry first;
private Entry!T first;
/// The last element of the list.
protected Entry* rear;
private Entry!T* rear;
/// The allocator.
protected shared Allocator allocator;
mixin DefaultAllocator;
}
///
unittest
{
auto q = Queue!int(defaultAllocator);
Queue!int q;
q.insertBack(5);
assert(!q.empty);