Browse Source

Refactor commands to use new collections

pull/8/head
Anton Tarasenko 2 years ago
parent
commit
fbe1ffd265
  1. 22
      sources/Commands/BuiltInCommands/ACommandHelp.uc
  2. 12
      sources/Commands/Command.uc
  3. 28
      sources/Commands/CommandDataBuilder.uc
  4. 97
      sources/Commands/CommandParser.uc
  5. 80
      sources/Commands/Tests/TEST_Command.uc
  6. 4
      sources/Commands/Tests/TEST_CommandDataBuilder.uc

22
sources/Commands/BuiltInCommands/ACommandHelp.uc

@ -42,8 +42,8 @@ protected function BuildData(CommandDataBuilder builder)
protected function Executed(Command.CallData callData, EPlayer callerPlayer) protected function Executed(Command.CallData callData, EPlayer callerPlayer)
{ {
local AssociativeArray parameters, options;; local HashTable parameters, options;;
local DynamicArray commandsToDisplay; local ArrayList commandsToDisplay;
parameters = callData.parameters; parameters = callData.parameters;
options = callData.options; options = callData.options;
// Print command list if "--list" option was specified // Print command list if "--list" option was specified
@ -57,8 +57,9 @@ protected function Executed(Command.CallData callData, EPlayer callerPlayer)
// print a help page for this command. // print a help page for this command.
if (!options.HasKey(P("list")) || parameters.HasKey(P("commands"))) if (!options.HasKey(P("list")) || parameters.HasKey(P("commands")))
{ {
commandsToDisplay = DynamicArray(parameters.GetItem(P("commands"))); commandsToDisplay = parameters.GetArrayList(P("commands"));
DisplayCommandHelpPages(callerPlayer, commandsToDisplay); DisplayCommandHelpPages(callerPlayer, commandsToDisplay);
_.memory.Free(commandsToDisplay);
} }
} }
@ -82,7 +83,7 @@ private final function DisplayCommandList(EPlayer player)
nextCommand = commandsFeature.GetCommand(commandNames[i]); nextCommand = commandsFeature.GetCommand(commandNames[i]);
if (nextCommand == none) continue; if (nextCommand == none) continue;
nextData = nextCommand.GetData(); nextData = nextCommand.BorrowData();
console.UseColor(_.color.textEmphasis) console.UseColor(_.color.textEmphasis)
.Write(nextData.name) .Write(nextData.name)
.ResetColor() .ResetColor()
@ -93,10 +94,11 @@ private final function DisplayCommandList(EPlayer player)
} }
private final function DisplayCommandHelpPages( private final function DisplayCommandHelpPages(
EPlayer player, EPlayer player,
DynamicArray commandList) ArrayList commandList)
{ {
local int i; local int i;
local Text nextCommandName;
local Command nextCommand; local Command nextCommand;
local Commands_Feature commandsFeature; local Commands_Feature commandsFeature;
if (player == none) return; if (player == none) return;
@ -107,15 +109,17 @@ private final function DisplayCommandHelpPages(
// If arguments were empty - at least display our own help page // If arguments were empty - at least display our own help page
if (commandList == none) if (commandList == none)
{ {
PrintHelpPage(player.BorrowConsole(), GetData()); PrintHelpPage(player.BorrowConsole(), BorrowData());
return; return;
} }
// Otherwise - print help for specified commands // Otherwise - print help for specified commands
for (i = 0; i < commandList.GetLength(); i += 1) for (i = 0; i < commandList.GetLength(); i += 1)
{ {
nextCommand = commandsFeature.GetCommand(Text(commandList.GetItem(i))); nextCommandName = commandList.GetText(i);
nextCommand = commandsFeature.GetCommand(nextCommandName);
_.memory.Free(nextCommandName);
if (nextCommand == none) continue; if (nextCommand == none) continue;
PrintHelpPage(player.BorrowConsole(), nextCommand.GetData()); PrintHelpPage(player.BorrowConsole(), nextCommand.BorrowData());
} }
} }

12
sources/Commands/Command.uc

@ -70,8 +70,8 @@ struct CallData
// Specified sub-command and parameters/options // Specified sub-command and parameters/options
var public Text subCommandName; var public Text subCommandName;
// Provided parameters and specified options // Provided parameters and specified options
var public AssociativeArray parameters; var public HashTable parameters;
var public AssociativeArray options; var public HashTable options;
// Errors that occurred during command call processing are described by // Errors that occurred during command call processing are described by
// error type and optional error textual name of the object // error type and optional error textual name of the object
// (parameter, option, etc.) that caused it. // (parameter, option, etc.) that caused it.
@ -94,9 +94,9 @@ enum ParameterType
CPT_Text, CPT_Text,
// Special parameter that consumes the rest of the input into `Text` // Special parameter that consumes the rest of the input into `Text`
CPT_Remainder, CPT_Remainder,
// Parses into `AssociativeArray` // Parses into `HashTable`
CPT_Object, CPT_Object,
// Parses into `DynamicArray` // Parses into `ArrayList`
CPT_Array CPT_Array
}; };
@ -202,7 +202,7 @@ protected function Constructor()
dataBuilder = dataBuilder =
CommandDataBuilder(_.memory.Allocate(class'CommandDataBuilder')); CommandDataBuilder(_.memory.Allocate(class'CommandDataBuilder'));
BuildData(dataBuilder); BuildData(dataBuilder);
commandData = dataBuilder.GetData(); commandData = dataBuilder.BorrowData();
dataBuilder.FreeSelf(); dataBuilder.FreeSelf();
dataBuilder = none; dataBuilder = none;
} }
@ -577,7 +577,7 @@ public final function Text GetName()
* so deallocating any objects in the returned `struct` would lead to * so deallocating any objects in the returned `struct` would lead to
* undefined behavior. * undefined behavior.
*/ */
public final function Data GetData() public final function Data BorrowData()
{ {
return commandData; return commandData;
} }

28
sources/Commands/CommandDataBuilder.uc

@ -540,7 +540,7 @@ public final function CommandDataBuilder OptionalParams()
* @return Returns the caller `CommandDataBuilder` to allow for * @return Returns the caller `CommandDataBuilder` to allow for
* method chaining. * method chaining.
*/ */
public final function Command.Data GetData() public final function Command.Data BorrowData()
{ {
local Command.Data newData; local Command.Data newData;
RecordSelection(); RecordSelection();
@ -594,7 +594,7 @@ private final function Command.Parameter NewParameter(
* this setting only affects how parameter will be displayed in * this setting only affects how parameter will be displayed in
* generated help. * generated help.
* @param variableName Name of the variable that will store this * @param variableName Name of the variable that will store this
* parameter's value in `AssociativeArray` after user's command input * parameter's value in `HashTable` after user's command input
* is parsed. Provided value will be copied. * is parsed. Provided value will be copied.
* If left `none`, - will coincide with `name` parameter. * If left `none`, - will coincide with `name` parameter.
* @return Returns the caller `CommandDataBuilder` to allow for * @return Returns the caller `CommandDataBuilder` to allow for
@ -629,7 +629,7 @@ public final function CommandDataBuilder ParamBoolean(
* this setting only affects how parameter will be displayed in * this setting only affects how parameter will be displayed in
* generated help. * generated help.
* @param variableName Name of the variable that will store this * @param variableName Name of the variable that will store this
* parameter's value in `AssociativeArray` after user's command input * parameter's value in `HashTable` after user's command input
* is parsed. Provided value will be copied. * is parsed. Provided value will be copied.
* If left `none`, - will coincide with `name` parameter. * If left `none`, - will coincide with `name` parameter.
* @return Returns the caller `CommandDataBuilder` to allow for * @return Returns the caller `CommandDataBuilder` to allow for
@ -660,7 +660,7 @@ public final function CommandDataBuilder ParamBooleanList(
* @param name Name of the parameter, will be copied * @param name Name of the parameter, will be copied
* (as it would appear in the generated help info). * (as it would appear in the generated help info).
* @param variableName Name of the variable that will store this * @param variableName Name of the variable that will store this
* parameter's value in `AssociativeArray` after user's command input * parameter's value in `HashTable` after user's command input
* is parsed. Provided value will be copied. * is parsed. Provided value will be copied.
* If left `none`, - will coincide with `name` parameter. * If left `none`, - will coincide with `name` parameter.
* @return Returns the caller `CommandDataBuilder` to allow for * @return Returns the caller `CommandDataBuilder` to allow for
@ -687,7 +687,7 @@ public final function CommandDataBuilder ParamInteger(
* @param name Name of the parameter, will be copied * @param name Name of the parameter, will be copied
* (as it would appear in the generated help info). * (as it would appear in the generated help info).
* @param variableName Name of the variable that will store this * @param variableName Name of the variable that will store this
* parameter's value in `AssociativeArray` after user's command input * parameter's value in `HashTable` after user's command input
* is parsed. Provided value will be copied. * is parsed. Provided value will be copied.
* If left `none`, - will coincide with `name` parameter. * If left `none`, - will coincide with `name` parameter.
* @return Returns the caller `CommandDataBuilder` to allow for * @return Returns the caller `CommandDataBuilder` to allow for
@ -714,7 +714,7 @@ public final function CommandDataBuilder ParamIntegerList(
* @param name Name of the parameter, will be copied * @param name Name of the parameter, will be copied
* (as it would appear in the generated help info). * (as it would appear in the generated help info).
* @param variableName Name of the variable that will store this * @param variableName Name of the variable that will store this
* parameter's value in `AssociativeArray` after user's command input * parameter's value in `HashTable` after user's command input
* is parsed. Provided value will be copied. * is parsed. Provided value will be copied.
* If left `none`, - will coincide with `name` parameter. * If left `none`, - will coincide with `name` parameter.
* @return Returns the caller `CommandDataBuilder` to allow for * @return Returns the caller `CommandDataBuilder` to allow for
@ -741,7 +741,7 @@ public final function CommandDataBuilder ParamNumber(
* @param name Name of the parameter, will be copied * @param name Name of the parameter, will be copied
* (as it would appear in the generated help info). * (as it would appear in the generated help info).
* @param variableName Name of the variable that will store this * @param variableName Name of the variable that will store this
* parameter's value in `AssociativeArray` after user's command input * parameter's value in `HashTable` after user's command input
* is parsed. Provided value will be copied. * is parsed. Provided value will be copied.
* If left `none`, - will coincide with `name` parameter. * If left `none`, - will coincide with `name` parameter.
* @return Returns the caller `CommandDataBuilder` to allow for * @return Returns the caller `CommandDataBuilder` to allow for
@ -768,7 +768,7 @@ public final function CommandDataBuilder ParamNumberList(
* @param name Name of the parameter, will be copied * @param name Name of the parameter, will be copied
* (as it would appear in the generated help info). * (as it would appear in the generated help info).
* @param variableName Name of the variable that will store this * @param variableName Name of the variable that will store this
* parameter's value in `AssociativeArray` after user's command input * parameter's value in `HashTable` after user's command input
* is parsed. Provided value will be copied. * is parsed. Provided value will be copied.
* If left `none`, - will coincide with `name` parameter. * If left `none`, - will coincide with `name` parameter.
* @return Returns the caller `CommandDataBuilder` to allow for * @return Returns the caller `CommandDataBuilder` to allow for
@ -795,7 +795,7 @@ public final function CommandDataBuilder ParamText(
* @param name Name of the parameter, will be copied * @param name Name of the parameter, will be copied
* (as it would appear in the generated help info). * (as it would appear in the generated help info).
* @param variableName Name of the variable that will store this * @param variableName Name of the variable that will store this
* parameter's value in `AssociativeArray` after user's command input * parameter's value in `HashTable` after user's command input
* is parsed. Provided value will be copied. * is parsed. Provided value will be copied.
* If left `none`, - will coincide with `name` parameter. * If left `none`, - will coincide with `name` parameter.
* @return Returns the caller `CommandDataBuilder` to allow for * @return Returns the caller `CommandDataBuilder` to allow for
@ -822,7 +822,7 @@ public final function CommandDataBuilder ParamTextList(
* @param name Name of the parameter, will be copied * @param name Name of the parameter, will be copied
* (as it would appear in the generated help info). * (as it would appear in the generated help info).
* @param variableName Name of the variable that will store this * @param variableName Name of the variable that will store this
* parameter's value in `AssociativeArray` after user's command input * parameter's value in `HashTable` after user's command input
* is parsed. Provided value will be copied. * is parsed. Provided value will be copied.
* If left `none`, - will coincide with `name` parameter. * If left `none`, - will coincide with `name` parameter.
* @return Returns the caller `CommandDataBuilder` to allow for * @return Returns the caller `CommandDataBuilder` to allow for
@ -849,7 +849,7 @@ public final function CommandDataBuilder ParamRemainder(
* @param name Name of the parameter, will be copied * @param name Name of the parameter, will be copied
* (as it would appear in the generated help info). * (as it would appear in the generated help info).
* @param variableName Name of the variable that will store this * @param variableName Name of the variable that will store this
* parameter's value in `AssociativeArray` after user's command input * parameter's value in `HashTable` after user's command input
* is parsed. Provided value will be copied. * is parsed. Provided value will be copied.
* If left `none`, - will coincide with `name` parameter. * If left `none`, - will coincide with `name` parameter.
* @return Returns the caller `CommandDataBuilder` to allow for * @return Returns the caller `CommandDataBuilder` to allow for
@ -876,7 +876,7 @@ public final function CommandDataBuilder ParamObject(
* @param name Name of the parameter, will be copied * @param name Name of the parameter, will be copied
* (as it would appear in the generated help info). * (as it would appear in the generated help info).
* @param variableName Name of the variable that will store this * @param variableName Name of the variable that will store this
* parameter's value in `AssociativeArray` after user's command input * parameter's value in `HashTable` after user's command input
* is parsed. Provided value will be copied. * is parsed. Provided value will be copied.
* If left `none`, - will coincide with `name` parameter. * If left `none`, - will coincide with `name` parameter.
* @return Returns the caller `CommandDataBuilder` to allow for * @return Returns the caller `CommandDataBuilder` to allow for
@ -903,7 +903,7 @@ public final function CommandDataBuilder ParamObjectList(
* @param name Name of the parameter, will be copied * @param name Name of the parameter, will be copied
* (as it would appear in the generated help info). * (as it would appear in the generated help info).
* @param variableName Name of the variable that will store this * @param variableName Name of the variable that will store this
* parameter's value in `AssociativeArray` after user's command input * parameter's value in `HashTable` after user's command input
* is parsed. Provided value will be copied. * is parsed. Provided value will be copied.
* If left `none`, - will coincide with `name` parameter. * If left `none`, - will coincide with `name` parameter.
* @return Returns the caller `CommandDataBuilder` to allow for * @return Returns the caller `CommandDataBuilder` to allow for
@ -930,7 +930,7 @@ public final function CommandDataBuilder ParamArray(
* @param name Name of the parameter, will be copied * @param name Name of the parameter, will be copied
* (as it would appear in the generated help info). * (as it would appear in the generated help info).
* @param variableName Name of the variable that will store this * @param variableName Name of the variable that will store this
* parameter's value in `AssociativeArray` after user's command input * parameter's value in `HashTable` after user's command input
* is parsed. Provided value will be copied. * is parsed. Provided value will be copied.
* If left `none`, - will coincide with `name` parameter. * If left `none`, - will coincide with `name` parameter.
* @return Returns the caller `CommandDataBuilder` to allow for * @return Returns the caller `CommandDataBuilder` to allow for

97
sources/Commands/CommandParser.uc

@ -210,11 +210,11 @@ public final function Command.CallData ParseWith(
Parser parser, Parser parser,
Command.Data commandData) Command.Data commandData)
{ {
local AssociativeArray commandParameters; local HashTable commandParameters;
// Temporary object to return `nextResult` while setting variable to `none` // Temporary object to return `nextResult` while setting variable to `none`
local Command.CallData toReturn; local Command.CallData toReturn;
nextResult.parameters = _.collections.EmptyAssociativeArray(); nextResult.parameters = _.collections.EmptyHashTable();
nextResult.options = _.collections.EmptyAssociativeArray(); nextResult.options = _.collections.EmptyHashTable();
if (commandData.subCommands.length == 0) if (commandData.subCommands.length == 0)
{ {
DeclareError(CET_NoSubCommands, none); DeclareError(CET_NoSubCommands, none);
@ -265,17 +265,17 @@ private final function AssertNoTrailingInput()
// Assumes `commandParser` is not `none`. // Assumes `commandParser` is not `none`.
// Parses given required and optional parameters along with any // Parses given required and optional parameters along with any
// possible option declarations. // possible option declarations.
// Returns `AssociativeArray` filled with (variable, parsed value) pairs. // Returns `HashTable` filled with (variable, parsed value) pairs.
// Failure is equal to `commandParser` entering into a failed state. // Failure is equal to `commandParser` entering into a failed state.
private final function AssociativeArray ParseParameterArrays( private final function HashTable ParseParameterArrays(
array<Command.Parameter> requiredParameters, array<Command.Parameter> requiredParameters,
array<Command.Parameter> optionalParameters) array<Command.Parameter> optionalParameters)
{ {
local AssociativeArray parsedParameters; local HashTable parsedParameters;
if (!commandParser.Ok()) { if (!commandParser.Ok()) {
return none; return none;
} }
parsedParameters = _.collections.EmptyAssociativeArray(); parsedParameters = _.collections.EmptyHashTable();
// Parse parameters // Parse parameters
ParseRequiredParameterArray(parsedParameters, requiredParameters); ParseRequiredParameterArray(parsedParameters, requiredParameters);
ParseOptionalParameterArray(parsedParameters, optionalParameters); ParseOptionalParameterArray(parsedParameters, optionalParameters);
@ -286,9 +286,9 @@ private final function AssociativeArray ParseParameterArrays(
// Assumes `commandParser` and `parsedParameters` are not `none`. // Assumes `commandParser` and `parsedParameters` are not `none`.
// Parses given required parameters along with any possible option // Parses given required parameters along with any possible option
// declarations into given `parsedParameters` associative array. // declarations into given `parsedParameters` `HashTable`.
private final function ParseRequiredParameterArray( private final function ParseRequiredParameterArray(
AssociativeArray parsedParameters, HashTable parsedParameters,
array<Command.Parameter> requiredParameters) array<Command.Parameter> requiredParameters)
{ {
local int i; local int i;
@ -324,9 +324,9 @@ private final function ParseRequiredParameterArray(
// Assumes `commandParser` and `parsedParameters` are not `none`. // Assumes `commandParser` and `parsedParameters` are not `none`.
// Parses given optional parameters along with any possible option // Parses given optional parameters along with any possible option
// declarations into given `parsedParameters` associative array. // declarations into given `parsedParameters` hash table.
private final function ParseOptionalParameterArray( private final function ParseOptionalParameterArray(
AssociativeArray parsedParameters, HashTable parsedParameters,
array<Command.Parameter> optionalParameters) array<Command.Parameter> optionalParameters)
{ {
local int i; local int i;
@ -354,11 +354,11 @@ private final function ParseOptionalParameterArray(
// Assumes `commandParser` and `parsedParameters` are not `none`. // Assumes `commandParser` and `parsedParameters` are not `none`.
// Parses one given parameter along with any possible option // Parses one given parameter along with any possible option
// declarations into given `parsedParameters` associative array. // declarations into given `parsedParameters` `HashTable`.
// Returns `true` if we've successfully parsed given parameter without // Returns `true` if we've successfully parsed given parameter without
// any errors. // any errors.
private final function bool ParseParameter( private final function bool ParseParameter(
AssociativeArray parsedParameters, HashTable parsedParameters,
Command.Parameter expectedParameter) Command.Parameter expectedParameter)
{ {
local bool parsedEnough; local bool parsedEnough;
@ -393,11 +393,11 @@ private final function bool ParseParameter(
// Assumes `commandParser` and `parsedParameters` are not `none`. // Assumes `commandParser` and `parsedParameters` are not `none`.
// Parses a single value for a given parameter (e.g. one integer for // Parses a single value for a given parameter (e.g. one integer for
// integer or integer list parameter types) along with any possible option // integer or integer list parameter types) along with any possible option
// declarations into given `parsedParameters` associative array. // declarations into given `parsedParameters` `HashTable`.
// Returns `true` if we've successfully parsed a single value without // Returns `true` if we've successfully parsed a single value without
// any errors. // any errors.
private final function bool ParseSingleValue( private final function bool ParseSingleValue(
AssociativeArray parsedParameters, HashTable parsedParameters,
Command.Parameter expectedParameter) Command.Parameter expectedParameter)
{ {
// Before parsing any other value we need to check if user has // Before parsing any other value we need to check if user has
@ -454,9 +454,9 @@ private final function bool ParseSingleValue(
// Assumes `commandParser` and `parsedParameters` are not `none`. // Assumes `commandParser` and `parsedParameters` are not `none`.
// Parses a single boolean value into given `parsedParameters` // Parses a single boolean value into given `parsedParameters`
// associative array. // hash table.
private final function bool ParseBooleanValue( private final function bool ParseBooleanValue(
AssociativeArray parsedParameters, HashTable parsedParameters,
Command.Parameter expectedParameter) Command.Parameter expectedParameter)
{ {
local int i; local int i;
@ -501,9 +501,9 @@ private final function bool ParseBooleanValue(
// Assumes `commandParser` and `parsedParameters` are not `none`. // Assumes `commandParser` and `parsedParameters` are not `none`.
// Parses a single integer value into given `parsedParameters` // Parses a single integer value into given `parsedParameters`
// associative array. // hash table.
private final function bool ParseIntegerValue( private final function bool ParseIntegerValue(
AssociativeArray parsedParameters, HashTable parsedParameters,
Command.Parameter expectedParameter) Command.Parameter expectedParameter)
{ {
local int integerValue; local int integerValue;
@ -518,9 +518,9 @@ private final function bool ParseIntegerValue(
// Assumes `commandParser` and `parsedParameters` are not `none`. // Assumes `commandParser` and `parsedParameters` are not `none`.
// Parses a single number (float) value into given `parsedParameters` // Parses a single number (float) value into given `parsedParameters`
// associative array. // hash table.
private final function bool ParseNumberValue( private final function bool ParseNumberValue(
AssociativeArray parsedParameters, HashTable parsedParameters,
Command.Parameter expectedParameter) Command.Parameter expectedParameter)
{ {
local float numberValue; local float numberValue;
@ -535,9 +535,9 @@ private final function bool ParseNumberValue(
// Assumes `commandParser` and `parsedParameters` are not `none`. // Assumes `commandParser` and `parsedParameters` are not `none`.
// Parses a single `Text` value into given `parsedParameters` // Parses a single `Text` value into given `parsedParameters`
// associative array. // hash table.
private final function bool ParseTextValue( private final function bool ParseTextValue(
AssociativeArray parsedParameters, HashTable parsedParameters,
Command.Parameter expectedParameter) Command.Parameter expectedParameter)
{ {
local bool failedParsing; local bool failedParsing;
@ -568,9 +568,9 @@ private final function bool ParseTextValue(
// Assumes `commandParser` and `parsedParameters` are not `none`. // Assumes `commandParser` and `parsedParameters` are not `none`.
// Parses a single `Text` value into given `parsedParameters` // Parses a single `Text` value into given `parsedParameters`
// associative array, consuming all remaining contents. // hash table, consuming all remaining contents.
private final function bool ParseRemainderValue( private final function bool ParseRemainderValue(
AssociativeArray parsedParameters, HashTable parsedParameters,
Command.Parameter expectedParameter) Command.Parameter expectedParameter)
{ {
local MutableText value; local MutableText value;
@ -585,13 +585,13 @@ private final function bool ParseRemainderValue(
// Assumes `commandParser` and `parsedParameters` are not `none`. // Assumes `commandParser` and `parsedParameters` are not `none`.
// Parses a single JSON object into given `parsedParameters` // Parses a single JSON object into given `parsedParameters`
// associative array. // hash table.
private final function bool ParseObjectValue( private final function bool ParseObjectValue(
AssociativeArray parsedParameters, HashTable parsedParameters,
Command.Parameter expectedParameter) Command.Parameter expectedParameter)
{ {
local AssociativeArray objectValue; local HashTable objectValue;
objectValue = _.json.ParseObjectWith(commandParser); objectValue = _.json.ParseHashTableWith(commandParser);
if (!commandParser.Ok()) { if (!commandParser.Ok()) {
return false; return false;
} }
@ -601,13 +601,13 @@ private final function bool ParseObjectValue(
// Assumes `commandParser` and `parsedParameters` are not `none`. // Assumes `commandParser` and `parsedParameters` are not `none`.
// Parses a single JSON array into given `parsedParameters` // Parses a single JSON array into given `parsedParameters`
// associative array. // hash table.
private final function bool ParseArrayValue( private final function bool ParseArrayValue(
AssociativeArray parsedParameters, HashTable parsedParameters,
Command.Parameter expectedParameter) Command.Parameter expectedParameter)
{ {
local DynamicArray arrayValue; local ArrayList arrayValue;
arrayValue = _.json.ParseArrayWith(commandParser); arrayValue = _.json.ParseArrayListWith(commandParser);
if (!commandParser.Ok()) { if (!commandParser.Ok()) {
return false; return false;
} }
@ -623,24 +623,27 @@ private final function bool ParseArrayValue(
// recorded at `parameter.variableName` key (creating it if missing). // recorded at `parameter.variableName` key (creating it if missing).
// All recorded values are managed by `parametersArray`. // All recorded values are managed by `parametersArray`.
private final function RecordParameter( private final function RecordParameter(
AssociativeArray parametersArray, HashTable parametersArray,
Command.Parameter parameter, Command.Parameter parameter,
AcediaObject value) /* take */AcediaObject value)
{ {
local DynamicArray parameterVariable; local ArrayList parameterVariable;
if (!parameter.allowsList) if (!parameter.allowsList)
{ {
parametersArray.SetItem(parameter.variableName, value, true); parametersArray.SetItem(parameter.variableName, value);
_.memory.Free(value);
return; return;
} }
parameterVariable = parameterVariable =
DynamicArray(parametersArray.GetItem(parameter.variableName)); ArrayList(parametersArray.GetItem(parameter.variableName));
if (parameterVariable == none) { if (parameterVariable == none) {
parameterVariable = _.collections.EmptyDynamicArray(); parameterVariable = _.collections.EmptyArrayList();
} }
parameterVariable.AddItem(value, true); parameterVariable.AddItem(value);
parametersArray.SetItem(parameter.variableName, parameterVariable, true); _.memory.Free(value);
parametersArray.SetItem(parameter.variableName, parameterVariable);
_.memory.Free(parameterVariable);
} }
// Assumes `commandParser` is not `none`. // Assumes `commandParser` is not `none`.
@ -815,7 +818,7 @@ private final function bool AddOptionByCharacter(
// Assumes `commandParser` and `nextResult` are not `none`. // Assumes `commandParser` and `nextResult` are not `none`.
private final function bool ParseOptionParameters(Command.Option pickedOption) private final function bool ParseOptionParameters(Command.Option pickedOption)
{ {
local AssociativeArray optionParameters; local HashTable optionParameters;
// If we are already parsing other option's parameters and did not finish // If we are already parsing other option's parameters and did not finish
// parsing all required ones - we cannot start another option // parsing all required ones - we cannot start another option
if (currentTargetIsOption && currentTarget != CPT_ExtraParameter) if (currentTargetIsOption && currentTarget != CPT_ExtraParameter)
@ -825,9 +828,7 @@ private final function bool ParseOptionParameters(Command.Option pickedOption)
} }
if (pickedOption.required.length == 0 && pickedOption.optional.length == 0) if (pickedOption.required.length == 0 && pickedOption.optional.length == 0)
{ {
// Here `optionParameters == none` nextResult.options.SetItem(pickedOption.longName, none);
nextResult.options
.SetItem(pickedOption.longName, optionParameters, true);
return true; return true;
} }
currentTargetIsOption = true; currentTargetIsOption = true;
@ -838,9 +839,11 @@ private final function bool ParseOptionParameters(Command.Option pickedOption)
if (commandParser.Ok()) if (commandParser.Ok())
{ {
nextResult.options nextResult.options
.SetItem(pickedOption.longName, optionParameters, true); .SetItem(pickedOption.longName, optionParameters);
_.memory.Free(optionParameters);
return true; return true;
} }
_.memory.Free(optionParameters);
return false; return false;
} }

80
sources/Commands/Tests/TEST_Command.uc

@ -192,10 +192,10 @@ protected static function Test_SubCommandName()
protected static function SubTest_MockAQ1AndFailed() protected static function SubTest_MockAQ1AndFailed()
{ {
local Parser parser; local Parser parser;
local Command command; local Command command;
local DynamicArray paramArray; local ArrayList paramArray;
local AssociativeArray parameters; local HashTable parameters;
parser = Parser(__().memory.Allocate(class'Parser')); parser = Parser(__().memory.Allocate(class'Parser'));
command = class'MockCommandA'.static.GetInstance(); command = class'MockCommandA'.static.GetInstance();
Issue("Command queries that should fail succeed instead."); Issue("Command queries that should fail succeed instead.");
@ -211,7 +211,7 @@ protected static function SubTest_MockAQ1AndFailed()
command.ParseInputWith(parser.InitializeS(default.queryASuccess1), none) command.ParseInputWith(parser.InitializeS(default.queryASuccess1), none)
.Parameters; .Parameters;
TEST_ExpectTrue(parameters.GetLength() == 2); TEST_ExpectTrue(parameters.GetLength() == 2);
paramArray = DynamicArray(parameters.GetItem(P("isItSimple?"))); paramArray = ArrayList(parameters.GetItem(P("isItSimple?")));
TEST_ExpectTrue(paramArray.GetLength() == 1); TEST_ExpectTrue(paramArray.GetLength() == 1);
TEST_ExpectFalse(BoolBox(paramArray.GetItem(0)).Get()); TEST_ExpectFalse(BoolBox(paramArray.GetItem(0)).Get());
TEST_ExpectTrue(IntBox(parameters.GetItem(P("int"))).Get() == 8); TEST_ExpectTrue(IntBox(parameters.GetItem(P("int"))).Get() == 8);
@ -221,27 +221,27 @@ protected static function SubTest_MockAQ1AndFailed()
protected static function SubTest_MockAQ2() protected static function SubTest_MockAQ2()
{ {
local DynamicArray paramArray, subArray; local ArrayList paramArray, subArray;
local AssociativeArray result, subObject; local HashTable result, subObject;
Issue("Cannot parse command queries without optional parameters."); Issue("Cannot parse command queries without optional parameters.");
result = class'MockCommandA'.static.GetInstance() result = class'MockCommandA'.static.GetInstance()
.ParseInputWith(PRS(default.queryASuccess2), none).Parameters; .ParseInputWith(PRS(default.queryASuccess2), none).Parameters;
TEST_ExpectTrue(result.GetLength() == 2); TEST_ExpectTrue(result.GetLength() == 2);
subObject = AssociativeArray(result.GetItem(P("just_obj"))); subObject = HashTable(result.GetItem(P("just_obj")));
TEST_ExpectTrue(IntBox(subObject.GetItem(P("var"))).Get() == 7); TEST_ExpectTrue(IntBox(subObject.GetItem(P("var"))).Get() == 7);
TEST_ExpectTrue(subObject.HasKey(P("another"))); TEST_ExpectTrue(subObject.HasKey(P("another")));
TEST_ExpectNone(subObject.GetItem(P("another"))); TEST_ExpectNone(subObject.GetItem(P("another")));
paramArray = DynamicArray(result.GetItem(P("manyLists"))); paramArray = ArrayList(result.GetItem(P("manyLists")));
TEST_ExpectTrue(paramArray.GetLength() == 4); TEST_ExpectTrue(paramArray.GetLength() == 4);
subArray = DynamicArray(paramArray.GetItem(0)); subArray = ArrayList(paramArray.GetItem(0));
TEST_ExpectTrue(subArray.GetLength() == 2); TEST_ExpectTrue(subArray.GetLength() == 2);
TEST_ExpectTrue(IntBox(subArray.GetItem(0)).Get() == 1); TEST_ExpectTrue(IntBox(subArray.GetItem(0)).Get() == 1);
TEST_ExpectTrue(IntBox(subArray.GetItem(1)).Get() == 2); TEST_ExpectTrue(IntBox(subArray.GetItem(1)).Get() == 2);
subArray = DynamicArray(paramArray.GetItem(1)); subArray = ArrayList(paramArray.GetItem(1));
TEST_ExpectTrue(subArray.GetLength() == 1); TEST_ExpectTrue(subArray.GetLength() == 1);
TEST_ExpectTrue(IntBox(subArray.GetItem(0)).Get() == 3); TEST_ExpectTrue(IntBox(subArray.GetItem(0)).Get() == 3);
TEST_ExpectTrue(DynamicArray(paramArray.GetItem(2)).GetLength() == 0); TEST_ExpectTrue(ArrayList(paramArray.GetItem(2)).GetLength() == 0);
subArray = DynamicArray(paramArray.GetItem(3)); subArray = ArrayList(paramArray.GetItem(3));
TEST_ExpectTrue(subArray.GetLength() == 3); TEST_ExpectTrue(subArray.GetLength() == 3);
TEST_ExpectTrue(IntBox(subArray.GetItem(0)).Get() == 8); TEST_ExpectTrue(IntBox(subArray.GetItem(0)).Get() == 8);
TEST_ExpectTrue(IntBox(subArray.GetItem(1)).Get() == 5); TEST_ExpectTrue(IntBox(subArray.GetItem(1)).Get() == 5);
@ -251,13 +251,13 @@ protected static function SubTest_MockAQ2()
protected static function SubTest_MockAQ3() protected static function SubTest_MockAQ3()
{ {
local DynamicArray paramArray; local ArrayList paramArray;
local AssociativeArray result; local HashTable result;
Issue("Cannot parse command queries with optional parameters."); Issue("Cannot parse command queries with optional parameters.");
result = class'MockCommandA'.static.GetInstance() result = class'MockCommandA'.static.GetInstance()
.ParseInputWith(PRS(default.queryASuccess3), none).Parameters; .ParseInputWith(PRS(default.queryASuccess3), none).Parameters;
// Booleans // Booleans
paramArray = DynamicArray(result.GetItem(P("isItSimple?"))); paramArray = ArrayList(result.GetItem(P("isItSimple?")));
TEST_ExpectTrue(paramArray.GetLength() == 7); TEST_ExpectTrue(paramArray.GetLength() == 7);
TEST_ExpectTrue(BoolBox(paramArray.GetItem(0)).Get()); TEST_ExpectTrue(BoolBox(paramArray.GetItem(0)).Get());
TEST_ExpectFalse(BoolBox(paramArray.GetItem(1)).Get()); TEST_ExpectFalse(BoolBox(paramArray.GetItem(1)).Get());
@ -269,13 +269,13 @@ protected static function SubTest_MockAQ3()
// Integer // Integer
TEST_ExpectTrue(IntBox(result.GetItem(P("int"))).Get() == -32); TEST_ExpectTrue(IntBox(result.GetItem(P("int"))).Get() == -32);
// Floats // Floats
paramArray = DynamicArray(result.GetItem(P("list"))); paramArray = ArrayList(result.GetItem(P("list")));
TEST_ExpectTrue(paramArray.GetLength() == 3); TEST_ExpectTrue(paramArray.GetLength() == 3);
TEST_ExpectTrue(FloatBox(paramArray.GetItem(0)).Get() == 0.45); TEST_ExpectTrue(FloatBox(paramArray.GetItem(0)).Get() == 0.45);
TEST_ExpectTrue(FloatBox(paramArray.GetItem(1)).Get() == 234.7); TEST_ExpectTrue(FloatBox(paramArray.GetItem(1)).Get() == 234.7);
TEST_ExpectTrue(FloatBox(paramArray.GetItem(2)).Get() == 13); TEST_ExpectTrue(FloatBox(paramArray.GetItem(2)).Get() == 13);
// `Text`s // `Text`s
paramArray = DynamicArray(result.GetItem(P("another list"))); paramArray = ArrayList(result.GetItem(P("another list")));
TEST_ExpectTrue(paramArray.GetLength() == 3); TEST_ExpectTrue(paramArray.GetLength() == 3);
TEST_ExpectTrue(Text(paramArray.GetItem(0)).ToString() == "dk"); TEST_ExpectTrue(Text(paramArray.GetItem(0)).ToString() == "dk");
TEST_ExpectTrue(Text(paramArray.GetItem(1)).ToString() == "someone"); TEST_ExpectTrue(Text(paramArray.GetItem(1)).ToString() == "someone");
@ -285,19 +285,19 @@ protected static function SubTest_MockAQ3()
protected static function SubTest_MockAQ4() protected static function SubTest_MockAQ4()
{ {
local DynamicArray paramArray; local ArrayList paramArray;
local AssociativeArray result, subObject; local HashTable result, subObject;
Issue("Cannot parse command queries with optional parameters."); Issue("Cannot parse command queries with optional parameters.");
result = class'MockCommandA'.static.GetInstance() result = class'MockCommandA'.static.GetInstance()
.ParseInputWith(PRS(default.queryASuccess4), none).Parameters; .ParseInputWith(PRS(default.queryASuccess4), none).Parameters;
TEST_ExpectTrue(result.GetLength() == 3); TEST_ExpectTrue(result.GetLength() == 3);
subObject = AssociativeArray(result.GetItem(P("just_obj"))); subObject = HashTable(result.GetItem(P("just_obj")));
TEST_ExpectTrue(IntBox(subObject.GetItem(P("var"))).Get() == 7); TEST_ExpectTrue(IntBox(subObject.GetItem(P("var"))).Get() == 7);
TEST_ExpectTrue(subObject.HasKey(P("another"))); TEST_ExpectTrue(subObject.HasKey(P("another")));
TEST_ExpectNone(subObject.GetItem(P("another"))); TEST_ExpectNone(subObject.GetItem(P("another")));
paramArray = DynamicArray(result.GetItem(P("manyLists"))); paramArray = ArrayList(result.GetItem(P("manyLists")));
TEST_ExpectTrue(paramArray.GetLength() == 4); TEST_ExpectTrue(paramArray.GetLength() == 4);
subObject = AssociativeArray(result.GetItem(P("last_obj"))); subObject = HashTable(result.GetItem(P("last_obj")));
TEST_ExpectTrue(subObject.GetLength() == 0); TEST_ExpectTrue(subObject.GetLength() == 0);
} }
@ -336,15 +336,15 @@ protected static function SubTest_MockBFailed()
protected static function SubTest_MockBQ1() protected static function SubTest_MockBQ1()
{ {
local Command.CallData result; local Command.CallData result;
local DynamicArray subArray; local ArrayList subArray;
local AssociativeArray params, options, subObject; local HashTable params, options, subObject;
Issue("Cannot parse command queries with options."); Issue("Cannot parse command queries with options.");
result = class'MockCommandB'.static.GetInstance() result = class'MockCommandB'.static.GetInstance()
.ParseInputWith(PRS(default.queryBSuccess1), none); .ParseInputWith(PRS(default.queryBSuccess1), none);
params = result.Parameters; params = result.Parameters;
TEST_ExpectTrue(params.GetLength() == 2); TEST_ExpectTrue(params.GetLength() == 2);
subArray = DynamicArray(params.GetItem(P("just_array"))); subArray = ArrayList(params.GetItem(P("just_array")));
TEST_ExpectTrue(subArray.GetLength() == 2); TEST_ExpectTrue(subArray.GetLength() == 2);
TEST_ExpectTrue(IntBox(subArray.GetItem(0)).Get() == 7); TEST_ExpectTrue(IntBox(subArray.GetItem(0)).Get() == 7);
TEST_ExpectNone(subArray.GetItem(1)); TEST_ExpectNone(subArray.GetItem(1));
@ -352,9 +352,9 @@ protected static function SubTest_MockBQ1()
== "text"); == "text");
options = result.options; options = result.options;
TEST_ExpectTrue(options.GetLength() == 1); TEST_ExpectTrue(options.GetLength() == 1);
subObject = AssociativeArray(options.GetItem(P("values"))); subObject = HashTable(options.GetItem(P("values")));
TEST_ExpectTrue(subObject.GetLength() == 1); TEST_ExpectTrue(subObject.GetLength() == 1);
subArray = DynamicArray(subObject.GetItem(P("types"))); subArray = ArrayList(subObject.GetItem(P("types")));
TEST_ExpectTrue(subArray.GetLength() == 5); TEST_ExpectTrue(subArray.GetLength() == 5);
TEST_ExpectTrue(IntBox(subArray.GetItem(0)).Get() == 1); TEST_ExpectTrue(IntBox(subArray.GetItem(0)).Get() == 1);
TEST_ExpectTrue(IntBox(subArray.GetItem(1)).Get() == 3); TEST_ExpectTrue(IntBox(subArray.GetItem(1)).Get() == 3);
@ -365,9 +365,9 @@ protected static function SubTest_MockBQ1()
protected static function SubTest_MockBQ2() protected static function SubTest_MockBQ2()
{ {
local Command.CallData result; local Command.CallData result;
local DynamicArray subArray; local ArrayList subArray;
local AssociativeArray options, subObject; local HashTable options, subObject;
Issue("Cannot parse command queries with mixed-in options."); Issue("Cannot parse command queries with mixed-in options.");
result = class'MockCommandB'.static.GetInstance() result = class'MockCommandB'.static.GetInstance()
.ParseInputWith(PRS(default.queryBSuccess2), none); .ParseInputWith(PRS(default.queryBSuccess2), none);
@ -382,13 +382,13 @@ protected static function SubTest_MockBQ2()
TEST_ExpectNone(options.GetItem(P("verbose"))); TEST_ExpectNone(options.GetItem(P("verbose")));
TEST_ExpectTrue(options.HasKey(P("forced"))); TEST_ExpectTrue(options.HasKey(P("forced")));
TEST_ExpectNone(options.GetItem(P("forced"))); TEST_ExpectNone(options.GetItem(P("forced")));
subObject = AssociativeArray(options.GetItem(P("type"))); subObject = HashTable(options.GetItem(P("type")));
TEST_ExpectTrue( Text(subObject.GetItem(P("type"))).ToString() TEST_ExpectTrue( Text(subObject.GetItem(P("type"))).ToString()
== "value"); == "value");
subObject = AssociativeArray(options.GetItem(P("Test"))); subObject = HashTable(options.GetItem(P("Test")));
TEST_ExpectTrue(Text(subObject.GetItem(P("to_test"))).IsEmpty()); TEST_ExpectTrue(Text(subObject.GetItem(P("to_test"))).IsEmpty());
subObject = AssociativeArray(options.GetItem(P("values"))); subObject = HashTable(options.GetItem(P("values")));
subArray = DynamicArray(subObject.GetItem(P("types"))); subArray = ArrayList(subObject.GetItem(P("types")));
TEST_ExpectTrue(subArray.GetLength() == 1); TEST_ExpectTrue(subArray.GetLength() == 1);
TEST_ExpectTrue(IntBox(subArray.GetItem(0)).Get() == 8); TEST_ExpectTrue(IntBox(subArray.GetItem(0)).Get() == 8);
} }
@ -396,19 +396,19 @@ protected static function SubTest_MockBQ2()
protected static function SubTest_MockBQ3Remainder() protected static function SubTest_MockBQ3Remainder()
{ {
local Command.CallData result; local Command.CallData result;
local DynamicArray subArray; local ArrayList subArray;
local AssociativeArray options, subObject; local HashTable options, subObject;
Issue("Cannot parse command queries with `CPT_Remainder` type parameters."); Issue("Cannot parse command queries with `CPT_Remainder` type parameters.");
result = class'MockCommandB'.static.GetInstance() result = class'MockCommandB'.static.GetInstance()
.ParseInputWith(PRS(default.queryBSuccess3), none); .ParseInputWith(PRS(default.queryBSuccess3), none);
TEST_ExpectTrue(result.parameters.GetLength() == 1); TEST_ExpectTrue(result.parameters.GetLength() == 1);
subArray = DynamicArray(result.parameters.GetItem(P("list"))); subArray = ArrayList(result.parameters.GetItem(P("list")));
TEST_ExpectTrue(FloatBox(subArray.GetItem(0)).Get() == 3); TEST_ExpectTrue(FloatBox(subArray.GetItem(0)).Get() == 3);
TEST_ExpectTrue(FloatBox(subArray.GetItem(1)).Get() == -76); TEST_ExpectTrue(FloatBox(subArray.GetItem(1)).Get() == -76);
options = result.options; options = result.options;
TEST_ExpectTrue(options.GetLength() == 1); TEST_ExpectTrue(options.GetLength() == 1);
TEST_ExpectTrue(options.HasKey(P("remainder"))); TEST_ExpectTrue(options.HasKey(P("remainder")));
subObject = AssociativeArray(options.GetItem(P("remainder"))); subObject = HashTable(options.GetItem(P("remainder")));
TEST_ExpectTrue( Text(subObject.GetItem(P("everything"))).ToString() TEST_ExpectTrue( Text(subObject.GetItem(P("everything"))).ToString()
== "--type \"value\" -va 8 -sV --forced -T \"\" 32"); == "--type \"value\" -va 8 -sV --forced -T \"\" 32");
} }

4
sources/Commands/Tests/TEST_CommandDataBuilder.uc

@ -91,7 +91,7 @@ protected static function Test_Empty()
@ "blank command data."); @ "blank command data.");
builder = builder =
CommandDataBuilder(__().memory.Allocate(class'CommandDataBuilder')); CommandDataBuilder(__().memory.Allocate(class'CommandDataBuilder'));
data = builder.GetData(); data = builder.BorrowData();
TEST_ExpectTrue(data.subcommands.length == 1); TEST_ExpectTrue(data.subcommands.length == 1);
TEST_ExpectTrue(data.subcommands[0].name.IsEmpty()); TEST_ExpectTrue(data.subcommands[0].name.IsEmpty());
TEST_ExpectNone(data.subcommands[0].description); TEST_ExpectNone(data.subcommands[0].description);
@ -104,7 +104,7 @@ protected static function Test_Empty()
protected static function Test_Full() protected static function Test_Full()
{ {
local Command.Data data; local Command.Data data;
data = PrepareBuilder().GetData(); data = PrepareBuilder().BorrowData();
Context("Testing that `CommandDataBuilder` properly builds command data for" Context("Testing that `CommandDataBuilder` properly builds command data for"
@ "complex commands."); @ "complex commands.");
Issue("Incorrect amount of sub-commands and/or option."); Issue("Incorrect amount of sub-commands and/or option.");

Loading…
Cancel
Save