2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
5 * Defines a hierarchical registry abstraction.
12 #include "uniconfgen.h"
13 #include "uniconfkey.h"
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
;
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())
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.
52 friend class UniConfRoot
;
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
);
67 /** Creates a NULL UniConf handle, useful for reporting errors. */
70 /** Copies a UniConf handle. */
71 UniConf(const UniConf
&other
);
73 /** Destroys the UniConf handle. */
77 /***** Handle Manipulation API *****/
79 /** Returns a handle to the root of the tree. */
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()); }
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
94 /** Returns true if the handle is invalid (NULL). */
96 { return xroot
== NULL
; }
98 /** Returns the full path of this node, starting at the root. */
99 UniConfKey
fullkey() const
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
)
133 xfullkey
= other
.xfullkey
;
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
153 /** A different way to say cfg.getme().num(): use cfg->num() instead. */
154 WvStringStar
operator -> () const
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.
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
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
227 void move(const UniConf
&dst
) const;
230 * Removes this key and all of its children from the registry.
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
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.
263 /***** Generator Mounting API *****/
266 * Mounts a generator at this key using a moniker.
268 * If 'refresh' is true, automatically refresh()es the generator
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
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(). */
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
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.
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.
359 * Clears the list of pending notifications without sending them.
360 * Does not affect the hold nesting count.
365 * Flushes the list of pending notifications by sending them.
366 * Does not affect the hold nesting count.
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
391 // iterates over direct children
393 // iterates over all descendents in preorder traversal
395 // iterates over children matching a wildcard
398 // internal base class for sorted key iterators
399 class SortedIterBase
;
400 // sorted variant of Iter
402 // sorted variant of RecursiveIter
403 class SortedRecursiveIter
;
404 // sorted variant of XIter
407 // lists of iterators
413 * An implementation base class for key iterators.
415 class UniConf::IterBase
421 IterBase(const UniConf
&_top
)
426 const UniConf
*ptr() const
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
;
440 /** Creates an iterator over the direct children of a branch. */
441 Iter(const UniConf
&_top
);
452 current
= top
[it
->key()];
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
;
471 /** Creates a recursive iterator over a branch. */
472 RecursiveIter(const UniConf
&_top
);
483 current
= top
[it
->key()];
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
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
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 */
521 /** Creates a wildcard iterator. */
522 XIter(const UniConf
&_top
, const UniConfKey
&pattern
);
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
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
);
557 Comparator xcomparator
;
565 std::vector
<UniConf
> xkeys
;
568 void populate(Iter
&i
)
571 for (i
.rewind(); i
.next(); )
579 * A sorted variant of UniConf::Iter.
581 class UniConf::SortedIter
: public UniConf::SortedIterBase
586 SortedIter(const UniConf
&_top
, Comparator comparator
= defcomparator
)
587 : SortedIterBase(_top
, comparator
), i(_top
)
596 * A sorted variant of UniConf::RecursiveIter.
598 class UniConf::SortedRecursiveIter
: public UniConf::SortedIterBase
600 UniConf::RecursiveIter i
;
603 SortedRecursiveIter(const UniConf
&_top
,
604 Comparator comparator
= defcomparator
)
605 : SortedIterBase(_top
, comparator
), i(_top
)
614 * A sorted variant of UniConf::XIter.
616 class UniConf::SortedXIter
: public UniConf::SortedIterBase
621 SortedXIter(const UniConf
&_top
, const UniConfKey
&pattern
,
622 Comparator comparator
= defcomparator
)
623 : SortedIterBase(_top
, comparator
), i(_top
, pattern
)
630 #endif // __UNICONF_H