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 }