diff options
Diffstat (limited to 'filesystem/src')
-rw-r--r-- | filesystem/src/filesystem.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/filesystem/src/filesystem.c b/filesystem/src/filesystem.c new file mode 100644 index 0000000..6c0dcfb --- /dev/null +++ b/filesystem/src/filesystem.c | |||
@@ -0,0 +1,92 @@ | |||
1 | #include <filesystem.h> | ||
2 | |||
3 | #include <assert.h> | ||
4 | #include <stdlib.h> | ||
5 | #include <string.h> | ||
6 | |||
7 | size_t get_file_size(FILE* file) { | ||
8 | assert(file); | ||
9 | const long int starting_pos = ftell(file); | ||
10 | if (starting_pos == -1) { | ||
11 | return (size_t)-1; | ||
12 | } | ||
13 | if (fseek(file, 0, SEEK_END) != 0) { | ||
14 | return (size_t)-1; | ||
15 | } | ||
16 | const size_t file_size = ftell(file); | ||
17 | if (file_size == (size_t)-1) { | ||
18 | return (size_t)-1; | ||
19 | } | ||
20 | if (fseek(file, starting_pos, SEEK_SET) != 0) { | ||
21 | return (size_t)-1; | ||
22 | } | ||
23 | return file_size; | ||
24 | } | ||
25 | |||
26 | void* read_file(const char* filepath) { | ||
27 | assert(filepath); | ||
28 | |||
29 | void* data = 0; | ||
30 | |||
31 | FILE* file = fopen(filepath, "rb"); | ||
32 | if (!file) { | ||
33 | return 0; | ||
34 | } | ||
35 | const size_t file_size = get_file_size(file); | ||
36 | if (file_size == (size_t)-1) { | ||
37 | goto cleanup; | ||
38 | } | ||
39 | |||
40 | data = calloc(1, file_size); | ||
41 | if (!data) { | ||
42 | goto cleanup; | ||
43 | } | ||
44 | if (fread(data, 1, file_size, file) != file_size) { | ||
45 | goto cleanup; | ||
46 | } | ||
47 | |||
48 | return data; | ||
49 | |||
50 | cleanup: | ||
51 | fclose(file); | ||
52 | if (data) { | ||
53 | free(data); | ||
54 | } | ||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | bool make_relative_path( | ||
59 | size_t max_path_length, const char* filepath, const char* path, | ||
60 | char* relative) { | ||
61 | assert(filepath); | ||
62 | assert(path); | ||
63 | assert(relative); | ||
64 | |||
65 | // Handle empty filepath. | ||
66 | const size_t filepath_len = strlen(filepath); | ||
67 | if (filepath_len == 0) { | ||
68 | memcpy(relative, path, max_path_length); | ||
69 | return true; | ||
70 | } | ||
71 | |||
72 | memcpy(relative, filepath, max_path_length); | ||
73 | // Search for the last / in the tile map file path to get its parent | ||
74 | // directory. | ||
75 | assert(filepath_len > 0); | ||
76 | size_t tm_dir_len = 0; | ||
77 | for (tm_dir_len = strlen(filepath) - 1; tm_dir_len > 0; --tm_dir_len) { | ||
78 | if (filepath[tm_dir_len] == '/') { | ||
79 | break; | ||
80 | } | ||
81 | } | ||
82 | tm_dir_len++; // Preserve the backslash. | ||
83 | |||
84 | // Copy the tile set file path where the parent dir ends. | ||
85 | // Make sure there is enough space in the output. | ||
86 | const size_t path_len = strlen(path); | ||
87 | if ((tm_dir_len + path_len + 1) >= max_path_length) { | ||
88 | return false; | ||
89 | } | ||
90 | memcpy(&relative[tm_dir_len], path, path_len); | ||
91 | return true; | ||
92 | } | ||