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