9#include "wvstringtable.h"
14#ifdef DEBUG_DEL_CALLBACK
34static int parse_wvconf_request(
char *request,
char *§ion,
35 char *&entry,
char *&value)
39 section = strchr(request,
'[');
45 entry = strchr(section,
']');
51 value = strchr(entry,
'=');
68static void do_setbool(
void *userdata,
69 WvStringParm section, WvStringParm key,
70 WvStringParm oldval, WvStringParm newval)
72 bool* b =
static_cast<bool*
>(userdata);
78static void do_addname(
void *userdata,
79 WvStringParm section, WvStringParm key,
80 WvStringParm oldval, WvStringParm newval)
89 WvConfigEntryEmu* entry = entries[s];
91 if (uniconf[s].exists())
95 entry =
new WvConfigEntryEmu(s, uniconf[s].getme());
96 entries.add(entry,
true);
99 entry->value = uniconf[s].getme();
108const char *WvConfigSectionEmu::get(WvStringParm entry,
const char *def_val)
113 WvString s(uniconf[entry].getme(def_val));
116 WvString *sp = values[s];
117 if (!sp) values.add(sp =
new WvString(s),
true);
122void WvConfigSectionEmu::set(WvStringParm entry, WvStringParm value)
127 uniconf[entry].setme(value);
129 uniconf[entry].setme(WvString::null);
134void WvConfigSectionEmu::quick_set(WvStringParm entry, WvStringParm value)
136 uniconf[entry].setme(value);
140bool WvConfigSectionEmu::isempty()
const
142 return !uniconf.haschildren();
146WvConfigSectionEmu::Iter::~Iter()
151void WvConfigSectionEmu::Iter::rewind()
154 link.data = entry = NULL;
158WvLink *WvConfigSectionEmu::Iter::next()
170 entry = sect[iter->fullkey(sect.uniconf)];
171 link.data =
static_cast<void*
>(entry);
181WvLink *WvConfigSectionEmu::Iter::cur()
187WvConfigEntryEmu *WvConfigSectionEmu::Iter::ptr()
const
193void *WvConfigSectionEmu::Iter::vptr()
const
199void WvConfEmu::notify(
const UniConf &_uni,
const UniConfKey &_key)
201 WvString section(_key.
first());
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);
221WvConfEmu::WvConfEmu(
const UniConf &_uniconf)
222 : sections(42), hold(false), values(420), uniconf(_uniconf)
225 uniconf.add_callback(
this, wv::bind(&WvConfEmu::notify,
this, _1, _2),
231WvConfEmu::~WvConfEmu()
237#ifndef DEBUG_DEL_CALLBACK
238 assert(callbacks.isempty());
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);
253 uniconf.del_callback(
this);
263bool WvConfEmu::isclean()
const
265 return isok() && !dirty;
269bool WvConfEmu::isok()
const
271 return !uniconf.isnull();
275void WvConfEmu::load_file(WvStringParm filename)
277 UniConfRoot new_uniconf(WvString(
"ini:%s", filename));
280 new_uniconf.copy(uniconf,
true);
285void 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();
295void WvConfEmu::save()
301void WvConfEmu::flush()
310 if (UniConfKey(sect).numsegments() != 1)
313 WvConfigSectionEmu* section = sections[sect];
315 if (!section && uniconf[sect].exists())
317 section =
new WvConfigSectionEmu(uniconf[sect], sect, &values);
318 sections.add(section,
true);
325void WvConfEmu::add_callback(WvConfCallback callback,
void *userdata,
326 WvStringParm section, WvStringParm key,
332 WvList<CallbackInfo>::Iter i(callbacks);
333 for (i.rewind(); i.next(); )
335 if (i->cookie == cookie
336 && i->section == section
341#ifdef DEBUG_DEL_CALLBACK
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");
352 callbacks.append(
new CallbackInfo(callback, userdata, section, key,
358void WvConfEmu::del_callback(WvStringParm section, WvStringParm key,
void *cookie)
360 WvList<CallbackInfo>::Iter i(callbacks);
364 for (i.rewind(); i.next(); )
366 if (i->cookie == cookie
367 && i->section == section
370#ifdef DEBUG_DEL_CALLBACK
371 fprintf(stderr,
"TRACE:del:%s:%s:%p\n", section.
cstr(), key.
cstr(), cookie);
379void WvConfEmu::add_setbool(
bool *b, WvStringParm _section, WvStringParm _key)
381 add_callback(do_setbool, b, _section, _key, b);
385void WvConfEmu::del_setbool(
bool *b, WvStringParm _section, WvStringParm _key)
387 del_callback(_section, _key, b);
391void WvConfEmu::add_addname(
WvStringList *list, WvStringParm sect, WvStringParm ent)
393 add_callback(do_addname, list, sect, ent, list);
398 WvStringParm sect, WvStringParm ent)
400 del_callback(sect, ent, list);
406 char *section, *entry, *value;
407 parse_error = parse_wvconf_request(wvconfstr.
edit(),
408 section, entry, value);
413 return get(section, entry, value);
417int WvConfEmu::getint(WvStringParm section, WvStringParm entry,
int def_val)
419 if (!section || !entry)
422 return uniconf[section][entry].getmeint(def_val);
426const char *WvConfEmu::get(WvStringParm section, WvStringParm entry,
429 if (!section || !entry)
432 WvString s(uniconf[section][entry].getme(def_val));
435 WvString *sp = values[s];
436 if (!sp) values.add(sp =
new WvString(s),
true);
440int WvConfEmu::fuzzy_getint(
WvStringList §, WvStringParm entry,
443 WvString def_str(def_val);
444 return check_for_bool_string(fuzzy_get(sect, entry, def_str));
448const char *WvConfEmu::fuzzy_get(
WvStringList §, WvStringParm entry,
451 WvStringList::Iter i(sect);
452 WvStringTable cache(5);
453 WvConfigSectionEmu *s;
455 for (i.rewind(); i.next(); )
458 s && !cache[s->name];
459 s = (*s)[
"Inherits"] ? (*this)[(*s)[
"Inherits"]->value] : NULL)
461 const char *ret = s->get(entry);
463 cache.add(&s->name,
false);
470void WvConfEmu::setraw(
WvString wvconfstr,
const char *&_value,
473 char *section, *entry, *value;
474 parse_error = parse_wvconf_request(wvconfstr.
edit(),
475 section, entry, value);
478 set(section, entry, value);
479 _value = get(section, entry, value);
486void WvConfEmu::setint(WvStringParm section, WvStringParm entry,
int value)
489 uniconf[section][entry].setmeint(value);
493void WvConfEmu::set(WvStringParm section, WvStringParm entry,
498 if (value && value[0] != 0)
499 uniconf[section][entry].setme(value);
501 uniconf[section][entry].setme(WvString::null);
507void WvConfEmu::maybesetint(WvStringParm section, WvStringParm entry,
510 if (!!entry && !get(section, entry, NULL))
511 setint(section, entry, value);
515void WvConfEmu::maybeset(WvStringParm section, WvStringParm entry,
518 if (!!entry && get(section, entry, 0) == 0)
519 set(section, entry, value);
523void WvConfEmu::delete_section(WvStringParm section)
525 uniconf[section].remove();
530int 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)
537 if (strcasecmp(s,
"on") == 0
538 || strcasecmp(s,
"true") == 0
539 || strcasecmp(s,
"yes") == 0)
547void WvConfEmu::Iter::rewind()
554WvLink *WvConfEmu::Iter::next()
557 while (link.data == NULL && iter.next())
559 link.data =
static_cast<void*
>(conf[iter->key()]);
569WvConfigSectionEmu *WvConfEmu::Iter::ptr()
const
571 return conf[iter->key()];
UniConfKey removefirst(int n=1) const
Returns the path formed by removing the first n segments of this path.
UniConfKey first(int n=1) const
Returns the path formed by the n first segments of this path.
const char * cstr() const
return a (const char *) for this string.
This is a WvList of WvStrings, and is a really handy way to parse strings.
WvString is an implementation of a simple and efficient printable-string class.
char * edit()
make the string editable, and return a non-const (char*)
char * trim_string(char *string)
Trims whitespace from the beginning and end of the character string, including carriage return / line...