Finish DList implementation. Fixes #209

* removeBack
* insertAfter
* Diverse fixes of insertion logic
* Internal moveFront and moveBack functions
* Internal makeList function
This commit is contained in:
Eugen Wissner 2017-07-08 15:51:17 +02:00
parent 53df12897b
commit 4834b36271

View File

@ -1307,6 +1307,34 @@ struct DList(T)
return 1; return 1;
} }
// Creates a lsit of linked entries from a range.
// Returns count of the elements in the list.
private size_t makeList(R)(ref R el, out Entry* head, out Entry* tail) @trusted
out (retLength)
{
assert(retLength == 0 && head is null && tail is null
|| retLength > 0 && head !is null && tail !is null);
}
body
{
size_t retLength;
if (!el.empty)
{
head = tail = allocator.make!Entry(el.front);
el.popFront();
retLength = 1;
}
foreach (ref e; el)
{
tail.next = allocator.make!Entry(e);
tail.next.prev = tail;
tail = tail.next;
++retLength;
}
return retLength;
}
/** /**
* Inserts a new element at the beginning. * Inserts a new element at the beginning.
* *
@ -1355,39 +1383,25 @@ struct DList(T)
} }
/// Ditto. /// Ditto.
size_t insertFront(R)(R el) @trusted size_t insertFront(R)(R el)
if (!isInfinite!R if (!isInfinite!R
&& isInputRange!R && isInputRange!R
&& isImplicitlyConvertible!(ElementType!R, T)) && isImplicitlyConvertible!(ElementType!R, T))
{ {
size_t retLength; Entry* begin, end;
Entry* next, newHead; const inserted = makeList(el, begin, end);
if (!el.empty)
{
next = allocator.make!Entry(el.front);
newHead = next;
el.popFront();
retLength = 1;
}
foreach (ref e; el)
{
next.next = allocator.make!Entry(e);
next.next.prev = next;
next = next.next;
++retLength;
}
if (this.head is null) if (this.head is null)
{ {
this.tail = next; this.tail = end;
} }
if (newHead !is null) if (begin !is null)
{ {
next.next = this.head; end.next = this.head;
this.head = newHead; this.head = begin;
} }
return retLength; return inserted;
} }
private @safe @nogc unittest private @safe @nogc unittest
@ -1500,11 +1514,20 @@ struct DList(T)
&& isInputRange!R && isInputRange!R
&& isImplicitlyConvertible!(ElementType!R, T)) && isImplicitlyConvertible!(ElementType!R, T))
{ {
size_t inserted; Entry* begin, end;
const inserted = makeList(el, begin, end);
foreach (ref e; el) if (this.tail is null)
{ {
inserted += insertBack(e); this.head = begin;
}
else
{
this.tail.next = begin;
}
if (begin !is null)
{
this.tail = end;
} }
return inserted; return inserted;