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 
16 UniConf::UniConf(UniConfRoot *root, const UniConfKey &fullkey)
17  : xroot(root), xfullkey(fullkey)
18 {
19  // nothing special
20 }
21 
22 
23 UniConf::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 
50 bool UniConf::exists() const
51 {
52  return xroot->mounts.exists(xfullkey);
53 }
54 
55 
57 {
58  return xroot->mounts.haschildren(xfullkey);
59 }
60 
61 
62 void UniConf::prefetch(bool recursive) const
63 {
64  xroot->mounts.prefetch(xfullkey, recursive);
65 }
66 
67 
68 WvString UniConf::getme(WvStringParm defvalue) const
69 {
70  WvString value = xroot->mounts.get(xfullkey);
71  if (value.isnull())
72  return defvalue;
73  return value;
74 }
75 
76 
77 int UniConf::getmeint(int defvalue) const
78 {
79  return xroot->mounts.str2int(getme(), defvalue);
80 }
81 
82 
83 void UniConf::setme(WvStringParm value) const
84 {
85  xroot->mounts.set(xfullkey, value);
86 }
87 
88 
89 void UniConf::setmeint(int value) const
90 {
91  setme(WvString(value));
92 }
93 
94 
95 void UniConf::move(const UniConf &dst) const
96 {
97  dst.remove();
98  copy(dst, true);
99  remove();
100 }
101 
102 
103 void 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 
119 bool UniConf::refresh() const
120 {
121  return xroot->mounts.refresh();
122 }
123 
124 
125 void UniConf::commit() const
126 {
127  xroot->mounts.commit();
128 }
129 
130 
131 IUniConfGen *UniConf::mount(WvStringParm moniker, bool refresh) const
132 {
133  return xroot->mounts.mount(xfullkey, moniker, refresh);
134 }
135 
136 
137 IUniConfGen *UniConf::mountgen(IUniConfGen *gen, bool refresh) const
138 {
139  return xroot->mounts.mountgen(xfullkey, gen, refresh);
140 }
141 
142 
143 void 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 
161 bool UniConf::isok() const
162 {
163  IUniConfGen *gen = whichmount();
164  return gen && gen->isok();
165 }
166 
167 
168 void UniConf::add_callback(void *cookie, const UniConfCallback &callback,
169  bool recurse) const
170 {
171  xroot->add_callback(cookie, xfullkey, callback, recurse);
172 }
173 
174 
175 void UniConf::del_callback(void *cookie, bool recurse) const
176 {
177  xroot->del_callback(cookie, xfullkey, recurse);
178 }
179 
180 
181 void UniConf::add_setbool(bool *flag, bool recurse) const
182 {
183  xroot->add_setbool(xfullkey, flag, recurse);
184 }
185 
186 
187 void 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 
217 void 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 
253 UniConf::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 
273 UniConf::XIter::~XIter()
274 {
275  cleanup();
276 }
277 
278 
279 void 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 
299 void 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 
344 inline 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 
367 void UniConf::XIter::enter(const UniConf &child)
368 {
369  subit = new UniConf::XIter(child, pattail);
370  subit->rewind();
371 }
372 
373 
374 bool 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 
411 UniConf::SortedIterBase::SortedIterBase(const UniConf &root,
412  UniConf::SortedIterBase::Comparator comparator)
413  : IterBase(root), xcomparator(comparator), xkeys()
414 {
415 }
416 
417 
418 UniConf::SortedIterBase::~SortedIterBase()
419 {
420  _purge();
421 }
422 
423 
425  const UniConf &b)
426 {
427  return a.fullkey().compareto(b.fullkey());
428 }
429 
430 
431 static UniConf::SortedIterBase::Comparator innercomparator = NULL;
432 
433 static bool wrapcomparator(const UniConf &a, const UniConf &b)
434 {
435  return innercomparator(a, b) < 0;
436 }
437 
438 
439 void UniConf::SortedIterBase::_purge()
440 {
441  count = xkeys.size();
442  xkeys.clear();
443 }
444 
445 
446 void 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 
457 bool UniConf::SortedIterBase::next()
458 {
459  if (index >= count)
460  return false;
461  current = xkeys[index];
462  index += 1;
463  return true;
464 }
UniConf::IterBase
An implementation base class for key iterators.
Definition: uniconf.h:415
UniConf::refresh
bool refresh() const
Refreshes information about this key recursively.
Definition: uniconf.cc:119
UniConfKey::removefirst
UniConfKey removefirst(int n=1) const
Returns the path formed by removing the first n segments of this path.
Definition: uniconfkey.h:335
UniConf::commit
void commit() const
Commits information about this key recursively.
Definition: uniconf.cc:125
UniConf::UniConf
UniConf()
Creates a NULL UniConf handle, useful for reporting errors.
Definition: uniconf.cc:23
UniConf::XIter
This iterator walks over all children that match a wildcard pattern.
Definition: uniconf.h:511
UniConf::setmeint
void setmeint(int value) const
Stores an integer value for this key into the registry.
Definition: uniconf.cc:89
UniConfKey::compareto
int compareto(const UniConfKey &other) const
Compares two paths lexicographically.
Definition: uniconfkey.cc:235
UniConf::del_callback
void del_callback(void *cookie, bool recurse=true) const
Cancels notification requested using add_callback().
Definition: uniconf.cc:175
UniConf::Iter::Iter
Iter(const UniConf &_top)
Creates an iterator over the direct children of a branch.
Definition: uniconf.cc:232
UniConf::~UniConf
virtual ~UniConf()
Destroys the UniConf handle.
Definition: uniconf.cc:36
UniConf::mountgen
IUniConfGen * mountgen(IUniConfGen *gen, bool refresh=true) const
Mounts a generator at this key.
Definition: uniconf.cc:137
UniConf::add_callback
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
UniConf::isok
bool isok() const
Returns true if the generator at this key isok().
Definition: uniconf.cc:161
UniConf::remove
void remove() const
Removes this key and all of its children from the registry.
Definition: uniconf.h:232
UniConf
UniConf instances function as handles to subtrees of a UniConf tree and expose a high-level interface...
Definition: uniconf.h:50
UniConf::prefetch
void prefetch(bool recursive) const
See UniConfGen::prefetch().
Definition: uniconf.cc:62
UniConfKey::subkey
UniConfKey subkey(const UniConfKey &key) const
If this UniConfKey is a subkey of 'key', then return the subkey portion.
Definition: uniconfkey.cc:324
UniConf::root
UniConf root() const
Returns a handle to the root of the tree.
Definition: uniconf.h:80
UniConf::getme
WvString getme(WvStringParm defvalue=WvString::null) const
Fetches the string value for this key from the registry.
Definition: uniconf.cc:68
UniConf::dump
void dump(WvStream &stream, bool everything=false) const
Prints the entire contents of this subtree to a stream.
Definition: uniconf.cc:217
UniConf::unmount
void unmount(IUniConfGen *gen, bool commit) const
Unmounts the generator providing this key and destroys it.
Definition: uniconf.cc:143
UniConf::flush_delta
void flush_delta()
Flushes the list of pending notifications by sending them.
Definition: uniconf.cc:211
UniConf::SortedIterBase::defcomparator
static int defcomparator(const UniConf &a, const UniConf &b)
Default comparator.
Definition: uniconf.cc:424
UniConf::add_setbool
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
WvString
WvString is an implementation of a simple and efficient printable-string class.
Definition: wvstring.h:329
IUniConfGen
An abstract data container that backs a UniConf tree.
Definition: uniconfgen.h:39
UniConf::rootobj
UniConfRoot * rootobj() const
Returns a pointer to the UniConfRoot that manages this node.
Definition: uniconf.h:91
WvFastString::isnull
bool isnull() const
returns true if this string is null
Definition: wvstring.h:290
UniConfKey
Represents a UniConf key which is a path in a hierarchy structured much like the traditional Unix fil...
Definition: uniconfkey.h:38
UniConfKey::ANY
static UniConfKey ANY
Definition: uniconfkey.h:172
UniConf::del_setbool
void del_setbool(bool *flag, bool recurse=true) const
Cancels notification requested using add_setbool().
Definition: uniconf.cc:187
UniConf::copy
void copy(const UniConf &dst, bool force) const
Equivalent to "cp -r" in a standard unix filesystem.
Definition: uniconf.cc:103
UniConfKey::isempty
bool isempty() const
Returns true if this path has zero segments (also known as root).
Definition: uniconfkey.h:264
UniConfKey::first
UniConfKey first(int n=1) const
Returns the path formed by the n first segments of this path.
Definition: uniconfkey.h:314
UniConfKey::EMPTY
static UniConfKey EMPTY
Definition: uniconfkey.h:171
UniConf::getmeint
int getmeint(int defvalue=0) const
Fetches the integer value for this key from the registry.
Definition: uniconf.cc:77
UniConf::setme
void setme(WvStringParm value) const
Stores a string value for this key into the registry.
Definition: uniconf.cc:83
WvStream
Unified support for streams, that is, sequences of bytes that may or may not be ready for read/write ...
Definition: wvstream.h:24
UniConf::mount
IUniConfGen * mount(WvStringParm moniker, bool refresh=true) const
Mounts a generator at this key using a moniker.
Definition: uniconf.cc:131
UniConf::RecursiveIter::RecursiveIter
RecursiveIter(const UniConf &_top)
Creates a recursive iterator over a branch.
Definition: uniconf.cc:243
IUniConfGen::isok
virtual bool isok()=0
Determines if the generator is usable and working properly.
UniConf::fullkey
UniConfKey fullkey() const
Returns the full path of this node, starting at the root.
Definition: uniconf.h:99
UniConfGen::NullIter
An iterator that's always empty.
Definition: uniconfgen.h:357
UniConf::hold_delta
void hold_delta()
Pauses notifications until matched with a call to unhold_delta().
Definition: uniconf.cc:193
UniConf::XIter::XIter
XIter(const UniConf &_top, const UniConfKey &pattern)
Creates a wildcard iterator.
Definition: uniconf.cc:253
UniConf::haschildren
bool haschildren() const
Returns true if this key has children.
Definition: uniconf.cc:56
UniConfKey::iswild
bool iswild() const
Returns true if the key contains a wildcard.
Definition: uniconfkey.cc:174
UniConfRoot
Represents the root of a hierarhical registry consisting of pairs of UniConfKeys and associated strin...
Definition: uniconfroot.h:73
UniConf::ismountpoint
bool ismountpoint() const
Determines if any generators are mounted at this key.
Definition: uniconf.cc:149
UniConf::move
void move(const UniConf &dst) const
Equivalent to "mv" in a standard unix filesystem.
Definition: uniconf.cc:95
UniConf::Iter
This iterator walks through all immediate children of a UniConf node.
Definition: uniconf.h:435
UniConf::exists
bool exists() const
Without fetching its value, returns true if this key exists.
Definition: uniconf.cc:50
UniConf::clear_delta
void clear_delta()
Clears the list of pending notifications without sending them.
Definition: uniconf.cc:205
UniConf::unhold_delta
void unhold_delta()
Resumes notifications when each hold_delta() has been matched.
Definition: uniconf.cc:199
UniConf::RecursiveIter
This iterator performs depth-first traversal of a subtree.
Definition: uniconf.h:466
UniConfKey::append
void append(const UniConfKey &other)
Appends a path to this path.
Definition: uniconfkey.cc:130
UniConfKey::RECURSIVE_ANY
static UniConfKey RECURSIVE_ANY
Definition: uniconfkey.h:173
UniConf::whichmount
IUniConfGen * whichmount(UniConfKey *mountpoint=NULL) const
Finds the generator that owns this key.
Definition: uniconf.cc:155