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