/[gxemul]/upstream/0.4.6/src/settings.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/0.4.6/src/settings.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 43 - (show annotations)
Mon Oct 8 16:22:43 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 14281 byte(s)
0.4.6
1 /*
2 * Copyright (C) 2006-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 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 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: settings.c,v 1.16 2007/06/15 17:02:38 debug Exp $
29 *
30 * A generic settings object. (This module should be 100% indepedent of GXemul
31 * and hence easily reusable.) It is basically a tree structure of nodes,
32 * where each node has a name and a few properties. The main property is
33 * a pointer, which can either point to other settings ("sub-settings"),
34 * or to a variable in memory.
35 *
36 * Appart from the pointer, the other properties are a definition of the
37 * type being pointed to (int, int32_t, int64_t, char*, etc), how it should be
38 * presented (e.g. it may be an int value in memory, but it should be
39 * presented as a boolean "true/false" value), and a flag which tells us
40 * whether the setting is directly writable or not.
41 *
42 * If UNSTABLE_DEVEL is defined, then warnings are printed when
43 * settings_destroy() is called if individual settings have not yet been
44 * deleted. (This is to help making sure that code which uses the settings
45 * subsystem correctly un-initializes stuff.)
46 */
47
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51
52 /* Including misc.h should ONLY be necessary to work around the fact that
53 many systems don't have PRIx64 etc defined. */
54 #include "misc.h"
55
56 #include "settings.h"
57
58
59 struct settings {
60 struct settings *parent;
61 char *name_in_parent;
62
63 int n_settings;
64
65 /*
66 * Each setting has a name, a writable flag, a storage type, a
67 * presentation format, and a pointer.
68 *
69 * For subsettings, the pointer points to the subsettings object;
70 * for other settings, the pointer points to a variable.
71 *
72 * These pointers point to simple linear arrays, containing n_settings
73 * entries each.
74 */
75
76 char **name;
77 int *writable;
78 int *storage_type;
79 int *presentation_format;
80 void **ptr;
81 };
82
83
84 /*
85 * settings_new():
86 *
87 * Create a new settings object. Return value is a pointer to the newly
88 * created object. The function does not return on failure.
89 */
90 struct settings *settings_new(void)
91 {
92 struct settings *settings;
93
94 CHECK_ALLOCATION(settings = malloc(sizeof(struct settings)));
95 memset(settings, 0, sizeof(struct settings));
96
97 return settings;
98 }
99
100
101 /*
102 * settings_destroy():
103 *
104 * Frees all resources occupied by a settings object. Also, if this settings
105 * object has a parent, then remove it from the parent.
106 */
107 void settings_destroy(struct settings *settings)
108 {
109 int i;
110
111 if (settings == NULL) {
112 fprintf(stderr, "settings_destroy(): internal error, "
113 "settings = NULL!\n");
114 exit(1);
115 }
116
117 #ifdef UNSTABLE_DEVEL
118 if (settings->n_settings > 0)
119 printf("settings_destroy(): there are remaining settings!\n");
120 #endif
121
122 if (settings->name != NULL) {
123 for (i=0; i<settings->n_settings; i++) {
124 if (settings->name[i] != NULL) {
125 #ifdef UNSTABLE_DEVEL
126 printf("settings_destroy(): setting '%s'"
127 " was not properly deleted before "
128 "exiting!\n", settings->name[i]);
129 #endif
130 free(settings->name[i]);
131 }
132 }
133
134 free(settings->name);
135 } else if (settings->n_settings != 0) {
136 fprintf(stderr, "settings_destroy(): internal error, "
137 "settings->name = NULL, but there were settings?"
138 " (n_settings = %i)\n", settings->n_settings);
139 exit(1);
140 }
141
142 if (settings->writable != NULL)
143 free(settings->writable);
144
145 if (settings->storage_type != NULL)
146 free(settings->storage_type);
147
148 if (settings->presentation_format != NULL)
149 free(settings->presentation_format);
150
151 if (settings->ptr != NULL)
152 free(settings->ptr);
153
154 if (settings->parent != NULL) {
155 settings_remove(settings->parent, settings->name_in_parent);
156 free(settings->name_in_parent);
157 }
158
159 free(settings);
160 }
161
162
163 /*
164 * settings_read():
165 *
166 * Used internally by settings_access() and settings_debugdump().
167 */
168 static int settings_read(struct settings *settings, int i, uint64_t *valuep)
169 {
170 *valuep = 0;
171
172 switch (settings->storage_type[i]) {
173 case SETTINGS_TYPE_INT:
174 *valuep = *((int *) settings->ptr[i]);
175 break;
176 case SETTINGS_TYPE_INT8:
177 *valuep = *((int8_t *) settings->ptr[i]);
178 break;
179 case SETTINGS_TYPE_INT16:
180 *valuep = *((int16_t *) settings->ptr[i]);
181 break;
182 case SETTINGS_TYPE_INT32:
183 *valuep = *((int32_t *) settings->ptr[i]);
184 break;
185 case SETTINGS_TYPE_INT64:
186 *valuep = *((int64_t *) settings->ptr[i]);
187 break;
188 case SETTINGS_TYPE_UINT:
189 *valuep = *((uint *) settings->ptr[i]);
190 break;
191 case SETTINGS_TYPE_UINT8:
192 *valuep = *((uint8_t *) settings->ptr[i]);
193 break;
194 case SETTINGS_TYPE_UINT16:
195 *valuep = *((uint16_t *) settings->ptr[i]);
196 break;
197 case SETTINGS_TYPE_UINT32:
198 *valuep = *((uint32_t *) settings->ptr[i]);
199 break;
200 case SETTINGS_TYPE_UINT64:
201 *valuep = *((uint64_t *) settings->ptr[i]);
202 break;
203 case SETTINGS_TYPE_STRING:
204 /* Note: Strings cannot be read like this. */
205 break;
206 default:printf("settings_read(): FATAL ERROR! Unknown storage type"
207 ": %i\n", settings->storage_type[i]);
208 exit(1);
209 }
210
211 return SETTINGS_OK;
212 }
213
214
215 /*
216 * settings_write():
217 *
218 * Used internally by settings_access().
219 */
220 static int settings_write(struct settings *settings, int i, uint64_t *valuep)
221 {
222 if (!settings->writable[i])
223 return SETTINGS_READONLY;
224
225 switch (settings->storage_type[i]) {
226 case SETTINGS_TYPE_INT:
227 case SETTINGS_TYPE_UINT:
228 *((int *) settings->ptr[i]) = *valuep;
229 break;
230 case SETTINGS_TYPE_INT8:
231 case SETTINGS_TYPE_UINT8:
232 *((int8_t *) settings->ptr[i]) = *valuep;
233 break;
234 case SETTINGS_TYPE_INT16:
235 case SETTINGS_TYPE_UINT16:
236 *((int16_t *) settings->ptr[i]) = *valuep;
237 break;
238 case SETTINGS_TYPE_INT32:
239 case SETTINGS_TYPE_UINT32:
240 *((int32_t *) settings->ptr[i]) = *valuep;
241 break;
242 case SETTINGS_TYPE_INT64:
243 case SETTINGS_TYPE_UINT64:
244 *((int64_t *) settings->ptr[i]) = *valuep;
245 break;
246 case SETTINGS_TYPE_STRING:
247 /* Note: Strings cannot be read like this. */
248 printf("settings_write(): ERROR! Strings cannot be "
249 "written like this.\n");
250 break;
251 default:printf("settings_read(): FATAL ERROR! Unknown storage type"
252 ": %i\n", settings->storage_type[i]);
253 exit(1);
254 }
255
256 return SETTINGS_OK;
257 }
258
259
260 /*
261 * settings_debugdump():
262 *
263 * Dump settings in a settings object to stdout.
264 * If recurse is non-zero, all subsetting objects are also dumped.
265 */
266 void settings_debugdump(struct settings *settings, const char *prefix,
267 int recurse)
268 {
269 size_t name_buflen = strlen(prefix) + 100;
270 char *name;
271 int i;
272 uint64_t value = 0;
273
274 CHECK_ALLOCATION(name = malloc(name_buflen));
275
276 for (i=0; i<settings->n_settings; i++) {
277 snprintf(name, name_buflen, "%s.%s", prefix, settings->name[i]);
278
279 if (settings->storage_type[i] == SETTINGS_TYPE_SUBSETTINGS) {
280 /* Subsettings: */
281 if (recurse)
282 settings_debugdump(settings->ptr[i], name, 1);
283 } else {
284 /* Normal value: */
285 printf("%s = ", name);
286
287 settings_read(settings, i, &value);
288
289 switch (settings->presentation_format[i]) {
290 case SETTINGS_FORMAT_DECIMAL:
291 printf("%"PRIi64, value);
292 break;
293 case SETTINGS_FORMAT_HEX8:
294 printf("0x%02"PRIx8, (int8_t) value);
295 break;
296 case SETTINGS_FORMAT_HEX16:
297 printf("0x%04"PRIx16, (int16_t) value);
298 break;
299 case SETTINGS_FORMAT_HEX32:
300 printf("0x%08"PRIx32, (int32_t) value);
301 break;
302 case SETTINGS_FORMAT_HEX64:
303 printf("0x%016"PRIx64, (int64_t) value);
304 break;
305 case SETTINGS_FORMAT_BOOL:
306 printf(value? "true" : "false");
307 break;
308 case SETTINGS_FORMAT_YESNO:
309 printf(value? "yes" : "no");
310 break;
311 case SETTINGS_FORMAT_STRING:
312 printf("\"%s\"", *((char **)settings->ptr[i]));
313 break;
314 default:printf("FATAL ERROR! Unknown presentation "
315 "format: %i\n",
316 settings->presentation_format[i]);
317 exit(1);
318 }
319
320 if (!settings->writable[i])
321 printf(" (R/O)");
322
323 printf("\n");
324 }
325 }
326
327 free(name);
328 }
329
330
331 /*
332 * settings_add():
333 *
334 * Add a setting to a settings object.
335 */
336 void settings_add(struct settings *settings, const char *name, int writable,
337 int type, int format, void *ptr)
338 {
339 int i;
340
341 for (i=0; i<settings->n_settings; i++) {
342 if (strcmp(settings->name[i], name) == 0)
343 break;
344 }
345
346 if (i < settings->n_settings) {
347 fprintf(stderr, "settings_add(): name '%s' is already"
348 " in use\n", name);
349 exit(1);
350 }
351
352 settings->n_settings ++;
353
354 CHECK_ALLOCATION(settings->name = realloc(settings->name,
355 settings->n_settings * sizeof(char *)));
356 CHECK_ALLOCATION(settings->writable = realloc(settings->writable,
357 settings->n_settings * sizeof(int)));
358 CHECK_ALLOCATION(settings->storage_type = realloc(
359 settings->storage_type, settings->n_settings * sizeof(int)));
360 CHECK_ALLOCATION(settings->presentation_format = realloc(settings->
361 presentation_format, settings->n_settings * sizeof(int)));
362 CHECK_ALLOCATION(settings->ptr = realloc(settings->ptr,
363 settings->n_settings * sizeof(void *)));
364
365 CHECK_ALLOCATION(settings->name[settings->n_settings - 1] =
366 strdup(name));
367 settings->writable[settings->n_settings - 1] = writable;
368 settings->storage_type[settings->n_settings - 1] = type;
369 settings->presentation_format[settings->n_settings - 1] = format;
370 settings->ptr[settings->n_settings - 1] = ptr;
371
372 if (type == SETTINGS_TYPE_SUBSETTINGS) {
373 ((struct settings *)ptr)->parent = settings;
374 CHECK_ALLOCATION( ((struct settings *)ptr)->name_in_parent =
375 strdup(name) );
376 }
377 }
378
379
380 /*
381 * settings_remove():
382 *
383 * Remove a setting from a settings object.
384 */
385 void settings_remove(struct settings *settings, const char *name)
386 {
387 int i, m;
388
389 for (i=0; i<settings->n_settings; i++) {
390 if (strcmp(settings->name[i], name) == 0)
391 break;
392 }
393
394 if (i >= settings->n_settings) {
395 #ifdef UNSTABLE_DEVEL
396 fprintf(stderr, "settings_remove(): attempting to remove"
397 " non-existant setting '%s'\n", name);
398 #endif
399 return;
400 }
401
402 /* Check subsettings specifically: */
403 if (settings->storage_type[i] == SETTINGS_TYPE_SUBSETTINGS &&
404 settings->ptr[i] != NULL) {
405 struct settings *subsettings = settings->ptr[i];
406 if (subsettings->n_settings != 0) {
407 fprintf(stderr, "settings_remove(): attempting to "
408 "remove non-emtpy setting '%s'\n", name);
409 fprintf(stderr, "Remaining settings are:\n");
410 for (i=0; i<subsettings->n_settings; i++)
411 fprintf(stderr, "\t%s\n", subsettings->name[i]);
412 exit(1);
413 }
414 }
415
416 settings->n_settings --;
417 free(settings->name[i]);
418
419 m = settings->n_settings - i;
420 if (m == 0)
421 return;
422
423 memmove(&settings->name[i], &settings->name[i+1],
424 m * sizeof(settings->name[0]));
425 memmove(&settings->writable[i], &settings->writable[i+1],
426 m * sizeof(settings->writable[0]));
427 memmove(&settings->storage_type[i], &settings->storage_type[i+1],
428 m * sizeof(settings->storage_type[0]));
429 memmove(&settings->presentation_format[i],
430 &settings->presentation_format[i+1],
431 m * sizeof(settings->presentation_format[0]));
432 memmove(&settings->ptr[i], &settings->ptr[i+1],
433 m * sizeof(settings->ptr[0]));
434 }
435
436
437 /*
438 * settings_remove_all():
439 *
440 * Remove all (level-1) settings from a settings object. By level-1, I mean
441 * all settings that do not contain subsettings.
442 */
443 void settings_remove_all(struct settings *settings)
444 {
445 while (settings->n_settings > 0)
446 settings_remove(settings, settings->name[0]);
447 }
448
449
450 /*
451 * settings_access():
452 *
453 * Read or write a setting. fullname may be something like "settings.x.y".
454 * When writing a value, valuebuf should point to a uint64_t containing the
455 * new value (note: always a uint64_t). When reading a value, valuebuf should
456 * point to a uint64_t where the value will be stored.
457 *
458 * The return value is one of the following:
459 *
460 * SETTINGS_OK
461 * The value was read or written.
462 *
463 * SETTINGS_NAME_NOT_FOUND
464 * The name was not found in the settings object.
465 *
466 * SETTINGS_READONLY
467 * The name was found, but it was marked as read-only, and
468 * an attempt was made to write to it.
469 */
470 int settings_access(struct settings *settings, const char *fullname,
471 int writeflag, uint64_t *valuep)
472 {
473 int i;
474
475 /* printf("settings_access(fullname='%s')\n", fullname); */
476
477 if (strncmp(fullname, GLOBAL_SETTINGS_NAME".",
478 strlen(GLOBAL_SETTINGS_NAME) + 1) == 0)
479 fullname += strlen(GLOBAL_SETTINGS_NAME) + 1;
480
481 for (i=0; i<settings->n_settings; i++) {
482 size_t settings_name_len = strlen(settings->name[i]);
483
484 if (strncmp(fullname, settings->name[i],
485 settings_name_len) != 0)
486 continue;
487
488 /* Found the correct setting? */
489 if (fullname[settings_name_len] == '\0') {
490 if (writeflag)
491 return settings_write(settings, i, valuep);
492 else
493 return settings_read(settings, i, valuep);
494 }
495
496 /* Found a setting which has sub-settings? */
497 if (fullname[settings_name_len] == '.') {
498 /* Recursive search: */
499 return settings_access(
500 (struct settings *)settings->ptr[i],
501 fullname + settings_name_len + 1,
502 writeflag, valuep);
503 }
504 }
505
506 return SETTINGS_NAME_NOT_FOUND;
507 }
508

  ViewVC Help
Powered by ViewVC 1.1.26