Modules

Xar

moduleSource

Available on macOS, Linux, Windows, Wasm

#import "Xar";

A growable array whose elements never move, so pointers to them stay valid while you add more.

Example↗
array: Xar(int, 2, 8);
first := xar_add(*array, 10);
for 1..20 xar_add(*array, it * 10);

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

Procedures#

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

Appends el and returns a pointer to the stored copy, or null if a chunk could not be allocated.

array: Xar(int, 2, 4);
slot := xar_add(*array, 7);
slot.* += 1;
assert(array[0] == 8);
xar_reset(*array);
↗
(array: *Xar)

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

array: Xar(int, 2, 4);
xar_add(*array, 1);
xar_reset(*array);
assert(array.count == 0);
↗
(array: *Xar, iterator: array.Iterator) -> *array.Element_Type

Returns a pointer to the element the iterator is at. Fails an assert when the iterator is past the end.

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

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

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 previous element and returns a pointer to it, or null at the start (the iterator then stays put).

array: Xar(int, 2, 4);
for 1..3 xar_add(*array, it);
iterator := xar_iterator(*array, 2);
assert(xar_prev(*array, *iterator).* == 2);
xar_reset(*array);
↗
(array: *$T/Xar, body: Code, flags: For_Flags)

Makes a Xar work in a for loop: it is the element (a pointer with for *) and it_index its index. Do not add during the loop. Reverse loops are a compile error.

array: Xar(int, 2, 4);
for 1..3 xar_add(*array, it);
total := 0;
for array total += it * it_index;
assert(total == 8);
xar_reset(*array);
↗
(array: $T/Xar, f: (T.Element_Type, T.Element_Type) -> $R)

Sorts in place with a three-way comparator (negative, zero or positive). Despite the name it is an unstable heap sort, O(n log n); it returns nothing and has no key form.

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 sort as quick_sort under another name, so code written for either works.

array: Xar(int, 2, 4);
for value: int.[2, 1] xar_add(*array, value);
quick_sort_simple(array, (a: int, b: int) -> int { return a - b; });
assert(array[0] == 1);
xar_reset(*array);
↗

Types#

XarstructSource
:: struct

Xar(Element_Type, first_chunk_size_shift, max_chunks) stores its elements in separately allocated chunks.

count: s64
chunks: [max_chunks] *Element_Type
allocator: Allocator
array: Xar(string, 3, 4); // chunks of 8, 8, 16, 32
xar_add(*array, "a");
xar_add(*array, "b");
assert(array.count == 2 && array[1] == "b");
xar_reset(*array);
↗