Browse Source

Add new `ArrayList` collection

pull/8/head
Anton Tarasenko 2 years ago
parent
commit
940885f883
  1. 870
      sources/Data/Collections/ArrayList.uc
  2. 76
      sources/Data/Collections/ArrayListIterator.uc
  3. 35
      sources/Data/Collections/CollectionsAPI.uc

870
sources/Data/Collections/ArrayList.uc

@ -0,0 +1,870 @@
/**
* Dynamic array object for storing arbitrary types of data. Generic
* storage is achieved by using `AcediaObject` as the stored type. Native
* variable types such as `int`, `bool`, etc. can be stored by boxing them into
* `AcediaObject`s.
* Appropriate classes and APIs for their construction are provided for
* main primitive types and can be extended to any custom `struct`.
* Copyright 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 <https://www.gnu.org/licenses/>.
*/
class ArrayList extends Collection;
// Actual storage of all our data.
var private array<AcediaObject> storedObjects;
// Recorded `lifeVersions` of all stored objects.
// Invariant `lifeVersions.length == storedObjects.length` should be
// enforced by all methods.
var private array<int> lifeVersions;
// Free array data
protected function Finalizer()
{
Empty();
}
// Method, used to compare array values at different indices.
// Does not check boundary conditions, so make sure passed indices are valid.
private function bool AreEqual(AcediaObject object1, AcediaObject object2)
{
if (object1 == none && object2 == none) return true;
if (object1 == none || object2 == none) return false;
return object1.IsEqual(object2);
}
/**
* Returns current length of dynamic `ArrayList`.
*
* @return Returns length of the caller `ArrayList`.
* Guaranteed to be non-negative.
*/
public final function int GetLength()
{
return storedObjects.length;
}
/**
* Changes length of the caller `ArrayList`.
* If `ArrayList` size is increased as a result - added items will be
* filled with `none`s.
*
* @param newLength New length of an `ArrayList`.
* If negative value is passes - method will do nothing.
* @return Reference to the caller `ArrayList` to allow for method chaining.
*/
public final function ArrayList SetLength(int newLength)
{
local int i;
if (newLength < 0) {
return self;
}
for (i = newLength; i < storedObjects.length; i += 1) {
FreeItem(i);
}
storedObjects.length = newLength;
lifeVersions.length = newLength;
return self;
}
/**
* Deallocates an item at a given index `index`.
* Does not check `ArrayList` bounds for `index`, so you must ensure that
* `index` is valid.
*
* @param index Index of the item to deallocate.
* @return Reference to the caller `ArrayList` to allow for method chaining.
*/
protected final function ArrayList FreeItem(int index)
{
if (storedObjects[index] == none) {
return self;
}
storedObjects[index].FreeSelf(lifeVersions[index]);
storedObjects[index] = none;
return self;
}
public function Empty(optional bool deprecated)
{
SetLength(0);
}
/**
* Adds `amountOfNewItems` empty (`none`) items at the end of
* the `ArrayList`.
* To insert items at an arbitrary array index, use `Insert()`.
*
* @param amountOfNewItems Amount of items to add at the end.
* If non-positive value is passed, - method does nothing.
* @return Reference to the caller `ArrayList` to allow for method chaining.
*/
public final function ArrayList Add(int amountOfNewItems)
{
if (amountOfNewItems > 0) {
SetLength(storedObjects.length + amountOfNewItems);
}
return self;
}
/**
* Inserts `count` empty (`none`) items into the `ArrayList`
* at specified position.
* The indices of the following items are increased by `count` in order
* to make room for the new items.
*
* To add items at the end of an `ArrayList`, consider using `Add()`,
* which is equivalent to `array.Insert(array.GetLength(), ...)`.
*
* @param index Index, where first inserted item will be located.
* Must belong to `[0; self.GetLength()]` inclusive interval,
* otherwise method does nothing.
* @param count Amount of new items to insert.
* Must be positive, otherwise method does nothing.
* @return Reference to the caller `ArrayList` to allow for method chaining.
*/
public final function ArrayList Insert(int index, int count)
{
local int i;
local int swapIndex;
local int amountToShift;
if (count <= 0) return self;
if (index < 0 || index > storedObjects.length) return self;
// Native `Insert()` for an array is bugged and cannot be trusted
amountToShift = storedObjects.length - index;
Add(count);
if (amountToShift == 0) {
return self;
}
for (i = 0; i < amountToShift; i += 1)
{
swapIndex = storedObjects.length - i - 1;
Swap(swapIndex, swapIndex - count);
}
return self;
}
/**
* Swaps two `ArrayList` items.
*
* @param index1 Index of item to swap.
* @param index2 Index of item to swap.
*/
protected final function Swap(int index1, int index2)
{
local AcediaObject temporaryItem;
local int temporaryNumber;
// Swap object
temporaryItem = storedObjects[index1];
storedObjects[index1] = storedObjects[index2];
storedObjects[index2] = temporaryItem;
// Swap life versions
temporaryNumber = lifeVersions[index1];
lifeVersions[index1] = lifeVersions[index2];
lifeVersions[index2] = temporaryNumber;
}
/**
* Removes number items from the `ArrayList`, starting at `index`.
* All items before position and from `index + count` on are not changed,
* but the item indices change, - they shift to close the gap,
* created by removed items.
*
* @param index Remove items starting from this index.
* Must belong to `[0; self.GetLength() - 1]` inclusive interval,
* otherwise method does nothing.
* @param count Removes at most this much items.
* Must be positive, otherwise method does nothing.
* Specifying more items than can be removed simply removes
* all items, starting from `index`.
* @return Reference to the caller `ArrayList` to allow for method chaining.
*/
public final function ArrayList Remove(int index, int count)
{
local int i;
if (count <= 0) return self;
if (index < 0 || index > storedObjects.length) return self;
count = Min(count, storedObjects.length - index);
for (i = 0; i < count; i += 1) {
FreeItem(index + i);
}
storedObjects.Remove(index, count);
lifeVersions.Remove(index, count);
return self;
}
/**
* Removes item at a given index, shifting all the items that come after
* one place backwards.
*
* @param index Remove items starting from this index.
* Must belong to `[0; self.GetLength() - 1]` inclusive interval,
* otherwise method does nothing.
* @return Reference to the caller `ArrayList` to allow for method chaining.
*/
public final function ArrayList RemoveIndex(int index)
{
Remove(index, 1);
return self;
}
/**
* Validates item at `index`: in case it was erroneously deallocated while
* being stored in caller `ArrayList` - forgets stored `AcediaObject`
* reference.
*
* @param index Index of an item to validate/
* @return `true` if `index` is valid for `storedObjects` / `lifeVersions`
* and there is no need to check it.
*/
private final function bool ValidateIndex(int index)
{
local AcediaObject item;
if (index < 0) return false;
if (index >= storedObjects.length) return false;
item = storedObjects[index];
if (item == none) return true;
if (item.GetLifeVersion() != lifeVersions[index])
{
storedObjects[index] = none;
lifeVersions[index] = 0;
}
return true;
}
/**
* Returns item at `index` and replaces it with `none` inside `ArrayList`.
*
* @param index Index of an item that `ArrayList` has to return.
* @return Either value at `index` in the caller `ArrayList` or `none` if
* passed `index` is invalid.
*/
public final function AcediaObject TakeItem(int index)
{
local AcediaObject result;
if (ValidateIndex(index))
{
result = storedObjects[index];
storedObjects[index] = none;
lifeVersions[index] = 0;
}
return result;
}
/**
* Returns borrowed item at `index`. If index is invalid, returns `none`.
*
* @param index Index of an item that `ArrayList` has to return.
* @return Either value at `index` in the caller `ArrayList` or `none` if
* passed `index` is invalid.
*/
private final function AcediaObject BorrowItem(int index)
{
if (ValidateIndex(index)) {
return storedObjects[index];
}
}
/**
* Returns item at `index`. If index is invalid, returns `none`.
*
* @param index Index of an item that `ArrayList` has to return.
* @return Either value at `index` in the caller `ArrayList` or `none` if
* passed `index` is invalid.
*/
public final function AcediaObject GetItem(int index)
{
local AcediaObject result;
if (ValidateIndex(index))
{
result = storedObjects[index];
storedObjects[index] = none;
lifeVersions[index] = 0;
}
if (result != none) {
result.NewRef();
}
return result;
}
/**
* Changes `ArrayList`'s value at `index` to `item`.
*
* @param index Index, at which to change the value. If `ArrayList` is
* not long enough to hold it, it will be automatically expanded.
* If passed index is negative - method will do nothing.
* @param item Value to be set at a given index.
* @return Reference to the caller `ArrayList` to allow for method chaining.
*/
public final function ArrayList SetItem(int index, AcediaObject item)
{
if (index < 0) {
return self;
}
if (index >= storedObjects.length) {
SetLength(index + 1);
}
else if (item != storedObjects[index]) {
FreeItem(index);
}
if (item != none && item.IsAllocated())
{
item.NewRef();
storedObjects[index] = item;
lifeVersions[index] = item.GetLifeVersion();
}
return self;
}
/**
* Creates a new instance of class `valueClass` and records it's value at index
* `index` in the caller `ArrayList`.
*
* @param index Index, at which to change the value. If `ArrayList`
* is not long enough to hold it, it will be automatically expanded.
* If passed index is negative - method will do nothing.
* @param valueClass Class of object to create. Will only be created if
* passed `index` is valid.
* @return Caller `ArrayList` to allow for method chaining.
*/
public final function ArrayList CreateItem(
int index,
class<AcediaObject> valueClass)
{
local AcediaObject newObject;
if (index < 0) return self;
if (valueClass == none) return self;
newObject = AcediaObject(_.memory.Allocate(valueClass));
SetItem(index, newObject);
_.memory.Free(newObject);
return self;
}
/**
* Adds given `item` at the end of the `ArrayList`, expanding it by
* one item.
*
* @param item Item to be added at the end of the `ArrayList`.
* @return Reference to the caller `ArrayList` to allow for method chaining.
*/
public final function ArrayList AddItem(AcediaObject item)
{
return SetItem(storedObjects.length, item);
}
/**
* Inserts given `item` at index `index` of the `ArrayList`,
* shifting all the items starting from `index` one position to the right.
*
* @param index Index at which to insert new item. Must belong to
* inclusive range `[0; self.GetLength()]`, otherwise method does nothing.
* @param item Item to insert.
* @return Reference to the caller `ArrayList` to allow for method chaining.
*/
public final function ArrayList InsertItem(int index, AcediaObject item)
{
if (index < 0) return self;
if (index > storedObjects.length) return self;
Insert(index, 1);
SetItem(index, item);
return self;
}
/**
* Returns all occurrences of `item` in the caller `ArrayList`
* (optionally only first one).
*
* @param item Item that needs to be removed from a `ArrayList`.
* @param onlyFirstItem Set to `true` to only remove first occurrence.
* By default `false`, which means all occurrences will be removed.
* @return Reference to the caller `ArrayList` to allow for method chaining.
*/
public final function ArrayList RemoveItem(
AcediaObject item,
optional bool onlyFirstItem)
{
local int i;
while (i < storedObjects.length)
{
if (AreEqual(storedObjects[i], item))
{
Remove(i, 1);
if (onlyFirstItem) {
return self;
}
}
else {
i += 1;
}
}
return self;
}
/**
* Finds first occurrence of `item` in caller `ArrayList` and returns
* it's index.
*
* @param item Item to find in `ArrayList`.
* @return Index of first occurrence of `item` in caller `ArrayList`.
* `-1` if `item` is not found.
*/
public final function int Find(AcediaObject item)
{
local int i;
if (item != none && !item.IsAllocated()) {
item = none;
}
for (i = 0; i < storedObjects.length; i += 1)
{
if (AreEqual(storedObjects[i], item)) {
return i;
}
}
return -1;
}
protected function AcediaObject GetByText(BaseText key)
{
local int index, consumed;
local Parser parser;
parser = _.text.Parse(key);
parser.MUnsignedInteger(index,,, consumed);
if (!parser.Ok())
{
parser.FreeSelf();
return none;
}
parser.FreeSelf();
return GetItem(index);
}
/**
* Checks if value recorded at a given `index` is `none`.
*
* @param index Index to check the value at.
* @return `true` if `none` value is recorded at `index` and
* `false` otherwise.
* In case `index` is out-of-bound, nothing is recorded there,
* not even `none`, so method will return `false`.
*/
public final function bool IsNone(int index)
{
if (ValidateIndex(index)) {
return (storedObjects[index] == none);
}
return false;
}
/**
* Returns `bool` item at `index`. If index is invalid or
* stores a non-`bool` value, returns `defaultValue`.
*
* Referred value must be stored as `BoolBox` or `BoolRef`
* (or one of their sub-classes) for this method to work.
*
* @param index Index of a `bool` item that `ArrayList`
* has to return.
* @param defaultValue Value to return if there is either no item recorded
* at `index` or it has a wrong type.
* @return `bool` value at `index` in the caller `ArrayList`.
* `defaultValue` if passed `index` is invalid or non-`bool` value
* is stored there.
*/
public final function bool GetBool(int index, optional bool defaultValue)
{
local AcediaObject result;
local BoolBox asBox;
local BoolRef asRef;
result = BorrowItem(index);
if (result == none) {
return defaultValue;
}
asBox = BoolBox(result);
if (asBox != none) {
return asBox.Get();
}
asRef = BoolRef(result);
if (asRef != none) {
return asRef.Get();
}
return defaultValue;
}
/**
* Changes `ArrayList`'s value at `index` to `value` that will be recorded
* as either `BoolBox` or `BoolRef`, depending of `asRef` optional parameter.
*
* @param index Index, at which to change the value. If `ArrayList` is
* not long enough to hold it, it will be automatically expanded.
* If passed index is negative - method will do nothing.
* @param value Value to be set at a given index.
* @param asRef Given `bool` value will be recorded as immutable `BoolBox`
* by default (`asRef == false`). Setting this parameter to `true` will
* make this method record it as a mutable `BoolRef`.
* @return Reference to the caller `ArrayList` to allow for method chaining.
*/
public final function ArrayList SetBool(
int index,
bool value,
optional bool asRef)
{
if (asRef) {
SetItem(index, _.ref.bool(value));
}
else {
SetItem(index, _.box.bool(value));
}
return self;
}
/**
* Returns `byte` item at `index`. If index is invalid or
* stores a non-`byte` value, returns `defaultValue`.
*
* Referred value must be stored as `ByteBox` or `ByteRef`
* (or one of their sub-classes) for this method to work.
*
* @param index Index of a `byte` item that `ArrayList`
* has to return.
* @param defaultValue Value to return if there is either no item recorded
* at `index` or it has a wrong type.
* @return `byte` value at `index` in the caller `ArrayList`.
* `defaultValue` if passed `index` is invalid or non-`byte` value
* is stored there.
*/
public final function byte GetByte(int index, optional byte defaultValue)
{
local AcediaObject result;
local ByteBox asBox;
local ByteRef asRef;
result = BorrowItem(index);
if (result == none) {
return defaultValue;
}
asBox = ByteBox(result);
if (asBox != none) {
return asBox.Get();
}
asRef = ByteRef(result);
if (asRef != none) {
return asRef.Get();
}
return defaultValue;
}
/**
* Changes `ArrayList`'s value at `index` to `value` that will be recorded
* as either `ByteBox` or `ByteRef`, depending of `asRef` optional parameter.
*
* @param index Index, at which to change the value. If `ArrayList` is
* not long enough to hold it, it will be automatically expanded.
* If passed index is negative - method will do nothing.
* @param value Value to be set at a given index.
* @param asRef Given `byte` value will be recorded as immutable `ByteBox`
* by default (`asRef == false`). Setting this parameter to `true` will
* make this method record it as a mutable `ByteRef`.
* @return Reference to the caller `ArrayList` to allow for method chaining.
*/
public final function ArrayList SetByte(
int index,
byte value,
optional bool asRef)
{
if (asRef) {
SetItem(index, _.ref.byte(value));
}
else {
SetItem(index, _.box.byte(value));
}
return self;
}
/**
* Returns `int` item at `index`. If index is invalid or
* stores a non-`int` value, returns `defaultValue`.
*
* Referred value must be stored as `IntBox` or `IntRef`
* (or one of their sub-classes) for this method to work.
*
* @param index Index of a `int` item that `ArrayList`
* has to return.
* @param defaultValue Value to return if there is either no item recorded
* at `index` or it has a wrong type.
* @return `int` value at `index` in the caller `ArrayList`.
* `defaultValue` if passed `index` is invalid or non-`int` value
* is stored there.
*/
public final function int GetInt(int index, optional int defaultValue)
{
local AcediaObject result;
local IntBox asBox;
local IntRef asRef;
result = BorrowItem(index);
if (result == none) {
return defaultValue;
}
asBox = IntBox(result);
if (asBox != none) {
return asBox.Get();
}
asRef = IntRef(result);
if (asRef != none) {
return asRef.Get();
}
return defaultValue;
}
/**
* Changes `ArrayList`'s value at `index` to `value` that will be recorded
* as either `IntBox` or `IntRef`, depending of `asRef` optional parameter.
*
* @param index Index, at which to change the value. If `ArrayList` is
* not long enough to hold it, it will be automatically expanded.
* If passed index is negative - method will do nothing.
* @param value Value to be set at a given index.
* @param asRef Given `int` value will be recorded as immutable `IntBox`
* by default (`asRef == false`). Setting this parameter to `true` will
* make this method record it as a mutable `IntRef`.
* @return Reference to the caller `ArrayList` to allow for method chaining.
*/
public final function ArrayList SetInt(
int index,
int value,
optional bool asRef)
{
if (asRef) {
SetItem(index, _.ref.int(value));
}
else {
SetItem(index, _.box.int(value));
}
return self;
}
/**
* Returns `float` item at `index`. If index is invalid or
* stores a non-`int` value, returns `defaultValue`.
*
* Referred value must be stored as `FloatBox` or `FloatRef`
* (or one of their sub-classes) for this method to work.
*
* @param index Index of a `float` item that `ArrayList`
* has to return.
* @param defaultValue Value to return if there is either no item recorded
* at `index` or it has a wrong type.
* @return `float` value at `index` in the caller `ArrayList`.
* `defaultValue` if passed `index` is invalid or non-`float` value
* is stored there.
*/
public final function float GetFloat(int index, optional float defaultValue)
{
local AcediaObject result;
local FloatBox asBox;
local FloatRef asRef;
result = BorrowItem(index);
if (result == none) {
return defaultValue;
}
asBox = FloatBox(result);
if (asBox != none) {
return asBox.Get();
}
asRef = FloatRef(result);
if (asRef != none) {
return asRef.Get();
}
return defaultValue;
}
/**
* Changes `ArrayList`'s value at `index` to `value` that will be recorded
* as either `FloatBox` or `FloatRef`, depending of `asRef` optional parameter.
*
* @param index Index, at which to change the value. If `ArrayList` is
* not long enough to hold it, it will be automatically expanded.
* If passed index is negative - method will do nothing.
* @param value Value to be set at a given index.
* @param asRef Given `float` value will be recorded as immutable `FloatBox`
* by default (`asRef == false`). Setting this parameter to `true` will
* make this method record it as a mutable `FloatRef`.
* @return Reference to the caller `ArrayList` to allow for method chaining.
*/
public final function ArrayList SetFloat(
int index,
float value,
optional bool asRef)
{
if (asRef) {
SetItem(index, _.ref.float(value));
}
else {
SetItem(index, _.box.float(value));
}
return self;
}
/**
* Returns `BaseText` item at `index`. If index is invalid or
* stores a non-`BaseText` value, returns `none`.
*
* Referred value must be stored as `BaseText` (or one of it's sub-classes,
* such as `Text` or `MutableText`) for this method to work.
*
* @param index Index of a `BaseText` item that `ArrayList` has to return.
* @return `BaseText` value at `index` in the caller `ArrayList`.
* `none` if passed `index` is invalid or non-`BaseText` value
* is stored there.
*/
public final function BaseText GetBaseText(int index)
{
local BaseText result;
result = BaseText(BorrowItem(index));
if (result != none) {
result.NewRef();
}
return result;
}
/**
* Returns `Text` item at `index`. If index is invalid or
* stores a non-`Text` value, returns `none`.
*
* Referred value must be stored as `Text` (or one of it's sub-classes,
* such as `MutableText`) for this method to work.
*
* @param index Index of a `Text` item that `ArrayList` has to return.
* @return `Text` value at `index` in the caller `ArrayList`.
* `none` if passed `index` is invalid or non-`Text` value
* is stored there.
*/
public final function Text GetText(int index)
{
local Text result;
result = Text(BorrowItem(index));
if (result != none) {
result.NewRef();
}
return result;
}
/**
* Returns `MutableText` item at `index`. If index is invalid or
* stores a non-`Text` value, returns `none`.
*
* Referred value must be stored as `MutableText` for this method to work.
*
* @param index Index of a `MutableText` item that `ArrayList` will return.
* @return `MutableText` value at `index` in the caller `ArrayList`.
* `none` if passed `index` is invalid or non-`MutableText` value
* is stored there.
*/
public final function MutableText GetMutableText(int index)
{
local MutableText result;
result = MutableText(BorrowItem(index));
if (result != none) {
result.NewRef();
}
return result;
}
/**
* Returns `AssociativeArray` item at `index`. If index is invalid or
* stores a non-`AssociativeArray` value, returns `none`.
*
* Referred value must be stored as `AssociativeArray`
* (or one of it's sub-classes) for this method to work.
*
* @param index Index of an `AssociativeArray` item that `ArrayList`
* has to return.
* @return `AssociativeArray` value at `index` in the caller `ArrayList`.
* `none` if passed `index` is invalid or non-`AssociativeArray` value
* is stored there.
*/
public final function AssociativeArray GetAssociativeArray(int index)
{
local AssociativeArray result;
result = AssociativeArray(BorrowItem(index));
if (result != none) {
result.NewRef();
}
return result;
}
/**
* Returns `DynamicArray` item at `index`. If index is invalid or
* stores a non-`DynamicArray` value, returns `none`.
*
* Referred value must be stored as `Text` (or one of it's sub-classes,
* such as `MutableText`) for this method to work.
*
* @param index Index of a `DynamicArray` item that caller `ArrayList`
* has to return.
* @return `DynamicArray` value at `index` in the caller `ArrayList`.
* `none` if passed `index` is invalid or non-`ArrayList` value
* is stored there.
*/
public final function DynamicArray GetDynamicArray(int index)
{
local DynamicArray result;
result = DynamicArray(BorrowItem(index));
if (result != none) {
result.NewRef();
}
return result;
}
/**
* Returns `ArrayList` item at `index`. If index is invalid or
* stores a non-`ArrayList` value, returns `none`.
*
* Referred value must be stored as `Text` (or one of it's sub-classes,
* such as `MutableText`) for this method to work.
*
* @param index Index of a `ArrayList` item that caller `ArrayList`
* has to return.
* @return `ArrayList` value at `index` in the caller `ArrayList`.
* `none` if passed `index` is invalid or non-`ArrayList` value
* is stored there.
*/
public final function ArrayList GetArrayList(int index)
{
local ArrayList result;
result = ArrayList(BorrowItem(index));
if (result != none) {
result.NewRef();
}
return result;
}
defaultproperties
{
iteratorClass = class'ArrayListIterator'
}

76
sources/Data/Collections/ArrayListIterator.uc

@ -0,0 +1,76 @@
/**
* Iterator for iterating over `ArrayList`'s items.
* Copyright 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 <https://www.gnu.org/licenses/>.
*/
class ArrayListIterator extends Iter;
var private ArrayList relevantCollection;
var private int currentIndex;
protected function Finalizer()
{
relevantCollection = none;
}
public function bool Initialize(Collection relevantArray)
{
currentIndex = 0;
relevantCollection = ArrayList(relevantArray);
if (relevantCollection == none) {
return false;
}
return true;
}
public function Iter Next(optional bool skipNone)
{
local int collectionLength;
if (!skipNone)
{
currentIndex += 1;
return self;
}
collectionLength = relevantCollection.GetLength();
while (currentIndex < collectionLength)
{
currentIndex += 1;
if (!relevantCollection.IsNone(currentIndex)) {
return self;
}
}
return self;
}
public function AcediaObject Get()
{
return relevantCollection.GetItem(currentIndex);
}
public function AcediaObject GetKey()
{
return _.box.int(currentIndex);
}
public function bool HasFinished()
{
return currentIndex >= relevantCollection.GetLength();
}
defaultproperties
{
}

35
sources/Data/Collections/CollectionsAPI.uc

@ -19,6 +19,41 @@
*/ */
class CollectionsAPI extends AcediaObject; class CollectionsAPI extends AcediaObject;
/**
* Creates a new `ArrayList`, optionally filling it with objects from
* a given native array.
*
* @param objectArray Objects to place inside created `ArrayList`;
* if empty (by default) - new, empty `ArrayList` will be returned.
* Objects will be added in the same order as in `objectArray`.
* @param managed Flag that indicates whether objects from
* `objectArray` argument should be added as managed.
* By default `false` - they would not be managed.
* @return New `ArrayList`, optionally filled with contents of
* `objectArray`. Guaranteed to be not `none` and to not contain any items
* outside of `objectArray`.
*/
public final function ArrayList NewArrayList(array<AcediaObject> objectArray)
{
local int i;
local ArrayList result;
result = ArrayList(_.memory.Allocate(class'ArrayList'));
for (i = 0; i < objectArray.length; i += 1) {
result.AddItem(objectArray[i]);
}
return result;
}
/**
* Creates a new empty `ArrayList`.
*
* @return New empty instance of `ArrayList`.
*/
public final function ArrayList EmptyArrayList()
{
return ArrayList(_.memory.Allocate(class'ArrayList'));
}
/** /**
* Creates a new `DynamicArray`, optionally filling it with objects from * Creates a new `DynamicArray`, optionally filling it with objects from
* a given native array. * a given native array.

Loading…
Cancel
Save