Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

wvhconf.cc

Go to the documentation of this file.
00001 /*
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
00004  * 
00005  * WvHConf is the new, improved, hierarchical version of WvConf.  It stores
00006  * strings in a hierarchy and can load/save them from "various places."
00007  * 
00008  * See wvhconf.h.
00009  */
00010 #include "wvhconf.h"
00011 #include "wvstream.h"
00012 
00013 
00014 // basic constructor, generally used for toplevel config file
00015 WvHConf::WvHConf()
00016     : name("")
00017 {
00018     parent = NULL;
00019     init();
00020 }
00021 
00022 
00023 WvHConf::WvHConf(WvHConf *_parent, const WvString &_name)
00024     : name(_name)
00025 {
00026     parent = _parent;
00027     init();
00028 }
00029 
00030 
00031 void WvHConf::init()
00032 {
00033     children = NULL;
00034     defaults = NULL;
00035     generator = NULL;
00036     
00037     dirty  = child_dirty  = false;
00038     notify = child_notify = false;
00039     
00040     obsolete = child_obsolete = false;
00041 }
00042 
00043 
00044 WvHConf::~WvHConf()
00045 {
00046     if (children)
00047         delete children;
00048     if (generator)
00049         delete generator;
00050 }
00051 
00052 
00053 // find the topmost WvHConf object in this tree.  Using this too often might
00054 // upset the clever transparency of hierarchical nesting, but sometimes it's
00055 // a good idea (particularly if you need to use full_key()).
00056 WvHConf *WvHConf::top()
00057 {
00058     WvHConf *h = this;
00059     while (h->parent)
00060         h = h->parent;
00061     return h;
00062 }
00063 
00064 
00065 // this method of returning the object is pretty inefficient - lots of extra
00066 // copying stuff around.
00067 WvHConfKey WvHConf::full_key() const
00068 {
00069     WvHConfKey k;
00070     const WvHConf *h = this;
00071     
00072     do
00073     {
00074         k.prepend(new WvString(h->name), true);
00075         h = h->parent;
00076     } while (h);
00077     
00078     return k;
00079 }
00080 
00081 
00082 // find the topmost WvHConf object in the tree that's still owned by the
00083 // same WvHConfGen object.
00084 WvHConf *WvHConf::gen_top()
00085 {
00086     WvHConf *h = this;
00087     while (h->parent && !h->generator)
00088         h = h->parent;
00089     
00090     return h; // we reached the top of the tree without finding a generator.
00091 }
00092 
00093 
00094 // Figure out the full key for this location, but based from the gen_top()
00095 // instead of the top().
00096 // 
00097 // like with gen_key, this method of returning the object is pretty
00098 // inefficient - lots of extra copying stuff around.
00099 WvHConfKey WvHConf::gen_full_key() const
00100 {
00101     WvHConfKey k;
00102     const WvHConf *h = this;
00103     
00104     while (h && !h->generator)
00105     {
00106         k.prepend(new WvString(h->name), true);
00107         h = h->parent;
00108     };
00109     
00110     return k;
00111 }
00112 
00113 
00114 // find a key in the subtree.  If it doesn't already exist, return NULL.
00115 WvHConf *WvHConf::find(const WvHConfKey &key)
00116 {
00117     if (key.isempty())
00118         return this;
00119     if (!children)
00120         return NULL;
00121     
00122     WvHConf *h = (*children)[*key.first()];
00123     if (!h)
00124         return NULL;
00125     else
00126         return h->find(key.skip(1));
00127 }
00128 
00129 
00130 // find a key in the subtree.  If it doesn't already exist, create it.
00131 WvHConf *WvHConf::find_make(const WvHConfKey &key)
00132 {
00133     if (key.isempty())
00134         return this;
00135     if (children)
00136     {
00137         WvHConf *h = (*children)[*key.first()];
00138         if (h)
00139             return h->find_make(key.skip(1));
00140     }
00141         
00142     // we need to actually create the key
00143     WvHConf *htop = gen_top();
00144     if (htop->generator)
00145         return htop->generator->make_tree(this, key);
00146     else
00147         return WvHConfGen().make_tree(this, key); // generate an empty tree
00148 }
00149 
00150 
00151 // find a key that contains the default value for this key, regardless of
00152 // whether this key _needs_ a default value or not.  (If !!value, we no longer
00153 // need a default, but this function still can return non-NULL.)
00154 // 
00155 // If there's no available default value for this key, return NULL.
00156 // 
00157 WvHConf *WvHConf::find_default(WvHConfKey *_k) const
00158 {
00159     WvHConfKey tmp_key;
00160     WvHConfKey &k = (_k ? *_k : tmp_key);
00161     WvHConf *def;
00162     
00163     //wvcon->print("find_default for '%s'\n", full_key());
00164         
00165     if (defaults)
00166     {
00167         //wvcon->print("  find key '%s' in '%s'\n", k, defaults->full_key());
00168         def = defaults->find(k);
00169         if (def)
00170             return def;
00171     }
00172     
00173     if (parent)
00174     {
00175         // go up a level and try again
00176         WvString s1(name);
00177         k.prepend(&s1, false);
00178         def = parent->find_default(&k);
00179         k.unlink_first();
00180         if (def)
00181             return def;
00182         
00183         // try with a wildcard instead
00184         WvString s2("*");
00185         k.prepend(&s2, false);
00186         def = parent->find_default(&k);
00187         k.unlink_first();
00188         if (def)
00189             return def;
00190     }
00191     
00192     return NULL;
00193 }
00194 
00195 
00196 void WvHConf::set_without_notify(const WvString &s)
00197 {
00198     value = s;
00199     value.unique();
00200 }
00201 
00202 
00203 void WvHConf::set(const WvString &s)
00204 {
00205     WvHConf *h;
00206     
00207     if (s == value)
00208         return; // nothing to change - no notifications needed
00209     
00210     set_without_notify(s);
00211     
00212     if (dirty && notify)
00213         return; // nothing more needed
00214     
00215     dirty = notify = true;
00216     
00217     // also notify all parents that a child has changed.  We can stop this
00218     // if we reach a parent that already has child_notify AND child_dirty
00219     // set to true.
00220     h = parent;
00221     while (h && (!h->child_dirty || !h->child_notify))
00222     {
00223         h->child_dirty = h->child_notify = true;
00224         h = h->parent;
00225     }
00226 }
00227 
00228 
00229 void WvHConf::do_notify()
00230 {
00231     WvHConf *h;
00232     
00233     dirty = notify = true;
00234     
00235     h = parent;
00236     while (h && (!h->child_dirty || !h->child_notify))
00237     {
00238         h->child_dirty = h->child_notify = true;
00239         h = h->parent;
00240     }
00241 }
00242 
00243 
00244 const WvString &WvHConf::printable() const
00245 {
00246     WvHConf *def;
00247     
00248     if (!!value)
00249         return value;
00250     
00251     def = find_default();
00252     if (def)
00253         return def->printable();
00254     
00255     // no default found: return the value (basically NULL) anyway
00256     return value;
00257 }
00258 
00259 
00260 void WvHConf::load()
00261 {
00262     if (generator)
00263         generator->load();
00264     else if (children)
00265     {
00266         WvHConfDict::Iter i(*children);
00267         for (i.rewind(); i.next(); )
00268             i->load();
00269     }
00270 }
00271 
00272 
00273 void WvHConf::save()
00274 {
00275     if (!dirty && !child_dirty)
00276         return; // done!
00277     
00278     if (generator)
00279         generator->save();
00280     else if (children && child_dirty)
00281     {
00282         WvHConfDict::Iter i(*children);
00283         for (i.rewind(); i.next(); )
00284             i->save();
00285     }
00286 }
00287 
00288 
00289 void WvHConf::dump(WvStream &s)
00290 {
00291     if (!!value)
00292     {
00293         s.print("  %s%s%s%s%s%s %s = %s\n",
00294                 child_dirty, dirty,
00295                 child_notify, notify,
00296                 child_obsolete, obsolete,
00297                 full_key(), value);
00298     }
00299 
00300     if (children)
00301     {
00302         WvHConfDict::Iter i(*children);
00303         for (i.rewind(); i.next(); )
00304             i->dump(s);
00305     }
00306 }
00307 
00308 

Generated on Sat Aug 24 23:07:55 2002 for WvStreams by doxygen1.2.15