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