aboutsummaryrefslogtreecommitdiff
path: root/filesystem/src
diff options
context:
space:
mode:
Diffstat (limited to 'filesystem/src')
-rw-r--r--filesystem/src/filesystem.c40
-rw-r--r--filesystem/src/path.c104
2 files changed, 105 insertions, 39 deletions
diff --git a/filesystem/src/filesystem.c b/filesystem/src/filesystem.c
index f6bb693..b228e85 100644
--- a/filesystem/src/filesystem.c
+++ b/filesystem/src/filesystem.c
@@ -1,6 +1,7 @@
1#include <filesystem.h> 1#include <filesystem.h>
2 2
3#include <assert.h> 3#include <assert.h>
4#include <stdio.h>
4#include <stdlib.h> 5#include <stdlib.h>
5#include <string.h> 6#include <string.h>
6 7
@@ -54,42 +55,3 @@ cleanup:
54 } 55 }
55 return 0; 56 return 0;
56} 57}
57
58bool make_relative_path(
59 const char* filepath, const char* path, char* relative,
60 size_t relative_length) {
61 assert(filepath);
62 assert(path);
63 assert(relative);
64
65 const size_t filepath_len = strlen(filepath);
66 const size_t path_len = strlen(path);
67 assert(filepath_len < relative_length);
68 assert(path_len < relative_length);
69
70 // Handle empty filepath.
71 if (filepath_len == 0) {
72 memcpy(relative, path, path_len);
73 return true;
74 }
75
76 // Search for the last / in the file path to get its parent directory.
77 assert(filepath_len > 0);
78 size_t tm_dir_len = 0;
79 for (tm_dir_len = strlen(filepath) - 1; tm_dir_len > 0; --tm_dir_len) {
80 if (filepath[tm_dir_len] == '/') {
81 break;
82 }
83 }
84 tm_dir_len++; // Preserve the backslash.
85
86 // Copy the file path where the parent dir ends.
87 // Make sure there is enough space in the output.
88 if ((tm_dir_len + path_len + 1) >= relative_length) {
89 return false;
90 }
91 memcpy(relative, filepath, tm_dir_len);
92 memcpy(&relative[tm_dir_len], path, path_len);
93
94 return true;
95}
diff --git a/filesystem/src/path.c b/filesystem/src/path.c
new file mode 100644
index 0000000..2ce5a04
--- /dev/null
+++ b/filesystem/src/path.c
@@ -0,0 +1,104 @@
1#include <path.h>
2
3#include <cassert.h>
4#include <stdlib.h>
5#include <string.h>
6
7static const path Empty = (path){0, 0};
8
9path path_new(const char* str) {
10 assert(str);
11 const size_t size = strlen(str);
12 if (size > 0) {
13 char* data = calloc(size + 1, sizeof(char)); // +1 for null
14 memcpy(data, str, size);
15 data[size] = 0;
16 return (path){data, size};
17 }
18 return Empty;
19}
20
21void path_del(path* path) {
22 if (path) {
23 free(path->data);
24 path->data = 0;
25 path->size = 0;
26 }
27}
28
29path path_parent_dir(path p) {
30 assert(p.data);
31
32 if (p.size == 0) {
33 return Empty;
34 }
35 size_t i = p.size - 1;
36 // If the path ends with '/', skip the characters.
37 while ((i > 0) && (p.data[i] == '/')) {
38 i--;
39 }
40 // Search backwards for the parent dir.
41 for (; i > 0; --i) {
42 if (p.data[i] == '/') {
43 return (path){p.data, i + 1};
44 }
45 }
46 return Empty; // No parent.
47}
48
49path path_concat(path left, path right) {
50 assert(left.data);
51 assert(right.data);
52
53 // +1 for separator.
54 const size_t out_size = left.size + right.size + 1;
55 // +1 for null.
56 char* out = calloc(out_size + 1, sizeof(char));
57 ASSERT(out);
58
59 memcpy(out, left.data, left.size);
60 out[left.size] = '/';
61 memcpy(out + left.size + 1, right.data, right.size);
62 out[out_size] = 0;
63
64 return (path){out, out_size};
65}
66
67bool path_make_relative(
68 const char* filepath, const char* path, char* relative,
69 size_t relative_length) {
70 assert(filepath);
71 assert(path);
72 assert(relative);
73
74 const size_t filepath_len = strlen(filepath);
75 const size_t path_len = strlen(path);
76 assert(filepath_len < relative_length);
77 assert(path_len < relative_length);
78
79 // Handle empty filepath.
80 if (filepath_len == 0) {
81 memcpy(relative, path, path_len);
82 return true;
83 }
84
85 // Search for the last / in the file path to get its parent directory.
86 assert(filepath_len > 0);
87 size_t tm_dir_len = 0;
88 for (tm_dir_len = strlen(filepath) - 1; tm_dir_len > 0; --tm_dir_len) {
89 if (filepath[tm_dir_len] == '/') {
90 break;
91 }
92 }
93 tm_dir_len++; // Preserve the backslash.
94
95 // Copy the file path where the parent dir ends.
96 // Make sure there is enough space in the output.
97 if ((tm_dir_len + path_len + 1) >= relative_length) {
98 return false;
99 }
100 memcpy(relative, filepath, tm_dir_len);
101 memcpy(&relative[tm_dir_len], path, path_len);
102
103 return true;
104}