1 /* MIT License 2 * 3 * Copyright (c) 2024 Brad House 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a copy 6 * of this software and associated documentation files (the "Software"), to deal 7 * in the Software without restriction, including without limitation the rights 8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 * copies of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 * 24 * SPDX-License-Identifier: MIT 25 */ 26 #ifndef __ARES__ARRAY_H 27 #define __ARES__ARRAY_H 28 29 #include "ares.h" 30 31 /*! \addtogroup ares_array Array Data Structure 32 * 33 * This is an array with helpers. It is meant to have as little overhead 34 * as possible over direct array management by applications but to provide 35 * safety and some optimization features. It can also return the array in 36 * native form once all manipulation has been performed. 37 * 38 * @{ 39 */ 40 41 struct ares_array; 42 43 /*! Opaque data structure for array */ 44 typedef struct ares_array ares_array_t; 45 46 /*! Callback to free user-defined member data 47 * 48 * \param[in] data pointer to member of array to be destroyed. The pointer 49 * itself must not be destroyed, just the data it contains. 50 */ 51 typedef void (*ares_array_destructor_t)(void *data); 52 53 /*! Callback to compare two array elements used for sorting 54 * 55 * \param[in] data1 array member 1 56 * \param[in] data2 array member 2 57 * \return < 0 if data1 < data2, > 0 if data1 > data2, 0 if data1 == data2 58 */ 59 typedef int (*ares_array_cmp_t)(const void *data1, const void *data2); 60 61 /*! Create an array object 62 * 63 * NOTE: members of the array are typically going to be an going to be a 64 * struct with compiler/ABI specific padding to ensure proper alignment. 65 * Care needs to be taken if using primitive types, especially floating 66 * point numbers which size may not indicate the required alignment. 67 * For example, a double may be 80 bits (10 bytes), but required 68 * alignment of 16 bytes. In such a case, a member_size of 16 would be 69 * required to be used. 70 * 71 * \param[in] destruct Optional. Destructor to call on a removed member 72 * \param[in] member_size Size of array member, usually determined using 73 * sizeof() for the member such as a struct. 74 * 75 * \return array object or NULL on out of memory 76 */ 77 CARES_EXTERN ares_array_t *ares_array_create(size_t member_size, 78 ares_array_destructor_t destruct); 79 80 81 /*! Request the array be at least the requested size. Useful if the desired 82 * array size is known prior to populating the array to prevent reallocations. 83 * 84 * \param[in] arr Initialized array object. 85 * \param[in] size Minimum number of members 86 * \return ARES_SUCCESS on success, ARES_EFORMERR on misuse, 87 * ARES_ENOMEM on out of memory */ 88 CARES_EXTERN ares_status_t ares_array_set_size(ares_array_t *arr, size_t size); 89 90 /*! Sort the array using the given comparison function. This is not 91 * persistent, any future elements inserted will not maintain this sort. 92 * 93 * \param[in] arr Initialized array object. 94 * \param[in] cb Sort callback 95 * \return ARES_SUCCESS on success 96 */ 97 CARES_EXTERN ares_status_t ares_array_sort(ares_array_t *arr, 98 ares_array_cmp_t cmp); 99 100 /*! Destroy an array object. If a destructor is set, will be called on each 101 * member of the array. 102 * 103 * \param[in] arr Initialized array object. 104 */ 105 CARES_EXTERN void ares_array_destroy(ares_array_t *arr); 106 107 /*! Retrieve the array in the native format. This will also destroy the 108 * container. It is the responsibility of the caller to free the returned 109 * pointer and also any data within each array element. 110 * 111 * \param[in] arr Initialized array object 112 * \param[out] num_members the number of members in the returned array 113 * \return pointer to native array on success, NULL on failure. 114 */ 115 CARES_EXTERN void *ares_array_finish(ares_array_t *arr, size_t *num_members); 116 117 /*! Retrieve the number of members in the array 118 * 119 * \param[in] arr Initialized array object. 120 * \return numbrer of members 121 */ 122 CARES_EXTERN size_t ares_array_len(const ares_array_t *arr); 123 124 /*! Insert a new array member at the given index 125 * 126 * \param[out] elem_ptr Optional. Pointer to the returned array element. 127 * \param[in] arr Initialized array object. 128 * \param[in] idx Index in array to place new element, will shift any 129 * elements down that exist after this point. 130 * \return ARES_SUCCESS on success, ARES_EFORMERR on bad index, 131 * ARES_ENOMEM on out of memory. 132 */ 133 CARES_EXTERN ares_status_t ares_array_insert_at(void **elem_ptr, 134 ares_array_t *arr, size_t idx); 135 136 /*! Insert a new array member at the end of the array 137 * 138 * \param[out] elem_ptr Optional. Pointer to the returned array element. 139 * \param[in] arr Initialized array object. 140 * \return ARES_SUCCESS on success, ARES_ENOMEM on out of memory. 141 */ 142 CARES_EXTERN ares_status_t ares_array_insert_last(void **elem_ptr, 143 ares_array_t *arr); 144 145 /*! Insert a new array member at the beginning of the array 146 * 147 * \param[out] elem_ptr Optional. Pointer to the returned array element. 148 * \param[in] arr Initialized array object. 149 * \return ARES_SUCCESS on success, ARES_ENOMEM on out of memory. 150 */ 151 CARES_EXTERN ares_status_t ares_array_insert_first(void **elem_ptr, 152 ares_array_t *arr); 153 154 155 /*! Insert a new array member at the given index and copy the data pointed 156 * to by the data pointer into the array. This will copy member_size bytes 157 * from the provided pointer, this may not be safe for some data types 158 * that may have a smaller size than the provided member_size which includes 159 * padding as discussed in ares_array_create(). 160 * 161 * \param[in] arr Initialized array object. 162 * \param[in] idx Index in array to place new element, will shift any 163 * elements down that exist after this point. 164 * \param[in] data_ptr Pointer to data to copy into array. 165 * \return ARES_SUCCESS on success, ARES_EFORMERR on bad index or null data 166 * ptr, ARES_ENOMEM on out of memory. 167 */ 168 CARES_EXTERN ares_status_t ares_array_insertdata_at(ares_array_t *arr, 169 size_t idx, 170 const void *data_ptr); 171 172 /*! Insert a new array member at the end of the array and copy the data pointed 173 * to by the data pointer into the array. This will copy member_size bytes 174 * from the provided pointer, this may not be safe for some data types 175 * that may have a smaller size than the provided member_size which includes 176 * padding as discussed in ares_array_create(). 177 * 178 * \param[in] arr Initialized array object. 179 * \param[in] data_ptr Pointer to data to copy into array. 180 * \return ARES_SUCCESS on success, ARES_EFORMERR on bad index or null data 181 * ptr, ARES_ENOMEM on out of memory. 182 */ 183 CARES_EXTERN ares_status_t ares_array_insertdata_last(ares_array_t *arr, 184 const void *data_ptr); 185 186 /*! Insert a new array member at the beginning of the array and copy the data 187 * pointed to by the data pointer into the array. This will copy member_size 188 * bytes from the provided pointer, this may not be safe for some data types 189 * that may have a smaller size than the provided member_size which includes 190 * padding as discussed in ares_array_create(). 191 * 192 * \param[in] arr Initialized array object. 193 * \param[in] data_ptr Pointer to data to copy into array. 194 * \return ARES_SUCCESS on success, ARES_EFORMERR on bad index or null data 195 * ptr, ARES_ENOMEM on out of memory. 196 */ 197 CARES_EXTERN ares_status_t ares_array_insertdata_first(ares_array_t *arr, 198 const void *data_ptr); 199 200 /*! Fetch a pointer to the given element in the array 201 * \param[in] array Initialized array object 202 * \param[in] idx Index to fetch 203 * \return pointer on success, NULL on failure */ 204 CARES_EXTERN void *ares_array_at(ares_array_t *arr, size_t idx); 205 206 /*! Fetch a pointer to the first element in the array 207 * \param[in] array Initialized array object 208 * \return pointer on success, NULL on failure */ 209 CARES_EXTERN void *ares_array_first(ares_array_t *arr); 210 211 /*! Fetch a pointer to the last element in the array 212 * \param[in] array Initialized array object 213 * \return pointer on success, NULL on failure */ 214 CARES_EXTERN void *ares_array_last(ares_array_t *arr); 215 216 /*! Fetch a constant pointer to the given element in the array 217 * \param[in] array Initialized array object 218 * \param[in] idx Index to fetch 219 * \return pointer on success, NULL on failure */ 220 CARES_EXTERN const void *ares_array_at_const(const ares_array_t *arr, 221 size_t idx); 222 223 /*! Fetch a constant pointer to the first element in the array 224 * \param[in] array Initialized array object 225 * \return pointer on success, NULL on failure */ 226 CARES_EXTERN const void *ares_array_first_const(const ares_array_t *arr); 227 228 /*! Fetch a constant pointer to the last element in the array 229 * \param[in] array Initialized array object 230 * \return pointer on success, NULL on failure */ 231 CARES_EXTERN const void *ares_array_last_const(const ares_array_t *arr); 232 233 /*! Claim the data from the specified array index, copying it to the buffer 234 * provided by the caller. The index specified in the array will then be 235 * removed (without calling any possible destructor) 236 * 237 * \param[in,out] dest Optional. Buffer to hold array member. Pass NULL 238 * if not needed. This could leak memory if array 239 * member needs destructor if not provided. 240 * \param[in] dest_size Size of buffer provided, used as a sanity check. 241 * Must match member_size provided to 242 * ares_array_create() if dest_size specified. 243 * \param[in] arr Initialized array object 244 * \param[in] idx Index to claim 245 * \return ARES_SUCCESS on success, ARES_EFORMERR on usage failure. 246 */ 247 CARES_EXTERN ares_status_t ares_array_claim_at(void *dest, size_t dest_size, 248 ares_array_t *arr, size_t idx); 249 250 /*! Remove the member at the specified array index. The destructor will be 251 * called. 252 * 253 * \param[in] arr Initialized array object 254 * \param[in] idx Index to remove 255 * \return ARES_SUCCESS if removed, ARES_EFORMERR on invalid use 256 */ 257 CARES_EXTERN ares_status_t ares_array_remove_at(ares_array_t *arr, size_t idx); 258 259 /*! Remove the first member of the array. 260 * 261 * \param[in] arr Initialized array object 262 * \return ARES_SUCCESS if removed, ARES_EFORMERR on invalid use 263 */ 264 CARES_EXTERN ares_status_t ares_array_remove_first(ares_array_t *arr); 265 266 /*! Remove the last member of the array. 267 * 268 * \param[in] arr Initialized array object 269 * \return ARES_SUCCESS if removed, ARES_EFORMERR on invalid use 270 */ 271 CARES_EXTERN ares_status_t ares_array_remove_last(ares_array_t *arr); 272 273 274 /*! @} */ 275 276 #endif /* __ARES__ARRAY_H */ 277