![]() |
ucx
UAP Common Extensions
|
Array list implementation. More...
#include "list.h"Go to the source code of this file.
Data Structures | |
| struct | cx_array_reallocator_s |
| Defines a reallocation mechanism for arrays. More... | |
Macros | |
| #define | CX_ARRAY_DECLARE_SIZED(type, name, size_type) |
| Declares variables for an array that can be used with the convenience macros. | |
| #define | CX_ARRAY_DECLARE(type, name) |
| Declares variables for an array that can be used with the convenience macros. | |
| #define | cx_array_initialize(array, capacity) |
| Initializes an array with the given capacity. | |
| #define | cx_array_initialize_a(allocator, array, capacity) |
| Initializes an array with the given capacity using the specified allocator. | |
| #define | cx_array_simple_copy_a(reallocator, array, index, src, count) |
| Convenience macro that uses cx_array_copy() with a default layout and the specified reallocator. | |
| #define | cx_array_simple_copy(array, index, src, count) |
| Convenience macro that uses cx_array_copy() with a default layout and the default reallocator. | |
| #define | cx_array_simple_reserve_a(reallocator, array, count) |
| Convenience macro that uses cx_array_reserve() with a default layout and the specified reallocator. | |
| #define | cx_array_simple_reserve(array, count) |
| Convenience macro that uses cx_array_reserve() with a default layout and the default reallocator. | |
| #define | cx_array_add(target, size, capacity, elem_size, elem, reallocator) |
| Adds an element to an array with the possibility of allocating more space. | |
| #define | cx_array_simple_add_a(reallocator, array, elem) |
| Convenience macro that uses cx_array_add() with a default layout and the specified reallocator. | |
| #define | cx_array_simple_add(array, elem) |
| Convenience macro that uses cx_array_add() with a default layout and the default reallocator. | |
| #define | cx_array_add_sorted(target, size, capacity, elem_size, elem, cmp_func, reallocator) |
| Inserts an element into a sorted array. | |
| #define | cx_array_simple_add_sorted_a(reallocator, array, elem, cmp_func) |
| Convenience macro for cx_array_add_sorted() with a default layout and the specified reallocator. | |
| #define | cx_array_simple_add_sorted(array, elem, cmp_func) |
| Convenience macro for cx_array_add_sorted() with a default layout and the default reallocator. | |
| #define | cx_array_simple_insert_sorted_a(reallocator, array, src, n, cmp_func) |
| Convenience macro for cx_array_insert_sorted() with a default layout and the specified reallocator. | |
| #define | cx_array_simple_insert_sorted(array, src, n, cmp_func) |
| Convenience macro for cx_array_insert_sorted() with a default layout and the default reallocator. | |
| #define | cx_array_add_unique(target, size, capacity, elem_size, elem, cmp_func, reallocator) |
| Inserts an element into a sorted array if it does not exist. | |
| #define | cx_array_simple_add_unique_a(reallocator, array, elem, cmp_func) |
| Convenience macro for cx_array_add_unique() with a default layout and the specified reallocator. | |
| #define | cx_array_simple_add_unique(array, elem, cmp_func) |
| Convenience macro for cx_array_add_unique() with a default layout and the default reallocator. | |
| #define | cx_array_simple_insert_unique_a(reallocator, array, src, n, cmp_func) |
| Convenience macro for cx_array_insert_unique() with a default layout and the specified reallocator. | |
| #define | cx_array_simple_insert_unique(array, src, n, cmp_func) |
| Convenience macro for cx_array_insert_unique() with a default layout and the default reallocator. | |
| #define | cxArrayListCreateSimple(elem_size, initial_capacity) |
Allocates an array list for storing elements with elem_size bytes each. | |
Typedefs | |
| typedef struct cx_array_reallocator_s | CxArrayReallocator |
| Typedef for the array reallocator struct. | |
Functions | |
| CxArrayReallocator | cx_array_reallocator (const struct cx_allocator_s *allocator, const void *stack_ptr) |
| Creates a new array reallocator. | |
| int | cx_array_reserve (void **array, void *size, void *capacity, unsigned width, size_t elem_size, size_t elem_count, CxArrayReallocator *reallocator) |
| Reserves memory for additional elements. | |
| int | cx_array_copy (void **target, void *size, void *capacity, unsigned width, size_t index, const void *src, size_t elem_size, size_t elem_count, CxArrayReallocator *reallocator) |
| Copies elements from one array to another. | |
| int | cx_array_insert_sorted (void **target, size_t *size, size_t *capacity, cx_compare_func cmp_func, const void *src, size_t elem_size, size_t elem_count, CxArrayReallocator *reallocator) |
| Inserts a sorted array into another sorted array. | |
| int | cx_array_insert_unique (void **target, size_t *size, size_t *capacity, cx_compare_func cmp_func, const void *src, size_t elem_size, size_t elem_count, CxArrayReallocator *reallocator) |
| Inserts a sorted array into another sorted array, avoiding duplicates. | |
| size_t | cx_array_binary_search_inf (const void *arr, size_t size, size_t elem_size, const void *elem, cx_compare_func cmp_func) |
| Searches the largest lower bound in a sorted array. | |
| size_t | cx_array_binary_search (const void *arr, size_t size, size_t elem_size, const void *elem, cx_compare_func cmp_func) |
| Searches an item in a sorted array. | |
| size_t | cx_array_binary_search_sup (const void *arr, size_t size, size_t elem_size, const void *elem, cx_compare_func cmp_func) |
| Searches the smallest upper bound in a sorted array. | |
| void | cx_array_swap (void *arr, size_t elem_size, size_t idx1, size_t idx2) |
| Swaps two array elements. | |
| CxList * | cxArrayListCreate (const CxAllocator *allocator, cx_compare_func comparator, size_t elem_size, size_t initial_capacity) |
Allocates an array list for storing elements with elem_size bytes each. | |
Variables | |
| const unsigned | cx_array_swap_sbo_size |
| The maximum item size in an array list that fits into a stack buffer when swapped. | |
| CxArrayReallocator * | cx_array_default_reallocator |
| A default array reallocator that is based on the cxDefaultAllocator. | |
Array list implementation.
| #define cx_array_add | ( | target, | |
| size, | |||
| capacity, | |||
| elem_size, | |||
| elem, | |||
| reallocator ) |
Adds an element to an array with the possibility of allocating more space.
The element elem is added to the end of the target array which contains size elements, already. The capacity must point to a variable denoting the current maximum number of elements the array can hold.
If the capacity is insufficient to hold the new element, an attempt to increase the capacity is made and the new capacity is written back.
The @ SIZE_TYPE is flexible and can be any unsigned integer type. It is important, however, that size and capacity are pointers to variables of the same type.
| target | (void**) a pointer to the target array |
| size | (SIZE_TYPE*) a pointer to the size of the target array |
| capacity | (SIZE_TYPE*) a pointer to the capacity of the target array |
| elem_size | (size_t) the size of one element |
| elem | (void*) a pointer to the element to add |
| reallocator | (CxArrayReallocator*) the array reallocator to use |
| zero | success |
| non-zero | failure |
| #define cx_array_add_sorted | ( | target, | |
| size, | |||
| capacity, | |||
| elem_size, | |||
| elem, | |||
| cmp_func, | |||
| reallocator ) |
Inserts an element into a sorted array.
If the target array is not already sorted with respect to the specified cmp_func, the behavior is undefined.
If the capacity is not enough to hold the new data, a reallocation attempt is made.
The @ SIZE_TYPE is flexible and can be any unsigned integer type. It is important, however, that size and capacity are pointers to variables of the same type.
| target | (void**) a pointer to the target array |
| size | (SIZE_TYPE*) a pointer to the size of the target array |
| capacity | (SIZE_TYPE*) a pointer to the capacity of the target array |
| elem_size | (size_t) the size of one element |
| elem | (void*) a pointer to the element to add |
| cmp_func | (cx_cmp_func) the compare function for the elements |
| reallocator | (CxArrayReallocator*) the array reallocator to use |
| zero | success |
| non-zero | failure |
| #define cx_array_add_unique | ( | target, | |
| size, | |||
| capacity, | |||
| elem_size, | |||
| elem, | |||
| cmp_func, | |||
| reallocator ) |
Inserts an element into a sorted array if it does not exist.
If the target array is not already sorted with respect to the specified cmp_func, the behavior is undefined.
If the capacity is insufficient to hold the new data, a reallocation attempt is made.
The @ SIZE_TYPE is flexible and can be any unsigned integer type. It is important, however, that size and capacity are pointers to variables of the same type.
| target | (void**) a pointer to the target array |
| size | (SIZE_TYPE*) a pointer to the size of the target array |
| capacity | (SIZE_TYPE*) a pointer to the capacity of the target array |
| elem_size | (size_t) the size of one element |
| elem | (void*) a pointer to the element to add |
| cmp_func | (cx_cmp_func) the compare function for the elements |
| reallocator | (CxArrayReallocator*) the array reallocator to use |
| zero | success (also when the element was already present) |
| non-zero | failure |
| #define CX_ARRAY_DECLARE | ( | type, | |
| name ) |
Declares variables for an array that can be used with the convenience macros.
The size and capacity variables will have type size_t. Use CX_ARRAY_DECLARE_SIZED() to specify a different type.
| type | the type of the data |
| name | the name of the array |
| #define CX_ARRAY_DECLARE_SIZED | ( | type, | |
| name, | |||
| size_type ) |
Declares variables for an array that can be used with the convenience macros.
| type | the type of the data |
| name | the name of the array |
| size_type | the type of the size (should be uint8_t, uint16_t, uint32_t, or size_t) |
| #define cx_array_initialize | ( | array, | |
| capacity ) |
Initializes an array with the given capacity.
The type of the capacity depends on the type used during declaration.
The memory for the array is allocated with the cxDefaultAllocator.
| array | the name of the array |
| capacity | the initial capacity |
| #define cx_array_initialize_a | ( | allocator, | |
| array, | |||
| capacity ) |
Initializes an array with the given capacity using the specified allocator.
| allocator | (CxAllocator*) the allocator |
| array | the name of the array |
| capacity | the initial capacity |
| #define cx_array_simple_add | ( | array, | |
| elem ) |
Convenience macro that uses cx_array_add() with a default layout and the default reallocator.
| array | the name of the array (NOT a pointer or alias to the array) |
| elem | the element to add (NOT a pointer, address is automatically taken) |
| zero | success |
| non-zero | failure |
| #define cx_array_simple_add_a | ( | reallocator, | |
| array, | |||
| elem ) |
Convenience macro that uses cx_array_add() with a default layout and the specified reallocator.
| reallocator | (CxArrayReallocator*) the array reallocator to use |
| array | the name of the array (NOT a pointer or alias to the array) |
| elem | the element to add (NOT a pointer, address is automatically taken) |
| zero | success |
| non-zero | failure |
| #define cx_array_simple_add_sorted | ( | array, | |
| elem, | |||
| cmp_func ) |
Convenience macro for cx_array_add_sorted() with a default layout and the default reallocator.
| array | the name of the array (NOT a pointer or alias to the array) |
| elem | the element to add (NOT a pointer, address is automatically taken) |
| cmp_func | (cx_cmp_func) the compare function for the elements |
| zero | success |
| non-zero | failure |
| #define cx_array_simple_add_sorted_a | ( | reallocator, | |
| array, | |||
| elem, | |||
| cmp_func ) |
Convenience macro for cx_array_add_sorted() with a default layout and the specified reallocator.
| reallocator | (CxArrayReallocator*) the array reallocator to use |
| array | the name of the array (NOT a pointer or alias to the array) |
| elem | the element to add (NOT a pointer, address is automatically taken) |
| cmp_func | (cx_cmp_func) the compare function for the elements |
| zero | success |
| non-zero | failure |
| #define cx_array_simple_add_unique | ( | array, | |
| elem, | |||
| cmp_func ) |
Convenience macro for cx_array_add_unique() with a default layout and the default reallocator.
| array | the name of the array (NOT a pointer or alias to the array) |
| elem | the element to add (NOT a pointer, address is automatically taken) |
| cmp_func | (cx_cmp_func) the compare function for the elements |
| zero | success |
| non-zero | failure |
| #define cx_array_simple_add_unique_a | ( | reallocator, | |
| array, | |||
| elem, | |||
| cmp_func ) |
Convenience macro for cx_array_add_unique() with a default layout and the specified reallocator.
| reallocator | (CxArrayReallocator*) the array reallocator to use |
| array | the name of the array (NOT a pointer or alias to the array) |
| elem | the element to add (NOT a pointer, address is automatically taken) |
| cmp_func | (cx_cmp_func) the compare function for the elements |
| zero | success |
| non-zero | failure |
| #define cx_array_simple_copy | ( | array, | |
| index, | |||
| src, | |||
| count ) |
Convenience macro that uses cx_array_copy() with a default layout and the default reallocator.
| array | the name of the array (NOT a pointer or alias to the array) |
| index | (size_t) the index where the copied elements shall be placed |
| src | (void*) the source array |
| count | (size_t) the number of elements to copy |
| zero | success |
| non-zero | failure |
| #define cx_array_simple_copy_a | ( | reallocator, | |
| array, | |||
| index, | |||
| src, | |||
| count ) |
Convenience macro that uses cx_array_copy() with a default layout and the specified reallocator.
| reallocator | (CxArrayReallocator*) the array reallocator to use |
| array | the name of the array (NOT a pointer or alias to the array) |
| index | (size_t) the index where the copied elements shall be placed |
| src | (void*) the source array |
| count | (size_t) the number of elements to copy |
| zero | success |
| non-zero | failure |
| #define cx_array_simple_insert_sorted | ( | array, | |
| src, | |||
| n, | |||
| cmp_func ) |
Convenience macro for cx_array_insert_sorted() with a default layout and the default reallocator.
| array | the name of the array (NOT a pointer or alias to the array) |
| src | (void*) pointer to the source array |
| n | (size_t) number of elements in the source array |
| cmp_func | (cx_cmp_func) the compare function for the elements |
| zero | success |
| non-zero | failure |
| #define cx_array_simple_insert_sorted_a | ( | reallocator, | |
| array, | |||
| src, | |||
| n, | |||
| cmp_func ) |
Convenience macro for cx_array_insert_sorted() with a default layout and the specified reallocator.
| reallocator | (CxArrayReallocator*) the array reallocator to use |
| array | the name of the array (NOT a pointer or alias to the array) |
| src | (void*) pointer to the source array |
| n | (size_t) number of elements in the source array |
| cmp_func | (cx_cmp_func) the compare function for the elements |
| zero | success |
| non-zero | failure |
| #define cx_array_simple_insert_unique | ( | array, | |
| src, | |||
| n, | |||
| cmp_func ) |
Convenience macro for cx_array_insert_unique() with a default layout and the default reallocator.
| array | the name of the array (NOT a pointer or alias to the array) |
| src | (void*) pointer to the source array |
| n | (size_t) number of elements in the source array |
| cmp_func | (cx_cmp_func) the compare function for the elements |
| zero | success |
| non-zero | failure |
| #define cx_array_simple_insert_unique_a | ( | reallocator, | |
| array, | |||
| src, | |||
| n, | |||
| cmp_func ) |
Convenience macro for cx_array_insert_unique() with a default layout and the specified reallocator.
| reallocator | (CxArrayReallocator*) the array reallocator to use |
| array | the name of the array (NOT a pointer or alias to the array) |
| src | (void*) pointer to the source array |
| n | (size_t) number of elements in the source array |
| cmp_func | (cx_cmp_func) the compare function for the elements |
| zero | success |
| non-zero | failure |
| #define cx_array_simple_reserve | ( | array, | |
| count ) |
Convenience macro that uses cx_array_reserve() with a default layout and the default reallocator.
| array | the name of the array (NOT a pointer or alias to the array) |
| count | (size_t) the number of expected additional elements |
| zero | success |
| non-zero | failure |
| #define cx_array_simple_reserve_a | ( | reallocator, | |
| array, | |||
| count ) |
Convenience macro that uses cx_array_reserve() with a default layout and the specified reallocator.
| reallocator | (CxArrayReallocator*) the array reallocator to use |
| array | the name of the array (NOT a pointer or alias to the array) |
| count | (size_t) the number of expected additional elements |
| zero | success |
| non-zero | failure |
| #define cxArrayListCreateSimple | ( | elem_size, | |
| initial_capacity ) |
Allocates an array list for storing elements with elem_size bytes each.
The list will use the cxDefaultAllocator and NO compare function. If you want to call functions that need a compare function, you have to set it immediately after creation or use cxArrayListCreate().
If elem_size is CX_STORE_POINTERS, the created list stores pointers instead of copies of the added elements and the compare function will be automatically set to cx_cmp_ptr().
| elem_size | (size_t) the size of each element in bytes |
| initial_capacity | (size_t) the initial number of elements the array can store |
| size_t cx_array_binary_search | ( | const void * | arr, |
| size_t | size, | ||
| size_t | elem_size, | ||
| const void * | elem, | ||
| cx_compare_func | cmp_func ) |
Searches an item in a sorted array.
When such an element exists more than once, the largest index of all those elements is returned.
If the array is not sorted with respect to the cmp_func, the behavior is undefined.
| arr | the array to search |
| size | the size of the array |
| elem_size | the size of one element |
| elem | the element to find |
| cmp_func | the compare function |
size if the element cannot be found | size_t cx_array_binary_search_inf | ( | const void * | arr, |
| size_t | size, | ||
| size_t | elem_size, | ||
| const void * | elem, | ||
| cx_compare_func | cmp_func ) |
Searches the largest lower bound in a sorted array.
In other words, this function returns the index of the largest element in arr that is less or equal to elem with respect to cmp_func. When no such element exists, size is returned.
When such an element exists more than once, the largest index of all those elements is returned.
If elem is contained in the array, this is identical to cx_array_binary_search().
If the array is not sorted with respect to the cmp_func, the behavior is undefined.
| arr | the array to search |
| size | the size of the array |
| elem_size | the size of one element |
| elem | the element to find |
| cmp_func | the compare function |
size | size_t cx_array_binary_search_sup | ( | const void * | arr, |
| size_t | size, | ||
| size_t | elem_size, | ||
| const void * | elem, | ||
| cx_compare_func | cmp_func ) |
Searches the smallest upper bound in a sorted array.
In other words, this function returns the index of the smallest element in arr that is greater or equal to elem with respect to cmp_func. When no such element exists, size is returned.
When such an element exists more than once, the smallest index of all those elements is returned.
If elem is contained in the array, this is identical to cx_array_binary_search().
If the array is not sorted with respect to the cmp_func, the behavior is undefined.
| arr | the array to search |
| size | the size of the array |
| elem_size | the size of one element |
| elem | the element to find |
| cmp_func | the compare function |
size | int cx_array_copy | ( | void ** | target, |
| void * | size, | ||
| void * | capacity, | ||
| unsigned | width, | ||
| size_t | index, | ||
| const void * | src, | ||
| size_t | elem_size, | ||
| size_t | elem_count, | ||
| CxArrayReallocator * | reallocator ) |
Copies elements from one array to another.
The elements are copied to the target array at the specified index, overwriting possible elements. The index does not need to be in range of the current array size. If the new index plus the number of elements added extends the array's size, the remaining capacity is used.
If the capacity is also insufficient to hold the new data, a reallocation attempt is made with the specified reallocator. You can create your own reallocator by hand, use cx_array_default_reallocator, or use the convenience function cx_array_reallocator() to create a custom reallocator.
The width in bytes refers to the size and capacity. Both must have the same width. Supported are 0, 1, 2, and 4, as well as 8 if running on a 64-bit architecture. If set to zero, the native word width is used.
| target | a pointer to the target array |
| size | a pointer to the size of the target array |
| capacity | a pointer to the capacity of the target array |
| width | the width in bytes for the size and capacity or zero for default |
| index | the index where the copied elements shall be placed |
| src | the source array |
| elem_size | the size of one element |
| elem_count | the number of elements to copy |
| reallocator | the array reallocator to use (NULL defaults to cx_array_default_reallocator) |
| zero | success |
| non-zero | failure |
| int cx_array_insert_sorted | ( | void ** | target, |
| size_t * | size, | ||
| size_t * | capacity, | ||
| cx_compare_func | cmp_func, | ||
| const void * | src, | ||
| size_t | elem_size, | ||
| size_t | elem_count, | ||
| CxArrayReallocator * | reallocator ) |
Inserts a sorted array into another sorted array.
If either the target or the source array is not already sorted with respect to the specified cmp_func, the behavior is undefined.
If the capacity is insufficient to hold the new data, a reallocation attempt is made. You can create your own reallocator by hand, use cx_array_default_reallocator, or use the convenience function cx_array_reallocator() to create a custom reallocator.
| target | a pointer to the target array |
| size | a pointer to the size of the target array |
| capacity | a pointer to the capacity of the target array |
| cmp_func | the compare function for the elements |
| src | the source array |
| elem_size | the size of one element |
| elem_count | the number of elements to insert |
| reallocator | the array reallocator to use (NULL defaults to cx_array_default_reallocator) |
| zero | success |
| non-zero | failure |
| int cx_array_insert_unique | ( | void ** | target, |
| size_t * | size, | ||
| size_t * | capacity, | ||
| cx_compare_func | cmp_func, | ||
| const void * | src, | ||
| size_t | elem_size, | ||
| size_t | elem_count, | ||
| CxArrayReallocator * | reallocator ) |
Inserts a sorted array into another sorted array, avoiding duplicates.
If either the target or the source array is not already sorted with respect to the specified cmp_func, the behavior is undefined.
If the capacity is insufficient to hold the new data, a reallocation attempt is made. You can create your own reallocator by hand, use cx_array_default_reallocator, or use the convenience function cx_array_reallocator() to create a custom reallocator.
| target | a pointer to the target array |
| size | a pointer to the size of the target array |
| capacity | a pointer to the capacity of the target array |
| cmp_func | the compare function for the elements |
| src | the source array |
| elem_size | the size of one element |
| elem_count | the number of elements to insert |
| reallocator | the array reallocator to use (NULL defaults to cx_array_default_reallocator) |
| zero | success |
| non-zero | failure |
| CxArrayReallocator cx_array_reallocator | ( | const struct cx_allocator_s * | allocator, |
| const void * | stack_ptr ) |
Creates a new array reallocator.
When allocator is NULL, the cxDefaultAllocator will be used.
When stack_ptr is not NULL, the reallocator is supposed to be used only for the specific array initially located at stack_ptr. When reallocation is needed, the reallocator checks if the array is still located at stack_ptr and copies the contents to the heap.
NULL will return a reallocator that behaves like cx_array_default_reallocator.| allocator | the allocator this reallocator shall be based on |
| stack_ptr | the address of the array when the array is initially located on the stack or shall not reallocate in place |
| int cx_array_reserve | ( | void ** | array, |
| void * | size, | ||
| void * | capacity, | ||
| unsigned | width, | ||
| size_t | elem_size, | ||
| size_t | elem_count, | ||
| CxArrayReallocator * | reallocator ) |
Reserves memory for additional elements.
This function checks if the capacity of the array is sufficient to hold at least size plus elem_count elements. If not, a reallocation is performed with the specified reallocator. You can create your own reallocator by hand, use cx_array_default_reallocator, or use the convenience function cx_array_reallocator() to create a custom reallocator.
This function can be useful to replace subsequent calls to cx_array_copy() with one single cx_array_reserve() and then - after guaranteeing a sufficient capacity - use simple memmove() or memcpy().
The width in bytes refers to the size and capacity. Both must have the same width. Supported are 0, 1, 2, and 4, as well as 8 if running on a 64-bit architecture. If set to zero, the native word width is used.
| array | a pointer to the target array |
| size | a pointer to the size of the array |
| capacity | a pointer to the capacity of the array |
| width | the width in bytes for the size and capacity or zero for default |
| elem_size | the size of one element |
| elem_count | the number of expected additional elements |
| reallocator | the array reallocator to use (NULL defaults to cx_array_default_reallocator) |
| zero | success |
| non-zero | failure |
| void cx_array_swap | ( | void * | arr, |
| size_t | elem_size, | ||
| size_t | idx1, | ||
| size_t | idx2 ) |
Swaps two array elements.
| arr | the array |
| elem_size | the element size |
| idx1 | index of the first element |
| idx2 | index of the second element |
| CxList * cxArrayListCreate | ( | const CxAllocator * | allocator, |
| cx_compare_func | comparator, | ||
| size_t | elem_size, | ||
| size_t | initial_capacity ) |
Allocates an array list for storing elements with elem_size bytes each.
If elem_size is CX_STORE_POINTERS, the created list stores pointers instead of copies of the added elements, and the compare function will be automatically set to cx_cmp_ptr(), if none is given.
| allocator | the allocator for allocating the list memory (if NULL, the cxDefaultAllocator will be used) |
| comparator | the comparator for the elements (if NULL, and the list is not storing pointers, sort and find functions will not work) |
| elem_size | the size of each element in bytes |
| initial_capacity | the initial number of elements the array can store |