The MArray module provides array objects, meaning sequences of values. For example, an array of numbers. Each number in the array is known as an item. The number of items in an array object can be changed (the array can grow or shrink in size).
MArray is homogeneous meaning all items within an MArray instance must be the same type. For example, it is not possible to have some items be type "TUInt8" while others are "TUInt32", in the same MArray instance. Supporting the ability for items to have different sizes/types within the same instance (meaning heterogeneous) would impose substantial extra memory and processing overhead.
The maximum number of items that can be stored in an array instance is an indefinitely large amount. Storing 100 thousand items is no problem, if the items are small. Storing 100 million items is theoretically possible but would probably be slow, inefficient, and impractical. If you need to store a gigantic number of items, then MArray is the wrong solution for your particular problem; perhaps try a database instead.
OrdinalsEach item in an array is accessed/specified using its ordinal. The ordinal of the first item is 0. The ordinal of the second item is 1. The ordinal of the third item is 2, etc. Thus if you want to retrieve the value of the first item, then you would be required to specify that you want the item at ordinal 0. If there are 14 items in total, then the ordinal of the last item is 13.
The ordinal of the first item is not 1 because starting at 1 (as opposed to 0) tends to be awkward mathematically, requiring that 1 be subtracted from or added to various calculations. 0-based is more natural mathematically. For example, if you have the ordinal of an item, and you wish to calculate how many items from (and including) that position to the end of the array, then the formula is the total number/count of items minus the ordinal, if the ordinals are 0-based. However if the ordinals are 1-based, then the formula is the total number/count of items minus the ordinal, then plus 1. It is also slightly faster/easier to verify the validity of a 0-based ordinal than a 1-based ordinal.
Note that when a new item is inserted into the array, the ordinals of all following items automatically increase by 1. And when an item is removed from the array, the ordinals of all following items automatically decrease by 1. Thus the ordinals cannot be relied upon to always identify the same items, unless the array never changes, or unless items are only appended never inserted or removed. If this behavior is a problem for you, then MArray is probably the wrong solution for your particular problem; use one of the other modules.
| Ordinal | Value |
|---|---|
| 0 | 123 |
| 1 | 46 |
| 2 | 86 |
| 3 | 666 |
| 4 | 13 |
| 5 | 7 |
| 6 | 99 |
After inserting a new item with value 456 at ordinal 3:
| Ordinal | Value |
|---|---|
| 0 | 123 |
| 1 | 46 |
| 2 | 86 |
| 3 | 456 |
| 4 | 666 |
| 5 | 13 |
| 6 | 7 |
| 7 | 99 |
The ordinals are not literally stored with the items. Only the item values are actually stored. The ordinals are known implicitly, or calculated mathematically.
MNumArray::Create| outAry | RNumArray | The variable to receive the reference to the new array object. |
| inType | VarType | The type of items that the array stores, for example uint32, sint32, uint64, float64, etc. Must be a basic numeric type. |
- Any existing reference in the outAry variable is removed and replaced by the reference to the new array object.
- If creation of the new object fails, the outAry variable is unchanged.
- The reference is set to be a non-subset reference (but can subsequently be changed to a subset).
| inAry | RNumArray | A reference to an array object to modify. |
| inValue | VarType | The numeric value to append as a new item. |
- If this command fails, the reference and the object are (or appear) unchanged.
- If the object reference is a subset, this command will append to the end of the subset, not to the end of the entire array. Thus it may actually be inserting into the middle of the array, if the subset ends before the end of the array. In other words, it inserts at the subset end.
- The subset range is expanded to include the appended new item.
- Fails if the subset range starts or ends beyond the end of the array. Acceptable if is exactly at end.
- It is acceptable if the specified array or subset is empty.
| MArray::kError::NullObject | inAry is a null reference (no array object). |
| MArray::kError::IncorrectObjectType | The inAry object is not an MNumArray object. |
| MArray::kError::InvalidSubset | The subset range of the inAry reference starts or ends beyond the end of the array. |
| MArray::kError::MaxLimit | Adding the new item to the array would exceed the maximum size of a MNumArray object. |
| MMemory::kError::Insufficient | There is not enough free memory to add the item to the array. |
| inAry | RNumArray | A reference to an array object to modify. |
| inValue | VarType | The numeric value to insert as a new item. |
This command is not named "Prepend" (by analogy with "Append") because prepend tends to imply that the new item can be "tacked on" or joined with the pre-existing items with little or no disturbance to the pre-existing items, whereas in reality this command is forced to move/copy every single pre-existing item value to the next storage slot to make the first storage slot free for the new item value being inserted.
Although this command is unable to operate as "prepend" implies, the MNumArray::Append command does in fact operate as "append" implies (with little or no disturbance to the pre-existing items, except if it is a subset). Thus the MNumArray::Append command is usually much faster than the MNumArray::InsertAtStart command, especially if the array contains a large number of items.
- If the reference is a subset, it inserts at the start of the subset.
- It is acceptable if the specified array or subset is empty.
- See MNumArray::Insert for other details.
| inAry | RNumArray | A reference to an array object to modify. |
| inAtOrdinal | uint32 | The ordinal at which to insert the new item. |
| inValue | VarType | The numeric value for the new item. |
The ordinal of the last item in the array is the item count minus 1. Therefore if you insert at that ordinal, the last item will continue to be the last item (the new item will be the second-last item). If inAtOrdinal exactly equals the item count (being the ordinal of the first non-existent item) then the new item will be the last of the items, meaning the same result as if the item were appended.
If inAtOrdinal is greater than the item count, then this command fails with the kError::InvalidOrdinal error code. This strict behavior means that the ordinal of the newly inserted item is always exactly equal to inAtOrdinal. Whereas if inAtOrdinal being greater than the item count was interpreted to mean that the item should be appended (relaxed behavior), then it would be possible for the ordinal of the newly inserted item to be different to inAtOrdinal (and then inAtOrdinal would probably have to be changed to an in/out parameter). It was decided that it is simpler and safer to be able to say that as a rule the ordinal of the newly inserted item is always exactly equal to inAtOrdinal.
- The new item is inserted AT the specified ordinal, meaning BEFORE any existing item at the ordinal, not after. The existing item (and all following items) is pushed forward to the next ordinal / storage slot. Inserting at ordinal 0 means the newly inserted item will be the first item.
- Immediately after this command finishes successfully, the ordinal of the newly inserted item is always exactly equal to inAtOrdinal (until other items are inserted or removed).
- If this command fails, the reference and the object are (or appear) unchanged.
- If the object reference is a subset, then inAtOrdinal is an ordinal into the subset, and it inserts into the subset. For example, inAtOrdinal being 0 would mean that it inserts at the start of the subset.
- The subset range is expanded with the newly inserted item (it inserts into the subset).
- Fails if the subset range starts or ends beyond the end of the array. Acceptable if is exactly at end.
| MArray::kError::NullObject | inAry is a null reference (no array object). |
| MArray::kError::IncorrectObjectType | The inAry object is not an MNumArray object. |
| MArray::kError::InvalidOrdinal | inAtOrdinal is greater than the item count. |
| MArray::kError::InvalidSubset | The subset range of the inAry reference starts or ends beyond the end of the array. |
| MArray::kError::MaxLimit | Inserting the new item into the array would exceed the maximum size of a MNumArray object. |
| MMemory::kError::Insufficient | There is not enough free memory to insert the item into the array. |
| inAry | RNumArray | A reference to an array object to modify. |
| inOrdinal | uint32 | The ordinal of the item to modify. |
| inValue | VarType | The new numeric value of the item. |
Fails if inOrdinal is invalid (greater than or equal to the number of items).
The type of the inValue parameter is flexible depending on the type of items the array is storing. If you supply a value bigger than the array item can store, the value is truncated (upper digits/bits removed).
**** TO DO: Perhaps the compiler should disallow supplying a variable of a bigger or incompatible type than the type of items the array is storing. (This would be a compile-time error, not runtime.)
- If the object reference is a subset, then inOrdinal is an ordinal into the subset. For example, inOrdinal being 0 would mean the first item in the subset.
- Fails if inOrdinal specifies an item beyond the end of the subset.
- Fails if the subset range starts beyond the end of the array.
- inOrdinal is added to the subset-start-ordinal to calculate the real ordinal. If this calculation overflows, inOrdinal is considered to be invalid.
| MArray::kError::NullObject | inAry is a null reference (no array object). |
| MArray::kError::IncorrectObjectType | The inAry object is not an MNumArray object. |
| MArray::kError::InvalidOrdinal | There is no item with the specified ordinal, or the item is outside the subset range, or the subset range starts beyond the end of the array, or calculation of the real ordinal overflowed. |
| inAry | RNumArray | A reference to an array object to query. |
| inOrdinal | uint32 | The ordinal of the item to modify. |
| outValue | VarType | The specified variable will receive the value of the item. |
Fails if inOrdinal is invalid (greater than or equal to the number of items).
The type of the outValue parameter is flexible depending on the type of items the array is storing.
**** TO DO: Should the compiler produce an error message if the type of the variable supplied for the outValue parameter is a smaller size than the type of items the array is storing? Perhaps produce an error message if the type is not an exact match? (This would be a compile-time error, not runtime.)
- Behavior regarding subsets is the same as MNumArray::Set.
- This command cannot be used to get the value of items outside of the subset range.
| inAry | RNumArray | A reference to an array object to query. |
| outCount | uint32 | The specified variable will receive the count. |