Modules

Xar

moduleSource
macOSLinuxWindowswasm

#import "Xar";

A growable array that allocates in chunks, so its elements never move.

Procedures#

(array: *Xar, el: array.Element_Type) -> *array.Element_Type

Appends el and returns a pointer to the stored copy, which stays valid until xar_reset. Returns null if a chunk could not be allocated.

(array: *Xar, index: int)

Removes element index by copying the last element over it and shrinking the count. The order changes and no memory is freed.

array: Xar(int, 2, 4);
for 1..4 xar_add(*array, it);
xar_unordered_remove(*array, 0);
assert(array.count == 3 && array[0] == 4);
xar_reset(*array);
↗
(array: *Xar)

Frees every chunk and empties the array, so it can be used again. All pointers into it are invalid afterwards. The elements are not destroyed first.

(array: *Xar, index: int) -> array.Iterator

An iterator positioned at element index, for walking with xar_get, xar_next and xar_prev; cheaper than indexing each step.

(array: *Xar, iterator: array.Iterator) -> *array.Element_Type

A pointer to the element an iterator is at. Fails an assert when the iterator is past the end or was never positioned.

(array: *Xar, iterator: *array.Iterator) -> *array.Element_Type

Moves the iterator to the following element and returns a pointer to it, or null at the end (the iterator then stays where it was).

array: Xar(int, 1, 4);
for 1..5 xar_add(*array, it);

iterator := xar_iterator(*array, 0);
sum := xar_get(*array, iterator).*;
while true {
    element := xar_next(*array, *iterator);
    if !element break;
    sum += element.*;
}

assert(sum == 15);
xar_reset(*array);
↗
(array: *Xar, iterator: *array.Iterator) -> *array.Element_Type

Moves the iterator to the preceding element and returns a pointer to it, or null at the start (the iterator then stays where it was).

(array: *$T/Xar, body: Code, flags: For_Flags)

Lets a Xar be used in a for loop over its elements in order: it is the element (a pointer with for *) and it_index its index.

(array: $T/Xar, f: (T.Element_Type, T.Element_Type) -> $R)

Sorts a Xar in place with a three-way comparator (negative, zero or positive). Despite the name it is a heap sort, not a quicksort.

array: Xar(int, 2, 4);
for value: int.[3, 1, 2] xar_add(*array, value);
quick_sort(array, (a: int, b: int) -> int { return a - b; });
assert(array[0] == 1 && array[2] == 3);
xar_reset(*array);
↗
(array: $T/Xar, f: (T.Element_Type, T.Element_Type) -> $R)

The same heap sort as quick_sort (unstable, O(n log n)); the name is kept so that code written for either works.

(array: $T/Xar, f: (T.Element_Type, T.Element_Type) -> $R)

The same heap sort as quick_sort (unstable, O(n log n)); the name is kept so that code written for either works.

Types#

Xarstruct
:: struct

Xar(Element_Type, first_chunk_size_shift, max_chunks): a growable array whose elements never move.

array: Xar(int, 2, 8); // chunks of 4, 4, 8, 16, ...
first := xar_add(*array, 10);
for 1..20 xar_add(*array, it * 10);

assert(array.count == 21 && first.* == 10 && first == *array[0]);
assert(array[5] == 50);
xar_reset(*array);
↗