dte test coverage


Directory: ./
File: src/util/xstring.h
Date: 2025-09-07 23:01:39
Exec Total Coverage
Lines: 27 27 100.0%
Functions: 9 9 100.0%
Branches: 17 18 94.4%

Line Branch Exec Source
1 #ifndef UTIL_XSTRING_H
2 #define UTIL_XSTRING_H
3
4 // Several of the *mem*() wrapper functions below explicitly allow NULL
5 // pointer arguments when the corresponding length bound is 0. This is
6 // unlike the equivalent/underlying library functions (where it would
7 // ordinarily be undefined behavior) and is done in the spirit of the
8 // WG14 N3322 proposal.
9 // See also:
10 // • https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf
11
12 #include <stdbool.h>
13 #include <string.h>
14 #include "ascii.h"
15 #include "debug.h"
16 #include "macros.h"
17
18 // Return true if null-terminated strings a and b are identical
19 NONNULL_ARGS
20 70714 static inline bool streq(const char *a, const char *b)
21 {
22 70714 return strcmp(a, b) == 0;
23 }
24
25 // Like streq(), but allowing one or both parameters to be NULL
26 1974 static inline bool xstreq(const char *a, const char *b)
27 {
28
6/6
✓ Branch 0 (2→3) taken 1833 times.
✓ Branch 1 (2→6) taken 141 times.
✓ Branch 2 (3→4) taken 1831 times.
✓ Branch 3 (3→6) taken 2 times.
✓ Branch 4 (4→5) taken 1827 times.
✓ Branch 5 (4→6) taken 4 times.
1974 return (a == b) || (a && b && streq(a, b));
29 }
30
31 // Like strrchr(3), but for use when `ch` is known to be present in
32 // `str` (e.g. when searching for '/' in absolute filenames)
33 NONNULL_ARGS_AND_RETURN
34 5 static inline const char *xstrrchr(const char *str, int ch)
35 {
36 5 const char *ptr = strrchr(str, ch);
37 5 BUG_ON(!ptr);
38 5 return ptr;
39 }
40
41 NONNULL_ARG_IF_NONZERO_LENGTH(1, 3) NONNULL_ARG_IF_NONZERO_LENGTH(2, 3)
42 47709 static inline bool mem_equal(const void *s1, const void *s2, size_t n)
43 {
44 47709 BUG_ON(n && (!s1 || !s2)); // See N3322 reference above
45
3/4
✓ Branch 0 (5→6) taken 47524 times.
✗ Branch 1 (5→8) not taken.
✓ Branch 2 (6→7) taken 44102 times.
✓ Branch 3 (6→8) taken 3422 times.
47524 return n == 0 || memcmp(s1, s2, n) == 0;
46 }
47
48 // Portable version of glibc/FreeBSD mempcpy(3)
49 NONNULL_ARG(1) RETURNS_NONNULL NONNULL_ARG_IF_NONZERO_LENGTH(2, 3)
50 9353 static inline void *xmempcpy(void *restrict dest, const void *restrict src, size_t n)
51 {
52 9353 BUG_ON(n && !src); // See N3322 reference above
53
2/2
✓ Branch 0 (4→5) taken 9313 times.
✓ Branch 1 (4→6) taken 40 times.
9353 return likely(n) ? (char*)memcpy(dest, src, n) + n : dest;
54 }
55
56 NONNULL_ARG(1) RETURNS_NONNULL
57 2069 static inline void *xmempcpy2 (
58 void *dest,
59 const void *p1, size_t n1,
60 const void *p2, size_t n2
61 ) {
62 2069 return xmempcpy(xmempcpy(dest, p1, n1), p2, n2);
63 }
64
65 NONNULL_ARG(1) RETURNS_NONNULL
66 240 static inline void *xmempcpy3 ( // NOLINT(readability-function-size)
67 void *dest,
68 const void *p1, size_t n1,
69 const void *p2, size_t n2,
70 const void *p3, size_t n3
71 ) {
72 240 return xmempcpy(xmempcpy2(dest, p1, n1, p2, n2), p3, n3);
73 }
74
75 NONNULL_ARG(1) RETURNS_NONNULL
76 145 static inline void *xmempcpy4 ( // NOLINT(readability-function-size)
77 void *dest,
78 const void *p1, size_t n1,
79 const void *p2, size_t n2,
80 const void *p3, size_t n3,
81 const void *p4, size_t n4
82 ) {
83 145 return xmempcpy(xmempcpy3(dest, p1, n1, p2, n2, p3, n3), p4, n4);
84 }
85
86 65 static inline bool mem_equal_icase(const void *p1, const void *p2, size_t n)
87 {
88
2/2
✓ Branch 0 (2→3) taken 60 times.
✓ Branch 1 (2→7) taken 5 times.
65 if (n == 0) {
89 return true; // See N3322 reference above
90 }
91
92 60 const char *s1 = p1;
93 60 const char *s2 = p2;
94 60 BUG_ON(!s1 || !s2);
95
96
2/2
✓ Branch 0 (6→5) taken 207 times.
✓ Branch 1 (6→7) taken 24 times.
231 while (n--) {
97
2/2
✓ Branch 0 (5→6) taken 171 times.
✓ Branch 1 (5→7) taken 36 times.
207 if (ascii_tolower(*s1++) != ascii_tolower(*s2++)) {
98 return false;
99 }
100 }
101
102 return true;
103 }
104
105 #endif
106