dte test coverage


Directory: ./
File: src/util/string-view.h
Date: 2025-02-14 16:55:22
Exec Total Coverage
Lines: 71 71 100.0%
Functions: 24 24 100.0%
Branches: 44 48 91.7%

Line Branch Exec Source
1 #ifndef UTIL_STRING_VIEW_H
2 #define UTIL_STRING_VIEW_H
3
4 #include <stdbool.h>
5 #include <stddef.h>
6 #include <string.h>
7 #include <sys/types.h>
8 #include "ascii.h"
9 #include "debug.h"
10 #include "macros.h"
11 #include "xmemrchr.h"
12 #include "xstring.h"
13
14 // A non-owning, length-bounded "view" into another string, similar to
15 // the C++17 string_view class or what many languages call a "slice".
16 // The .data member will usually *not* be null-terminated and the
17 // underlying string *must* outlive the view.
18 typedef struct {
19 const unsigned char NONSTRING *data;
20 size_t length;
21 } StringView;
22
23 #define STRING_VIEW_INIT { \
24 .data = NULL, \
25 .length = 0 \
26 }
27
28 #define STRING_VIEW(s) { \
29 .data = s, \
30 .length = STRLEN(s) \
31 }
32
33 14376 static inline StringView string_view(const char *str, size_t length)
34 {
35 14376 return (StringView) {
36 .data = str,
37 .length = length
38 };
39 }
40
41 4226 static inline StringView strview_from_cstring(const char *str)
42 {
43
2/2
✓ Branch 0 (2→3) taken 3974 times.
✓ Branch 1 (2→4) taken 252 times.
4226 return string_view(str, str ? strlen(str) : 0);
44 }
45
46 NONNULL_ARGS
47 2 static inline bool strview_equal(const StringView *a, const StringView *b)
48 {
49 2 size_t n = a->length;
50
2/4
✓ Branch 0 (2→3) taken 2 times.
✗ Branch 1 (2→6) not taken.
✗ Branch 2 (4→5) not taken.
✓ Branch 3 (4→6) taken 2 times.
2 return n == b->length && mem_equal(a->data, b->data, n);
51 }
52
53 NONNULL_ARGS
54 1833 static inline bool strview_equal_strn (
55 const StringView *sv,
56 const char *str,
57 size_t len
58 ) {
59
4/4
✓ Branch 0 (2→3) taken 1104 times.
✓ Branch 1 (2→6) taken 729 times.
✓ Branch 2 (4→5) taken 668 times.
✓ Branch 3 (4→6) taken 436 times.
1833 return len == sv->length && mem_equal(sv->data, str, len);
60 }
61
62 NONNULL_ARGS
63 15 static inline bool strview_equal_strn_icase (
64 const StringView *sv,
65 const char *str,
66 size_t len
67 ) {
68
3/4
✓ Branch 0 (2→3) taken 12 times.
✓ Branch 1 (2→6) taken 3 times.
✗ Branch 2 (4→5) not taken.
✓ Branch 3 (4→6) taken 12 times.
15 return len == sv->length && mem_equal_icase(sv->data, str, len);
69 }
70
71 NONNULL_ARGS
72 1808 static inline bool strview_equal_cstring(const StringView *sv, const char *str)
73 {
74 1808 return strview_equal_strn(sv, str, strlen(str));
75 }
76
77 NONNULL_ARGS
78 15 static inline bool strview_equal_cstring_icase(const StringView *sv, const char *str)
79 {
80 15 return strview_equal_strn_icase(sv, str, strlen(str));
81 }
82
83 NONNULL_ARG(1) NONNULL_ARG_IF_NONZERO_LENGTH(2, 3)
84 9748 static inline bool strview_has_strn_prefix(const StringView *sv, const char *p, size_t n)
85 {
86
4/4
✓ Branch 0 (2→3) taken 8004 times.
✓ Branch 1 (2→6) taken 1744 times.
✓ Branch 2 (4→5) taken 7641 times.
✓ Branch 3 (4→6) taken 363 times.
9748 return sv->length >= n && mem_equal(sv->data, p, n);
87 }
88
89 NONNULL_ARG(1) NONNULL_ARG_IF_NONZERO_LENGTH(2, 3)
90 332 static inline bool strview_has_strn_suffix(const StringView *sv, const char *suf, size_t suflen)
91 {
92 // See also: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3261.pdf
93 332 size_t len = sv->length;
94
6/6
✓ Branch 0 (2→3) taken 323 times.
✓ Branch 1 (2→7) taken 9 times.
✓ Branch 2 (3→4) taken 139 times.
✓ Branch 3 (3→7) taken 184 times.
✓ Branch 4 (5→6) taken 27 times.
✓ Branch 5 (5→7) taken 112 times.
332 return suflen == 0 || (len >= suflen && mem_equal(sv->data + len - suflen, suf, suflen));
95 }
96
97 NONNULL_ARGS
98 9394 static inline bool strview_has_prefix(const StringView *sv, const char *p)
99 {
100 9394 return strview_has_strn_prefix(sv, p, strlen(p));
101 }
102
103 NONNULL_ARGS
104 12 static inline bool strview_has_prefix_icase(const StringView *sv, const char *p)
105 {
106 12 size_t length = strlen(p);
107
4/4
✓ Branch 0 (2→3) taken 11 times.
✓ Branch 1 (2→6) taken 1 times.
✓ Branch 2 (4→5) taken 7 times.
✓ Branch 3 (4→6) taken 4 times.
12 return sv->length >= length && mem_equal_icase(sv->data, p, length);
108 }
109
110 NONNULL_ARGS
111 33 static inline bool strview_has_suffix(const StringView *sv, const char *suffix)
112 {
113 33 return strview_has_strn_suffix(sv, suffix, strlen(suffix));
114 }
115
116 NONNULL_ARGS
117 2 static inline bool strview_has_prefix_and_suffix (
118 const StringView *sv,
119 const char *prefix,
120 const char *suffix
121 ) {
122
3/4
✓ Branch 0 (3→4) taken 1 times.
✓ Branch 1 (3→7) taken 1 times.
✗ Branch 2 (5→6) not taken.
✓ Branch 3 (5→7) taken 1 times.
2 return strview_has_prefix(sv, prefix) && strview_has_suffix(sv, suffix);
123 }
124
125 NONNULL_ARGS
126 103 static inline bool strview_isblank(const StringView *sv)
127 {
128 103 size_t len = sv->length;
129 103 return len == ascii_blank_prefix_length(sv->data, len);
130 }
131
132 NONNULL_ARGS
133 3 static inline bool strview_contains_char_type(const StringView *sv, AsciiCharType mask)
134 {
135 3 return strn_contains_char_type(sv->data, sv->length, mask);
136 }
137
138 NONNULL_ARGS
139 15 static inline const unsigned char *strview_memchr(const StringView *sv, int c)
140 {
141
2/2
✓ Branch 0 (2→3) taken 14 times.
✓ Branch 1 (2→4) taken 1 times.
15 return sv->length ? memchr(sv->data, c, sv->length) : NULL;
142 }
143
144 NONNULL_ARGS
145 380 static inline const unsigned char *strview_memrchr(const StringView *sv, int c)
146 {
147
2/2
✓ Branch 0 (2→3) taken 250 times.
✓ Branch 1 (2→4) taken 130 times.
380 return sv->length ? xmemrchr(sv->data, c, sv->length) : NULL;
148 }
149
150 NONNULL_ARGS
151 376 static inline ssize_t strview_memrchr_idx(const StringView *sv, int c)
152 {
153 376 const unsigned char *ptr = strview_memrchr(sv, c);
154
2/2
✓ Branch 0 (2→3) taken 220 times.
✓ Branch 1 (2→4) taken 156 times.
376 return ptr ? (ssize_t)(ptr - sv->data) : -1;
155 }
156
157 9449 static inline void strview_remove_prefix(StringView *sv, size_t len)
158 {
159 9449 BUG_ON(len > sv->length);
160
2/2
✓ Branch 0 (4→5) taken 545 times.
✓ Branch 1 (4→6) taken 8904 times.
9449 if (len > 0) {
161 545 sv->data += len;
162 545 sv->length -= len;
163 }
164 9449 }
165
166 317 static inline bool strview_remove_matching_prefix(StringView *sv, const char *prefix)
167 {
168 317 size_t prefix_len = strlen(prefix);
169
2/2
✓ Branch 0 (3→4) taken 89 times.
✓ Branch 1 (3→6) taken 228 times.
317 if (!strview_has_strn_prefix(sv, prefix, prefix_len)) {
170 return false;
171 }
172 89 strview_remove_prefix(sv, prefix_len);
173 89 return true;
174 }
175
176 296 static inline bool strview_remove_matching_suffix(StringView *sv, const char *suffix)
177 {
178 296 size_t suffix_len = strlen(suffix);
179
2/2
✓ Branch 0 (3→4) taken 9 times.
✓ Branch 1 (3→5) taken 287 times.
296 if (!strview_has_strn_suffix(sv, suffix, suffix_len)) {
180 return false;
181 }
182 9 sv->length -= suffix_len;
183 9 return true;
184 }
185
186 NONNULL_ARGS
187 8711 static inline size_t strview_trim_left(StringView *sv)
188 {
189 8711 size_t blank_len = ascii_blank_prefix_length(sv->data, sv->length);
190 8711 strview_remove_prefix(sv, blank_len);
191 8711 return blank_len;
192 }
193
194 NONNULL_ARGS
195 206 static inline void strview_trim_right(StringView *sv)
196 {
197 206 const unsigned char *data = sv->data;
198 206 size_t n = sv->length;
199
4/4
✓ Branch 0 (3→4) taken 230 times.
✓ Branch 1 (3→5) taken 44 times.
✓ Branch 2 (4→3) taken 68 times.
✓ Branch 3 (4→5) taken 162 times.
274 while (n && ascii_isblank(data[n - 1])) {
200 n--;
201 }
202 206 sv->length = n;
203 206 }
204
205 NONNULL_ARGS
206 7 static inline void strview_trim(StringView *sv)
207 {
208 7 strview_trim_left(sv);
209 7 strview_trim_right(sv);
210 7 }
211
212 #endif
213