container.Set and HashTable: Fix constructors
This commit is contained in:
parent
385ec19e2f
commit
c511b97b1b
@ -26,7 +26,7 @@ Tanya consists of the following packages and (top-level) modules:
|
||||
* `algorithm`: Collection of generic algorithms.
|
||||
* `async`: Event loop (epoll, kqueue and IOCP).
|
||||
* `container`: Queue, Array, Singly and doubly linked lists, Buffers, UTF-8
|
||||
string, Hash table.
|
||||
string, Set, Hash table.
|
||||
* `conv`: This module provides functions for converting between different
|
||||
types.
|
||||
* `encoding`: This package provides tools to work with text encodings.
|
||||
|
@ -16,7 +16,9 @@ module tanya.container.entry;
|
||||
|
||||
import tanya.algorithm.mutation;
|
||||
import tanya.container.array;
|
||||
import tanya.memory.allocator;
|
||||
import tanya.meta.trait;
|
||||
import tanya.meta.transform;
|
||||
import tanya.typecons;
|
||||
|
||||
package struct SEntry(T)
|
||||
@ -119,6 +121,49 @@ package struct HashArray(alias hasher, K, V = void)
|
||||
size_t lengthIndex;
|
||||
size_t length;
|
||||
|
||||
this(shared Allocator allocator)
|
||||
in
|
||||
{
|
||||
assert(allocator !is null);
|
||||
}
|
||||
do
|
||||
{
|
||||
this.array = Buckets(allocator);
|
||||
}
|
||||
|
||||
this(T)(ref T data, shared Allocator allocator)
|
||||
if (is(Unqual!T == HashArray))
|
||||
in
|
||||
{
|
||||
assert(allocator !is null);
|
||||
}
|
||||
do
|
||||
{
|
||||
this.array = Buckets(data.array, allocator);
|
||||
this.lengthIndex = data.lengthIndex;
|
||||
this.length = data.length;
|
||||
}
|
||||
|
||||
// Move constructor
|
||||
void move(ref HashArray data, shared Allocator allocator)
|
||||
in
|
||||
{
|
||||
assert(allocator !is null);
|
||||
}
|
||||
do
|
||||
{
|
||||
this.array = Buckets(.move(data.array), allocator);
|
||||
this.lengthIndex = data.lengthIndex;
|
||||
this.length = data.length;
|
||||
}
|
||||
|
||||
void swap(ref HashArray data)
|
||||
{
|
||||
.swap(this.array, data.array);
|
||||
.swap(this.lengthIndex, data.lengthIndex);
|
||||
.swap(this.length, data.length);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns bucket position for `hash`. `0` may mean the 0th position or an
|
||||
* empty `buckets` array.
|
||||
@ -189,7 +234,7 @@ package struct HashArray(alias hasher, K, V = void)
|
||||
return false; // Rehashing failed.
|
||||
}
|
||||
}
|
||||
move(storage, this.array);
|
||||
.move(storage, this.array);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -151,7 +151,7 @@ struct Range(T)
|
||||
* Params:
|
||||
* Key = Key type.
|
||||
* Value = Value type.
|
||||
* hasher = Hash function for $(D_PARAM K).
|
||||
* hasher = Hash function for $(D_PARAM Key).
|
||||
*/
|
||||
struct HashTable(Key, Value, alias hasher = hash)
|
||||
if (is(typeof(hasher(Key.init)) == size_t))
|
||||
@ -170,6 +170,13 @@ if (is(typeof(hasher(Key.init)) == size_t))
|
||||
/// ditto
|
||||
alias ConstRange = .Range!(const HashArray);
|
||||
|
||||
invariant
|
||||
{
|
||||
assert(this.data.lengthIndex < primes.length);
|
||||
assert(this.data.array.length == 0
|
||||
|| this.data.array.length == primes[this.data.lengthIndex]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
@ -190,6 +197,13 @@ if (is(typeof(hasher(Key.init)) == size_t))
|
||||
rehash(n);
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
auto hashTable = HashTable!(string, int)(5);
|
||||
assert(hashTable.capacity == 7);
|
||||
}
|
||||
|
||||
/// ditto
|
||||
this(shared Allocator allocator)
|
||||
in
|
||||
@ -198,7 +212,7 @@ if (is(typeof(hasher(Key.init)) == size_t))
|
||||
}
|
||||
do
|
||||
{
|
||||
this.data = HashArray(Buckets(allocator));
|
||||
this.data = HashArray(allocator);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -220,7 +234,7 @@ if (is(typeof(hasher(Key.init)) == size_t))
|
||||
}
|
||||
do
|
||||
{
|
||||
this.data = HashArray(Buckets(init.data, allocator));
|
||||
this.data = HashArray(init.data, allocator);
|
||||
}
|
||||
|
||||
/// ditto
|
||||
@ -232,9 +246,7 @@ if (is(typeof(hasher(Key.init)) == size_t))
|
||||
}
|
||||
do
|
||||
{
|
||||
this.data = HashArray(Buckets(move(init.data), allocator));
|
||||
this.lengthIndex = init.lengthIndex;
|
||||
init.lengthIndex = 0;
|
||||
this.data.move(init.data, allocator);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -261,8 +273,7 @@ if (is(typeof(hasher(Key.init)) == size_t))
|
||||
ref typeof(this) opAssign(S)(S that) @trusted
|
||||
if (is(S == HashTable))
|
||||
{
|
||||
swap(this.data, that.data);
|
||||
swap(this.lengthIndex, that.lengthIndex);
|
||||
this.data.swap(that.data);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -576,3 +587,27 @@ if (is(typeof(hasher(Key.init)) == size_t))
|
||||
static assert(is(const HashTable!(string, int)));
|
||||
static assert(isForwardRange!(HashTable!(string, int).Range));
|
||||
}
|
||||
|
||||
// Constructs by reference
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
auto hashTable1 = HashTable!(string, int)(7);
|
||||
auto hashTable2 = HashTable!(string, int)(hashTable1);
|
||||
assert(hashTable1.length == hashTable2.length);
|
||||
assert(hashTable1.capacity == hashTable2.capacity);
|
||||
}
|
||||
|
||||
// Constructs by value
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
auto hashTable = HashTable!(string, int)(HashTable!(string, int)(7));
|
||||
assert(hashTable.capacity == 7);
|
||||
}
|
||||
|
||||
// Assigns by value
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
HashTable!(string, int) hashTable;
|
||||
hashTable = HashTable!(string, int)(7);
|
||||
assert(hashTable.capacity == 7);
|
||||
}
|
||||
|
@ -194,6 +194,13 @@ if (is(typeof(hasher(T.init)) == size_t))
|
||||
rehash(n);
|
||||
}
|
||||
|
||||
///
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
auto set = Set!int(5);
|
||||
assert(set.capacity == 7);
|
||||
}
|
||||
|
||||
/// ditto
|
||||
this(shared Allocator allocator)
|
||||
in
|
||||
@ -202,7 +209,7 @@ if (is(typeof(hasher(T.init)) == size_t))
|
||||
}
|
||||
do
|
||||
{
|
||||
this.data = HashArray(Buckets(allocator));
|
||||
this.data = HashArray(allocator);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -224,7 +231,7 @@ if (is(typeof(hasher(T.init)) == size_t))
|
||||
}
|
||||
do
|
||||
{
|
||||
this.data = HashArray(Buckets(init.data, allocator));
|
||||
this.data = HashArray(init.data, allocator);
|
||||
}
|
||||
|
||||
/// ditto
|
||||
@ -236,9 +243,7 @@ if (is(typeof(hasher(T.init)) == size_t))
|
||||
}
|
||||
do
|
||||
{
|
||||
this.data = HashArray(Buckets(move(init.data), allocator));
|
||||
this.lengthIndex = init.lengthIndex;
|
||||
init.lengthIndex = 0;
|
||||
this.data.move(init.data, allocator);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -257,7 +262,7 @@ if (is(typeof(hasher(T.init)) == size_t))
|
||||
if (is(Unqual!S == Set))
|
||||
{
|
||||
this.data = that.data;
|
||||
this.lengthIndex = that.lengthIndex;
|
||||
this.data.lengthIndex = that.data.lengthIndex;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -265,8 +270,7 @@ if (is(typeof(hasher(T.init)) == size_t))
|
||||
ref typeof(this) opAssign(S)(S that) @trusted
|
||||
if (is(S == Set))
|
||||
{
|
||||
swap(this.data, that.data);
|
||||
swap(this.lengthIndex, that.lengthIndex);
|
||||
this.data.swap(that.data);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -598,3 +602,27 @@ if (is(typeof(hasher(T.init)) == size_t))
|
||||
auto set = Set!int(8);
|
||||
assert(set.capacity == 13);
|
||||
}
|
||||
|
||||
// Constructs by reference
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
auto set1 = Set!int(7);
|
||||
auto set2 = Set!int(set1);
|
||||
assert(set1.length == set2.length);
|
||||
assert(set1.capacity == set2.capacity);
|
||||
}
|
||||
|
||||
// Constructs by value
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
auto set = Set!int(Set!int(7));
|
||||
assert(set.capacity == 7);
|
||||
}
|
||||
|
||||
// Assigns by value
|
||||
@nogc nothrow pure @safe unittest
|
||||
{
|
||||
Set!int set;
|
||||
set = Set!int(7);
|
||||
assert(set.capacity == 7);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user