Open expat_au.library on AROS.
[AROS.git] / workbench / devs / diskimage / prefs / readprefs.c
bloba5421f96ee3e76f88dca8bcf5b06e88f83235b7c
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 <libraries/expat_au.h>
31 # include <proto/expat_au.h>
32 # include <string.h>
33 #else
34 # include <libraries/expat.h>
35 # include <proto/expat.h>
36 #endif
38 #include <proto/exec.h>
39 #include <proto/dos.h>
40 #include <stdlib.h>
42 #define PREFS_BUFFER_SIZE 512
44 typedef struct {
45 LONG state;
46 PrefsObject *dict;
47 BOOL key_tag, value_tag;
48 BOOL has_key;
49 TEXT key[64];
50 TEXT value[512];
51 struct Library *expatbase;
52 XML_Parser parser;
53 BOOL error;
54 } parser_data;
56 static void start_element_handler (void *user_data, const char *name, const char **attrs);
57 static void end_element_handler (void *user_data, const char *name);
58 static void character_data_handler (void *user_data, const char *s, int len);
60 BOOL ReadPrefs (PrefsObject *dict, CONST_STRPTR filename) {
61 struct Library *ExpatBase;
62 BOOL res = FALSE;
63 #ifdef __AROS__
64 ExpatBase = OpenLibrary("expat_au.library", 0);
65 #else
66 ExpatBase = OpenLibrary("expat.library", 4);
67 #endif
68 if (!ExpatBase) {
69 return res;
71 if (dict && dict->type == PREFS_DICTIONARY) {
72 BPTR file;
73 ClearPrefsDictionary(dict);
74 file = Open(filename, MODE_OLDFILE);
75 if (file) {
76 XML_Parser parser;
77 parser = XML_ParserCreate(NULL);
78 if (parser) {
79 STRPTR buffer;
80 parser_data *data;
81 buffer = AllocVec(PREFS_BUFFER_SIZE, MEMF_ANY);
82 data = AllocVec(sizeof(parser_data), MEMF_ANY);
83 if (buffer && data) {
84 LONG len;
85 BOOL eof;
86 data->state = 0;
87 data->dict = dict;
88 data->key_tag = FALSE;
89 data->value_tag = FALSE;
90 data->has_key = FALSE;
91 data->expatbase = ExpatBase;
92 data->parser = parser;
93 data->error = FALSE;
94 XML_SetUserData(parser, data);
95 XML_SetElementHandler(parser, start_element_handler, end_element_handler);
96 XML_SetCharacterDataHandler(parser, character_data_handler);
97 while (TRUE) {
98 len = Read(file, buffer, PREFS_BUFFER_SIZE);
99 if (len == -1) {
100 break;
102 eof = (len == 0);
103 if (!XML_Parse(parser, buffer, len, eof)) {
104 break;
106 if (data->error) {
107 break;
109 if (eof) {
110 res = TRUE;
111 break;
115 FreeVec(buffer);
116 FreeVec(data);
117 XML_ParserFree(parser);
119 Close(file);
122 CloseLibrary(ExpatBase);
123 return res;
126 static void stop_parser (parser_data *data) {
127 struct Library *ExpatBase = data->expatbase;
128 data->error = TRUE;
129 XML_StopParser(data->parser, XML_TRUE);
132 static void start_element_handler (void *user_data, const char *name, const char **attrs) {
133 parser_data *data = user_data;
134 if (data->error) {
135 return;
137 switch (data->state) {
138 case 0:
139 if (!strcmp(name, "pobjects")) {
140 data->state++;
141 } else {
142 stop_parser(data);
143 return;
145 break;
146 case 1:
147 if (!strcmp(name, "dict")) {
148 data->state++;
149 } else {
150 stop_parser(data);
151 return;
153 break;
154 case 2:
155 if (data->key_tag || data->value_tag) {
156 stop_parser(data);
157 return;
159 if (!data->has_key && !strcmp(name, "key")) {
160 data->key_tag = TRUE;
161 data->key[0] = 0;
162 } else if (data->has_key &&
163 (!strcmp(name, "dict") ||
164 !strcmp(name, "bool") ||
165 !strcmp(name, "integer") ||
166 !strcmp(name, "string")))
168 if (!strcmp(name, "dict")) {
169 PrefsObject *obj;
170 obj = AllocPrefsDictionary();
171 if (DictSetObjectForKey(data->dict, obj, data->key)) {
172 data->dict = obj;
173 data->has_key = FALSE;
174 } else {
175 stop_parser(data);
176 return;
178 } else {
179 data->value_tag = TRUE;
180 data->value[0] = 0;
182 } else {
183 stop_parser(data);
184 return;
186 break;
187 default:
188 stop_parser(data);
189 return;
193 static void end_element_handler (void *user_data, const char *name) {
194 parser_data *data = user_data;
195 if (data->error) {
196 return;
198 switch (data->state) {
199 case 2:
200 if (!data->has_key && !strcmp(name, "dict")) {
201 data->dict = data->dict->parent;
202 if (!data->dict) {
203 data->state++;
205 } else if (data->key_tag && !strcmp(name, "key")) {
206 data->has_key = (data->key[0] != 0);
207 data->key_tag = FALSE;
208 } else if (data->has_key && data->value_tag &&
209 (!strcmp(name, "bool") ||
210 !strcmp(name, "integer") ||
211 !strcmp(name, "string")))
213 PrefsObject *obj;
214 if (!strcmp(name, "bool")) {
215 obj = AllocPrefsBoolean(!strcmp(data->value, "TRUE"));
216 } else if (!strcmp(name, "integer")) {
217 obj = AllocPrefsInteger(atol(data->value));
218 } else if (!strcmp(name, "string")) {
219 obj = AllocPrefsString(data->value);
220 } else {
221 obj = NULL;
223 if (DictSetObjectForKey(data->dict, obj, data->key)) {
224 data->has_key = FALSE;
225 data->value_tag = FALSE;
226 } else {
227 stop_parser(data);
228 return;
230 } else {
231 stop_parser(data);
232 return;
234 break;
235 case 3:
236 if (!strcmp(name, "pobjects")) {
237 data->state++;
238 } else {
239 stop_parser(data);
240 return;
242 break;
243 default:
244 stop_parser(data);
245 return;
249 static void append_text (char *dest, int dest_len, const char *src, int src_len) {
250 int offs = strlen(dest);
251 int space = dest_len - offs;
252 int len;
253 if (space > src_len) {
254 len = src_len;
255 } else {
256 len = space - 1;
258 if (len > 0) {
259 memcpy(&dest[offs], src, len);
260 dest[offs + len] = 0;
264 static void character_data_handler (void *user_data, const char *s, int len) {
265 parser_data *data = user_data;
266 if (data->error) {
267 return;
269 if (data->key_tag) {
270 append_text(data->key, sizeof(data->key), s, len);
271 } else if (data->value_tag) {
272 append_text(data->value, sizeof(data->value), s, len);