dte test coverage


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 50.0% high: ≥ 85.0%
Coverage Exec / Excl / Total
Lines: 100.0% 52 / 0 / 52
Functions: 100.0% 12 / 0 / 12
Branches: 90.0% 18 / 2 / 22

src/util/str-util.h
Line Branch Exec Source
1 #ifndef UTIL_STR_UTIL_H
2 #define UTIL_STR_UTIL_H
3
4 #include <stdbool.h>
5 #include <stddef.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include "debug.h"
9 #include "macros.h"
10 #include "string-view.h"
11 #include "xstring.h"
12
13 #define copyliteral(dest, lit) copystrn(dest, lit, STRLEN(lit))
14
15 2027 static inline size_t copystrn(char *dest, const char *src, size_t len)
16 {
17 2027 memcpy(dest, src, len);
18 2027 return len;
19 }
20
21 // Like getenv(3), but also returning NULL for empty strings
22 38 static inline const char *xgetenv(const char *name)
23 {
24 38 const char *val = getenv(name);
25
3/4
✓ Branch 3 → 4 taken 10 times.
✓ Branch 3 → 5 taken 28 times.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 10 times.
38 return (!val || val[0] == '\0') ? NULL : val;
26 }
27
28 // Like setenv(3), but always using overwrite=1 and aborting on failure
29 // (which can only mean errno=ENOMEM, if `name` is known to be valid)
30 11 static inline void xsetenv(const char *name, const char *value)
31 {
32 11 int r = setenv(name, value, 1);
33
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 11 times.
11 FATAL_ERROR_ON(r != 0, errno);
34 11 }
35
36 PURE NONNULL_ARGS
37 1584 static inline bool str_has_sv_prefix(const char *str, StringView prefix)
38 {
39 1584 return strview_has_sv_prefix(strview(str), prefix);
40 }
41
42 PURE NONNULL_ARGS
43 215 static inline bool str_has_prefix(const char *str, const char *prefix)
44 {
45 215 return strview_has_sv_prefix(strview(str), strview(prefix));
46 }
47
48 NONNULL_ARGS
49 143 static inline size_t str_common_prefix_length(const char *a, const char *b)
50 {
51 143 size_t n = 0;
52
4/4
✓ Branch 4 → 5 taken 3067 times.
✓ Branch 4 → 6 taken 83 times.
✓ Branch 5 → 3 taken 3007 times.
✓ Branch 5 → 6 taken 60 times.
3150 while (a[n] && a[n] == b[n]) {
53 3007 n++;
54 }
55 143 return n;
56 }
57
58 6 static inline void strn_replace_byte(char *str, size_t n, char byte, char rep)
59 {
60
2/2
✓ Branch 6 → 3 taken 70 times.
✓ Branch 6 → 7 taken 6 times.
76 for (size_t i = 0; i < n; i++) {
61
2/2
✓ Branch 3 → 4 taken 23 times.
✓ Branch 3 → 5 taken 47 times.
70 if (str[i] == byte) {
62 23 str[i] = rep;
63 }
64 }
65 6 }
66
67 // Extract a substring between `buf + pos` and either the next `delim`
68 // byte (if found) or `buf + size` (the remainder of the string). The
69 // substring is returned as a StringView and the `posp` in-out param
70 // is set to the offset one byte after the found delimiter (or to the
71 // end of the size-bounded string, if no delimiter was found).
72 NONNULL_ARGS READONLY(1, 3) READWRITE(2)
73 22795 static inline StringView get_delim(const char *buf, size_t *posp, size_t size, int delim)
74 {
75 22795 size_t pos = *posp;
76 22795 BUG_ON(pos >= size);
77 22795 size_t len = size - pos;
78 22795 const char *start = buf + pos;
79 22795 const char *found = memchr(start, delim, len);
80
2/2
✓ Branch 4 → 5 taken 22446 times.
✓ Branch 4 → 6 taken 349 times.
22795 len = found ? (size_t)(found - start) : len;
81 22795 size_t delim_len = found ? 1 : 0;
82 22795 *posp += len + delim_len;
83 22795 return string_view(start, len);
84 }
85
86 // Similar to get_delim(), but returning a null-terminated substring
87 // instead of a StringView, by mutating the contents of `buf` (i.e.
88 // replacing the delimiter with a NUL byte). Using get_delim() should
89 // be preferred, unless the substring specifically needs to be
90 // null-terminated (e.g. for passing to a library function).
91 NONNULL_ARGS
92 1181 static inline char *get_delim_str(char *buf, size_t *posp, size_t size, int delim)
93 {
94 1181 char *substr = buf + *posp;
95 1181 StringView sv = get_delim(buf, posp, size, delim);
96
97 // If no delimiter was found, this writes the null-terminator 1 byte
98 // beyond the `size` bound. Callers must ensure this is safe to do.
99 // Thus, when calling this function (perhaps repeatedly) to consume
100 // an entire string, either buf[size-1] must be a delim byte or
101 // buf[size] must be in-bounds, writable memory.
102 1181 substr[sv.length] = '\0';
103 1181 return substr;
104 }
105
106 NONNULL_ARGS
107 11161 static inline StringView buf_slice_next_line(const char *buf, size_t *posp, size_t size)
108 {
109 11161 return get_delim(buf, posp, size, '\n');
110 }
111
112 NONNULL_ARGS
113 1148 static inline char *buf_next_line(char *buf, size_t *posp, size_t size)
114 {
115 1148 return get_delim_str(buf, posp, size, '\n');
116 }
117
118 NONNULL_ARGS
119 937 static inline size_t count_nl(const char *buf, size_t size)
120 {
121 937 const char *end = buf + size;
122 937 size_t nl = 0;
123
2/2
✓ Branch 5 → 3 taken 3231 times.
✓ Branch 5 → 6 taken 729 times.
3960 while (buf < end) {
124 3231 buf = memchr(buf, '\n', end - buf);
125
2/2
✓ Branch 3 → 4 taken 3023 times.
✓ Branch 3 → 6 taken 208 times.
3231 if (!buf) {
126 break;
127 }
128 3023 buf++;
129 3023 nl++;
130 }
131 937 return nl;
132 }
133
134 #endif
135