HashTable/Set: Add proper assignment

This commit is contained in:
Eugen Wissner 2018-05-20 21:58:15 +02:00
parent 9efbc9d5e0
commit c268696ee9
3 changed files with 61 additions and 19 deletions

View File

@ -164,13 +164,22 @@ package struct HashArray(alias hasher, K, V = void)
.swap(this.length, data.length);
}
void opAssign(ref typeof(this) that)
{
this.array = that.array;
this.lengthIndex = that.lengthIndex;
this.length = that.length;
}
/*
* Returns bucket position for `hash`. `0` may mean the 0th position or an
* empty `buckets` array.
*/
size_t locateBucket(ref const Key key) const
{
return this.array.length == 0 ? 0 : hasher(key) % this.array.length;
return this.array.length == 0
? 0
: hasher(key) % primes[this.lengthIndex];
}
/*
@ -179,11 +188,9 @@ package struct HashArray(alias hasher, K, V = void)
*/
ref Bucket insert(ref Key key)
{
while (true)
while ((this.lengthIndex + 1) != primes.length)
{
auto bucketPosition = locateBucket(key);
foreach (ref e; this.array[bucketPosition .. $])
foreach (ref e; this.array[locateBucket(key) .. $])
{
if (e == key)
{
@ -196,16 +203,13 @@ package struct HashArray(alias hasher, K, V = void)
}
}
if (primes.length == (this.lengthIndex + 1))
{
this.array.insertBack(Bucket(key));
return this.array[$ - 1];
}
if (this.rehashToSize(this.lengthIndex + 1))
{
++this.lengthIndex;
}
}
this.array.insertBack(Bucket(key));
return this.array[$ - 1];
}
// Takes an index in the primes array.
@ -221,7 +225,7 @@ package struct HashArray(alias hasher, K, V = void)
{
if (e1.status == BucketStatus.used)
{
auto bucketPosition = hasher(e1.key) % storage.length;
auto bucketPosition = hasher(e1.key) % primes[n];
foreach (ref e2; storage[bucketPosition .. $])
{
@ -267,8 +271,7 @@ package struct HashArray(alias hasher, K, V = void)
size_t remove(ref Key key)
{
auto bucketPosition = locateBucket(key);
foreach (ref e; this.array[bucketPosition .. $])
foreach (ref e; this.array[locateBucket(key) .. $])
{
if (e == key) // Found.
{
@ -286,8 +289,7 @@ package struct HashArray(alias hasher, K, V = void)
bool opBinaryRight(string op : "in")(ref inout(Key) key) inout
{
auto bucketPosition = locateBucket(key);
foreach (ref e; this.array[bucketPosition .. $])
foreach (ref e; this.array[locateBucket(key) .. $])
{
if (e == key) // Found.
{

View File

@ -194,7 +194,7 @@ if (is(typeof(hasher(Key.init)) == size_t))
do
{
this(allocator);
rehash(n);
this.data.rehash(n);
}
///
@ -265,7 +265,6 @@ if (is(typeof(hasher(Key.init)) == size_t))
if (is(Unqual!S == HashTable))
{
this.data = that.data;
this.data.lengthIndex = that.data.lengthIndex;
return this;
}
@ -604,6 +603,16 @@ if (is(typeof(hasher(Key.init)) == size_t))
assert(hashTable.capacity == 7);
}
// Assigns by reference
@nogc nothrow pure @safe unittest
{
auto hashTable1 = HashTable!(string, int)(7);
HashTable!(string, int) hashTable2;
hashTable1 = hashTable2;
assert(hashTable1.length == hashTable2.length);
assert(hashTable1.capacity == hashTable2.capacity);
}
// Assigns by value
@nogc nothrow pure @safe unittest
{
@ -611,3 +620,14 @@ if (is(typeof(hasher(Key.init)) == size_t))
hashTable = HashTable!(string, int)(7);
assert(hashTable.capacity == 7);
}
// Postblit copies
@nogc nothrow pure @safe unittest
{
auto hashTable = HashTable!(string, int)(7);
void testFunc(HashTable!(string, int) hashTable)
{
assert(hashTable.capacity == 7);
}
testFunc(hashTable);
}

View File

@ -191,7 +191,7 @@ if (is(typeof(hasher(T.init)) == size_t))
do
{
this(allocator);
rehash(n);
this.data.rehash(n);
}
///
@ -262,7 +262,6 @@ if (is(typeof(hasher(T.init)) == size_t))
if (is(Unqual!S == Set))
{
this.data = that.data;
this.data.lengthIndex = that.data.lengthIndex;
return this;
}
@ -619,6 +618,16 @@ if (is(typeof(hasher(T.init)) == size_t))
assert(set.capacity == 7);
}
// Assigns by reference
@nogc nothrow pure @safe unittest
{
auto set1 = Set!int(7);
Set!int set2;
set1 = set2;
assert(set1.length == set2.length);
assert(set1.capacity == set2.capacity);
}
// Assigns by value
@nogc nothrow pure @safe unittest
{
@ -626,3 +635,14 @@ if (is(typeof(hasher(T.init)) == size_t))
set = Set!int(7);
assert(set.capacity == 7);
}
// Postblit copies
@nogc nothrow pure @safe unittest
{
auto set = Set!int(7);
void testFunc(Set!int set)
{
assert(set.capacity == 7);
}
testFunc(set);
}