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

uniconf.cc

Go to the documentation of this file.
00001 /*
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
00004  * 
00005  * Defines a hierarchical registry abstraction.  See uniconf.h.
00006  */
00007 #include "uniconf.h"
00008 #include "uniconfroot.h"
00009 #include "uniconfgen.h"
00010 #include "wvstream.h"
00011 #include <assert.h>
00012 
00013 
00014 UniConfKey UniConf::fullkey(const UniConfKey &k) const
00015 {
00016     int n = k.numsegments();
00017     
00018     // this function is undefined if k isn't an ancestor!
00019     assert(k == xfullkey.first(n));
00020     
00021     return xfullkey.removefirst(n);
00022 }
00023 
00024 
00025 bool UniConf::exists() const
00026 {
00027     return xroot->mounts.exists(xfullkey);
00028 }
00029 
00030 
00031 bool UniConf::haschildren() const
00032 {
00033     return xroot->mounts.haschildren(xfullkey);
00034 }
00035 
00036 
00037 WvString UniConf::get(WvStringParm defvalue) const
00038 {
00039     WvString value = xroot->mounts.get(xfullkey);
00040     if (value.isnull())
00041         return defvalue;
00042     return value;
00043 }
00044 
00045 
00046 int UniConf::getint(int defvalue) const
00047 {
00048     return xroot->mounts.str2int(get(), defvalue);
00049 }
00050 
00051 
00052 void UniConf::set(WvStringParm value) const
00053 {
00054     xroot->mounts.set(xfullkey, value);
00055 }
00056 
00057 
00058 void UniConf::setint(int value) const
00059 {
00060     set(WvString(value));
00061 }
00062 
00063 
00064 void UniConf::move(const UniConf &dst)
00065 {
00066     dst.remove();
00067     
00068     // do the main key first
00069     dst.set(get());
00070 
00071     // now all the children
00072     RecursiveIter i(*this);
00073     for (i.rewind(); i.next(); )
00074         dst[i->fullkey(*this)].set(i->get());
00075     
00076     remove();
00077 }
00078 
00079 
00080 void UniConf::copy(const UniConf &dst, bool force) const
00081 {
00082     // do the main key first
00083     dst.set(get());
00084 
00085     // now all the children
00086     RecursiveIter i(*this);
00087     for (i.rewind(); i.next(); )
00088     {
00089         UniConf dst2 = dst[i->fullkey(*this)];
00090         if (force || dst2.get().isnull())
00091             dst2.set(i->get());
00092     }
00093 }
00094 
00095 
00096 bool UniConf::refresh() const
00097 {
00098     return xroot->mounts.refresh();
00099 }
00100 
00101 
00102 void UniConf::commit() const
00103 {
00104     xroot->mounts.commit();
00105 }
00106 
00107 
00108 UniConfGen *UniConf::mount(WvStringParm moniker, bool refresh) const
00109 {
00110     return xroot->mounts.mount(xfullkey, moniker, refresh);
00111 }
00112 
00113 
00114 UniConfGen *UniConf::mountgen(UniConfGen *gen, bool refresh) const
00115 {
00116     return xroot->mounts.mountgen(xfullkey, gen, refresh);
00117 }
00118 
00119 
00120 void UniConf::unmount(UniConfGen *gen, bool commit) const
00121 {
00122     return xroot->mounts.unmount(gen, commit);
00123 }
00124 
00125 
00126 bool UniConf::ismountpoint() const
00127 {
00128     return xroot->mounts.ismountpoint(xfullkey);
00129 }
00130 
00131 
00132 UniConfGen *UniConf::whichmount(UniConfKey *mountpoint) const
00133 {
00134     return xroot->mounts.whichmount(xfullkey, mountpoint);
00135 }
00136 
00137 
00138 void UniConf::add_callback(void *cookie, const UniConfCallback &callback,
00139                            bool recurse) const
00140 {
00141     xroot->add_callback(cookie, xfullkey, callback, recurse);
00142 }
00143 
00144 
00145 void UniConf::del_callback(void *cookie, bool recurse) const
00146 {
00147     xroot->del_callback(cookie, xfullkey, recurse);
00148 }
00149 
00150 
00151 void UniConf::add_setbool(bool *flag, bool recurse) const
00152 {
00153     xroot->add_setbool(xfullkey, flag, recurse);
00154 }
00155 
00156 
00157 void UniConf::del_setbool(bool *flag, bool recurse) const
00158 {
00159     xroot->del_setbool(xfullkey, flag, recurse);
00160 }
00161 
00162 
00163 void UniConf::hold_delta()
00164 {
00165     xroot->mounts.hold_delta();
00166 }
00167 
00168 
00169 void UniConf::unhold_delta()
00170 {
00171     xroot->mounts.unhold_delta();
00172 }
00173 
00174 
00175 void UniConf::clear_delta()
00176 {
00177     xroot->mounts.clear_delta();
00178 }
00179 
00180 
00181 void UniConf::flush_delta()
00182 {
00183     xroot->mounts.flush_delta();
00184 }
00185 
00186 
00187 void UniConf::dump(WvStream &stream, bool everything) const
00188 {
00189     UniConf::RecursiveIter it(*this);
00190     for (it.rewind(); it.next(); )
00191     {
00192         WvString value(it->get());
00193         if (everything || !!value)
00194             stream.print("%s = %s\n", it->fullkey(), value);
00195     }
00196 }
00197 
00198 
00199 
00200 /***** UniConf::Iter *****/
00201 
00202 UniConf::Iter::Iter(const UniConf &_top)
00203     : IterBase(_top), it(_top.rootobj()->mounts.iterator(top.fullkey()))
00204 {
00205 }
00206 
00207 
00208 
00209 /***** UniConf::RecursiveIter *****/
00210 
00211 UniConf::RecursiveIter::RecursiveIter(const UniConf &root)
00212     : IterBase(root)
00213 {
00214 }
00215 
00216 
00217 void UniConf::RecursiveIter::rewind()
00218 {
00219     itlist.zap();
00220     UniConf::Iter *subi = new UniConf::Iter(top);
00221     subi->rewind();
00222     itlist.prepend(subi, true);
00223 }
00224 
00225 
00226 bool UniConf::RecursiveIter::next()
00227 {
00228     assert(!itlist.isempty()); // trying to seek past the end is illegal!
00229     
00230     UniConf::IterList::Iter i(itlist);
00231     for (i.rewind(); i.next(); )
00232     {
00233         if (i->next()) // NOTE: not the same as i.next()
00234         {
00235             // return the item first
00236             current = **i;
00237             
00238             // set up so next time, we go into its subtree
00239             if (current.haschildren())
00240             {
00241                 UniConf::Iter *subi = new UniConf::Iter(current);
00242                 subi->rewind();
00243                 itlist.prepend(subi, true);
00244             }
00245             
00246             return true;
00247         }
00248         
00249         // otherwise, this iterator is empty; move up the tree
00250         i.xunlink();
00251     }
00252     
00253     // all done!
00254     return false;
00255 }
00256 
00257 
00258 
00259 /***** UniConf::XIter *****/
00260 
00261 UniConf::XIter::XIter(const UniConf &_top, const UniConfKey &pattern)
00262     : IterBase(_top), pathead(pattern.first()),
00263     pattail(pattern.removefirst()), subit(NULL), it(NULL), recit(NULL)
00264 {
00265     if (! pathead.iswild())
00266     {
00267         // optimization to collect as many consecutive non-wildcard
00268         // segments as possible in one go
00269         while (! pattail.isempty())
00270         {
00271             UniConfKey patnext(pattail.first());
00272             if (patnext.iswild())
00273                 break;
00274             pathead.append(patnext);
00275             pattail = pattail.removefirst();
00276         }
00277     }
00278 }
00279 
00280 
00281 UniConf::XIter::~XIter()
00282 {
00283     cleanup();
00284 }
00285 
00286 
00287 void UniConf::XIter::cleanup()
00288 {
00289     if (subit)
00290     {
00291         delete subit;
00292         subit = NULL;
00293     }
00294     if (it)
00295     {
00296         delete it;
00297         it = NULL;
00298     }
00299     if (recit)
00300     {
00301         delete recit;
00302         recit = NULL;
00303     }
00304 }
00305 
00306 
00307 void UniConf::XIter::rewind()
00308 {
00309     cleanup();
00310     ready = false;
00311 
00312     if (pathead.isempty())
00313     {
00314         current = top;
00315         ready = current.exists();
00316     }
00317     else if (pathead == UniConfKey::RECURSIVE_ANY)
00318     {
00319         recit = new UniConf::RecursiveIter(top);
00320         recit->rewind();
00321         if (UniConfKey::EMPTY.matches(pattail))
00322         {
00323             // pattern includes self
00324             current = top;
00325             ready = current.exists();
00326         }
00327     }
00328     else if (pathead == UniConfKey::ANY)
00329     {
00330         it = new UniConf::Iter(top);
00331         it->rewind();
00332     }
00333     else
00334     {
00335         // non-wildcard segment
00336         current = top[pathead];
00337         if (pattail.isempty())
00338         {
00339             // don't bother recursing if there are no deeper wildcard
00340             // elements (works together with optimization in constructor)
00341             ready = current.exists();
00342         }
00343         else
00344         {
00345             // more wildcards, setup recursion
00346             enter(current);
00347         }
00348     }
00349 }
00350 
00351 
00352 inline bool UniConf::XIter::qnext()
00353 {
00354     if (subit) // currently in a sub-iterator
00355     {
00356         bool found = subit->next();
00357         if (found)
00358         {
00359             current = **subit;
00360             return true;
00361         }
00362         else
00363         {
00364             // end of this sub-iterator
00365             delete subit;
00366             subit = NULL;
00367             return false;
00368         }
00369     }
00370     else // no sub-iterator at all
00371         return false;
00372 }
00373 
00374 
00375 void UniConf::XIter::enter(const UniConf &child)
00376 {
00377     subit = new UniConf::XIter(child, pattail);
00378     subit->rewind();
00379 }
00380 
00381 
00382 bool UniConf::XIter::next()
00383 {
00384     if (ready)
00385     {
00386         ready = false;
00387         return true;
00388     }
00389     while (!qnext())
00390     {
00391         // UniConfKey::ANY
00392         if (it && it->next())
00393         {
00394             /* Not needed for now since we don't match partial keys
00395             if (! pathead.matches(it->key()))
00396                 break;
00397             */
00398             enter(**it);
00399             continue;
00400         }
00401         // UniConfKey::RECURSIVE_ANY
00402         if (recit && recit->next())
00403         {
00404             enter(**recit);
00405             continue;
00406         }
00407         // anything else or finished
00408         return false;
00409     }
00410     
00411     // if we get here, qnext() returned true
00412     return true; 
00413 }
00414 
00415 
00416 
00417 /***** UniConf::SortedIterBase *****/
00418 
00419 UniConf::SortedIterBase::SortedIterBase(const UniConf &root,
00420     UniConf::SortedIterBase::Comparator comparator) 
00421     : IterBase(root), xcomparator(comparator), xkeys(true)
00422 {
00423 }
00424 
00425 
00426 UniConf::SortedIterBase::~SortedIterBase()
00427 {
00428     _purge();
00429 }
00430 
00431 
00432 int UniConf::SortedIterBase::defcomparator(const UniConf &a,
00433     const UniConf &b)
00434 {
00435     return a.fullkey().compareto(b.fullkey());
00436 }
00437 
00438 
00439 UniConf::SortedIterBase::Comparator
00440     UniConf::SortedIterBase::innercomparator = NULL;
00441 
00442 int UniConf::SortedIterBase::wrapcomparator(const UniConf **a,
00443     const UniConf **b)
00444 {
00445     return innercomparator(**a, **b);
00446 }
00447 
00448 
00449 void UniConf::SortedIterBase::_purge()
00450 {
00451     count = xkeys.count();
00452     xkeys.zap();
00453 }
00454 
00455 
00456 void UniConf::SortedIterBase::_rewind()
00457 {
00458     index = 0;
00459     count = xkeys.count();
00460     
00461     // This code is NOT reentrant because qsort makes it too hard
00462     innercomparator = xcomparator;
00463     qsort(xkeys.ptr(), count, sizeof(UniConf*),
00464         (int (*)(const void *, const void *))wrapcomparator);
00465 }
00466 
00467 
00468 bool UniConf::SortedIterBase::next()
00469 {
00470     if (index >= count)
00471         return false;
00472     current = *xkeys[index];
00473     index += 1;
00474     return true;
00475 }

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