/* REF ARRAY Header file for of the dynamic array with reference count. Copyright (C) Dmitri Pal 2009 This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef REF_ARRAY_H #define REF_ARRAY_H #include #include struct ref_array; #ifndef EOK #define EOK 0 #endif /** @mainpage The Referenced Array Interface * * The referenced array interface is a dynamically allocated * array of data of any type. The array can be shared by * multiple objects to avoid data duplication. * * The array is created once and then any number of * the references can be requested. The references are pointers * to the array. Each reference must be freed after use. * Freeing last reference to the array would free the array's storage. * * The array does not have any knowledge of the data type * of the actual data stored in the array. All elements of the array * are of the same size as prescribed by caller when the array is created. * The caller can potentially mix different types of data in the array * but this should be done with caution. * * At the moment the interface is not complete. * It provides basic functionality required to support other * components. In future it might make sense to add entry points * to insert and delete elements from the array. * Current use cases do not require this kind of * functionality so it is left out of the implementation. * */ /** * @defgroup ref_array Interface * @{ */ /** * @brief Enumeration of the delete modes * * When the array is destroyed each element of the array * most likely needs to be freed. Same is true when an element * is removed from the array. However the caller might need * to do different things with the data depending on whether * the array is destroyed or whether the element is removed. * This enumeration defines constants that you used to indicate * which operation was performed. */ typedef enum { REF_ARRAY_DESTROY, REF_ARRAY_DELETE, } ref_array_del_enum; /** * @brief Element cleanup callback * * Callback that can be provided by a caller * to free data when the storage is actually destroyed. * * @param[in] elem Pointer to the array element. * @param[in] type Type of the operation performed. * @param[in] data Application data that can be used * inside the callback. * No return value. */ typedef void (*ref_array_fn)(void *elem, ref_array_del_enum type, void *data); /** * @brief Copy callback * * Callback that can be provided by a caller * to copy elements of the array. * * @param[in] elem Pointer to the array element. * @param[out] new_elem Pointer to pointer to the new element. * * @return 0 - Success. * @return ENOMEM - No memory. * @return EINVAL - Invalid argument. * * Callback can return other errors and the implementor's discretion. */ typedef int (*ref_array_copy_cb)(void *elem, void *new_elem); /** * @brief Create referenced array * * @param[out] ra Newly created array object. * @param[in] elem Element size in bytes. * @param[in] grow_by Defines how many elements * should be allocated together * as one chunk. * @param[in] cb Cleanup callback. * @param[in] data Caller supplied data * passed to cleanup callback. * * @return 0 - Success. * @return ENOMEM - No memory. * @return EINVAL - Invalid argument. */ int ref_array_create(struct ref_array **ra, size_t elem, uint32_t grow_by, ref_array_fn cb, void *data); /** * @brief Get new reference to an array * * @param[in] ra Existing array object. * * @return A new reference to an array object. * @return NULL - Invalid argument. */ struct ref_array *ref_array_getref(struct ref_array *ra); /** * @brief Delete the array * * @param[in] ra Existing array object * or a reference. * */ void ref_array_destroy(struct ref_array *ra); /** * @brief Add new element to the array * * Appends an element to the end of the array. * * @param[in] ra Existing array object. * @param[in] element Pointer to data. * The number of bytes * defined at the array creation * as the array size will be copied * into the array element. * * @return 0 - Success. * @return ENOMEM - No memory. * @return EINVAL - Invalid argument. */ int ref_array_append(struct ref_array *ra, void *element); /** * @brief Get element data * * Retrieves data from the array element. * * @param[in] ra Existing array object. * @param[in] idx Index of the array element. * @param[in] acptr Pointer to the memory * where the element's data * will be copied. Can be NULL. * In this case nothing is copied. * * @return Pointer to the data stored in the element. * Conventionally it should be a const pointer, * however such declaration would make using * variable that receives the result of this * function immutable. This is very inconvenient * because such variable should be able to * point to data related to multiple elements * of the array. * * @return Pointer to the element's data. * @return NULL if index is out of range. */ void *ref_array_get(struct ref_array *ra, uint32_t idx, void *acptr); /** * @brief Get array length * * Determines length of the array. * * @param[in] ra Existing array object. * @param[out] len Variable will receive * the length of the array. * * @return 0 - Success. * @return EINVAL - Invalid argument. */ int ref_array_getlen(struct ref_array *ra, uint32_t *len); /** * @brief Array length * * Alternative function to get length. * * @param[in] ra Existing array object. * * @return Length of the array. Returns 0 if the array is invalid. */ uint32_t ref_array_len(struct ref_array *ra); /** * @brief Insert a new element into the array * * Inserts an element into the array. * If idx is 0 the element will be added * to the beginning of the array, * if idx is 1 the element will be added * after the first element of the array * and so on. * If index is greater than the number of * elements in the array the function * returns error. * * @param[in] ra Existing array object. * @param[in] idx Index of the array element. * @param[in] element Pointer to data. * The number of bytes * defined at the array creation * as the array size will be copied * into the array element. * * @return 0 - Success. * @return ENOMEM - No memory. * @return EINVAL - Invalid argument. * @return ERANGE - Index is our of range. */ int ref_array_insert(struct ref_array *ra, uint32_t idx, void *element); /** * @brief Replace element in the array * * Replace an element of the array * identified by index with a new value. * If index is greater than the number of * elements in the array the function * returns error. * * @param[in] ra Existing array object. * @param[in] idx Index of the array element. * @param[in] element Pointer to data. * The number of bytes * defined at the array creation * as the array size will be copied * into the array element. * * @return 0 - Success. * @return ENOMEM - No memory. * @return EINVAL - Invalid argument. * @return ERANGE - Index is our of range. */ int ref_array_replace(struct ref_array *ra, uint32_t idx, void *element); /** * @brief Remove element from the array * * The element is removed and the length * is decreased by 1. * If index is greater than the number of * elements in the array the function * returns error. * * @param[in] ra Existing array object. * @param[in] idx Index of the array element. * * @return 0 - Success. * @return EINVAL - Invalid argument. * @return ERANGE - Index is our of range. */ int ref_array_remove(struct ref_array *ra, uint32_t idx); /** * @brief Swap two elements in the array * * If any of the indexes is greater than * the number of elements in the array * the function returns error. * * @param[in] ra Existing array object. * @param[in] idx1 Index of the array element. * @param[in] idx2 Index of the array element. * * @return 0 - Success. * @return EINVAL - Invalid argument. * @return ERANGE - Index is our of range. * @return ENOMEM - No memory. */ int ref_array_swap(struct ref_array *ra, uint32_t idx1, uint32_t idx2); /** * @brief Reset array * * Function clears all contents without destroying * the object. The delete callback will be called * for every element of the array from the beginning * to the end passing in REF_ARRAY_DESTROY value. * All the storage for the array will be deallocated. * After the call the array will be empty as if just created. * * * @param[in] ra Existing array object. * No return value. * */ void ref_array_reset(struct ref_array *ra); /** * @brief Copy array * * Function copies all contents calling a provided * callback for every entry of the array. * * * @param[in] ra Existing array object to copy. * @param[in] copy_cb Copy callback. * @param[in] cb Cleanup callback, will be used * to clean data in the array copy. * @param[in] data Caller supplied data * passed to cleanup callback. * @param[out] copy_ra Newly allocated copy. * * @return 0 - Success. * @return ENOMEM - No memory. * @return EINVAL - Invalid argument. */ int ref_array_copy(struct ref_array *ra, ref_array_copy_cb copy_cb, ref_array_fn cb, void *data, struct ref_array **copy_ra); /** * @} */ #endif