WvStreams
uniconf.cc
1/*
2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
4 *
5 * Defines a hierarchical registry abstraction. See uniconf.h.
6 */
7#include "uniconf.h"
8#include "uniconfroot.h"
9#include "uniconfgen.h"
10#include "wvstream.h"
11#include <climits>
12#include <algorithm>
13#include <assert.h>
14
15
17 : xroot(root), xfullkey(fullkey)
18{
19 // nothing special
20}
21
22
23UniConf::UniConf() : xroot(NULL), xfullkey(UniConfKey::EMPTY)
24{
25 // nothing special
26}
27
28
30 : xroot(other.xroot), xfullkey(other.xfullkey)
31{
32 // nothing special
33}
34
35
37{
38 // nothing special
39}
40
41
42
43
45{
46 return k.subkey(xfullkey);
47}
48
49
50bool UniConf::exists() const
51{
52 return xroot->mounts.exists(xfullkey);
53}
54
55
57{
58 return xroot->mounts.haschildren(xfullkey);
59}
60
61
62void UniConf::prefetch(bool recursive) const
63{
64 xroot->mounts.prefetch(xfullkey, recursive);
65}
66
67
69{
70 WvString value = xroot->mounts.get(xfullkey);
71 if (value.isnull())
72 return defvalue;
73 return value;
74}
75
76
77int UniConf::getmeint(int defvalue) const
78{
79 return xroot->mounts.str2int(getme(), defvalue);
80}
81
82
84{
85 xroot->mounts.set(xfullkey, value);
86}
87
88
89void UniConf::setmeint(int value) const
90{
91 setme(WvString(value));
92}
93
94
95void UniConf::move(const UniConf &dst) const
96{
97 dst.remove();
98 copy(dst, true);
99 remove();
100}
101
102
103void UniConf::copy(const UniConf &dst, bool force) const
104{
105 // do the main key first
106 dst.setme(getme());
107
108 // now all the children
109 RecursiveIter i(*this);
110 for (i.rewind(); i.next(); )
111 {
112 UniConf dst2 = dst[i->fullkey(*this)];
113 if (force || dst2.getme().isnull())
114 dst2.setme(i->getme());
115 }
116}
117
118
120{
121 return xroot->mounts.refresh();
122}
123
124
125void UniConf::commit() const
126{
127 xroot->mounts.commit();
128}
129
130
131IUniConfGen *UniConf::mount(WvStringParm moniker, bool refresh) const
132{
133 return xroot->mounts.mount(xfullkey, moniker, refresh);
134}
135
136
137IUniConfGen *UniConf::mountgen(IUniConfGen *gen, bool refresh) const
138{
139 return xroot->mounts.mountgen(xfullkey, gen, refresh);
140}
141
142
143void UniConf::unmount(IUniConfGen *gen, bool commit) const
144{
145 return xroot->mounts.unmount(gen, commit);
146}
147
148
150{
151 return xroot->mounts.ismountpoint(xfullkey);
152}
153
154
156{
157 return xroot->mounts.whichmount(xfullkey, mountpoint);
158}
159
160
161bool UniConf::isok() const
162{
163 IUniConfGen *gen = whichmount();
164 return gen && gen->isok();
165}
166
167
168void UniConf::add_callback(void *cookie, const UniConfCallback &callback,
169 bool recurse) const
170{
171 xroot->add_callback(cookie, xfullkey, callback, recurse);
172}
173
174
175void UniConf::del_callback(void *cookie, bool recurse) const
176{
177 xroot->del_callback(cookie, xfullkey, recurse);
178}
179
180
181void UniConf::add_setbool(bool *flag, bool recurse) const
182{
183 xroot->add_setbool(xfullkey, flag, recurse);
184}
185
186
187void UniConf::del_setbool(bool *flag, bool recurse) const
188{
189 xroot->del_setbool(xfullkey, flag, recurse);
190}
191
192
194{
195 xroot->mounts.hold_delta();
196}
197
198
200{
201 xroot->mounts.unhold_delta();
202}
203
204
206{
207 xroot->mounts.clear_delta();
208}
209
210
212{
213 xroot->mounts.flush_delta();
214}
215
216
217void UniConf::dump(WvStream &stream, bool everything) const
218{
219 UniConf::RecursiveIter it(*this);
220 for (it.rewind(); it.next(); )
221 {
222 WvString value(it->getme());
223 if (everything || !!value)
224 stream.print("%s = %s\n", it->fullkey(), value);
225 }
226}
227
228
229
230/***** UniConf::Iter *****/
231
233 : IterBase(_top)
234{
235 it = _top.rootobj()->mounts.iterator(top.fullkey());
236 if (!it) it = new UniConfGen::NullIter;
237}
238
239
240
241/***** UniConf::RecursiveIter *****/
242
244 : IterBase(_top)
245{
246 it = _top.rootobj()->mounts.recursiveiterator(top.fullkey());
247 if (!it) it = new UniConfGen::NullIter;
248}
249
250
251/***** UniConf::XIter *****/
252
253UniConf::XIter::XIter(const UniConf &_top, const UniConfKey &pattern)
254 : IterBase(_top), pathead(pattern.first()),
255 pattail(pattern.removefirst()), subit(NULL), it(NULL), recit(NULL)
256{
257 if (! pathead.iswild())
258 {
259 // optimization to collect as many consecutive non-wildcard
260 // segments as possible in one go
261 while (! pattail.isempty())
262 {
263 UniConfKey patnext(pattail.first());
264 if (patnext.iswild())
265 break;
266 pathead.append(patnext);
267 pattail = pattail.removefirst();
268 }
269 }
270}
271
272
273UniConf::XIter::~XIter()
274{
275 cleanup();
276}
277
278
279void UniConf::XIter::cleanup()
280{
281 if (subit)
282 {
283 delete subit;
284 subit = NULL;
285 }
286 if (it)
287 {
288 delete it;
289 it = NULL;
290 }
291 if (recit)
292 {
293 delete recit;
294 recit = NULL;
295 }
296}
297
298
299void UniConf::XIter::rewind()
300{
301 cleanup();
302 ready = false;
303
304 if (pathead.isempty())
305 {
306 current = top;
307 ready = current.exists();
308 }
309 else if (pathead == UniConfKey::RECURSIVE_ANY)
310 {
311 recit = new UniConf::RecursiveIter(top);
312 recit->rewind();
313 if (UniConfKey::EMPTY.matches(pattail))
314 {
315 // pattern includes self
316 current = top;
317 ready = current.exists();
318 }
319 }
320 else if (pathead == UniConfKey::ANY)
321 {
322 it = new UniConf::Iter(top);
323 it->rewind();
324 }
325 else
326 {
327 // non-wildcard segment
328 current = top[pathead];
329 if (pattail.isempty())
330 {
331 // don't bother recursing if there are no deeper wildcard
332 // elements (works together with optimization in constructor)
333 ready = current.exists();
334 }
335 else
336 {
337 // more wildcards, setup recursion
338 enter(current);
339 }
340 }
341}
342
343
344inline bool UniConf::XIter::qnext()
345{
346 if (subit) // currently in a sub-iterator
347 {
348 bool found = subit->next();
349 if (found)
350 {
351 current = **subit;
352 return true;
353 }
354 else
355 {
356 // end of this sub-iterator
357 delete subit;
358 subit = NULL;
359 return false;
360 }
361 }
362 else // no sub-iterator at all
363 return false;
364}
365
366
367void UniConf::XIter::enter(const UniConf &child)
368{
369 subit = new UniConf::XIter(child, pattail);
370 subit->rewind();
371}
372
373
374bool UniConf::XIter::next()
375{
376 if (ready)
377 {
378 ready = false;
379 return true;
380 }
381 while (!qnext())
382 {
383 // UniConfKey::ANY
384 if (it && it->next())
385 {
386 /* Not needed for now since we don't match partial keys
387 if (! pathead.matches(it->key()))
388 break;
389 */
390 enter(**it);
391 continue;
392 }
393 // UniConfKey::RECURSIVE_ANY
394 if (recit && recit->next())
395 {
396 enter(**recit);
397 continue;
398 }
399 // anything else or finished
400 return false;
401 }
402
403 // if we get here, qnext() returned true
404 return true;
405}
406
407
408
409/***** UniConf::SortedIterBase *****/
410
411UniConf::SortedIterBase::SortedIterBase(const UniConf &root,
412 UniConf::SortedIterBase::Comparator comparator)
413 : IterBase(root), xcomparator(comparator), xkeys()
414{
415}
416
417
418UniConf::SortedIterBase::~SortedIterBase()
419{
420 _purge();
421}
422
423
425 const UniConf &b)
426{
427 return a.fullkey().compareto(b.fullkey());
428}
429
430
431static UniConf::SortedIterBase::Comparator innercomparator = NULL;
432
433static bool wrapcomparator(const UniConf &a, const UniConf &b)
434{
435 return innercomparator(a, b) < 0;
436}
437
438
439void UniConf::SortedIterBase::_purge()
440{
441 count = xkeys.size();
442 xkeys.clear();
443}
444
445
446void UniConf::SortedIterBase::_rewind()
447{
448 index = 0;
449 count = xkeys.size();
450
451 // This code is NOT reentrant because qsort makes it too hard
452 innercomparator = xcomparator;
453 std::sort(xkeys.begin(), xkeys.end(), wrapcomparator);
454}
455
456
457bool UniConf::SortedIterBase::next()
458{
459 if (index >= count)
460 return false;
461 current = xkeys[index];
462 index += 1;
463 return true;
464}
An abstract data container that backs a UniConf tree.
Definition: uniconfgen.h:40
virtual bool isok()=0
Determines if the generator is usable and working properly.
An iterator that's always empty.
Definition: uniconfgen.h:358
Represents a UniConf key which is a path in a hierarchy structured much like the traditional Unix fil...
Definition: uniconfkey.h:39
UniConfKey subkey(const UniConfKey &key) const
If this UniConfKey is a subkey of 'key', then return the subkey portion.
Definition: uniconfkey.cc:324
UniConfKey removefirst(int n=1) const
Returns the path formed by removing the first n segments of this path.
Definition: uniconfkey.h:335
static UniConfKey ANY
Definition: uniconfkey.h:172
int compareto(const UniConfKey &other) const
Compares two paths lexicographically.
Definition: uniconfkey.cc:235
bool iswild() const
Returns true if the key contains a wildcard.
Definition: uniconfkey.cc:174
static UniConfKey RECURSIVE_ANY
Definition: uniconfkey.h:173
void append(const UniConfKey &other)
Appends a path to this path.
Definition: uniconfkey.cc:130
bool isempty() const
Returns true if this path has zero segments (also known as root).
Definition: uniconfkey.h:264
static UniConfKey EMPTY
Definition: uniconfkey.h:171
UniConfKey first(int n=1) const
Returns the path formed by the n first segments of this path.
Definition: uniconfkey.h:314
Represents the root of a hierarhical registry consisting of pairs of UniConfKeys and associated strin...
Definition: uniconfroot.h:74
An implementation base class for key iterators.
Definition: uniconf.h:416
This iterator walks through all immediate children of a UniConf node.
Definition: uniconf.h:436
Iter(const UniConf &_top)
Creates an iterator over the direct children of a branch.
Definition: uniconf.cc:232
This iterator performs depth-first traversal of a subtree.
Definition: uniconf.h:467
RecursiveIter(const UniConf &_top)
Creates a recursive iterator over a branch.
Definition: uniconf.cc:243
static int defcomparator(const UniConf &a, const UniConf &b)
Default comparator.
Definition: uniconf.cc:424
This iterator walks over all children that match a wildcard pattern.
Definition: uniconf.h:512
XIter(const UniConf &_top, const UniConfKey &pattern)
Creates a wildcard iterator.
Definition: uniconf.cc:253
UniConf instances function as handles to subtrees of a UniConf tree and expose a high-level interface...
Definition: uniconf.h:51
void commit() const
Commits information about this key recursively.
Definition: uniconf.cc:125
void add_callback(void *cookie, const UniConfCallback &callback, bool recurse=true) const
Requests notification when any of the keys covered by the recursive depth specification change by inv...
Definition: uniconf.cc:168
void remove() const
Removes this key and all of its children from the registry.
Definition: uniconf.h:232
void prefetch(bool recursive) const
See UniConfGen::prefetch().
Definition: uniconf.cc:62
UniConf root() const
Returns a handle to the root of the tree.
Definition: uniconf.h:80
void clear_delta()
Clears the list of pending notifications without sending them.
Definition: uniconf.cc:205
void move(const UniConf &dst) const
Equivalent to "mv" in a standard unix filesystem.
Definition: uniconf.cc:95
int getmeint(int defvalue=0) const
Fetches the integer value for this key from the registry.
Definition: uniconf.cc:77
bool haschildren() const
Returns true if this key has children.
Definition: uniconf.cc:56
void setme(WvStringParm value) const
Stores a string value for this key into the registry.
Definition: uniconf.cc:83
bool exists() const
Without fetching its value, returns true if this key exists.
Definition: uniconf.cc:50
void unmount(IUniConfGen *gen, bool commit) const
Unmounts the generator providing this key and destroys it.
Definition: uniconf.cc:143
UniConf()
Creates a NULL UniConf handle, useful for reporting errors.
Definition: uniconf.cc:23
void add_setbool(bool *flag, bool recurse=true) const
Requests notification when any of the keys covered by the recursive depth specification change by set...
Definition: uniconf.cc:181
void del_setbool(bool *flag, bool recurse=true) const
Cancels notification requested using add_setbool().
Definition: uniconf.cc:187
bool refresh() const
Refreshes information about this key recursively.
Definition: uniconf.cc:119
IUniConfGen * mount(WvStringParm moniker, bool refresh=true) const
Mounts a generator at this key using a moniker.
Definition: uniconf.cc:131
IUniConfGen * whichmount(UniConfKey *mountpoint=NULL) const
Finds the generator that owns this key.
Definition: uniconf.cc:155
UniConfKey fullkey() const
Returns the full path of this node, starting at the root.
Definition: uniconf.h:99
void flush_delta()
Flushes the list of pending notifications by sending them.
Definition: uniconf.cc:211
void del_callback(void *cookie, bool recurse=true) const
Cancels notification requested using add_callback().
Definition: uniconf.cc:175
UniConfRoot * rootobj() const
Returns a pointer to the UniConfRoot that manages this node.
Definition: uniconf.h:91
void copy(const UniConf &dst, bool force) const
Equivalent to "cp -r" in a standard unix filesystem.
Definition: uniconf.cc:103
bool isok() const
Returns true if the generator at this key isok().
Definition: uniconf.cc:161
void dump(WvStream &stream, bool everything=false) const
Prints the entire contents of this subtree to a stream.
Definition: uniconf.cc:217
void unhold_delta()
Resumes notifications when each hold_delta() has been matched.
Definition: uniconf.cc:199
void setmeint(int value) const
Stores an integer value for this key into the registry.
Definition: uniconf.cc:89
virtual ~UniConf()
Destroys the UniConf handle.
Definition: uniconf.cc:36
void hold_delta()
Pauses notifications until matched with a call to unhold_delta().
Definition: uniconf.cc:193
bool ismountpoint() const
Determines if any generators are mounted at this key.
Definition: uniconf.cc:149
WvString getme(WvStringParm defvalue=WvString::null) const
Fetches the string value for this key from the registry.
Definition: uniconf.cc:68
IUniConfGen * mountgen(IUniConfGen *gen, bool refresh=true) const
Mounts a generator at this key.
Definition: uniconf.cc:137
A WvFastString acts exactly like a WvString, but can take (const char *) strings without needing to a...
Definition: wvstring.h:94
bool isnull() const
returns true if this string is null
Definition: wvstring.h:290
Unified support for streams, that is, sequences of bytes that may or may not be ready for read/write ...
Definition: wvstream.h:25
WvString is an implementation of a simple and efficient printable-string class.
Definition: wvstring.h:330