00001
00002
00003
00004
00005
00006
00007 #include "unimounttreegen.h"
00008 #include "wvmoniker.h"
00009
00010
00011
00012 UniMountTreeGen::UniMountTreeGen()
00013 {
00014 mounts = new UniMountTree(NULL, UniConfKey::EMPTY);
00015 }
00016
00017
00018 UniMountTreeGen::~UniMountTreeGen()
00019 {
00020
00021 delete mounts;
00022 }
00023
00024
00025 WvString UniMountTreeGen::get(const UniConfKey &key)
00026 {
00027
00028 hold_delta();
00029 UniMountTree::GenIter it(*mounts, key);
00030 for (it.rewind(); it.next(); )
00031 {
00032 UniConfGen *gen = it.ptr();
00033 WvString result = gen->get(it.tail());
00034 if (!result.isnull())
00035 {
00036 unhold_delta();
00037 return result;
00038 }
00039 }
00040 unhold_delta();
00041
00042
00043 UniMountTree *node = mounts->find(key);
00044 if (node)
00045 return "";
00046
00047
00048 return WvString::null;
00049 }
00050
00051
00052 void UniMountTreeGen::set(const UniConfKey &key, WvStringParm value)
00053 {
00054
00055 UniConfKey mountpoint;
00056 UniConfGen *provider = whichmount(key, &mountpoint);
00057 if (provider)
00058 provider->set(mountpoint, value);
00059 }
00060
00061
00062 bool UniMountTreeGen::exists(const UniConfKey &key)
00063 {
00064
00065 UniMountTree *node = mounts->find(key);
00066 if (node)
00067 return true;
00068
00069
00070 hold_delta();
00071 UniMountTree::GenIter it(*mounts, key);
00072 for (it.rewind(); it.next(); )
00073 {
00074 UniConfGen *gen = it.ptr();
00075 if (gen->exists(it.tail()))
00076 {
00077 unhold_delta();
00078 return true;
00079 }
00080 }
00081 unhold_delta();
00082
00083
00084 return false;
00085 }
00086
00087
00088 bool UniMountTreeGen::haschildren(const UniConfKey &key)
00089 {
00090 hold_delta();
00091 UniMountTree *node = mounts->find(key);
00092 bool result = node && node->haschildren();
00093 if (! result)
00094 {
00095 UniMountTree::GenIter it(*mounts, key);
00096 for (it.rewind(); it.next(); )
00097 {
00098 UniConfGen *gen = it.ptr();
00099 if (gen->haschildren(it.tail()))
00100 {
00101 result = true;
00102 break;
00103 }
00104 }
00105 }
00106 unhold_delta();
00107 return result;
00108 }
00109
00110
00111 bool UniMountTreeGen::refresh()
00112 {
00113 hold_delta();
00114 bool result = true;
00115
00116 UniConfGenList::Iter i(mounts->generators);
00117 for (i.rewind(); i.next();)
00118 result = result && i->refresh();
00119
00120 unhold_delta();
00121 return result;
00122 }
00123
00124
00125 void UniMountTreeGen::commit()
00126 {
00127 hold_delta();
00128
00129 UniConfGenList::Iter i(mounts->generators);
00130 for (i.rewind(); i.next();)
00131 i->commit();
00132
00133 unhold_delta();
00134 }
00135
00136
00137 UniConfGen *UniMountTreeGen::mount(const UniConfKey &key,
00138 WvStringParm moniker, bool refresh)
00139 {
00140 UniConfGen *gen = wvcreate<UniConfGen>(moniker);
00141 if (gen)
00142 mountgen(key, gen, refresh);
00143 assert(gen && "Moniker doesn't get us a generator!");
00144 return gen;
00145 }
00146
00147
00148 UniConfGen *UniMountTreeGen::mountgen(const UniConfKey &key,
00149 UniConfGen *gen, bool refresh)
00150 {
00151 UniMountTree *node = mounts->findormake(key);
00152 node->generators.append(gen, true);
00153
00154 hold_delta();
00155
00156 gen->setcallback(UniConfGenCallback(this,
00157 &UniMountTreeGen::gencallback), node);
00158 if (gen && refresh)
00159 gen->refresh();
00160
00161 unhold_delta();
00162 return gen;
00163 }
00164
00165
00166 void UniMountTreeGen::unmount(const UniConfKey &key,
00167 UniConfGen *gen, bool commit)
00168 {
00169 UniMountTree *node = mounts->find(key);
00170 if (!node)
00171 return;
00172
00173 UniConfGenList::Iter genit(node->generators);
00174 if (! genit.find(gen))
00175 return;
00176
00177 hold_delta();
00178
00179 if (commit)
00180 gen->commit();
00181 gen->setcallback(UniConfGenCallback(), NULL);
00182
00183 node->generators.unlink(gen);
00184
00185 unhold_delta();
00186 }
00187
00188
00189 UniConfGen *UniMountTreeGen::whichmount(const UniConfKey &key,
00190 UniConfKey *mountpoint)
00191 {
00192 hold_delta();
00193
00194
00195 UniMountTree::GenIter it(*mounts, key);
00196 for (it.rewind(); it.next(); )
00197 {
00198 UniConfGen *gen = it.ptr();
00199 if (gen->exists(it.tail()))
00200 goto found;
00201 }
00202
00203 it.rewind();
00204 if (! it.next())
00205 {
00206 unhold_delta();
00207 return NULL;
00208 }
00209
00210 found:
00211 if (mountpoint)
00212 *mountpoint = it.tail();
00213 unhold_delta();
00214 return it.ptr();
00215 }
00216
00217
00218 bool UniMountTreeGen::ismountpoint(const UniConfKey &key)
00219 {
00220 UniMountTree *node = mounts->find(key);
00221 return node && ! node->generators.isempty();
00222 }
00223
00224
00225 UniMountTreeGen::Iter *UniMountTreeGen::iterator(const UniConfKey &key)
00226 {
00227 return new KeyIter(*this, key);
00228 }
00229
00230
00231 void UniMountTreeGen::prune(UniMountTree *node)
00232 {
00233 while (node != mounts && !node->isessential())
00234 {
00235 UniMountTree *next = node->parent();
00236 delete node;
00237 node = next;
00238 }
00239 }
00240
00241
00242 void UniMountTreeGen::gencallback(const UniConfKey &key, WvStringParm value,
00243 void *userdata)
00244 {
00245 UniMountTree *node = static_cast<UniMountTree*>(userdata);
00246 delta(UniConfKey(node->fullkey(), key), value);
00247 }
00248
00249
00250
00251
00252
00253 UniMountTreeGen::KeyIter::KeyIter(UniMountTreeGen &root, const UniConfKey &key)
00254 : xroot(&root), xkey(key), genit(*root.mounts, key),
00255 hack(71), hackit(hack)
00256 {
00257 }
00258
00259
00260 void UniMountTreeGen::KeyIter::rewind()
00261 {
00262 xroot->hold_delta();
00263 hack.zap();
00264
00265
00266
00267
00268 UniMountTree *node = xroot->mounts->find(xkey);
00269 if (node)
00270 {
00271 UniMountTree::Iter nodeit(*node);
00272 for (nodeit.rewind(); nodeit.next(); )
00273 hack.add(new WvString(nodeit->key()), true);
00274 }
00275
00276
00277
00278 for (genit.rewind(); genit.next(); )
00279 {
00280 UniConfGen *gen = genit.ptr();
00281 UniConfGen::Iter *keyit = gen->iterator(genit.tail());
00282 for (keyit->rewind(); keyit->next(); )
00283 hack.add(new WvString(keyit->key()), true);
00284 delete keyit;
00285 }
00286
00287 hackit.rewind();
00288 xroot->unhold_delta();
00289 }
00290
00291
00292 bool UniMountTreeGen::KeyIter::next()
00293 {
00294 return hackit.next();
00295 }
00296
00297
00298 UniConfKey UniMountTreeGen::KeyIter::key() const
00299 {
00300 return UniConfKey(hackit());
00301 }
00302
00303
00304
00305
00306
00307 UniMountTree::UniMountTree(UniMountTree *parent,
00308 const UniConfKey &key) :
00309 UniConfTree<UniMountTree>(parent, key)
00310 {
00311 }
00312
00313
00314 UniMountTree::~UniMountTree()
00315 {
00316 }
00317
00318
00319 UniMountTree *UniMountTree::findnearest(const UniConfKey &key,
00320 int &split)
00321 {
00322 split = 0;
00323 UniMountTree *node = this;
00324 UniConfKey::Iter it(key);
00325 for (it.rewind(); it.next(); split++)
00326 {
00327 UniMountTree *next = node->findchild(it());
00328 if (!next)
00329 break;
00330 node = next;
00331 }
00332 return node;
00333 }
00334
00335
00336 UniMountTree *UniMountTree::findormake(const UniConfKey &key)
00337 {
00338 UniMountTree *node = this;
00339 UniConfKey::Iter it(key);
00340 for (it.rewind(); it.next(); )
00341 {
00342 UniMountTree *prev = node;
00343 node = prev->findchild(it());
00344 if (!node)
00345 node = new UniMountTree(prev, it());
00346 }
00347 return node;
00348 }
00349
00350
00351
00352
00353
00354 UniMountTree::MountIter::MountIter(UniMountTree &root,
00355 const UniConfKey &key)
00356 : xkey(key)
00357 {
00358 bestnode = root.findnearest(key, bestsplit);
00359 }
00360
00361
00362 void UniMountTree::MountIter::rewind()
00363 {
00364 xnode = NULL;
00365 }
00366
00367
00368 bool UniMountTree::MountIter::next()
00369 {
00370 if (! xnode)
00371 {
00372 xsplit = bestsplit;
00373 xnode = bestnode;
00374 }
00375 else if (xsplit != 0)
00376 {
00377 xsplit -= 1;
00378 xnode = xnode->parent();
00379 }
00380 else
00381 return false;
00382 return true;
00383 }
00384
00385
00386
00387
00388
00389 UniMountTree::GenIter::GenIter(UniMountTree &root,
00390 const UniConfKey &key) :
00391 UniMountTree::MountIter(root, key),
00392 genit(NULL)
00393 {
00394 }
00395
00396
00397 UniMountTree::GenIter::~GenIter()
00398 {
00399 delete genit;
00400 }
00401
00402
00403 void UniMountTree::GenIter::rewind()
00404 {
00405 if (genit)
00406 {
00407 delete genit;
00408 genit = NULL;
00409 }
00410 UniMountTree::MountIter::rewind();
00411 }
00412
00413
00414 bool UniMountTree::GenIter::next()
00415 {
00416 for (;;)
00417 {
00418 if (genit && genit->next())
00419 return true;
00420 if (! UniMountTree::MountIter::next())
00421 return false;
00422
00423 genit = new UniConfGenList::Iter(node()->generators);
00424 genit->rewind();
00425 }
00426 return false;
00427 }