Fix several warnings that appear in gcc 4.3.2.
[wvstreams.git] / uniconf / wvconfemu.cc
blob9e614f065164f2a136b11806cce9a0f27b301966
1 /*
2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
5 * Basic WvConf emulation layer for UniConf.
6 */
7 #include "wvconfemu.h"
8 #include "uniinigen.h"
9 #include "wvstringtable.h"
10 #include "wvfile.h"
11 #include "strutils.h"
13 //#define DEBUG_DEL_CALLBACK 1
14 #ifdef DEBUG_DEL_CALLBACK
15 #include <execinfo.h>
16 #endif
19 * Parse the WvConf string "request"; pointers to the found section,
20 * entry, and value fields are stored in *section, *entry, and *value
21 * respectively, and request[] is modified.
23 * For example, the string:
24 * [silly]billy=willy
25 * is parsed into:
26 * section="silly"; entry="billy"; value="willy";
28 * Returns 0 on success, -1 if the command is missing the '[', -2 if
29 * the string is missing a ']', or -3 if the section or entry is
30 * blank. If a "value" is not found (ie. there is no equal sign
31 * outside the [] brackets) this does not qualify as an error, but
32 * *value is set to NULL.
34 static int parse_wvconf_request(char *request, char *&section,
35 char *&entry, char *&value)
37 entry = value = NULL;
39 section = strchr(request, '[');
40 if (!section)
41 return -1;
43 section++;
45 entry = strchr(section, ']');
46 if (!entry)
47 return -2;
49 *entry++ = 0;
51 value = strchr(entry, '=');
52 if (value)
54 *value++ = 0;
55 value = trim_string(value);
58 section = trim_string(section);
59 entry = trim_string(entry);
61 if (!*section)
62 return -3;
64 return 0;
68 static void do_setbool(void *userdata,
69 WvStringParm section, WvStringParm key,
70 WvStringParm oldval, WvStringParm newval)
72 bool* b = static_cast<bool*>(userdata);
74 *b = true;
78 static void do_addname(void *userdata,
79 WvStringParm section, WvStringParm key,
80 WvStringParm oldval, WvStringParm newval)
82 if (!!key)
83 (*(WvStringList *)userdata).append(new WvString(key), true);
87 WvConfigEntryEmu *WvConfigSectionEmu::operator[] (WvStringParm s)
89 WvConfigEntryEmu* entry = entries[s];
91 if (uniconf[s].exists())
93 if (!entry)
95 entry = new WvConfigEntryEmu(s, uniconf[s].getme());
96 entries.add(entry, true);
98 else
99 entry->value = uniconf[s].getme();
101 else
102 entry = NULL;
104 return entry;
108 const char *WvConfigSectionEmu::get(WvStringParm entry, const char *def_val)
110 if (!entry)
111 return def_val;
113 WvString s(uniconf[entry].getme(def_val));
115 // look it up in the cache
116 WvString *sp = values[s];
117 if (!sp) values.add(sp = new WvString(s), true);
118 return sp->cstr();
122 void WvConfigSectionEmu::set(WvStringParm entry, WvStringParm value)
124 if (!!entry)
126 if (!!value)
127 uniconf[entry].setme(value);
128 else
129 uniconf[entry].setme(WvString::null);
134 void WvConfigSectionEmu::quick_set(WvStringParm entry, WvStringParm value)
136 uniconf[entry].setme(value);
140 bool WvConfigSectionEmu::isempty() const
142 return !uniconf.haschildren();
146 WvConfigSectionEmu::Iter::~Iter()
151 void WvConfigSectionEmu::Iter::rewind()
153 iter.rewind();
154 link.data = entry = NULL;
158 WvLink *WvConfigSectionEmu::Iter::next()
160 while (iter.next())
162 // WvConf-enabled code expects all set keys to be non-empty;
163 // enforce this behaviour
164 if (!!iter->getme())
167 * FIXME: if the WvConfEmu is not at the root of the
168 * UniConf tree, this will give an incorrect result.
170 entry = sect[iter->fullkey(sect.uniconf)];
171 link.data = static_cast<void*>(entry);
172 assert(entry);
173 return &link;
177 return NULL;
181 WvLink *WvConfigSectionEmu::Iter::cur()
183 return &link;
187 WvConfigEntryEmu *WvConfigSectionEmu::Iter::ptr() const
189 return entry;
193 void *WvConfigSectionEmu::Iter::vptr() const
195 return link.data;
199 void WvConfEmu::notify(const UniConf &_uni, const UniConfKey &_key)
201 WvString section(_key.first());
202 WvString key(_key.removefirst());
204 if (hold)
205 return;
207 WvString value = uniconf[section][key].getme("");
209 WvList<CallbackInfo>::Iter i(callbacks);
210 for (i.rewind(); i.next(); )
212 if ((!i->section || !strcasecmp(i->section, section))
213 && (!i->key || !strcasecmp(i->key, key)))
215 i->callback(i->userdata, section, key, WvString(), value);
221 WvConfEmu::WvConfEmu(const UniConf &_uniconf)
222 : sections(42), hold(false), values(420), uniconf(_uniconf)
224 wvauthd = NULL;
225 uniconf.add_callback(this, wv::bind(&WvConfEmu::notify, this, _1, _2),
226 true);
227 dirty = false;
231 WvConfEmu::~WvConfEmu()
233 // things will "work" if you don't empty the callback list before
234 // deleting the WvConfEmu, but they probably won't work the way you
235 // think they will. (ie. someone might be using a temporary WvConfEmu
236 // and think his callbacks will stick around; they won't!)
237 #ifndef DEBUG_DEL_CALLBACK
238 assert(callbacks.isempty());
239 #else
240 if (!callbacks.isempty())
242 WvList<CallbackInfo>::Iter i(callbacks);
244 fprintf(stderr, " *** leftover callbacks in WvConfEmu ***\n");
245 for (i.rewind(); i.next(); )
247 fprintf(stderr, " - [%s]%s (%p)\n", i->section.cstr(),
248 i->key.cstr(), i->cookie);
251 #endif
253 uniconf.del_callback(this);
257 void WvConfEmu::zap()
259 uniconf.remove();
263 bool WvConfEmu::isclean() const
265 return isok() && !dirty;
269 bool WvConfEmu::isok() const
271 return !uniconf.isnull();
275 void WvConfEmu::load_file(WvStringParm filename)
277 UniConfRoot new_uniconf(WvString("ini:%s", filename));
279 hold = true;
280 new_uniconf.copy(uniconf, true);
281 hold = false;
285 void WvConfEmu::save(WvStringParm filename, int _create_mode)
287 UniConfRoot tmp_uniconf(new UniIniGen(filename, _create_mode), false);
289 uniconf.copy(tmp_uniconf, true);
291 tmp_uniconf.commit();
295 void WvConfEmu::save()
297 uniconf.commit();
301 void WvConfEmu::flush()
303 uniconf.commit();
304 dirty = false;
308 WvConfigSectionEmu *WvConfEmu::operator[] (WvStringParm sect)
310 if (UniConfKey(sect).numsegments() != 1)
311 return NULL;
313 WvConfigSectionEmu* section = sections[sect];
315 if (!section && uniconf[sect].exists())
317 section = new WvConfigSectionEmu(uniconf[sect], sect, &values);
318 sections.add(section, true);
321 return section;
325 void WvConfEmu::add_callback(WvConfCallback callback, void *userdata,
326 WvStringParm section, WvStringParm key,
327 void *cookie)
329 if (!callback)
330 return;
332 WvList<CallbackInfo>::Iter i(callbacks);
333 for (i.rewind(); i.next(); )
335 if (i->cookie == cookie
336 && i->section == section
337 && i->key == key)
338 return;
341 #ifdef DEBUG_DEL_CALLBACK
342 void* trace[10];
343 int count = backtrace(trace, sizeof(trace)/sizeof(trace[0]));
344 char** tracedump = backtrace_symbols(trace, count);
345 fprintf(stderr, "TRACE:add:%s:%s:%p", section.cstr(), key.cstr(), cookie);
346 for (int i = 0; i < count; ++i)
347 fprintf(stderr, ":%s", tracedump[i]);
348 fprintf(stderr, "\n");
349 free(tracedump);
350 #endif
352 callbacks.append(new CallbackInfo(callback, userdata, section, key,
353 cookie),
354 true);
358 void WvConfEmu::del_callback(WvStringParm section, WvStringParm key, void *cookie)
360 WvList<CallbackInfo>::Iter i(callbacks);
362 assert(cookie);
364 for (i.rewind(); i.next(); )
366 if (i->cookie == cookie
367 && i->section == section
368 && i->key == key)
370 #ifdef DEBUG_DEL_CALLBACK
371 fprintf(stderr, "TRACE:del:%s:%s:%p\n", section.cstr(), key.cstr(), cookie);
372 #endif
373 i.xunlink();
379 void WvConfEmu::add_setbool(bool *b, WvStringParm _section, WvStringParm _key)
381 add_callback(do_setbool, b, _section, _key, b);
385 void WvConfEmu::del_setbool(bool *b, WvStringParm _section, WvStringParm _key)
387 del_callback(_section, _key, b);
391 void WvConfEmu::add_addname(WvStringList *list, WvStringParm sect, WvStringParm ent)
393 add_callback(do_addname, list, sect, ent, list);
397 void WvConfEmu::del_addname(WvStringList *list,
398 WvStringParm sect, WvStringParm ent)
400 del_callback(sect, ent, list);
404 WvString WvConfEmu::getraw(WvString wvconfstr, int &parse_error)
406 char *section, *entry, *value;
407 parse_error = parse_wvconf_request(wvconfstr.edit(),
408 section, entry, value);
410 if (parse_error)
411 return WvString();
413 return get(section, entry, value);
417 int WvConfEmu::getint(WvStringParm section, WvStringParm entry, int def_val)
419 if (!section || !entry)
420 return def_val;
422 return uniconf[section][entry].getmeint(def_val);
426 const char *WvConfEmu::get(WvStringParm section, WvStringParm entry,
427 const char *def_val)
429 if (!section || !entry)
430 return def_val;
432 WvString s(uniconf[section][entry].getme(def_val));
434 // look it up in the cache
435 WvString *sp = values[s];
436 if (!sp) values.add(sp = new WvString(s), true);
437 return sp->cstr();
440 int WvConfEmu::fuzzy_getint(WvStringList &sect, WvStringParm entry,
441 int def_val)
443 WvString def_str(def_val);
444 return check_for_bool_string(fuzzy_get(sect, entry, def_str));
448 const char *WvConfEmu::fuzzy_get(WvStringList &sect, WvStringParm entry,
449 const char *def_val)
451 WvStringList::Iter i(sect);
452 WvStringTable cache(5);
453 WvConfigSectionEmu *s;
455 for (i.rewind(); i.next(); )
457 for(s = (*this)[*i];
458 s && !cache[s->name];
459 s = (*s)["Inherits"] ? (*this)[(*s)["Inherits"]->value] : NULL)
461 const char *ret = s->get(entry);
462 if (ret) return ret;
463 cache.add(&s->name, false);
467 return def_val;
470 void WvConfEmu::setraw(WvString wvconfstr, const char *&_value,
471 int &parse_error)
473 char *section, *entry, *value;
474 parse_error = parse_wvconf_request(wvconfstr.edit(),
475 section, entry, value);
476 if (!parse_error)
478 set(section, entry, value);
479 _value = get(section, entry, value);
481 else
482 _value = NULL;
486 void WvConfEmu::setint(WvStringParm section, WvStringParm entry, int value)
488 if (!!entry)
489 uniconf[section][entry].setmeint(value);
493 void WvConfEmu::set(WvStringParm section, WvStringParm entry,
494 const char *value)
496 if (!!entry)
498 if (value && value[0] != 0)
499 uniconf[section][entry].setme(value);
500 else
501 uniconf[section][entry].setme(WvString::null);
502 dirty = true;
507 void WvConfEmu::maybesetint(WvStringParm section, WvStringParm entry,
508 int value)
510 if (!!entry && !get(section, entry, NULL))
511 setint(section, entry, value);
515 void WvConfEmu::maybeset(WvStringParm section, WvStringParm entry,
516 const char *value)
518 if (!!entry && get(section, entry, 0) == 0)
519 set(section, entry, value);
523 void WvConfEmu::delete_section(WvStringParm section)
525 uniconf[section].remove();
526 dirty = true;
530 int WvConfEmu::check_for_bool_string(const char *s)
532 if (strcasecmp(s, "off") == 0
533 || strcasecmp(s, "false") == 0
534 || strncasecmp(s, "no", 2) == 0) // also handles "none"
535 return 0;
537 if (strcasecmp(s, "on") == 0
538 || strcasecmp(s, "true") == 0
539 || strcasecmp(s, "yes") == 0)
540 return 1;
542 // not a special bool case, so just return the number
543 return atoi(s);
547 void WvConfEmu::Iter::rewind()
549 iter.rewind();
550 link.data = NULL;
554 WvLink *WvConfEmu::Iter::next()
556 link.data = NULL;
557 while (link.data == NULL && iter.next())
559 link.data = static_cast<void*>(conf[iter->key()]);
561 if (link.data)
563 return &link;
565 return NULL;
569 WvConfigSectionEmu *WvConfEmu::Iter::ptr() const
571 return conf[iter->key()];