Make WvStreams compile with gcc 4.4.
[wvstreams.git] / include / uniconf.h
blobc4e796fb58df562dee78d8aa0d6cc00d05565cfb
1 /* -*- Mode: C++ -*-
2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
4 *
5 * Defines a hierarchical registry abstraction.
6 */
7 #ifndef __UNICONF_H
8 #define __UNICONF_H
10 #include <vector>
12 #include "uniconfgen.h"
13 #include "uniconfkey.h"
14 #include "wvtr1.h"
16 class WvStream;
17 class UniConf;
18 class UniConfRoot;
20 /**
21 * The callback type for signalling key changes from UniConf.
23 * Parameters: cfg, relkey
24 * cfg - the UniConf config object representing the key that has changed
25 * relkey - the changed keypath, relative to the config object
27 typedef wv::function<void(const UniConf&, const UniConfKey&)> UniConfCallback;
29 /**
30 * UniConf instances function as handles to subtrees of a UniConf
31 * tree and expose a high-level interface for clients.
33 * All operations are marked "const" unless they modify the target
34 * of the handle. In effect, this grants UniConf handles the
35 * same semantics as pointers where a const pointer may point
36 * to a non-const object, which simply means that the pointer
37 * cannot be reassigned.
39 * When handles are returned from functions, they are always marked
40 * const to guard against accidentally assigning to a temporary by
41 * an expression such as cfg["foo"] = cfg["bar"].
42 * Instead this must be written as
43 * cfg["foo"].setme(cfg["bar"].getme())
44 * which is slightly
45 * less elegant but avoids many subtle mistakes. Also for this
46 * reason, unusual cast operators, assignment operators,
47 * or copy constructors are not provided. Please do not add any.
50 class UniConf
52 friend class UniConfRoot;
54 protected:
55 UniConfRoot *xroot;
56 UniConfKey xfullkey;
58 /**
59 * Creates a handle to the specified subtree of the given root.
61 * You can't create non-NULL UniConf objects yourself - ask UniConfRoot
62 * or another UniConf object to make one for you.
64 UniConf(UniConfRoot *root, const UniConfKey &fullkey = UniConfKey::EMPTY);
66 public:
67 /** Creates a NULL UniConf handle, useful for reporting errors. */
68 UniConf();
70 /** Copies a UniConf handle. */
71 UniConf(const UniConf &other);
73 /** Destroys the UniConf handle. */
74 virtual ~UniConf();
77 /***** Handle Manipulation API *****/
79 /** Returns a handle to the root of the tree. */
80 UniConf root() const
81 { return UniConf(xroot, UniConfKey::EMPTY); }
83 /** Returns a handle to the parent of this node. */
84 UniConf parent() const
85 { return UniConf(xroot, xfullkey.removelast()); }
87 /**
88 * Returns a pointer to the UniConfRoot that manages this node.
89 * This may be NULL, to signal an invalid handle.
91 UniConfRoot *rootobj() const
92 { return xroot; }
94 /** Returns true if the handle is invalid (NULL). */
95 bool isnull() const
96 { return xroot == NULL; }
98 /** Returns the full path of this node, starting at the root. */
99 UniConfKey fullkey() const
100 { return xfullkey; }
102 /** Returns the full path of this node, starting at the given key.
103 * Assumes that k is an ancestor of fullkey(). */
104 UniConfKey fullkey(const UniConfKey &k) const;
106 /** Returns the full path of this node, starting at the given handle. */
107 UniConfKey fullkey(const UniConf &cfg) const
108 { return fullkey(cfg.fullkey()); }
110 /** Returns the path of this node relative to its parent. */
111 UniConfKey key() const
112 { return xfullkey.last(); }
115 * Returns a handle for a subtree below this key. 'key' is the path
116 * of the subtree to be appended to the full path of this handle to
117 * obtain the full path of the new handle.
119 const UniConf operator[] (const UniConfKey &key) const
120 { return UniConf(xroot, UniConfKey(xfullkey, key)); }
123 * Return a subtree handle (see operator[]). Mainly to support bindings
124 * for languages that can't handle methods named [].
126 const UniConf u(const UniConfKey &key) const
127 { return (*this)[key]; }
129 /** Reassigns the target of this handle to match a different one. */
130 UniConf &operator= (const UniConf &other)
132 xroot = other.xroot;
133 xfullkey = other.xfullkey;
134 return *this;
138 /***** Key Retrieval API *****/
140 /** See UniConfGen::prefetch(). */
141 void prefetch(bool recursive) const;
144 * Fetches the string value for this key from the registry. If the
145 * key is not found, returns 'defvalue' instead.
147 WvString getme(WvStringParm defvalue = WvString::null) const;
149 /** A different way to say cfg.getme(): use *cfg instead. */
150 WvString operator* () const
151 { return getme(); }
153 /** A different way to say cfg.getme().num(): use cfg->num() instead. */
154 WvStringStar operator -> () const
155 { return getme(); }
157 /** A different way to say cfg[x].getme(y). */
158 WvString xget(WvStringParm key,
159 WvStringParm defvalue = WvString::null) const
160 { return (*this)[key].getme(defvalue); }
163 * Fetches the integer value for this key from the registry. If the
164 * key is not found, returns 'defvalue' instead. (This is also used to
165 * fetch booleans - 'true', 'yes', 'on' and 'enabled' are recognized as
166 * 1, 'false', 'no', 'off' and 'disabled' as 0. Note that a nonexistant
167 * key is false by default.)
169 int getmeint(int defvalue = 0) const;
171 /** A different way to say cfg[x].getmeint(y). */
172 int xgetint(WvStringParm key, int defvalue = 0) const
173 { return (*this)[key].getmeint(defvalue); }
176 * Without fetching its value, returns true if this key exists.
178 * This is provided because it is often more efficient to
179 * test existance than to actually retrieve the value.
181 bool exists() const;
184 /***** Key Storage API *****/
187 * Stores a string value for this key into the registry. If the value
188 * is WvString::null, deletes the key and all of its children.
190 void setme(WvStringParm value) const;
193 * Stores a string value for this key into the registry.
195 void setme(WVSTRING_FORMAT_DECL) const
196 { return setme(WvString(WVSTRING_FORMAT_CALL)); }
198 /** A different way to say cfg[x].setme(y). */
199 void xset(WvStringParm key, WvStringParm value) const
200 { (*this)[key].setme(value); }
203 * Stores an integer value for this key into the registry.
205 void setmeint(int value) const;
207 /** A different way to say cfg[x].setme(y). */
208 void xsetint(WvStringParm key, int value) const
209 { (*this)[key].setmeint(value); }
212 /***** Key Handling API *****/
215 * Equivalent to "mv" in a standard unix filesystem. This recursively
216 * moves a given key and any subkeys to a new point. If the new point
217 * exists then the key will be left as a subkey at the new point.
218 * Otherwise, the key will also be renamed to the new point (as when
219 * using mv).
221 * Don't try to do dumb stuff like making dst a subkey of this one,
222 * or vice versa, because we won't try to save you.
224 * Unlike unix mv(), this is *not* currently atomic. It's more like
225 * cp-then-rm.
227 void move(const UniConf &dst) const;
230 * Removes this key and all of its children from the registry.
232 void remove() const
233 { setme(WvString::null); }
236 * Equivalent to "cp -r" in a standard unix filesystem. This
237 * recursively copies a given key to a new location. Any keys that
238 * already exist at that location will not be overridden unless force
239 * is true.
241 * Don't try to do dumb stuff like making dst a subkey of this one,
242 * or vice versa, because we won't try to save you.
244 void copy(const UniConf &dst, bool force) const;
248 /***** Key Persistence API *****/
251 * Refreshes information about this key recursively.
252 * May discard uncommitted data.
253 * Returns true on success.
255 bool refresh() const;
258 * Commits information about this key recursively.
260 void commit() const;
263 /***** Generator Mounting API *****/
266 * Mounts a generator at this key using a moniker.
268 * If 'refresh' is true, automatically refresh()es the generator
269 * after mounting.
271 * Returns the mounted generator, or NULL on failure.
273 IUniConfGen *mount(WvStringParm moniker, bool refresh = true) const;
276 * Mounts a generator at this key.
278 * Takes ownership of the supplied generator instance.
280 * If 'refresh' is true, automatically refresh()es the generator
281 * after mounting.
283 * Returns the mounted generator, or NULL on failure.
285 IUniConfGen *mountgen(IUniConfGen *gen, bool refresh = true) const;
287 /** Unmounts the generator providing this key and destroys it. */
288 void unmount(IUniConfGen *gen, bool commit) const;
290 /** Determines if any generators are mounted at this key. */
291 bool ismountpoint() const;
293 /** Returns true if the generator at this key isok(). */
294 bool isok() const;
297 * Finds the generator that owns this key.
299 * If the key exists, returns the generator that provides its
300 * contents. Otherwise returns the generator that would be
301 * updated if a value were set.
303 * If non-NULL, 'mountpoint' is set to the actual key where the generator
304 * is mounted.
306 IUniConfGen *whichmount(UniConfKey *mountpoint = NULL) const;
309 /***** Notification API *****/
312 * Requests notification when any of the keys covered by the
313 * recursive depth specification change by invoking a callback.
315 * As a programmer, you probably DO NOT want to use this. Use
316 * UniWatchList.add() instead. Otherwise, make sure you call
317 * del_callback at the appropriate time.
319 void add_callback(void *cookie, const UniConfCallback &callback,
320 bool recurse = true) const;
323 * Cancels notification requested using add_callback().
325 void del_callback(void *cookie, bool recurse = true) const;
328 * Requests notification when any of the keys covered by the
329 * recursive depth specification change by setting a flag.
331 void add_setbool(bool *flag, bool recurse = true) const;
334 * Cancels notification requested using add_setbool().
336 void del_setbool(bool *flag, bool recurse = true) const;
339 * Pauses notifications until matched with a call to unhold_delta().
341 * While paused, notification events are placed into a pending list.
342 * Redundant notifications may be discarded.
344 * Use this to safeguard non-reentrant code.
346 void hold_delta();
349 * Resumes notifications when each hold_delta() has been matched.
351 * On resumption, dispatches all pending notifications except
352 * those that were destined to watches that were removed.
354 * Use this to safeguard non-reentrant code.
356 void unhold_delta();
359 * Clears the list of pending notifications without sending them.
360 * Does not affect the hold nesting count.
362 void clear_delta();
365 * Flushes the list of pending notifications by sending them.
366 * Does not affect the hold nesting count.
368 void flush_delta();
371 /***** Key Enumeration API *****/
374 * Prints the entire contents of this subtree to a stream.
375 * If 'everything' is true, also prints empty values.
377 void dump(WvStream &stream, bool everything = false) const;
380 * Returns true if this key has children.
382 * This is provided because it is often more efficient to
383 * test existance than to actually retrieve the keys.
385 bool haschildren() const;
387 /*** Iterators (see comments in class declaration) ***/
389 // internal base class for all of the key iterators
390 class IterBase;
391 // iterates over direct children
392 class Iter;
393 // iterates over all descendents in preorder traversal
394 class RecursiveIter;
395 // iterates over children matching a wildcard
396 class XIter;
398 // internal base class for sorted key iterators
399 class SortedIterBase;
400 // sorted variant of Iter
401 class SortedIter;
402 // sorted variant of RecursiveIter
403 class SortedRecursiveIter;
404 // sorted variant of XIter
405 class SortedXIter;
407 // lists of iterators
408 DeclareWvList(Iter);
413 * An implementation base class for key iterators.
415 class UniConf::IterBase
417 protected:
418 UniConf top;
419 UniConf current;
421 IterBase(const UniConf &_top)
422 : top(_top)
425 public:
426 const UniConf *ptr() const
427 { return &current; }
428 WvIterStuff(const UniConf);
433 * This iterator walks through all immediate children of a UniConf node.
435 class UniConf::Iter : public UniConf::IterBase
437 UniConfGen::Iter *it;
439 public:
440 /** Creates an iterator over the direct children of a branch. */
441 Iter(const UniConf &_top);
443 ~Iter()
444 { delete it; }
446 void rewind()
447 { it->rewind(); }
448 bool next()
450 if (!it->next())
451 return false;
452 current = top[it->key()];
453 return true;
456 // FIXME: this is a speed optimization only. Don't use this unless
457 // you're apenwarr. It will change.
458 WvString _value() const
459 { return it->value(); }
464 * This iterator performs depth-first traversal of a subtree.
466 class UniConf::RecursiveIter : public UniConf::IterBase
468 UniConfGen::Iter *it;
470 public:
471 /** Creates a recursive iterator over a branch. */
472 RecursiveIter(const UniConf &_top);
474 ~RecursiveIter()
475 { delete it; }
477 void rewind()
478 { it->rewind(); }
479 bool next()
481 if (!it->next())
482 return false;
483 current = top[it->key()];
484 return true;
487 // FIXME: this is a speed optimization only. Don't use this unless
488 // you're apenwarr. It will change.
489 WvString _value() const
490 { return it->value(); }
495 * This iterator walks over all children that match a wildcard
496 * pattern.
498 * See UniConfKey::matches(const UniConfKey&) for information about patterns.
500 * Example patterns: (where STAR is the asterisk character, '*')
502 * "": a null iterator
503 * "a": matches only the key "a" if it exists
504 * "STAR": matches all direct children
505 * "STAR/foo": matches any existing key "foo" under direct children
506 * "STAR/STAR": matches all children of depth exactly 2
507 * "foo/...": matches all keys including and below "foo"
508 * "foo/STAR/...": matches all keys below "foo"
509 * ".../foo/STAR": matches all keys below any subkey named "foo" in the tree
511 class UniConf::XIter : public UniConf::IterBase
513 UniConfKey pathead;
514 UniConfKey pattail;
515 UniConf::XIter *subit;
516 UniConf::Iter *it; /*!< iterator over direct children */
517 UniConf::RecursiveIter *recit; /*!< iterator over descendents */
518 bool ready; /*!< next key is ready */
520 public:
521 /** Creates a wildcard iterator. */
522 XIter(const UniConf &_top, const UniConfKey &pattern);
523 ~XIter();
525 void rewind();
526 bool next();
528 private:
529 void cleanup();
530 bool qnext();
531 void enter(const UniConf &child);
536 * An implementation base class for sorted key iterators.
538 * Unfortunately WvSorter is too strongly tied down to lists and pointers
539 * to be of use here. The main problem is that UniConf::Iter and company
540 * return pointers to temporary objects whereas WvSorter assumes that the
541 * pointers will remain valid for the lifetime of the iterator.
543 class UniConf::SortedIterBase : public UniConf::IterBase
545 public:
546 typedef int (*Comparator)(const UniConf &a, const UniConf &b);
548 /** Default comparator. Sorts alphabetically by full key. */
549 static int defcomparator(const UniConf &a, const UniConf &b);
551 SortedIterBase(const UniConf &_top, Comparator comparator = defcomparator);
552 ~SortedIterBase();
554 bool next();
556 private:
557 Comparator xcomparator;
558 int index;
559 int count;
561 void _purge();
562 void _rewind();
564 protected:
565 std::vector<UniConf> xkeys;
567 template<class Iter>
568 void populate(Iter &i)
570 _purge();
571 for (i.rewind(); i.next(); )
572 xkeys.push_back(*i);
573 _rewind();
579 * A sorted variant of UniConf::Iter.
581 class UniConf::SortedIter : public UniConf::SortedIterBase
583 UniConf::Iter i;
585 public:
586 SortedIter(const UniConf &_top, Comparator comparator = defcomparator)
587 : SortedIterBase(_top, comparator), i(_top)
590 void rewind()
591 { populate(i); }
596 * A sorted variant of UniConf::RecursiveIter.
598 class UniConf::SortedRecursiveIter : public UniConf::SortedIterBase
600 UniConf::RecursiveIter i;
602 public:
603 SortedRecursiveIter(const UniConf &_top,
604 Comparator comparator = defcomparator)
605 : SortedIterBase(_top, comparator), i(_top)
608 void rewind()
609 { populate(i); }
614 * A sorted variant of UniConf::XIter.
616 class UniConf::SortedXIter : public UniConf::SortedIterBase
618 UniConf::XIter i;
620 public:
621 SortedXIter(const UniConf &_top, const UniConfKey &pattern,
622 Comparator comparator = defcomparator)
623 : SortedIterBase(_top, comparator), i(_top, pattern)
626 void rewind()
627 { populate(i); }
630 #endif // __UNICONF_H