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); .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 * Returns bucket position for `hash`. `0` may mean the 0th position or an
* empty `buckets` array. * empty `buckets` array.
*/ */
size_t locateBucket(ref const Key key) const 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) ref Bucket insert(ref Key key)
{ {
while (true) while ((this.lengthIndex + 1) != primes.length)
{ {
auto bucketPosition = locateBucket(key); foreach (ref e; this.array[locateBucket(key) .. $])
foreach (ref e; this.array[bucketPosition .. $])
{ {
if (e == 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)) if (this.rehashToSize(this.lengthIndex + 1))
{ {
++this.lengthIndex; ++this.lengthIndex;
} }
} }
this.array.insertBack(Bucket(key));
return this.array[$ - 1];
} }
// Takes an index in the primes array. // Takes an index in the primes array.
@ -221,7 +225,7 @@ package struct HashArray(alias hasher, K, V = void)
{ {
if (e1.status == BucketStatus.used) if (e1.status == BucketStatus.used)
{ {
auto bucketPosition = hasher(e1.key) % storage.length; auto bucketPosition = hasher(e1.key) % primes[n];
foreach (ref e2; storage[bucketPosition .. $]) foreach (ref e2; storage[bucketPosition .. $])
{ {
@ -267,8 +271,7 @@ package struct HashArray(alias hasher, K, V = void)
size_t remove(ref Key key) size_t remove(ref Key key)
{ {
auto bucketPosition = locateBucket(key); foreach (ref e; this.array[locateBucket(key) .. $])
foreach (ref e; this.array[bucketPosition .. $])
{ {
if (e == key) // Found. 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 bool opBinaryRight(string op : "in")(ref inout(Key) key) inout
{ {
auto bucketPosition = locateBucket(key); foreach (ref e; this.array[locateBucket(key) .. $])
foreach (ref e; this.array[bucketPosition .. $])
{ {
if (e == key) // Found. if (e == key) // Found.
{ {

View File

@ -194,7 +194,7 @@ if (is(typeof(hasher(Key.init)) == size_t))
do do
{ {
this(allocator); 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)) if (is(Unqual!S == HashTable))
{ {
this.data = that.data; this.data = that.data;
this.data.lengthIndex = that.data.lengthIndex;
return this; return this;
} }
@ -604,6 +603,16 @@ if (is(typeof(hasher(Key.init)) == size_t))
assert(hashTable.capacity == 7); 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 // Assigns by value
@nogc nothrow pure @safe unittest @nogc nothrow pure @safe unittest
{ {
@ -611,3 +620,14 @@ if (is(typeof(hasher(Key.init)) == size_t))
hashTable = HashTable!(string, int)(7); hashTable = HashTable!(string, int)(7);
assert(hashTable.capacity == 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 do
{ {
this(allocator); 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)) if (is(Unqual!S == Set))
{ {
this.data = that.data; this.data = that.data;
this.data.lengthIndex = that.data.lengthIndex;
return this; return this;
} }
@ -619,6 +618,16 @@ if (is(typeof(hasher(T.init)) == size_t))
assert(set.capacity == 7); 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 // Assigns by value
@nogc nothrow pure @safe unittest @nogc nothrow pure @safe unittest
{ {
@ -626,3 +635,14 @@ if (is(typeof(hasher(T.init)) == size_t))
set = Set!int(7); set = Set!int(7);
assert(set.capacity == 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);
}