uniconf.cc

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

Generated on Thu Jan 24 16:50:55 2008 for WvStreams by  doxygen 1.5.4