dte test coverage


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 50.0% high: ≥ 85.0%
Coverage Exec / Excl / Total
Lines: 100.0% 56 / 0 / 56
Functions: 100.0% 13 / 0 / 13
Branches: 92.9% 26 / 2 / 30

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 2015 static inline size_t copystrn(char *dest, const char *src, size_t len)
16 {
17 2015 memcpy(dest, src, len);
18 2015 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 1867 static inline bool str_has_strn_prefix(const char *str, const char *prefix, size_t plen)
38 {
39 // Note that `prefix` must be a null-terminated string and `plen`
40 // should be equal to strlen(prefix). The explicit length parameter
41 // is simply for the sake of efficiency, e.g. to allow strlen() to
42 // be hoisted out of loops when `prefix` is loop-invariant.
43
4/4
✓ Branch 2 → 3 taken 1285 times.
✓ Branch 2 → 5 taken 582 times.
✓ Branch 3 → 4 taken 1183 times.
✓ Branch 3 → 5 taken 102 times.
1867 return plen == 0 || strncmp(str, prefix, plen) == 0;
44 }
45
46 PURE NONNULL_ARGS
47 217 static inline bool str_has_prefix(const char *str, const char *prefix)
48 {
49 217 return str_has_strn_prefix(str, prefix, strlen(prefix));
50 }
51
52 PURE NONNULL_ARGS
53 15 static inline bool str_has_suffix(const char *str, const char *suffix)
54 {
55 15 size_t l1 = strlen(str);
56 15 size_t l2 = strlen(suffix);
57
4/4
✓ Branch 2 → 3 taken 11 times.
✓ Branch 2 → 6 taken 4 times.
✓ Branch 4 → 5 taken 3 times.
✓ Branch 4 → 6 taken 8 times.
15 return (l1 >= l2) && mem_equal(str + l1 - l2, suffix, l2);
58 }
59
60 NONNULL_ARGS
61 143 static inline size_t str_common_prefix_length(const char *a, const char *b)
62 {
63 143 size_t n = 0;
64
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]) {
65 3007 n++;
66 }
67 143 return n;
68 }
69
70 6 static inline void strn_replace_byte(char *str, size_t n, char byte, char rep)
71 {
72
2/2
✓ Branch 6 → 3 taken 70 times.
✓ Branch 6 → 7 taken 6 times.
76 for (size_t i = 0; i < n; i++) {
73
2/2
✓ Branch 3 → 4 taken 23 times.
✓ Branch 3 → 5 taken 47 times.
70 if (str[i] == byte) {
74 23 str[i] = rep;
75 }
76 }
77 6 }
78
79 // Extract a substring between `buf + pos` and either the next `delim`
80 // byte (if found) or `buf + size` (the remainder of the string). The
81 // substring is returned as a StringView and the `posp` in-out param
82 // is set to the offset one byte after the found delimiter (or to the
83 // end of the size-bounded string, if no delimiter was found).
84 NONNULL_ARGS READONLY(1, 3) READWRITE(2)
85 22496 static inline StringView get_delim(const char *buf, size_t *posp, size_t size, int delim)
86 {
87 22496 size_t pos = *posp;
88 22496 BUG_ON(pos >= size);
89 22496 size_t len = size - pos;
90 22496 const char *start = buf + pos;
91 22496 const char *found = memchr(start, delim, len);
92
2/2
✓ Branch 4 → 5 taken 22147 times.
✓ Branch 4 → 6 taken 349 times.
22496 len = found ? (size_t)(found - start) : len;
93 22496 size_t delim_len = found ? 1 : 0;
94 22496 *posp += len + delim_len;
95 22496 return string_view(start, len);
96 }
97
98 // Similar to get_delim(), but returning a null-terminated substring
99 // instead of a StringView, by mutating the contents of `buf` (i.e.
100 // replacing the delimiter with a NUL byte). Using get_delim() should
101 // be preferred, unless the substring specifically needs to be
102 // null-terminated (e.g. for passing to a library function).
103 NONNULL_ARGS
104 1197 static inline char *get_delim_str(char *buf, size_t *posp, size_t size, int delim)
105 {
106 1197 char *substr = buf + *posp;
107 1197 StringView sv = get_delim(buf, posp, size, delim);
108
109 // If no delimiter was found, this writes the null-terminator 1 byte
110 // beyond the `size` bound. Callers must ensure this is safe to do.
111 // Thus, when calling this function (perhaps repeatedly) to consume
112 // an entire string, either buf[size-1] must be a delim byte or
113 // buf[size] must be in-bounds, writable memory.
114 1197 substr[sv.length] = '\0';
115 1197 return substr;
116 }
117
118 NONNULL_ARGS
119 10862 static inline StringView buf_slice_next_line(const char *buf, size_t *posp, size_t size)
120 {
121 10862 return get_delim(buf, posp, size, '\n');
122 }
123
124 NONNULL_ARGS
125 1164 static inline char *buf_next_line(char *buf, size_t *posp, size_t size)
126 {
127 1164 return get_delim_str(buf, posp, size, '\n');
128 }
129
130 NONNULL_ARGS
131 937 static inline size_t count_nl(const char *buf, size_t size)
132 {
133 937 const char *end = buf + size;
134 937 size_t nl = 0;
135
2/2
✓ Branch 5 → 3 taken 3231 times.
✓ Branch 5 → 6 taken 729 times.
3960 while (buf < end) {
136 3231 buf = memchr(buf, '\n', end - buf);
137
2/2
✓ Branch 3 → 4 taken 3023 times.
✓ Branch 3 → 6 taken 208 times.
3231 if (!buf) {
138 break;
139 }
140 3023 buf++;
141 3023 nl++;
142 }
143 937 return nl;
144 }
145
146 #endif
147