dte test coverage


Directory: ./
File: src/util/array.h
Date: 2025-06-04 06:50:24
Exec Total Coverage
Lines: 21 21 100.0%
Functions: 3 3 100.0%
Branches: 10 12 83.3%

Line Branch Exec Source
1 #ifndef UTIL_ARRAY_H
2 #define UTIL_ARRAY_H
3
4 #include <stdbool.h>
5 #include <sys/types.h>
6 #include "debug.h"
7 #include "macros.h"
8 #include "ptr-array.h"
9 #include "xstring.h"
10
11 #define static_assert_flat_string_array(a) \
12 static_assert_incompatible_types(a[0], const char*); \
13 static_assert_incompatible_types(a[0], char*); \
14 static_assert_compatible_types(a[0][0], char)
15
16 #define static_assert_flat_struct_array(a, field) \
17 static_assert_offsetof(a[0], field, 0); \
18 static_assert_incompatible_types(a[0].field, const char*); \
19 static_assert_incompatible_types(a[0].field, char*); \
20 static_assert_compatible_types(a[0].field[0], char)
21
22 #define CHECK_STRING_ARRAY(a) \
23 static_assert_flat_string_array(a); \
24 check_array(a, #a, "", ARRAYLEN(a), sizeof(a[0]), sizeof(a[0]))
25
26 #define CHECK_STRUCT_ARRAY(a, field) \
27 static_assert_flat_struct_array(a, field); \
28 check_array(a, #a, "." #field, ARRAYLEN(a), sizeof(a[0]), sizeof(a[0].field))
29
30 #define COLLECT_STRINGS(a, ptrs, prefix) \
31 static_assert_flat_string_array(a); \
32 collect_strings_from_flat_array(a[0], ARRAYLEN(a), sizeof(a[0]), ptrs, prefix)
33
34 #define COLLECT_STRING_FIELDS(a, field, ptrs, prefix) \
35 static_assert_flat_struct_array(a, field); \
36 collect_strings_from_flat_array(a[0].field, ARRAYLEN(a), sizeof(a[0]), ptrs, prefix)
37
38 #define STR_TO_ENUM_WITH_OFFSET(str, a, nfval, off) \
39 str_to_enum(str, a[0], ARRAYLEN(a), sizeof(a[0]), off, nfval)
40
41 #define SSTR_TO_ENUM_WITH_OFFSET(str, a, field, nfval, off) \
42 str_to_enum(str, a[0].field, ARRAYLEN(a), sizeof(a[0]), off, nfval)
43
44 #define STR_TO_ENUM(str, a, nfval) \
45 STR_TO_ENUM_WITH_OFFSET(str, a, nfval, 0)
46
47 #define STR_TO_BITFLAGS(str, a, tolerate_errors) \
48 str_to_bitflags(str, a[0], ARRAYLEN(a), sizeof(a[0]), tolerate_errors)
49
50 #define FIND_STR_IDX(str, a) \
51 find_str_idx(str, (char*)a, ARRAYLEN(a), sizeof(a[0]), streq)
52
53 // This is somewhat similar to lfind(3), but returning an index
54 // instead of a pointer and specifically for arrays of type
55 // `const char[nmemb][size]`
56 1250 static inline ssize_t find_str_idx (
57 const char *str,
58 const char *base,
59 size_t nmemb,
60 size_t size,
61 bool (*equal)(const char *s1, const char *s2)
62 ) {
63 1250 const char *entry = base;
64
2/2
✓ Branch 0 (7→3) taken 10329 times.
✓ Branch 1 (7→8) taken 519 times.
10848 for (size_t i = 0; i < nmemb; i++, entry += size) {
65
2/2
✓ Branch 0 (4→5) taken 731 times.
✓ Branch 1 (4→6) taken 9598 times.
10329 if (equal(str, entry)) {
66 731 return i;
67 }
68 }
69 return -1;
70 }
71
72 // Attempt to find `str` in a flat array of strings starting at `base`.
73 // If found, return the index plus `return_offset`, otherwise return
74 // `not_found_val`.
75 957 static inline int str_to_enum (
76 const char *str,
77 const char *base,
78 size_t nmemb,
79 size_t size,
80 int return_offset,
81 int not_found_val
82 ) {
83 957 ssize_t idx = find_str_idx(str, base, nmemb, size, streq);
84
2/2
✓ Branch 0 (3→4) taken 616 times.
✓ Branch 1 (3→5) taken 341 times.
957 return (idx >= 0) ? idx + return_offset : not_found_val;
85 }
86
87 void collect_strings_from_flat_array (
88 const char *base,
89 size_t nr_elements,
90 size_t element_len,
91 PointerArray *a,
92 const char *prefix
93 );
94
95 638 static inline void check_array (
96 const void *base,
97 const char *array_name,
98 const char *name_field_name,
99 size_t array_len,
100 size_t elem_size,
101 size_t name_size
102 ) {
103 638 if (!DEBUG_ASSERTIONS_ENABLED) {
104 return;
105 }
106
107 638 BUG_ON(!base);
108 638 BUG_ON(!array_name);
109 638 BUG_ON(!name_field_name);
110 638 BUG_ON(name_field_name[0] != '\0' && name_field_name[0] != '.');
111 638 BUG_ON(array_len == 0);
112 638 BUG_ON(elem_size == 0);
113 638 BUG_ON(name_size == 0);
114
115 const char *first_name = base;
116
2/2
✓ Branch 0 (21→16) taken 22880 times.
✓ Branch 1 (21→22) taken 638 times.
23518 for (size_t i = 0; i < array_len; i++) {
117 22880 const char *curr_name = first_name + (i * elem_size);
118 // NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult)
119
1/2
✗ Branch 0 (16→17) not taken.
✓ Branch 1 (16→18) taken 22880 times.
22880 if (curr_name[0] == '\0') {
120 BUG("Empty string at %s[%zu]%s", array_name, i, name_field_name);
121 }
122 // NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult)
123
1/2
✗ Branch 0 (18→19) not taken.
✓ Branch 1 (18→20) taken 22880 times.
22880 if (curr_name[name_size - 1] != '\0') {
124 BUG("String sentinel missing from %s[%zu]%s", array_name, i, name_field_name);
125 }
126 }
127 }
128
129 unsigned int str_to_bitflags(const char *str, const char *base, size_t nstrs, size_t size, bool tolerate_errors);
130
131 #endif
132