dte test coverage


Directory: ./
File: src/util/ptr-array.h
Date: 2025-07-01 18:22:46
Exec Total Coverage
Lines: 34 34 100.0%
Functions: 7 7 100.0%
Branches: 6 6 100.0%

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 "container.h"
7 #include "debug.h"
8 #include "macros.h"
9 #include "xmalloc.h"
10
11 typedef struct {
12 void **ptrs;
13 size_t alloc;
14 size_t count;
15 } PointerArray;
16
17 #define PTR_ARRAY_INIT { \
18 .ptrs = NULL, \
19 .alloc = 0, \
20 .count = 0 \
21 }
22
23 typedef int (*CompareFunction)(const void *, const void *);
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 9 static inline void ptr_array_init(PointerArray *array, size_t capacity)
36 {
37 9 capacity = next_multiple(capacity, 8);
38 9 array->count = 0;
39
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;
40 9 array->alloc = capacity;
41 9 }
42
43 NONNULL_ARG(1)
44 48371 static inline void ptr_array_append(PointerArray *array, void *ptr)
45 {
46
2/2
✓ Branch 0 (2→3) taken 13509 times.
✓ Branch 1 (2→5) taken 34862 times.
48371 if (unlikely(array->alloc <= array->count)) {
47 13509 ptr_array_grow_and_append(array, ptr);
48 13509 return;
49 }
50 34862 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 1911 static inline size_t ptr_array_xindex(const PointerArray *array, const void *ptr)
56 {
57 1911 size_t idx = ptr_array_index(array, ptr);
58 1911 BUG_ON(idx >= array->count);
59 1911 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 10207 static inline void ptr_array_free(PointerArray *array)
77 {
78 10207 ptr_array_free_cb(array, free);
79 10207 }
80
81 // Free the array itself but not the pointers (useful when the
82 // pointers are "borrowed" references)
83 NONNULL_ARGS
84 15210 static inline void ptr_array_free_array(PointerArray *array)
85 {
86 15210 free(array->ptrs);
87 15210 *array = (PointerArray) PTR_ARRAY_INIT;
88 15210 }
89
90 87 static inline void ptr_array_sort (
91 const PointerArray *array,
92 CompareFunction compare
93 ) {
94
2/2
✓ Branch 0 (2→3) taken 27 times.
✓ Branch 1 (2→4) taken 60 times.
87 if (array->count >= 2) {
95 27 qsort(array->ptrs, array->count, sizeof(*array->ptrs), compare);
96 }
97 87 }
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