File Coverage

src/b_path.c
Criterion Covered Total %
statement 24 47 51.0
branch 17 34 50.0
condition n/a
subroutine n/a
pod n/a
total 41 81 50.6


line stmt bran cond sub pod time code
1             #include
2             #include
3             #include "b_string.h"
4             #include "b_stack.h"
5             #include "b_path.h"
6             #include "b_util.h"
7              
8 20245           b_stack *b_path_new(b_string *string) {
9             b_stack *ret;
10 20245           char *item, *dup, *tmp, *ctx = NULL;
11              
12 20245 50         if ((ret = b_stack_new(0)) == NULL) {
13 0           goto error_stack_new;
14             }
15              
16 20245           b_stack_set_destructor(ret, B_STACK_DESTRUCTOR(b_string_free));
17              
18 20245 50         if ((dup = malloc(string->len + 1)) == NULL) {
19 0           goto error_malloc;
20             }
21              
22 20245 50         if (memcpy(dup, string->str, string->len) == NULL) {
23 0           goto error_memcpy;
24             }
25              
26 20245           dup[string->len] = '\0';
27              
28 20245           tmp = dup;
29              
30 51065 100         while ((item = strtok_r(tmp, "/", &ctx)) != NULL) {
31             b_string *item_copy;
32              
33 30820           tmp = NULL;
34              
35             /*
36             * Skip all but the first "." component for consideration.
37             */
38 30820 100         if (b_stack_count(ret) > 0 && strcmp(item, ".") == 0) {
    50          
39 0           continue;
40             }
41              
42             /*
43             * Since strtok_r() discards any empty items, for convenience an empty
44             * string object will be added to the beginning of the stack if the input
45             * path is absolute.
46             */
47 30820 100         if (b_stack_count(ret) == 0 && string->str[0] == '/') {
    100          
48 6985           b_stack_push(ret, b_string_new(""));
49             }
50              
51 30820 50         if ((item_copy = b_string_new(item)) == NULL) {
52 0           goto error_item_copy;
53             }
54              
55 30820 50         if (b_stack_push(ret, item_copy) == NULL) {
56 0           goto error_item_push;
57             }
58             }
59              
60             /*
61             * If there are still no items in the stack, then add /, if the path is
62             * absolute. This is necessary because a path of '/', or '//' passed to
63             * strtok_r() would yield no results (see strtok(3) for details).
64             */
65 20245 50         if (b_stack_count(ret) == 0 && string->str[0] == '/') {
    0          
66 0 0         if (b_stack_push(ret, b_string_new("/")) == NULL) {
67 0           goto error_item_push;
68             }
69             }
70              
71 20245           free(dup);
72              
73 20245           return ret;
74              
75             error_item_push:
76             error_item_copy:
77             error_memcpy:
78 0           free(dup);
79              
80             error_malloc:
81 0           b_stack_destroy(ret);
82              
83             error_stack_new:
84 20245           return NULL;
85             }
86              
87 13176           b_string *b_path_clean(b_string *string) {
88             b_string *ret;
89             b_stack *parts;
90              
91 13176 50         if ((parts = b_path_new(string)) == NULL) {
92 0           goto error_path_new;
93             }
94              
95 13176 50         if ((ret = b_string_join("/", parts)) == NULL) {
96 0           goto error_join;
97             }
98              
99 13176           b_stack_destroy(parts);
100              
101 13176           return ret;
102              
103             error_join:
104 0           b_stack_destroy(parts);
105              
106             error_path_new:
107 0           return NULL;
108             }
109              
110 0           b_string *b_path_clean_str(char *str) {
111             b_string *ret;
112             b_string *tmp;
113              
114 0 0         if ((tmp = b_string_new(str)) == NULL) {
115 0           goto error_string_new;
116             }
117              
118 0 0         if ((ret = b_path_clean(tmp)) == NULL) {
119 0           goto error_path_clean;
120             }
121              
122 0           b_string_free(tmp);
123              
124 0           return ret;
125              
126             error_path_clean:
127 0           b_string_free(tmp);
128              
129             error_string_new:
130 0           return NULL;
131             }