Add range support for SList

This commit is contained in:
Eugen Wissner 2017-01-24 08:20:07 +01:00
parent a7206cbd02
commit a48d9cb739
2 changed files with 129 additions and 32 deletions

View File

@ -10,9 +10,63 @@
*/ */
module tanya.container.list; module tanya.container.list;
import std.traits;
import tanya.container.entry; import tanya.container.entry;
import tanya.memory; import tanya.memory;
private struct Range(E)
if (__traits(isSame, TemplateOf!E, SEntry))
{
private alias T = typeof(E.content);
private E* head;
private this(E* head)
{
this.head = head;
}
@property Range save()
{
return this;
}
@property bool empty() const
{
return head is null;
}
@property ref inout(T) front() inout
in
{
assert(!empty);
}
body
{
return head.content;
}
void popFront()
in
{
assert(!empty);
}
body
{
head = head.next;
}
Range opIndex()
{
return typeof(return)(head);
}
Range!(const E) opIndex() const
{
return typeof(return)(head);
}
}
/** /**
* Singly-linked list. * Singly-linked list.
* *
@ -21,6 +75,11 @@ import tanya.memory;
*/ */
struct SList(T) struct SList(T)
{ {
private alias Entry = SEntry!T;
// 0th element of the list.
private Entry* head;
/** /**
* Removes all elements from the list. * Removes all elements from the list.
*/ */
@ -36,7 +95,7 @@ struct SList(T)
{ {
while (!empty) while (!empty)
{ {
popFront(); removeFront();
} }
} }
@ -61,7 +120,7 @@ struct SList(T)
} }
body body
{ {
return first.next.content; return head.content;
} }
/** /**
@ -72,11 +131,11 @@ struct SList(T)
*/ */
void insertFront(ref T x) void insertFront(ref T x)
{ {
auto temp = allocator.make!(SEntry!T); auto temp = allocator.make!Entry;
temp.content = x; temp.content = x;
temp.next = first.next; temp.next = head;
first.next = temp; head = temp;
} }
/// Ditto. /// Ditto.
@ -104,25 +163,27 @@ struct SList(T)
*/ */
@property bool empty() const @property bool empty() const
{ {
return first.next is null; return head is null;
} }
/** /**
* Returns the first element and moves to the next one. * Returns the first element and moves to the next one.
* *
* Returns: The first element. * Returns: The first element.
*
* Precondition: $(D_INLINECODE !empty)
*/ */
void popFront() void removeFront()
in in
{ {
assert(!empty); assert(!empty);
} }
body body
{ {
auto n = first.next.next; auto n = head.next;
allocator.dispose(first.next); allocator.dispose(head);
first.next = n; head = n;
} }
/// ///
@ -133,14 +194,16 @@ struct SList(T)
l.insertFront(8); l.insertFront(8);
l.insertFront(9); l.insertFront(9);
assert(l.front == 9); assert(l.front == 9);
l.popFront(); l.removeFront();
assert(l.front == 8); assert(l.front == 8);
l.removeFront();
assert(l.empty);
} }
/** /**
* Removes $(D_PARAM howMany) elements from the list. * Removes $(D_PARAM howMany) elements from the list.
* *
* Unlike $(D_PSYMBOL popFront()), this method doesn't fail, if it could not * Unlike $(D_PSYMBOL removeFront()), this method doesn't fail, if it could not
* remove $(D_PARAM howMany) elements. Instead, if $(D_PARAM howMany) is * remove $(D_PARAM howMany) elements. Instead, if $(D_PARAM howMany) is
* greater than the list length, all elements are removed. * greater than the list length, all elements are removed.
* *
@ -149,12 +212,17 @@ struct SList(T)
* *
* Returns: The number of elements removed. * Returns: The number of elements removed.
*/ */
size_t removeFront(in size_t howMany = 1) size_t removeFront(in size_t howMany)
out (removed)
{
assert(removed <= howMany);
}
body
{ {
size_t i; size_t i;
for (; i < howMany && !empty; ++i) for (; i < howMany && !empty; ++i)
{ {
popFront(); removeFront();
} }
return i; return i;
} }
@ -182,12 +250,12 @@ struct SList(T)
* Params: * Params:
* dg = $(D_KEYWORD foreach) body. * dg = $(D_KEYWORD foreach) body.
*/ */
int opApply(scope int delegate(ref size_t i, ref T) dg) int opApply(scope int delegate(ref size_t i, ref T) @nogc dg)
{ {
int result; int result;
size_t i; size_t i;
for (auto pos = first.next; pos; pos = pos.next, ++i) for (auto pos = head; pos; pos = pos.next, ++i)
{ {
result = dg(i, pos.content); result = dg(i, pos.content);
@ -200,11 +268,11 @@ struct SList(T)
} }
/// Ditto. /// Ditto.
int opApply(scope int delegate(ref T) dg) int opApply(scope int delegate(ref T) @nogc dg)
{ {
int result; int result;
for (auto pos = first.next; pos; pos = pos.next) for (auto pos = head; pos; pos = pos.next)
{ {
result = dg(pos.content); result = dg(pos.content);
@ -232,8 +300,15 @@ struct SList(T)
} }
} }
/// 0th element of the list. Range!Entry opIndex()
private SEntry!T first; {
return typeof(return)(head);
}
Range!(const Entry) opIndex() const
{
return typeof(return)(head);
}
mixin DefaultAllocator; mixin DefaultAllocator;
} }
@ -257,7 +332,7 @@ unittest
assert(i == 3); assert(i == 3);
} }
private unittest unittest
{ {
interface Stuff interface Stuff
{ {

View File

@ -547,6 +547,23 @@ struct Vector(T)
return length == 0; return length == 0;
} }
/**
* Removes the value at the back of the vector.
*
* Returns: The number of elements removed
*
* Precondition: $(D_INLINECODE !empty)
*/
void removeBack()
in
{
assert(!empty);
}
body
{
length = length - 1;
}
/** /**
* Removes $(D_PARAM howMany) elements from the vector. * Removes $(D_PARAM howMany) elements from the vector.
* *
@ -559,11 +576,16 @@ struct Vector(T)
* *
* Returns: The number of elements removed * Returns: The number of elements removed
*/ */
size_t removeBack(in size_t howMany = 1) size_t removeBack(in size_t howMany)
out (removed)
{ {
immutable toRemove = min(howMany, length_); assert(removed <= howMany);
}
body
{
immutable toRemove = min(howMany, length);
length = length_ - toRemove; length = length - toRemove;
return toRemove; return toRemove;
} }
@ -1119,9 +1141,9 @@ struct Vector(T)
/// Ditto. /// Ditto.
int opApply(scope int delegate(ref size_t i, ref T) @nogc dg) int opApply(scope int delegate(ref size_t i, ref T) @nogc dg)
{ {
for (size_t i = 0; i < length_; ++i) for (size_t i = 0; i < length; ++i)
{ {
assert(i < length_); assert(i < length);
int result = dg(i, *(vector + i)); int result = dg(i, *(vector + i));
if (result != 0) if (result != 0)
@ -1135,7 +1157,7 @@ struct Vector(T)
/// Ditto. /// Ditto.
int opApplyReverse(scope int delegate(ref T) dg) int opApplyReverse(scope int delegate(ref T) dg)
{ {
for (T* end = vector + length_ - 1; vector != end; --end) for (T* end = vector + length - 1; vector != end; --end)
{ {
int result = dg(*end); int result = dg(*end);
if (result != 0) if (result != 0)
@ -1149,13 +1171,13 @@ struct Vector(T)
/// Ditto. /// Ditto.
int opApplyReverse(scope int delegate(ref size_t i, ref T) dg) int opApplyReverse(scope int delegate(ref size_t i, ref T) dg)
{ {
if (length_ > 0) if (length > 0)
{ {
size_t i = length_; size_t i = length;
do do
{ {
--i; --i;
assert(i < length_); assert(i < length);
int result = dg(i, *(vector + i)); int result = dg(i, *(vector + i));
if (result != 0) if (result != 0)
@ -1211,7 +1233,7 @@ struct Vector(T)
/** /**
* Returns: The first element. * Returns: The first element.
* *
* Precondition: $(D_INLINECODE length > 0) * Precondition: $(D_INLINECODE !empty)
*/ */
@property ref inout(T) front() inout @property ref inout(T) front() inout
in in
@ -1238,7 +1260,7 @@ struct Vector(T)
/** /**
* Returns: The last element. * Returns: The last element.
* *
* Precondition: $(D_INLINECODE length > 0) * Precondition: $(D_INLINECODE !empty)
*/ */
@property ref inout(T) back() inout @trusted @property ref inout(T) back() inout @trusted
in in