dte test coverage


Directory: ./
File: src/util/ptr-array.c
Date: 2025-02-14 16:55:22
Exec Total Coverage
Lines: 69 69 100.0%
Functions: 10 10 100.0%
Branches: 30 34 88.2%

Line Branch Exec Source
1 #include <errno.h>
2 #include <string.h>
3 #include "ptr-array.h"
4
5 11112 static void ptr_array_grow(PointerArray *array)
6 {
7 11112 BUG_ON(array->alloc < array->count);
8 11112 const size_t alloc_min = 8;
9
2/2
✓ Branch 0 (4→5) taken 404 times.
✓ Branch 1 (4→6) taken 10708 times.
11112 size_t alloc = MAX((array->alloc * 3) / 2, alloc_min);
10
1/2
✗ Branch 0 (6→7) not taken.
✓ Branch 1 (6→8) taken 11112 times.
11112 if (unlikely(alloc <= array->count)) {
11 fatal_error(__func__, EOVERFLOW);
12 }
13 11112 array->ptrs = xrenew(array->ptrs, alloc);
14 11112 array->alloc = alloc;
15 11112 }
16
17 // This is separate from ptr_array_append(), to allow the hot path to be
18 // inlined. It also duplicates the append operation so as to allow tail
19 // calling, which appears to improve code generation.
20 11112 void ptr_array_grow_and_append(PointerArray *array, void *ptr)
21 {
22 11112 ptr_array_grow(array);
23 11112 array->ptrs[array->count++] = ptr;
24 11112 }
25
26 // Move a pointer from one index to another
27 34 void ptr_array_move(PointerArray *array, size_t from, size_t to)
28 {
29 34 BUG_ON(from >= array->count);
30 34 BUG_ON(to >= array->count);
31
2/2
✓ Branch 0 (6→7) taken 24 times.
✓ Branch 1 (6→17) taken 10 times.
34 if (unlikely(from == to)) {
32 return;
33 }
34
35 24 void **p = array->ptrs;
36 24 bool up = (from < to);
37
2/2
✓ Branch 0 (7→8) taken 8 times.
✓ Branch 1 (7→9) taken 16 times.
24 void *dest = up ? p + from : p + to + 1;
38
2/2
✓ Branch 0 (10→11) taken 8 times.
✓ Branch 1 (10→12) taken 16 times.
24 void *src = up ? p + from + 1 : p + to;
39
2/2
✓ Branch 0 (13→14) taken 8 times.
✓ Branch 1 (13→15) taken 16 times.
24 size_t difference = up ? to - from : from - to;
40
41 24 void *tmp = p[from];
42 24 memmove(dest, src, difference * sizeof(void*));
43 24 p[to] = tmp;
44 }
45
46 12 void ptr_array_insert(PointerArray *array, void *ptr, size_t idx)
47 {
48 12 size_t last = array->count;
49 12 BUG_ON(idx > last);
50 12 ptr_array_append(array, ptr); // last is now array->count - 1
51 12 ptr_array_move(array, last, idx);
52 12 }
53
54 // Call a FreeFunction declared with an arbitrary pointer parameter type
55 // without -fsanitize=function pedantry
56 NO_SANITIZE("undefined")
57 38686 static void do_free_ptr(FreeFunction free_ptr, void *ptr)
58 {
59 38686 free_ptr(ptr);
60 38686 }
61
62 13214 void ptr_array_free_cb(PointerArray *array, FreeFunction free_ptr)
63 {
64
2/2
✓ Branch 0 (5→3) taken 38686 times.
✓ Branch 1 (5→6) taken 13214 times.
51900 for (size_t i = 0, n = array->count; i < n; i++) {
65 38686 do_free_ptr(free_ptr, array->ptrs[i]);
66 38686 array->ptrs[i] = NULL;
67 }
68 13214 ptr_array_free_array(array);
69 13214 }
70
71 245 size_t ptr_array_remove(PointerArray *array, void *ptr)
72 {
73 245 size_t idx = ptr_array_index(array, ptr);
74 245 ptr_array_remove_index(array, idx);
75 245 return idx;
76 }
77
78 1465 void *ptr_array_remove_index(PointerArray *array, size_t idx)
79 {
80 1465 BUG_ON(idx >= array->count);
81 1465 void **ptrs = array->ptrs + idx;
82 1465 void *removed = *ptrs;
83 1465 memmove(ptrs, ptrs + 1, (--array->count - idx) * sizeof(void*));
84 1465 return removed;
85 }
86
87 // Return the first array index found to contain `ptr`, or SIZE_MAX
88 // if not found. See also: ptr_array_xindex(), ptr_array_bsearch().
89 1451 size_t ptr_array_index(const PointerArray *array, const void *ptr)
90 {
91
1/2
✓ Branch 0 (5→3) taken 6461 times.
✗ Branch 1 (5→6) not taken.
6461 for (size_t i = 0, n = array->count; i < n; i++) {
92
2/2
✓ Branch 0 (3→4) taken 5010 times.
✓ Branch 1 (3→6) taken 1451 times.
6461 if (array->ptrs[i] == ptr) {
93 return i;
94 }
95 }
96
97 // If `ptr` isn't found in the array, return -1 (SIZE_MAX). Callers
98 // should check that the returned index is less than `array->count`
99 // before indexing `array->ptrs` with it or use ptr_array_xindex()
100 // instead, if applicable.
101 return -1;
102 }
103
104 // Trim all leading NULLs and all but one trailing NULL (if any)
105 1190 void ptr_array_trim_nulls(PointerArray *array)
106 {
107 1190 size_t n = array->count;
108
2/2
✓ Branch 0 (2→3) taken 1189 times.
✓ Branch 1 (2→18) taken 1 times.
1190 if (n == 0) {
109 return;
110 }
111
112 1189 void **ptrs = array->ptrs;
113
4/4
✓ Branch 0 (5→6) taken 2379 times.
✓ Branch 1 (5→7) taken 2 times.
✓ Branch 2 (6→4) taken 1192 times.
✓ Branch 3 (6→7) taken 1187 times.
2381 while (n > 0 && ptrs[n - 1] == NULL) {
114 1192 n--;
115 }
116
117
1/2
✓ Branch 0 (7→8) taken 1189 times.
✗ Branch 1 (7→9) not taken.
1189 if (n != array->count) {
118 // Leave 1 trailing NULL
119 1189 n++;
120 }
121
122
3/4
✓ Branch 0 (9→10) taken 1189 times.
✗ Branch 1 (9→11) not taken.
✓ Branch 2 (10→11) taken 1186 times.
✓ Branch 3 (10→13) taken 3 times.
1189 if (n == 0 || ptrs[0] != NULL) {
123 // No leading NULLs; simply adjust count and return early
124 1186 array->count = n;
125 1186 return;
126 }
127
128 size_t i = 0;
129
4/4
✓ Branch 0 (13→14) taken 5 times.
✓ Branch 1 (13→15) taken 2 times.
✓ Branch 2 (14→12) taken 4 times.
✓ Branch 3 (14→15) taken 1 times.
7 while (i < n && ptrs[i] == NULL) {
130 4 i++;
131 }
132
133 3 BUG_ON(i == 0);
134 3 n -= i;
135 3 array->count = n;
136 3 memmove(ptrs, ptrs + i, n * sizeof(void*));
137 }
138