configure.ac: if neither boost nor tr1 is available, die right away.
[wvstreams.git] / uniconf / uniconf.cc
bloba373ec27e532518f83c78b5b6a98f3124896f05c
1 /*
2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
4 *
5 * Defines a hierarchical registry abstraction. See uniconf.h.
6 */
7 #include "uniconf.h"
8 #include "uniconfroot.h"
9 #include "uniconfgen.h"
10 #include "wvstream.h"
11 #include <assert.h>
14 UniConf::UniConf(UniConfRoot *root, const UniConfKey &fullkey)
15 : xroot(root), xfullkey(fullkey)
17 // nothing special
21 UniConf::UniConf() : xroot(NULL), xfullkey(UniConfKey::EMPTY)
23 // nothing special
27 UniConf::UniConf(const UniConf &other)
28 : xroot(other.xroot), xfullkey(other.xfullkey)
30 // nothing special
34 UniConf::~UniConf()
36 // nothing special
42 UniConfKey UniConf::fullkey(const UniConfKey &k) const
44 return k.subkey(xfullkey);
48 bool UniConf::exists() const
50 return xroot->mounts.exists(xfullkey);
54 bool UniConf::haschildren() const
56 return xroot->mounts.haschildren(xfullkey);
60 void UniConf::prefetch(bool recursive) const
62 xroot->mounts.prefetch(xfullkey, recursive);
66 WvString UniConf::getme(WvStringParm defvalue) const
68 WvString value = xroot->mounts.get(xfullkey);
69 if (value.isnull())
70 return defvalue;
71 return value;
75 int UniConf::getmeint(int defvalue) const
77 return xroot->mounts.str2int(getme(), defvalue);
81 void UniConf::setme(WvStringParm value) const
83 xroot->mounts.set(xfullkey, value);
87 void UniConf::setmeint(int value) const
89 setme(WvString(value));
93 void UniConf::move(const UniConf &dst) const
95 dst.remove();
96 copy(dst, true);
97 remove();
101 void UniConf::copy(const UniConf &dst, bool force) const
103 // do the main key first
104 dst.setme(getme());
106 // now all the children
107 RecursiveIter i(*this);
108 for (i.rewind(); i.next(); )
110 UniConf dst2 = dst[i->fullkey(*this)];
111 if (force || dst2.getme().isnull())
112 dst2.setme(i->getme());
117 bool UniConf::refresh() const
119 return xroot->mounts.refresh();
123 void UniConf::commit() const
125 xroot->mounts.commit();
129 IUniConfGen *UniConf::mount(WvStringParm moniker, bool refresh) const
131 return xroot->mounts.mount(xfullkey, moniker, refresh);
135 IUniConfGen *UniConf::mountgen(IUniConfGen *gen, bool refresh) const
137 return xroot->mounts.mountgen(xfullkey, gen, refresh);
141 void UniConf::unmount(IUniConfGen *gen, bool commit) const
143 return xroot->mounts.unmount(gen, commit);
147 bool UniConf::ismountpoint() const
149 return xroot->mounts.ismountpoint(xfullkey);
153 IUniConfGen *UniConf::whichmount(UniConfKey *mountpoint) const
155 return xroot->mounts.whichmount(xfullkey, mountpoint);
159 bool UniConf::isok() const
161 IUniConfGen *gen = whichmount();
162 return gen && gen->isok();
166 void UniConf::add_callback(void *cookie, const UniConfCallback &callback,
167 bool recurse) const
169 xroot->add_callback(cookie, xfullkey, callback, recurse);
173 void UniConf::del_callback(void *cookie, bool recurse) const
175 xroot->del_callback(cookie, xfullkey, recurse);
179 void UniConf::add_setbool(bool *flag, bool recurse) const
181 xroot->add_setbool(xfullkey, flag, recurse);
185 void UniConf::del_setbool(bool *flag, bool recurse) const
187 xroot->del_setbool(xfullkey, flag, recurse);
191 void UniConf::hold_delta()
193 xroot->mounts.hold_delta();
197 void UniConf::unhold_delta()
199 xroot->mounts.unhold_delta();
203 void UniConf::clear_delta()
205 xroot->mounts.clear_delta();
209 void UniConf::flush_delta()
211 xroot->mounts.flush_delta();
215 void UniConf::dump(WvStream &stream, bool everything) const
217 UniConf::RecursiveIter it(*this);
218 for (it.rewind(); it.next(); )
220 WvString value(it->getme());
221 if (everything || !!value)
222 stream.print("%s = %s\n", it->fullkey(), value);
228 /***** UniConf::Iter *****/
230 UniConf::Iter::Iter(const UniConf &_top)
231 : IterBase(_top)
233 it = _top.rootobj()->mounts.iterator(top.fullkey());
234 if (!it) it = new UniConfGen::NullIter;
239 /***** UniConf::RecursiveIter *****/
241 UniConf::RecursiveIter::RecursiveIter(const UniConf &_top)
242 : IterBase(_top)
244 it = _top.rootobj()->mounts.recursiveiterator(top.fullkey());
245 if (!it) it = new UniConfGen::NullIter;
249 /***** UniConf::XIter *****/
251 UniConf::XIter::XIter(const UniConf &_top, const UniConfKey &pattern)
252 : IterBase(_top), pathead(pattern.first()),
253 pattail(pattern.removefirst()), subit(NULL), it(NULL), recit(NULL)
255 if (! pathead.iswild())
257 // optimization to collect as many consecutive non-wildcard
258 // segments as possible in one go
259 while (! pattail.isempty())
261 UniConfKey patnext(pattail.first());
262 if (patnext.iswild())
263 break;
264 pathead.append(patnext);
265 pattail = pattail.removefirst();
271 UniConf::XIter::~XIter()
273 cleanup();
277 void UniConf::XIter::cleanup()
279 if (subit)
281 delete subit;
282 subit = NULL;
284 if (it)
286 delete it;
287 it = NULL;
289 if (recit)
291 delete recit;
292 recit = NULL;
297 void UniConf::XIter::rewind()
299 cleanup();
300 ready = false;
302 if (pathead.isempty())
304 current = top;
305 ready = current.exists();
307 else if (pathead == UniConfKey::RECURSIVE_ANY)
309 recit = new UniConf::RecursiveIter(top);
310 recit->rewind();
311 if (UniConfKey::EMPTY.matches(pattail))
313 // pattern includes self
314 current = top;
315 ready = current.exists();
318 else if (pathead == UniConfKey::ANY)
320 it = new UniConf::Iter(top);
321 it->rewind();
323 else
325 // non-wildcard segment
326 current = top[pathead];
327 if (pattail.isempty())
329 // don't bother recursing if there are no deeper wildcard
330 // elements (works together with optimization in constructor)
331 ready = current.exists();
333 else
335 // more wildcards, setup recursion
336 enter(current);
342 inline bool UniConf::XIter::qnext()
344 if (subit) // currently in a sub-iterator
346 bool found = subit->next();
347 if (found)
349 current = **subit;
350 return true;
352 else
354 // end of this sub-iterator
355 delete subit;
356 subit = NULL;
357 return false;
360 else // no sub-iterator at all
361 return false;
365 void UniConf::XIter::enter(const UniConf &child)
367 subit = new UniConf::XIter(child, pattail);
368 subit->rewind();
372 bool UniConf::XIter::next()
374 if (ready)
376 ready = false;
377 return true;
379 while (!qnext())
381 // UniConfKey::ANY
382 if (it && it->next())
384 /* Not needed for now since we don't match partial keys
385 if (! pathead.matches(it->key()))
386 break;
388 enter(**it);
389 continue;
391 // UniConfKey::RECURSIVE_ANY
392 if (recit && recit->next())
394 enter(**recit);
395 continue;
397 // anything else or finished
398 return false;
401 // if we get here, qnext() returned true
402 return true;
407 /***** UniConf::SortedIterBase *****/
409 UniConf::SortedIterBase::SortedIterBase(const UniConf &root,
410 UniConf::SortedIterBase::Comparator comparator)
411 : IterBase(root), xcomparator(comparator), xkeys()
416 UniConf::SortedIterBase::~SortedIterBase()
418 _purge();
422 int UniConf::SortedIterBase::defcomparator(const UniConf &a,
423 const UniConf &b)
425 return a.fullkey().compareto(b.fullkey());
429 static UniConf::SortedIterBase::Comparator innercomparator = NULL;
431 static bool wrapcomparator(const UniConf &a, const UniConf &b)
433 return innercomparator(a, b) < 0;
437 void UniConf::SortedIterBase::_purge()
439 count = xkeys.size();
440 xkeys.clear();
444 void UniConf::SortedIterBase::_rewind()
446 index = 0;
447 count = xkeys.size();
449 // This code is NOT reentrant because qsort makes it too hard
450 innercomparator = xcomparator;
451 std::sort(xkeys.begin(), xkeys.end(), wrapcomparator);
455 bool UniConf::SortedIterBase::next()
457 if (index >= count)
458 return false;
459 current = xkeys[index];
460 index += 1;
461 return true;