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