Skip to content

Array

Array is a heap-owned, resizable ordered list of Object*. Elements keep their insertion order, indices are dense, and every stored element is held with a strong (+1) reference.

#import "Array.xc" // or the Foundation umbrella

An Array wraps a heap-allocated pointer[], one cell per element, that grows geometrically (8, then doubling) as you add. It inherits from Object and needs a real heap (-falloc=heap, the default on the xt 6502 layout and every native backend).

Array<T> is generic in name only. The type parameter is a compile-time check that the compiler erases at runtime. The slots are type-erased pointer cells, so any class works as an element. A parentless class X is an implicit child of the built-in Object root, so an X* is always an Object*.

Ownership (ARC). The Array holds a strong reference on every element. add / insert retain; set retains the incoming element and releases the outgoing one; the remove… family releases the slot it vacates; dealloc releases whatever is left and frees the backing buffer. A copy is shallow: the elements are shared, each retained by both arrays so each array owns its references independently.

Complexity. Indexed get/set are O(1); add is amortised O(1); insert, removeAt and the range operations shift the tail and are O(n); indexOf and the predicate scans are O(n); sort is quicksort, O(n log n) average.

Searching returns an index and a miss is notFound(), never a negative number. Range operations clamp to the valid range rather than faulting, as subarray does.

Every Array* is also an Object* and fits anywhere one is expected.

Creating · withCapacity · with · withArray · init

Accessing · count · length · isEmpty · capacity · get · first · last

Adding · add · insert · insertAll · addAll · adding · set · replaceAt

Removing · removeAt · removeFirst · removeLast · removeAll · remove · removeEqual · removeRange · replaceRange · setTo

Searching · indexOf · contains · indexOfEqual · containsEqual · notFound

Functional (map / filter / reduce) · filtered · mapped · forEach · firstWhere · indexWhere · countWhere · anySatisfy · allSatisfy

Sorting · sortUsing · sort · sortedUsing · sorted · isSortedUsing

Structural · subarray · swapAt · reverse · reversed · isEqualToArray

Iterating · enumLength · enumAt

Lifecycle · copy · dealloc


static Array* withCapacity(u32 cap)

Pre-sizes the backing store to cap cells, skipping the geometric-resize copies when the rough total is known up front. cap == 0 behaves like new Array().

static Array* with(Object* a)
static Array* with(Object* a, Object* b)
static Array* with(Object* a, Object* b, Object* c)
static Array* with(Object* a, Object* b, Object* c, Object* d)

Builds a small Array from a fixed list of one to four elements, the equivalent of arrayWithObjects: for common counts (xtc has no nil-terminated vararg convention). Each element is retained.

static Array* withArray(Array* other)

A new Array over the elements of other (a shallow copy, the same as calling copy on other).

void init(void)

The default initializer: an empty Array with no allocation. Prefer new Array() or withCapacity; you rarely call init directly.

↑ Topics

u32 count(void)

Number of live elements. O(1).

u32 length(void)

Alias for count.

bool isEmpty(void)

true when count is zero.

u32 capacity(void)

Cells currently allocated in the backing buffer (≥ count). See withCapacity.

Object* get(u32 i)

The element at index i. O(1). There is no bounds check, so keep i < count().

Object* first(void)

The first element, or null when the Array is empty.

Object* last(void)

The last element, or null when the Array is empty.

↑ Topics

void add(Object* obj)

Appends obj to the end, growing the buffer if needed. Retains obj. Amortised O(1).

void insert(u32 i, Object* obj)

Inserts obj at index i, shifting [i..count-1] up one. i == count is the same as add; i > count is ignored. Retains obj. O(n).

void insertAll(u32 at, Array* other)

Inserts every element of other starting at at, order preserved. at past the end clamps to the end. Inserting an Array into itself is handled by snapshotting first.

void addAll(Array* other)

Appends every element of other in order (each retained). A null argument is a no-op.

Array* adding(Object* obj)

Returns a new Array of the receiver’s elements followed by obj; the receiver is untouched (arrayByAddingObject:).

void set(u32 i, Object* obj)

Replaces the element at i with obj: retains the incoming element before releasing the outgoing one (so a.set(i, a.get(i)) is safe). Out of range is a no-op.

void replaceAt(u32 i, Object* obj)

replaceObjectAtIndex:: the same operation as set, under the Foundation name.

↑ Topics

Each removal releases the strong reference on the slot it vacates.

void removeAt(u32 i)

Removes the element at i, shifting the tail down one. Out of range is a no-op. O(n).

void removeFirst(void)

Removes the first element (removeAt(0)).

void removeLast(void)

Removes the last element. No-op on an empty Array. O(1).

void removeAll(void)

Releases and drops every element, leaving the Array empty (the buffer is kept).

bool remove(Object* obj)

Removes the first element with this identity (removeObjectIdenticalTo:). Returns whether one was found.

bool removeEqual(Comparable* obj)

Removes the first element equal to obj by value (removeObject:, via the element’s Comparable equals). Returns whether one was found.

void removeRange(u32 at, u32 len)

Removes len elements starting at at in one pass of releases and a single tail shift. The range clamps to what is available.

void replaceRange(u32 at, u32 len, Array* other)

Replaces len elements at at with all of other; the two lengths need not match. Safe when other is the receiver (snapshotted first).

void setTo(Array* other)

Becomes other (setArray:): releases the current contents, then adds all of other.

↑ Topics

Searches return a u32 index; a miss is notFound().

u32 indexOf(Object* obj)

First index whose element is identical to obj (pointer identity: two distinct Number(42) instances are different elements here). O(n).

bool contains(Object* obj)

true if any element is identical to obj (indexOf(obj) != notFound()).

u32 indexOfEqual(Comparable* obj)

First index whose element is equal to obj by value, dispatching equals through the Comparable slot. A null argument returns notFound().

bool containsEqual(Comparable* obj)

true if any element is equal to obj by value.

static u32 notFound(void) // 0xFFFFFFFF

The sentinel returned by the search methods on a miss. It lies outside the valid index range. $FFFF cannot serve as the sentinel because the container can hold more than 65535 elements.

↑ Topics

Each takes a callback argument, which can be a plain function (widened) or a bound method that carries its receiver. A bound method lets a predicate use state (&filter.matches) without a global. A null callback gives an empty result or does nothing.

Array* filtered(callback keep bool(Object* o))

A new Array of the elements the predicate keeps, in order. The receiver is untouched; survivors are retained by the result.

Array* mapped(callback f Object*(Object* o))

A new Array of each element passed through f. A null result is skipped rather than stored, so mapped doubles as a filtering transform.

void forEach(callback fn void(Object* o))

Calls fn once per element, in order.

Object* firstWhere(callback p bool(Object* o))

The first element satisfying p, or null. Stops at the first hit.

u32 indexWhere(callback p bool(Object* o))

The index of the first element satisfying p, or notFound().

u32 countWhere(callback p bool(Object* o))

How many elements satisfy p.

bool anySatisfy(callback p bool(Object* o))

true if at least one element satisfies p (indexWhere(p) != notFound()).

bool allSatisfy(callback p bool(Object* o))

true if every element satisfies p (vacuously true for an empty Array). A null predicate returns false.

↑ Topics

The comparator type is cmp2_t, i8 (Object*, Object*), following the C / NSComparisonResult convention (< 0 if the first sorts before the second). The in-place sorts move only the slot pointers, so no element is retained or released.

void sortUsing(callback cmp i8(Object* a, Object* b))

Sorts in place with quicksort under comparator cmp (a plain function or a bound method; &self.byColumn captures a receiver). A null comparator or fewer than two elements is a no-op.

bool sort(void)

Sorts in place by the elements’ own order, the optional Comparable compare slot. Returns false and leaves the Array untouched when the elements do not implement compare. In that case use sortUsing with an explicit comparator.

Array* sortedUsing(callback cmp i8(Object* a, Object* b))

A sorted copy under cmp; the receiver is left alone. The copy holds its own strong reference to every element.

Array* sorted(void)

A sorted copy by the elements’ natural Comparable order; the receiver is left alone.

bool isSortedUsing(callback cmp i8(Object* a, Object* b))

true if the Array is already in non-descending order under cmp. It is cheap, and useful in tests and as a guard before a merge.

↑ Topics

Array* subarray(u32 from, u32 len)

A new Array holding the slice of len elements starting at from. Out of range clamps to empty, as String’s slicing does.

void swapAt(u32 i, u32 j)

Swaps the elements at i and j in place. Out-of-range or equal indices are a no-op.

void reverse(void)

Reverses the Array in place (only the slot cells move, so no refcount changes).

Array* reversed(void)

A new Array with the elements in reverse order; the receiver is untouched.

bool isEqualToArray(Array* other)

true when other has the same count and elements equal pairwise by value (identity first, then the element’s own Comparable equality). This is Foundation’s isEqualToArray:. Array’s inherited Object equals still means pointer identity, which keeps an Array usable as a Map key or Set member.

↑ Topics

The Enumerable hooks; you normally use for (Object* o in a) rather than calling these directly.

u32 enumLength(void)

Number of elements the for-in driver will visit (== count).

Object* enumAt(u32 i)

The i-th element for the for-in driver (== get).

↑ Topics

Array* copy(void)

A new Array over the same elements. The copy is shallow: the elements are shared, each retained by the new Array so both arrays own their references independently. This is the Copying method.

void dealloc(void)

Releases every element still held, then frees the backing buffer. ARC calls it when the last reference goes away; you do not call it directly.

↑ Topics

#import "Stdio.xc"
#import "Foundation.xc"
i32 main(void)
{
Array* a = new Array();
a.add(Number.with((i32)3));
a.add(Number.with((i32)1));
a.add(Number.with((i32)2));
a.sort(); // elements' own Comparable order
for (Object* o in a) { // Enumerable: for-in
Number* n = (Number* ?)o; // safe-checked downcast
if (n != 0) Stdio.printf("%d ", n.asI16());
}
Stdio.printf("\n");
return 0;
}
1 2 3