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; module tanya.container.list;
import tanya.container.entry;
import tanya.memory; import tanya.memory;
/** /**
* Singly linked list. * Singly-linked list.
* *
* Params: * Params:
* T = Content type. * 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. * 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() void clear()
{ {
@ -54,14 +43,12 @@ class SList(T)
/// ///
unittest unittest
{ {
auto l = make!(SList!int)(defaultAllocator); SList!int l;
l.insertFront(8); l.insertFront(8);
l.insertFront(5); l.insertFront(5);
l.clear(); l.clear();
assert(l.empty); assert(l.empty);
dispose(defaultAllocator, l);
} }
/** /**
@ -83,35 +70,39 @@ class SList(T)
* Params: * Params:
* x = New element. * 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.content = x;
temp.next = first.next; temp.next = first.next;
first.next = temp; first.next = temp;
} }
/// Ditto.
void insertFront(T x)
{
insertFront(x);
}
/// Ditto. /// Ditto.
alias insert = insertFront; alias insert = insertFront;
/// ///
unittest unittest
{ {
auto l = make!(SList!int)(defaultAllocator); SList!int l;
l.insertFront(8); l.insertFront(8);
assert(l.front == 8); assert(l.front == 8);
l.insertFront(9); l.insertFront(9);
assert(l.front == 9); assert(l.front == 9);
dispose(defaultAllocator, l);
} }
/** /**
* Returns: $(D_KEYWORD true) if the list is empty. * Returns: $(D_KEYWORD true) if the list is empty.
*/ */
@property bool empty() inout const @property bool empty() const
{ {
return first.next is null; return first.next is null;
} }
@ -121,7 +112,7 @@ class SList(T)
* *
* Returns: The first element. * Returns: The first element.
*/ */
T popFront() void popFront()
in in
{ {
assert(!empty); assert(!empty);
@ -129,26 +120,21 @@ class SList(T)
body body
{ {
auto n = first.next.next; auto n = first.next.next;
auto content = first.next.content;
dispose(allocator, first.next); allocator.dispose(first.next);
first.next = n; first.next = n;
return content;
} }
/// ///
unittest unittest
{ {
auto l = make!(SList!int)(defaultAllocator); SList!int l;
l.insertFront(8); l.insertFront(8);
l.insertFront(9); l.insertFront(9);
assert(l.front == 9); assert(l.front == 9);
l.popFront(); l.popFront();
assert(l.front == 8); assert(l.front == 8);
dispose(defaultAllocator, l);
} }
/** /**
@ -179,7 +165,7 @@ class SList(T)
/// ///
unittest unittest
{ {
auto l = make!(SList!int)(defaultAllocator); SList!int l;
l.insertFront(8); l.insertFront(8);
l.insertFront(5); l.insertFront(5);
@ -188,8 +174,6 @@ class SList(T)
assert(l.removeFront(2) == 2); assert(l.removeFront(2) == 2);
assert(l.removeFront(3) == 1); assert(l.removeFront(3) == 1);
assert(l.removeFront(3) == 0); assert(l.removeFront(3) == 0);
dispose(defaultAllocator, l);
} }
/** /**
@ -235,7 +219,7 @@ class SList(T)
/// ///
unittest unittest
{ {
auto l = make!(SList!int)(defaultAllocator); SList!int l;
l.insertFront(5); l.insertFront(5);
l.insertFront(4); l.insertFront(4);
@ -246,32 +230,18 @@ class SList(T)
assert(i != 1 || e == 4); assert(i != 1 || e == 4);
assert(i != 2 || e == 5); 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. /// 0th element of the list.
protected Entry first; private Entry!T first;
/// Allocator. mixin DefaultAllocator;
protected shared Allocator allocator;
} }
/// ///
unittest unittest
{ {
auto l = make!(SList!int)(defaultAllocator); SList!int l;
size_t i; size_t i;
l.insertFront(5); l.insertFront(5);
@ -285,8 +255,6 @@ unittest
++i; ++i;
} }
assert(i == 3); assert(i == 3);
dispose(defaultAllocator, l);
} }
private unittest private unittest
@ -294,8 +262,5 @@ private unittest
interface Stuff interface Stuff
{ {
} }
static assert(is(SList!Stuff));
auto l = make!(SList!Stuff)(defaultAllocator);
dispose(defaultAllocator, l);
} }

View File

@ -10,7 +10,6 @@
*/ */
module tanya.container; module tanya.container;
public import tanya.container.bit;
public import tanya.container.buffer; public import tanya.container.buffer;
public import tanya.container.list; public import tanya.container.list;
public import tanya.container.vector; public import tanya.container.vector;

View File

@ -6,32 +6,22 @@
* 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:belka@caraus.de, Eugene Wissner) * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
*/ */
module tanya.container.queue; module tanya.container.queue;
import tanya.container.entry;
import std.traits;
import tanya.memory; import tanya.memory;
/** /**
* Queue. * FIFO queue.
* *
* Params: * Params:
* T = Content type. * T = Content type.
*/ */
struct Queue(T) 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. * Removes all elements from the queue.
*/ */
@ -54,15 +44,147 @@ struct Queue(T)
/// ///
unittest unittest
{ {
auto q = defaultAllocator.make!(Queue!int); Queue!int q;
assert(q.empty); assert(q.empty);
q.insertBack(8); q.insertBack(8);
q.insertBack(9); q.insertBack(9);
q.clear(); q.clear();
assert(q.empty); 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: * Params:
* x = New element. * x = New element.
*/ */
void insertBack(T x) void insertBack(ref T x)
{ {
if (allocator is null) auto temp = allocator.make!(Entry!T);
{
allocator = defaultAllocator;
}
Entry* temp = make!Entry(allocator);
temp.content = x; temp.content = x;
@ -105,27 +223,31 @@ struct Queue(T)
} }
} }
/// Ditto.
void insertBack(T x)
{
insertBack(x);
}
/// Ditto. /// Ditto.
alias insert = insertBack; alias insert = insertBack;
/// ///
unittest unittest
{ {
auto q = make!(Queue!int)(defaultAllocator); Queue!int q;
assert(q.empty); assert(q.empty);
q.insertBack(8); q.insertBack(8);
assert(q.front == 8); assert(q.front == 8);
q.insertBack(9); q.insertBack(9);
assert(q.front == 8); assert(q.front == 8);
dispose(defaultAllocator, q);
} }
/** /**
* Returns: $(D_KEYWORD true) if the queue is empty. * 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; return first.next is null;
} }
@ -133,14 +255,12 @@ struct Queue(T)
/// ///
unittest unittest
{ {
auto q = make!(Queue!int)(defaultAllocator); Queue!int q;
int value = 7; int value = 7;
assert(q.empty); assert(q.empty);
q.insertBack(value); q.insertBack(value);
assert(!q.empty); assert(!q.empty);
dispose(defaultAllocator, q);
} }
/** /**
@ -163,15 +283,13 @@ struct Queue(T)
/// ///
unittest unittest
{ {
auto q = make!(Queue!int)(defaultAllocator); Queue!int q;
q.insertBack(8); q.insertBack(8);
q.insertBack(9); q.insertBack(9);
assert(q.front == 8); assert(q.front == 8);
q.popFront(); q.popFront();
assert(q.front == 9); assert(q.front == 9);
dispose(defaultAllocator, q);
} }
/** /**
@ -215,7 +333,7 @@ struct Queue(T)
/// ///
unittest unittest
{ {
auto q = Queue!int(defaultAllocator); Queue!int q;
size_t j; size_t j;
q.insertBack(5); q.insertBack(5);
@ -246,32 +364,19 @@ struct Queue(T)
assert(q.empty); assert(q.empty);
} }
/**
* Queue entry.
*/
protected struct Entry
{
/// Queue item content.
T content;
/// Next list item.
Entry* next;
}
/// The first element of the list. /// The first element of the list.
protected Entry first; private Entry!T first;
/// The last element of the list. /// The last element of the list.
protected Entry* rear; private Entry!T* rear;
/// The allocator. mixin DefaultAllocator;
protected shared Allocator allocator;
} }
/// ///
unittest unittest
{ {
auto q = Queue!int(defaultAllocator); Queue!int q;
q.insertBack(5); q.insertBack(5);
assert(!q.empty); assert(!q.empty);

View File

@ -8,7 +8,7 @@
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:belka@caraus.de, Eugene Wissner) * 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. * Wrapper that allows bit manipulation on $(D_KEYWORD ubyte[]) array.

View File

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

View File

@ -10,9 +10,7 @@
*/ */
module tanya.crypto; module tanya.crypto;
public public import tanya.crypto.bit;
{ public import tanya.crypto.des;
import tanya.crypto.des; public import tanya.crypto.mode;
import tanya.crypto.mode; public import tanya.crypto.symmetric;
import tanya.crypto.symmetric;
}

View File

@ -54,15 +54,30 @@ interface Allocator
/** /**
* The mixin generates common methods for classes and structs using * The mixin generates common methods for classes and structs using
* allocators. It provides a protected member and a read-only property, * allocators. It provides a protected member, constructor and a read-only
* that checks if an allocator was already set and sets it to the default * property, that checks if an allocator was already set and sets it to the
* one, if not (useful for structs which don't have a default constructor). * default one, if not (useful for structs which don't have a default
* constructor).
*/ */
mixin template DefaultAllocator() mixin template DefaultAllocator()
{ {
/// Allocator. /// Allocator.
protected shared Allocator 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 * This property checks if the allocator was set in the constructor
* and sets it to the default one, if not. * and sets it to the default one, if not.