Browse Source

Squashed commit of the following:

commit dd6f236b360640b4c5ca2bfefdddf11482ab1bcf
Author: Anton Tarasenko <dkanus@gmail.com>
Date:   Mon Jul 4 03:55:45 2022 +0700

    Change `AcediaConfig` to use new collections
pull/8/head
Anton Tarasenko 2 years ago
parent
commit
8cfc42eda4
  1. 43
      sources/Avarice/Avarice.uc
  2. 14
      sources/Commands/Commands.uc
  3. 63
      sources/Config/AcediaConfig.uc
  4. 10
      sources/Config/Tests/MockConfig.uc
  5. 10
      sources/Config/Tests/TEST_AcediaConfig.uc
  6. 24
      sources/Data/Collections/ArrayList.uc
  7. 1
      sources/Data/Collections/HashTable.uc

43
sources/Avarice/Avarice.uc

@ -43,58 +43,67 @@ var public config array<AvariceLinkRecord> link;
// connection too long.
var public config float reconnectTime;
protected function AssociativeArray ToData()
protected function HashTable ToData()
{
local int i;
local AssociativeArray data;
local AssociativeArray linkData;
local DynamicArray linksArray;
data = __().collections.EmptyAssociativeArray();
local int i;
local Text nextValue;
local HashTable data;
local HashTable linkData;
local ArrayList linksArray;
data = __().collections.EmptyHashTable();
data.SetFloat(P("reconnectTime"), reconnectTime, true);
linksArray = __().collections.EmptyDynamicArray();
linksArray = __().collections.EmptyArrayList();
data.SetItem(P("link"), linksArray);
for (i = 0; i < link.length; i += 1)
{
linkData = __().collections.EmptyAssociativeArray();
linkData.SetItem(P("name"), __().text.FromString(link[i].name));
linkData.SetItem(P("address"), __().text.FromString(link[i].address));
linkData = __().collections.EmptyHashTable();
nextValue = __().text.FromString(link[i].name);
linkData.SetItem(P("name"), nextValue);
nextValue.FreeSelf();
nextValue = __().text.FromString(link[i].address);
linkData.SetItem(P("address"), nextValue);
nextValue.FreeSelf();
linksArray.AddItem(linkData);
linkData.FreeSelf();
}
linksArray.FreeSelf();
return data;
}
protected function FromData(AssociativeArray source)
protected function FromData(HashTable source)
{
local int i;
local Text nextText;
local DynamicArray linksArray;
local AssociativeArray nextLink;
local ArrayList linksArray;
local HashTable nextLink;
local AvariceLinkRecord nextRecord;
if (source == none) {
return;
}
reconnectTime = source.GetFloat(P("reconnectTime"));
link.length = 0;
linksArray = source.GetDynamicArray(P("link"));
linksArray = source.GetArrayList(P("link"));
if (linksArray == none) {
return;
}
for (i = 0; i < linksArray.GetLength(); i += 1)
{
nextLink = linksArray.GetAssociativeArray(i);
nextLink = linksArray.GetHashTable(i);
if (nextLink == none) {
continue;
}
nextText = nextLink.GetText(P("name"));
if (nextText != none) {
nextRecord.name = nextText.ToString();
nextRecord.name = __().text.ToString(nextText);
}
nextText = nextLink.GetText(P("address"));
if (nextText != none) {
nextRecord.address = nextText.ToString();
nextRecord.address = __().text.ToString(nextText);
}
link[i] = nextRecord;
_.memory.Free(nextLink);
}
_.memory.Free(linksArray);
}
protected function DefaultIt()

14
sources/Commands/Commands.uc

@ -25,18 +25,20 @@ var public config bool useChatInput;
var public config bool useMutateInput;
var public config string chatCommandPrefix;
protected function AssociativeArray ToData()
protected function HashTable ToData()
{
local AssociativeArray data;
data = __().collections.EmptyAssociativeArray();
local Text chatPrefix;
local HashTable data;
data = __().collections.EmptyHashTable();
data.SetBool(P("useChatInput"), useChatInput, true);
data.SetBool(P("useMutateInput"), useMutateInput, true);
data.SetItem( P("chatCommandPrefix"),
_.text.FromString(chatCommandPrefix), true);
chatPrefix = _.text.FromString(chatCommandPrefix);
data.SetItem(P("chatCommandPrefix"), chatPrefix);
_.memory.Free(chatPrefix);
return data;
}
protected function FromData(AssociativeArray source)
protected function FromData(HashTable source)
{
local Text newChatPrefix;
if (source == none) {

63
sources/Config/AcediaConfig.uc

@ -8,7 +8,7 @@
* is that "<config_object_name>" must be considered *valid* by
* `BaseText.IsValidName()` standards, otherwise method will return `none`.
*
* Copyright 2021 Anton Tarasenko
* Copyright 2021-2022 Anton Tarasenko
*------------------------------------------------------------------------------
* This file is part of Acedia.
*
@ -26,7 +26,7 @@
* along with Acedia. If not, see <https://www.gnu.org/licenses/>.
*/
class AcediaConfig extends AcediaObject
dependson(AssociativeArray)
dependson(HashTable)
abstract;
/**
@ -65,7 +65,7 @@ class AcediaConfig extends AcediaObject
// In case it has a `none` value stored under some key - it means that value
// was detected in config, but not yet loaded.
// Only its default value is ever used.
var private AssociativeArray existingConfigs;
var private HashTable existingConfigs;
// Stores name of the config where settings are to be stored.
// Must correspond to value in `config(...)` modifier in class definition.
@ -79,10 +79,10 @@ var public const bool supportsDataConversion;
/**
* These methods must be overloaded to store and load all the config
* variables inside an `AssociativeArray` collection. How exactly to store
* variables inside an `HashTable` collection. How exactly to store
* them is up to each config class to decide, as long as it allows conversion
* into JSON (see `JSONAPI.IsCompatible()` for details).
* Note that `AssociativeArray` reference `FromData()` receives is
* Note that `HashTable` reference `FromData()` receives is
* not necessarily the same one your `ToData()` method returns - any particular
* value boxes can be replaced with value references and vice versa.
* NOTE: DO NOT use `P()`, `C()`, `F()` or `T()` methods for keys or
@ -90,8 +90,8 @@ var public const bool supportsDataConversion;
* deallocated when necessary, so these methods for creating `Text` values are
* not suitable.
*/
protected function AssociativeArray ToData() { return none; }
protected function FromData(AssociativeArray source) {}
protected function HashTable ToData() { return none; }
protected function FromData(HashTable source) {}
/**
* This method must be overloaded to setup default values for all config
@ -99,12 +99,6 @@ protected function FromData(AssociativeArray source) {}
*/
protected function DefaultIt() {}
protected static function StaticFinalizer()
{
__().memory.Free(default.existingConfigs);
default.existingConfigs = none;
}
/**
* This reads all of the `AcediaConfig`'s settings objects into internal
* storage. Must be called before any other methods. Actual loading might be
@ -113,12 +107,12 @@ protected static function StaticFinalizer()
public static function Initialize()
{
local int i;
local Text nextName;
local Text nextName, lowerName;
local array<string> names;
if (default.existingConfigs != none) {
return;
}
default.existingConfigs = __().collections.EmptyAssociativeArray();
default.existingConfigs = __().collections.EmptyHashTable();
names = GetPerObjectNames( default.configName, string(default.class.name),
MaxInt);
for (i = 0; i < names.length; i += 1)
@ -127,8 +121,11 @@ public static function Initialize()
continue;
}
nextName = __().text.FromString(NameToActualVersion(names[i]));
if (nextName.IsValidName()) {
default.existingConfigs.SetItem(nextName.LowerCopy(), none);
if (nextName.IsValidName())
{
lowerName = nextName.LowerCopy();
default.existingConfigs.SetItem(lowerName, none);
lowerName.FreeSelf();
}
nextName.FreeSelf();
}
@ -178,6 +175,7 @@ public final static function bool NewConfig(BaseText name)
newConfig.DefaultIt();
newConfig.SaveConfig();
default.existingConfigs.SetItem(name, newConfig);
name.FreeSelf();
return true;
}
@ -214,15 +212,16 @@ public final static function bool Exists(BaseText name)
*/
public final static function DeleteConfig(BaseText name)
{
local AssociativeArray.Entry entry;
if (default.existingConfigs == none) {
return;
}
entry = default.existingConfigs.TakeEntry(name);
if (entry.value != none) {
entry.value.ClearConfig();
local AcediaObject value;
if (name == none) return;
if (default.existingConfigs == none) return;
name = name.LowerCopy();
value = default.existingConfigs.TakeItem(name);
if (value != none) {
value.ClearConfig();
}
__().memory.Free(entry.key);
__().memory.Free(name);
}
/**
@ -235,7 +234,7 @@ public static function array<Text> AvailableConfigs()
{
local array<Text> emptyResult;
if (default.existingConfigs != none) {
return default.existingConfigs.CopyTextKeys();
return default.existingConfigs.GetTextKeys();
}
return emptyResult;
}
@ -250,7 +249,7 @@ public static function array<Text> AvailableConfigs()
*/
public final static function AcediaConfig GetConfigInstance(BaseText name)
{
local AssociativeArray.Entry configEntry;
local HashTable.Entry configEntry;
if (name == none) return none;
if (!name.IsValidName()) return none;
if (default.existingConfigs == none) return none;
@ -265,6 +264,8 @@ public final static function AcediaConfig GetConfigInstance(BaseText name)
default.existingConfigs.SetItem(configEntry.key, configEntry.value);
}
__().memory.Free(name);
// We return value, so do not deallocate it
__().memory.Free(configEntry.key);
return AcediaConfig(configEntry.value);
}
@ -284,10 +285,10 @@ public final static function AcediaConfig GetConfigInstance(BaseText name)
* For correctly implemented config objects should only return `none` if
* their class was not yet initialized (see `self.Initialize()` method).
*/
public final static function AssociativeArray LoadData(BaseText name)
public final static function HashTable LoadData(BaseText name)
{
local AssociativeArray result;
local AcediaConfig requiredConfig;
local HashTable result;
local AcediaConfig requiredConfig;
requiredConfig = GetConfigInstance(name);
if (requiredConfig != none) {
result = requiredConfig.ToData();
@ -309,7 +310,7 @@ public final static function AssociativeArray LoadData(BaseText name)
* allows for JSON deserialization (see `JSONAPI.IsCompatible()` for
* details).
*/
public final static function SaveData(BaseText name, AssociativeArray data)
public final static function SaveData(BaseText name, HashTable data)
{
local AcediaConfig requiredConfig;
requiredConfig = GetConfigInstance(name);

10
sources/Config/Tests/MockConfig.uc

@ -1,6 +1,6 @@
/**
* Mock object for testing config functionality of Acedia's `Feature`s.
* Copyright 2021 Anton Tarasenko
* Copyright 2021-2022 Anton Tarasenko
*------------------------------------------------------------------------------
* This file is part of Acedia.
*
@ -23,15 +23,15 @@ class MockConfig extends AcediaConfig
var public config int value;
protected function AssociativeArray ToData()
protected function HashTable ToData()
{
local AssociativeArray data;
data = __().collections.EmptyAssociativeArray();
local HashTable data;
data = __().collections.EmptyHashTable();
data.SetInt(P("value").Copy(), value, true);
return data;
}
protected function FromData(AssociativeArray source)
protected function FromData(HashTable source)
{
if (source != none) {
value = source.GetIntBy(P("/value"));

10
sources/Config/Tests/TEST_AcediaConfig.uc

@ -1,6 +1,6 @@
/**
* Set of tests for `AcediaConfig` class.
* Copyright 2021 Anton Tarasenko
* Copyright 2021-2022 Anton Tarasenko
*------------------------------------------------------------------------------
* This file is part of Acedia.
*
@ -68,19 +68,19 @@ protected static function TEST_AvailableConfigs()
protected static function TEST_DataGetSet()
{
local AssociativeArray data, newData;
local HashTable data, newData;
data = class'MockConfig'.static.LoadData(P("other"));
Issue("Wrong value is loaded from config.");
TEST_ExpectTrue(data.GetIntBy(P("/value")) == 11);
newData = __().collections.EmptyAssociativeArray();
newData = __().collections.EmptyHashTable();
newData.SetItem(P("value"), __().box.int(903));
class'MockConfig'.static.SaveData(P("other"), newData);
data = class'MockConfig'.static.LoadData(P("other"));
Issue("Wrong value is loaded from config after saving another value.");
TEST_ExpectTrue(data.GetIntBy(P("/value")) == 903);
Issue("`AcediaConfig` returns `AssociativeArray` reference that was"
Issue("`AcediaConfig` returns `HashTable` reference that was"
@ "passed in `SaveData()` call instead of a new collection.");
TEST_ExpectTrue(data != newData);
@ -91,7 +91,7 @@ protected static function TEST_DataGetSet()
protected static function TEST_DataNew()
{
local AssociativeArray data;
local HashTable data;
Issue("Creating new config with existing name succeeds.");
TEST_ExpectFalse(class'MockConfig'.static.NewConfig(P("another.config")));
data = class'MockConfig'.static.LoadData(P("another.config"));

24
sources/Data/Collections/ArrayList.uc

@ -870,6 +870,30 @@ public final function ArrayList GetArrayList(int index)
return result;
}
/**
* Returns `HashTable` item at `index`. If index is invalid or
* stores a non-`HashTable` value, returns `none`.
*
* Referred value must be stored as `Text` (or one of it's sub-classes,
* such as `MutableText`) for this method to work.
*
* @param index Index of a `HashTable` item that caller `ArrayList`
* has to return.
* @return `HashTable` value at `index` in the caller `ArrayList`.
* `none` if passed `index` is invalid or non-`HashTable` value
* is stored there.
*/
public final function HashTable GetHashTable(int index)
{
local HashTable result;
result = HashTable(BorrowItem(index));
if (result != none) {
result.NewRef();
}
return result;
}
defaultproperties
{
iteratorClass = class'ArrayListIterator'

1
sources/Data/Collections/HashTable.uc

@ -388,6 +388,7 @@ public final function HashTable SetItem(
storedElementCount += 1;
}
key.NewRef();
_.memory.Free(oldEntry.key);
newEntry.key = key;
newEntry.value = value;
if (value != none) {

Loading…
Cancel
Save