Browse Source

Add `AssociativeArray` ability to deallocate keys

`AssociativeArray` by design does not manage keys, automatically
deallocating them, like it can with stored values. This patch adds a
parameter to `Empty()` method that allows it to deallocate all of the
used keys when deallocation all of the values.

As a side effect this patch also fixes a bug that broke
`AssociativeArray` after using `Empty()` method.
pull/8/head
Anton Tarasenko 4 years ago
parent
commit
a233bf0e4b
  1. 18
      sources/Data/Collections/AssociativeArray.uc
  2. 29
      sources/Data/Collections/Tests/TEST_AssociativeArray.uc

18
sources/Data/Collections/AssociativeArray.uc

@ -424,9 +424,14 @@ public final function AssociativeArray RemoveItem(AcediaObject key)
* Completely clears caller `AssociativeArray` of all stored entries, * Completely clears caller `AssociativeArray` of all stored entries,
* deallocating any stored managed values. * deallocating any stored managed values.
* *
* @param deallocateKeys Setting this to `true` will force this method to
* also deallocate all keys from the caller `AssociativeArray`.
* Since we do not record whether `AssociativeArray` manages keys like it
* does values - all keys will be deallocated, so use this parameter with
* caution.
* @return Caller `AssociativeArray` to allow for method chaining. * @return Caller `AssociativeArray` to allow for method chaining.
*/ */
public function Empty() public function Empty(optional bool deallocateKeys)
{ {
local int i, j; local int i, j;
local array<Entry> nextEntries; local array<Entry> nextEntries;
@ -439,9 +444,19 @@ public function Empty()
if (nextEntries[j].value == none) continue; if (nextEntries[j].value == none) continue;
nextEntries[j].value.FreeSelf(nextEntries[j].valueLifeVersion); nextEntries[j].value.FreeSelf(nextEntries[j].valueLifeVersion);
} }
if (deallocateKeys)
{
for (j = 0; j < nextEntries.length; j += 1)
{
if (nextEntries[j].key != none) {
nextEntries[j].key.FreeSelf(nextEntries[j].keyLifeVersion);
}
}
}
} }
hashTable.length = 0; hashTable.length = 0;
storedElementCount = 0; storedElementCount = 0;
UpdateHashTableCapacity();
} }
/** /**
@ -458,7 +473,6 @@ public final function array<AcediaObject> GetKeys()
local array<Entry> nextEntry; local array<Entry> nextEntry;
for (i = 0; i < hashTable.length; i += 1) for (i = 0; i < hashTable.length; i += 1)
{ {
//hashTable[i] = CleanBucket(hashTable[i]);
CleanBucket(hashTable[i]); CleanBucket(hashTable[i]);
nextEntry = hashTable[i].entries; nextEntry = hashTable[i].entries;
for (j = 0; j < nextEntry.length; j += 1) { for (j = 0; j < nextEntry.length; j += 1) {

29
sources/Data/Collections/Tests/TEST_AssociativeArray.uc

@ -183,16 +183,39 @@ protected static function Test_CreateItem()
protected static function Test_Empty() protected static function Test_Empty()
{ {
local AcediaObject key1, key2, key3;
local AssociativeArray array; local AssociativeArray array;
key1 = __().text.FromString("key");
key2 = __().box.int(13);
key3 = __().box.float(345.2);
array = AssociativeArray(__().memory.Allocate(class'AssociativeArray')); array = AssociativeArray(__().memory.Allocate(class'AssociativeArray'));
array.SetItem(key1, __().text.FromString("value"));
array.SetItem(key2, __().text.FromString("value #2"), true);
array.SetItem(key3, __().box.bool(true));
Context("Testing `Empty()` method for `AssociativeArray`."); Context("Testing `Empty()` method for `AssociativeArray`.");
array.SetItem(__().text.FromString("key"), __().text.FromString("value"));
array.SetItem(__().box.int(13), __().text.FromString("value #2"));
array.SetItem(__().box.float(345.2), __().box.bool(true));
Issue("`AssociativeArray` still contains elements after being emptied."); Issue("`AssociativeArray` still contains elements after being emptied.");
array.Empty(); array.Empty();
TEST_ExpectTrue(array.GetKeys().length == 0); TEST_ExpectTrue(array.GetKeys().length == 0);
TEST_ExpectTrue(array.GetLength() == 0); TEST_ExpectTrue(array.GetLength() == 0);
Issue("`AssociativeArray` deallocated keys when not being told to do so.");
TEST_ExpectTrue(key1.IsAllocated());
TEST_ExpectTrue(key2.IsAllocated());
TEST_ExpectTrue(key3.IsAllocated());
Issue("`AssociativeArray` still contains elements after being emptied.");
array.SetItem(key1, __().text.FromString("value"), true);
array.SetItem(key2, __().text.FromString("value #2"));
array.SetItem(key3, __().box.bool(true), true);
array.Empty(true);
TEST_ExpectTrue(array.GetKeys().length == 0);
TEST_ExpectTrue(array.GetLength() == 0);
Issue("`AssociativeArray` does not deallocate keys when told to do so.");
TEST_ExpectFalse(key1.IsAllocated());
TEST_ExpectFalse(key2.IsAllocated());
TEST_ExpectFalse(key3.IsAllocated());
} }
protected static function Test_Length() protected static function Test_Length()

Loading…
Cancel
Save