Files
bluelib/object/include/blue/object/array.h
2024-11-14 16:56:18 +00:00

305 lines
11 KiB
C

#ifndef BLUELIB_ARRAY_H_
#define BLUELIB_ARRAY_H_
#include <blue/core/iterator.h>
#include <blue/core/misc.h>
#include <blue/core/status.h>
#include <blue/object/object.h>
#include <blue/object/type.h>
/**
* Cast a generic b_object pointer to an b_array pointer.
*/
#define B_ARRAY(p) ((b_array *)(p))
/**
* Iterate through each object in an b_array.
*
* This should be used for read-only iterations only. Adding or removing objects
* while iterating though an array using b_array_foreach is NOT supported.
*
* @param it A pointer to an b_array_iterator. This iterator will contain the
* current object reference for the current loop iteration.
* @param array A pointer to the b_array to iterate over.
*/
#define b_array_foreach(it, array) \
for (int z__b_unique_name() = b_array_iterator_begin(array, it); \
(it)->value != NULL; b_array_iterator_next(it))
#ifdef __cplusplus
extern "C" {
#endif
/**
* A heterogeneous array of objects. b_array only stores references
* to the objects that it contains, not the object data itself.
*
* b_array stores pointers to objects in a single contiguous array,
* but this is an implementation detail that may change in the future.
* Users of b_array should not rely on this being the case.
*/
typedef struct b_array b_array;
/**
* Iterator for traversing the contents of an b_array.
*
* The iterator provides the current b_object `value`, as well
* as the index `i` of that value within the array.
*
* Any members whose names begin with _ (underscore) are reserved
* and should not be accessed.
*/
typedef struct b_array_iterator {
b_iterator _base;
b_array *_a;
/** The index of the current value */
size_t i;
/** The current value */
b_object *value;
} b_array_iterator;
/**
* Creates an empty b_array.
*
* @return A pointer to the new array, or NULL if an error occurred.
*/
BLUE_API b_array *b_array_create(void);
/**
* Creates an b_array initialised with the contents of the provided b_object
* pointer array. The b_array will take a reference to each object specified in
* `values`, and will increment the reference count. The order of objects in the
* new b_array will be the same as the order of objects in `values`. Any NULL
* pointers in the `values` array will be ignored, and will not result in gaps
* in the created b_array. However, `nr_values` should be large enough to cover
* the final non-NULL pointer in `values`, including any NULL pointers
* in-between.
*
* @param values The list of object pointers which should make up the contents
* of the new b_array.
* @param nr_values The size of the `values` array.
* @return A pointer to the new b_array, or NULL if an error occurred.
*/
BLUE_API b_array *b_array_create_with_values(
b_object *const *values, size_t nr_values);
/**
* Increment the reference counter of an b_array.
*
* @param array The b_array to reference.
* @return The b_array pointer that was passed to the function.
*/
static inline b_array *b_array_retain(b_array *array)
{
return B_ARRAY(b_retain(B_OBJECT(array)));
}
/**
* Decrement the reference counter of an b_array, destroying the array if it reaches zero.
* @param array The b_array reference to release.
*/
static inline void b_array_release(b_array *array)
{
b_release(B_OBJECT(array));
}
/**
* Remove all object references from an b_array, resetting the size of the array to zero.
* The reference counts of all objects in the array will be decremented.
*
* @param array The b_array to clear.
*/
BLUE_API void b_array_clear(b_array *array);
/**
* Inserts an object at the end of an b_array. The reference count of the object
* will be incremented.
*
* @param array The b_array to append the object to.
* @param value The object to append.
* @return B_SUCCESS if the object was appended successfully, or an error code if an error occurred.
*/
BLUE_API b_status b_array_append(b_array *array, b_object *value);
/**
* Inserts an object at the beginning of an b_array. The reference count of the object
* will be incremented. All other objects in the array will be moved to make space
* for the object being pre-pended.
*
* @param array The b_array to prepend the object to.
* @param value The object to prepend.
* @return B_SUCCESS if the object was prepended successfully, or an error code if an error occurred.
*/
BLUE_API b_status b_array_prepend(b_array *array, b_object *value);
/**
* Inserts an object into an b_array at a given index. The reference count of the object
* will be incremented. If the specified index is at the beginning or mid-way through
* the array (i.e. not at the end), some or all of the objects already in the array will
* be moved to make space for the object being inserted.
*
* @param array The b_array to insert the object into.
* @param value The object to insert.
* @param at The index to insert the object at. If the index is `B_NPOS`, the object will
* be inserted at the end of the b_array.
* @return B_SUCCESS if the object was inserted, or a status code describing any error that occurred.
*/
BLUE_API b_status b_array_insert(b_array *array, b_object *value, size_t at);
/**
* Removes the object at the specified index from an b_array. The reference count
* of the removed object will be decremented. If the specified index is at the beginning
* or mid-way through the array (i.e. not at the end), the remaining objects will be moved
* to fill the empty space created by the object's removal.
*
* @param array The b_array to remove the object from.
* @param at The index of the object to be removed.
* @return B_SUCCESS if the object was removed, or a status code describing any error that occurred.
*/
BLUE_API b_status b_array_remove(b_array *array, size_t at);
/**
* Removes the object at the beginning of an b_array. The reference count
* of the removed object will be decremented. The remaining objects will be moved
* to fill the empty space created by the object's removal.
*
* @param array The b_array to remove the object from.
* @return B_SUCCESS if the object was removed, or a status code describing any error that occurred.
*/
BLUE_API b_status b_array_remove_front(b_array *array);
/**
* Removes the object at the end of an b_array. The reference count
* of the removed object will be decremented.
*
* @param array The b_array to remove the object from.
* @return B_SUCCESS if the object was removed, or a status code describing any error that occurred.
*/
BLUE_API b_status b_array_remove_back(b_array *array);
/**
* Removes the object at the specified index of an b_array, and returns a
* pointer to it. The reference count of the removed object will NOT be
* decremented. The caller becomes the owner of the array's reference to the
* object. If the specified index is at the beginning or mid-way through the
* array (i.e. not at the end), the remaining objects will be moved to fill the
* empty space created by the object's removal.
*
* @param array The b_array to remove the object from.
* @param at The index of the object to be removed.
* @return An pointer to the removed object. This pointer is owned by the
* caller. Returns NULL if an error occurred.
*/
BLUE_API b_object *b_array_pop(b_array *array, size_t at);
/**
* Removes the object at the beginning of an b_array, and returns a pointer to
* it. The reference count of the removed object will NOT be decremented. The
* caller becomes the owner of the array's reference to the object. The
* remaining objects in the b_array will be moved to fill the empty space left
* by the removed object.
*
* @param array The b_array to remove the object from.
* @return An pointer to the removed object. This pointer is owned by the
* caller. Returns NULL if an error occurred.
*/
BLUE_API b_object *b_array_pop_front(b_array *array);
/**
* Removes the object at the end of an b_array, and returns a pointer to it. The
* reference count of the removed object will NOT be decremented. The caller
* becomes the owner of the array's reference to the object.
*
* @param array The b_array to remove the object from.
* @return An pointer to the removed object. This pointer is owned by the
* caller. Returns NULL if an error occurred.
*/
BLUE_API b_object *b_array_pop_back(b_array *array);
/**
* Returns an unowned pointer to the object at the given index of an b_array.
* The caller does not own the returned pointer, and MUST NOT release it.
*
* @param array The b_array.
* @param at The index of the object to return.
* @return A pointer to the object at the given index. This pointer is NOT owned
* by the caller. Returns NULL if an error occurred.
*/
BLUE_API b_object *b_array_at(const b_array *array, size_t at);
/**
* Returns an owned pointer to the object at the given index of an b_array. The caller owns
* the returned pointer, and must release it when they are finished with it.
*
* @param array The b_array.
* @param at The index of the object to return.
* @return A pointer to the object at the given index. This pointer is owned by the caller.
* Returns NULL if an error occurred.
*/
BLUE_API b_object *b_array_get(b_array *array, size_t at);
/**
* Returns the number of objects contained in an b_array.
*
* @param array The b_array.
* @return The number of objects contained in the b_array.
*/
BLUE_API size_t b_array_size(const b_array *array);
/**
* Returns the current maximum capacity of an b_array. This represents the
* number of objects that can be stored in an b_array before its internal buffer
* would need to be re-sized.
*
* @param array The b_array.
* @return The maximum capacity of the b_array.
*/
BLUE_API size_t b_array_capacity(const b_array *array);
/**
* Initialise an b_array_iterator to pointer to the first object in an b_array.
* If the b_array is empty, then `it` will be an invalid iterator.
*
* @param array
* @param it
* @return Always returns 0.
*/
BLUE_API int b_array_iterator_begin(b_array *array, b_array_iterator *it);
/**
* Advances an b_array_iterator to pointer to the next object in an b_array.
* @param it The iterator to advance.
* @return True if the iterator contains a valid reference to an object, or
* False if the iterator has gone past the end of the array.
*/
BLUE_API bool b_array_iterator_next(b_array_iterator *it);
/**
* Removes the object pointed to by an b_array_iterator from its container
* b_array, and advances the iterator to the next object in the b_array.
*
* The reference count of the removed object will be decremented.
*
* @param it The iterator whose object should be removed.
* @return B_SUCCESS if the object was removed, or a status code describing the error that occurred.
*/
BLUE_API b_status b_array_iterator_erase(b_array_iterator *it);
/**
* Checks whether or not an iterator contains a valid reference to an object.
* An iterator will become invalid if it has moved past the end of the b_array
* it was iterating across, or if b_array_iterator_erase() was called on an
* iterator pointing to the last object in an b_array.
*
* @param it The iterator to check.
* @return True if the iterator is valid. False otherwise.
*/
BLUE_API bool b_array_iterator_is_valid(const b_array_iterator *it);
#ifdef __cplusplus
}
#endif
#endif