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 UniConfKey UniConf::fullkey(const UniConfKey &k) const
00015 {
00016 int n = k.numsegments();
00017
00018
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
00069 dst.set(get());
00070
00071
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
00083 dst.set(get());
00084
00085
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
00201
00202 UniConf::Iter::Iter(const UniConf &_top)
00203 : IterBase(_top), it(_top.rootobj()->mounts.iterator(top.fullkey()))
00204 {
00205 }
00206
00207
00208
00209
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());
00229
00230 UniConf::IterList::Iter i(itlist);
00231 for (i.rewind(); i.next(); )
00232 {
00233 if (i->next())
00234 {
00235
00236 current = **i;
00237
00238
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
00250 i.xunlink();
00251 }
00252
00253
00254 return false;
00255 }
00256
00257
00258
00259
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
00268
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
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
00336 current = top[pathead];
00337 if (pattail.isempty())
00338 {
00339
00340
00341 ready = current.exists();
00342 }
00343 else
00344 {
00345
00346 enter(current);
00347 }
00348 }
00349 }
00350
00351
00352 inline bool UniConf::XIter::qnext()
00353 {
00354 if (subit)
00355 {
00356 bool found = subit->next();
00357 if (found)
00358 {
00359 current = **subit;
00360 return true;
00361 }
00362 else
00363 {
00364
00365 delete subit;
00366 subit = NULL;
00367 return false;
00368 }
00369 }
00370 else
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
00392 if (it && it->next())
00393 {
00394
00395
00396
00397
00398 enter(**it);
00399 continue;
00400 }
00401
00402 if (recit && recit->next())
00403 {
00404 enter(**recit);
00405 continue;
00406 }
00407
00408 return false;
00409 }
00410
00411
00412 return true;
00413 }
00414
00415
00416
00417
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
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 }