dte test coverage


Directory: ./
File: src/util/str-array.h
Date: 2025-07-03 15:44:24
Exec Total Coverage
Lines: 37 37 100.0%
Functions: 7 7 100.0%
Branches: 22 24 91.7%

Line Branch Exec Source
1 #ifndef UTIL_STR_ARRAY_H
2 #define UTIL_STR_ARRAY_H
3
4 // Utility functions for working with null-terminated arrays of null-terminated
5 // strings, like e.g. the "argv" argument passed to main()
6
7 #include <stdbool.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include "debug.h"
11 #include "macros.h"
12 #include "str-util.h"
13 #include "xmalloc.h"
14 #include "xstring.h"
15
16 11318 static inline size_t string_array_length(char **strings)
17 {
18 11318 size_t n = 0;
19
2/2
✓ Branch 0 (4→3) taken 24733 times.
✓ Branch 1 (4→5) taken 11318 times.
36051 while (strings[n]) {
20 24733 n++;
21 }
22 11318 return n;
23 }
24
25 48 static inline bool string_array_contains_prefix(char **strs, const char *prefix)
26 {
27 48 size_t prefix_len = strlen(prefix);
28
2/2
✓ Branch 0 (5→3) taken 104 times.
✓ Branch 1 (5→6) taken 48 times.
152 for (size_t i = 0; strs[i]; i++) {
29
1/2
✓ Branch 0 (3→4) taken 104 times.
✗ Branch 1 (3→6) not taken.
104 if (str_has_strn_prefix(strs[i], prefix, prefix_len)) {
30 return true;
31 }
32 }
33 return false;
34 }
35
36 2 static inline bool string_array_contains_str(char **strs, const char *str)
37 {
38
2/2
✓ Branch 0 (5→3) taken 1 times.
✓ Branch 1 (5→6) taken 1 times.
2 for (size_t i = 0; strs[i]; i++) {
39
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→6) taken 1 times.
1 if (streq(strs[i], str)) {
40 return true;
41 }
42 }
43 return false;
44 }
45
46 611 static inline char **copy_string_array(char **src, size_t count)
47 {
48 611 char **dst = xmallocarray(count + 1, sizeof(*dst));
49
2/2
✓ Branch 0 (6→4) taken 1037 times.
✓ Branch 1 (6→7) taken 611 times.
1648 for (size_t i = 0; i < count; i++) {
50 1037 dst[i] = xstrdup(src[i]);
51 }
52 611 dst[count] = NULL;
53 611 return dst;
54 }
55
56 // Concatenates an array of strings into a fixed-size buffer, as a single,
57 // delimiter-separated string. This is separate from string_array_concat()
58 // only as a convenience for testing.
59 WARN_UNUSED_RESULT NONNULL_ARGS
60 93 static inline bool string_array_concat_ (
61 char *buf, size_t bufsize,
62 const char *const *strs, size_t nstrs,
63 const char *delim, size_t delim_len
64 ) {
65 93 BUG_ON(bufsize == 0);
66 93 const char *end = buf + bufsize;
67 93 char *ptr = buf;
68 93 buf[0] = '\0'; // Always null-terminate `buf`, even if `nstrs == 0`
69
70
2/2
✓ Branch 0 (12→5) taken 519 times.
✓ Branch 1 (12→13) taken 64 times.
583 for (size_t i = 0; i < nstrs; i++) {
71 519 bool last_iter = (i + 1 == nstrs);
72 519 ptr = memccpy(ptr, strs[i], '\0', end - ptr);
73
6/6
✓ Branch 0 (6→7) taken 510 times.
✓ Branch 1 (6→13) taken 9 times.
✓ Branch 2 (7→8) taken 449 times.
✓ Branch 3 (7→9) taken 61 times.
✓ Branch 4 (8→9) taken 429 times.
✓ Branch 5 (8→13) taken 20 times.
519 if (unlikely(!ptr || (!last_iter && ptr + delim_len > end))) {
74 return false;
75 }
76 // Append `delim` (over the copied '\0'), if not on the last iteration
77
2/2
✓ Branch 0 (9→10) taken 429 times.
✓ Branch 1 (9→11) taken 61 times.
490 ptr = last_iter ? ptr : xmempcpy(ptr - 1, delim, delim_len);
78 }
79
80 return true;
81 }
82
83 // Like string_array_concat_(), but asserting that it should never return
84 // false (i.e. because the required `bufsize` is known at compile-time)
85 61 static inline void string_array_concat (
86 char *buf, size_t bufsize,
87 const char *const *strs, size_t nstrs,
88 const char *delim, size_t delim_len
89 ) {
90 61 bool r = string_array_concat_(buf, bufsize, strs, nstrs, delim, delim_len);
91 61 BUG_ON(!r);
92 61 }
93
94 NONNULL_ARGS
95 2486 static inline void free_string_array(char **strings)
96 {
97
2/2
✓ Branch 0 (4→3) taken 1113 times.
✓ Branch 1 (4→5) taken 2486 times.
3599 for (size_t i = 0; strings[i]; i++) {
98 1113 free(strings[i]);
99 }
100 2486 free(strings);
101 2486 }
102
103 #endif
104