• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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