Add length and opCmp to the Queue

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

View 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;
}

View File

@ -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));
}

View File

@ -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;

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);

View File

@ -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.

View File

@ -10,7 +10,7 @@
*/
module tanya.crypto.des;
import tanya.container.bit;
import tanya.crypto.bit;
import tanya.crypto.symmetric;
/// Initial permutation table.

View File

@ -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;

View File

@ -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.