]> git.lizzy.rs Git - nothing.git/blob - src/game/level_folder.c
Merge pull request #1 from tsoding/master
[nothing.git] / src / game / level_folder.c
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 #include "system/stacktrace.h"
5 #include "system/lt.h"
6 #include "system/nth_alloc.h"
7 #include "system/line_stream.h"
8 #include "system/str.h"
9 #include "dynarray.h"
10 #include "game/level_metadata.h"
11
12 #include "./level_folder.h"
13
14 #define LEVEL_FOLDER_MAX_LENGTH 512
15
16 struct LevelFolder
17 {
18     Lt *lt;
19     Dynarray *filenames;
20     Dynarray *titles;
21 };
22
23 LevelFolder *create_level_folder(const char *dirpath)
24 {
25     trace_assert(dirpath);
26
27     Lt *lt = create_lt();
28     if (lt == NULL) {
29         return NULL;
30     }
31
32     LevelFolder *level_folder = PUSH_LT(
33         lt,
34         nth_calloc(1, sizeof(LevelFolder)),
35         free);
36     if (level_folder == NULL) {
37         RETURN_LT(lt, NULL);
38     }
39     level_folder->lt = lt;
40
41     level_folder->filenames = PUSH_LT(
42         lt,
43         create_dynarray(sizeof(const char*)),
44         destroy_dynarray);
45     if (level_folder->filenames == NULL) {
46         RETURN_LT(lt, NULL);
47     }
48
49     level_folder->titles = PUSH_LT(
50         lt,
51         create_dynarray(sizeof(const char*)),
52         destroy_dynarray);
53     if (level_folder->titles == NULL) {
54         RETURN_LT(lt, NULL);
55     }
56
57     char path[LEVEL_FOLDER_MAX_LENGTH];
58     snprintf(path, LEVEL_FOLDER_MAX_LENGTH, "%s/meta.txt", dirpath);
59
60     LineStream *meta = PUSH_LT(
61         lt,
62         create_line_stream(
63             path,
64             "r",
65             LEVEL_FOLDER_MAX_LENGTH),
66         destroy_line_stream);
67     if (meta == NULL) {
68         RETURN_LT(lt, NULL);
69     }
70
71     const char *line = line_stream_next(meta);
72     while (line) {
73         snprintf(path, LEVEL_FOLDER_MAX_LENGTH, "%s/%s", dirpath, line);
74         line = PUSH_LT(lt, string_duplicate(trim_endline(path), NULL), free);
75         if (line == NULL) {
76             RETURN_LT(lt, NULL);
77         }
78
79         LevelMetadata *level_metadata = create_level_metadata_from_file(line);
80         if (level_metadata == NULL) {
81             RETURN_LT(lt, NULL);
82         }
83         const char *title = PUSH_LT(
84             lt,
85             string_duplicate(level_metadata_title(level_metadata), NULL),
86             free);
87         destroy_level_metadata(level_metadata);
88
89         dynarray_push(level_folder->titles, &title);
90         dynarray_push(level_folder->filenames, &line);
91
92         line = line_stream_next(meta);
93     }
94
95     destroy_line_stream(RELEASE_LT(lt, meta));
96
97     return level_folder;
98 }
99
100 void destroy_level_folder(LevelFolder *level_folder)
101 {
102     trace_assert(level_folder);
103     RETURN_LT0(level_folder->lt);
104 }
105
106 const char **level_folder_filenames(const LevelFolder *level_folder)
107 {
108     trace_assert(level_folder);
109     return dynarray_data(level_folder->filenames);
110 }
111
112 const char **level_folder_titles(const LevelFolder *level_folder)
113 {
114     trace_assert(level_folder);
115     return dynarray_data(level_folder->titles);
116 }
117
118 size_t level_folder_count(const LevelFolder *level_folder)
119 {
120     trace_assert(level_folder);
121     return dynarray_count(level_folder->filenames);
122 }