Add length and opCmp to the Queue
This commit is contained in:
parent
40857e69b7
commit
f1bc4dc2e2
45
source/tanya/container/entry.d
Normal file
45
source/tanya/container/entry.d
Normal file
@ -0,0 +1,45 @@
|
||||
/* 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/. */
|
||||
|
||||
/*
|
||||
* Internal package used by containers that rely on entries/nodes.
|
||||
*
|
||||
* 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.entry;
|
||||
|
||||
version (unittest)
|
||||
{
|
||||
package struct ConstEqualsStruct
|
||||
{
|
||||
int opEquals(typeof(this) that) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
package struct MutableEqualsStruct
|
||||
{
|
||||
int opEquals(typeof(this) that)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
package struct NoEqualsStruct
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
package struct Entry(T)
|
||||
{
|
||||
/// Item content.
|
||||
T content;
|
||||
|
||||
/// Next item.
|
||||
Entry* next;
|
||||
}
|
@ -10,28 +10,17 @@
|
||||
*/
|
||||
module tanya.container.list;
|
||||
|
||||
import tanya.container.entry;
|
||||
import tanya.memory;
|
||||
|
||||
/**
|
||||
* Singly linked list.
|
||||
* Singly-linked list.
|
||||
*
|
||||
* Params:
|
||||
* T = Content type.
|
||||
*/
|
||||
class SList(T)
|
||||
struct SList(T)
|
||||
{
|
||||
/**
|
||||
* Creates a new $(D_PSYMBOL SList).
|
||||
*
|
||||
* Params:
|
||||
* allocator = The allocator should be used for the element
|
||||
* allocations.
|
||||
*/
|
||||
this(shared Allocator allocator = defaultAllocator)
|
||||
{
|
||||
this.allocator = allocator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all elements from the list.
|
||||
*/
|
||||
@ -41,7 +30,7 @@ class SList(T)
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all contents from the $(D_PSYMBOL SList).
|
||||
* Removes all contents from the list.
|
||||
*/
|
||||
void clear()
|
||||
{
|
||||
@ -54,14 +43,12 @@ class SList(T)
|
||||
///
|
||||
unittest
|
||||
{
|
||||
auto l = make!(SList!int)(defaultAllocator);
|
||||
SList!int l;
|
||||
|
||||
l.insertFront(8);
|
||||
l.insertFront(5);
|
||||
l.clear();
|
||||
assert(l.empty);
|
||||
|
||||
dispose(defaultAllocator, l);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -83,35 +70,39 @@ class SList(T)
|
||||
* Params:
|
||||
* x = New element.
|
||||
*/
|
||||
void insertFront(T x)
|
||||
void insertFront(ref T x)
|
||||
{
|
||||
Entry* temp = make!Entry(allocator);
|
||||
auto temp = allocator.make!(Entry!T);
|
||||
|
||||
temp.content = x;
|
||||
temp.next = first.next;
|
||||
first.next = temp;
|
||||
}
|
||||
|
||||
/// Ditto.
|
||||
void insertFront(T x)
|
||||
{
|
||||
insertFront(x);
|
||||
}
|
||||
|
||||
/// Ditto.
|
||||
alias insert = insertFront;
|
||||
|
||||
///
|
||||
unittest
|
||||
{
|
||||
auto l = make!(SList!int)(defaultAllocator);
|
||||
SList!int l;
|
||||
|
||||
l.insertFront(8);
|
||||
assert(l.front == 8);
|
||||
l.insertFront(9);
|
||||
assert(l.front == 9);
|
||||
|
||||
dispose(defaultAllocator, l);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns: $(D_KEYWORD true) if the list is empty.
|
||||
*/
|
||||
@property bool empty() inout const
|
||||
@property bool empty() const
|
||||
{
|
||||
return first.next is null;
|
||||
}
|
||||
@ -121,7 +112,7 @@ class SList(T)
|
||||
*
|
||||
* Returns: The first element.
|
||||
*/
|
||||
T popFront()
|
||||
void popFront()
|
||||
in
|
||||
{
|
||||
assert(!empty);
|
||||
@ -129,26 +120,21 @@ class SList(T)
|
||||
body
|
||||
{
|
||||
auto n = first.next.next;
|
||||
auto content = first.next.content;
|
||||
|
||||
dispose(allocator, first.next);
|
||||
allocator.dispose(first.next);
|
||||
first.next = n;
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
///
|
||||
unittest
|
||||
{
|
||||
auto l = make!(SList!int)(defaultAllocator);
|
||||
SList!int l;
|
||||
|
||||
l.insertFront(8);
|
||||
l.insertFront(9);
|
||||
assert(l.front == 9);
|
||||
l.popFront();
|
||||
assert(l.front == 8);
|
||||
|
||||
dispose(defaultAllocator, l);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -179,7 +165,7 @@ class SList(T)
|
||||
///
|
||||
unittest
|
||||
{
|
||||
auto l = make!(SList!int)(defaultAllocator);
|
||||
SList!int l;
|
||||
|
||||
l.insertFront(8);
|
||||
l.insertFront(5);
|
||||
@ -188,8 +174,6 @@ class SList(T)
|
||||
assert(l.removeFront(2) == 2);
|
||||
assert(l.removeFront(3) == 1);
|
||||
assert(l.removeFront(3) == 0);
|
||||
|
||||
dispose(defaultAllocator, l);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -235,7 +219,7 @@ class SList(T)
|
||||
///
|
||||
unittest
|
||||
{
|
||||
auto l = make!(SList!int)(defaultAllocator);
|
||||
SList!int l;
|
||||
|
||||
l.insertFront(5);
|
||||
l.insertFront(4);
|
||||
@ -246,32 +230,18 @@ class SList(T)
|
||||
assert(i != 1 || e == 4);
|
||||
assert(i != 2 || e == 5);
|
||||
}
|
||||
dispose(defaultAllocator, l);
|
||||
}
|
||||
|
||||
/**
|
||||
* List entry.
|
||||
*/
|
||||
protected struct Entry
|
||||
{
|
||||
/// List item content.
|
||||
T content;
|
||||
|
||||
/// Next list item.
|
||||
Entry* next;
|
||||
}
|
||||
|
||||
/// 0th element of the list.
|
||||
protected Entry first;
|
||||
private Entry!T first;
|
||||
|
||||
/// Allocator.
|
||||
protected shared Allocator allocator;
|
||||
mixin DefaultAllocator;
|
||||
}
|
||||
|
||||
///
|
||||
unittest
|
||||
{
|
||||
auto l = make!(SList!int)(defaultAllocator);
|
||||
SList!int l;
|
||||
size_t i;
|
||||
|
||||
l.insertFront(5);
|
||||
@ -285,8 +255,6 @@ unittest
|
||||
++i;
|
||||
}
|
||||
assert(i == 3);
|
||||
|
||||
dispose(defaultAllocator, l);
|
||||
}
|
||||
|
||||
private unittest
|
||||
@ -294,8 +262,5 @@ private unittest
|
||||
interface Stuff
|
||||
{
|
||||
}
|
||||
|
||||
auto l = make!(SList!Stuff)(defaultAllocator);
|
||||
|
||||
dispose(defaultAllocator, l);
|
||||
static assert(is(SList!Stuff));
|
||||
}
|
||||
|
@ -10,7 +10,6 @@
|
||||
*/
|
||||
module tanya.container;
|
||||
|
||||
public import tanya.container.bit;
|
||||
public import tanya.container.buffer;
|
||||
public import tanya.container.list;
|
||||
public import tanya.container.vector;
|
||||
|
@ -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);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Mozilla Public License, v. 2.0).
|
||||
* Authors: $(LINK2 mailto:belka@caraus.de, Eugene Wissner)
|
||||
*/
|
||||
module tanya.container.bit;
|
||||
module tanya.crypto.bit;
|
||||
|
||||
/**
|
||||
* Wrapper that allows bit manipulation on $(D_KEYWORD ubyte[]) array.
|
@ -10,7 +10,7 @@
|
||||
*/
|
||||
module tanya.crypto.des;
|
||||
|
||||
import tanya.container.bit;
|
||||
import tanya.crypto.bit;
|
||||
import tanya.crypto.symmetric;
|
||||
|
||||
/// Initial permutation table.
|
||||
|
@ -10,9 +10,7 @@
|
||||
*/
|
||||
module tanya.crypto;
|
||||
|
||||
public
|
||||
{
|
||||
import tanya.crypto.des;
|
||||
import tanya.crypto.mode;
|
||||
import tanya.crypto.symmetric;
|
||||
}
|
||||
public import tanya.crypto.bit;
|
||||
public import tanya.crypto.des;
|
||||
public import tanya.crypto.mode;
|
||||
public import tanya.crypto.symmetric;
|
||||
|
@ -54,15 +54,30 @@ interface Allocator
|
||||
|
||||
/**
|
||||
* The mixin generates common methods for classes and structs using
|
||||
* allocators. It provides a protected member and a read-only property,
|
||||
* that checks if an allocator was already set and sets it to the default
|
||||
* one, if not (useful for structs which don't have a default constructor).
|
||||
* allocators. It provides a protected member, constructor and a read-only
|
||||
* property, that checks if an allocator was already set and sets it to the
|
||||
* default one, if not (useful for structs which don't have a default
|
||||
* constructor).
|
||||
*/
|
||||
mixin template DefaultAllocator()
|
||||
{
|
||||
/// Allocator.
|
||||
protected shared Allocator allocator_;
|
||||
|
||||
/**
|
||||
* Params:
|
||||
* allocator = The allocator should be used.
|
||||
*/
|
||||
this(shared Allocator allocator)
|
||||
in
|
||||
{
|
||||
assert(allocator !is null);
|
||||
}
|
||||
body
|
||||
{
|
||||
this.allocator_ = allocator;
|
||||
}
|
||||
|
||||
/**
|
||||
* This property checks if the allocator was set in the constructor
|
||||
* and sets it to the default one, if not.
|
||||
|
Loading…
Reference in New Issue
Block a user