add existing code (build system, libs, initial mizucp code)
[mizunara.git] / ucx / ucx / array.h
1 /*
2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3  *
4  * Copyright 2019 Mike Becker, Olaf Wintermann All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  *   1. Redistributions of source code must retain the above copyright
10  *      notice, this list of conditions and the following disclaimer.
11  *
12  *   2. Redistributions in binary form must reproduce the above copyright
13  *      notice, this list of conditions and the following disclaimer in the
14  *      documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 /**
29  * Dynamically allocated array implementation.
30  * 
31  * @file   array.h
32  * @author Mike Becker
33  * @author Olaf Wintermann
34  */
35
36 #ifndef UCX_ARRAY_H
37 #define UCX_ARRAY_H
38
39 #include "ucx.h"
40 #include "allocator.h"
41
42 #ifdef  __cplusplus
43 extern "C" {
44 #endif
45
46 /**
47  * UCX array type.
48  */
49 typedef struct {
50     /**
51      * The current capacity of the array.
52      */
53     size_t capacity;
54     /**
55      * The actual number of elements in the array.
56      */
57     size_t size;
58     /**
59      * The size of an individual element in bytes.
60      */
61     size_t elemsize;
62     /**
63      * A pointer to the data.
64      */
65     void* data;
66     /**
67      * The allocator used for the data.
68      */
69     UcxAllocator* allocator;
70 } UcxArray;
71
72 /**
73  * Sets an element in an arbitrary user defined array.
74  * The data is copied from the specified data location.
75  * 
76  * If the capacity is insufficient, the array is automatically reallocated and
77  * the possibly new pointer is stored in the <code>array</code> argument.
78  * 
79  * On reallocation the capacity of the array is doubled until it is sufficient.
80  * The new capacity is stored back to <code>capacity</code>.
81  *  
82  * @param array a pointer to location of the array pointer
83  * @param capacity a pointer to the capacity
84  * @param elmsize the size of each element
85  * @param idx the index of the element to set
86  * @param data a pointer to the element data
87  * @return zero on success or non-zero on error (errno will be set)
88  */
89 #define ucx_array_util_set(array, capacity, elmsize, idx, data) \
90     ucx_array_util_set_a(ucx_default_allocator(), (void**)(array), capacity, \
91                          elmsize, idx, data)
92
93 /**
94  * Sets an element in an arbitrary user defined array.
95  * The data is copied from the specified data location.
96  * 
97  * If the capacity is insufficient, the array is automatically reallocated
98  * using the specified allocator and the possibly new pointer is stored in
99  * the <code>array</code> argument.
100  * 
101  * On reallocation the capacity of the array is doubled until it is sufficient.
102  * The new capacity is stored back to <code>capacity</code>. 
103  * 
104  * @param alloc the allocator that shall be used to reallocate the array
105  * @param array a pointer to location of the array pointer
106  * @param capacity a pointer to the capacity
107  * @param elmsize the size of each element
108  * @param idx the index of the element to set
109  * @param data a pointer to the element data
110  * @return zero on success or non-zero on error (errno will be set)
111  */
112 int ucx_array_util_set_a(UcxAllocator* alloc, void** array, size_t* capacity,
113     size_t elmsize, size_t idx, void* data);
114
115 /**
116  * Stores a pointer in an arbitrary user defined array.
117  * The element size of the array must be sizeof(void*).
118  * 
119  * If the capacity is insufficient, the array is automatically reallocated and
120  * the possibly new pointer is stored in the <code>array</code> argument.
121  * 
122  * On reallocation the capacity of the array is doubled until it is sufficient.
123  * The new capacity is stored back to <code>capacity</code>.
124  *  
125  * @param array a pointer to location of the array pointer
126  * @param capacity a pointer to the capacity
127  * @param idx the index of the element to set
128  * @param ptr the pointer to store
129  * @return zero on success or non-zero on error (errno will be set)
130  */
131 #define ucx_array_util_setptr(array, capacity, idx, ptr) \
132     ucx_array_util_setptr_a(ucx_default_allocator(), (void**)(array), \
133                             capacity, idx, ptr)
134
135 /**
136  * Stores a pointer in an arbitrary user defined array.
137  * The element size of the array must be sizeof(void*).
138  * 
139  * If the capacity is insufficient, the array is automatically reallocated
140  * using the specified allocator and the possibly new pointer is stored in
141  * the <code>array</code> argument.
142  * 
143  * On reallocation the capacity of the array is doubled until it is sufficient.
144  * The new capacity is stored back to <code>capacity</code>. 
145  * 
146  * @param alloc the allocator that shall be used to reallocate the array
147  * @param array a pointer to location of the array pointer
148  * @param capacity a pointer to the capacity
149  * @param idx the index of the element to set
150  * @param ptr the pointer to store
151  * @return zero on success or non-zero on error (errno will be set)
152  */
153 int ucx_array_util_setptr_a(UcxAllocator* alloc, void** array, size_t* capacity,
154     size_t idx, void* ptr);
155
156
157 /**
158  * Creates a new UCX array with the given capacity and element size.
159  * @param capacity the initial capacity
160  * @param elemsize the element size
161  * @return a pointer to a new UCX array structure
162  */
163 UcxArray* ucx_array_new(size_t capacity, size_t elemsize);
164
165 /**
166  * Creates a new UCX array using the specified allocator.
167  * 
168  * @param capacity the initial capacity
169  * @param elemsize the element size
170  * @param allocator the allocator to use
171  * @return a pointer to new UCX array structure
172  */
173 UcxArray* ucx_array_new_a(size_t capacity, size_t elemsize,
174         UcxAllocator* allocator);
175
176 /**
177  * Initializes a UCX array structure with the given capacity and element size.
178  * The structure must be uninitialized as the data pointer will be overwritten.
179  * 
180  * @param array the structure to initialize
181  * @param capacity the initial capacity
182  * @param elemsize the element size
183  */
184 void ucx_array_init(UcxArray* array, size_t capacity, size_t elemsize);
185
186 /**
187  * Initializes a UCX array structure using the specified allocator.
188  * The structure must be uninitialized as the data pointer will be overwritten.
189  * 
190  * @param array the structure to initialize
191  * @param capacity the initial capacity
192  * @param elemsize the element size
193  * @param allocator the allocator to use
194  */
195 void ucx_array_init_a(UcxArray* array, size_t capacity, size_t elemsize,
196         UcxAllocator* allocator);
197
198 /**
199  * Creates an shallow copy of an array.
200  * 
201  * This function clones the specified array by using memcpy().
202  * If the destination capacity is insufficient, an automatic reallocation is
203  * attempted.
204  * 
205  * Note: if the destination array is uninitialized, the behavior is undefined.
206  * 
207  * @param dest the array to copy to
208  * @param src the array to copy from
209  * @return zero on success, non-zero on reallocation failure.
210  */
211 int ucx_array_clone(UcxArray* dest, UcxArray const* src);
212
213
214 /**
215  * Compares two UCX arrays element-wise by using a compare function.
216  *
217  * Elements of the two specified arrays are compared by using the specified
218  * compare function and the additional data. The type and content of this
219  * additional data depends on the cmp_func() used.
220  * 
221  * This function always returns zero, if the element sizes of the arrays do
222  * not match and performs no comparisons in this case.
223  * 
224  * @param array1 the first array
225  * @param array2 the second array
226  * @param cmpfnc the compare function
227  * @param data additional data for the compare function
228  * @return 1, if and only if the two arrays equal element-wise, 0 otherwise
229  */
230 int ucx_array_equals(UcxArray const *array1, UcxArray const *array2,
231         cmp_func cmpfnc, void* data);
232
233 /**
234  * Destroys the array.
235  * 
236  * The data is freed and both capacity and count are reset to zero.
237  * If the array structure itself has been dynamically allocated, it has to be
238  * freed separately.
239  * 
240  * @param array the array to destroy
241  */
242 void ucx_array_destroy(UcxArray *array);
243
244 /**
245  * Destroys and frees the array.
246  * 
247  * @param array the array to free
248  */
249 void ucx_array_free(UcxArray *array);
250
251 /**
252  * Inserts elements at the end of the array.
253  * 
254  * This is an O(1) operation.
255  * The array will automatically grow, if the capacity is exceeded.
256  * If a pointer to data is provided, the data is copied into the array with
257  * memcpy(). Otherwise the new elements are completely zeroed.
258  * 
259  * @param array a pointer the array where to append the data
260  * @param data a pointer to the data to insert (may be <code>NULL</code>)
261  * @param count number of elements to copy from data (if data is
262  * <code>NULL</code>, zeroed elements are appended)
263  * @return zero on success, non-zero if a reallocation was necessary but failed
264  * @see ucx_array_set_from()
265  * @see ucx_array_append()
266  */
267 int ucx_array_append_from(UcxArray *array, void *data, size_t count);
268
269
270 /**
271  * Inserts elements at the beginning of the array.
272  * 
273  * This is an expensive operation, because the contents must be moved.
274  * If there is no particular reason to prepend data, you should use
275  * ucx_array_append_from() instead.
276  * 
277  * @param array a pointer the array where to prepend the data
278  * @param data a pointer to the data to insert (may be <code>NULL</code>)
279  * @param count number of elements to copy from data (if data is
280  * <code>NULL</code>, zeroed elements are inserted)
281  * @return zero on success, non-zero if a reallocation was necessary but failed
282  * @see ucx_array_append_from()
283  * @see ucx_array_set_from()
284  * @see ucx_array_prepend()
285  */
286 int ucx_array_prepend_from(UcxArray *array, void *data, size_t count);
287
288
289 /**
290  * Sets elements starting at the specified index.
291  * 
292  * If the any index is out of bounds, the array automatically grows.
293  * The pointer to the data may be NULL, in which case the elements are zeroed. 
294  * 
295  * @param array a pointer the array where to set the data
296  * @param index the index of the element to set
297  * @param data a pointer to the data to insert (may be <code>NULL</code>)
298  * @param count number of elements to copy from data (if data is
299  * <code>NULL</code>, the memory in the array is zeroed)
300  * @return zero on success, non-zero if a reallocation was necessary but failed
301  * @see ucx_array_append_from()
302  * @see ucx_array_set()
303  */
304 int ucx_array_set_from(UcxArray *array, size_t index, void *data, size_t count);
305
306 /**
307  * Concatenates two arrays.
308  * 
309  * The contents of the second array are appended to the first array in one
310  * single operation. The second array is otherwise left untouched.
311  * 
312  * The first array may grow automatically. If this fails, both arrays remain
313  * unmodified.
314  * 
315  * @param array1 first array
316  * @param array2 second array
317  * @return zero on success, non-zero if reallocation was necessary but failed 
318  * or the element size does not match
319  */
320 int ucx_array_concat(UcxArray *array1, const UcxArray *array2);
321
322 /**
323  * Returns a pointer to the array element at the specified index.
324  * 
325  * @param array the array to retrieve the element from
326  * @param index index of the element to return
327  * @return a pointer to the element at the specified index or <code>NULL</code>,
328  * if the index is greater than the array size
329  */
330 void *ucx_array_at(UcxArray const* array, size_t index);
331
332 /**
333  * Returns the index of an element containing the specified data.
334  *
335  * This function uses a cmp_func() to compare the data of each list element
336  * with the specified data. If no cmp_func is provided, memcmp() is used.
337  * 
338  * If the array contains the data more than once, the index of the first
339  * occurrence is returned.
340  * If the array does not contain the data, the size of array is returned.
341  *  
342  * @param array the array where to search for the data
343  * @param elem the element data
344  * @param cmpfnc the compare function
345  * @param data additional data for the compare function
346  * @return the index of the element containing the specified data or the size of
347  * the array, if the data is not found in this array
348  */
349 size_t ucx_array_find(UcxArray const *array, void *elem,
350     cmp_func cmpfnc, void *data);
351
352 /**
353  * Checks, if an array contains a specific element.
354  * 
355  * An element is found, if ucx_array_find() returns a value less than the size.
356  * 
357  * @param array the array where to search for the data
358  * @param elem the element data
359  * @param cmpfnc the compare function
360  * @param data additional data for the compare function
361  * @return 1, if and only if the array contains the specified element data
362  * @see ucx_array_find()
363  */
364 int ucx_array_contains(UcxArray const *array, void *elem,
365     cmp_func cmpfnc, void *data);
366
367 /**
368  * Sorts a UcxArray with the best available sort algorithm.
369  * 
370  * The qsort_r() function is used, if available (glibc, FreeBSD or MacOS).
371  * The order of arguments is automatically adjusted for the FreeBSD and MacOS
372  * version of qsort_r().
373  * 
374  * If qsort_r() is not available, a merge sort algorithm is used, which is
375  * guaranteed to use no more additional memory than for exactly one element.
376  * 
377  * @param array the array to sort
378  * @param cmpfnc the function that shall be used to compare the element data
379  * @param data additional data for the cmp_func() or <code>NULL</code>
380  */
381 void ucx_array_sort(UcxArray* array, cmp_func cmpfnc, void *data);
382
383 /**
384  * Removes an element from the array.
385  * 
386  * This is in general an expensive operation, because several elements may
387  * be moved. If the order of the elements is not relevant, use
388  * ucx_array_remove_fast() instead.
389  * 
390  * @param array pointer to the array from which the element shall be removed
391  * @param index the index of the element to remove
392  */
393 void ucx_array_remove(UcxArray *array, size_t index);
394
395 /**
396  * Removes an element from the array.
397  * 
398  * This is an O(1) operation, but does not maintain the order of the elements.
399  * The last element in the array is moved to the location of the removed
400  * element.
401  * 
402  * @param array pointer to the array from which the element shall be removed
403  * @param index the index of the element to remove
404  */
405 void ucx_array_remove_fast(UcxArray *array, size_t index);
406
407 /**
408  * Shrinks the memory to exactly fit the contents.
409  * 
410  * After this operation, the capacity equals the size.
411  * 
412  * @param array a pointer to the array
413  * @return zero on success, non-zero if reallocation failed
414  */
415 int ucx_array_shrink(UcxArray* array);
416
417 /**
418  * Sets the capacity of the array.
419  * 
420  * If the new capacity is smaller than the size of the array, the elements
421  * are removed and the size is adjusted accordingly.
422  * 
423  * @param array a pointer to the array
424  * @param capacity the new capacity
425  * @return zero on success, non-zero if reallocation failed
426  */
427 int ucx_array_resize(UcxArray* array, size_t capacity);
428
429 /**
430  * Resizes the array only, if the capacity is insufficient.
431  * 
432  * If the requested capacity is smaller than the current capacity, this
433  * function does nothing.
434  * 
435  * @param array a pointer to the array
436  * @param capacity the guaranteed capacity
437  * @return zero on success, non-zero if reallocation failed
438  */
439 int ucx_array_reserve(UcxArray* array, size_t capacity);
440
441 /**
442  * Resizes the capacity, if the specified number of elements would not fit.
443  * 
444  * A call to ucx_array_grow(array, count) is effectively the same as
445  * ucx_array_reserve(array, array->size+count).
446  * 
447  * @param array a pointer to the array
448  * @param count the number of elements that should additionally fit
449  * into the array
450  * @return zero on success, non-zero if reallocation failed
451  */
452 int ucx_array_grow(UcxArray* array, size_t count);
453
454
455 #ifdef  __cplusplus
456 }
457 #endif
458
459 #endif  /* UCX_ARRAY_H */
460