diff --git a/sources/Aliases/AliasSource.uc b/sources/Aliases/AliasSource.uc index 90b6100..5a1e8a5 100644 --- a/sources/Aliases/AliasSource.uc +++ b/sources/Aliases/AliasSource.uc @@ -123,7 +123,7 @@ private final function HashValidAliasesFromPerObjectConfig() // they already exist. // Takes care of lower case conversion to store aliases in `aliasHash` // in a case-insensitive way. -private final function InsertAlias(Text alias, Text value) +private final function InsertAlias(BaseText alias, BaseText value) { local Text aliasLowerCaseCopy; local AssociativeArray.Entry hashEntry; @@ -145,7 +145,7 @@ private final function InsertAlias(Text alias, Text value) * @param alias Alias to check, case-insensitive. * @return `true` if present, `false` otherwise. */ -public function bool HasAlias(Text alias) +public function bool HasAlias(BaseText alias) { local bool result; local Text lowerCaseAlias; @@ -174,7 +174,7 @@ public function bool HasAlias(Text alias) * and `copyOnFailure == true` means method will return `alias.Copy()`. * If `alias == none` method always returns `none`. */ -public function Text Resolve(Text alias, optional bool copyOnFailure) +public function Text Resolve(BaseText alias, optional bool copyOnFailure) { local Text result; local Text lowerCaseAlias; @@ -273,7 +273,7 @@ public final function bool AddAlias( * * @param aliasToRemove Alias that you want to remove from caller source. */ -public final function RemoveAlias(Text aliasToRemove) +public final function RemoveAlias(BaseText aliasToRemove) { local int i; local bool isMatchingRecord; @@ -308,7 +308,9 @@ public final function RemoveAlias(Text aliasToRemove) } } -private final function LogDuplicateAliasWarning(Text alias, Text existingValue) +private final function LogDuplicateAliasWarning( + BaseText alias, + BaseText existingValue) { _.logger.Auto(warnDuplicateAlias) .ArgClass(class) @@ -319,7 +321,7 @@ private final function LogDuplicateAliasWarning(Text alias, Text existingValue) // Tries to find a loaded `Aliases` config object that stores aliases for // the given value. If such object does not exists - creates a new one. // Assumes `value != none`. -private final function Aliases GetAliasesObjectWithValue(Text value) +private final function Aliases GetAliasesObjectWithValue(BaseText value) { local int i; local Text nextValue; diff --git a/sources/Aliases/Aliases.uc b/sources/Aliases/Aliases.uc index 5d0c290..58014f4 100644 --- a/sources/Aliases/Aliases.uc +++ b/sources/Aliases/Aliases.uc @@ -48,7 +48,7 @@ var protected config array alias; // we need methods to convert between "storage" (`string`) // and "actual" (`Text`) value version. // `ToStorageVersion()` and `ToActualVersion()` do that. -private final static function string ToStorageVersion(Text actualValue) +private final static function string ToStorageVersion(BaseText actualValue) { return Repl(actualValue.ToString(), ".", ":"); } @@ -98,7 +98,7 @@ private static final function Aliases LoadObjectByName(string objectName) * correspond to. * @return Instance of `Aliases` object with a given name. */ -public static final function Aliases LoadObject(Text aliasesValue) +public static final function Aliases LoadObject(BaseText aliasesValue) { if (aliasesValue != none) { return LoadObjectByName(ToStorageVersion(aliasesValue)); @@ -141,7 +141,7 @@ public final function array GetAliases() * @param aliasToAdd Alias to add to caller `Aliases` object. * If `none`, method will do nothing. */ -public final function AddAlias(Text aliasToAdd) +public final function AddAlias(BaseText aliasToAdd) { local int i; if (aliasToAdd == none) return; @@ -165,7 +165,7 @@ public final function AddAlias(Text aliasToAdd) * * @param aliasToRemove Alias to remove from caller `Aliases` object. */ -public final function RemoveAlias(Text aliasToRemove) +public final function RemoveAlias(BaseText aliasToRemove) { local int i; local bool removedAlias; diff --git a/sources/Aliases/AliasesAPI.uc b/sources/Aliases/AliasesAPI.uc index f2b8db9..2f5a641 100644 --- a/sources/Aliases/AliasesAPI.uc +++ b/sources/Aliases/AliasesAPI.uc @@ -155,7 +155,7 @@ public final function AliasSource GetFeatureSource() * If `alias == none` method always returns `none`. */ public final function Text ResolveWeapon( - Text alias, + BaseText alias, optional bool copyOnFailure) { local AliasSource source; @@ -187,7 +187,9 @@ public final function Text ResolveWeapon( * and `copyOnFailure == true` means method will return `alias.Copy()`. * If `alias == none` method always returns `none`. */ -public final function Text ResolveColor(Text alias, optional bool copyOnFailure) +public final function Text ResolveColor( + BaseText alias, + optional bool copyOnFailure) { local AliasSource source; source = GetColorSource(); @@ -219,7 +221,7 @@ public final function Text ResolveColor(Text alias, optional bool copyOnFailure) * If `alias == none` method always returns `none`. */ public final function Text ResolveFeature( - Text alias, + BaseText alias, optional bool copyOnFailure) { local AliasSource source; diff --git a/sources/Avarice/AvariceAPI.uc b/sources/Avarice/AvariceAPI.uc index 3a9557c..6217064 100644 --- a/sources/Avarice/AvariceAPI.uc +++ b/sources/Avarice/AvariceAPI.uc @@ -47,7 +47,7 @@ public final function array GetAllLinks() * If `linkName == none` or `AvariceLink` with such name does not exist - * returns `none`. */ -public final function AvariceLink GetLink(Text linkName) +public final function AvariceLink GetLink(BaseText linkName) { local int i; local Text nextName; diff --git a/sources/Avarice/AvariceLink.uc b/sources/Avarice/AvariceLink.uc index 4001be3..817abcd 100644 --- a/sources/Avarice/AvariceLink.uc +++ b/sources/Avarice/AvariceLink.uc @@ -123,7 +123,7 @@ protected function Finalizer() * @param name Port used by the Avarice instance that caller `AvariceLink` * is connecting to. */ -public final function Initialize(Text name, Text host, int port) +public final function Initialize(BaseText name, BaseText host, int port) { if (tcpStream != none) return; if (name == none) return; @@ -198,12 +198,13 @@ public final function SimpleSlot OnDeath(AcediaObject receiver) /* SIGNAL */ public final function Avarice_OnMessage_Slot OnMessage( AcediaObject receiver, - Text service) + BaseText service) { return Avarice_OnMessage_Slot(GetServiceSignal(service).NewSlot(receiver)); } -private final function Avarice_OnMessage_Signal GetServiceSignal(Text service) +private final function Avarice_OnMessage_Signal GetServiceSignal( + BaseText service) { local Avarice_OnMessage_Signal result; if (service != none) { @@ -370,8 +371,8 @@ public final function int GetPort() * addressing make a reply. */ public final function bool SendMessage( - Text service, - Text type, + BaseText service, + BaseText type, AcediaObject parameters) { local Mutabletext parametesAsJSON; diff --git a/sources/Avarice/AvariceTcpStream.uc b/sources/Avarice/AvariceTcpStream.uc index 34b966c..b2bf80a 100644 --- a/sources/Avarice/AvariceTcpStream.uc +++ b/sources/Avarice/AvariceTcpStream.uc @@ -269,7 +269,7 @@ private final function HandleIncomingData() _.memory.FreeMany(receivedMessages); } -public final function SendMessage(Text textMessage) +public final function SendMessage(BaseText textMessage) { local int i; local int nextByte; @@ -331,7 +331,7 @@ private final function SendReceived(int received) SendBinary(3, buffer); } -private final function AvariceMessage MessageFromText(Text message) +private final function AvariceMessage MessageFromText(BaseText message) { local Parser parser; local AvariceMessage result; diff --git a/sources/Chat/ChatAPI.uc b/sources/Chat/ChatAPI.uc index 6910e26..ffad999 100644 --- a/sources/Chat/ChatAPI.uc +++ b/sources/Chat/ChatAPI.uc @@ -80,7 +80,7 @@ public function ChatAPI_OnMessage_Slot OnMessage( * also be interrupted. * * [Signature] - * bool (EPlayer receiver, EPlayer sender, Text message) + * bool (EPlayer receiver, EPlayer sender, BaseText message) * * @param receiver `EPlayer` that will receive the message. * @param sender `EPlayer` that has sent the message. diff --git a/sources/Chat/Events/ChatAPI_OnMessageFor_Signal.uc b/sources/Chat/Events/ChatAPI_OnMessageFor_Signal.uc index ff6dbb6..8e2ccb0 100644 --- a/sources/Chat/Events/ChatAPI_OnMessageFor_Signal.uc +++ b/sources/Chat/Events/ChatAPI_OnMessageFor_Signal.uc @@ -19,7 +19,10 @@ */ class ChatAPI_OnMessageFor_Signal extends Signal; -public final function bool Emit(EPlayer receiver, EPlayer sender, Text message) +public final function bool Emit( + EPlayer receiver, + EPlayer sender, + BaseText message) { local Slot nextSlot; local bool nextReply; diff --git a/sources/Chat/Events/ChatAPI_OnMessageFor_Slot.uc b/sources/Chat/Events/ChatAPI_OnMessageFor_Slot.uc index bc921e4..9d63827 100644 --- a/sources/Chat/Events/ChatAPI_OnMessageFor_Slot.uc +++ b/sources/Chat/Events/ChatAPI_OnMessageFor_Slot.uc @@ -19,7 +19,7 @@ */ class ChatAPI_OnMessageFor_Slot extends Slot; -delegate bool connect(EPlayer receiver, EPlayer sender, Text message) +delegate bool connect(EPlayer receiver, EPlayer sender, BaseText message) { DummyCall(); return true; diff --git a/sources/Color/ColorAPI.uc b/sources/Color/ColorAPI.uc index 73127b1..8b710ac 100644 --- a/sources/Color/ColorAPI.uc +++ b/sources/Color/ColorAPI.uc @@ -1026,7 +1026,7 @@ public final function bool ParseString( * @return `true` if parsing was successful and false otherwise. */ public final function bool Parse( - Text textWithColor, + BaseText textWithColor, out Color resultingColor) { local bool successfullyParsed; @@ -1051,8 +1051,8 @@ public final function bool Parse( * @return `true` if resolving was successful and false otherwise. */ public final function bool ResolveShortTagColor( - Text.Character shortTag, - out Color resultingColor) + BaseText.Character shortTag, + out Color resultingColor) { local int i; if (shortTag.codePoint <= 0) { diff --git a/sources/Commands/BuiltInCommands/ACommandHelp.uc b/sources/Commands/BuiltInCommands/ACommandHelp.uc index e3abfff..2725d89 100644 --- a/sources/Commands/BuiltInCommands/ACommandHelp.uc +++ b/sources/Commands/BuiltInCommands/ACommandHelp.uc @@ -157,7 +157,7 @@ private final function PrintCommands(ConsoleWriter cout, Command.Data data) private final function PrintSubCommand( ConsoleWriter cout, SubCommand subCommand, - Text commandName) + BaseText commandName) { // Command + parameters // Command name + sub command name diff --git a/sources/Commands/Command.uc b/sources/Commands/Command.uc index 7491429..9bdc31b 100644 --- a/sources/Commands/Command.uc +++ b/sources/Commands/Command.uc @@ -24,7 +24,7 @@ * along with Acedia. If not, see . */ class Command extends AcediaObject - dependson(Text); + dependson(BaseText); /** * Possible errors that can arise when parsing command parameters from @@ -149,7 +149,7 @@ struct SubCommand // Options are independent from sub-commands. struct Option { - var Text.Character shortName; + var BaseText.Character shortName; var Text longName; var Text description; // Option can also have their own parameters @@ -550,12 +550,12 @@ private final function array ParseTargets( return targetPlayers; } - // TODO: This is a hack to insert new line symbol, // this needs to be redone in a better way -private final function Text.Character GetNewLine(Text.Formatting formatting) +private final function BaseText.Character GetNewLine( + BaseText.Formatting formatting) { - local Text.Character newLine; + local BaseText.Character newLine; newLine.codePoint = 10; newLine.formatting = formatting; return newLine; diff --git a/sources/Commands/CommandDataBuilder.uc b/sources/Commands/CommandDataBuilder.uc index e5b46d3..461bf76 100644 --- a/sources/Commands/CommandDataBuilder.uc +++ b/sources/Commands/CommandDataBuilder.uc @@ -95,7 +95,7 @@ protected function Finalizer() // Find index of sub-command with a given name `name` in `subcommands`. // `-1` if there's not sub-command with such name. // Case-sensitive. -private final function int FindSubCommandIndex(Text name) +private final function int FindSubCommandIndex(BaseText name) { local int i; if (name == none) { @@ -113,7 +113,7 @@ private final function int FindSubCommandIndex(Text name) // Find index of option with a given name `name` in `options`. // `-1` if there's not sub-command with such name. // Case-sensitive. -private final function int FindOptionIndex(Text longName) +private final function int FindOptionIndex(BaseText longName) { local int i; if (longName == none) { @@ -132,7 +132,7 @@ private final function int FindOptionIndex(Text longName) // name (long name) `name`. // Doe not check whether subcommand/option with that name already exists. // Copies passed `name`, assumes that it is not `none`. -private final function MakeEmptySelection(Text name, bool selectedOption) +private final function MakeEmptySelection(BaseText name, bool selectedOption) { selectedItemIsOption = selectedOption; selectedItemName = name.Copy(); @@ -146,7 +146,7 @@ private final function MakeEmptySelection(Text name, bool selectedOption) // creates new record in selection, otherwise copies previously saved data. // Automatically saves previously selected data into prepared data. // Copies `name` if it has to create new record. -private final function SelectSubCommand(Text name) +private final function SelectSubCommand(BaseText name) { local int subcommandIndex; if (name == none) return; @@ -181,7 +181,7 @@ private final function SelectSubCommand(Text name) // creates new record in selection, otherwise copies previously saved data. // Automatically saves previously selected data into prepared data. // Copies `name` if it has to create new record. -private final function SelectOption(Text longName) +private final function SelectOption(BaseText longName) { local int optionIndex; if (longName == none) return; @@ -293,7 +293,7 @@ private final function RecordSelectedOption() * @return Returns the caller `CommandDataBuilder` to allow for * method chaining. */ -public final function CommandDataBuilder SubCommand(Text name) +public final function CommandDataBuilder SubCommand(BaseText name) { SelectSubCommand(name); return self; @@ -309,9 +309,9 @@ public final function CommandDataBuilder SubCommand(Text name) // the option altogether. // Returns `none` if validation failed and chosen short name otherwise // (if `shortName` was used for it - it's value will be copied). -private final function Text.Character GetValidShortName( - Text longName, - Text shortName) +private final function BaseText.Character GetValidShortName( + BaseText longName, + BaseText shortName) { // Validate `longName` if (longName == none) { @@ -341,8 +341,8 @@ private final function Text.Character GetValidShortName( // i.e. we cannot have several options with identical names: // (--silent, -s) and (--sick, -s). private final function bool VerifyNoOptionNamingConflict( - Text longName, - Text.Character shortName) + BaseText longName, + BaseText.Character shortName) { local int i; // To make sure we will search through the up-to-date `options`, @@ -397,11 +397,11 @@ private final function bool VerifyNoOptionNamingConflict( * method chaining. */ public final function CommandDataBuilder Option( - Text longName, - optional Text shortName) + BaseText longName, + optional BaseText shortName) { - local int optionIndex; - local Text.Character shortNameAsCharacter; + local int optionIndex; + local BaseText.Character shortNameAsCharacter; // Unlike for `SubCommand()`, we need to ensure that option naming is // correct and does not conflict with existing options // (user might attempt to add two options with same long names and @@ -440,7 +440,7 @@ public final function CommandDataBuilder Option( * @return Returns the caller `CommandDataBuilder` to allow for * method chaining. */ -public final function CommandDataBuilder Describe(Text description) +public final function CommandDataBuilder Describe(BaseText description) { if (selectedDescription == description) { return self; @@ -459,7 +459,7 @@ public final function CommandDataBuilder Describe(Text description) * @return Returns the caller `CommandDataBuilder` to allow for * method chaining. */ -public final function CommandDataBuilder Name(Text newName) +public final function CommandDataBuilder Name(BaseText newName) { if (newName != none && newName == commandName) { return self; @@ -481,7 +481,7 @@ public final function CommandDataBuilder Name(Text newName) * @return Returns the caller `CommandDataBuilder` to allow for * method chaining. */ -public final function CommandDataBuilder Summary(Text newSummary) +public final function CommandDataBuilder Summary(BaseText newSummary) { if (newSummary != none && newSummary == commandSummary) { return self; @@ -561,10 +561,10 @@ private final function PushParameter(Command.Parameter newParameter) // Fills `Command.ParameterType` struct with given values // (except boolean format). Assumes `displayName != none`. private final function Command.Parameter NewParameter( - Text displayName, + BaseText displayName, Command.ParameterType parameterType, bool isListParameter, - optional Text variableName) + optional BaseText variableName) { local Command.Parameter newParameter; newParameter.displayName = displayName.Copy(); @@ -574,7 +574,7 @@ private final function Command.Parameter NewParameter( newParameter.variableName = variableName.Copy(); } else { - newParameter.variableName = displayName; + newParameter.variableName = displayName.Copy(); } return newParameter; } @@ -601,9 +601,9 @@ private final function Command.Parameter NewParameter( * method chaining. */ public final function CommandDataBuilder ParamBoolean( - Text name, + BaseText name, optional Command.PreferredBooleanFormat format, - optional Text variableName) + optional BaseText variableName) { local Command.Parameter newParam; if (name == none) { @@ -636,9 +636,9 @@ public final function CommandDataBuilder ParamBoolean( * method chaining. */ public final function CommandDataBuilder ParamBooleanList( - Text name, + BaseText name, optional Command.PreferredBooleanFormat format, - optional Text variableName) + optional BaseText variableName) { local Command.Parameter newParam; if (name == none) { @@ -667,8 +667,8 @@ public final function CommandDataBuilder ParamBooleanList( * method chaining. */ public final function CommandDataBuilder ParamInteger( - Text name, - optional Text variableName) + BaseText name, + optional BaseText variableName) { if (name == none) { return self; @@ -694,8 +694,8 @@ public final function CommandDataBuilder ParamInteger( * method chaining. */ public final function CommandDataBuilder ParamIntegerList( - Text name, - optional Text variableName) + BaseText name, + optional BaseText variableName) { if (name == none) { return self; @@ -721,8 +721,8 @@ public final function CommandDataBuilder ParamIntegerList( * method chaining. */ public final function CommandDataBuilder ParamNumber( - Text name, - optional Text variableName) + BaseText name, + optional BaseText variableName) { if (name == none) { return self; @@ -748,8 +748,8 @@ public final function CommandDataBuilder ParamNumber( * method chaining. */ public final function CommandDataBuilder ParamNumberList( - Text name, - optional Text variableName) + BaseText name, + optional BaseText variableName) { if (name == none) { return self; @@ -775,8 +775,8 @@ public final function CommandDataBuilder ParamNumberList( * method chaining. */ public final function CommandDataBuilder ParamText( - Text name, - optional Text variableName) + BaseText name, + optional BaseText variableName) { if (name == none) { return self; @@ -802,8 +802,8 @@ public final function CommandDataBuilder ParamText( * method chaining. */ public final function CommandDataBuilder ParamTextList( - Text name, - optional Text variableName) + BaseText name, + optional BaseText variableName) { if (name == none) { return self; @@ -829,8 +829,8 @@ public final function CommandDataBuilder ParamTextList( * method chaining. */ public final function CommandDataBuilder ParamRemainder( - Text name, - optional Text variableName) + BaseText name, + optional BaseText variableName) { if (name == none) { return self; @@ -856,8 +856,8 @@ public final function CommandDataBuilder ParamRemainder( * method chaining. */ public final function CommandDataBuilder ParamObject( - Text name, - optional Text variableName) + BaseText name, + optional BaseText variableName) { if (name == none) { return self; @@ -883,8 +883,8 @@ public final function CommandDataBuilder ParamObject( * method chaining. */ public final function CommandDataBuilder ParamObjectList( - Text name, - optional Text variableName) + BaseText name, + optional BaseText variableName) { if (name == none) { return self; @@ -910,8 +910,8 @@ public final function CommandDataBuilder ParamObjectList( * method chaining. */ public final function CommandDataBuilder ParamArray( - Text name, - optional Text variableName) + BaseText name, + optional BaseText variableName) { if (name == none) { return self; @@ -937,8 +937,8 @@ public final function CommandDataBuilder ParamArray( * method chaining. */ public final function CommandDataBuilder ParamArrayList( - Text name, - optional Text variableName) + BaseText name, + optional BaseText variableName) { if (name == none) { return self; diff --git a/sources/Commands/CommandParser.uc b/sources/Commands/CommandParser.uc index 702ac78..d35d6c2 100644 --- a/sources/Commands/CommandParser.uc +++ b/sources/Commands/CommandParser.uc @@ -141,7 +141,7 @@ private final function Reset() // Auxiliary method for recording errors private final function DeclareError( Command.ErrorType type, - optional Text cause) + optional BaseText cause) { nextResult.parsingError = type; if (cause != none) { @@ -764,9 +764,9 @@ private final function bool ParseShortOption() // `nextError.DeclareError()` call, so you can use `nextResult.IsSuccessful()` // to check if method has failed. private final function bool AddOptionByCharacter( - Text.Character optionCharacter, - Text optionSourceList, - bool forbidOptionWithParameters) + BaseText.Character optionCharacter, + BaseText optionSourceList, + bool forbidOptionWithParameters) { local int i; local bool optionHasParameters; diff --git a/sources/Commands/Commands.uc b/sources/Commands/Commands.uc index 37ecaeb..d6b37ff 100644 --- a/sources/Commands/Commands.uc +++ b/sources/Commands/Commands.uc @@ -44,7 +44,7 @@ protected function FromData(AssociativeArray source) } useChatInput = source.GetBool(P("useChatInput")); useMutateInput = source.GetBool(P("useMutateInput")); - newChatPrefix = source.GetText(P("chatCommandPrefix")); + newChatPrefix = source.GetText(P("chatCommandPrefix")); chatCommandPrefix = "!"; if (newChatPrefix != none) { chatCommandPrefix = newChatPrefix.ToString(); diff --git a/sources/Commands/Commands_Feature.uc b/sources/Commands/Commands_Feature.uc index 2b44b9a..c65023f 100644 --- a/sources/Commands/Commands_Feature.uc +++ b/sources/Commands/Commands_Feature.uc @@ -185,7 +185,7 @@ public final function RemoveCommand(class commandClass) * @return Command, registered with a given name `commandName`. * If no command with such name was registered - returns `none`. */ -public final function Command GetCommand(Text commandName) +public final function Command GetCommand(BaseText commandName) { local Text commandNameLowerCase; local Command commandInstance; diff --git a/sources/Commands/PlayersParser.uc b/sources/Commands/PlayersParser.uc index 3f06a63..bf84f8c 100644 --- a/sources/Commands/PlayersParser.uc +++ b/sources/Commands/PlayersParser.uc @@ -153,7 +153,7 @@ private final function RemoveByKey(int key) } // Adds all the players with specified name (`name`) to the current selection. -private final function AddByName(Text name) +private final function AddByName(BaseText name) { local int i; local Text nextPlayerName; @@ -170,7 +170,7 @@ private final function AddByName(Text name) // Removes all the players with specified name (`name`) from // the current selection. -private final function RemoveByName(Text name) +private final function RemoveByName(BaseText name) { local int i; local Text nextPlayerName; @@ -216,7 +216,7 @@ private final function RemoveAdmins() // Add all the players specified by `macroText` (from macro "@"). // Does nothing if there is no such macro. -private final function AddByMacro(Text macroText) +private final function AddByMacro(BaseText macroText) { if (macroText.Compare(T(TADMIN), SCASE_INSENSITIVE)) { @@ -239,7 +239,7 @@ private final function AddByMacro(Text macroText) // Removes all the players specified by `macroText` // (from macro "@"). // Does nothing if there is no such macro. -private final function RemoveByMacro(Text macroText) +private final function RemoveByMacro(BaseText macroText) { local int i; if (macroText.Compare(T(TADMIN), SCASE_INSENSITIVE)) @@ -478,7 +478,7 @@ private final function Reset() * @param toParse `Text` from which to parse player list. * @return `true` if parsing was successful and `false` otherwise. */ -public final function bool Parse(Text toParse) +public final function bool Parse(BaseText toParse) { local bool wasSuccessful; local Parser parser; diff --git a/sources/Config/AcediaConfig.uc b/sources/Config/AcediaConfig.uc index fa2bb23..f426372 100644 --- a/sources/Config/AcediaConfig.uc +++ b/sources/Config/AcediaConfig.uc @@ -153,7 +153,7 @@ private static function string NameToActualVersion(string configObjectName) * @return `false` iff config object name `name` already existed * or `name` is invalid for config object. */ -public final static function bool NewConfig(Text name) +public final static function bool NewConfig(BaseText name) { local AcediaConfig newConfig; if (name == none) return false; @@ -186,7 +186,7 @@ public final static function bool NewConfig(Text name) * and dot ('.') character. * @return `true` iff new config object was created. */ -public final static function bool Exists(Text name) +public final static function bool Exists(BaseText name) { local bool result; if (name == none) return false; @@ -214,7 +214,7 @@ public final static function bool Exists(Text name) * Case-insensitive, must contain only ASCII latin letters, digits * and dot ('.') character. */ -public final static function DeleteConfig(Text name) +public final static function DeleteConfig(BaseText name) { local AssociativeArray.Entry entry; if (default.existingConfigs == none) { @@ -250,7 +250,7 @@ public static function array AvailableConfigs() * digits and dot ('.') character. * @return `AcediaConfig` of caller class with name `name`. */ -public final static function AcediaConfig GetConfigInstance(Text name) +public final static function AcediaConfig GetConfigInstance(BaseText name) { local AssociativeArray.Entry configEntry; if (name == none) return none; @@ -286,7 +286,7 @@ public final static function AcediaConfig GetConfigInstance(Text 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(Text name) +public final static function AssociativeArray LoadData(BaseText name) { local AssociativeArray result; local AcediaConfig requiredConfig; @@ -311,7 +311,7 @@ public final static function AssociativeArray LoadData(Text name) * allows for JSON deserialization (see `JSONAPI.IsCompatible()` for * details). */ -public final static function SaveData(Text name, AssociativeArray data) +public final static function SaveData(BaseText name, AssociativeArray data) { local AcediaConfig requiredConfig; requiredConfig = GetConfigInstance(name); diff --git a/sources/Console/ConsoleBuffer.uc b/sources/Console/ConsoleBuffer.uc index 09b74bf..94d5b05 100644 --- a/sources/Console/ConsoleBuffer.uc +++ b/sources/Console/ConsoleBuffer.uc @@ -21,7 +21,7 @@ * along with Acedia. If not, see . */ class ConsoleBuffer extends AcediaObject - dependson(Text) + dependson(BaseText) dependson(ConsoleAPI); /** @@ -177,10 +177,10 @@ public final function ConsoleBuffer Clear() * @param inputType How to treat given `string` regarding coloring. * @return Returns caller `ConsoleBuffer` to allow method chaining. */ -public final function ConsoleBuffer Insert(Text input) +public final function ConsoleBuffer Insert(BaseText input) { - local int inputConsumed; - local Text.Character nextCharacter; + local int inputConsumed; + local BaseText.Character nextCharacter; if (input == none) { return self; } @@ -249,11 +249,11 @@ public final function ConsoleBuffer Flush() // It is assumed that passed characters are not whitespace, - // responsibility to check is on the one calling this method. -private final function InsertIntoWordBuffer(Text.Character newCharacter) +private final function InsertIntoWordBuffer(BaseText.Character newCharacter) { - local int newCharacterIndex; - local Text.Formatting newFormatting; - local Color oldColor, newColor; + local int newCharacterIndex; + local BaseText.Formatting newFormatting; + local Color oldColor, newColor; // Fix text color in the buffer to remember default color, if we use it. newFormatting = _.text.GetCharacterFormatting(newCharacter); newFormatting.color = @@ -336,7 +336,7 @@ private final function bool CanAppendWhitespaceIntoLine() } private final function bool CanAppendNonWhitespaceIntoLine( - Text.Character nextCharacter) + BaseText.Character nextCharacter) { // We always allow to insert at least something into empty line, // otherwise we can never insert it anywhere @@ -357,7 +357,8 @@ private final function bool CanAppendNonWhitespaceIntoLine( // For performance reasons assumes that passed character is a whitespace, // the burden of checking is on the caller. -private final function AppendWhitespaceToCurrentLine(Text.Character whitespace) +private final function AppendWhitespaceToCurrentLine( + BaseText.Character whitespace) { if (_.text.IsCodePoint(whitespace, CODEPOINT_NEWLINE)) { BreakLine(false); diff --git a/sources/Console/ConsoleWriter.uc b/sources/Console/ConsoleWriter.uc index 55bcf15..23ad5f5 100644 --- a/sources/Console/ConsoleWriter.uc +++ b/sources/Console/ConsoleWriter.uc @@ -505,7 +505,7 @@ public final function ConsoleWriter Flush() * @param message `Text` to output. * @return Returns caller `ConsoleWriter` to allow for method chaining. */ -public final function ConsoleWriter Write(optional Text message) +public final function ConsoleWriter Write(optional BaseText message) { outputBuffer.Insert(message); if (needToResetColor) { @@ -521,7 +521,7 @@ public final function ConsoleWriter Write(optional Text message) * @param message `Text` to output. * @return Returns caller `ConsoleWriter` to allow for method chaining. */ -public final function ConsoleWriter WriteLine(optional Text message) +public final function ConsoleWriter WriteLine(optional BaseText message) { return Write(message).Flush(); } @@ -538,7 +538,7 @@ public final function ConsoleWriter WriteLine(optional Text message) * @param message `Text` to output. * @return Returns caller `ConsoleWriter` to allow for method chaining. */ -public final function ConsoleWriter WriteBlock(optional Text message) +public final function ConsoleWriter WriteBlock(optional BaseText message) { outputBuffer.Insert(message).Flush(); SendBuffer(true); @@ -558,7 +558,7 @@ public final function ConsoleWriter WriteBlock(optional Text message) * @param message `Text` to output. * @return Returns caller `ConsoleWriter` to allow for method chaining. */ -public final function ConsoleWriter Say(optional Text message) +public final function ConsoleWriter Say(optional BaseText message) { outputBuffer.Insert(message).Flush(); SendBuffer(, true); diff --git a/sources/Data/Collections/AssociativeArray.uc b/sources/Data/Collections/AssociativeArray.uc index 920a88a..5e6867a 100644 --- a/sources/Data/Collections/AssociativeArray.uc +++ b/sources/Data/Collections/AssociativeArray.uc @@ -669,7 +669,7 @@ public final function Entry GetEntryByIndex(Index index) return hashTable[index.bucketIndex].entries[index.entryIndex]; } -protected function AcediaObject GetByText(Text key) +protected function AcediaObject GetByText(BaseText key) { return GetItem(key); } diff --git a/sources/Data/Collections/Collection.uc b/sources/Data/Collections/Collection.uc index f882f9b..4344e12 100644 --- a/sources/Data/Collections/Collection.uc +++ b/sources/Data/Collections/Collection.uc @@ -36,7 +36,7 @@ var protected class iteratorClass; * this method (i.e. `AssociativeArray` only lets you access values with * `Text` keys). */ -protected function AcediaObject GetByText(Text key); +protected function AcediaObject GetByText(BaseText key); /** * Creates an `Iterator` instance to iterate over stored items. @@ -166,7 +166,7 @@ public final function AcediaObject GetItemByJSON(JSONPointer jsonPointer) * @return An item `jsonPointerAsText` is referring to (according to the above * stated rules). `none` if such item does not exist. */ -public final function AcediaObject GetItemBy(Text jsonPointerAsText) +public final function AcediaObject GetItemBy(BaseText jsonPointerAsText) { local AcediaObject result; local JSONPointer jsonPointer; @@ -196,7 +196,7 @@ public final function AcediaObject GetItemBy(Text jsonPointerAsText) * is missing or has a different type. */ public final function bool GetBoolBy( - Text jsonPointerAsText, + BaseText jsonPointerAsText, optional bool defaultValue) { local AcediaObject result; @@ -234,7 +234,7 @@ public final function bool GetBoolBy( * is missing or has a different type. */ public final function byte GetByteBy( - Text jsonPointerAsText, + BaseText jsonPointerAsText, optional byte defaultValue) { local AcediaObject result; @@ -272,7 +272,7 @@ public final function byte GetByteBy( * is missing or has a different type. */ public final function int GetIntBy( - Text jsonPointerAsText, + BaseText jsonPointerAsText, optional int defaultValue) { local AcediaObject result; @@ -310,7 +310,7 @@ public final function int GetIntBy( * is missing or has a different type. */ public final function float GetFloatBy( - Text jsonPointerAsText, + BaseText jsonPointerAsText, optional float defaultValue) { local AcediaObject result; @@ -344,7 +344,7 @@ public final function float GetFloatBy( * @return `Text` value, stored at `jsonPointerAsText` or `none` if it * is missing or has a different type. */ -public final function Text GetTextBy(Text jsonPointerAsText) +public final function Text GetTextBy(BaseText jsonPointerAsText) { return Text(GetItemBy(jsonPointerAsText)); } @@ -364,7 +364,7 @@ public final function Text GetTextBy(Text jsonPointerAsText) * `none` if it is missing or has a different type. */ public final function AssociativeArray GetAssociativeArrayBy( - Text jsonPointerAsText) + BaseText jsonPointerAsText) { return AssociativeArray(GetItemBy(jsonPointerAsText)); } @@ -383,7 +383,7 @@ public final function AssociativeArray GetAssociativeArrayBy( * @return `DynamicArray` value, stored at `jsonPointerAsText` or * `none` if it is missing or has a different type. */ -public final function DynamicArray GetDynamicArrayBy(Text jsonPointerAsText) +public final function DynamicArray GetDynamicArrayBy(BaseText jsonPointerAsText) { return DynamicArray(GetItemBy(jsonPointerAsText)); } diff --git a/sources/Data/Collections/DynamicArray.uc b/sources/Data/Collections/DynamicArray.uc index c4e985f..0a723e5 100644 --- a/sources/Data/Collections/DynamicArray.uc +++ b/sources/Data/Collections/DynamicArray.uc @@ -479,7 +479,7 @@ public final function int Find(AcediaObject item) return -1; } -protected function AcediaObject GetByText(Text key) +protected function AcediaObject GetByText(BaseText key) { local int index, consumed; local Parser parser; diff --git a/sources/Data/Database/DBAPI.uc b/sources/Data/Database/DBAPI.uc index 29314e9..8d29c02 100644 --- a/sources/Data/Database/DBAPI.uc +++ b/sources/Data/Database/DBAPI.uc @@ -51,7 +51,7 @@ private final function CreateLocalDBMapIfMissing() * @param databaseLink Link from which to extract database's name. * @return Database named "" of type "" from the `databaseLink`. */ -public final function Database Load(Text databaseLink) +public final function Database Load(BaseText databaseLink) { local Parser parser; local Database result; @@ -94,7 +94,7 @@ public final function Database Load(Text databaseLink) * Guaranteed to not be `none` if provided argument `databaseLink` * is not `none`. */ -public final function JSONPointer GetPointer(Text databaseLink) +public final function JSONPointer GetPointer(BaseText databaseLink) { local int slashIndex; local Text textPointer; @@ -122,7 +122,7 @@ public final function JSONPointer GetPointer(Text databaseLink) * @param databaseName Name for the new database. * @return Reference to created database. Returns `none` iff method failed. */ -public final function LocalDatabaseInstance NewLocal(Text databaseName) +public final function LocalDatabaseInstance NewLocal(BaseText databaseName) { local DBRecord rootRecord; local Text rootRecordName; @@ -158,7 +158,7 @@ public final function LocalDatabaseInstance NewLocal(Text databaseName) * @param databaseName Name of the database to load. * @return Loaded local database. `none` if it does not exist. */ -public final function LocalDatabaseInstance LoadLocal(Text databaseName) +public final function LocalDatabaseInstance LoadLocal(BaseText databaseName) { local DBRecord rootRecord; local Text rootRecordName; @@ -209,7 +209,7 @@ public final function LocalDatabaseInstance LoadLocal(Text databaseName) * @param databaseName Name of the database to check. * @return `true` if database with specified name exists and `false` otherwise. */ -public final function bool ExistsLocal(Text databaseName) +public final function bool ExistsLocal(BaseText databaseName) { return LoadLocal(databaseName) != none; } @@ -221,7 +221,7 @@ public final function bool ExistsLocal(Text databaseName) * @return `true` if database with specified name existed and was deleted and * `false` otherwise. */ -public final function bool DeleteLocal(Text databaseName) +public final function bool DeleteLocal(BaseText databaseName) { local LocalDatabase localDatabaseConfig; local LocalDatabaseInstance localDatabase; @@ -250,7 +250,7 @@ public final function bool DeleteLocal(Text databaseName) return false; } -private function EraseAllPackageData(Text packageToErase) +private function EraseAllPackageData(BaseText packageToErase) { local int i; local string packageName; diff --git a/sources/Data/Database/Local/DBRecord.uc b/sources/Data/Database/Local/DBRecord.uc index 5137558..0107919 100644 --- a/sources/Data/Database/Local/DBRecord.uc +++ b/sources/Data/Database/Local/DBRecord.uc @@ -266,7 +266,7 @@ public static final function Global __() * @return New `DBRecord`, created in specified package. * `none` iff `dbPackageName == none`. */ -public final static function DBRecord NewRecord(Text dbPackageName) +public final static function DBRecord NewRecord(BaseText dbPackageName) { if (dbPackageName == none) { return none; @@ -303,8 +303,8 @@ private final static function DBRecord NewRecordFor(string dbPackageName) } public final static function DBRecord LoadRecord( - Text recordName, - Text dbPackageName) + BaseText recordName, + BaseText dbPackageName) { if (dbPackageName == none) return none; if (recordName == none) return none; diff --git a/sources/Data/Database/Local/LocalDatabase.uc b/sources/Data/Database/Local/LocalDatabase.uc index 238199b..ce7a013 100644 --- a/sources/Data/Database/Local/LocalDatabase.uc +++ b/sources/Data/Database/Local/LocalDatabase.uc @@ -48,7 +48,7 @@ public final function Text GetRootName() * * Only makes changes if root is not already defined. */ -public final function SetRootName(Text rootName) +public final function SetRootName(BaseText rootName) { if (HasDefinedRoot()) { return; @@ -61,7 +61,7 @@ public final function SetRootName(Text rootName) } } -public final static function LocalDatabase Load(Text databaseName) +public final static function LocalDatabase Load(BaseText databaseName) { if (!__().text.IsEmpty(databaseName)) { return new(none, databaseName.ToString()) class'LocalDatabase'; diff --git a/sources/Data/Database/Tests/TEST_LocalDatabase.uc b/sources/Data/Database/Tests/TEST_LocalDatabase.uc index 4b25c45..c05ab5d 100644 --- a/sources/Data/Database/Tests/TEST_LocalDatabase.uc +++ b/sources/Data/Database/Tests/TEST_LocalDatabase.uc @@ -1000,7 +1000,7 @@ protected static function SubTest_IncrementString(LocalDatabaseInstance db) TEST_ExpectTrue( Text(default.resultObject).ToString() == "simpleValue!"); task = db.IncrementData(__().json.Pointer(P("/A")), - __().text.FromStringM("?")); + __().text.FromString("?")); task.connect = DBIncrementHandler; task.TryCompleting(); TEST_ExpectTrue(default.resultType == DBR_Success); diff --git a/sources/Features/Feature.uc b/sources/Features/Feature.uc index 2daff5c..4fdd479 100644 --- a/sources/Features/Feature.uc +++ b/sources/Features/Feature.uc @@ -138,8 +138,9 @@ protected function Finalizer() * * @param newConfigName Name of the config to apply to the caller `Feature`. */ -private final function ApplyConfig(Text newConfigName) +private final function ApplyConfig(BaseText newConfigName) { + local Text configNameCopy; local FeatureConfig newConfig; if (newConfigName == none) { return; @@ -150,17 +151,17 @@ private final function ApplyConfig(Text newConfigName) { _.logger.Auto(errorBadConfigData).ArgClass(class); // Fallback to "default" config - newConfigName = _.text.FromString(defaultConfigName); - configClass.static.NewConfig(newConfigName); + configNameCopy = _.text.FromString(defaultConfigName); + configClass.static.NewConfig(configNameCopy); newConfig = - FeatureConfig(configClass.static.GetConfigInstance(newConfigName)); + FeatureConfig(configClass.static.GetConfigInstance(configNameCopy)); } else { - newConfigName = newConfigName.Copy(); + configNameCopy = newConfigName.Copy(); } SwapConfig(newConfig); _.memory.Free(currentConfigName); - currentConfigName = newConfigName; + currentConfigName = configNameCopy; } /** @@ -258,7 +259,7 @@ public static final function bool IsEnabled() * Passing `none` will make caller `Feature` use "default" config. * @return Active instance of the caller `Feature` class. */ -public static final function Feature EnableMe(Text configName) +public static final function Feature EnableMe(BaseText configName) { local Feature myInstance; if (configName == none) { diff --git a/sources/Features/FeatureConfig.uc b/sources/Features/FeatureConfig.uc index 0cdbbec..23544d2 100644 --- a/sources/Features/FeatureConfig.uc +++ b/sources/Features/FeatureConfig.uc @@ -97,7 +97,7 @@ public static function Text GetAutoEnabledConfig() * @return `true` iff some config was set to be used when it's `Feature` is * auto-enabled, even if the same config was already configured to be used. */ -public static function bool SetAutoEnabledConfig(Text autoEnabledConfigName) +public static function bool SetAutoEnabledConfig(BaseText autoEnabledConfigName) { local int i; local array names; diff --git a/sources/Gameplay/BaseClasses/Frontend/Templates/ATemplatesComponent.uc b/sources/Gameplay/BaseClasses/Frontend/Templates/ATemplatesComponent.uc index 77a8366..b78c43d 100644 --- a/sources/Gameplay/BaseClasses/Frontend/Templates/ATemplatesComponent.uc +++ b/sources/Gameplay/BaseClasses/Frontend/Templates/ATemplatesComponent.uc @@ -31,7 +31,7 @@ class ATemplatesComponent extends AcediaObject * @return `true` if list named `listName` exists and `false` otherwise. * Always returns `false` if `listName` equals `none`. */ -public function bool ItemListExists(Text listName) +public function bool ItemListExists(BaseText listName) { return false; } @@ -54,7 +54,7 @@ public function bool ItemListExists(Text listName) * When incorrect `listName` is specified - empty array is returned * (which can also happen if specified list is empty). */ -public function array GetItemList(Text listName) +public function array GetItemList(BaseText listName) { local array emptyArray; return emptyArray; diff --git a/sources/Gameplay/BaseClasses/KillingFloor/Frontend/KFFrontend.uc b/sources/Gameplay/BaseClasses/KillingFloor/Frontend/KFFrontend.uc index e7d035f..711efc9 100644 --- a/sources/Gameplay/BaseClasses/KillingFloor/Frontend/KFFrontend.uc +++ b/sources/Gameplay/BaseClasses/KillingFloor/Frontend/KFFrontend.uc @@ -46,7 +46,7 @@ protected function Finalizer() * `none` if item template with given name does not exist or passed * `templateName` is equal to `none`. */ -public function EItemTemplateInfo GetItemTemplateInfo(Text templateName) +public function EItemTemplateInfo GetItemTemplateInfo(BaseText templateName) { return none; } diff --git a/sources/Gameplay/BaseClasses/KillingFloor/Frontend/Trading/ATradingComponent.uc b/sources/Gameplay/BaseClasses/KillingFloor/Frontend/Trading/ATradingComponent.uc index 9622bac..187c8d6 100644 --- a/sources/Gameplay/BaseClasses/KillingFloor/Frontend/Trading/ATradingComponent.uc +++ b/sources/Gameplay/BaseClasses/KillingFloor/Frontend/Trading/ATradingComponent.uc @@ -100,7 +100,7 @@ public function array GetTraders(); * @return `ETrader` with a given `traderName`. `none` if either `traderName` * is `none` or there is no trader with such a name. */ -public function ETrader GetTrader(Text traderName); +public function ETrader GetTrader(BaseText traderName); /** * Checks whether trading is currently active. diff --git a/sources/Gameplay/BaseClasses/KillingFloor/Frontend/Trading/ETrader.uc b/sources/Gameplay/BaseClasses/KillingFloor/Frontend/Trading/ETrader.uc index 138016e..a60eb1d 100644 --- a/sources/Gameplay/BaseClasses/KillingFloor/Frontend/Trading/ETrader.uc +++ b/sources/Gameplay/BaseClasses/KillingFloor/Frontend/Trading/ETrader.uc @@ -60,7 +60,7 @@ public function Text GetName(); * @param newName New name of the caller trader. * @return `true` if trader is currently enabled and `false` otherwise. */ -public function ETrader SetName(Text newName); +public function ETrader SetName(BaseText newName); /** * Checks if caller trader is currently enabled. diff --git a/sources/Gameplay/KF1Frontend/BaseImplementation/EKFAmmo.uc b/sources/Gameplay/KF1Frontend/BaseImplementation/EKFAmmo.uc index 776f39a..bf5e5e9 100644 --- a/sources/Gameplay/KF1Frontend/BaseImplementation/EKFAmmo.uc +++ b/sources/Gameplay/KF1Frontend/BaseImplementation/EKFAmmo.uc @@ -121,7 +121,7 @@ public function array GetTags() return tagArray; } -public function bool HasTag(Text tagToCheck) +public function bool HasTag(BaseText tagToCheck) { if (tagToCheck == none) return false; if (tagToCheck.Compare(P("ammo"))) return true; diff --git a/sources/Gameplay/KF1Frontend/BaseImplementation/EKFFlashlightAmmo.uc b/sources/Gameplay/KF1Frontend/BaseImplementation/EKFFlashlightAmmo.uc index 6d24c1d..e3a5aaa 100644 --- a/sources/Gameplay/KF1Frontend/BaseImplementation/EKFFlashlightAmmo.uc +++ b/sources/Gameplay/KF1Frontend/BaseImplementation/EKFFlashlightAmmo.uc @@ -121,7 +121,7 @@ public function array GetTags() return tagArray; } -public function bool HasTag(Text tagToCheck) +public function bool HasTag(BaseText tagToCheck) { if (tagToCheck == none) return false; if (tagToCheck.Compare(P("ammo"))) return true; diff --git a/sources/Gameplay/KF1Frontend/BaseImplementation/EKFInventory.uc b/sources/Gameplay/KF1Frontend/BaseImplementation/EKFInventory.uc index 731c011..e80a8e8 100644 --- a/sources/Gameplay/KF1Frontend/BaseImplementation/EKFInventory.uc +++ b/sources/Gameplay/KF1Frontend/BaseImplementation/EKFInventory.uc @@ -310,7 +310,7 @@ public function EItem Add(EItem newItem, optional bool forceAddition) * and can fail adding an item even if `CanAddTemplate()` succeeded. */ public function EItem AddTemplate( - Text newItemTemplate, + BaseText newItemTemplate, optional bool forceAddition) { local Pawn pawn; @@ -399,7 +399,7 @@ public function Text CanAddExplain( * and can raise "faulty implementation" error in case it cannot. */ public function Text CanAddTemplateExplain( - Text itemTemplateToCheck, + BaseText itemTemplateToCheck, optional bool forceAddition) { local class inventoryClass; @@ -614,7 +614,7 @@ public function bool Remove( * added by other mods) items. */ public function bool RemoveTemplate( - Text template, + BaseText template, optional bool keepItem, optional bool forceRemoval, optional bool removeAll) @@ -962,7 +962,7 @@ public function bool Contains(EItem itemToCheck) return false; } -public function bool ContainsTemplate(Text itemTemplateToCheck) +public function bool ContainsTemplate(BaseText itemTemplateToCheck) { local bool success; local EItem templateItem; @@ -1100,7 +1100,7 @@ public function array GetItemsSupporting(class interfaceClass) return GetItemsByFlags(getWeapon, getAmmo, false); } -public function array GetTagItems(Text tag) +public function array GetTagItems(BaseText tag) { local array emptyArray; local bool getWeapon, getAmmo; @@ -1112,7 +1112,7 @@ public function array GetTagItems(Text tag) return GetItemsByFlags(getWeapon, getAmmo, false); } -public function EItem GetTagItem(Text tag) +public function EItem GetTagItem(BaseText tag) { local bool getWeapon, getAmmo; if (tag == none) { @@ -1123,7 +1123,7 @@ public function EItem GetTagItem(Text tag) return GetItemByFlags(getWeapon, getAmmo, false); } -public function array GetTemplateItems(Text template) +public function array GetTemplateItems(BaseText template) { local Pawn pawn; local bool getBuiltInAmmo; @@ -1173,7 +1173,7 @@ public function array GetTemplateItems(Text template) return result; } -public function EItem GetTemplateItem(Text template) +public function EItem GetTemplateItem(BaseText template) { local Pawn pawn; local bool getBuiltInAmmo; diff --git a/sources/Gameplay/KF1Frontend/BaseImplementation/EKFMedicAmmo.uc b/sources/Gameplay/KF1Frontend/BaseImplementation/EKFMedicAmmo.uc index fdd6c72..eeed5db 100644 --- a/sources/Gameplay/KF1Frontend/BaseImplementation/EKFMedicAmmo.uc +++ b/sources/Gameplay/KF1Frontend/BaseImplementation/EKFMedicAmmo.uc @@ -120,7 +120,7 @@ public function array GetTags() return tagArray; } -public function bool HasTag(Text tagToCheck) +public function bool HasTag(BaseText tagToCheck) { if (tagToCheck == none) return false; if (tagToCheck.Compare(P("ammo"))) return true; diff --git a/sources/Gameplay/KF1Frontend/BaseImplementation/EKFSyringeAmmo.uc b/sources/Gameplay/KF1Frontend/BaseImplementation/EKFSyringeAmmo.uc index bf34b98..72933b2 100644 --- a/sources/Gameplay/KF1Frontend/BaseImplementation/EKFSyringeAmmo.uc +++ b/sources/Gameplay/KF1Frontend/BaseImplementation/EKFSyringeAmmo.uc @@ -120,7 +120,7 @@ public function array GetTags() return tagArray; } -public function bool HasTag(Text tagToCheck) +public function bool HasTag(BaseText tagToCheck) { if (tagToCheck == none) return false; if (tagToCheck.Compare(P("ammo"))) return true; diff --git a/sources/Gameplay/KF1Frontend/BaseImplementation/EKFUnknownItem.uc b/sources/Gameplay/KF1Frontend/BaseImplementation/EKFUnknownItem.uc index c5a1a6a..d809a15 100644 --- a/sources/Gameplay/KF1Frontend/BaseImplementation/EKFUnknownItem.uc +++ b/sources/Gameplay/KF1Frontend/BaseImplementation/EKFUnknownItem.uc @@ -111,7 +111,7 @@ public function array GetTags() return emptyArray; } -public function bool HasTag(Text tagToCheck) +public function bool HasTag(BaseText tagToCheck) { return false; } diff --git a/sources/Gameplay/KF1Frontend/BaseImplementation/EKFWeapon.uc b/sources/Gameplay/KF1Frontend/BaseImplementation/EKFWeapon.uc index ad30565..d08174f 100644 --- a/sources/Gameplay/KF1Frontend/BaseImplementation/EKFWeapon.uc +++ b/sources/Gameplay/KF1Frontend/BaseImplementation/EKFWeapon.uc @@ -118,7 +118,7 @@ public function array GetTags() return tagArray; } -public function bool HasTag(Text tagToCheck) +public function bool HasTag(BaseText tagToCheck) { if (tagToCheck == none) return false; if (tagToCheck.Compare(P("weapon"))) return true; diff --git a/sources/Gameplay/KF1Frontend/KF1_Frontend.uc b/sources/Gameplay/KF1Frontend/KF1_Frontend.uc index ad34233..bf395cd 100644 --- a/sources/Gameplay/KF1Frontend/KF1_Frontend.uc +++ b/sources/Gameplay/KF1Frontend/KF1_Frontend.uc @@ -21,7 +21,7 @@ */ class KF1_Frontend extends KFFrontend; -public function EItemTemplateInfo GetItemTemplateInfo(Text templateName) +public function EItemTemplateInfo GetItemTemplateInfo(BaseText templateName) { local class inventoryClass; inventoryClass = class(_.memory.LoadClass(templateName)); diff --git a/sources/Gameplay/KF1Frontend/Templates/KF1_TemplatesComponent.uc b/sources/Gameplay/KF1Frontend/Templates/KF1_TemplatesComponent.uc index 4b99645..cc84f31 100644 --- a/sources/Gameplay/KF1Frontend/Templates/KF1_TemplatesComponent.uc +++ b/sources/Gameplay/KF1Frontend/Templates/KF1_TemplatesComponent.uc @@ -150,7 +150,7 @@ private function array CopyList(array inputList) return outputList; } -public function bool ItemListExists(Text listName) +public function bool ItemListExists(BaseText listName) { local string listNameAsString; if (listName == none) return false; @@ -171,7 +171,7 @@ public function bool ItemListExists(Text listName) return false; } -public function array GetItemList(Text listName) +public function array GetItemList(BaseText listName) { local string listNameAsString; local array emptyArray; diff --git a/sources/Gameplay/KF1Frontend/Trading/KF1_Trader.uc b/sources/Gameplay/KF1Frontend/Trading/KF1_Trader.uc index f1636eb..ad665a3 100644 --- a/sources/Gameplay/KF1Frontend/Trading/KF1_Trader.uc +++ b/sources/Gameplay/KF1Frontend/Trading/KF1_Trader.uc @@ -138,13 +138,13 @@ public final /* unreal */ function ShopVolume GetShopVolume() public function Text GetName() { if (myName == none) { - return _.text.Empty(); + return P(""); } return myName.Copy(); } // TODO: it is broken, needs fixing -public function ETrader SetName(Text newName) +public function ETrader SetName(BaseText newName) { if (newName == none) return self; if (newName.IsEmpty()) return self; diff --git a/sources/Gameplay/KF1Frontend/Trading/KF1_TradingComponent.uc b/sources/Gameplay/KF1Frontend/Trading/KF1_TradingComponent.uc index d636f10..d3cf987 100644 --- a/sources/Gameplay/KF1Frontend/Trading/KF1_TradingComponent.uc +++ b/sources/Gameplay/KF1Frontend/Trading/KF1_TradingComponent.uc @@ -84,7 +84,7 @@ public function array GetTraders() return result; } -public function ETrader GetTrader(Text traderName) +public function ETrader GetTrader(BaseText traderName) { local int i; local Text nextTraderName; diff --git a/sources/Logger/ConsoleLogger.uc b/sources/Logger/ConsoleLogger.uc index 0549f09..66b8e95 100644 --- a/sources/Logger/ConsoleLogger.uc +++ b/sources/Logger/ConsoleLogger.uc @@ -24,7 +24,7 @@ class ConsoleLogger extends Logger config(AcediaSystem) dependson(LoggerAPI); -public function Write(Text message, LoggerAPI.LogLevel messageLevel) +public function Write(BaseText message, LoggerAPI.LogLevel messageLevel) { local MutableText builder; if (message != none) diff --git a/sources/Logger/LogMessage.uc b/sources/Logger/LogMessage.uc index d0a69b0..8372005 100644 --- a/sources/Logger/LogMessage.uc +++ b/sources/Logger/LogMessage.uc @@ -79,7 +79,7 @@ var private array normalizedArguments; // amounts of trash objects, since only one of them can "make a mess". var private LogMessage dirtyLogMessage; // Arguments, collected so far by the `Arg*()` calls -var private array collectedArguments; +var private array collectedArguments; protected function Finalizer() { @@ -105,11 +105,11 @@ protected function Finalizer() */ public final function Initialize(LoggerAPI.Definition logMessageDefinition) { - local int nextArgument; - local Parser parser; - local MutableText nextLogPart, nextChunk; - local Text.Character percentCharacter; - local array parsedArguments; + local int nextArgument; + local Parser parser; + local MutableText nextLogPart, nextChunk; + local BaseText.Character percentCharacter; + local array parsedArguments; if (isInitialized) { return; } @@ -208,7 +208,7 @@ private final function NormalizeArguments(array argumentsOrder) * returned by `P()`, `C()` or `F()` calls. * @return Caller `LogMessage` to allow for method chaining. */ -public final function LogMessage Arg(Text argument) +public final function LogMessage Arg(/*take*/ BaseText argument) { if (IsArgumentListFull()) { return self; @@ -335,7 +335,7 @@ public final function Text Collect() { local int i, argumentIndex; local Text result; - local Text nextArgument; + local BaseText nextArgument; local MutableText builder; if (logParts.length == 0) { return P("").Copy(); diff --git a/sources/Logger/Logger.uc b/sources/Logger/Logger.uc index 32fca55..7240897 100644 --- a/sources/Logger/Logger.uc +++ b/sources/Logger/Logger.uc @@ -60,7 +60,7 @@ protected static function StaticFinalizer() * unless it is deallocated. * @return Logger with object name `loggerName`. */ -public final static function Logger GetLogger(Text loggerName) +public final static function Logger GetLogger(BaseText loggerName) { local Logger loggerInstance; local Text loggerKey; @@ -136,7 +136,7 @@ protected function MutableText GetPrefix(LoggerAPI.LogLevel messageLevel) * @param message Message to output. * @param messageLevel Level, at which message must be output. */ -public function Write(Text message, LoggerAPI.LogLevel messageLevel){} +public function Write(BaseText message, LoggerAPI.LogLevel messageLevel){} defaultproperties { diff --git a/sources/Logger/LoggerAPI.uc b/sources/Logger/LoggerAPI.uc index 2730640..42184d8 100644 --- a/sources/Logger/LoggerAPI.uc +++ b/sources/Logger/LoggerAPI.uc @@ -245,7 +245,7 @@ public final function LogMessage Auto(out Definition definition) * @param message Message to log. * @param messageLevel Level at which to log message. */ -public final function LogAtLevel(Text message, LogLevel messageLevel) +public final function LogAtLevel(BaseText message, LogLevel messageLevel) { switch (messageLevel) { @@ -274,7 +274,7 @@ public final function LogAtLevel(Text message, LogLevel messageLevel) * * @param message Message to log. */ -public final function Debug(Text message) +public final function Debug(BaseText message) { local int i; for (i = 0; i < debugLoggerInstances.length; i += 1) { @@ -288,7 +288,7 @@ public final function Debug(Text message) * * @param message Message to log. */ -public final function Info(Text message) +public final function Info(BaseText message) { local int i; for (i = 0; i < infoLoggerInstances.length; i += 1) { @@ -302,7 +302,7 @@ public final function Info(Text message) * * @param message Message to log. */ -public final function Warning(Text message) +public final function Warning(BaseText message) { local int i; for (i = 0; i < warningLoggerInstances.length; i += 1) { @@ -316,7 +316,7 @@ public final function Warning(Text message) * * @param message Message to log. */ -public final function Error(Text message) +public final function Error(BaseText message) { local int i; for (i = 0; i < errorLoggerInstances.length; i += 1) { @@ -330,7 +330,7 @@ public final function Error(Text message) * * @param message Message to log. */ -public final function Fatal(Text message) +public final function Fatal(BaseText message) { local int i; for (i = 0; i < fatalLoggerInstances.length; i += 1) { diff --git a/sources/Memory/MemoryAPI.uc b/sources/Memory/MemoryAPI.uc index 66838a9..777211e 100644 --- a/sources/Memory/MemoryAPI.uc +++ b/sources/Memory/MemoryAPI.uc @@ -30,7 +30,7 @@ class MemoryAPI extends AcediaObject; * @param classReference Text representation of the class to return. * @return Loaded class, corresponding to its name from `classReference`. */ -public final function class LoadClass(Text classReference) +public final function class LoadClass(BaseText classReference) { if (classReference == none) { return none; @@ -139,7 +139,7 @@ public final function Object Allocate( * guarantees to return last pooled object (in a LIFO queue), * unless `forceNewInstance == true`. * - * @param refToClassToAllocate `Text` representation of the class of + * @param refToClassToAllocate `BaseText` representation of the class of * the `Object` / `Actor` that this method must create. * @param forceNewInstance Set this to `true` if you require this method to * create a new instance, bypassing any object pools. @@ -147,7 +147,7 @@ public final function Object Allocate( * `none` if creation has failed (only possible for actors). */ public final function Object AllocateByReference( - Text refToClassToAllocate, + BaseText refToClassToAllocate, optional bool forceNewInstance) { return Allocate(LoadClass(refToClassToAllocate), forceNewInstance); diff --git a/sources/Players/EPlayer.uc b/sources/Players/EPlayer.uc index c14aac4..671dcf1 100644 --- a/sources/Players/EPlayer.uc +++ b/sources/Players/EPlayer.uc @@ -256,7 +256,7 @@ public final function Text GetName() * @param newPlayerName New name of the caller `EPlayer`. This value will * be copied. Passing `none` will result in an empty name. */ -public final function SetName(Text newPlayerName) +public final function SetName(BaseText newPlayerName) { local Text oldPlayerName; local PlayerReplicationInfo replicationInfo; @@ -270,10 +270,10 @@ public final function SetName(Text newPlayerName) } // Converts `Text` nickname into a suitable `string` representation. -private final function string ConvertTextNameIntoString(Text playerName) +private final function string ConvertTextNameIntoString(BaseText playerName) { - local string newPlayerNameAsString; - local Text.Formatting endingFormatting; + local string newPlayerNameAsString; + local BaseText.Formatting endingFormatting; if (playerName == none) { return ""; } @@ -301,8 +301,8 @@ private final function string ConvertTextNameIntoString(Text playerName) // Calls appropriate events to let them modify / "censor" player's new name. private final function string CensorPlayerName( - Text oldPlayerName, - Text newPlayerName) + BaseText oldPlayerName, + BaseText newPlayerName) { local string result; local Text censoredName; diff --git a/sources/Players/Events/PlayerAPI_OnPlayerNameChanged_Signal.uc b/sources/Players/Events/PlayerAPI_OnPlayerNameChanged_Signal.uc index f78f69b..934d0ae 100644 --- a/sources/Players/Events/PlayerAPI_OnPlayerNameChanged_Signal.uc +++ b/sources/Players/Events/PlayerAPI_OnPlayerNameChanged_Signal.uc @@ -19,7 +19,7 @@ */ class PlayerAPI_OnPlayerNameChanged_Signal extends Signal; -public final function Emit(EPlayer player, Text oldName, Text newName) +public final function Emit(EPlayer player, BaseText oldName, BaseText newName) { local Slot nextSlot; StartIterating(); diff --git a/sources/Players/Events/PlayerAPI_OnPlayerNameChanged_Slot.uc b/sources/Players/Events/PlayerAPI_OnPlayerNameChanged_Slot.uc index 74488ba..71ecce2 100644 --- a/sources/Players/Events/PlayerAPI_OnPlayerNameChanged_Slot.uc +++ b/sources/Players/Events/PlayerAPI_OnPlayerNameChanged_Slot.uc @@ -19,7 +19,7 @@ */ class PlayerAPI_OnPlayerNameChanged_Slot extends Slot; -delegate connect(EPlayer player, Text oldName, Text newName) +delegate connect(EPlayer player, BaseText oldName, BaseText newName) { DummyCall(); } diff --git a/sources/Players/Events/PlayerAPI_OnPlayerNameChanging_Signal.uc b/sources/Players/Events/PlayerAPI_OnPlayerNameChanging_Signal.uc index bafb91f..dafaf4b 100644 --- a/sources/Players/Events/PlayerAPI_OnPlayerNameChanging_Signal.uc +++ b/sources/Players/Events/PlayerAPI_OnPlayerNameChanging_Signal.uc @@ -19,7 +19,9 @@ */ class PlayerAPI_OnPlayerNameChanging_Signal extends Signal; -public final function Emit(EPlayer player, Text oldName, MutableText newName) +public final function Emit(EPlayer player, + BaseText oldName, + MutableText newName) { local Slot nextSlot; StartIterating(); diff --git a/sources/Players/Events/PlayerAPI_OnPlayerNameChanging_Slot.uc b/sources/Players/Events/PlayerAPI_OnPlayerNameChanging_Slot.uc index 4be3110..c7bab73 100644 --- a/sources/Players/Events/PlayerAPI_OnPlayerNameChanging_Slot.uc +++ b/sources/Players/Events/PlayerAPI_OnPlayerNameChanging_Slot.uc @@ -19,7 +19,7 @@ */ class PlayerAPI_OnPlayerNameChanging_Slot extends Slot; -delegate connect(EPlayer player, Text oldName, MutableText newName) +delegate connect(EPlayer player, BaseText oldName, MutableText newName) { DummyCall(); } diff --git a/sources/Players/Inventory/EInventory.uc b/sources/Players/Inventory/EInventory.uc index 5a055da..8ddf5bb 100644 --- a/sources/Players/Inventory/EInventory.uc +++ b/sources/Players/Inventory/EInventory.uc @@ -82,7 +82,7 @@ public function EItem Add(EItem newItem, optional bool forceAddition) * `none` iff adding item has failed. */ public function EItem AddTemplate( - Text newItemTemplate, + BaseText newItemTemplate, optional bool forceAddition) { return none; @@ -130,7 +130,7 @@ public final function bool CanAdd( * `false` otherwise. */ public function bool CanAddTemplate( - Text itemTemplateToCheck, + BaseText itemTemplateToCheck, optional bool forceAddition) { local bool success; @@ -181,7 +181,7 @@ public function Text CanAddExplain( * description of reason why not otherwise. */ public function Text CanAddTemplateExplain( - Text itemTemplateToCheck, + BaseText itemTemplateToCheck, optional bool forceAddition) { return none; @@ -243,7 +243,7 @@ public function bool Remove( * caller `EInventory` in the first place). */ public function bool RemoveTemplate( - Text itemTemplateToRemove, + BaseText itemTemplateToRemove, optional bool keepItem, optional bool forceRemoval, optional bool removeAll) @@ -307,7 +307,7 @@ public function bool Contains(EItem itemToCheck) * @result `true` if item with a given template does belong to the inventory * and `false` otherwise. */ -public function bool ContainsTemplate(Text itemTemplateToCheck) +public function bool ContainsTemplate(BaseText itemTemplateToCheck) { return false; } @@ -348,7 +348,7 @@ public function array GetItemsSupporting(class interfaceClass) * Guaranteed to not contain `none` references of interfaces to * inexistent entities. */ -public function array GetTagItems(Text tag) +public function array GetTagItems(BaseText tag) { local array emptyArray; return emptyArray; @@ -368,7 +368,7 @@ public function array GetTagItems(Text tag) * the specified tag `tag`. * Guaranteed to not be `none` or refer to non-existent entity. */ -public function EItem GetTagItem(Text tag) { return none; } +public function EItem GetTagItem(BaseText tag) { return none; } /** * Returns array with all `EItem`s contained inside the caller `EInventory` @@ -380,7 +380,7 @@ public function EItem GetTagItem(Text tag) { return none; } * Guaranteed to not contain `none` references or interfaces to * inexistent entities. */ -public function array GetTemplateItems(Text template) +public function array GetTemplateItems(BaseText template) { local array emptyArray; return emptyArray; @@ -400,7 +400,7 @@ public function array GetTemplateItems(Text template) * from the specified template `template`. * Guaranteed to not be `none` or refer to non-existent entity. */ -public function EItem GetTemplateItem(Text template) { return none; } +public function EItem GetTemplateItem(BaseText template) { return none; } /** * Returns array of caller `EInventory`'s items that are currently equipped by diff --git a/sources/Players/Inventory/EItem.uc b/sources/Players/Inventory/EItem.uc index 1dd09f9..96b6a1b 100644 --- a/sources/Players/Inventory/EItem.uc +++ b/sources/Players/Inventory/EItem.uc @@ -64,7 +64,7 @@ public function array GetTags() } // TODO: document this -public function bool HasTag(Text tagToCheck) +public function bool HasTag(BaseText tagToCheck) { return false; } diff --git a/sources/Players/PlayersAPI.uc b/sources/Players/PlayersAPI.uc index 0ea4e6c..508d84a 100644 --- a/sources/Players/PlayersAPI.uc +++ b/sources/Players/PlayersAPI.uc @@ -19,7 +19,7 @@ */ class PlayersAPI extends AcediaObject dependson(ConnectionService) - dependson(Text) + dependson(BaseText) dependson(EPlayer); // Writer that can be used to write into this player's console @@ -108,7 +108,7 @@ public function PlayerAPI_OnLostPlayer_Slot OnLostPlayer( * use `OnPlayerNameChanged` instead. * * [Signature] - * void (EPlayer affectedPlayer, Text oldName, MutableText newName) + * void (EPlayer affectedPlayer, BaseText oldName, MutableText newName) * * @param affectedPlayer Player, whos name got changed. * @param oldName Player's old name. @@ -130,7 +130,7 @@ public function PlayerAPI_OnPlayerNameChanging_Slot OnPlayerNameChanging( * after change caused by someone else, use `OnPlayerNameChanging` instead. * * [Signature] - * void (EPlayer affectedPlayer, Text oldName, Text newName) + * void (EPlayer affectedPlayer, BaseText oldName, BaseText newName) * * @param affectedPlayer Player, whos name got changed. * @param oldName Player's old name. diff --git a/sources/Text/BaseText.uc b/sources/Text/BaseText.uc new file mode 100644 index 0000000..23ff3bf --- /dev/null +++ b/sources/Text/BaseText.uc @@ -0,0 +1,1578 @@ +/** + * Acedia's base text class. It implements all of the methods for + * immutable `Text`, but by itself does not give a guarantee of immutability, + * since `MutableText` is one of its child classes. + * Copyright 2020 - 2022 Anton Tarasenko + *------------------------------------------------------------------------------ + * This file is part of Acedia. + * + * Acedia is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License, or + * (at your option) any later version. + * + * Acedia is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Acedia. If not, see . + */ +class BaseText extends AcediaObject + abstract; + +// Enumeration that describes how should we treat `BaseText`s that +// differ in case only. +// By default we would consider them unequal. +enum CaseSensitivity +{ + SCASE_SENSITIVE, + SCASE_INSENSITIVE +}; + +// Enumeration that describes how should we treat `BaseText`s that +// differ only in their formatting. +// By default we would consider them unequal. +enum FormatSensitivity +{ + SFORM_INSENSITIVE, + SFORM_SENSITIVE +}; + +// Describes text formatting, can be applied per-character. +struct Formatting +{ + // Whether this formatting describes a color of the text + var bool isColored; + // Color of the text, used only when `isColored == true` + var Color color; +}; + +// Represents one character, together with it's formatting +struct Character +{ + var int codePoint; + var Formatting formatting; +}; + +// Actual content of the `BaseText` is stored as a sequence of +// Unicode code points. +var private array codePoints; +// Structure for inner use, describes a change of formatting to `formatting`, +// starting from index `startIndex` +struct FormattingChunk +{ + var private int startIndex; + var private Formatting formatting; +}; +// Series of `FormattingChunk` that defines formatting over characters, +// defined by `codePoints`. +// This array is sorted by `startIndex` of it's elements and +// formatting for character at is defined by the `FormattingChunk` +// with the largest `startIndex <= `. +var private array formattingChunks; +// To optimize look up of formatting for characters we remember index of +// the last used `FormattingChunk` to attempt to start the next lookup +// from that point. +// This improves performance when several lookups are done in order. +var private int formattingIndexCache; + +/* + * In the base class we implement `AppendCodePoint()` and + * `AppendManyCodePoints()` methods that allow to add code points 1-by-1. + * To reduce the amount of checks, formatting is set not per-code point, + * but separately by `SetFormatting()`: to append a group of code points with + * a certain formatting one has to first set their formatting, + * then just add code points. + */ +// Formatting to use for the next code point +var private Formatting nextFormatting; +// `true` if the next code point will have a different formatting from +// the last added one. +var private bool formattingUpdated; + +// Escape code point is used to change output's color and is used in +// Unreal Engine's `string`s. +var protected const int CODEPOINT_ESCAPE; +// Opening and closing symbols for colored blocks in formatted strings. +var protected const int CODEPOINT_OPEN_FORMAT; +var protected const int CODEPOINT_CLOSE_FORMAT; +var protected const string STRING_OPEN_FORMAT; +var protected const string STRING_CLOSE_FORMAT; +// Symbol for separating opening formatting block from it's contents +var protected const string STRING_SEPARATOR_FORMAT; +// Symbol to escape any character in formatted strings, +// including above mentioned opening and closing symbols. +var protected const int CODEPOINT_FORMAT_ESCAPE; +var protected const string STRING_FORMAT_ESCAPE; + +// Simply free all used memory. +protected function Finalizer() +{ + codePoints.length = 0; + formattingChunks.length = 0; +} + +/** + * Auxiliary method that changes formatting of the whole `BaseText` to + * a specified one (`newFormatting`). This method is faster than calling + * `ReformatRange`. + * + * @param newFormatting Formatting to set to the whole `BaseText`. + */ +protected final function ReformatWhole(Formatting newFormatting) +{ + local FormattingChunk newChunk; + formattingChunks.length = 0; + newChunk.startIndex = 0; + newChunk.formatting = newFormatting; + formattingChunks[0] = newChunk; +} + +/** + * Auxiliary method that changes formatting of the characters with indices in + * range `[start; end]` to a specified one (`newFormatting`). + * + * This method assumes, but does not check that: + * 1. `start <= end`; + * 2. `start` and `end` parameters belong to the range of valid indices + * `[0; GetLength() - 1]` + * + * @param start First character to change formatting of. + * @param end Last character to change formatting of. + * @param newFormatting Formatting to set to the specified characters. + */ +protected final function ReformatRange( + int start, + int end, + Formatting newFormatting) +{ + local int i; + local Formatting formattingAfterChangedSegment; + local FormattingChunk newChunk; + local array newFormattingChunks; + start = Max(start, 0); + end = Min(GetLength() - 1, end); + // Formatting right after `end`, the end of re-formatted segment + formattingAfterChangedSegment = GetFormatting(end + 1); + // 1. Copy old formatting before `start` + for (i = 0; i < formattingChunks.length; i += 1) + { + if (start <= formattingChunks[i].startIndex) { + break; + } + newFormattingChunks[newFormattingChunks.length] = formattingChunks[i]; + } + newChunk.formatting = newFormatting; + newChunk.startIndex = start; + newFormattingChunks[newFormattingChunks.length] = newChunk; + if (end == GetLength() - 1) + { + formattingChunks = newFormattingChunks; + // We have inserted `FormattingChunk` without checking if it actually + // changes formatting. It might be excessive, so do a normalization. + NormalizeFormatting(); + return; + } + // 2. Drop old formatting overwritten by `newFormatting` + while (i < formattingChunks.length) + { + if (end < formattingChunks[i].startIndex) { + break; + } + i += 1; + } + // 3. Copy old formatting after `end` + newChunk.formatting = formattingAfterChangedSegment; + newChunk.startIndex = end + 1; // end < GetLength() - 1 + newFormattingChunks[newFormattingChunks.length] = newChunk; + while (i < formattingChunks.length) + { + newFormattingChunks[newFormattingChunks.length] = formattingChunks[i]; + i += 1; + } + formattingChunks = newFormattingChunks; + // We have inserted `FormattingChunk` without checking if it actually + // changes formatting. It might be excessive, so do a normalization. + NormalizeFormatting(); +} + +/** + * Static method for creating an immutable `Text` object from (plain) `string`. + * + * It is preferred to use `TextAPI` methods for creating `Text` instances. + * + * @param source Plain `string` to convert into `Text`. + * @return `Text` instance (guaranteed to be not `none`) that stores contents + * of `source` if treated as a plain `string`. + */ +public static final function Text ConstFromPlainString(string source) +{ + local MutableText builder; + local Text result; + builder = MutableText(__().memory.Allocate(class'MutableText')); + result = builder.AppendString(source).Copy(); + builder.FreeSelf(); + return result; +} + +/** + * Static method for creating an immutable `Text` object from + * (colored) `string`. + * + * It is preferred to use `TextAPI` methods for creating `Text` instances. + * + * @param source Colored `string` to convert into `Text`. + * @return `Text` instance (guaranteed to be not `none`) that stores contents + * of `source` if treated as a colored `string`. + */ +public static final function Text ConstFromColoredString(string source) +{ + local MutableText builder; + local Text result; + builder = MutableText(__().memory.Allocate(class'MutableText')); + result = builder.AppendColoredString(source).Copy(); + builder.FreeSelf(); + return result; +} + +/** + * Static method for creating an immutable `Text` object from + * (formatted) `string`. + * + * It is preferred to use `TextAPI` methods for creating `Text` instances. + * + * @param source Formatted `string` to convert into `Text`. + * @return `Text` instance (guaranteed to be not `none`) that stores contents + * of `source` if treated as a formatted `string`. + */ +public static final function Text ConstFromFormattedString(string source) +{ + local MutableText builder; + local Text result; + builder = MutableText(__().memory.Allocate(class'MutableText')); + result = builder.AppendFormattedString(source).Copy(); + builder.FreeSelf(); + return result; +} + +/** + * Makes an immutable copy (`class'Text'`) of the caller `BaseText`. + * + * Copies characters in the range `[startIndex; startIndex + maxLength - 1]` + * If provided parameters `startIndex` and `maxLength` define a range that + * goes beyond `[0; self.GetLength() - 1]`, then intersection with a valid + * range will be used. + * + * @param startIndex Position of the first character to copy. + * By default `0`, corresponding to the very first character. + * @param maxLength Max length of the extracted string. By default `0`, + * - that and all negative values mean that method should extract all + * characters to the right of `startIndex`. + * @return Immutable copy of the caller `BaseText` instance. + * Guaranteed to be not `none` and have class `Text`. + */ +public final function Text Copy( + optional int startIndex, + optional int maxLength) +{ + // `startIndex` is inclusive and `endIndex` is not + local int i, endIndex; + local Text copy; + local Character nextCharacter; + if (maxLength <= 0) { + maxLength = codePoints.length - startIndex; + } + endIndex = startIndex + maxLength; + copy = Text(_.memory.Allocate(class'Text')); + // Edge cases + if (endIndex <= 0) { + return copy; + } + if (startIndex <= 0 && startIndex + maxLength >= codePoints.length) + { + copy.codePoints = codePoints; + copy.formattingChunks = formattingChunks; + return copy; + } + // Substring copy + if (startIndex < 0) { + startIndex = 0; + } + endIndex = Min(endIndex, codePoints.length); + for (i = startIndex; i < endIndex; i += 1) + { + nextCharacter = GetCharacter(i); + copy.SetFormatting(nextCharacter.formatting); + copy.AppendCodePoint(nextCharacter.codePoint); + } + return copy; +} + +/** + * Makes a mutable copy (`class'MutableText'`) of the caller + * `BaseText` instance. + * + * If provided parameters `startIndex` and `maxLength` define a range that + * goes beyond `[0; self.GetLength() - 1]`, then intersection with a valid + * range will be used. + * + * @param startIndex Position of the first character to copy. + * By default `0`, corresponding to the very first character. + * @param maxLength Max length of the extracted string. By default `0`, + * - that and all negative values mean that method should extract all + * characters to the right of `startIndex`. + * @return Mutable copy of the caller `BaseText` instance. + * Guaranteed to be not `none` and have class `MutableText`. + */ +public final function MutableText MutableCopy( + optional int startIndex, + optional int maxLength) +{ + // `startIndex` is inclusive and `endIndex` is not + local int i, endIndex; + local MutableText copy; + if (maxLength <= 0) { + maxLength = codePoints.length - startIndex; + } + endIndex = startIndex + maxLength; + copy = MutableText(_.memory.Allocate(class'MutableText')); + // Edge cases + if (endIndex <= 0 || startIndex >= codePoints.length) { + return copy; + } + if (startIndex <= 0 && startIndex + maxLength >= codePoints.length) + { + copy.codePoints = codePoints; + copy.formattingChunks = formattingChunks; + return copy; + } + // Substring copy + if (startIndex < 0) { + startIndex = 0; + } + endIndex = Min(endIndex, codePoints.length); + for (i = startIndex; i < endIndex; i += 1) { + copy.AppendCharacter(GetCharacter(i)); + } + return copy; +} + +/** + * Makes an immutable copy (`class'Text'`) of the caller `BaseText` + * in a lower case. + * + * If provided parameters `startPosition` and `maxLength` define a range that + * goes beyond `[0; self.GetLength() - 1]`, then intersection with a valid + * range will be used. + * + * @param startPosition Position of the first character to copy. + * By default `0`, corresponding to the very first character. + * @param maxLength Max length of the extracted string. By default `0`, + * - that and all negative values mean that method should extract all + * characters to the right of `startIndex`. + * @return Immutable copy of caller `BaseText` in a lower case. + * Guaranteed to be not `none` and have class `Text`. + */ +public final function Text LowerCopy( + optional int startIndex, + optional int maxLength) +{ + local Text textCopy; + textCopy = Copy(startIndex, maxLength); + textCopy.ConvertCase(true); + return textCopy; +} + +/** + * Makes an immutable copy (`class'Text'`) of the caller `BaseText` + * in an upper case. + * + * If provided parameters `startPosition` and `maxLength` define a range that + * goes beyond `[0; self.GetLength() - 1]`, then intersection with a valid + * range will be used. + * + * @param startPosition Position of the first character to copy. + * By default `0`, corresponding to the very first character. + * @param maxLength Max length of the extracted string. By default `0`, + * - that and all negative values mean that method should extract all + * characters to the right of `startIndex`. + * @return Immutable copy of caller `BaseText` in a upper case. + * Guaranteed to be not `none` and have class `Text`. + */ +public final function Text UpperCopy( + optional int startIndex, + optional int maxLength) +{ + local Text textCopy; + textCopy = Copy(startIndex, maxLength); + textCopy.ConvertCase(false); + return textCopy; +} + +/** + * Makes a mutable copy (`class'MutableText'`) of the caller + * `BaseText` instance in lower case. + * + * If provided parameters `startPosition` and `maxLength` define a range that + * goes beyond `[0; self.GetLength() - 1]`, then intersection with a valid + * range will be used. + * + * @param startPosition Position of the first character to copy. + * By default `0`, corresponding to the very first character. + * @param maxLength Max length of the extracted string. By default `0`, + * - that and all negative values mean that method should extract all + * characters to the right of `startIndex`. + * @return Mutable copy of caller `BaseText` instance in lower case. + * Guaranteed to be not `none` and have class `MutableText`. + */ +public final function MutableText LowerMutableCopy( + optional int startIndex, + optional int maxLength) +{ + local MutableText textCopy; + textCopy = MutableCopy(startIndex, maxLength); + textCopy.ConvertCase(true); + return textCopy; +} + +/** + * Makes a mutable copy (`class'MutableText'`) of the caller text instance + * in upper case. + * + * If provided parameters `startPosition` and `maxLength` define a range that + * goes beyond `[0; self.GetLength() - 1]`, then intersection with a valid + * range will be used. + * + * @param startPosition Position of the first character to copy. + * By default `0`, corresponding to the very first character. + * @param maxLength Max length of the extracted string. By default `0`, + * - that and all negative values mean that method should extract all + * characters to the right of `startIndex`. + * @return Mutable copy of caller `BaseText` instance in upper case. + * Guaranteed to be not `none` and have class `MutableText`. + */ +public final function MutableText UpperMutableCopy( + optional int startIndex, + optional int maxLength) +{ + local MutableText textCopy; + textCopy = MutableCopy(startIndex, maxLength); + textCopy.ConvertCase(false); + return textCopy; +} + +/** + * Checks if caller `BaseText` contains a valid name for a config object or + * not. + * + * Valid names contain only ASCII characters, digits and '.' / '_' characters. + * Empty `BaseText` is not considered a valid name. + * + * @return `true` if caller `BaseText` contains a valid config object name and + * `false` otherwise. + */ +public final function bool IsValidConfigName() +{ + local int i; + local int codePoint; + local bool isValidCodePoint; + local Character nextCharacter; + if (IsEmpty()) { + return false; + } + for (i = 0; i < GetLength(); i += 1) + { + nextCharacter = GetCharacter(i); + codePoint = nextCharacter.codePoint; + isValidCodePoint = + ( (codePoint == 0x2E) || (codePoint == 0x5F) // '.' or '_' + || (0x30 <= codePoint && codePoint <= 0x39) // '0' to '9' + || (0x41 <= codePoint && codePoint <= 0x5A) // 'A' to 'Z' + || (0x61 <= codePoint && codePoint <= 0x7A)); // 'a' to 'z' + if (!isValidCodePoint) { + return false; + } + } + return true; +} + +/** + * Auxiliary function that converts case of the caller `BaseText` object. + * As `BaseText` is supposed to be immutable, cannot be public. + * + * @param toLower `true` if caller `BaseText` must be converted to + * the lower case and `false` otherwise. + */ +protected final function ConvertCase(bool toLower) +{ + local int i; + local Character nextCharacter; + for (i = 0; i < GetLength(); i += 1) + { + nextCharacter = GetCharacter(i); + if (toLower) { + nextCharacter = _.text.ToLower(nextCharacter); + } + else { + nextCharacter = _.text.ToUpper(nextCharacter); + } + codePoints[i] = nextCharacter.codePoint; + } +} + +/** + * Calculates hash value of the caller `BaseText`. Hash will depend only on + * it's textual contents, without taking formatting (color information) + * into account. + * + * @return Hash, that depends on textual contents only. + */ +protected function int CalculateHashCode() +{ + // We have left this method here, since only the base class has access + // to code points, which allows for more efficient implementation. + // You must overload it for mutable text child classes + // (like `MutableText`). + local int i; + local int hash; + // Manually inline `CombineHash()`, to avoid too many calls + // (and infinite loop detection) for some long text data. + hash = 5381; + for (i = 0; i < codePoints.length; i += 1) + { + // hash * 33 + codePoints[i] + hash = ((hash << 5) + hash) + codePoints[i]; + } + return hash; +} + +/** + * Checks whether contents of the caller `BaseText` are empty. + * + * @return `true` if caller `BaseText` contains no symbols. + */ +public final function bool IsEmpty() +{ + return (codePoints.length == 0); +} + +/** + * Returns current length of the caller `BaseText` in symbols. + * + * Do note that codepoint is not the same as a symbol, since one symbol + * can consist of several code points. While current implementation only + * supports symbols represented by a single code point, this might change + * in the future. + * + * @return Current length of caller `BaseText`'s contents in symbols. + */ +public final function int GetLength() +{ + return codePoints.length; +} + +/** + * Override equality check for `BaseText` to make two different + * `BaseText`s equal based on their text contents. + * Text equality check is case-sensitive and does not take formatting + * into account. + * + * `BaseText` cannot be equal to object of any class that is not + * derived from `BaseText`. + * + * @param other Object to compare to the caller. + * `none` is only equal to the `none`. + * @return `true` if `other` is considered equal to the caller `BaseText`, + * `false` otherwise. + */ +public function bool IsEqual(Object other) +{ + if (self == other) { + return true; + } + return Compare(BaseText(other)); +} + +// "Normalizes" code point for comparison by converting it to lower case if +// `caseSensitivity == SCASE_INSENSITIVE`. +// Otherwise returns same code point. +private final function int NormalizeCodePoint( + int codePoint, + CaseSensitivity caseSensitivity) +{ + local int newCodePoint; + if (caseSensitivity == SCASE_INSENSITIVE) { + newCodePoint = class'UnicodeData'.static.ToLowerCodePoint(codePoint); + } + else { + newCodePoint = codePoint; + } + if (newCodePoint < 0) { + return codePoint; + } + return newCodePoint; +} + +/** + * Method for checking equality between the caller and another `BaseText` + * object. + * + * This method supports comparison both sensitive and not sensitive to + * the case and difference in formatting (color of the characters). + * By default comparison is case-sensitive, but ignores + * formatting information. + * + * @param otherText `BaseText` to compare caller instance to. + * @param caseSensitivity Defines whether comparison should be + * case-sensitive. By default it is. + * @param formatSensitivity Defines whether comparison should be + * sensitive for color information. By default it is not. + * @return `true` if the caller `BaseText` is equal to the `otherText` under + * specified parameters and `false` otherwise. + */ +public final function bool Compare( + BaseText otherText, + optional CaseSensitivity caseSensitivity, + optional FormatSensitivity formatSensitivity) +{ + local int i; + local array otherCodePoints; + if (otherText == none) { + return false; + } + if (GetLength() != otherText.GetLength()) { + return false; + } + if (formatSensitivity == SFORM_SENSITIVE && !CompareFormatting(otherText)) { + return false; + } + // Copy once to avoid doing it each iteration + otherCodePoints = otherText.codePoints; + for (i = 0; i < codePoints.length; i += 1) + { + if ( NormalizeCodePoint(codePoints[i], caseSensitivity) + != NormalizeCodePoint(otherCodePoints[i], caseSensitivity)) { + return false; + } + } + return true; +} + +/** + * Method for checking if the caller starts with another `BaseText` object. + * + * This method supports comparison both sensitive and not sensitive to + * the case and difference in formatting (color of the characters). + * By default comparison is case-sensitive, but ignores + * formatting information. + * + * @param otherText `BaseText` that caller is checked to start with. + * @param caseSensitivity Defines whether comparison should be + * case-sensitive. By default it is. + * @param formatSensitivity Defines whether comparison should be + * sensitive for color information. By default it is not. + * @return `true` if the caller `BaseText` starts with `otherText` under + * specified parameters and `false` otherwise. + */ +public final function bool StartsWith( + BaseText otherText, + optional CaseSensitivity caseSensitivity, + optional FormatSensitivity formatSensitivity) +{ + local int i; + local Character char1, char2; + if (otherText == none) { + return false; + } + if (GetLength() < otherText.GetLength()) { + return false; + } + for (i = 0; i < otherText.GetLength(); i += 1) + { + char1 = GetCharacter(i); + char2 = otherText.GetCharacter(i); + if ( NormalizeCodePoint(char1.codePoint, caseSensitivity) + != NormalizeCodePoint(char2.codePoint, caseSensitivity)) { + return false; + } + if ( formatSensitivity == SFORM_SENSITIVE + && !_.text.IsFormattingEqual(char1.formatting, char2.formatting)) { + return false; + } + } + return true; +} + +/** + * Method for checking if the caller starts with another `string`. + * + * This method supports comparison both sensitive and not sensitive to + * the case. By default comparison is case-sensitive. + * + * @param otherString `string` that caller is checked to start with. + * @param caseSensitivity Defines whether comparison should be + * case-sensitive. By default it is. + * @return `true` if the caller `BaseText` starts with `otherString` under + * specified parameters and `false` otherwise. + */ +public final function bool StartsWithS( + string otherString, + optional CaseSensitivity caseSensitivity) +{ + local bool result; + local MutableText otherText; + otherText = _.text.FromStringM(otherString); + result = StartsWith(otherText, caseSensitivity); + _.memory.Free(otherText); + return result; +} + +/** + * Method for checking if the caller ends with another `BaseText` object. + * + * This method supports comparison both sensitive and not sensitive to + * the case and difference in formatting (color of the characters). + * By default comparison is case-sensitive, but ignores + * formatting information. + * + * @param otherText `BaseText` that caller is checked to end with. + * @param caseSensitivity Defines whether comparison should be + * case-sensitive. By default it is. + * @param formatSensitivity Defines whether comparison should be + * sensitive for color information. By default it is not. + * @return `true` if the caller `BaseText` ends with `otherText` under + * specified parameters and `false` otherwise. + */ +public final function bool EndsWith( + BaseText otherText, + optional CaseSensitivity caseSensitivity, + optional FormatSensitivity formatSensitivity) +{ + local int index, otherIndex; + local Character char1, char2; + if (otherText == none) { + return false; + } + if (GetLength() < otherText.GetLength()) { + return false; + } + index = GetLength() - 1; + otherIndex = otherText.GetLength() - 1; + while (otherIndex >= 0) + { + char1 = GetCharacter(index); + char2 = otherText.GetCharacter(otherIndex); + if ( NormalizeCodePoint(char1.codePoint, caseSensitivity) + != NormalizeCodePoint(char2.codePoint, caseSensitivity)) { + return false; + } + if ( formatSensitivity == SFORM_SENSITIVE + && !_.text.IsFormattingEqual(char1.formatting, char2.formatting)) { + return false; + } + index -= 1; + otherIndex -= 1; + } + return true; +} + +/** + * Method for checking if the caller ends with another `string`. + * + * This method supports comparison both sensitive and not sensitive to + * the case. By default comparison is case-sensitive. + * + * @param otherString `string` that caller is checked to end with. + * @param caseSensitivity Defines whether comparison should be + * case-sensitive. By default it is. + * @return `true` if the caller `BaseText` ends with `otherString` under + * specified parameters and `false` otherwise. + */ +public final function bool EndsWithS( + string otherString, + optional CaseSensitivity caseSensitivity) +{ + local bool result; + local MutableText otherText; + otherText = _.text.FromStringM(otherString); + result = EndsWith(otherText, caseSensitivity); + _.memory.Free(otherText); + return result; +} + +// Helper method for comparing formatting data of the caller `BaseText` +// and `otherText`. +private final function bool CompareFormatting(BaseText otherText) +{ + local int i; + local TextAPI api; + local array rightChunks; + rightChunks = otherText.formattingChunks; + if (formattingChunks.length != rightChunks.length) { + return false; + } + api = _.text; + for (i = 0; i < formattingChunks.length; i += 1) + { + if (formattingChunks[i].startIndex != rightChunks[i].startIndex) { + return false; + } + if (!api.IsFormattingEqual( formattingChunks[i].formatting, + rightChunks[i].formatting)) + { + return false; + } + } + return true; +} + +/** + * Method for checking equality between the caller `BaseText` and + * a (plain) `string`. + * + * This method supports comparison both sensitive and not sensitive to + * the case and difference in formatting (color of the characters). + * By default comparison is case-sensitive, but ignores + * formatting information. + * + * @param otherText Plain `string` to compare caller `BaseText` to. + * @param caseSensitivity Defines whether comparison should be + * case-sensitive. By default it is. + * @param formatSensitivity Defines whether comparison should be + * sensitive for color information. By default it is not. + * @return `true` if the caller `BaseText` is equal to the `stringToCompare` + * under specified parameters and `false` otherwise. + */ +public final function bool CompareToString( + string stringToCompare, + optional CaseSensitivity caseSensitivity, + optional FormatSensitivity formatSensitivity) +{ + local MutableText builder; + local bool result; + builder = MutableText(_.memory.Allocate(class'MutableText')); + builder.AppendString(stringToCompare); + result = Compare(builder, caseSensitivity, formatSensitivity); + builder.FreeSelf(); + return result; +} + +/** + * Method for checking equality between the caller `BaseText` and + * a (colored) `string`. + * + * This method supports comparison both sensitive and not sensitive to + * the case and difference in formatting (color of the characters). + * By default comparison is case-sensitive, but ignores + * formatting information. + * + * @param otherText Colored `string` to compare caller + * `BaseText` to. + * @param caseSensitivity Defines whether comparison should be + * case-sensitive. By default it is. + * @param formatSensitivity Defines whether comparison should be + * sensitive for color information. By default it is not. + * @return `true` if the caller `BaseText` is equal to the `stringToCompare` + * under specified parameters and `false` otherwise. + */ +public final function bool CompareToColoredString( + string stringToCompare, + optional CaseSensitivity caseSensitivity, + optional FormatSensitivity formatSensitivity) +{ + local MutableText builder; + local bool result; + builder = MutableText(_.memory.Allocate(class'MutableText')); + builder.AppendColoredString(stringToCompare); + result = Compare(builder, caseSensitivity, formatSensitivity); + builder.FreeSelf(); + return result; +} + +/** + * Method for checking equality between the caller `BaseText` and + * a (formatted) `string`. + * + * This method supports comparison both sensitive and not sensitive to + * the case and difference in formatting (color of the characters). + * By default comparison is case-sensitive, but ignores + * formatting information. + * + * @param otherText Formatted `string` to compare caller + * `BaseText` to. + * @param caseSensitivity Defines whether comparison should be + * case-sensitive. By default it is. + * @param formatSensitivity Defines whether comparison should be + * sensitive for color information. By default it is not. + * @return `true` if the caller `BaseText` is equal to the `stringToCompare` + * under specified parameters and `false` otherwise. + */ +public final function bool CompareToFormattedString( + string stringToCompare, + optional CaseSensitivity caseSensitivity, + optional FormatSensitivity formatSensitivity) +{ + local MutableText builder; + local bool result; + builder = MutableText(_.memory.Allocate(class'MutableText')); + builder.AppendFormattedString(stringToCompare); + result = Compare(builder, caseSensitivity, formatSensitivity); + builder.FreeSelf(); + return result; +} + +/** + * Returns character at position given by `position`. + * + * Character is returned along with it's color information. + * + * If you do not care about color, you might want to use + * `GetRawCharacter()` method that's slightly faster. + * + * Does some optimizations to speed up lookup of the characters, + * when they are looked up in order of increasing `position`. + * + * @param position Position of the character to return. + * First character is at `0`. + * @return Character at required position. If `position` was out of bounds + * (`< 0` or `>= self.GetLength()`), returns invalid character instead. + */ +public final function Character GetCharacter(int position) +{ + local Character result; + if (position < 0) return _.text.GetInvalidCharacter(); + if (position >= codePoints.length) return _.text.GetInvalidCharacter(); + + result.codePoint = codePoints[position]; + result.formatting = GetFormatting(position); + return result; +} + +/** + * Returns character at position given by `position`. + * + * Character is returned without it's color information + * (guaranteed to have `.formatting.isColored == false`). + * + * Unlike `GetCharacter()` does not optimizations. + * + * @param position Position of the character to return. + * First character is at `0`. + * @return Character at required position, without any color information. + * If `position` was out of bounds (`< 0` or `>= self.GetLength()`), + * returns invalid character instead. + */ +public final function Character GetRawCharacter(int position) +{ + local Character result; + if (position < 0) return _.text.GetInvalidCharacter(); + if (position >= codePoints.length) return _.text.GetInvalidCharacter(); + + result.codePoint = codePoints[position]; + return result; +} + +/** + * Appends new code point to the `BaseText`'s data. + * Allows to create mutable child classes. + * + * Formatting of this code point needs to be set beforehand by + * `SetFormatting()` method. + * + * @param codePoint Code point to append, does nothing for + * invalid (`< 1`) code points. + * @return Returns caller `BaseText`, to allow for method chaining. + */ +protected final function BaseText AppendCodePoint(int codePoint) +{ + local FormattingChunk newChunk; + codePoints[codePoints.length] = codePoint; + if (formattingUpdated) + { + newChunk.startIndex = codePoints.length - 1; + newChunk.formatting = nextFormatting; + formattingChunks[formattingChunks.length] = newChunk; + formattingUpdated = false; + } + return self; +} + +/** + * Appends several new code points to the `BaseText`'s data. + * Convenience method over existing `AppendCodePoint()`. + * + * Formatting of these code points needs to be set beforehand by + * `SetFormatting()` method. + * + * @return Returns caller `BaseText`, to allow for method chaining. + */ +protected final function BaseText AppendManyCodePoints(array codePoints) +{ + local int i; + for (i = 0; i < codePoints.length; i += 1) { + AppendCodePoint(codePoints[i]); + } + return self; +} + +/** + * Drops all of the code points in the caller `BaseText`. + * Allows to easier create mutable child classes. + * + * @return Returns caller `BaseText`, to allow for method chaining. + */ +protected final function BaseText DropCodePoints() { + codePoints.length = 0; + formattingChunks.length = 0; + return self; +} + +/** + * Sets `newFormatting` for every non-formatted character in + * the caller `BaseText`. + * Allows to create mutable child classes. + * + * @param newFormatting Formatting to use for all non-formatted character in + * the caller `BaseText`. If `newFormatting` is not colored itself - + * method does nothing. + * @return Returns caller `BaseText`, to allow for method chaining. + */ +protected final function BaseText _changeDefaultFormatting( + Formatting newFormatting) +{ + local int i; + local FormattingChunk newFormattingChunk; + local array newFormattingChunks; + if (!newFormatting.isColored) { + return self; + } + newFormattingChunk.formatting = newFormatting; + if ( formattingChunks.length <= 0 + || formattingChunks[0].startIndex > 0) + { + newFormattingChunks[0] = newFormattingChunk; + } + while (i < formattingChunks.length) + { + if (formattingChunks[i].formatting.isColored) + { + newFormattingChunks[newFormattingChunks.length] = + formattingChunks[i]; + } + else + { + newFormattingChunk.startIndex = formattingChunks[i].startIndex; + newFormattingChunks[newFormattingChunks.length] = + newFormattingChunk; + } + i += 1; + } + formattingChunks = newFormattingChunks; + NormalizeFormatting(); + return self; +} + +/** + * Sets formatting for the next code point(s) to be added by + * `AppendCodePoint()` / `AppendManyCodePoints()`. + * Allows to create mutable child classes. + * + * Formatting is not reset by `Append...` calls, i.e. if you are adding + * several code points with the same formatting in a row, you only need to + * call `SetFormatting()` once. + * + * @param newFormatting Formatting to use for next code points, + * added via `AppendCodePoint()` / `AppendManyCodePoints()` methods. + * @return Returns caller `BaseText`, to allow for method chaining. + */ +protected final function BaseText SetFormatting( + optional Formatting newFormatting) +{ + local Formatting lastFormatting; + nextFormatting = newFormatting; + if (formattingChunks.length > 0) + { + lastFormatting = + formattingChunks[formattingChunks.length - 1].formatting; + } + formattingUpdated = !_.text.IsFormattingEqual( lastFormatting, + nextFormatting); + return self; +} + +/** + * Checks whether formatting has changed at character at position `position` + * (different from formatting of a character before it). + * + * Helps to compose `string`s from caller `BaseText`. + * + * If this method is called for the first character (`position == 0`), + * then method checks whether that character has any formatting setup + * (has a defined color). + * + * @param position Position of the character to check. Starts from `0`. + * @return `true` if formatting of specified character is different from + * the previous one (for the first character - if it has a defined color). + * `false` if formatting is the same or specified `position` is + * out-of-bounds (`< 0` or `>= self.GetLength()`) + */ +protected final function bool IsFormattingChangedAt(int position) +{ + local int i; + UpdateFormattingCacheFor(position); + for (i = formattingIndexCache; i < formattingChunks.length; i += 1) + { + if (formattingChunks[i].startIndex > position) { + return false; + } + if (formattingChunks[i].startIndex == position) { + return true; + } + } + return false; +} + +/** + * Returns formatting information of character at position `position`. + * + * Does some optimizations to speed up lookup of the formatting, + * when they are looked up in order of increasing `position`. + * + * @param position Position of the character to get formatting for. + * Starts from `0`. + * @return Formatting of requested character. Default formatting with + * undefined color, if `position is out-of-bounds + * (`< 0` or `>= self.GetLength()`). + */ +public final function Formatting GetFormatting(int position) +{ + local int i; + local Formatting result; + UpdateFormattingCacheFor(position); + for (i = formattingIndexCache; i < formattingChunks.length; i += 1) + { + if (formattingChunks[i].startIndex > position) { + break; + } + } + i -= 1; + if (i < 0) { + return result; + } + return formattingChunks[i].formatting; +} + +// Verifies that current `formattingIndexCache` can be used as a starting +// position to look up for formatting of symbol at `index`. +// If it cannot - resets it to zero. +private final function UpdateFormattingCacheFor(int index) +{ + if ( formattingIndexCache < 0 + || formattingIndexCache >= formattingChunks.length) { + formattingIndexCache = 0; + return; + } + if (formattingChunks[formattingIndexCache].startIndex > index) { + formattingIndexCache = 0; + } +} + +// Removes possible unnecessary chunks from `formattingChunks`: +// if there is a chunk that tells us to have red color after index `3` and +// next one tells us to have red color after index `5` - the second chunk is +// unnecessary. +private final function NormalizeFormatting() +{ + local int i; + while (i < formattingChunks.length - 1) + { + if (_.text.IsFormattingEqual( formattingChunks[i].formatting, + formattingChunks[i + 1].formatting)) + { + formattingChunks.Remove(i + 1, 1); + } + else { + i += 1; + } + } +} + +/** + * Converts data from the caller `BaseText` instance into a plain `string`. + * Can be used to extract only substrings. + * + * If provided parameters `startIndex` and `maxLength` define a range that + * goes beyond `[0; self.GetLength() - 1]`, then intersection with a valid + * range will be used. + * + * @param startIndex Position of the first symbol to extract into a + * plain `string`. By default `0`, corresponding to the first symbol. + * @param maxLength Max length of the extracted string. By default `0`, + * - that and all negative values are replaces by `MaxInt`, + * effectively extracting as much of a `string` as possible. + * @return Plain `string` representation of the caller `BaseText`, + * i.e. `string` without any color information inside. + */ +public final function string ToString( + optional int startIndex, + optional int maxLength) +{ + local int i; + local string result; + if (maxLength <= 0) { + maxLength = MaxInt; + } + else if (startIndex < 0) { + maxLength += startIndex; + } + startIndex = Max(0, startIndex); + for (i = startIndex; i < codePoints.length; i += 1) + { + if (maxLength <= 0) { + break; + } + maxLength -= 1; + result $= Chr(codePoints[i]); + } + return result; +} + +/** + * Converts data from the caller `BaseText` instance into a colored `string`. + * Can be used to extract only substrings. + * + * Guaranteed to add a color tag (possibly of `defaultColor`parameter) + * at the beginning of the returned `string`. + * + * If provided parameters `startIndex` and `maxLength` define a range that + * goes beyond `[0; self.GetLength() - 1]`, then intersection with a valid + * range will be used. + * + * @param startIndex Position of the first symbol to extract into a + * colored `string`. By default `0`, corresponding to the first symbol. + * @param maxLength Max length of the extracted string. By default `0`, + * - that and all negative values are replaces by `MaxInt`, + * effectively extracting as much of a `string` as possible. + * NOTE: this parameter only counts actual visible symbols, ignoring + * 4-byte color code sequences, so method `Len()`, applied to + * the result of `ToColoredString()`, will return a bigger value + * than `maxLength`. + * @param defaultColor Color to be applied to the parts of the string that + * do not have any specified color. + * This is necessary, since 4-byte color sequences cannot unset the color. + * @return Colored `string` representation of the caller `BaseText`, + * i.e. `string` without any color information inside. + */ +public final function string ToColoredString( + optional int startIndex, + optional int maxLength, + optional Color defaultColor) +{ + local int i; + local Formatting newFormatting; + local Color nextColor, appliedColor; + local string result; + if (maxLength <= 0) { + maxLength = MaxInt; + } + else if (startIndex < 0) { + maxLength += startIndex; + } + startIndex = Max(0, startIndex); + // `appliedColor` will contain perfect black and so, + // guaranteed to be different from any actually used color + defaultColor = _.color.FixColor(defaultColor); + for (i = startIndex; i < codePoints.length; i += 1) + { + if (maxLength <= 0) { + break; + } + maxLength -= 1; + if (IsFormattingChangedAt(i) || i == startIndex) + { + newFormatting = GetFormatting(i); + if (newFormatting.isColored) { + nextColor = _.color.FixColor(newFormatting.color); + } + else { + nextColor = defaultColor; + } + // Colors are already fixed (and will be different from + // `appliedColor` before we initialize it) + if (!_.color.AreEqual(nextColor, appliedColor)) + { + result $= Chr(CODEPOINT_ESCAPE); + result $= Chr(nextColor.r); + result $= Chr(nextColor.g); + result $= Chr(nextColor.b); + appliedColor = nextColor; + } + } + result $= Chr(codePoints[i]); + } + return result; +} + +/** + * Converts data from the caller `BaseText` instance into a formatted `string`. + * Can be used to extract only substrings. + * + * If provided parameters `startIndex` and `maxLength` define a range that + * goes beyond `[0; self.GetLength() - 1]`, then intersection with a valid + * range will be used. + * + * @param startIndex Position of the first symbol to extract into a + * formatted `string`. By default `0`, corresponding to the first symbol. + * @param maxLength Max length of the extracted `string`. + * By default `0` - that and all negative values are replaces by `MaxInt`, + * effectively extracting as much of a `string` as possible. + * NOTE: this parameter only counts actual visible symbols, + * ignoring formatting blocks ('{ }') + * or escape sequences (i.e. '&{' is one character), + * so method `Len()`, applied to the result of + * `ToFormattedString()`, will return a bigger value + * than `maxLength`. + * @return Formatted `string` representation of the caller `BaseText`, + * i.e. `string` without any color information inside. + */ +public final function string ToFormattedString( + optional int startIndex, + optional int maxLength) +{ + local int i; + local bool isInsideBlock; + local string result; + local Formatting newFormatting; + if (maxLength <= 0) { + maxLength = MaxInt; + } + else if (startIndex < 0) { + maxLength += startIndex; + } + startIndex = Max(0, startIndex); + for (i = startIndex; i < codePoints.length; i += 1) + { + if (maxLength <= 0) { + break; + } + maxLength -= 1; + if (IsFormattingChangedAt(i) || i == startIndex) + { + newFormatting = GetFormatting(i); + if (isInsideBlock && i != startIndex) { + result $= STRING_CLOSE_FORMAT; + isInsideBlock = false; + } + if (newFormatting.isColored) { + result $= STRING_OPEN_FORMAT + $ _.color.ToString(newFormatting.color) + $ STRING_SEPARATOR_FORMAT; + isInsideBlock = true; + } + } + if ( codePoints[i] == CODEPOINT_OPEN_FORMAT + || codePoints[i] == CODEPOINT_CLOSE_FORMAT) { + result $= STRING_FORMAT_ESCAPE; + } + result $= Chr(codePoints[i]); + } + if (isInsideBlock) { + result $= STRING_CLOSE_FORMAT; + } + return result; +} + +/** + * Splits the string into substrings wherever `separator` occurs, and returns + * array of those strings. + * + * If `separator` does not match anywhere in the string, method returns a + * single-element array containing copy of this `Text`. + * + * @param separator Character that separates different parts of this `Text`. + * @param skipEmpty Set this to `true` to filter out empty `MutableText`s + * from the output. + * @return Array of `MutableText`s that contain separated substrings. + */ +public final function array SplitByCharacter( + Character separator, + optional bool skipEmpty) +{ + local int i, length; + local Character nextCharacter; + local MutableText nextText; + local array result; + length = GetLength(); + nextText = _.text.Empty(); + i = 0; + while (i < length) + { + nextCharacter = GetCharacter(i); + if (_.text.AreEqual(separator, nextCharacter)) + { + if (!skipEmpty || !nextText.IsEmpty()) { + result[result.length] = nextText; + } + else { + _.memory.Free(nextText); + } + nextText = _.text.Empty(); + } + else { + nextText.AppendCharacter(nextCharacter); + } + i += 1; + } + if (!skipEmpty || !nextText.IsEmpty()) { + result[result.length] = nextText; + } + return result; +} + +/** + * Returns the index position of the first occurrence of the `otherText` in + * the caller `BaseText`, searching forward from index position `fromIndex`. + * + * @param otherText `BaseText` data to find inside the caller + * `BaseText`. + * @param fromIndex Index from which we should start searching. + * @param caseSensitivity Defines whether comparison should be + * case-sensitive. By default it is. + * @param formatSensitivity Defines whether comparison should be + * sensitive for color information. By default it is not. + * @return `-1` if `otherText` is not found after `fromIndex`. + */ +public final function int IndexOf( + BaseText otherText, + optional int fromIndex, + optional CaseSensitivity caseSensitivity, + optional FormatSensitivity formatSensitivity) +{ + local int startCandidate; + local int index, otherIndex; + local Character char1, char2; + if (otherText == none) return -1; + if (fromIndex > GetLength()) return -1; + if (GetLength() - fromIndex < otherText.GetLength()) return -1; + if (otherText.IsEmpty()) return fromIndex; + + startCandidate = fromIndex; + for (index = fromIndex; index < GetLength(); index += 1) + { + char1 = GetCharacter(index); + char2 = otherText.GetCharacter(otherIndex); + if ( NormalizeCodePoint(char1.codePoint, caseSensitivity) + != NormalizeCodePoint(char2.codePoint, caseSensitivity)) + { + startCandidate = index + 1; + otherIndex = 0; + continue; + } + if ( formatSensitivity == SFORM_SENSITIVE + && !_.text.IsFormattingEqual(char1.formatting, char2.formatting)) + { + startCandidate = index + 1; + otherIndex = 0; + continue; + } + otherIndex += 1; + if (otherIndex == otherText.GetLength()) { + return startCandidate; + } + } + return -1; +} + +/** + * Returns the index position of the last occurrence of the `otherText` in + * the caller `BaseText`, searching backward from index position `fromIndex`, + * counted the end of the caller `BaseText`. + * + * @param otherText `BaseText` data to find inside the caller + * `BaseText`. + * @param fromIndex Index from which we should start searching, but + * it's counted from the end of the caller `BaseText`: `0` means starting + * from the last character, `1` means next to last, etc. + * @param caseSensitivity Defines whether comparison should be + * case-sensitive. By default it is. + * @param formatSensitivity Defines whether comparison should be + * sensitive for color information. By default it is not. + * @return `-1` if `otherText` is not found starting `fromIndex` + * (this index is counted from the end of the caller `BaseText`). + */ +public final function int LastIndexOf( + BaseText otherText, + optional int fromIndex, + optional CaseSensitivity caseSensitivity, + optional FormatSensitivity formatSensitivity) +{ + local int startCandidate; + local int index, otherIndex; + local Character char1, char2; + if (otherText == none) return -1; + if (fromIndex > GetLength()) return -1; + if (GetLength() - fromIndex < otherText.GetLength()) return -1; + if (otherText.IsEmpty()) return fromIndex; + + otherIndex = otherText.GetLength() - 1; + startCandidate = GetLength() - fromIndex - 1; + for (index = startCandidate; index >= 0; index -= 1) + { + char1 = GetCharacter(index); + char2 = otherText.GetCharacter(otherIndex); + if ( NormalizeCodePoint(char1.codePoint, caseSensitivity) + != NormalizeCodePoint(char2.codePoint, caseSensitivity)) + { + startCandidate = index - 1; + otherIndex = otherText.GetLength() - 1; + continue; + } + if ( formatSensitivity == SFORM_SENSITIVE + && !_.text.IsFormattingEqual(char1.formatting, char2.formatting)) + { + startCandidate = index - 1; + otherIndex = otherText.GetLength() - 1; + continue; + } + otherIndex -= 1; + if (otherIndex < 0) { + return startCandidate - (otherText.GetLength() - 1); + } + } + return -1; +} + +/** + * This method frees caller `MutableText` and returns immutable `Text` + * copy instead. + * + * @return Immutable `Text` copy of the caller `MutableText`. + */ +public function Text IntoText() +{ + return none; +} + +/** + * This method frees caller `Text` and returns immutable `Text` copy instead. + * + * @return Immutable `Text` copy of the caller `MutableText`. + */ +public function MutableText IntoMutableText() +{ + return none; +} + +defaultproperties +{ + STRING_SEPARATOR_FORMAT = " " + STRING_OPEN_FORMAT = "{" + STRING_CLOSE_FORMAT = "}" + STRING_FORMAT_ESCAPE = "&" + CODEPOINT_ESCAPE = 27 // ASCII escape code + CODEPOINT_OPEN_FORMAT = 123 // '{' + CODEPOINT_CLOSE_FORMAT = 125 // '}' + CODEPOINT_FORMAT_ESCAPE = 38 // '&' +} \ No newline at end of file diff --git a/sources/Text/Codecs/Utf8Decoder.uc b/sources/Text/Codecs/Utf8Decoder.uc index 5f86e8f..ccb8797 100644 --- a/sources/Text/Codecs/Utf8Decoder.uc +++ b/sources/Text/Codecs/Utf8Decoder.uc @@ -141,7 +141,7 @@ private final function bool PushInnerByte(byte nextByte) private final function AppendCodePoint(int codePoint) { - local Text.Character nextCharacter; + local BaseText.Character nextCharacter; nextCharacter.codePoint = codePoint; builtText.AppendCharacter(nextCharacter); } diff --git a/sources/Text/Codecs/Utf8Encoder.uc b/sources/Text/Codecs/Utf8Encoder.uc index af0042b..915a5ef 100644 --- a/sources/Text/Codecs/Utf8Encoder.uc +++ b/sources/Text/Codecs/Utf8Encoder.uc @@ -44,7 +44,7 @@ var private int lastSixBits; * `none` iff `text == none` or `text` contains invalid Unicode * code points. */ -public final function ByteArrayRef Encode(Text text) +public final function ByteArrayRef Encode(BaseText text) { local int i, nextCodepoint, textLength; local ByteArrayRef buffer; diff --git a/sources/Text/FormattedStrings/FormattingCommandsSequence.uc b/sources/Text/FormattedStrings/FormattingCommandsSequence.uc index 63d3aa2..6d2a23e 100644 --- a/sources/Text/FormattedStrings/FormattingCommandsSequence.uc +++ b/sources/Text/FormattedStrings/FormattingCommandsSequence.uc @@ -24,7 +24,7 @@ * along with Acedia. If not, see . */ class FormattingCommandsSequence extends AcediaObject - dependson(Text); + dependson(BaseText); enum FormattingCommandType { @@ -48,7 +48,7 @@ struct FormattingCommand // Formatting character for the "^"-type tag // This parameter is only used for `FST_StackSwap` command type. - var Text.Character charTag; + var BaseText.Character charTag; // Rest of the parameters are only used for `FST_StackPush` // command type. @@ -149,7 +149,7 @@ protected function Finalizer() * direct access to formatting commands defined in `input`. */ public final static function FormattingCommandsSequence FromText( - Text input, + BaseText input, optional FormattingErrorsReport errorsReporter) { local FormattingCommandsSequence newSequence; @@ -205,7 +205,7 @@ public final function FormattingCommand GetCommand(int commandIndex) private final function BuildSelf() { - local Text.Character nextCharacter; + local BaseText.Character nextCharacter; while (!parser.HasFinished()) { parser.MCharacter(nextCharacter); diff --git a/sources/Text/FormattedStrings/FormattingErrorsReport.uc b/sources/Text/FormattedStrings/FormattingErrorsReport.uc index 39aca14..84b6b65 100644 --- a/sources/Text/FormattedStrings/FormattingErrorsReport.uc +++ b/sources/Text/FormattedStrings/FormattingErrorsReport.uc @@ -95,7 +95,9 @@ protected function Finalizer() * do nothing. * Parameter is unused for other types of errors. */ -public final function Report(FormattedStringErrorType type, optional Text cause) +public final function Report( + FormattedStringErrorType type, + optional BaseText cause) { switch (type) { diff --git a/sources/Text/FormattedStrings/FormattingStringParser.uc b/sources/Text/FormattedStrings/FormattingStringParser.uc index e4520b1..44858b1 100644 --- a/sources/Text/FormattedStrings/FormattingStringParser.uc +++ b/sources/Text/FormattedStrings/FormattingStringParser.uc @@ -22,7 +22,7 @@ * along with Acedia. If not, see . */ class FormattingStringParser extends AcediaObject - dependson(Text) + dependson(BaseText) dependson(FormattingErrorsReport) dependson(FormattingCommandsSequence); @@ -121,7 +121,7 @@ var private MutableText borrowedTarget; var private FormattingErrorsReport borrowedErrors; // Keep this as an easy access to separator of gradient colors ':' -var private Text.Character separatorCharacter; +var private BaseText.Character separatorCharacter; var private const int TOPENING_BRACKET, TCLOSING_BRACKET, TPERCENT; @@ -165,7 +165,7 @@ protected function Finalizer() */ public static final function array ParseFormatted( - Text source, + BaseText source, optional MutableText target, optional bool doReportErrors) { @@ -207,7 +207,7 @@ public static final function array private final function DoAppend() { local int i; - local Text.Formatting emptyFormatting; + local BaseText.Formatting emptyFormatting; local FormattingCommandsSequence.FormattingCommand nextCommand; SetupFormattingStack(emptyFormatting); // First element of color stack is special and has no color information; @@ -262,7 +262,7 @@ private final function AppendToTarget(array contents) private final function Report( FormattingErrorsReport.FormattedStringErrorType type, - optional Text cause) + optional BaseText cause) { if (borrowedErrors == none) { return; @@ -278,9 +278,9 @@ private final function bool IsCurrentFormattingGradient() return formattingStackHead.gradient; } -private final function Text.Formatting GetFormattingFor(int index) +private final function BaseText.Formatting GetFormattingFor(int index) { - local Text.Formatting emptyFormatting; + local BaseText.Formatting emptyFormatting; if (formattingStack.length <= 0) return emptyFormatting; if (!formattingStackHead.colored) return emptyFormatting; @@ -319,7 +319,7 @@ private final function Color GetColorFor(int index) return targetColor; } -private final function FormattingInfo ParseFormattingInfo(Text colorTag) +private final function FormattingInfo ParseFormattingInfo(BaseText colorTag) { local int i; local Parser colorParser; @@ -477,7 +477,8 @@ private final function array NormalizePoints(array points) // that will be used when we pop all the other elements. // It is necessary to deal with possible folded formatting definitions in // formatted strings. -private final function SetupFormattingStack(Text.Formatting defaultFormatting) +private final function SetupFormattingStack( + BaseText.Formatting defaultFormatting) { local FormattingInfo defaultFormattingInfo; defaultFormattingInfo.colored = defaultFormatting.isColored; @@ -499,7 +500,7 @@ private final function PushIntoFormattingStack( formattingStack[formattingStack.length] = formattingStackHead; } -private final function SwapFormattingStack(Text.Character tagCharacter) +private final function SwapFormattingStack(BaseText.Character tagCharacter) { local FormattingInfo updatedFormatting; if (formattingStack.length > 0) { diff --git a/sources/Text/JSON/JSONAPI.uc b/sources/Text/JSON/JSONAPI.uc index 2cec812..9609b9f 100644 --- a/sources/Text/JSON/JSONAPI.uc +++ b/sources/Text/JSON/JSONAPI.uc @@ -28,8 +28,9 @@ class JSONAPI extends AcediaObject var private bool formattingInitialized; // Variables used in json pretty printing for defining used colors; // Colors are taken from `ColorAPI`. -var private Text.Formatting jPropertyName, jObjectBraces, jArrayBraces, jComma; -var private Text.Formatting jColon, jNumber, jBoolean, jString, jNull; +var private BaseText.Formatting jPropertyName, jObjectBraces, jArrayBraces; +var private BaseText.Formatting jComma, jColon, jNumber, jBoolean, jString; +var private BaseText.Formatting jNull; var const int TNULL, TTRUE, TFALSE, TDOT, TEXPONENT; var const int TOPEN_BRACKET, TCLOSE_BRACKET, TOPEN_BRACE, TCLOSE_BRACE; @@ -79,7 +80,7 @@ private final function InitFormatting() * an incorrect JSON pointer or `none`, - empty `JSONPointer` will be * returned. */ -public final function JSONPointer Pointer(optional Text pointerAsText) +public final function JSONPointer Pointer(optional BaseText pointerAsText) { return JSONPointer(_.memory.Allocate(class'JSONPointer')) .Set(pointerAsText); @@ -147,7 +148,7 @@ public final function TryNullWith(Parser parser) * @param source `Text` instance to parse JSON null value from. * @return `true` if parsing succeeded and `false` otherwise. */ -public final function bool IsNull(Text source) +public final function bool IsNull(BaseText source) { local bool parsingSucceeded; local Parser parser; @@ -258,7 +259,7 @@ public final function AcediaObject ParseBooleanWith( * Returns `none` iff parsing has failed. */ public final function AcediaObject ParseBoolean( - Text source, + BaseText source, optional bool parseAsMutable) { local bool result; @@ -476,7 +477,7 @@ public final function AcediaObject ParseNumberWith( * Returns `none` iff parsing has failed. */ public final function AcediaObject ParseNumber( - Text source, + BaseText source, optional bool parseAsMutable) { local int integerResult; @@ -534,7 +535,7 @@ public final function AcediaObject ParseNumber( * `none` otherwise. To check for parsing success check the state of * the `parser`. */ -public final function Text ParseStringWith( +public final function BaseText ParseStringWith( Parser parser, optional bool parseAsMutable) { @@ -572,8 +573,8 @@ public final function Text ParseStringWith( * `none` otherwise. To check for parsing success check the state of * the `parser`. */ -public final function Text ParseString( - Text source, +public final function BaseText ParseString( + BaseText source, optional bool parseAsMutable) { local bool parsingSuccessful; @@ -1250,7 +1251,7 @@ private final function MutableText PrettyPrintObjectWithIndent( // initialized. private final function PrettyPrintKeyValue( MutableText builder, - Text nextKey, + BaseText nextKey, AcediaObject nextValue, MutableText accumulatedIndent) { @@ -1276,12 +1277,12 @@ private final function PrettyPrintKeyValue( // representation. // We can't just dump `original`'s contents into JSON output as is, // since we have to replace several special characters with escaped sequences. -private final function MutableText DisplayText(Text original) +private final function MutableText DisplayText(BaseText original) { - local int i, length; - local MutableText result; - local Text.Character nextCharacter; - local Text.Character reverseSolidus; + local int i, length; + local MutableText result; + local BaseText.Character nextCharacter; + local BaseText.Character reverseSolidus; reverseSolidus = _.text.CharacterFromCodePoint(CODEPOINT_REVERSE_SOLIDUS); result = T(TQUOTE).MutableCopy(); length = original.GetLength(); diff --git a/sources/Text/JSON/JSONPointer.uc b/sources/Text/JSON/JSONPointer.uc index 1b10ddc..6e16898 100644 --- a/sources/Text/JSON/JSONPointer.uc +++ b/sources/Text/JSON/JSONPointer.uc @@ -90,7 +90,7 @@ public final function JSONPointer Empty() * @param pointerAsText `Text` representation of the JSON pointer. * @return Reference to the caller `JSONPointer` to allow for method chaining. */ -public final function JSONPointer Set(Text pointerAsText) +public final function JSONPointer Set(BaseText pointerAsText) { local int i; local bool hasEscapedSequences; @@ -144,7 +144,7 @@ public final function JSONPointer Set(Text pointerAsText) * no changes will be made at all. * @return Reference to the caller `JSONPointer` to allow for method chaining. */ -public final function JSONPointer Push(Text newComponent) +public final function JSONPointer Push(BaseText newComponent) { local Component newComponentRecord; if (newComponent == none) { @@ -199,7 +199,7 @@ public final function Text Pop(optional bool doNotRemove) lastIndex = components.length - 1; // Do not use `GetComponent()` to avoid unnecessary `Text` copying if (components[lastIndex].asText == none) { - result = _.text.FromIntM(components[lastIndex].asNumber); + result = _.text.FromInt(components[lastIndex].asNumber); } else { result = components[lastIndex].asText.Copy(); diff --git a/sources/Text/MutableText.uc b/sources/Text/MutableText.uc index 3b4c76a..c5829f2 100644 --- a/sources/Text/MutableText.uc +++ b/sources/Text/MutableText.uc @@ -1,5 +1,5 @@ /** - * Mutable version of Acedia's `Text` + * Mutable version of Acedia's `BaseText`. * Copyright 2020 - 2022 Anton Tarasenko *------------------------------------------------------------------------------ * This file is part of Acedia. @@ -17,10 +17,23 @@ * You should have received a copy of the GNU General Public License * along with Acedia. If not, see . */ -class MutableText extends Text; +class MutableText extends BaseText; var private int CODEPOINT_NEWLINE; +public function Text IntoText() +{ + local Text immutableVersion; + immutableVersion = Copy(); + FreeSelf(); + return immutableVersion; +} + +public function MutableText IntoMutableText() +{ + return self; +} + /** * Clears all current data from the caller `MutableText` instance. * @@ -44,7 +57,7 @@ public final function MutableText Clear() * @return Caller `MutableText` to allow for method chaining. */ public final function MutableText AppendRawCharacter( - Text.Character newCharacter, + BaseText.Character newCharacter, optional Formatting characterFormatting) { if (!_.text.IsValidCharacter(newCharacter)) { @@ -70,8 +83,8 @@ public final function MutableText AppendRawCharacter( * @return Caller `MutableText` to allow for method chaining. */ public final function MutableText AppendManyRawCharacters( - array newCharacters, - optional Formatting charactersFormatting) + array newCharacters, + optional Formatting charactersFormatting) { local int i; SetFormatting(charactersFormatting); @@ -88,7 +101,8 @@ public final function MutableText AppendManyRawCharacters( * Only valid characters will be added. * @return Caller `MutableText` to allow for method chaining. */ -public final function MutableText AppendCharacter(Text.Character newCharacter) +public final function MutableText AppendCharacter( + BaseText.Character newCharacter) { if (!_.text.IsValidCharacter(newCharacter)) { return self; @@ -105,7 +119,7 @@ public final function MutableText AppendCharacter(Text.Character newCharacter) * @return Caller `MutableText` to allow for method chaining. */ public final function MutableText AppendManyCharacters( - array newCharacters) + array newCharacters) { local int i; for (i = 0; i < newCharacters.length; i += 1) { @@ -153,10 +167,10 @@ public final function MutableText AppendLineBreak() } /** - * Appends contents of another `Text` to the caller `MutableText`. + * Appends contents of another `BaseText` to the caller `MutableText`. * - * @param other Instance of `Text`, which content method must - * append. Appends nothing if passed value is `none`. + * @param other Instance of `BaseText`, which content method + * will append. Appends nothing if passed value is `none`. * @param defaultFormatting Formatting to apply to `other`'s character that * do not have it specified. For example, `defaultFormatting.isColored`, * but some of `other`'s characters do not have a color defined - @@ -164,7 +178,7 @@ public final function MutableText AppendLineBreak() * @return Caller `MutableText` to allow for method chaining. */ public final function MutableText Append( - Text other, + BaseText other, optional Formatting defaultFormatting) { local int i; @@ -255,7 +269,7 @@ public final function MutableText AppendColoredString( { if (i + 3 >= sourceLength) break; newFormatting.isColored = true; - newFormatting.color = _.color.RGB(sourceAsIntegers[i + 1], + newFormatting.color = _.color.RGB( sourceAsIntegers[i + 1], sourceAsIntegers[i + 2], sourceAsIntegers[i + 3]); i += 4; @@ -271,14 +285,14 @@ public final function MutableText AppendColoredString( } /** - * Appends contents of the formatted `Text` to the caller `MutableText`. + * Appends contents of the formatted `BaseText` to the caller `MutableText`. * - * @param source `Text` (with formatted string contents) to be + * @param source `BaseText` (with formatted string contents) to be * appended to the caller `MutableText`. * @return Caller `MutableText` to allow for method chaining. */ public final function MutableText AppendFormatted( - Text source, + BaseText source, optional Formatting defaultFormatting) { class'FormattingStringParser'.static.ParseFormatted(source, self); @@ -296,8 +310,8 @@ public final function MutableText AppendFormattedString( string source, optional Formatting defaultFormatting) { - local Text sourceAsText; - sourceAsText = _.text.FromString(source); + local MutableText sourceAsText; + sourceAsText = _.text.FromStringM(source); AppendFormatted(sourceAsText); _.memory.Free(sourceAsText); return self; @@ -316,10 +330,11 @@ protected function int CalculateHashCode() } /** - * Replaces every occurrence of the string `before` with the string `after`. + * Replaces every occurrence of the `Text` object `before` with + * the `Text` object `after`. * - * @param before `Text` contents to match and then replace. - * @param after `Text` contents to replace `before` with. + * @param before `BaseText` contents to match and then replace. + * @param after `BaseText` contents to replace `before` with. * @param caseSensitivity Defines whether `before` should be matched * in a case-sensitive manner. By default it will be. * @param formatSensitivity Defines whether `before` should be matched @@ -327,15 +342,15 @@ protected function int CalculateHashCode() * @return Returns caller `MutableText`, to allow for method chaining. */ public final function MutableText Replace( - Text before, - Text after, + BaseText before, + BaseText after, optional CaseSensitivity caseSensitivity, optional FormatSensitivity formatSensitivity) { - local int index; - local bool needToInsertReplacer; - local int nextReplacementIndex; - local Text selfCopy; + local int index; + local bool needToInsertReplacer; + local int nextReplacementIndex; + local BaseText selfCopy; if (before == none) return self; if (before.IsEmpty()) return self; @@ -372,10 +387,34 @@ public final function MutableText Replace( } /** - * Sets `newFormatting` for every non-formatted character in the caller `Text`. + * Replaces every occurrence of the string `before` with the string `after`. + * + * @param before `string` contents to match and then replace. + * @param after `string` contents to replace `before` with. + * @param caseSensitivity Defines whether `before` should be matched + * in a case-sensitive manner. By default it will be. + * @return Returns caller `MutableText`, to allow for method chaining. + */ +public final function MutableText ReplaceS( + string before, + string after, + optional CaseSensitivity caseSensitivity) +{ + local MutableText beforeText, afterText; + beforeText = _.text.FromStringM(before); + afterText = _.text.FromStringM(after); + Replace(beforeText, afterText, caseSensitivity); + _.memory.Free(beforeText); + _.memory.Free(afterText); + return self; +} + +/** + * Sets `newFormatting` for every non-formatted character in + * the caller `MutableText`. * * @param newFormatting Formatting to use for all non-formatted character in - * the caller `Text`. If `newFormatting` is not colored itself - + * the caller `MutableText`. If `newFormatting` is not colored itself - * method does nothing. * @return Returns caller `MutableText`, to allow for method chaining. */ diff --git a/sources/Text/Parser.uc b/sources/Text/Parser.uc index f02d12c..2bb3938 100644 --- a/sources/Text/Parser.uc +++ b/sources/Text/Parser.uc @@ -19,7 +19,7 @@ * along with Acedia. If not, see . */ class Parser extends AcediaObject - dependson(Text) + dependson(BaseText) dependson(UnicodeData); // Max value of a byte @@ -75,7 +75,7 @@ enum ParsedSign // Common logic for parser initialization. // Uses `source` as is, without copying, so public initialization method // must do it itself. -private final function Parser _initialize(Text source) +private final function Parser _initialize(/*take*/ Text source) { if (source == none) return self; @@ -98,7 +98,7 @@ private final function Parser _initialize(Text source) * If `none` is passed - parser won't be initialized. * @return Returns the caller `Parser`, to allow for function chaining. */ -public final function Parser Initialize(Text source) +public final function Parser Initialize(BaseText source) { if (source == none) { return self; @@ -304,10 +304,10 @@ protected final function Parser ShiftPointer(optional int shift) * invalid character if caller `Parser` was not initialized, * its contents are empty or it has already consumed all input. */ -protected final function Text.Character GetCharacter(optional int shift) +protected final function BaseText.Character GetCharacter(optional int shift) { - local Text.Character invalidCharacter; - local int absoluteAddress; + local BaseText.Character invalidCharacter; + local int absoluteAddress; if (content == none) return _.text.GetInvalidCharacter(); absoluteAddress = currentState.pointer + Max(0, shift); @@ -377,11 +377,12 @@ public final function bool HasFinished() } /** - * Returns still unparsed part of caller `Parser`'s source as `Text`. + * Returns still unparsed part of caller `Parser`'s source as `MutableText`. * - * @return Unparsed part of caller `Parser`'s source as `Text`. + * @return Unparsed part of caller `Parser`'s source as `MutableText`. + * Guaranteed to be not-`none`. */ -public final function Text GetRemainder() +public final function MutableText GetRemainderM() { local int i; local MutableText result; @@ -392,6 +393,17 @@ public final function Text GetRemainder() return result; } +/** + * Returns still unparsed part of caller `Parser`'s source as `Text`. + * + * @return Unparsed part of caller `Parser`'s source as `Text`. + * Guaranteed to be not-`none`. + */ +public final function Text GetRemainder() +{ + return GetRemainderM().IntoText(); +} + /** * Returns still unparsed part of caller `Parser`'s source as a plain `string`. * @@ -475,8 +487,8 @@ public final function Parser Skip(optional out int whitespacesAmount) * @return Returns the caller `Parser`, to allow for function chaining. */ public final function Parser Match( - Text word, - optional Text.CaseSensitivity caseSensitivity) + BaseText word, + optional BaseText.CaseSensitivity caseSensitivity) { local int i; local int wordLength; @@ -513,8 +525,8 @@ public final function Parser Match( * @return Returns the caller `Parser`, to allow for function chaining. */ public final function Parser MatchS( - string word, - optional Text.CaseSensitivity caseSensitivity) + string word, + optional BaseText.CaseSensitivity caseSensitivity) { local Text wrapper; wrapper = _.text.FromString(word); @@ -639,7 +651,7 @@ protected final function int SafeIntegerCombination( * @return Returns the caller `Parser`, to allow for function chaining. */ public final function Parser MEscapedSequence( - out Text.Character denotedCharacter) + out BaseText.Character denotedCharacter) { local int i; if (!Ok()) return self; @@ -686,8 +698,8 @@ public final function Parser MEscapedSequence( */ public final function Parser MName(out MutableText result) { - local TextAPI api; - local Text.Character nextCharacter; + local TextAPI api; + local BaseText.Character nextCharacter; ResetResultText(result); if (!Ok()) return self; if (GetRemainingLength() <= 0) return Fail(); @@ -753,10 +765,10 @@ public final function Parser MNameS(out string result) */ public final function Parser MStringLiteral(out MutableText result) { - local TextAPI api; - local Text.Character nextCharacter; - local Text.Character usedQuotationMark; - local Text.Character escapedCharacter; + local TextAPI api; + local BaseText.Character nextCharacter; + local BaseText.Character usedQuotationMark; + local BaseText.Character escapedCharacter; ResetResultText(result); if (!Ok()) return self; usedQuotationMark = GetCharacter(); @@ -843,13 +855,13 @@ public final function Parser MStringLiteralS(out string result) * @return Returns the caller `Parser`, to allow for function chaining. */ public final function Parser MUntil( - out MutableText result, - optional Text.Character characterBreak, - optional bool whitespacesBreak, - optional bool quotesBreak) + out MutableText result, + optional BaseText.Character characterBreak, + optional bool whitespacesBreak, + optional bool quotesBreak) { - local Text.Character nextCharacter; - local TextAPI api; + local BaseText.Character nextCharacter; + local TextAPI api; ResetResultText(result); if (!Ok()) return self; @@ -889,10 +901,10 @@ public final function Parser MUntil( * @return Returns the caller `Parser`, to allow for function chaining. */ public final function Parser MUntilS( - out string result, - optional Text.Character characterBreak, - optional bool whitespacesBreak, - optional bool quotesBreak) + out string result, + optional BaseText.Character characterBreak, + optional bool whitespacesBreak, + optional bool quotesBreak) { local MutableText wrapper; if (!Ok()) return self; @@ -929,14 +941,14 @@ public final function Parser MUntilS( */ public final function Parser MUntilMany( out MutableText result, - array separators, + array separators, optional bool whitespacesBreak, optional bool quotesBreak) { - local bool foundEnd; - local int i, pointerShift; - local array completions; - local Text.Character nextCharacter, separatorCharacter; + local bool foundEnd; + local int i, pointerShift; + local array completions; + local BaseText.Character nextCharacter, separatorCharacter; ResetResultText(result); if (!Ok()) return self; @@ -1002,7 +1014,7 @@ public final function Parser MUntilMany( */ public final function Parser MUntilManyS( out string result, - array separators, + array separators, optional bool whitespacesBreak, optional bool quotesBreak) { @@ -1093,8 +1105,8 @@ public final function Parser MStringS(out string result) */ public final function Parser MWhitespaces(out MutableText result) { - local Text.Character nextCharacter; - local TextAPI api; + local BaseText.Character nextCharacter; + local TextAPI api; if (!Ok()) return self; api = _.text; @@ -1148,7 +1160,7 @@ public final function Parser MWhitespacesS(out string result) * Any passed value is discarded. * @return Returns the caller `Parser`, to allow for function chaining. */ -public final function Parser MCharacter(out Text.Character result) +public final function Parser MCharacter(out BaseText.Character result) { if (!Ok()) return self; if (HasFinished()) return Fail(); @@ -1170,7 +1182,7 @@ public final function Parser MCharacter(out Text.Character result) */ public final function Parser MByte(out byte result) { - local Text.Character character; + local BaseText.Character character; if (!Ok()) return self; if (!MCharacter(character).Ok()) diff --git a/sources/Text/Tests/TEST_FormattedStrings.uc b/sources/Text/Tests/TEST_FormattedStrings.uc index 23f6aa9..4b3569e 100644 --- a/sources/Text/Tests/TEST_FormattedStrings.uc +++ b/sources/Text/Tests/TEST_FormattedStrings.uc @@ -212,7 +212,7 @@ protected static function SubTest_TestGradientTwoColors() TEST_ExpectTrue(currentColor.b == 56); } -protected static function CheckRedDecrease(Text sample, int from, int to) +protected static function CheckRedDecrease(BaseText sample, int from, int to) { local int i; local Color previousColor, currentColor; @@ -227,7 +227,7 @@ protected static function CheckRedDecrease(Text sample, int from, int to) } } -protected static function CheckRedIncrease(Text sample, int from, int to) +protected static function CheckRedIncrease(BaseText sample, int from, int to) { local int i; local Color previousColor, currentColor; diff --git a/sources/Text/Tests/TEST_Parser.uc b/sources/Text/Tests/TEST_Parser.uc index 2abd84f..c04a9ea 100644 Binary files a/sources/Text/Tests/TEST_Parser.uc and b/sources/Text/Tests/TEST_Parser.uc differ diff --git a/sources/Text/Tests/TEST_Text.uc b/sources/Text/Tests/TEST_Text.uc index 898df44..46af352 100644 Binary files a/sources/Text/Tests/TEST_Text.uc and b/sources/Text/Tests/TEST_Text.uc differ diff --git a/sources/Text/Tests/TEST_TextAPI.uc b/sources/Text/Tests/TEST_TextAPI.uc index 4c78867..e4b6968 100644 Binary files a/sources/Text/Tests/TEST_TextAPI.uc and b/sources/Text/Tests/TEST_TextAPI.uc differ diff --git a/sources/Text/Tests/TEST_UTF8EncoderDecoder.uc b/sources/Text/Tests/TEST_UTF8EncoderDecoder.uc index f439392..44c6f7b 100644 Binary files a/sources/Text/Tests/TEST_UTF8EncoderDecoder.uc and b/sources/Text/Tests/TEST_UTF8EncoderDecoder.uc differ diff --git a/sources/Text/Text.uc b/sources/Text/Text.uc index 31d5747..8d66cbc 100644 --- a/sources/Text/Text.uc +++ b/sources/Text/Text.uc @@ -1,6 +1,6 @@ /** - * Acedia's implementation of an immutable text (string) object. - * Since it is not native class, it has additional costs for it's creation and + * Acedia's type for an immutable text (string) object. + * Since it is not native type, it has additional costs for it's creation and * some of it operations, but it: * 1. Supports a more convenient (than native 4-byte color sequences) * storing of format information and allows to extract `string`s with @@ -28,1478 +28,21 @@ * You should have received a copy of the GNU General Public License * along with Acedia. If not, see . */ -class Text extends AcediaObject; +class Text extends BaseText; -// Enumeration that describes how should we treat `Text`s that differ in -// case only. -// By default we would consider them unequal. -enum CaseSensitivity +public function Text IntoText() { - SCASE_SENSITIVE, - SCASE_INSENSITIVE -}; - -// Enumeration that describes how should we treat `Text`s that differ only -// in their formatting. -// By default we would consider them unequal. -enum FormatSensitivity -{ - SFORM_INSENSITIVE, - SFORM_SENSITIVE -}; - -// Describes text formatting, can be applied per-character. -struct Formatting -{ - // Whether this formatting describes a color of the text - var bool isColored; - // Color of the text, used only when `isColored == true` - var Color color; -}; - -// Represents one character, together with it's formatting -struct Character -{ - var int codePoint; - var Formatting formatting; -}; - -// Actual content of the `Text` is stored as a sequence of Unicode code points. -var private array codePoints; -// Structure for inner use, describes a change of formatting to `formatting`, -// starting from index `startIndex` -struct FormattingChunk -{ - var private int startIndex; - var private Formatting formatting; -}; -// Series of `FormattingChunk` that defines formatting over characters, -// defined by `codePoints`. -// This array is sorted by `startIndex` of it's elements and -// formatting for character at is defined by the `FormattingChunk` -// with the largest `startIndex <= `. -var private array formattingChunks; -// To optimize look up of formatting for characters we remember index of -// the last used `FormattingChunk` to attempt to start the next lookup -// from that point. -// This improves performance when several lookups are done in order. -var private int formattingIndexCache; - -/* - * Even though `Text` is an immutable object, for child classes we - * encapsulate direct access to `codePoints` by providing a way to append - * new data to it's content through protected methods. - * For that we implement `AppendCodePoint()` and `AppendManyCodePoints()` - * methods that allow to add code points 1-by-1. - * To reduce the amount of checks, formatting is set not per-code point, - * but separately by `SetFormatting()`: to append a group of code points with - * a certain formatting one has to first set their formatting, - * then just add code points. - */ -// Formatting to use for the next code point -var private Formatting nextFormatting; -// `true` if the next code point will have a different formatting from -// the last added one. -var private bool formattingUpdated; - -// Escape code point is used to change output's color and is used in -// Unreal Engine's `string`s. -var protected const int CODEPOINT_ESCAPE; -// Opening and closing symbols for colored blocks in formatted strings. -var protected const int CODEPOINT_OPEN_FORMAT; -var protected const int CODEPOINT_CLOSE_FORMAT; -var protected const string STRING_OPEN_FORMAT; -var protected const string STRING_CLOSE_FORMAT; -// Symbol for separating opening formatting block from it's contents -var protected const string STRING_SEPARATOR_FORMAT; -// Symbol to escape any character in formatted strings, -// including above mentioned opening and closing symbols. -var protected const int CODEPOINT_FORMAT_ESCAPE; -var protected const string STRING_FORMAT_ESCAPE; - -// Simply free all used memory. -protected function Finalizer() -{ - codePoints.length = 0; - formattingChunks.length = 0; -} - -/** - * Auxiliary method that changes formatting of the whole `Text` to - * a specified one (`newFormatting`). This method is faster than calling - * `ReformatRange`. - * - * @param newFormatting Formatting to set to the whole `Text`. - */ -protected final function ReformatWhole(Formatting newFormatting) -{ - local FormattingChunk newChunk; - formattingChunks.length = 0; - newChunk.startIndex = 0; - newChunk.formatting = newFormatting; - formattingChunks[0] = newChunk; -} - -/** - * Auxiliary method that changes formatting of the characters with indices in - * range `[start; end]` to a specified one (`newFormatting`). - * - * This method assumes, but does not check that: - * 1. `start <= end`; - * 2. `start` and `end` parameters belong to the range of valid indices - * `[0; GetLength() - 1]` - * - * @param start First character to change formatting of. - * @param end Last character to change formatting of. - * @param newFormatting Formatting to set to the specified characters. - */ -protected final function ReformatRange( - int start, - int end, - Formatting newFormatting) -{ - local int i; - local Formatting formattingAfterChangedSegment; - local FormattingChunk newChunk; - local array newFormattingChunks; - start = Max(start, 0); - end = Min(GetLength() - 1, end); - // Formatting right after `end`, the end of re-formatted segment - formattingAfterChangedSegment = GetFormatting(end + 1); - // 1. Copy old formatting before `start` - for (i = 0; i < formattingChunks.length; i += 1) - { - if (start <= formattingChunks[i].startIndex) { - break; - } - newFormattingChunks[newFormattingChunks.length] = formattingChunks[i]; - } - newChunk.formatting = newFormatting; - newChunk.startIndex = start; - newFormattingChunks[newFormattingChunks.length] = newChunk; - if (end == GetLength() - 1) - { - formattingChunks = newFormattingChunks; - // We have inserted `FormattingChunk` without checking if it actually - // changes formatting. It might be excessive, so do a normalization. - NormalizeFormatting(); - return; - } - // 2. Drop old formatting overwritten by `newFormatting` - while (i < formattingChunks.length) - { - if (end < formattingChunks[i].startIndex) { - break; - } - i += 1; - } - // 3. Copy old formatting after `end` - newChunk.formatting = formattingAfterChangedSegment; - newChunk.startIndex = end + 1; // end < GetLength() - 1 - newFormattingChunks[newFormattingChunks.length] = newChunk; - while (i < formattingChunks.length) - { - newFormattingChunks[newFormattingChunks.length] = formattingChunks[i]; - i += 1; - } - formattingChunks = newFormattingChunks; - // We have inserted `FormattingChunk` without checking if it actually - // changes formatting. It might be excessive, so do a normalization. - NormalizeFormatting(); -} - -/** - * Static method for creating an immutable `Text` object from (plain) `string`. - * - * It is preferred to use `TextAPI` methods for creating `Text` instances. - * - * @param source Plain `string` to convert into `Text`. - * @return `Text` instance (guaranteed to be not `none`) that stores contents - * of `source` if treated as a plain `string`. - */ -public static final function Text ConstFromPlainString(string source) -{ - local MutableText builder; - local Text result; - builder = MutableText(__().memory.Allocate(class'MutableText')); - result = builder.AppendString(source).Copy(); - builder.FreeSelf(); - return result; -} - -/** - * Static method for creating an immutable `Text` object from - * (colored) `string`. - * - * It is preferred to use `TextAPI` methods for creating `Text` instances. - * - * @param source Colored `string` to convert into `Text`. - * @return `Text` instance (guaranteed to be not `none`) that stores contents - * of `source` if treated as a colored `string`. - */ -public static final function Text ConstFromColoredString(string source) -{ - local MutableText builder; - local Text result; - builder = MutableText(__().memory.Allocate(class'MutableText')); - result = builder.AppendColoredString(source).Copy(); - builder.FreeSelf(); - return result; -} - -/** - * Static method for creating an immutable `Text` object from - * (formatted) `string`. - * - * It is preferred to use `TextAPI` methods for creating `Text` instances. - * - * @param source Formatted `string` to convert into `Text`. - * @return `Text` instance (guaranteed to be not `none`) that stores contents - * of `source` if treated as a formatted `string`. - */ -public static final function Text ConstFromFormattedString(string source) -{ - local MutableText builder; - local Text result; - builder = MutableText(__().memory.Allocate(class'MutableText')); - result = builder.AppendFormattedString(source).Copy(); - builder.FreeSelf(); - return result; -} - -/** - * Makes an immutable copy (`class'Text'`) of the caller `Text`. - * - * Copies characters in the range `[startIndex; startIndex + maxLength - 1]` - * If provided parameters `startIndex` and `maxLength` define a range that - * goes beyond `[0; self.GetLength() - 1]`, then intersection with a valid - * range will be used. - * - * @param startIndex Position of the first character to copy. - * By default `0`, corresponding to the very first character. - * @param maxLength Max length of the extracted string. By default `0`, - * - that and all negative values mean that method should extract all - * characters to the right of `startIndex`. - * @return Immutable copy of the caller `Text` instance. - * Guaranteed to be not `none` and have class `Text`. - */ -public final function Text Copy( - optional int startIndex, - optional int maxLength) -{ - // `startIndex` is inclusive and `endIndex` is not - local int i, endIndex; - local Text copy; - local Character nextCharacter; - if (maxLength <= 0) { - maxLength = codePoints.length - startIndex; - } - endIndex = startIndex + maxLength; - copy = Text(_.memory.Allocate(class'Text')); - // Edge cases - if (endIndex <= 0) { - return copy; - } - if (startIndex <= 0 && startIndex + maxLength >= codePoints.length) - { - copy.codePoints = codePoints; - copy.formattingChunks = formattingChunks; - return copy; - } - // Substring copy - if (startIndex < 0) { - startIndex = 0; - } - endIndex = Min(endIndex, codePoints.length); - for (i = startIndex; i < endIndex; i += 1) - { - nextCharacter = GetCharacter(i); - copy.SetFormatting(nextCharacter.formatting); - copy.AppendCodePoint(nextCharacter.codePoint); - } - return copy; -} - -/** - * Makes a mutable copy (`class'MutableText'`) of the caller text instance. - * - * If provided parameters `startIndex` and `maxLength` define a range that - * goes beyond `[0; self.GetLength() - 1]`, then intersection with a valid - * range will be used. - * - * @param startIndex Position of the first character to copy. - * By default `0`, corresponding to the very first character. - * @param maxLength Max length of the extracted string. By default `0`, - * - that and all negative values mean that method should extract all - * characters to the right of `startIndex`. - * @return Mutable copy of the caller `Text` instance. - * Guaranteed to be not `none` and have class `MutableText`. - */ -public final function MutableText MutableCopy( - optional int startIndex, - optional int maxLength) -{ - // `startIndex` is inclusive and `endIndex` is not - local int i, endIndex; - local MutableText copy; - if (maxLength <= 0) { - maxLength = codePoints.length - startIndex; - } - endIndex = startIndex + maxLength; - copy = MutableText(_.memory.Allocate(class'MutableText')); - // Edge cases - if (endIndex <= 0 || startIndex >= codePoints.length) { - return copy; - } - if (startIndex <= 0 && startIndex + maxLength >= codePoints.length) - { - copy.codePoints = codePoints; - copy.formattingChunks = formattingChunks; - return copy; - } - // Substring copy - if (startIndex < 0) { - startIndex = 0; - } - endIndex = Min(endIndex, codePoints.length); - for (i = startIndex; i < endIndex; i += 1) { - copy.AppendCharacter(GetCharacter(i)); - } - return copy; -} - -/** - * Makes an immutable copy (`class'Text'`) of the caller `Text` - * in a lower case. - * - * If provided parameters `startPosition` and `maxLength` define a range that - * goes beyond `[0; self.GetLength() - 1]`, then intersection with a valid - * range will be used. - * - * @param startPosition Position of the first character to copy. - * By default `0`, corresponding to the very first character. - * @param maxLength Max length of the extracted string. By default `0`, - * - that and all negative values mean that method should extract all - * characters to the right of `startIndex`. - * @return Immutable copy of caller `Text` in a lower case. - * Guaranteed to be not `none` and have class `Text`. - */ -public final function Text LowerCopy( - optional int startIndex, - optional int maxLength) -{ - local Text textCopy; - textCopy = Copy(startIndex, maxLength); - textCopy.ConvertCase(true); - return textCopy; -} - -/** - * Makes an immutable copy (`class'Text'`) of the caller `Text` - * in a upper case. - * - * If provided parameters `startPosition` and `maxLength` define a range that - * goes beyond `[0; self.GetLength() - 1]`, then intersection with a valid - * range will be used. - * - * @param startPosition Position of the first character to copy. - * By default `0`, corresponding to the very first character. - * @param maxLength Max length of the extracted string. By default `0`, - * - that and all negative values mean that method should extract all - * characters to the right of `startIndex`. - * @return Immutable copy of caller `Text` in a upper case. - * Guaranteed to be not `none` and have class `Text`. - */ -public final function Text UpperCopy( - optional int startIndex, - optional int maxLength) -{ - local Text textCopy; - textCopy = Copy(startIndex, maxLength); - textCopy.ConvertCase(false); - return textCopy; -} - -/** - * Makes a mutable copy (`class'MutableText'`) of the caller text instance - * in lower case. - * - * If provided parameters `startPosition` and `maxLength` define a range that - * goes beyond `[0; self.GetLength() - 1]`, then intersection with a valid - * range will be used. - * - * @param startPosition Position of the first character to copy. - * By default `0`, corresponding to the very first character. - * @param maxLength Max length of the extracted string. By default `0`, - * - that and all negative values mean that method should extract all - * characters to the right of `startIndex`. - * @return Mutable copy of caller `Text` instance in lower case. - * Guaranteed to be not `none` and have class `MutableText`. - */ -public final function MutableText LowerMutableCopy( - optional int startIndex, - optional int maxLength) -{ - local MutableText textCopy; - textCopy = MutableCopy(startIndex, maxLength); - textCopy.ConvertCase(true); - return textCopy; -} - -/** - * Makes a mutable copy (`class'MutableText'`) of the caller text instance - * in upper case. - * - * If provided parameters `startPosition` and `maxLength` define a range that - * goes beyond `[0; self.GetLength() - 1]`, then intersection with a valid - * range will be used. - * - * @param startPosition Position of the first character to copy. - * By default `0`, corresponding to the very first character. - * @param maxLength Max length of the extracted string. By default `0`, - * - that and all negative values mean that method should extract all - * characters to the right of `startIndex`. - * @return Mutable copy of caller `Text` instance in upper case. - * Guaranteed to be not `none` and have class `MutableText`. - */ -public final function MutableText UpperMutableCopy( - optional int startIndex, - optional int maxLength) -{ - local MutableText textCopy; - textCopy = MutableCopy(startIndex, maxLength); - textCopy.ConvertCase(false); - return textCopy; -} - -/** - * Checks if caller `Text` contains a valid name for a config object or not. - * - * Valid names contain only ASCII characters, digits and '.' / '_' characters. - * Empty `Text` is not considered a valid name. - * - * @return `true` if caller `Text` contains a valid config object name and - * `false` otherwise. - */ -public final function bool IsValidConfigName() -{ - local int i; - local int codePoint; - local bool isValidCodePoint; - local Character nextCharacter; - if (IsEmpty()) { - return false; - } - for (i = 0; i < GetLength(); i += 1) - { - nextCharacter = GetCharacter(i); - codePoint = nextCharacter.codePoint; - isValidCodePoint = - ( (codePoint == 0x2E) || (codePoint == 0x5F) // '.' or '_' - || (0x30 <= codePoint && codePoint <= 0x39) // '0' to '9' - || (0x41 <= codePoint && codePoint <= 0x5A) // 'A' to 'Z' - || (0x61 <= codePoint && codePoint <= 0x7A)); // 'a' to 'z' - if (!isValidCodePoint) { - return false; - } - } - return true; -} - -/** - * Auxiliary function that converts case of the caller `Text` object. - * As `Text` is supposed to be immutable, cannot be public. - * - * @param toLower `true` if caller `Text` must be converted to the lower case - * and `false` otherwise. - */ -protected final function ConvertCase(bool toLower) -{ - local int i; - local Character nextCharacter; - for (i = 0; i < GetLength(); i += 1) - { - nextCharacter = GetCharacter(i); - if (toLower) { - nextCharacter = _.text.ToLower(nextCharacter); - } - else { - nextCharacter = _.text.ToUpper(nextCharacter); - } - codePoints[i] = nextCharacter.codePoint; - } -} - -/** - * Calculates hash value of the caller `Text`. Hash will depend only on - * it's textual contents, without taking formatting (color information) - * into account. - * - * @return Hash, that depends on textual contents only. - */ -protected function int CalculateHashCode() -{ - local int i; - local int hash; - // Manually inline `CombineHash()`, to avoid too many calls - // (and infinite loop detection) for some long text data. - hash = 5381; - for (i = 0; i < codePoints.length; i += 1) - { - // hash * 33 + codePoints[i] - hash = ((hash << 5) + hash) + codePoints[i]; - } - return hash; -} - -/** - * Checks whether contents of the caller `Text` are empty. - * - * @return `true` if caller `Text` contains no symbols. - */ -public final function bool IsEmpty() -{ - return (codePoints.length == 0); -} - -/** - * Returns current length of the caller `Text` in symbols. - * - * Do note that codepoint is not the same as a symbol, since one symbol - * can consist of several code points. While current implementation only - * supports symbols represented by a single code point, this might change - * in the future. - * - * @return Current length of caller `Text`'s contents in symbols. - */ -public final function int GetLength() -{ - return codePoints.length; -} - -/** - * Override equality check for `Text` to make two different `Text`s equal - * based on their text contents. - * Text equality check is case-sensitive and does not take formatting - * into account. - * - * `Text` cannot be equal to object of any class that is not - * derived from `Text`. - * - * @param other Object to compare to the caller. - * `none` is only equal to the `none`. - * @return `true` if `other` is considered equal to the caller `Text`, - * `false` otherwise. - */ -public function bool IsEqual(Object other) -{ - if (self == other) { - return true; - } - return Compare(Text(other)); -} - -// "Normalizes" code point for comparison by converting it to lower case if -// `caseSensitivity == SCASE_INSENSITIVE`. -// Otherwise returns same code point. -private final function int NormalizeCodePoint( - int codePoint, - CaseSensitivity caseSensitivity) -{ - local int newCodePoint; - if (caseSensitivity == SCASE_INSENSITIVE) { - newCodePoint = class'UnicodeData'.static.ToLowerCodePoint(codePoint); - } - else { - newCodePoint = codePoint; - } - if (newCodePoint < 0) { - return codePoint; - } - return newCodePoint; -} - -/** - * Method for checking equality between the caller and another `Text` object. - * - * This method supports comparison both sensitive and not sensitive to - * the case and difference in formatting (color of the characters). - * By default comparison is case-sensitive, but ignores - * formatting information. - * - * @param otherText `Text` to compare caller instance to. - * @param caseSensitivity Defines whether comparison should be - * case-sensitive. By default it is. - * @param formatSensitivity Defines whether comparison should be - * sensitive for color information. By default it is not. - * @return `true` if the caller `Text` is equal to the `otherText` under - * specified parameters and `false` otherwise. - */ -public final function bool Compare( - Text otherText, - optional CaseSensitivity caseSensitivity, - optional FormatSensitivity formatSensitivity) -{ - local int i; - local array otherCodePoints; - if (otherText == none) { - return false; - } - if (GetLength() != otherText.GetLength()) { - return false; - } - if (formatSensitivity == SFORM_SENSITIVE && !CompareFormatting(otherText)) { - return false; - } - // Copy once to avoid doing it each iteration - otherCodePoints = otherText.codePoints; - for (i = 0; i < codePoints.length; i += 1) - { - if ( NormalizeCodePoint(codePoints[i], caseSensitivity) - != NormalizeCodePoint(otherCodePoints[i], caseSensitivity)) { - return false; - } - } - return true; -} - -/** - * Method for checking if the caller starts with another `Text` object. - * - * This method supports comparison both sensitive and not sensitive to - * the case and difference in formatting (color of the characters). - * By default comparison is case-sensitive, but ignores - * formatting information. - * - * @param otherText `Text` that caller is checked to start with. - * @param caseSensitivity Defines whether comparison should be - * case-sensitive. By default it is. - * @param formatSensitivity Defines whether comparison should be - * sensitive for color information. By default it is not. - * @return `true` if the caller `Text` starts with `otherText` under - * specified parameters and `false` otherwise. - */ -public final function bool StartsWith( - Text otherText, - optional CaseSensitivity caseSensitivity, - optional FormatSensitivity formatSensitivity) -{ - local int i; - local Character char1, char2; - if (otherText == none) { - return false; - } - if (GetLength() < otherText.GetLength()) { - return false; - } - for (i = 0; i < otherText.GetLength(); i += 1) - { - char1 = GetCharacter(i); - char2 = otherText.GetCharacter(i); - if ( NormalizeCodePoint(char1.codePoint, caseSensitivity) - != NormalizeCodePoint(char2.codePoint, caseSensitivity)) { - return false; - } - if ( formatSensitivity == SFORM_SENSITIVE - && !_.text.IsFormattingEqual(char1.formatting, char2.formatting)) { - return false; - } - } - return true; -} - -/** - * Method for checking if the caller ends with another `Text` object. - * - * This method supports comparison both sensitive and not sensitive to - * the case and difference in formatting (color of the characters). - * By default comparison is case-sensitive, but ignores - * formatting information. - * - * @param otherText `Text` that caller is checked to end with. - * @param caseSensitivity Defines whether comparison should be - * case-sensitive. By default it is. - * @param formatSensitivity Defines whether comparison should be - * sensitive for color information. By default it is not. - * @return `true` if the caller `Text` ends with `otherText` under - * specified parameters and `false` otherwise. - */ -public final function bool EndsWith( - Text otherText, - optional CaseSensitivity caseSensitivity, - optional FormatSensitivity formatSensitivity) -{ - local int index, otherIndex; - local Character char1, char2; - if (otherText == none) { - return false; - } - if (GetLength() < otherText.GetLength()) { - return false; - } - index = GetLength() - 1; - otherIndex = otherText.GetLength() - 1; - while (otherIndex >= 0) - { - char1 = GetCharacter(index); - char2 = otherText.GetCharacter(otherIndex); - if ( NormalizeCodePoint(char1.codePoint, caseSensitivity) - != NormalizeCodePoint(char2.codePoint, caseSensitivity)) { - return false; - } - if ( formatSensitivity == SFORM_SENSITIVE - && !_.text.IsFormattingEqual(char1.formatting, char2.formatting)) { - return false; - } - index -= 1; - otherIndex -= 1; - } - return true; -} - -// Helper method for comparing formatting data of the caller `Text` -// and `otherText`. -private final function bool CompareFormatting(Text otherText) -{ - local int i; - local array rightChunks; - local TextAPI api; - rightChunks = otherText.formattingChunks; - if (formattingChunks.length != rightChunks.length) { - return false; - } - api = _.text; - for (i = 0; i < formattingChunks.length; i += 1) - { - if (formattingChunks[i].startIndex != rightChunks[i].startIndex) { - return false; - } - if (!api.IsFormattingEqual( formattingChunks[i].formatting, - rightChunks[i].formatting)) - { - return false; - } - } - return true; -} - -/** - * Method for checking equality between the caller `Text` and - * a (plain) `string`. - * - * This method supports comparison both sensitive and not sensitive to - * the case and difference in formatting (color of the characters). - * By default comparison is case-sensitive, but ignores - * formatting information. - * - * @param otherText Plain `string` to compare caller `Text` to. - * @param caseSensitivity Defines whether comparison should be - * case-sensitive. By default it is. - * @param formatSensitivity Defines whether comparison should be - * sensitive for color information. By default it is not. - * @return `true` if the caller `Text` is equal to the `stringToCompare` under - * specified parameters and `false` otherwise. - */ -public final function bool CompareToString( - string stringToCompare, - optional CaseSensitivity caseSensitivity, - optional FormatSensitivity formatSensitivity) -{ - local MutableText builder; - local bool result; - builder = MutableText(_.memory.Allocate(class'MutableText')); - builder.AppendString(stringToCompare); - result = Compare(builder, caseSensitivity, formatSensitivity); - builder.FreeSelf(); - return result; -} - -/** - * Method for checking equality between the caller `Text` and - * a (colored) `string`. - * - * This method supports comparison both sensitive and not sensitive to - * the case and difference in formatting (color of the characters). - * By default comparison is case-sensitive, but ignores - * formatting information. - * - * @param otherText Colored `string` to compare caller `Text` to. - * @param caseSensitivity Defines whether comparison should be - * case-sensitive. By default it is. - * @param formatSensitivity Defines whether comparison should be - * sensitive for color information. By default it is not. - * @return `true` if the caller `Text` is equal to the `stringToCompare` under - * specified parameters and `false` otherwise. - */ -public final function bool CompareToColoredString( - string stringToCompare, - optional CaseSensitivity caseSensitivity, - optional FormatSensitivity formatSensitivity) -{ - local MutableText builder; - local bool result; - builder = MutableText(_.memory.Allocate(class'MutableText')); - builder.AppendColoredString(stringToCompare); - result = Compare(builder, caseSensitivity, formatSensitivity); - builder.FreeSelf(); - return result; -} - -/** - * Method for checking equality between the caller `Text` and - * a (formatted) `string`. - * - * This method supports comparison both sensitive and not sensitive to - * the case and difference in formatting (color of the characters). - * By default comparison is case-sensitive, but ignores - * formatting information. - * - * @param otherText Formatted `string` to compare caller `Text` to. - * @param caseSensitivity Defines whether comparison should be - * case-sensitive. By default it is. - * @param formatSensitivity Defines whether comparison should be - * sensitive for color information. By default it is not. - * @return `true` if the caller `Text` is equal to the `stringToCompare` under - * specified parameters and `false` otherwise. - */ -public final function bool CompareToFormattedString( - string stringToCompare, - optional CaseSensitivity caseSensitivity, - optional FormatSensitivity formatSensitivity) -{ - local MutableText builder; - local bool result; - builder = MutableText(_.memory.Allocate(class'MutableText')); - builder.AppendFormattedString(stringToCompare); - result = Compare(builder, caseSensitivity, formatSensitivity); - builder.FreeSelf(); - return result; -} - -/** - * Returns character at position given by `position`. - * - * Character is returned along with it's color information. - * - * If you do not care about color, you might want to use - * `GetRawCharacter()` method that's slightly faster. - * - * Does some optimizations to speed up lookup of the characters, - * when they are looked up in order of increasing `position`. - * - * @param position Position of the character to return. - * First character is at `0`. - * @return Character at required position. If `position` was out of bounds - * (`< 0` or `>= self.GetLength()`), returns invalid character instead. - */ -public final function Character GetCharacter(int position) -{ - local Character result; - if (position < 0) return _.text.GetInvalidCharacter(); - if (position >= codePoints.length) return _.text.GetInvalidCharacter(); - - result.codePoint = codePoints[position]; - result.formatting = GetFormatting(position); - return result; -} - -/** - * Returns character at position given by `position`. - * - * Character is returned without it's color information - * (guaranteed to have `.formatting.isColored == false`). - * - * Unlike `GetCharacter()` does not optimizations. - * - * @param position Position of the character to return. - * First character is at `0`. - * @return Character at required position, without any color information. - * If `position` was out of bounds (`< 0` or `>= self.GetLength()`), - * returns invalid character instead. - */ -public final function Character GetRawCharacter(int position) -{ - local Character result; - if (position < 0) return _.text.GetInvalidCharacter(); - if (position >= codePoints.length) return _.text.GetInvalidCharacter(); - - result.codePoint = codePoints[position]; - return result; -} - -/** - * Appends new code point to the `Text`'s data. - * Allows to create mutable child classes. - * - * Formatting of this code point needs to be set beforehand by - * `SetFormatting()` method. - * - * @param codePoint Code point to append, does nothing for - * invalid (`< 1`) code points. - * @return Returns caller `Text`, to allow for method chaining. - */ -protected final function Text AppendCodePoint(int codePoint) -{ - local FormattingChunk newChunk; - codePoints[codePoints.length] = codePoint; - if (formattingUpdated) - { - newChunk.startIndex = codePoints.length - 1; - newChunk.formatting = nextFormatting; - formattingChunks[formattingChunks.length] = newChunk; - formattingUpdated = false; - } - return self; -} - -/** - * Appends several new code points to the `Text`'s data. - * Convenience method over existing `AppendCodePoint()`. - * - * Formatting of these code points needs to be set beforehand by - * `SetFormatting()` method. - * - * @return Returns caller `Text`, to allow for method chaining. - */ -protected final function Text AppendManyCodePoints(array codePoints) -{ - local int i; - for (i = 0; i < codePoints.length; i += 1) { - AppendCodePoint(codePoints[i]); - } - return self; -} - -/** - * Drops all of the code points in the caller `Text`. - * Allows to easier create mutable child classes. - * - * @return Returns caller `Text`, to allow for method chaining. - */ -protected final function Text DropCodePoints() { - codePoints.length = 0; - formattingChunks.length = 0; - return self; -} - -/** - * Sets `newFormatting` for every non-formatted character in the caller `Text`. - * Allows to create mutable child classes. - * - * @param newFormatting Formatting to use for all non-formatted character in - * the caller `Text`. If `newFormatting` is not colored itself - - * method does nothing. - * @return Returns caller `Text`, to allow for method chaining. - */ -protected final function Text _changeDefaultFormatting(Formatting newFormatting) -{ - local int i; - local FormattingChunk newFormattingChunk; - local array newFormattingChunks; - if (!newFormatting.isColored) { - return self; - } - newFormattingChunk.formatting = newFormatting; - if ( formattingChunks.length <= 0 - || formattingChunks[0].startIndex > 0) - { - newFormattingChunks[0] = newFormattingChunk; - } - while (i < formattingChunks.length) - { - if (formattingChunks[i].formatting.isColored) - { - newFormattingChunks[newFormattingChunks.length] = - formattingChunks[i]; - } - else - { - newFormattingChunk.startIndex = formattingChunks[i].startIndex; - newFormattingChunks[newFormattingChunks.length] = - newFormattingChunk; - } - i += 1; - } - formattingChunks = newFormattingChunks; - NormalizeFormatting(); return self; } -/** - * Sets formatting for the next code point(s) to be added by - * `AppendCodePoint()` / `AppendManyCodePoints()`. - * Allows to create mutable child classes. - * - * Formatting is not reset by `Append...` calls, i.e. if you are adding - * several code points with the same formatting in a row, you only need to - * call `SetFormatting()` once. - * - * @param newFormatting Formatting to use for next code points, - * added via `AppendCodePoint()` / `AppendManyCodePoints()` methods. - * @return Returns caller `Text`, to allow for method chaining. - */ -protected final function Text SetFormatting(optional Formatting newFormatting) -{ - local Formatting lastFormatting; - nextFormatting = newFormatting; - if (formattingChunks.length > 0) - { - lastFormatting = - formattingChunks[formattingChunks.length - 1].formatting; - } - formattingUpdated = !_.text.IsFormattingEqual( lastFormatting, - nextFormatting); - return self; -} - -/** - * Checks whether formatting has changed at character at position `position` - * (different from formatting of a character before it). - * - * Helps to compose `string`s from caller `Text`. - * - * If this method is called for the first character (`position == 0`), - * then method checks whether that character has any formatting setup - * (has a defined color). - * - * @param position Position of the character to check. Starts from `0`. - * @return `true` if formatting of specified character is different from - * the previous one (for the first character - if it has a defined color). - * `false` if formatting is the same or specified `position` is - * out-of-bounds (`< 0` or `>= self.GetLength()`) - */ -protected final function bool IsFormattingChangedAt(int position) -{ - local int i; - UpdateFormattingCacheFor(position); - for (i = formattingIndexCache; i < formattingChunks.length; i += 1) - { - if (formattingChunks[i].startIndex > position) { - return false; - } - if (formattingChunks[i].startIndex == position) { - return true; - } - } - return false; -} - -/** - * Returns formatting information of character at position `position`. - * - * Does some optimizations to speed up lookup of the formatting, - * when they are looked up in order of increasing `position`. - * - * @param position Position of the character to get formatting for. - * Starts from `0`. - * @return Formatting of requested character. Default formatting with - * undefined color, if `position is out-of-bounds - * (`< 0` or `>= self.GetLength()`). - */ -public final function Formatting GetFormatting(int position) -{ - local int i; - local Formatting result; - UpdateFormattingCacheFor(position); - for (i = formattingIndexCache; i < formattingChunks.length; i += 1) - { - if (formattingChunks[i].startIndex > position) { - break; - } - } - i -= 1; - if (i < 0) { - return result; - } - return formattingChunks[i].formatting; -} - -// Verifies that current `formattingIndexCache` can be used as a starting -// position to look up for formatting of symbol at `index`. -// If it cannot - resets it to zero. -private final function UpdateFormattingCacheFor(int index) -{ - if ( formattingIndexCache < 0 - || formattingIndexCache >= formattingChunks.length) { - formattingIndexCache = 0; - return; - } - if (formattingChunks[formattingIndexCache].startIndex > index) { - formattingIndexCache = 0; - } -} - -// Removes possible unnecessary chunks from `formattingChunks`: -// if there is a chunk that tells us to have red color after index `3` and -// next one tells us to have red color after index `5` - the second chunk is -// unnecessary. -private final function NormalizeFormatting() -{ - local int i; - while (i < formattingChunks.length - 1) - { - if (_.text.IsFormattingEqual( formattingChunks[i].formatting, - formattingChunks[i + 1].formatting)) - { - formattingChunks.Remove(i + 1, 1); - } - else { - i += 1; - } - } -} - -/** - * Converts data from the caller `Text` instance into a plain `string`. - * Can be used to extract only substrings. - * - * If provided parameters `startIndex` and `maxLength` define a range that - * goes beyond `[0; self.GetLength() - 1]`, then intersection with a valid - * range will be used. - * - * @param startIndex Position of the first symbol to extract into a - * plain `string`. By default `0`, corresponding to the first symbol. - * @param maxLength Max length of the extracted string. By default `0`, - * - that and all negative values are replaces by `MaxInt`, - * effectively extracting as much of a `string` as possible. - * @return Plain `string` representation of the caller `Text`, - * i.e. `string` without any color information inside. - */ -public final function string ToString( - optional int startIndex, - optional int maxLength) +public function MutableText IntoMutableText() { - local int i; - local string result; - if (maxLength <= 0) { - maxLength = MaxInt; - } - else if (startIndex < 0) { - maxLength += startIndex; - } - startIndex = Max(0, startIndex); - for (i = startIndex; i < codePoints.length; i += 1) - { - if (maxLength <= 0) { - break; - } - maxLength -= 1; - result $= Chr(codePoints[i]); - } - return result; -} - -/** - * Converts data from the caller `Text` instance into a colored `string`. - * Can be used to extract only substrings. - * - * Guaranteed to add a color tag (possibly of `defaultColor`parameter) - * at the beginning of the returned `string`. - * - * If provided parameters `startIndex` and `maxLength` define a range that - * goes beyond `[0; self.GetLength() - 1]`, then intersection with a valid - * range will be used. - * - * @param startIndex Position of the first symbol to extract into a - * colored `string`. By default `0`, corresponding to the first symbol. - * @param maxLength Max length of the extracted string. By default `0`, - * - that and all negative values are replaces by `MaxInt`, - * effectively extracting as much of a `string` as possible. - * NOTE: this parameter only counts actual visible symbols, ignoring - * 4-byte color code sequences, so method `Len()`, applied to - * the result of `ToColoredString()`, will return a bigger value - * than `maxLength`. - * @param defaultColor Color to be applied to the parts of the string that - * do not have any specified color. - * This is necessary, since 4-byte color sequences cannot unset the color. - * @return Colored `string` representation of the caller `Text`, - * i.e. `string` without any color information inside. - */ -public final function string ToColoredString( - optional int startIndex, - optional int maxLength, - optional Color defaultColor) -{ - local int i; - local Formatting newFormatting; - local Color nextColor, appliedColor; - local string result; - if (maxLength <= 0) { - maxLength = MaxInt; - } - else if (startIndex < 0) { - maxLength += startIndex; - } - startIndex = Max(0, startIndex); - // `appliedColor` will contain perfect black and so, - // guaranteed to be different from any actually used color - defaultColor = _.color.FixColor(defaultColor); - for (i = startIndex; i < codePoints.length; i += 1) - { - if (maxLength <= 0) { - break; - } - maxLength -= 1; - if (IsFormattingChangedAt(i) || i == startIndex) - { - newFormatting = GetFormatting(i); - if (newFormatting.isColored) { - nextColor = _.color.FixColor(newFormatting.color); - } - else { - nextColor = defaultColor; - } - // Colors are already fixed (and will be different from - // `appliedColor` before we initialize it) - if (!_.color.AreEqual(nextColor, appliedColor)) - { - result $= Chr(CODEPOINT_ESCAPE); - result $= Chr(nextColor.r); - result $= Chr(nextColor.g); - result $= Chr(nextColor.b); - appliedColor = nextColor; - } - } - result $= Chr(codePoints[i]); - } - return result; -} - -/** - * Converts data from the caller `Text` instance into a formatted `string`. - * Can be used to extract only substrings. - * - * If provided parameters `startIndex` and `maxLength` define a range that - * goes beyond `[0; self.GetLength() - 1]`, then intersection with a valid - * range will be used. - * - * @param startIndex Position of the first symbol to extract into a - * formatted `string`. By default `0`, corresponding to the first symbol. - * @param maxLength Max length of the extracted `string`. - * By default `0` - that and all negative values are replaces by `MaxInt`, - * effectively extracting as much of a `string` as possible. - * NOTE: this parameter only counts actual visible symbols, - * ignoring formatting blocks ('{ }') - * or escape sequences (i.e. '&{' is one character), - * so method `Len()`, applied to the result of - * `ToFormattedString()`, will return a bigger value - * than `maxLength`. - * @return Formatted `string` representation of the caller `Text`, - * i.e. `string` without any color information inside. - */ -public final function string ToFormattedString( - optional int startIndex, - optional int maxLength) -{ - local int i; - local bool isInsideBlock; - local string result; - local Formatting newFormatting; - if (maxLength <= 0) { - maxLength = MaxInt; - } - else if (startIndex < 0) { - maxLength += startIndex; - } - startIndex = Max(0, startIndex); - for (i = startIndex; i < codePoints.length; i += 1) - { - if (maxLength <= 0) { - break; - } - maxLength -= 1; - if (IsFormattingChangedAt(i) || i == startIndex) - { - newFormatting = GetFormatting(i); - if (isInsideBlock && i != startIndex) { - result $= STRING_CLOSE_FORMAT; - isInsideBlock = false; - } - if (newFormatting.isColored) { - result $= STRING_OPEN_FORMAT - $ _.color.ToString(newFormatting.color) - $ STRING_SEPARATOR_FORMAT; - isInsideBlock = true; - } - } - if ( codePoints[i] == CODEPOINT_OPEN_FORMAT - || codePoints[i] == CODEPOINT_CLOSE_FORMAT) { - result $= STRING_FORMAT_ESCAPE; - } - result $= Chr(codePoints[i]); - } - if (isInsideBlock) { - result $= STRING_CLOSE_FORMAT; - } - return result; -} - -/** - * Splits the string into substrings wherever `separator` occurs, and returns - * array of those strings. - * - * If `separator` does not match anywhere in the string, method returns a - * single-element array containing copy of this `Text`. - * - * @param separator Character that separates different parts of this `Text`. - * @param skipEmpty Set this to `true` to filter out empty `MutableText`s - * from the output. - * @return Array of `MutableText`s that contain separated substrings. - */ -public final function array SplitByCharacter( - Character separator, - optional bool skipEmpty) -{ - local int i, length; - local Character nextCharacter; - local MutableText nextText; - local array result; - length = GetLength(); - nextText = _.text.Empty(); - i = 0; - while (i < length) - { - nextCharacter = GetCharacter(i); - if (_.text.AreEqual(separator, nextCharacter)) - { - if (!skipEmpty || !nextText.IsEmpty()) { - result[result.length] = nextText; - } - else { - _.memory.Free(nextText); - } - nextText = _.text.Empty(); - } - else { - nextText.AppendCharacter(nextCharacter); - } - i += 1; - } - if (!skipEmpty || !nextText.IsEmpty()) { - result[result.length] = nextText; - } - return result; -} - -/** - * Returns the index position of the first occurrence of the `otherText` in - * the caller `Text`, searching forward from index position `fromIndex`. - * - * @param otherText `Text` data to find inside the caller `Text`. - * @param fromIndex Index from which we should start searching. - * @param caseSensitivity Defines whether comparison should be - * case-sensitive. By default it is. - * @param formatSensitivity Defines whether comparison should be - * sensitive for color information. By default it is not. - * @return `-1` if `otherText` is not found after `fromIndex`. - */ -public final function int IndexOf( - Text otherText, - optional int fromIndex, - optional CaseSensitivity caseSensitivity, - optional FormatSensitivity formatSensitivity) -{ - local int startCandidate; - local int index, otherIndex; - local Character char1, char2; - if (otherText == none) return -1; - if (fromIndex > GetLength()) return -1; - if (GetLength() - fromIndex < otherText.GetLength()) return -1; - if (otherText.IsEmpty()) return fromIndex; - - startCandidate = fromIndex; - for (index = fromIndex; index < GetLength(); index += 1) - { - char1 = GetCharacter(index); - char2 = otherText.GetCharacter(otherIndex); - if ( NormalizeCodePoint(char1.codePoint, caseSensitivity) - != NormalizeCodePoint(char2.codePoint, caseSensitivity)) - { - startCandidate = index + 1; - otherIndex = 0; - continue; - } - if ( formatSensitivity == SFORM_SENSITIVE - && !_.text.IsFormattingEqual(char1.formatting, char2.formatting)) - { - startCandidate = index + 1; - otherIndex = 0; - continue; - } - otherIndex += 1; - if (otherIndex == otherText.GetLength()) { - return startCandidate; - } - } - return -1; -} - -/** - * Returns the index position of the last occurrence of the `otherText` in - * the caller `Text`, searching backward from index position `fromIndex`, - * counted the end of the caller `Text`. - * - * @param otherText `Text` data to find inside the caller `Text`. - * @param fromIndex Index from which we should start searching, but - * it's counted from the end of the caller `Text`: `0` means starting from - * the last character, `1` means next to last, etc. - * @param caseSensitivity Defines whether comparison should be - * case-sensitive. By default it is. - * @param formatSensitivity Defines whether comparison should be - * sensitive for color information. By default it is not. - * @return `-1` if `otherText` is not found starting `fromIndex` - * (this index is counted from the end of the caller `Text`). - */ -public final function int LastIndexOf( - Text otherText, - optional int fromIndex, - optional CaseSensitivity caseSensitivity, - optional FormatSensitivity formatSensitivity) -{ - local int startCandidate; - local int index, otherIndex; - local Character char1, char2; - if (otherText == none) return -1; - if (fromIndex > GetLength()) return -1; - if (GetLength() - fromIndex < otherText.GetLength()) return -1; - if (otherText.IsEmpty()) return fromIndex; - - otherIndex = otherText.GetLength() - 1; - startCandidate = GetLength() - fromIndex - 1; - for (index = startCandidate; index >= 0; index -= 1) - { - char1 = GetCharacter(index); - char2 = otherText.GetCharacter(otherIndex); - if ( NormalizeCodePoint(char1.codePoint, caseSensitivity) - != NormalizeCodePoint(char2.codePoint, caseSensitivity)) - { - startCandidate = index - 1; - otherIndex = otherText.GetLength() - 1; - continue; - } - if ( formatSensitivity == SFORM_SENSITIVE - && !_.text.IsFormattingEqual(char1.formatting, char2.formatting)) - { - startCandidate = index - 1; - otherIndex = otherText.GetLength() - 1; - continue; - } - otherIndex -= 1; - if (otherIndex < 0) { - return startCandidate - (otherText.GetLength() - 1); - } - } - return -1; + local MutableText mutableVersion; + mutableVersion = MutableCopy(); + FreeSelf(); + return mutableVersion; } defaultproperties { - STRING_SEPARATOR_FORMAT = " " - STRING_OPEN_FORMAT = "{" - STRING_CLOSE_FORMAT = "}" - STRING_FORMAT_ESCAPE = "&" - CODEPOINT_ESCAPE = 27 // ASCII escape code - CODEPOINT_OPEN_FORMAT = 123 // '{' - CODEPOINT_CLOSE_FORMAT = 125 // '}' - CODEPOINT_FORMAT_ESCAPE = 38 // '&' } \ No newline at end of file diff --git a/sources/Text/TextAPI.uc b/sources/Text/TextAPI.uc index ea01acf..0fc75da 100644 --- a/sources/Text/TextAPI.uc +++ b/sources/Text/TextAPI.uc @@ -1,6 +1,6 @@ /** * API that provides functions for working with characters and for creating - * `Text` and `Parser` instances. + * `Text`, `MutableText` and `Parser` instances. * Copyright 2020 - 2022 Anton Tarasenko *------------------------------------------------------------------------------ * This file is part of Acedia. @@ -19,7 +19,7 @@ * along with Acedia. If not, see . */ class TextAPI extends AcediaObject - dependson(Text); + dependson(BaseText); /** * Creates a new `Formatting` structure that defines a default, @@ -29,9 +29,9 @@ class TextAPI extends AcediaObject * * @return Empty formatting object. */ -public final function Text.Formatting EmptyFormatting() +public final function BaseText.Formatting EmptyFormatting() { - local Text.Formatting emptyFormatting; + local BaseText.Formatting emptyFormatting; return emptyFormatting; } @@ -43,9 +43,9 @@ public final function Text.Formatting EmptyFormatting() * @param color Color that formatting must have. * @return Formatting object that describes text colored with `color`. */ -public final function Text.Formatting FormattingFromColor(Color color) +public final function BaseText.Formatting FormattingFromColor(Color color) { - local Text.Formatting coloredFormatting; + local BaseText.Formatting coloredFormatting; coloredFormatting.isColored = true; coloredFormatting.color = color; return coloredFormatting; @@ -62,8 +62,8 @@ public final function Text.Formatting FormattingFromColor(Color color) * @return `true` if formattings are equal and `false` otherwise. */ public final function bool IsFormattingEqual( - Text.Formatting formatting1, - Text.Formatting formatting2) + BaseText.Formatting formatting1, + BaseText.Formatting formatting2) { if (formatting1.isColored != formatting2.isColored) { return false; @@ -85,7 +85,7 @@ public final function bool IsFormattingEqual( * @param character Character to test for lower case. * @return `true` if given character is lower case. */ -public final function bool IsLower(Text.Character character) +public final function bool IsLower(BaseText.Character character) { // Small Latin letters if (character.codePoint >= 97 && character.codePoint <= 122) { @@ -113,7 +113,7 @@ public final function bool IsLower(Text.Character character) * @param character Character to test for upper case. * @return `true` if given character is upper case. */ -public final function bool IsUpper(Text.Character character) +public final function bool IsUpper(BaseText.Character character) { // Capital Latin letters if (character.codePoint >= 65 && character.codePoint <= 90) { @@ -136,7 +136,7 @@ public final function bool IsUpper(Text.Character character) * @param codePoint Unicode code point to check for being a digit. * @return `true` if given Unicode code point is a digit, `false` otherwise. */ -public final function bool IsDigit(Text.Character character) +public final function bool IsDigit(BaseText.Character character) { if (character.codePoint >= 48 && character.codePoint <= 57) { return true; @@ -152,7 +152,7 @@ public final function bool IsDigit(Text.Character character) * @return `true` if given Unicode code point belongs to a latin alphabet, * `false` otherwise. */ -public final function bool IsAlpha(Text.Character character) +public final function bool IsAlpha(BaseText.Character character) { // Capital Latin letters if (character.codePoint >= 65 && character.codePoint <= 90) { @@ -171,7 +171,7 @@ public final function bool IsAlpha(Text.Character character) * @param character Character to check for being from ASCII. * @return `true` if given character is a digit, `false` otherwise. */ -public final function bool IsASCII(Text.Character character) +public final function bool IsASCII(BaseText.Character character) { if (character.codePoint >= 0 && character.codePoint <= 127) { return true; @@ -189,7 +189,7 @@ public final function bool IsASCII(Text.Character character) * @param character Character to check for being a whitespace. * @return `true` if given character is a whitespace, `false` otherwise. */ -public final function bool IsWhitespace(Text.Character character) +public final function bool IsWhitespace(BaseText.Character character) { switch (character.codePoint) { @@ -232,7 +232,7 @@ public final function bool IsWhitespace(Text.Character character) * @return `true` if given Unicode code point denotes one of the recognized * quote symbols, `false` otherwise. */ -public final function bool IsQuotationMark(Text.Character character) +public final function bool IsQuotationMark(BaseText.Character character) { if (character.codePoint == 0x0022) return true; if (character.codePoint == 0x0027) return true; @@ -252,11 +252,11 @@ public final function bool IsQuotationMark(Text.Character character) * `formatting`. */ // TODO: Validity checks fro non-negative input code points -public final function Text.Character CharacterFromCodePoint( - int codePoint, - optional Text.Formatting formatting) +public final function BaseText.Character CharacterFromCodePoint( + int codePoint, + optional BaseText.Formatting formatting) { - local Text.Character result; + local BaseText.Character result; result.codePoint = codePoint; result.formatting = formatting; return result; @@ -266,7 +266,7 @@ public final function Text.Character CharacterFromCodePoint( * Extracts a character at position `position` from a given plain `string`. * * For extracting multiple character or character from colored/formatted - * `string` we advice to convert `string` into `Text` instead. + * `string` we advice to convert `string` into `BaseText` instead. * * @param source `string`, from which to extract the character. * @param position Position of the character to extract, starts from `0`. @@ -274,11 +274,11 @@ public final function Text.Character CharacterFromCodePoint( * If specified position is invalid (`< 0` or `>= Len(source)`), * returns invalid character. */ -public final function Text.Character GetCharacter( +public final function BaseText.Character GetCharacter( string source, optional int position) { - local Text.Character result; + local BaseText.Character result; if (position < 0) return GetInvalidCharacter(); if (position >= Len(source)) return GetInvalidCharacter(); @@ -287,34 +287,34 @@ public final function Text.Character GetCharacter( } /** - * Auxiliary method for checking whether `Text` object defines an "empty" + * Auxiliary method for checking whether `BaseText` object defines an "empty" * `string`. That is, if it's either `none` or has empty contents. * * It is added, since it allows to replace two common checks * `text == none || text.IsEmpty()` with a nicer looking one: * `_.text.IsEmpty(text)`. * - * @param text `Text` to check for emptiness. + * @param text `BaseText` to check for emptiness. * @return `true` iff either passed `text == none` or `text.IsEmpty()`. */ -public final function bool IsEmpty(Text text) +public final function bool IsEmpty(BaseText text) { return (text == none || text.IsEmpty()); } /** - * Converts given `Text` into a plain `string`, returns it's value and - * deallocates passed `Text`. + * Converts given `BaseText` into a plain `string`, returns it's value and + * deallocates passed `BaseText`. * * Method introduced to simplify a common use-case of converting returned copy - * of `Text` into a `string`, which required additional variable to store and - * later deallocate `Text` reference. + * of `BaseText` into a `string`, which required additional variable to store + * and later deallocate `BaseText` reference. * - * @param toConvert `Text` to convert. - * @return `string` representation of passed `Text` as a plain `string`. + * @param toConvert `BaseText` to convert. + * @return `string` representation of passed `BaseText` as a plain string. * Empty `string`, if `toConvert == none`. */ -public final function string ToString(Text toConvert) +public final function string ToString(/*take*/ BaseText toConvert) { local string result; if (toConvert != none) { @@ -325,18 +325,18 @@ public final function string ToString(Text toConvert) } /** - * Converts given `Text` into a colored `string`, returns it's value and - * deallocates passed `Text`. + * Converts given `BaseText` into a colored `string`, returns it's value and + * deallocates passed `BaseText`. * * Method introduced to simplify a common use-case of converting returned copy - * of `Text` into a `string`, which required additional variable to store and - * later deallocate `Text` reference. + * of `BaseText` into a `string`, which required additional variable to store + * and later deallocate `BaseText` reference. * - * @param toConvert `Text` to convert. - * @return `string` representation of passed `Text` as a colored `string`. + * @param toConvert `BaseText` to convert. + * @return `string` representation of passed `BaseText` as a colored `string`. * Empty `string`, if `toConvert == none`. */ -public final function string ToColoredString(Text toConvert) +public final function string ToColoredString(/*take*/ Text toConvert) { local string result; if (toConvert != none) { @@ -347,18 +347,18 @@ public final function string ToColoredString(Text toConvert) } /** - * Converts given `Text` into a formatted `string`, returns it's value and - * deallocates passed `Text`. + * Converts given `BaseText` into a formatted `string`, returns it's value and + * deallocates passed `BaseText`. * * Method introduced to simplify a common use-case of converting returned copy - * of `Text` into a `string`, which required additional variable to store and - * later deallocate `Text` reference. + * of `BaseText` into a `string`, which required additional variable to store + * and later deallocate `BaseText` reference. * - * @param toConvert `Text` to convert. - * @return `string` representation of passed `Text` as a formatted `string`. + * @param toConvert `BaseText` to convert. + * @return `string` representation of passed `BaseText` as a formatted `string`. * Empty `string`, if `toConvert == none`. */ -public final function string ToFormattedString(Text toConvert) +public final function string ToFormattedString(/*take*/ BaseText toConvert) { local string result; if (toConvert != none) { @@ -375,7 +375,7 @@ public final function string ToFormattedString(Text toConvert) * @return `string` that consists only of a given character, * if given character is valid. Empty `string` otherwise. */ -public final function string CharacterToString(Text.Character character) +public final function string CharacterToString(BaseText.Character character) { if (!IsValidCharacter(character)) { return ""; @@ -404,7 +404,7 @@ public final function string CharacterToString(Text.Character character) * `-1` if given character does not represent anything in the given base. */ public final function int CharacterToInt( - Text.Character character, + BaseText.Character character, optional int base ) { @@ -439,7 +439,9 @@ public final function int CharacterToInt( * @return `true` if given character can be represented by a given code point * and `false` otherwise. */ -public final function bool IsCodePoint(Text.Character character, int codePoint) +public final function bool IsCodePoint( + BaseText.Character character, + int codePoint) { return (character.codePoint == codePoint); } @@ -451,10 +453,10 @@ public final function bool IsCodePoint(Text.Character character, int codePoint) * @return Returns formatting of the given character. * Always returns 'null' (not colored) formatting for invalid characters. */ -public final function Text.Formatting GetCharacterFormatting( - Text.Character character) +public final function BaseText.Formatting GetCharacterFormatting( + BaseText.Character character) { - local Text.Formatting emptyFormatting; + local BaseText.Formatting emptyFormatting; if(IsValidCharacter(character)) { return character.formatting; } @@ -469,9 +471,9 @@ public final function Text.Formatting GetCharacterFormatting( * @return Same character as `character`, but with new formatting. * Invalid characters are not altered. */ -public final function Text.Character SetFormatting( - Text.Character character, - Text.Formatting newFormatting) +public final function BaseText.Character SetFormatting( + BaseText.Character character, + BaseText.Formatting newFormatting) { if(!IsValidCharacter(character)) { return character; @@ -492,8 +494,8 @@ public final function Text.Character SetFormatting( * `defaultColor`. */ public final function Color GetCharacterColor( - Text.Character character, - optional Color defaultColor) + BaseText.Character character, + optional Color defaultColor) { if (character.formatting.isColored) { return character.formatting.color; @@ -508,9 +510,9 @@ public final function Color GetCharacterColor( * * @return Invalid character instance. */ -public final function Text.Character GetInvalidCharacter() +public final function BaseText.Character GetInvalidCharacter() { - local Text.Character result; + local BaseText.Character result; result.codePoint = -1; return result; } @@ -521,7 +523,7 @@ public final function Text.Character GetInvalidCharacter() * @param character Character to check. * @return `true` if passed character is valid and `false` otherwise. */ -public final function bool IsValidCharacter(Text.Character character) +public final function bool IsValidCharacter(BaseText.Character character) { return (character.codePoint >= 0); } @@ -548,10 +550,10 @@ public final function bool IsValidCharacter(Text.Character character) * `false` otherwise. */ public final function bool AreEqual( - Text.Character character1, - Text.Character character2, - optional Text.CaseSensitivity caseSensitivity, - optional Text.FormatSensitivity formatSensitivity + BaseText.Character character1, + BaseText.Character character2, + optional BaseText.CaseSensitivity caseSensitivity, + optional BaseText.FormatSensitivity formatSensitivity ) { // These handle checks with invalid characters @@ -572,7 +574,7 @@ public final function bool AreEqual( } /** - * Converts Unicode code point into it's lower case folding, + * Converts Unicode code point into its lower case folding, * as defined by Unicode standard. * * @param codePoint Code point to convert into lower case. @@ -580,7 +582,7 @@ public final function bool AreEqual( * not define any lower case folding (like "&" or "!") for given code point, - * function returns given code point unchanged. */ -public final function Text.Character ToLower(Text.Character character) +public final function BaseText.Character ToLower(BaseText.Character character) { local int newCodePoint; newCodePoint = @@ -600,7 +602,7 @@ public final function Text.Character ToLower(Text.Character character) * not define any upper case version (like "&" or "!") for given code point, - * function returns given code point unchanged. */ -public final function Text.Character ToUpper(Text.Character character) +public final function BaseText.Character ToUpper(BaseText.Character character) { local int newCodePoint; newCodePoint = @@ -612,21 +614,21 @@ public final function Text.Character ToUpper(Text.Character character) } /** - * Prepares an array of parts from a given single `Text`. + * Prepares an array of parts from a given single `BaseText`. * First character is treated as a separator with which the rest of - * the given `Text` is split into parts: + * the given `BaseText` is split into parts: * ~ "/ab/c/d" => ["ab", "c", "d"] * ~ "zWordzomgzz" => ["Word", "omg", "", ""] * * This method is useful to easily prepare array of words for `Parser`'s * methods. * - * @param source `Text` that contains separator with parts to + * @param source `BaseText` that contains separator with parts to * separate and extract. * @return Separated words. Empty array if passed `source` was empty, * otherwise contains at least one element. */ -public final function array Parts(Text source) +public final function array Parts(BaseText source) { local array result; if (source == none) return result; @@ -757,16 +759,17 @@ public final function Parser NewParser() } /** - * Method for creating a new parser, initialized with contents of given `Text`. + * Method for creating a new parser, initialized with contents of given + * `BaseText`. * * @param source Returned `Parser` will be setup to parse the contents of - * the passed `Text`. + * the passed `BaseText`. * If `none` value is passed, - parser won't be initialized. * @return Guaranteed to be not `none` and contain a valid `Parser`. * If passed argument also is not `none`, - guaranteed to be * initialized with it's content. */ -public final function Parser Parse(Text source) +public final function Parser Parse(BaseText source) { local Parser parser; parser = NewParser(); @@ -798,7 +801,7 @@ public final function Parser ParseString(string source) * if given character is valid. Empty `Text` otherwise. * Guaranteed to be not `none`. */ -public final function Text FromCharacter(Text.Character character) +public final function Text FromCharacter(BaseText.Character character) { return _.text.FromString(CharacterToString(character)); } diff --git a/sources/Users/User.uc b/sources/Users/User.uc index 765f721..2d1ccf2 100644 --- a/sources/Users/User.uc +++ b/sources/Users/User.uc @@ -88,8 +88,8 @@ public final function int GetKey() * `_.users.PersistentStorageExists() == true`. */ public final function DBReadTask ReadPersistentData( - Text groupName, - Text dataName) + BaseText groupName, + BaseText dataName) { local DBReadTask task; if (groupName == none) return none; @@ -123,8 +123,8 @@ public final function DBReadTask ReadPersistentData( * `_.users.PersistentStorageExists() == true`. */ public final function DBWriteTask WritePersistentData( - Text groupName, - Text dataName, + BaseText groupName, + BaseText dataName, AcediaObject data) { local DBWriteTask task; diff --git a/sources/Users/UserAPI.uc b/sources/Users/UserAPI.uc index 3d18e49..5deb01e 100644 --- a/sources/Users/UserAPI.uc +++ b/sources/Users/UserAPI.uc @@ -53,7 +53,7 @@ public final function User Fetch(UserID userID) * @return Corresponding `User` object. Guaranteed to be a valid non-`none` * reference. */ -public final function User FetchByIDHash(Text idHash) +public final function User FetchByIDHash(BaseText idHash) { local UserID userID; local UserDatabase userDB; diff --git a/sources/Users/UserDatabase.uc b/sources/Users/UserDatabase.uc index 1088a10..eee877a 100644 --- a/sources/Users/UserDatabase.uc +++ b/sources/Users/UserDatabase.uc @@ -66,7 +66,7 @@ public final static function UserDatabase GetInstance() * correctly initialized with given `idHash` (guaranteed not to happen for * any valid id hashes). */ -public final function UserID FetchUserID(Text idHash) +public final function UserID FetchUserID(BaseText idHash) { local int i; local UserID.SteamID steamID; diff --git a/sources/Users/UserID.uc b/sources/Users/UserID.uc index b39e4dc..7d7ca42 100644 --- a/sources/Users/UserID.uc +++ b/sources/Users/UserID.uc @@ -129,7 +129,7 @@ private final function string GetSteamAccountTypeCharacter() * @param steamID64 Steam64 ID's decimal representation. * @return `SteamID` generated from a given Steam64 ID `steamID64`. */ -public static final function SteamID GetSteamIDFromIDHash(Text steamID64) +public static final function SteamID GetSteamIDFromIDHash(BaseText steamID64) { local int i; local SteamID newSteamID; @@ -170,7 +170,7 @@ public static final function SteamID GetSteamIDFromIDHash(Text steamID64) * (can happen if caller `UserID` was already initialized * or `steamID64 == none`). */ -public final function bool Initialize(Text steamID64) +public final function bool Initialize(BaseText steamID64) { if (initialized) return false; if (steamID64 == none) return false;