Resizable arrays¶
#include <libcork/ds.h>
This section defines a resizable array class, similar to C++’s
std::vector
or Java’s ArrayList
classes. Our arrays can store
any fixed-size element. The arrays automatically resize themselves as
necessary to store the elements that you add.
-
cork_array
(element_type)¶ A resizable array that contains elements of type element_type.
-
void
cork_array_init
(cork_array(T) *array)¶ Initializes a new array. You should allocate array yourself, presumably on the stack or directly within some other data type. The array will start empty.
-
void
cork_array_done
(cork_array(T) *array)¶ Finalizes an array, freeing any storage that was allocated to hold the arrays elements.
-
size_t
cork_array_size
(cork_array(T) *array)¶ Returns the number of elements in array.
-
bool
cork_array_is_empty
(cork_array(T) *array)¶ Returns whether array has any elements.
-
void
cork_array_void
(cork_array(T) *array)¶ Removes all elements from array.
-
T*
cork_array_elements
(cork_array(T) *array)¶ Returns a pointer to the underlying array of elements in array. The elements are guaranteed to be contiguous, just like in a normal C array, but the particular pointer that is returned in not guaranteed to be consistent across function calls that modify the contents of the array.
-
T
cork_array_at
(cork_array(T) *array, size_t index)¶ Returns the element in array at the given index. Like accessing a normal C array, we don’t do any bounds checking. The result is a valid lvalue, so it can be directly assigned to:
cork_array(int64_t) array; cork_array_append(array, 5, err); cork_array_at(array, 0) = 12;
-
void
cork_array_append
(cork_array(T) *array, T element)¶ Appends element to the end of array, reallocating the array’s storage if necessary. If you have an
init
orreset
callback for array, it will be used to initialize the space that was allocated for the new element, and then element will be directly copied into that space (usingmemcpy
or an equivalent). If that is not the right copy behavior for the elements of array, then you should usecork_array_append_get()
instead, and fill in the allocated element directly.
-
T *
cork_array_append_get
(cork_array(T) *array)¶ Appends a new element to the end of array, reallocating the array’s storage if necessary, returning a pointer to the new element.
-
int
cork_array_ensure_size
(cork_array(T) *array, size_t desired_count)¶ Ensures that array has enough allocated space to store desired_count elements, reallocating the array’s storage if needed. The actual size and existing contents of the array aren’t changed.
-
int
cork_array_copy
(cork_array(T) *dest, cork_array(T) *src, cork_copy_f *copy, void *user_data)¶ Copy elements from src to dest. If you provide a copy function, it will be called on each element to perform the copy. If not, we’ll use
memcpy
to bulk-copy the elements.If you’ve provided callbacks for dest, then those callbacks will be called appropriately. We’ll call the
remove
callback for any existing entries (will be overwritten by the copy). We’ll callinit
orreuse
on each element entry before it’s copied.-
typedef int
(*cork_copy_f)
(void *user_data, void *dest, const void *src)¶
-
typedef int
-
size_t
cork_array_element_size
(cork_array(T) *array)¶ Returns the size of the elements that are stored in array. You won’t normally need to call this, since you can just use
sizeof(T)
.
Initializing and finalizing elements¶
You can provide callback functions that will be used to automatically initialize and finalize the elements of a resizable array.
-
void
cork_array_set_init
(cork_array(T) *array, cork_init_f init)¶ -
void
cork_array_set_done
(cork_array(T) *array, cork_done_f done)¶ -
void
cork_array_set_reuse
(cork_array(T) *array, cork_init_f reuse)¶ -
void
cork_array_set_remove
(cork_array(T) *array, cork_done_f remove)¶ -
void
cork_array_set_callback_data
(cork_array(T) *array, void *user_data, cork_free_f free_user_data)¶ Set one of the callback functions for array. There are two pairs of callbacks:
init
anddone
, andreuse
andremove
. Within each pair, one callback is used to initialize an element of the array, while the other is used to finalize it.The
init
callback is used to initialize an element when its array entry is used for the first time. If you then shrink the array (viacork_array_clear()
, for instance), and then append elements again, you will reuse array entries; in this case, thereset
callback is used instead. (Having separateinit
andreuse
callbacks can be useful when the elements are complex objects with deep memory requirements. If you use theinit
callback to allocate that memory, and use thereset
callback to “clear” it, then you can reduce some of the memory allocation overhead.)Similarly, the
remove
callback is used when an element is removed from the array, but the space that the element used isn’t being reclaimed yet. Thedone
callback, on the other hand, is used when the array entry is reclaimed and freed.All of the callbacks take in an additional user_data parameter, in addition to the array entries themselves. You provide that parameter by calling the
cork_array_set_callback_data()
function. If you pass in a free_user_data function, then we will use that function to free the user_data when the array itself is finalized.