Mercurial > repos > blastem
comparison config.c @ 1489:637fbc3b5063 nuklear_ui
Added code to persist config back to a file
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Wed, 29 Nov 2017 08:41:37 -0800 |
parents | 369da70ee2c2 |
children | e94cff9cb625 |
comparison
equal
deleted
inserted
replaced
1488:f29bd94ffa76 | 1489:637fbc3b5063 |
---|---|
3 This file is part of BlastEm. | 3 This file is part of BlastEm. |
4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. | 4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. |
5 */ | 5 */ |
6 #include "tern.h" | 6 #include "tern.h" |
7 #include "util.h" | 7 #include "util.h" |
8 #include "paths.h" | |
8 #include <stdio.h> | 9 #include <stdio.h> |
9 #include <stdlib.h> | 10 #include <stdlib.h> |
10 #include <string.h> | 11 #include <string.h> |
11 | 12 |
12 #ifdef __MINGW64_VERSION_MAJOR | 13 #ifdef __MINGW64_VERSION_MAJOR |
34 } | 35 } |
35 return NULL; | 36 return NULL; |
36 } | 37 } |
37 #endif | 38 #endif |
38 | 39 |
39 tern_node * parse_config_int(char **state, int started, int *line) | 40 static tern_node * parse_config_int(char **state, int started, int *line) |
40 { | 41 { |
41 char *config_data, *curline; | 42 char *config_data, *curline; |
42 tern_node * head = NULL; | 43 tern_node * head = NULL; |
43 config_data = started ? NULL : *state; | 44 config_data = started ? NULL : *state; |
44 while ((curline = strtok_r(config_data, "\n", state))) | 45 while ((curline = strtok_r(config_data, "\n", state))) |
86 { | 87 { |
87 int line = 1; | 88 int line = 1; |
88 return parse_config_int(&config_data, 0, &line); | 89 return parse_config_int(&config_data, 0, &line); |
89 } | 90 } |
90 | 91 |
92 typedef struct { | |
93 char *buf; | |
94 uint32_t capacity; | |
95 uint32_t size; | |
96 uint32_t indent; | |
97 } serialize_state; | |
98 | |
99 static void ensure_buf_capacity(uint32_t ensure, serialize_state *state) | |
100 { | |
101 if (ensure + state->size > state->capacity) { | |
102 state->capacity = state->capacity * 2; | |
103 state->buf = realloc(state->buf, state->capacity); | |
104 } | |
105 } | |
106 | |
107 static void indent(serialize_state *state) | |
108 { | |
109 memset(state->buf + state->size, '\t', state->indent); | |
110 state->size += state->indent; | |
111 } | |
112 | |
113 static void serialize_config_int(tern_node *config, serialize_state *state); | |
114 | |
115 static void serialize_iter(char *key, tern_val val, uint8_t valtype, void *data) | |
116 { | |
117 serialize_state *state = data; | |
118 uint32_t keylen = strlen(key); | |
119 uint32_t vallen = 0; | |
120 if (valtype == TVAL_PTR) { | |
121 vallen = strlen(val.ptrval); | |
122 } | |
123 ensure_buf_capacity(state->indent + keylen + 2 + vallen, state); | |
124 state->buf[state->size++] = '\n'; | |
125 indent(state); | |
126 memcpy(state->buf + state->size, key, keylen); | |
127 state->size += keylen; | |
128 state->buf[state->size++] = ' '; | |
129 if (valtype == TVAL_PTR) { | |
130 memcpy(state->buf + state->size, val.ptrval, vallen); | |
131 state->size += vallen; | |
132 } else { | |
133 serialize_config_int(val.ptrval, state); | |
134 } | |
135 } | |
136 | |
137 static void serialize_config_int(tern_node *config, serialize_state *state) | |
138 { | |
139 ensure_buf_capacity(1, state); | |
140 state->buf[state->size++] = '{'; | |
141 state->indent++; | |
142 | |
143 tern_foreach(config, serialize_iter, state); | |
144 | |
145 --state->indent; | |
146 ensure_buf_capacity(2 + state->indent, state); | |
147 state->buf[state->size++] = '\n'; | |
148 indent(state); | |
149 state->buf[state->size++] = '}'; | |
150 } | |
151 | |
152 char *serialize_config(tern_node *config, uint32_t *size_out) | |
153 { | |
154 serialize_state state = { | |
155 .size = 0, | |
156 .capacity = 1024, | |
157 .indent = 0 | |
158 }; | |
159 state.buf = malloc(state.capacity); | |
160 tern_foreach(config, serialize_iter, &state); | |
161 //serialize_config_int(config, &state); | |
162 *size_out = state.size; | |
163 return state.buf; | |
164 } | |
165 | |
91 tern_node *parse_config_file(char *config_path) | 166 tern_node *parse_config_file(char *config_path) |
92 { | 167 { |
93 tern_node * ret = NULL; | 168 tern_node * ret = NULL; |
94 FILE * config_file = fopen(config_path, "rb"); | 169 FILE * config_file = fopen(config_path, "rb"); |
95 if (!config_file) { | 170 if (!config_file) { |
112 fclose(config_file); | 187 fclose(config_file); |
113 open_fail: | 188 open_fail: |
114 return ret; | 189 return ret; |
115 } | 190 } |
116 | 191 |
192 uint8_t serialize_config_file(tern_node *config, char *path) | |
193 { | |
194 FILE *f = fopen(path, "w"); | |
195 if (!f) { | |
196 return 0; | |
197 } | |
198 uint32_t buf_size; | |
199 char *buffer = serialize_config(config, &buf_size); | |
200 uint8_t ret = buf_size == fwrite(buffer, 1, buf_size, f); | |
201 fclose(f); | |
202 return ret; | |
203 } | |
204 | |
117 tern_node *parse_bundled_config(char *config_name) | 205 tern_node *parse_bundled_config(char *config_name) |
118 { | 206 { |
119 uint32_t confsize; | 207 uint32_t confsize; |
120 char *confdata = read_bundled_file(config_name, &confsize); | 208 char *confdata = read_bundled_file(config_name, &confsize); |
121 tern_node *ret = NULL; | 209 tern_node *ret = NULL; |
131 { | 219 { |
132 char const *confdir = get_config_dir(); | 220 char const *confdir = get_config_dir(); |
133 char *confpath = NULL; | 221 char *confpath = NULL; |
134 tern_node *ret; | 222 tern_node *ret; |
135 if (confdir) { | 223 if (confdir) { |
136 confpath = alloc_concat(confdir, "/blastem.cfg"); | 224 confpath = path_append(confdir, "blastem.cfg"); |
137 ret = parse_config_file(confpath); | 225 ret = parse_config_file(confpath); |
138 if (ret) { | 226 if (ret) { |
139 free(confpath); | 227 free(confpath); |
140 return ret; | 228 return ret; |
141 } | 229 } |
152 } else { | 240 } else { |
153 fatal_error("Failed to find a config file in the BlastEm executable directory and the config directory path could not be determined\n"); | 241 fatal_error("Failed to find a config file in the BlastEm executable directory and the config directory path could not be determined\n"); |
154 } | 242 } |
155 //this will never get reached, but the compiler doesn't know that. Let's make it happy | 243 //this will never get reached, but the compiler doesn't know that. Let's make it happy |
156 return NULL; | 244 return NULL; |
245 } | |
246 | |
247 void persist_config(tern_node *config) | |
248 { | |
249 char const *confdir = get_config_dir(); | |
250 if (!confdir) { | |
251 fatal_error("Failed to locate config file directory\n"); | |
252 } | |
253 char *confpath = path_append(confdir, "blastem.cfg"); | |
254 if (!serialize_config_file(config, confpath)) { | |
255 fatal_error("Failed to write config to %s\n", confpath); | |
256 } | |
257 free(confpath); | |
157 } | 258 } |
158 | 259 |
159 char **get_extension_list(tern_node *config, uint32_t *num_exts_out) | 260 char **get_extension_list(tern_node *config, uint32_t *num_exts_out) |
160 { | 261 { |
161 char *ext_filter = strdup(tern_find_path_default(config, "ui\0extensions\0", (tern_val){.ptrval = "bin gen md smd sms gg"}, TVAL_PTR).ptrval); | 262 char *ext_filter = strdup(tern_find_path_default(config, "ui\0extensions\0", (tern_val){.ptrval = "bin gen md smd sms gg"}, TVAL_PTR).ptrval); |