You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
290 lines
8.8 KiB
290 lines
8.8 KiB
4 years ago
|
/**
|
||
|
* Text object, meant as Acedia's replacement for a `string` type,
|
||
|
* that is supposed to provide a better (although by no means full)
|
||
|
* Unicode support than what is available from built-in unrealscript functions.
|
||
|
* Main differences with `string` are:
|
||
|
* 1. Text is a reference type, that doesn't copy it's contents with each
|
||
|
* assignment.
|
||
|
* 2. It's functions such as `ToUpper()` work with larger sets of
|
||
|
* symbols than native functions such as `Caps()` that only work with
|
||
|
* ASCII Latin;
|
||
|
* 3. Can store a wider range of characters than `string`, although
|
||
|
* the only way to actually add them to `Text` is via directly
|
||
|
* inputting Unicode code points.
|
||
|
* 4. Since it's functionality implemented in unrealscript,
|
||
|
* Text is slower that a string;
|
||
|
* 5. Once created, Text object won't disappear until garbage collection
|
||
|
* is performed, even if it is not referenced anywhere.
|
||
|
|
||
|
* API that provides extended text handling with extended Cyrillic (Russian)
|
||
|
* support (native functions like `Caps` only work with Latin letters).
|
||
|
* Copyright 2020 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 <https://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
class Text extends AcediaObject;
|
||
|
|
||
|
// Used to store a result of a `ParseSign()` function.
|
||
|
enum StringType
|
||
|
{
|
||
|
STRING_Plain,
|
||
|
STRING_Colored,
|
||
|
STRING_Formatted
|
||
|
};
|
||
|
|
||
|
enum LetterCase
|
||
|
{
|
||
|
LCASE_Lower,
|
||
|
LCASE_Upper
|
||
|
};
|
||
|
|
||
|
enum StringColorType
|
||
|
{
|
||
|
STRCOLOR_Default,
|
||
|
STRCOLOR_Struct,
|
||
|
STRCOLOR_Alias
|
||
|
};
|
||
|
|
||
|
struct Character
|
||
|
{
|
||
|
var int codePoint;
|
||
|
// `false` if relevant character has a particular color,
|
||
|
// `true` if it does not (use context-dependent default color).
|
||
|
var StringColorType colorType;
|
||
|
// Color of the relevant character if `isDefaultColor == false`.
|
||
|
var Color color;
|
||
|
var string colorAlias;
|
||
|
};
|
||
|
// We will store our string data in two different ways at once to make getters
|
||
|
// faster at the cost of doing more work in functions that change the string.
|
||
|
var private array<Character> contents;
|
||
|
|
||
|
/**
|
||
|
* Sets new value of the `Text` object, that has called this method,
|
||
|
* to be equal to the given `Text`. Does not change given `Text`.
|
||
|
*
|
||
|
* @param source After this function caller `Text` will have exactly
|
||
|
* the same contents as given parameter.
|
||
|
* @return Returns the calling `Text` object, to allow for function chaining.
|
||
|
*/
|
||
|
public final function Text Copy(Text otherText)
|
||
|
{
|
||
|
contents = otherText.contents;
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Replaces data of caller `Text` object with data given by the array of
|
||
|
* Unicode code points, preserving the order of characters where it matters
|
||
|
* (some modifier code points are allowed arbitrary order in Unicode standard).
|
||
|
*
|
||
|
* `Text` isn't a simple wrapper around array of Unicode code points, so
|
||
|
* this function call should be assumed to be more expensive than
|
||
|
* a simple copy.
|
||
|
*
|
||
|
* @param source New contents of the `Text`.
|
||
|
* @return Returns the calling object, to allow for function chaining.
|
||
|
*/
|
||
|
public final function Text CopyRaw(array<Character> rawSource)
|
||
|
{
|
||
|
contents = rawSource;
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Copies contents of the given string into caller `Text`.
|
||
|
*
|
||
|
* `Text` isn't a simple wrapper around unrealscript's `string`, so
|
||
|
* this function call should be assumed to be more expensive than simple
|
||
|
* `string` copy.
|
||
|
*
|
||
|
* @param source New contents of the caller `Text`.
|
||
|
* @return Returns the calling `Text` object, to allow for function chaining.
|
||
|
*/
|
||
|
public final function Text CopyString(string source)
|
||
|
{
|
||
|
CopyRaw(_().text.StringToRaw(source));
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns data in the caller `Text` object in form of an array of
|
||
|
* Unicode code points, preserving the order of characters where it matters
|
||
|
* (some modifier code points are allowed arbitrary order in Unicode standard).
|
||
|
*/
|
||
|
public final function array<Character> ToRaw()
|
||
|
{
|
||
|
return contents;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the `string` representation of contents of the caller `Text`.
|
||
|
*
|
||
|
* Unreal Engine doesn't seem to store code points higher than 2^16 in
|
||
|
* `string`, so some data might be lost in the process.
|
||
|
* (To check if it concerns you, refer to the Unicode symbol table,
|
||
|
* but it is not a problem for most people).
|
||
|
*/
|
||
|
public final function string ToString(optional StringType resultType)
|
||
|
{
|
||
|
return _().text.RawToString(contents, resultType);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Checks if the caller `Text` and a given `Text` have contain equal text
|
||
|
* content, according to Unicode standard. By default case-sensitive.
|
||
|
*/
|
||
|
public final function bool IsEqual
|
||
|
(
|
||
|
Text otherText,
|
||
|
optional bool caseInsensitive
|
||
|
)
|
||
|
{
|
||
|
local int i;
|
||
|
local array<Character> otherContentsCopy;
|
||
|
local TextAPI api;
|
||
|
if (contents.length != otherText.contents.length) return false;
|
||
|
|
||
|
api = _().text;
|
||
|
// There's some evidence that UnrealEngine might copy the whole
|
||
|
// `otherText.contents` each time we access any element,
|
||
|
// so just copy it once.
|
||
|
otherContentsCopy = otherText.contents;
|
||
|
for (i = 0; i < contents.length; i += 1)
|
||
|
{
|
||
|
if (!api.AreEqual(contents[i], otherContentsCopy[i], caseInsensitive))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Checks if the caller `Text` contains the same text content as the given
|
||
|
* `string`. By default case-sensitive.
|
||
|
*
|
||
|
* If text contains Unicode code points that can't be stored in
|
||
|
* a given `string`, equality should be considered impossible.
|
||
|
*/
|
||
|
public final function bool IsEqualToString
|
||
|
(
|
||
|
string source,
|
||
|
optional bool caseInsensitive,
|
||
|
optional StringType sourceType
|
||
|
)
|
||
|
{
|
||
|
local int i;
|
||
|
local array<Character> rawSource;
|
||
|
local TextAPI api;
|
||
|
api = _().text;
|
||
|
rawSource = api.StringToRaw(source, sourceType);
|
||
|
if (contents.length != rawSource.length) return false;
|
||
|
|
||
|
for (i = 0; i < contents.length; i += 1)
|
||
|
{
|
||
|
if (!api.AreEqual(contents[i], rawSource[i], caseInsensitive))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns `true` if the string has no characters, otherwise returns `false`.
|
||
|
*/
|
||
|
public final function bool IsEmpty()
|
||
|
{
|
||
|
return (contents.length == 0);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Attempts to returns Unicode code point, stored in caller `Text` at the
|
||
|
* given `index`.
|
||
|
*
|
||
|
* Doesn't properly work if `Text` contains characters consisting of
|
||
|
* multiple code points.
|
||
|
*
|
||
|
* @return For a valid index (non-negative, not exceeding the length,
|
||
|
* given by `GetLength()` of the `Text`) returns Unicode code point,
|
||
|
* stored in caller `Text` at the given `index`; otherwise - returns `-1`.
|
||
|
*/
|
||
|
public final function Character GetCharacter(optional int index)
|
||
|
{
|
||
|
if (index < 0) return _().text.GetInvalidCharacter();
|
||
|
if (index >= contents.length) return _().text.GetInvalidCharacter();
|
||
|
|
||
|
return contents[index];
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Converts caller `Text` to lower case.
|
||
|
*
|
||
|
* Changes every symbol contained in caller `Text` to it's lower case folding
|
||
|
* (according to Unicode standard). Symbols without lower case folding
|
||
|
* (like "&" or "!") are left unchanged.
|
||
|
*
|
||
|
* @return Returns the calling object, to allow for function chaining.
|
||
|
*/
|
||
|
public final function Text ToLower()
|
||
|
{
|
||
|
local int i;
|
||
|
local TextAPI api;
|
||
|
api = _().text;
|
||
|
for (i = 0; i < contents.length; i += 1)
|
||
|
{
|
||
|
contents[i] = api.ToLower(contents[i]);
|
||
|
}
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Converts caller `Text` to upper case.
|
||
|
*
|
||
|
* Changes every symbol contained in caller `Text` to it's upper case folding
|
||
|
* (according to Unicode standard). Symbols without upper case folding
|
||
|
* (like "&" or "!") are left unchanged.
|
||
|
*
|
||
|
* @return Returns the calling object, to allow for function chaining.
|
||
|
*/
|
||
|
public final function Text ToUpper()
|
||
|
{
|
||
|
local int i;
|
||
|
local TextAPI api;
|
||
|
api = _().text;
|
||
|
for (i = 0; i < contents.length; i += 1)
|
||
|
{
|
||
|
contents[i] = api.ToUpper(contents[i]);
|
||
|
}
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
public final function int GetHash() {
|
||
|
return _().text.GetHashRaw(contents);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns amount of symbols in the caller `Text`.
|
||
|
*/
|
||
|
public final function int GetLength()
|
||
|
{
|
||
|
return contents.length;
|
||
|
}
|
||
|
|
||
|
defaultproperties
|
||
|
{
|
||
|
}
|