219 lines
3.3 KiB
D
219 lines
3.3 KiB
D
/* 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/. */
|
|
|
|
/**
|
|
* Copyright: Eugene Wissner 2016.
|
|
* 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)
|
|
*/
|
|
module tanya.container.queue;
|
|
|
|
import tanya.memory;
|
|
|
|
/**
|
|
* Queue.
|
|
*
|
|
* Params:
|
|
* T = Content type.
|
|
*/
|
|
class Queue(T)
|
|
{
|
|
/**
|
|
* Creates a new $(D_PSYMBOL Queue).
|
|
*
|
|
* Params:
|
|
* allocator = The allocator should be used for the element
|
|
* allocations.
|
|
*/
|
|
this(IAllocator allocator = theAllocator)
|
|
{
|
|
this.allocator = allocator;
|
|
}
|
|
|
|
/**
|
|
* Removes all elements from the queue.
|
|
*/
|
|
~this()
|
|
{
|
|
foreach (e; this)
|
|
{
|
|
static if (isFinalizable!T)
|
|
{
|
|
dispose(allocator, e);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns: First element.
|
|
*/
|
|
@property ref T front()
|
|
in
|
|
{
|
|
assert(!empty);
|
|
}
|
|
body
|
|
{
|
|
return first.next.content;
|
|
}
|
|
|
|
/**
|
|
* Inserts a new element.
|
|
*
|
|
* Params:
|
|
* x = New element.
|
|
*
|
|
* Returns: $(D_KEYWORD this).
|
|
*/
|
|
typeof(this) insertBack(T x)
|
|
{
|
|
Entry* temp = make!Entry(allocator);
|
|
|
|
temp.content = x;
|
|
|
|
if (empty)
|
|
{
|
|
first.next = rear = temp;
|
|
}
|
|
else
|
|
{
|
|
rear.next = temp;
|
|
rear = rear.next;
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
alias insert = insertBack;
|
|
|
|
///
|
|
unittest
|
|
{
|
|
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);
|
|
|
|
q ~= value;
|
|
|
|
assert(q.front == value);
|
|
assert(!q.empty);
|
|
|
|
dispose(theAllocator, q);
|
|
}
|
|
|
|
/**
|
|
* Returns: $(D_KEYWORD true) if the queue is empty.
|
|
*/
|
|
@property bool empty() const @safe pure nothrow
|
|
{
|
|
return first.next is null;
|
|
}
|
|
|
|
///
|
|
unittest
|
|
{
|
|
auto q = make!(Queue!int)(theAllocator);
|
|
int value = 7;
|
|
|
|
assert(q.empty);
|
|
q.insertBack(value);
|
|
assert(!q.empty);
|
|
|
|
dispose(theAllocator, q);
|
|
}
|
|
|
|
/**
|
|
* Move position to the next element.
|
|
*
|
|
* Returns: $(D_KEYWORD this).
|
|
*/
|
|
typeof(this) popFront()
|
|
in
|
|
{
|
|
assert(!empty);
|
|
}
|
|
body
|
|
{
|
|
auto n = first.next.next;
|
|
|
|
dispose(allocator, first.next);
|
|
first.next = n;
|
|
|
|
return this;
|
|
}
|
|
|
|
///
|
|
unittest
|
|
{
|
|
auto q = make!(Queue!int)(theAllocator);
|
|
int[2] values = [8, 9];
|
|
|
|
q.insertBack(values[0]);
|
|
q.insertBack(values[1]);
|
|
assert(q.front is values[0]);
|
|
q.popFront();
|
|
assert(q.front is values[1]);
|
|
|
|
dispose(theAllocator, q);
|
|
}
|
|
|
|
/**
|
|
* Queue entry.
|
|
*/
|
|
protected struct Entry
|
|
{
|
|
/// Queue item content.
|
|
T content;
|
|
|
|
/// Next list item.
|
|
Entry* next;
|
|
}
|
|
|
|
/// The first element of the list.
|
|
protected Entry first;
|
|
|
|
/// The last element of the list.
|
|
protected Entry* rear;
|
|
|
|
private IAllocator allocator;
|
|
}
|
|
|
|
///
|
|
unittest
|
|
{
|
|
auto q = make!(Queue!int)(theAllocator);
|
|
|
|
dispose(theAllocator, q);
|
|
}
|