Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

uniconf.h

Go to the documentation of this file.
00001 /* -*- Mode: C++ -*-
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
00004  * 
00005  * Defines a hierarchical registry abstraction.
00006  */
00007 #ifndef __UNICONF_H
00008 #define __UNICONF_H
00009 
00010 #ifdef  __cplusplus
00011 
00012 #include "uniconfkey.h"
00013 #include "uniconfgen.h"
00014 #include "wvcallback.h"
00015 #include "wvvector.h"
00016 
00017 class WvStream;
00018 class UniConf;
00019 class UniConfRoot;
00020 
00021 /**
00022  * The callback type for signalling key changes from UniConf.
00023  * 
00024  * Parameters: cfg, relkey
00025  *   cfg - the UniConf config object representing the key that has changed
00026  *   relkey - the changed keypath, relative to the config object
00027  */
00028 typedef WvCallback<void, const UniConf &, const UniConfKey &> UniConfCallback;
00029 
00030 /**
00031  * UniConf instances function as handles to subtrees of a UniConf
00032  * tree and expose a high-level interface for clients.
00033  * 
00034  * All operations are marked "const" unless they modify the target
00035  * of the handle.  In effect, this grants UniConf handles the
00036  * same semantics as pointers where a const pointer may point
00037  * to a non-const object, which simply means that the pointer
00038  * cannot be reassigned.
00039  * 
00040  * When handles are returned from functions, they are always marked
00041  * const to guard against accidentally assigning to a temporary by
00042  * an expression such as cfg["foo"] = cfg["bar"].
00043  * Instead this must be written as
00044  *     cfg["foo"].set(cfg["bar"].get())
00045  * which is slightly
00046  * less elegant but avoids many subtle mistakes.  Also for this
00047  * reason, unusual cast operators, assignment operators,
00048  * or copy constructors are not provided.  Please do not add any.
00049  * 
00050  */
00051 class UniConf
00052 {
00053     friend class UniConfRoot;
00054     
00055 protected:
00056     UniConfRoot *xroot;
00057     UniConfKey xfullkey;
00058 
00059     /**
00060      * Creates a handle to the specified subtree of the given root.
00061      * 
00062      * You can't create non-NULL UniConf objects yourself - ask UniConfRoot
00063      * or another UniConf object to make one for you.
00064      */
00065     UniConf(UniConfRoot *root, const UniConfKey &fullkey = UniConfKey::EMPTY)
00066         : xroot(root), xfullkey(fullkey) { }
00067     
00068 public:
00069     /** Creates a NULL UniConf handle, useful for reporting errors. */
00070     UniConf() 
00071         : xroot(NULL), xfullkey(UniConfKey::EMPTY) { }
00072     
00073     /**
00074      * Copies a UniConf handle.
00075      * "other" is the handle to copy
00076      */
00077     UniConf(const UniConf &other)
00078         : xroot(other.xroot), xfullkey(other.xfullkey) { }
00079     
00080     /** Destroys the UniConf handle. */
00081     virtual ~UniConf() { }
00082 
00083     
00084     /***** Handle Manipulation API *****/
00085 
00086     /** Returns a handle to the root of the tree. */
00087     UniConf root() const
00088         { return UniConf(xroot, UniConfKey::EMPTY); }
00089 
00090     /** Returns a handle to the parent of this node. */
00091     UniConf parent() const
00092         { return UniConf(xroot, xfullkey.removelast()); }
00093     
00094     /**
00095      * Returns a pointer to the UniConfRoot that manages this node.
00096      * This may be NULL, to signal an invalid handle.
00097      */
00098     UniConfRoot *rootobj() const
00099         { return xroot; }
00100 
00101     /** Returns true if the handle is invalid (NULL). */
00102     bool isnull() const
00103         { return xroot == NULL; }
00104 
00105     /** Returns the full path of this node, starting at the root. */
00106     UniConfKey fullkey() const
00107         { return xfullkey; }
00108     
00109     /** Returns the full path of this node, starting at the given key.
00110      * Assumes that k is an ancestor of fullkey(). */
00111     UniConfKey fullkey(const UniConfKey &k) const;
00112     
00113     /** Returns the full path of this node, starting at the given handle. */
00114     UniConfKey fullkey(const UniConf &cfg) const
00115         { return fullkey(cfg.fullkey()); }
00116 
00117     /** Returns the path of this node relative to its parent. */
00118     UniConfKey key() const
00119         { return xfullkey.last(); }
00120 
00121     /**
00122      * Returns a handle for a subtree below this key. 'key' is the path
00123      * of the subtree to be appended to the full path of this handle to
00124      * obtain the full path of the new handle.
00125      */
00126     const UniConf operator[] (const UniConfKey &key) const
00127         { return UniConf(xroot, UniConfKey(xfullkey, key)); }
00128 
00129     /** Reassigns the target of this handle to match a different one. */
00130     UniConf &operator= (const UniConf &other)
00131     {
00132         xroot = other.xroot;
00133         xfullkey = other.xfullkey;
00134         return *this;
00135     }
00136 
00137     
00138     /***** Key Retrieval API *****/
00139     
00140     /**
00141      * Fetches the string value for this key from the registry.  If the
00142      * key is not found, returns 'defvalue' instead.
00143      */
00144     WvString get(WvStringParm defvalue = WvString::null) const;
00145 
00146     /**
00147      * Without fetching its value, returns true if this key exists.
00148      * 
00149      * This is provided because it is often more efficient to
00150      * test existance than to actually retrieve the value.
00151      */
00152     bool exists() const;
00153 
00154     /**
00155      * Fetches the integer value for this key from the registry.  If the
00156      * key is not found, returns 'defvalue' instead.  (This is also used to
00157      * fetch booleans - 'true', 'yes', 'on' and 'enabled' are recognized as
00158      * 1, 'false', 'no', 'off' and 'disabled' as 0.  Note that a nonexistant
00159      * key is false by default.)
00160      */
00161     int getint(int defvalue = 0) const;
00162 
00163 
00164     /***** Key Storage API *****/
00165 
00166     /**
00167      * Stores a string value for this key into the registry.  If the value
00168      * is WvString::null, deletes the key and all of its children.
00169      * Returns true on success.
00170      */
00171     void set(WvStringParm value) const;
00172 
00173     /**
00174      * Stores a string value for this key into the registry.
00175      * Returns true on success.
00176      */
00177     void set(WVSTRING_FORMAT_DECL) const
00178         { return set(WvString(WVSTRING_FORMAT_CALL)); }
00179 
00180     /**
00181      * Stores an integer value for this key into the registry.
00182      * Returns true on success.
00183      */
00184     void setint(int value) const;
00185 
00186 
00187     /***** Key Handling API *****/
00188 
00189     /**
00190      * Equivalent to "mv" in a standard unix filesystem. This recursively
00191      * moves a given key and any subkeys to a new point. If the new point
00192      * exists then the key will be left as a subkey at the new point.
00193      * Otherwise, the key will also be renamed to the new point (as when
00194      * using mv).
00195      * 
00196      * Don't try to do dumb stuff like making dst a subkey of this one,
00197      * or vice versa, because we won't try to save you.
00198      * 
00199      * Unlike unix mv(), this is *not* currently atomic.  It's more like
00200      * cp-then-rm.
00201      */
00202     void move(const UniConf &dst);
00203 
00204     /**
00205      * Removes this key and all of its children from the registry.
00206      * Returns true on success.
00207      */
00208     void remove() const
00209         { set(WvString::null); }
00210 
00211     /**
00212      * Equivalent to "cp -r" in a standard unix filesystem. This
00213      * recursively copies a given key to a new location. Any keys that
00214      * already exist at that location will not be overridden unless force
00215      * is true.
00216      * 
00217      * Don't try to do dumb stuff like making dst a subkey of this one,
00218      * or vice versa, because we won't try to save you.
00219      */
00220     void copy(const UniConf &dst, bool force) const;
00221 
00222 
00223     
00224     /***** Key Persistence API *****/
00225 
00226     /**
00227      * Refreshes information about this key recursively.
00228      * May discard uncommitted data.
00229      * Returns true on success.
00230      */
00231     bool refresh() const;
00232     
00233     /**
00234      * Commits information about this key recursively.
00235      */
00236     void commit() const;
00237 
00238     
00239     /***** Generator Mounting API *****/
00240     
00241     /**
00242      * Mounts a generator at this key using a moniker.
00243      * 
00244      * If 'refresh' is true, automatically refresh()es the generator
00245      * after mounting.
00246      *
00247      * Returns the mounted generator, or NULL on failure.
00248      */
00249     UniConfGen *mount(WvStringParm moniker, bool refresh = true) const;
00250     
00251     /**
00252      * Mounts a generator at this key.
00253      * 
00254      * Takes ownership of the supplied generator instance.
00255      * 
00256      * If 'refresh' is true, automatically refresh()es the generator
00257      * after mounting.
00258      * 
00259      * Returns the mounted generator, or NULL on failure.
00260      */
00261     UniConfGen *mountgen(UniConfGen *gen, bool refresh = true) const;
00262     
00263     /** Unmounts the generator providing this key and destroys it. */
00264     void unmount(UniConfGen *gen, bool commit) const;
00265     
00266     /** Determines if any generators are mounted at this key. */
00267     bool ismountpoint() const;
00268     
00269     /**
00270      * Finds the generator that owns this key.
00271      * 
00272      * If the key exists, returns the generator that provides its
00273      * contents.  Otherwise returns the generator that would be
00274      * updated if a value were set.
00275      * 
00276      * If non-NULL, 'mountpoint' is set to the actual key where the generator
00277      * is mounted.
00278      */
00279     UniConfGen *whichmount(UniConfKey *mountpoint = NULL) const;
00280 
00281     
00282     /***** Notification API *****/
00283 
00284     /**
00285      * Requests notification when any of the keys covered by the
00286      * recursive depth specification change by invoking a callback.
00287      */
00288     void add_callback(void *cookie, const UniConfCallback &callback,
00289                       bool recurse = true) const;
00290     
00291     /**
00292      * Cancels notification requested using add_callback().
00293      */
00294     void del_callback(void *cookie, bool recurse = true) const;
00295 
00296     /**
00297      * Requests notification when any of the keys covered by the
00298      * recursive depth specification change by setting a flag.
00299      */
00300     void add_setbool(bool *flag, bool recurse = true) const;
00301 
00302     /**
00303      * Cancels notification requested using add_setbool().
00304      */
00305     void del_setbool(bool *flag, bool recurse = true) const;
00306     
00307     /**
00308      * Pauses notifications until matched with a call to unhold_delta().
00309      * 
00310      * While paused, notification events are placed into a pending list.
00311      * Redundant notifications may be discarded.
00312      *
00313      * Use this to safeguard non-reentrant code.
00314      */
00315     void hold_delta();
00316 
00317     /**
00318      * Resumes notifications when each hold_delta() has been matched.
00319      * 
00320      * On resumption, dispatches all pending notifications except
00321      * those that were destined to watches that were removed.
00322      * 
00323      * Use this to safeguard non-reentrant code.
00324      */
00325     void unhold_delta();
00326     
00327     /**
00328      * Clears the list of pending notifications without sending them.
00329      * Does not affect the hold nesting count.
00330      */
00331     void clear_delta();
00332 
00333     /**
00334      * Flushes the list of pending notifications by sending them.
00335      * Does not affect the hold nesting count.
00336      */
00337     void flush_delta();
00338     
00339     
00340     /***** Key Enumeration API *****/
00341     
00342     /**
00343      * Prints the entire contents of this subtree to a stream.
00344      * If 'everything' is true, also prints empty values.
00345      */
00346     void dump(WvStream &stream, bool everything = false) const;
00347     
00348     /**
00349      * Returns true if this key has children.
00350      * 
00351      * This is provided because it is often more efficient to
00352      * test existance than to actually retrieve the keys.
00353      */
00354     bool haschildren() const;
00355     
00356     /*** Iterators (see comments in class declaration) ***/
00357 
00358     // internal base class for all of the key iterators
00359     class IterBase;
00360     // iterates over direct children
00361     class Iter;
00362     // iterates over all descendents in preorder traversal
00363     class RecursiveIter;
00364     // iterates over children matching a wildcard
00365     class XIter;
00366 
00367     // internal base class for sorted key iterators
00368     class SortedIterBase;
00369     // sorted variant of Iter
00370     class SortedIter;
00371     // sorted variant of RecursiveIter
00372     class SortedRecursiveIter;
00373     // sorted variant of XIter
00374     class SortedXIter;
00375     
00376     // lists of iterators
00377     DeclareWvList(Iter);
00378 };
00379 
00380 
00381 /**
00382  * An implementation base class for key iterators.
00383  */
00384 class UniConf::IterBase
00385 {
00386 protected:
00387     UniConf top;
00388     UniConf current;
00389 
00390     IterBase(const UniConf &_top)
00391         : top(_top)
00392         { }
00393 
00394 public:
00395     const UniConf *ptr() const
00396         { return &current; }
00397     WvIterStuff(const UniConf);
00398 };
00399 
00400 
00401 /**
00402  * This iterator walks through all immediate children of a UniConf node.
00403  */
00404 class UniConf::Iter : public UniConf::IterBase
00405 {
00406     UniConfGen::Iter *it;
00407     
00408 public:
00409     /** Creates an iterator over the direct children of a branch. */
00410     Iter(const UniConf &_top);
00411 
00412     ~Iter()
00413         { delete it; }
00414 
00415     void rewind()
00416         { it->rewind(); }
00417     bool next()
00418     {
00419         if (! it->next())
00420             return false;
00421         current = top[it->key()];
00422         return true;
00423     }   
00424 };
00425 
00426 
00427 /**
00428  * This iterator performs depth-first traversal of a subtree.
00429  */
00430 class UniConf::RecursiveIter : public UniConf::IterBase
00431 {
00432     UniConf::IterList itlist;
00433 
00434 public:
00435     /** Creates a recursive iterator over a branch. */
00436     RecursiveIter(const UniConf &_top);
00437 
00438     void rewind();
00439     bool next();
00440 };
00441 
00442 
00443 /**
00444  * This iterator walks over all children that match a wildcard
00445  * pattern.
00446  * 
00447  * See UniConfKey::matches(const UniConfKey&) for information about patterns.
00448  * 
00449  * Example patterns: (where STAR is the asterisk character, '*')
00450  *
00451  * "": a null iterator
00452  * "a": matches only the key "a" if it exists
00453  * "STAR": matches all direct children
00454  * "STAR/foo": matches any existing key "foo" under direct children
00455  * "STAR/STAR": matches all children of depth exactly 2
00456  * "foo/...": matches all keys including and below "foo"
00457  * "foo/STAR/...": matches all keys below "foo"
00458  * ".../foo/STAR": matches all keys below any subkey named "foo" in the tree
00459  */
00460 class UniConf::XIter : public UniConf::IterBase
00461 {
00462     UniConfKey pathead;
00463     UniConfKey pattail;
00464     UniConf::XIter *subit;
00465     UniConf::Iter *it; /*!< iterator over direct children */
00466     UniConf::RecursiveIter *recit; /*!< iterator over descendents */
00467     bool ready; /*!< next key is ready */
00468 
00469 public:
00470     /** Creates a wildcard iterator. */
00471     XIter(const UniConf &_top, const UniConfKey &pattern);
00472     ~XIter();
00473 
00474     void rewind();
00475     bool next();
00476     
00477 private:
00478     void cleanup();
00479     bool qnext();
00480     void enter(const UniConf &child);
00481 };
00482 
00483 
00484 /**
00485  * An implementation base class for sorted key iterators.
00486  * 
00487  * Unfortunately WvSorter is too strongly tied down to lists and pointers
00488  * to be of use here.  The main problem is that UniConf::Iter and company
00489  * return pointers to temporary objects whereas WvSorter assumes that the
00490  * pointers will remain valid for the lifetime of the iterator.
00491  */
00492 class UniConf::SortedIterBase : public UniConf::IterBase
00493 {
00494 public:
00495     typedef int (*Comparator)(const UniConf &a, const UniConf &b);
00496 
00497     /** Default comparator. Sorts alphabetically by full key. */
00498     static int defcomparator(const UniConf &a, const UniConf &b);
00499 
00500     SortedIterBase(const UniConf &_top, Comparator comparator = defcomparator);
00501     ~SortedIterBase();
00502 
00503     bool next();
00504 
00505 private:
00506     Comparator xcomparator;
00507     int index;
00508     int count;
00509     
00510     void _purge();
00511     void _rewind();
00512     
00513     static int wrapcomparator(const UniConf **a, const UniConf **b);
00514     static Comparator innercomparator;
00515 
00516 protected:
00517     typedef WvVector<UniConf> Vector;
00518     Vector xkeys;
00519     
00520     template<class Iter>
00521     void populate(Iter &i)
00522     {
00523         _purge();
00524         for (i.rewind(); i.next(); )
00525             xkeys.append(new UniConf(*i));
00526         _rewind();
00527     }
00528 };
00529 
00530 
00531 /**
00532  * A sorted variant of UniConf::Iter.
00533  */
00534 class UniConf::SortedIter : public UniConf::SortedIterBase
00535 {
00536     UniConf::Iter i;
00537 
00538 public:
00539     SortedIter(const UniConf &_top, Comparator comparator = defcomparator)
00540         : SortedIterBase(_top, comparator), i(_top)
00541         { }
00542 
00543     void rewind()
00544         { populate(i); }
00545 };
00546 
00547 
00548 /**
00549  * A sorted variant of UniConf::RecursiveIter.
00550  */
00551 class UniConf::SortedRecursiveIter : public UniConf::SortedIterBase
00552 {
00553     UniConf::RecursiveIter i;
00554 
00555 public:
00556     SortedRecursiveIter(const UniConf &_top,
00557                         Comparator comparator = defcomparator)
00558         : SortedIterBase(_top, comparator), i(_top)
00559         { }
00560 
00561     void rewind()
00562         { populate(i); }
00563 };
00564 
00565 
00566 /**
00567  * A sorted variant of UniConf::XIter.
00568  */
00569 class UniConf::SortedXIter : public UniConf::SortedIterBase
00570 {
00571     UniConf::XIter i;
00572 
00573 public:
00574     SortedXIter(const UniConf &_top, const UniConfKey &pattern,
00575                 Comparator comparator = defcomparator) 
00576         : SortedIterBase(_top, comparator), i(_top, pattern) 
00577         { }
00578 
00579     void rewind()
00580         { populate(i); }
00581 };
00582 
00583 extern "C" {
00584 #endif /* __cplusplus */
00585 
00586 
00587 #ifdef SWIG
00588 %module UniConf
00589 
00590 %{
00591 #include "uniconf.h"
00592 %}
00593 
00594 //%newobject uniconf_get;
00595 #endif
00596 
00597 /* FIXME: put the C binding here. */
00598 typedef void* uniconf_t;
00599 
00600 
00601 /* Initialize and destroy UniConf. */
00602 uniconf_t uniconf_init(const char* _moniker);
00603 
00604 
00605 void uniconf_free(uniconf_t _uniconf);
00606 
00607 
00608 /* The string returned has been allocated with malloc() and should
00609  * thus be free()d. */
00610 const char* uniconf_get(uniconf_t _uniconf, const char* _key);
00611 
00612 
00613 void uniconf_set(uniconf_t _uniconf,
00614                  const char* _key, const char* _value);
00615 
00616 
00617 #ifdef  __cplusplus
00618 }
00619 #endif
00620 
00621 #endif // __UNICONF_H

Generated on Wed Dec 15 15:08:10 2004 for WvStreams by  doxygen 1.3.9.1