dte test coverage


Directory: ./
File: src/util/path.h
Date: 2025-02-14 16:55:22
Exec Total Coverage
Lines: 43 43 100.0%
Functions: 8 8 100.0%
Branches: 20 20 100.0%

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
12 NONNULL_ARGS
13 322 static inline bool path_is_absolute(const char *path)
14 {
15 322 return path[0] == '/';
16 }
17
18 // filename must not contain trailing slashes (but it can be "/")
19 NONNULL_ARGS_AND_RETURN
20 427 static inline const char *path_basename(const char *filename)
21 {
22 427 const char *slash = strrchr(filename, '/');
23
2/2
✓ Branch 0 (2→3) taken 312 times.
✓ Branch 1 (2→4) taken 115 times.
427 return slash ? slash + 1 : filename;
24 }
25
26 NONNULL_ARGS
27 68 static inline StringView path_slice_dirname(const char *filename)
28 {
29 68 const char *slash = strrchr(filename, '/');
30
2/2
✓ Branch 0 (2→3) taken 6 times.
✓ Branch 1 (2→4) taken 62 times.
68 if (!slash) {
31 6 return string_view(".", 1);
32 }
33 62 bool slash_is_root_dir = (slash == filename);
34
2/2
✓ Branch 0 (4→5) taken 60 times.
✓ Branch 1 (4→6) taken 2 times.
62 size_t dirname_length = slash_is_root_dir ? 1 : slash - filename;
35 62 return string_view(filename, dirname_length);
36 }
37
38 XSTRDUP
39 46 static inline char *path_dirname(const char *filename)
40 {
41 46 const StringView dir = path_slice_dirname(filename);
42 46 return xstrcut(dir.data, dir.length);
43 }
44
45 XSTRDUP
46 127 static inline char *path_join_sv(const StringView *s1, const StringView *s2, bool trailing_slash)
47 {
48 127 size_t n1 = s1->length;
49 127 size_t n2 = s2->length;
50
2/2
✓ Branch 0 (2→3) taken 121 times.
✓ Branch 1 (2→4) taken 6 times.
248 char *path = xmalloc(n1 + n2 + (trailing_slash ? 3 : 2));
51 127 memcpy(path, s1->data, n1);
52 127 char *ptr = path + n1;
53
4/4
✓ Branch 0 (5→6) taken 117 times.
✓ Branch 1 (5→8) taken 10 times.
✓ Branch 2 (6→7) taken 112 times.
✓ Branch 3 (6→8) taken 5 times.
127 if (n1 && n2 && s1->data[n1 - 1] != '/') {
54 112 *ptr++ = '/';
55 }
56 127 memcpy(ptr, s2->data, n2);
57
4/4
✓ Branch 0 (8→9) taken 4 times.
✓ Branch 1 (8→11) taken 123 times.
✓ Branch 2 (9→10) taken 3 times.
✓ Branch 3 (9→11) taken 1 times.
127 if (trailing_slash && n2 && s2->data[n2 - 1] != '/') {
58 3 ptr[n2++] = '/';
59 }
60 127 ptr[n2] = '\0';
61 127 return path;
62 }
63
64 XSTRDUP
65 126 static inline char *path_joinx(const char *s1, const char *s2, bool trailing_slash)
66 {
67 126 StringView sv1 = strview_from_cstring(s1);
68 126 StringView sv2 = strview_from_cstring(s2);
69 126 return path_join_sv(&sv1, &sv2, trailing_slash);
70 }
71
72 XSTRDUP
73 67 static inline char *path_join(const char *s1, const char *s2)
74 {
75 67 return path_joinx(s1, s2, false);
76 }
77
78 // If path is the root directory, return false. Otherwise, mutate the
79 // path argument to become its parent directory and return true. Note
80 // that path *must* be canonical (i.e. as returned by path_absolute()).
81 11 static inline bool path_parent(StringView *path)
82 {
83 11 BUG_ON(!strview_has_prefix(path, "/"));
84
2/2
✓ Branch 0 (5→6) taken 9 times.
✓ Branch 1 (5→14) taken 2 times.
11 if (unlikely(path->length == 1)) {
85 return false; // Root dir
86 }
87
88 // Remove up to 1 trailing slash
89
2/2
✓ Branch 0 (7→8) taken 1 times.
✓ Branch 1 (7→11) taken 8 times.
9 if (unlikely(strview_remove_matching_suffix(path, "/"))) {
90 1 BUG_ON(strview_has_suffix(path, "/"));
91 }
92
93 // Adjust the length, to exclude the last path component
94 9 ssize_t slash_idx = strview_memrchr_idx(path, '/');
95 9 BUG_ON(slash_idx < 0);
96 9 path->length = MAX(slash_idx, 1); // Shortest valid path is "/"
97 9 return true;
98 }
99
100 char *path_absolute(const char *path) MALLOC NONNULL_ARGS;
101 char *path_relative(const char *absolute, const char *cwd) XSTRDUP;
102 char *short_filename(const char *absolute, const StringView *home_dir) XSTRDUP;
103 char *short_filename_cwd(const char *absolute, const char *cwd, const StringView *home_dir) XSTRDUP;
104 const char *path_slice_relative(const char *abs, const char *cwd) NONNULL_ARGS RETURNS_NONNULL;
105
106 #endif
107