1 #ifndef UTIL_PTR_ARRAY_H
2 #define UTIL_PTR_ARRAY_H
3 
4 #include <stdlib.h>
5 #include "macros.h"
6 #include "xmalloc.h"
7 
8 typedef struct {
9     void **ptrs;
10     size_t alloc;
11     size_t count;
12 } PointerArray;
13 
14 #define PTR_ARRAY_INIT { \
15     .ptrs = NULL, \
16     .alloc = 0, \
17     .count = 0 \
18 }
19 
20 typedef int (*CompareFunction)(const void *, const void *);
21 typedef void (*FreeFunction)(void *ptr);
22 #define FREE_FUNC(f) (FreeFunction)f
23 
24 void ptr_array_add(PointerArray *array, void *ptr) NONNULL_ARG(1);
25 void ptr_array_insert(PointerArray *array, void *ptr, size_t pos) NONNULL_ARG(1);
26 void ptr_array_free_cb(PointerArray *array, FreeFunction free_ptr) NONNULL_ARGS;
27 void ptr_array_remove(PointerArray *array, void *ptr) NONNULL_ARG(1);
28 void *ptr_array_remove_idx(PointerArray *array, size_t pos) NONNULL_ARG(1);
29 size_t ptr_array_idx(const PointerArray *array, const void *ptr) NONNULL_ARG(1);
30 void *ptr_array_rel(const PointerArray *array, const void *ptr, size_t offset) NONNULL_ARG(1);
31 void ptr_array_trim_nulls(PointerArray *array) NONNULL_ARGS;
32 
33 NONNULL_ARGS
ptr_array_init(PointerArray * array,size_t capacity)34 static inline void ptr_array_init(PointerArray *array, size_t capacity)
35 {
36     capacity = ROUND_UP(capacity, 8);
37     array->count = 0;
38     array->ptrs = capacity ? xnew(array->ptrs, capacity) : NULL;
39     array->alloc = capacity;
40 }
41 
42 NONNULL_ARG(1)
ptr_array_next(const PointerArray * array,const void * ptr)43 static inline void *ptr_array_next(const PointerArray *array, const void *ptr)
44 {
45     return ptr_array_rel(array, ptr, 1);
46 }
47 
48 NONNULL_ARG(1)
ptr_array_prev(const PointerArray * array,const void * ptr)49 static inline void *ptr_array_prev(const PointerArray *array, const void *ptr)
50 {
51     return ptr_array_rel(array, ptr, -1);
52 }
53 
54 // Free each pointer and then free the array.
55 NONNULL_ARGS
ptr_array_free(PointerArray * array)56 static inline void ptr_array_free(PointerArray *array)
57 {
58     ptr_array_free_cb(array, free);
59 }
60 
61 // Free the array itself but not the pointers. Useful when the pointers
62 // are "borrowed" references.
63 NONNULL_ARGS
ptr_array_free_array(PointerArray * array)64 static inline void ptr_array_free_array(PointerArray *array)
65 {
66     free(array->ptrs);
67     *array = (PointerArray) PTR_ARRAY_INIT;
68 }
69 
ptr_array_sort(const PointerArray * array,CompareFunction compare)70 static inline void ptr_array_sort (
71     const PointerArray *array,
72     CompareFunction compare
73 ) {
74     if (array->count >= 2) {
75         qsort(array->ptrs, array->count, sizeof(*array->ptrs), compare);
76     }
77 }
78 
ptr_array_bsearch(const PointerArray array,const void * ptr,CompareFunction compare)79 static inline void *ptr_array_bsearch (
80     const PointerArray array,
81     const void *ptr,
82     CompareFunction compare
83 ) {
84     return bsearch(&ptr, array.ptrs, array.count, sizeof(*array.ptrs), compare);
85 }
86 
87 #endif
88