Implement Set Range
This commit is contained in:
parent
6c0588164a
commit
2815b53a88
@ -12,6 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
module tanya.container.entry;
|
module tanya.container.entry;
|
||||||
|
|
||||||
|
import std.traits;
|
||||||
import tanya.typecons;
|
import tanya.typecons;
|
||||||
|
|
||||||
package struct SEntry(T)
|
package struct SEntry(T)
|
||||||
@ -63,14 +64,17 @@ package struct Bucket(T)
|
|||||||
this.status = BucketStatus.used;
|
this.status = BucketStatus.used;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property ref T content()
|
@property ref inout(T) content() inout
|
||||||
{
|
{
|
||||||
return this.content_;
|
return this.content_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove()
|
void remove()
|
||||||
{
|
{
|
||||||
this.content = T.init;
|
static if (hasElaborateDestructor!T)
|
||||||
|
{
|
||||||
|
destroy(this.content);
|
||||||
|
}
|
||||||
this.status = BucketStatus.deleted;
|
this.status = BucketStatus.deleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,15 +27,112 @@ import tanya.memory;
|
|||||||
*/
|
*/
|
||||||
struct Range(E)
|
struct Range(E)
|
||||||
{
|
{
|
||||||
private alias ContainerType = CopyConstness!(E, Array!(Bucket!(Unqual!E)));
|
static if (isMutable!E)
|
||||||
private ContainerType* container;
|
{
|
||||||
|
private alias DataRange = Array!(Bucket!(Unqual!E)).Range;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
private alias DataRange = Array!(Bucket!(Unqual!E)).ConstRange;
|
||||||
|
}
|
||||||
|
private DataRange dataRange;
|
||||||
|
|
||||||
@disable this();
|
@disable this();
|
||||||
|
|
||||||
|
private this(DataRange dataRange)
|
||||||
|
{
|
||||||
|
while (!dataRange.empty && dataRange.front.status != BucketStatus.used)
|
||||||
|
{
|
||||||
|
dataRange.popFront();
|
||||||
|
}
|
||||||
|
while (!dataRange.empty && dataRange.back.status != BucketStatus.used)
|
||||||
|
{
|
||||||
|
dataRange.popBack();
|
||||||
|
}
|
||||||
|
this.dataRange = dataRange;
|
||||||
|
}
|
||||||
|
|
||||||
@property Range save()
|
@property Range save()
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@property bool empty() const
|
||||||
|
{
|
||||||
|
return this.dataRange.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@property void popFront()
|
||||||
|
in
|
||||||
|
{
|
||||||
|
assert(!this.dataRange.empty);
|
||||||
|
assert(this.dataRange.front.status == BucketStatus.used);
|
||||||
|
}
|
||||||
|
out
|
||||||
|
{
|
||||||
|
assert(this.dataRange.empty
|
||||||
|
|| this.dataRange.back.status == BucketStatus.used);
|
||||||
|
}
|
||||||
|
body
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
dataRange.popFront();
|
||||||
|
}
|
||||||
|
while (!dataRange.empty && dataRange.front.status != BucketStatus.used);
|
||||||
|
}
|
||||||
|
|
||||||
|
@property void popBack()
|
||||||
|
in
|
||||||
|
{
|
||||||
|
assert(!this.dataRange.empty);
|
||||||
|
assert(this.dataRange.back.status == BucketStatus.used);
|
||||||
|
}
|
||||||
|
out
|
||||||
|
{
|
||||||
|
assert(this.dataRange.empty
|
||||||
|
|| this.dataRange.back.status == BucketStatus.used);
|
||||||
|
}
|
||||||
|
body
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
dataRange.popBack();
|
||||||
|
}
|
||||||
|
while (!dataRange.empty && dataRange.back.status != BucketStatus.used);
|
||||||
|
}
|
||||||
|
|
||||||
|
@property ref inout(E) front() inout
|
||||||
|
in
|
||||||
|
{
|
||||||
|
assert(!this.dataRange.empty);
|
||||||
|
assert(this.dataRange.front.status == BucketStatus.used);
|
||||||
|
}
|
||||||
|
body
|
||||||
|
{
|
||||||
|
return dataRange.front.content;
|
||||||
|
}
|
||||||
|
|
||||||
|
@property ref inout(E) back() inout
|
||||||
|
in
|
||||||
|
{
|
||||||
|
assert(!this.dataRange.empty);
|
||||||
|
assert(this.dataRange.back.status == BucketStatus.used);
|
||||||
|
}
|
||||||
|
body
|
||||||
|
{
|
||||||
|
return dataRange.back.content;
|
||||||
|
}
|
||||||
|
|
||||||
|
Range opIndex()
|
||||||
|
{
|
||||||
|
return typeof(return)(this.dataRange[]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Range!(const E) opIndex() const
|
||||||
|
{
|
||||||
|
return typeof(return)(this.dataRange[]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -95,6 +192,24 @@ struct Set(T)
|
|||||||
return this.data.length;
|
return this.data.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterates over the $(D_PSYMBOL Set) and counts the elements.
|
||||||
|
*
|
||||||
|
* Returns: Count of elements within the $(D_PSYMBOL Set).
|
||||||
|
*/
|
||||||
|
@property size_t length() const
|
||||||
|
{
|
||||||
|
size_t count;
|
||||||
|
foreach (ref e; this.data[])
|
||||||
|
{
|
||||||
|
if (e.status == BucketStatus.used)
|
||||||
|
{
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
private static const size_t[41] primes = [
|
private static const size_t[41] primes = [
|
||||||
3, 7, 13, 23, 29, 37, 53, 71, 97, 131, 163, 193, 239, 293, 389, 521,
|
3, 7, 13, 23, 29, 37, 53, 71, 97, 131, 163, 193, 239, 293, 389, 521,
|
||||||
769, 919, 1103, 1327, 1543, 2333, 3079, 4861, 6151, 12289, 24593,
|
769, 919, 1103, 1327, 1543, 2333, 3079, 4861, 6151, 12289, 24593,
|
||||||
@ -229,6 +344,21 @@ struct Set(T)
|
|||||||
private DataType data;
|
private DataType data;
|
||||||
private size_t lengthIndex;
|
private size_t lengthIndex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns: A bidirectional range that iterates over the $(D_PSYMBOL Set)'s
|
||||||
|
* elements.
|
||||||
|
*/
|
||||||
|
Range opIndex()
|
||||||
|
{
|
||||||
|
return typeof(return)(data[]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Ditto.
|
||||||
|
ConstRange opIndex() const
|
||||||
|
{
|
||||||
|
return typeof(return)(data[]);
|
||||||
|
}
|
||||||
|
|
||||||
mixin DefaultAllocator;
|
mixin DefaultAllocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,3 +399,15 @@ private unittest
|
|||||||
assert(set.data[3].content == 16);
|
assert(set.data[3].content == 16);
|
||||||
assert(set.data[4].status == BucketStatus.empty);
|
assert(set.data[4].status == BucketStatus.empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Static checks.
|
||||||
|
private unittest
|
||||||
|
{
|
||||||
|
import std.range.primitives;
|
||||||
|
|
||||||
|
static assert(isBidirectionalRange!(Set!int.ConstRange));
|
||||||
|
static assert(isBidirectionalRange!(Set!int.Range));
|
||||||
|
|
||||||
|
static assert(!isInfinite!(Set!int.Range));
|
||||||
|
static assert(!hasLength!(Set!int.Range));
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user