dte test coverage


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 50.0% high: ≥ 85.0%
Coverage Exec / Excl / Total
Lines: 100.0% 36 / 0 / 36
Functions: 100.0% 8 / 0 / 8
Branches: 100.0% 18 / 6 / 24

src/util/path.h
Line Branch Exec Source
1 #ifndef UTIL_PATH_H
2 #define UTIL_PATH_H
3
4 #include <stdbool.h>
5 #include <stddef.h>
6 #include <string.h>
7 #include "debug.h"
8 #include "macros.h"
9 #include "string-view.h"
10 #include "xmalloc.h"
11 #include "xmemrchr.h"
12
13 NONNULL_ARGS
14 325 static inline bool path_is_absolute(const char *path)
15 {
16 325 return path[0] == '/';
17 }
18
19 // `path` must not contain trailing slashes (but it can be "/")
20 326 static inline StringView path_slice_basename(StringView path)
21 {
22 326 ssize_t slash = strview_memrchr_idx(path, '/');
23 326 strview_remove_prefix(&path, slash + 1); // slash + 1 is 0 if no slash was found
24 326 return path;
25 }
26
27 // `path` must not contain trailing slashes (but it can be "/")
28 NONNULL_ARGS_AND_RETURN
29 218 static inline const char *path_basename(const char *path)
30 {
31 218 const char *slash = strrchr(path, '/');
32
2/2
✓ Branch 2 → 3 taken 206 times.
✓ Branch 2 → 4 taken 12 times.
218 return slash ? slash + 1 : path;
33 }
34
35 NONNULL_ARGS
36 85 static inline StringView path_slice_dirname(const char *path)
37 {
38 85 const char *slash = strrchr(path, '/');
39
2/2
✓ Branch 2 → 3 taken 16 times.
✓ Branch 2 → 4 taken 69 times.
85 if (!slash) {
40 16 return strview(".");
41 }
42 69 bool slash_is_root_dir = (slash == path);
43
2/2
✓ Branch 4 → 5 taken 65 times.
✓ Branch 4 → 6 taken 4 times.
69 return string_view(path, slash_is_root_dir ? 1 : slash - path);
44 }
45
46 XSTRDUP
47 50 static inline char *path_dirname(const char *path)
48 {
49 50 const StringView dir = path_slice_dirname(path);
50 50 return xstrcut(dir.data, dir.length);
51 }
52
53 122 static inline char *path_join_sv(StringView s1, StringView s2, bool trailing_slash)
54 {
55 122 const char slash[2] = "/";
56 122 size_t n1 = s1.length;
57 122 size_t n2 = s2.length;
58
4/4
✓ Branch 2 → 3 taken 110 times.
✓ Branch 2 → 4 taken 12 times.
✓ Branch 3 → 4 taken 5 times.
✓ Branch 3 → 5 taken 105 times.
122 size_t sep = n1 && n2 && s1.data[n1 - 1] != '/'; // Separating slash length (1 or 0)
59
4/4
✓ Branch 5 → 6 taken 4 times.
✓ Branch 5 → 7 taken 118 times.
✓ Branch 6 → 7 taken 1 time.
✓ Branch 6 → 8 taken 3 times.
122 size_t ts = trailing_slash && n2 && s2.data[n2 - 1] != '/'; // Trailing slash length (1 or 0)
60 122 return xmemjoin4(s1.data, n1, slash, sep, s2.data, n2, slash + !ts, ts + 1);
61 }
62
63 60 static inline char *path_join(const char *s1, const char *s2)
64 {
65 60 return path_join_sv(strview(s1), strview(s2), false);
66 }
67
68 // If path is the root directory, return false. Otherwise, mutate the
69 // path argument to become its parent directory and return true. Note
70 // that path *must* be canonical (i.e. as returned by path_absolute()).
71 11 static inline bool path_parent(StringView *path)
72 {
73 11 BUG_ON(!strview_has_prefix(*path, "/"));
74
2/2
✓ Branch 5 → 6 taken 9 times.
✓ Branch 5 → 14 taken 2 times.
11 if (unlikely(path->length == 1)) {
75 return false; // Root dir
76 }
77
78 // Remove up to 1 trailing slash
79
2/2
✓ Branch 7 → 8 taken 1 time.
✓ Branch 7 → 11 taken 8 times.
9 if (unlikely(strview_remove_matching_suffix(path, "/"))) {
80 1 BUG_ON(strview_has_suffix(*path, "/"));
81 }
82
83 // Adjust the length, to exclude the last path component
84 9 ssize_t slash_idx = strview_memrchr_idx(*path, '/');
85 9 BUG_ON(slash_idx < 0);
86 9 path->length = MAX(slash_idx, 1); // Shortest valid path is "/"
87 9 return true;
88 }
89
90 char *path_absolute(const char *path) MALLOC NONNULL_ARGS;
91 char *path_relative(const char *absolute, const char *cwd) XSTRDUP;
92 char *short_filename(const char *absolute, StringView home_dir) XSTRDUP;
93 char *short_filename_cwd(const char *absolute, const char *cwd, StringView home_dir) XSTRDUP;
94 const char *path_slice_relative(const char *abs, const char *cwd) NONNULL_ARGS RETURNS_NONNULL;
95
96 #endif
97