Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / devs / diskimage / prefs / readprefs.c
blob9c24db3f2c5fb80507942ae1a95149144f76dcca
1 /* Copyright 2007-2012 Fredrik Wikstrom. All rights reserved.
2 **
3 ** Redistribution and use in source and binary forms, with or without
4 ** modification, are permitted provided that the following conditions
5 ** are met:
6 **
7 ** 1. Redistributions of source code must retain the above copyright
8 ** notice, this list of conditions and the following disclaimer.
9 **
10 ** 2. Redistributions in binary form must reproduce the above copyright
11 ** notice, this list of conditions and the following disclaimer in the
12 ** documentation and/or other materials provided with the distribution.
14 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
15 ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 ** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 ** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 ** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 ** POSSIBILITY OF SUCH DAMAGE.
27 #include "prefs.h"
29 #ifdef __AROS__
30 # include <expat.h>
31 # include <string.h>
32 #else
33 # include <libraries/expat.h>
34 # include <proto/expat.h>
35 #endif
37 #include <proto/exec.h>
38 #include <proto/dos.h>
39 #include <stdlib.h>
41 #define PREFS_BUFFER_SIZE 512
43 typedef struct {
44 LONG state;
45 PrefsObject *dict;
46 BOOL key_tag, value_tag;
47 BOOL has_key;
48 TEXT key[64];
49 TEXT value[512];
50 #ifndef __AROS__
51 struct Library *expatbase;
52 #endif
53 XML_Parser parser;
54 BOOL error;
55 } parser_data;
57 static void start_element_handler (void *user_data, const char *name, const char **attrs);
58 static void end_element_handler (void *user_data, const char *name);
59 static void character_data_handler (void *user_data, const char *s, int len);
61 BOOL ReadPrefs (PrefsObject *dict, CONST_STRPTR filename) {
62 BOOL res = FALSE;
63 #ifndef __AROS__
64 struct Library *ExpatBase;
65 ExpatBase = OpenLibrary("expat.library", 4);
66 if (!ExpatBase) {
67 return res;
69 #endif
70 if (dict && dict->type == PREFS_DICTIONARY) {
71 BPTR file;
72 ClearPrefsDictionary(dict);
73 file = Open(filename, MODE_OLDFILE);
74 if (file) {
75 XML_Parser parser;
76 parser = XML_ParserCreate(NULL);
77 if (parser) {
78 STRPTR buffer;
79 parser_data *data;
80 buffer = AllocVec(PREFS_BUFFER_SIZE, MEMF_ANY);
81 data = AllocVec(sizeof(parser_data), MEMF_ANY);
82 if (buffer && data) {
83 LONG len;
84 BOOL eof;
85 data->state = 0;
86 data->dict = dict;
87 data->key_tag = FALSE;
88 data->value_tag = FALSE;
89 data->has_key = FALSE;
90 #ifndef __AROS__
91 data->expatbase = ExpatBase;
92 #endif
93 data->parser = parser;
94 data->error = FALSE;
95 XML_SetUserData(parser, data);
96 XML_SetElementHandler(parser, start_element_handler, end_element_handler);
97 XML_SetCharacterDataHandler(parser, character_data_handler);
98 while (TRUE) {
99 len = Read(file, buffer, PREFS_BUFFER_SIZE);
100 if (len == -1) {
101 break;
103 eof = (len == 0);
104 if (!XML_Parse(parser, buffer, len, eof)) {
105 break;
107 if (data->error) {
108 break;
110 if (eof) {
111 res = TRUE;
112 break;
116 FreeVec(buffer);
117 FreeVec(data);
118 XML_ParserFree(parser);
120 Close(file);
123 #ifndef __AROS__
124 CloseLibrary(ExpatBase);
125 #endif
126 return res;
129 static void stop_parser (parser_data *data) {
130 #ifndef __AROS__
131 struct Library *ExpatBase = data->expatbase;
132 #endif
133 data->error = TRUE;
134 XML_StopParser(data->parser, XML_TRUE);
137 static void start_element_handler (void *user_data, const char *name, const char **attrs) {
138 parser_data *data = user_data;
139 if (data->error) {
140 return;
142 switch (data->state) {
143 case 0:
144 if (!strcmp(name, "pobjects")) {
145 data->state++;
146 } else {
147 stop_parser(data);
148 return;
150 break;
151 case 1:
152 if (!strcmp(name, "dict")) {
153 data->state++;
154 } else {
155 stop_parser(data);
156 return;
158 break;
159 case 2:
160 if (data->key_tag || data->value_tag) {
161 stop_parser(data);
162 return;
164 if (!data->has_key && !strcmp(name, "key")) {
165 data->key_tag = TRUE;
166 data->key[0] = 0;
167 } else if (data->has_key &&
168 (!strcmp(name, "dict") ||
169 !strcmp(name, "bool") ||
170 !strcmp(name, "integer") ||
171 !strcmp(name, "string")))
173 if (!strcmp(name, "dict")) {
174 PrefsObject *obj;
175 obj = AllocPrefsDictionary();
176 if (DictSetObjectForKey(data->dict, obj, data->key)) {
177 data->dict = obj;
178 data->has_key = FALSE;
179 } else {
180 stop_parser(data);
181 return;
183 } else {
184 data->value_tag = TRUE;
185 data->value[0] = 0;
187 } else {
188 stop_parser(data);
189 return;
191 break;
192 default:
193 stop_parser(data);
194 return;
198 static void end_element_handler (void *user_data, const char *name) {
199 parser_data *data = user_data;
200 if (data->error) {
201 return;
203 switch (data->state) {
204 case 2:
205 if (!data->has_key && !strcmp(name, "dict")) {
206 data->dict = data->dict->parent;
207 if (!data->dict) {
208 data->state++;
210 } else if (data->key_tag && !strcmp(name, "key")) {
211 data->has_key = (data->key[0] != 0);
212 data->key_tag = FALSE;
213 } else if (data->has_key && data->value_tag &&
214 (!strcmp(name, "bool") ||
215 !strcmp(name, "integer") ||
216 !strcmp(name, "string")))
218 PrefsObject *obj;
219 if (!strcmp(name, "bool")) {
220 obj = AllocPrefsBoolean(!strcmp(data->value, "TRUE"));
221 } else if (!strcmp(name, "integer")) {
222 obj = AllocPrefsInteger(atol(data->value));
223 } else if (!strcmp(name, "string")) {
224 obj = AllocPrefsString(data->value);
225 } else {
226 obj = NULL;
228 if (DictSetObjectForKey(data->dict, obj, data->key)) {
229 data->has_key = FALSE;
230 data->value_tag = FALSE;
231 } else {
232 stop_parser(data);
233 return;
235 } else {
236 stop_parser(data);
237 return;
239 break;
240 case 3:
241 if (!strcmp(name, "pobjects")) {
242 data->state++;
243 } else {
244 stop_parser(data);
245 return;
247 break;
248 default:
249 stop_parser(data);
250 return;
254 static void append_text (char *dest, int dest_len, const char *src, int src_len) {
255 int offs = strlen(dest);
256 int space = dest_len - offs;
257 int len;
258 if (space > src_len) {
259 len = src_len;
260 } else {
261 len = space - 1;
263 if (len > 0) {
264 memcpy(&dest[offs], src, len);
265 dest[offs + len] = 0;
269 static void character_data_handler (void *user_data, const char *s, int len) {
270 parser_data *data = user_data;
271 if (data->error) {
272 return;
274 if (data->key_tag) {
275 append_text(data->key, sizeof(data->key), s, len);
276 } else if (data->value_tag) {
277 append_text(data->value, sizeof(data->value), s, len);