00001
00002
00003
00004
00005
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
00018 }
00019
00020
00021 UniConf::UniConf() : xroot(NULL), xfullkey(UniConfKey::EMPTY)
00022 {
00023
00024 }
00025
00026
00027 UniConf::UniConf(const UniConf &other)
00028 : xroot(other.xroot), xfullkey(other.xfullkey)
00029 {
00030
00031 }
00032
00033
00034 UniConf::~UniConf()
00035 {
00036
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
00104 dst.setme(getme());
00105
00106
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
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
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
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
00258
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
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
00326 current = top[pathead];
00327 if (pattail.isempty())
00328 {
00329
00330
00331 ready = current.exists();
00332 }
00333 else
00334 {
00335
00336 enter(current);
00337 }
00338 }
00339 }
00340
00341
00342 inline bool UniConf::XIter::qnext()
00343 {
00344 if (subit)
00345 {
00346 bool found = subit->next();
00347 if (found)
00348 {
00349 current = **subit;
00350 return true;
00351 }
00352 else
00353 {
00354
00355 delete subit;
00356 subit = NULL;
00357 return false;
00358 }
00359 }
00360 else
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
00382 if (it && it->next())
00383 {
00384
00385
00386
00387
00388 enter(**it);
00389 continue;
00390 }
00391
00392 if (recit && recit->next())
00393 {
00394 enter(**recit);
00395 continue;
00396 }
00397
00398 return false;
00399 }
00400
00401
00402 return true;
00403 }
00404
00405
00406
00407
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
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 }