Line | Branch | Exec | Source |
---|---|---|---|
1 | #ifndef UTIL_PTR_ARRAY_H | ||
2 | #define UTIL_PTR_ARRAY_H | ||
3 | |||
4 | #include <stdlib.h> | ||
5 | #include "debug.h" | ||
6 | #include "macros.h" | ||
7 | #include "xmalloc.h" | ||
8 | |||
9 | typedef struct { | ||
10 | void **ptrs; | ||
11 | size_t alloc; | ||
12 | size_t count; | ||
13 | } PointerArray; | ||
14 | |||
15 | #define PTR_ARRAY_INIT { \ | ||
16 | .ptrs = NULL, \ | ||
17 | .alloc = 0, \ | ||
18 | .count = 0 \ | ||
19 | } | ||
20 | |||
21 | typedef int (*CompareFunction)(const void *, const void *); | ||
22 | typedef void (*FreeFunction)(void *ptr); | ||
23 | #define FREE_FUNC(f) (FreeFunction)f | ||
24 | |||
25 | void ptr_array_grow_and_append(PointerArray *array, void *ptr) NONNULL_ARG(1) NOINLINE; | ||
26 | void ptr_array_insert(PointerArray *array, void *ptr, size_t idx) NONNULL_ARG(1); | ||
27 | void ptr_array_move(PointerArray *array, size_t from, size_t to) NONNULL_ARGS; | ||
28 | void ptr_array_free_cb(PointerArray *array, FreeFunction free_ptr) NONNULL_ARGS; | ||
29 | size_t ptr_array_remove(PointerArray *array, void *ptr) NONNULL_ARG(1); | ||
30 | void *ptr_array_remove_index(PointerArray *array, size_t idx) NONNULL_ARGS; | ||
31 | size_t ptr_array_index(const PointerArray *array, const void *ptr) NONNULL_ARG(1); | ||
32 | void ptr_array_trim_nulls(PointerArray *array) NONNULL_ARGS; | ||
33 | |||
34 | NONNULL_ARGS | ||
35 | 8 | static inline void ptr_array_init(PointerArray *array, size_t capacity) | |
36 | { | ||
37 | 8 | capacity = round_size_to_next_multiple(capacity, 8); | |
38 | 8 | array->count = 0; | |
39 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
|
8 | array->ptrs = capacity ? xnew(array->ptrs, capacity) : NULL; |
40 | 8 | array->alloc = capacity; | |
41 | 8 | } | |
42 | |||
43 | NONNULL_ARG(1) | ||
44 | 38569 | static inline void ptr_array_append(PointerArray *array, void *ptr) | |
45 | { | ||
46 |
2/2✓ Branch 0 taken 10773 times.
✓ Branch 1 taken 27796 times.
|
38569 | if (unlikely(array->alloc <= array->count)) { |
47 | 10773 | ptr_array_grow_and_append(array, ptr); | |
48 | 10773 | return; | |
49 | } | ||
50 | 27796 | array->ptrs[array->count++] = ptr; | |
51 | } | ||
52 | |||
53 | // Like ptr_array_index(), but asserting that `ptr` should always be found | ||
54 | // in the array (i.e. is known to be present), instead of the caller doing so | ||
55 | 1205 | static inline size_t ptr_array_xindex(const PointerArray *array, const void *ptr) | |
56 | { | ||
57 | 1205 | size_t idx = ptr_array_index(array, ptr); | |
58 | 1205 | BUG_ON(idx >= array->count); | |
59 | 1205 | return idx; | |
60 | } | ||
61 | |||
62 | // Swap the pointers at two indices | ||
63 | NONNULL_ARGS | ||
64 | 1 | static inline void ptr_array_swap(PointerArray *array, size_t a, size_t b) | |
65 | { | ||
66 | 1 | BUG_ON(a >= array->count); | |
67 | 1 | BUG_ON(b >= array->count); | |
68 | 1 | void **ptrs = array->ptrs; | |
69 | 1 | void *tmp = ptrs[a]; | |
70 | 1 | ptrs[a] = ptrs[b]; | |
71 | 1 | ptrs[b] = tmp; | |
72 | 1 | } | |
73 | |||
74 | // Free each pointer and then free the array | ||
75 | NONNULL_ARGS | ||
76 | 8293 | static inline void ptr_array_free(PointerArray *array) | |
77 | { | ||
78 | 8293 | ptr_array_free_cb(array, free); | |
79 | 8293 | } | |
80 | |||
81 | // Free the array itself but not the pointers (useful when the | ||
82 | // pointers are "borrowed" references) | ||
83 | NONNULL_ARGS | ||
84 | 13074 | static inline void ptr_array_free_array(PointerArray *array) | |
85 | { | ||
86 | 13074 | free(array->ptrs); | |
87 | 13074 | *array = (PointerArray) PTR_ARRAY_INIT; | |
88 | 13074 | } | |
89 | |||
90 | 86 | static inline void ptr_array_sort ( | |
91 | const PointerArray *array, | ||
92 | CompareFunction compare | ||
93 | ) { | ||
94 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 59 times.
|
86 | if (array->count >= 2) { |
95 | 27 | qsort(array->ptrs, array->count, sizeof(*array->ptrs), compare); | |
96 | } | ||
97 | 86 | } | |
98 | |||
99 | static inline void *ptr_array_bsearch ( | ||
100 | const PointerArray array, | ||
101 | const void *ptr, | ||
102 | CompareFunction compare | ||
103 | ) { | ||
104 | return bsearch(&ptr, array.ptrs, array.count, sizeof(*array.ptrs), compare); | ||
105 | } | ||
106 | |||
107 | #endif | ||
108 |