WvStreams
unitransactiongen.cc
1 #include "unitransactiongen.h"
2 #include "uniconftree.h"
3 #include "unilistiter.h"
4 #include "wvmoniker.h"
5 
6 static IUniConfGen *creator(WvStringParm s, IObject *_obj)
7 {
8  IUniConfGen *base = wvcreate<IUniConfGen>(s, _obj);
9  if (base)
10  return new UniTransactionGen(base);
11  else
12  return NULL;
13 }
14 
15 static WvMoniker<IUniConfGen> moniker("transaction", creator);
16 
17 /* This enum is a field of UniConfChangeTree. It indicates the type of
18  change represented by a node in a UniConfChangeTree. */
19 enum changeMode
20 {
21  /* This indicates that "newvalue" is valid and that
22  its value should be written to the underlying generator at commit
23  time. This tree *might* have children, which must be applied.
24  "newvalue" will be a non-null pointer to a non-null WvString. */
25  NEWVALUE,
26  /* This indicates that "newtree" is valid (but possibly NULL) and that
27  the underlying generator's corresponding subtree should be made
28  identical at commit time. This tree will *not* have children (though
29  newtree might). */
30  NEWTREE,
31  /* This indicates that "was_null_or_empty" is valid and that the key
32  in the underlying generator should be created at commit time if it
33  does not already exist at commit time. This tree *will* have
34  children, which must be applied, and at least one of which will
35  be non-BLANK. "was_null_or_empty" will be the return value of the
36  WvString negation operation on the last known value of the
37  corresponding key in the underlying generator; it is necessary
38  in order to filter callbacks in certain cases. */
39  NEWNODE,
40  /* This indicates that none of the fields are valid and that
41  nothing should be done for this tree. This tree *will* have children,
42  which must be applied, but they will all have mode of NEWTREE with
43  newtree == NULL. */
44  BLANK
45 };
46 
47 class UniConfChangeTree : public UniConfTree<UniConfChangeTree>
48 {
49 public:
50  changeMode mode;
51 
52  // This used to be a union, but it was causing memory errors that were
53  // extremely difficult to track down. Some of this code might serve no
54  // purpose without this being a union, but I'd rather have it still work
55  // and not leak than break it. -- mrwise
56  WvString newvalue;
57  UniConfValueTree *newtree;
58  bool was_null_or_empty;
59 
60  // Constructs a tree and links it to a parent.
62  : UniConfTree<UniConfChangeTree>(parent, key), newtree(0) {}
63 
64  // Destroys a tree and everything it owns.
66  {
67  if (newtree)
68  delete newtree;
69  }
70 };
71 
72 // Constructed by UniTransactionGen::iterator() to iterate over a section that
73 // is to be completely replaced by a particular UniConfValueTree.
75 {
76 public:
78  : i(*node)
79  {
80  // printf("GenStyleValueTreeIter\n");
81  }
82 
84  {
85  // printf("~GenStyleValueTreeIter\n");
86  }
87 
88  void rewind() { i.rewind(); }
89  bool next() { return i.next(); }
90  UniConfKey key() const { return i->key(); }
91  WvString value() const { return i->value(); }
92 
93 private:
95 };
96 
97 // Constructed by UniTransactionGen::iterator() to iterate over a section that
98 // is being modified but not replaced. We iterate first over all of the values
99 // that we're changing, except those we're deleting, and second over all
100 // existing values not iterated over in the first stage, except those we're
101 // deleting.
103 {
104 public:
106  const UniConfKey &_section,
107  IUniConfGen *_base)
108  : root(_root), section(_section), base(_base),
109  doing_i1(true), i1(*root), i2(base->iterator(section))
110  {
111  // printf("GenStyleChangeTreeIter(%s)\n", WvString(section).cstr());
112  }
113 
115  {
116  // printf("~GenStyleChangeTreeIter(%s)\n", WvString(section).cstr());
117  if (i2) delete i2;
118  }
119 
120  void rewind()
121  {
122  i1.rewind();
123  doing_i1 = true;
124  }
125 
126  bool next()
127  {
128  if (doing_i1)
129  {
130  for (;;)
131  {
132  if (i1.next())
133  {
134  if (i1->mode == NEWVALUE ||
135  i1->mode == NEWNODE ||
136  (i1->mode == NEWTREE && i1->newtree))
137  return true;
138  }
139  else
140  break;
141  }
142  doing_i1 = false;
143  if (i2) i2->rewind();
144  }
145  if (i2)
146  {
147  for (;;)
148  {
149  if (i2->next())
150  {
151  UniConfChangeTree *node = root->findchild(i2->key());
152  if (!node || node->mode == BLANK)
153  return true;
154  }
155  else
156  break;
157  }
158  }
159  return false;
160  }
161 
162  UniConfKey key() const
163  {
164  if (doing_i1)
165  return i1->key();
166  else if (i2)
167  return i2->key();
168  else
169  return UniConfKey();
170  }
171 
172  WvString value() const
173  {
174  if (doing_i1)
175  {
176  if (i1->mode == NEWVALUE)
177  return i1->newvalue;
178  else if (i1->mode == NEWTREE)
179  return i1->newtree->value();
180  else // i.e. i1->mode == NEWNODE
181  {
182  WvString value(base->get(UniConfKey(section, i1->key())));
183  return !value ? WvString::empty : value;
184  }
185  }
186  else
187  {
188  return i2->value();
189  }
190  }
191 
192 private:
193  UniConfChangeTree *root;
194  UniConfKey section;
195  IUniConfGen *base;
196 
197  bool doing_i1;
199  UniConfGen::Iter *i2;
200 };
201 
203  : root(NULL), base(_base)
204 {
205  base->add_callback(this, wv::bind(&UniTransactionGen::gencallback, this,
206  _1, _2));
207 }
208 
210 {
211  base->del_callback(this);
212  WVRELEASE(base);
213  WVDELETE(root);
214 }
215 
217 {
218  UniConfChangeTree *node = root;
219  for (int seg = 0;; node = node->findchild(key.segment(seg++)))
220  {
221  if (!node)
222  // If we couldn't find the next node, then we aren't
223  // changing the requested key, and so the value is whatever
224  // it currently is.
225  return base->get(key);
226  else if (node->mode == NEWTREE)
227  {
228  // Else if the next node has mode of NEWTREE, then we're changing
229  // the requested key to whatever its value is in the stored
230  // tree.
231  if (node->newtree)
232  {
233  UniConfValueTree *subnode = node->newtree->find(
234  key.last(key.numsegments() - seg));
235  if (subnode)
236  return subnode->value();
237  }
238  return WvString::null;
239  }
240  else if (seg == key.numsegments())
241  {
242  // Else if this is the last node, then figure out what the node
243  // would do and return the appropriate value. (The node's mode
244  // will be either NEWVALUE, NEWNODE, or BLANK.)
245  if (node->mode == NEWVALUE)
246  return node->newvalue;
247  WvString value(base->get(key.first(seg)));
248  return (node->mode == NEWNODE && !value) ? WvString::empty : value;
249  }
250  }
251 }
252 
253 void UniTransactionGen::set(const UniConfKey &key, WvStringParm value)
254 {
255  hold_delta();
256  root = set_change(root, key, 0, value);
257  unhold_delta();
258 }
259 
260 void UniTransactionGen::setv(const UniConfPairList &pairs)
261 {
262  hold_delta();
263  UniConfPairList::Iter i(pairs);
264  for (i.rewind(); i.next(); )
265  root = set_change(root, i->key(), 0, i->value());
266  unhold_delta();
267 }
268 
270 {
271  if (root)
272  {
273  // Apply our changes to the inner generator. We can't optimise
274  // away callbacks at this point, because we may get notified of
275  // changes caused by our changes.
276  hold_delta();
277  apply_changes(root, UniConfKey());
278 
279  // make sure the inner generator also commits
280  base->commit();
281 
282  // save deleting the root till now so we can hide any
283  // redundant notifications caused by the base->commit()
284  delete root;
285  root = NULL;
286  unhold_delta();
287  }
288 
289  // no need to base->commit() if we know we haven't changed anything!
290 }
291 
293 {
294  if (root)
295  {
296  hold_delta();
297  cancel_changes(root, UniConfKey());
298  delete root;
299  root = NULL;
300  unhold_delta();
301 
302  // no need to base->commit() here, since the inner generator never
303  // saw any changes
304  }
305 
306  // must always base->refresh(), even if we didn't change anything
307  return base->refresh();
308 }
309 
311 {
312  UniConfChangeTree *node = root;
313  for (int seg = 0;; node = node->findchild(key.segment(seg++)))
314  {
315  if (!node)
316  // If we couldn't find the next node, then we aren't changing the
317  // children of the requested key, so they're whatever they
318  // currently are.
319  return base->iterator(key);
320  else if (node->mode == NEWTREE)
321  {
322  // Else if the next node has mode of NEWTREE, then we're changing
323  // the children of the requested key to whatever they are in the
324  // stored tree.
325  if (node->newtree)
326  {
327  UniConfValueTree *subnode = node->newtree->find(
328  key.last(key.numsegments() - seg));
329  if (subnode)
330  {
331  UniConfGen::Iter *i = new GenStyleValueTreeIter(subnode);
332  UniListIter *i2 = new UniListIter(this);
333  i2->autofill(i);
334  delete i;
335  return i2;
336  }
337  }
338  return new UniConfGen::NullIter();
339  }
340  else if (seg == key.numsegments())
341  {
342  // Else if this is the last node, then iterate over its direct
343  // children.
344  UniConfGen::Iter *i = new GenStyleChangeTreeIter(node, key, base);
345  UniListIter *i2 = new UniListIter(this);
346  i2->autofill(i);
347  delete i;
348  return i2;
349  }
350  }
351 }
352 
354  const UniConfKey &section)
355 {
356  base->set(section, newcontents->value());
357 
358  UniConfGen::Iter *j = base->iterator(section);
359  if (j)
360  {
361  for (j->rewind(); j->next();)
362  {
363  if (newcontents->findchild(j->key()) == NULL)
364  // Delete all children of the current value in the
365  // underlying generator that do not exist in our
366  // replacement tree.
367  base->set(UniConfKey(section, j->key()), WvString::null);
368  }
369  delete j;
370  }
371 
372  // Repeat for each child in the replacement tree.
373  UniConfValueTree::Iter i(*newcontents);
374  for (i.rewind(); i.next();)
375  apply_values(i.ptr(), UniConfKey(section, i->key()));
376 }
377 
379  const UniConfKey &section)
380 {
381  if (node->mode == NEWTREE)
382  {
383  // If the current change is a NEWTREE change, then replace the
384  // tree in the underlying generator with the stored one.
385  if (node->newtree == NULL)
386  base->set(section, WvString::null);
387  else
388  apply_values(node->newtree, section);
389  // Since such changes have no children, return immediately.
390  return;
391  }
392  else if (node->mode == NEWVALUE)
393  {
394  // Else if the current change is a NEWVALUE change, ...
395  base->set(section, node->newvalue);
396  }
397  else if (node->mode == NEWNODE)
398  {
399  // Else if the current change is a NEWNODE change, ...
400  if (!base->exists(section))
401  // ... and the current value in the underlying generator doesn't
402  // exist, then create it.
403  base->set(section, WvString::empty);
404  // Note: This *is* necessary. We can't ignore this change and have
405  // the underlying generator handle it, because it's possible that
406  // this NEWNODE was the result of a set() which was later deleted.
407  }
408 
409  // Repeat for each child in the change tree.
410  UniConfChangeTree::Iter i(*node);
411  for (i.rewind(); i.next();)
412  apply_changes(i.ptr(), UniConfKey(section, i->key()));
413 }
414 
416 {
417  UniConfValueTree *node;
418  const UniConfKey &key;
419 };
420 
422  void *userdata)
423 {
424  my_userdata *data = (my_userdata *)userdata;
425  delta(UniConfKey(data->key, node->fullkey(data->node)), WvString::null);
426 }
427 
428 // Mirror image of apply_values() that issues all of the callbacks associated
429 // with discarding a replacement value tree.
431  const UniConfKey &section)
432 {
433  WvString value(base->get(section));
434  if (!newcontents || newcontents->value() != value)
435  delta(section, value);
436 
437  if (newcontents)
438  {
439  UniConfValueTree::Iter i(*newcontents);
440  for (i.rewind(); i.next();)
441  {
442  UniConfKey subkey(section, i->key());
443  if (!base->exists(subkey))
444  {
445  my_userdata data = { i.ptr(), subkey };
446  i->visit(wv::bind(&UniTransactionGen::deletion_visitor, this,
447  _1, _2),
448  (void*)&data, false, true);
449  }
450  }
451  }
452 
453  UniConfGen::Iter *i = base->iterator(section);
454  if (i)
455  {
456  for (i->rewind(); i->next();)
457  cancel_values(newcontents ?
458  newcontents->findchild(i->key()) : NULL,
459  UniConfKey(section, i->key()));
460  delete i;
461  }
462 }
463 
464 // Mirror image of apply_changes() that issues all of the callbacks associated
465 // with discarding a change tree.
467  const UniConfKey &section)
468 {
469  if (node->mode == NEWTREE)
470  {
471  if (!base->exists(section))
472  {
473  if (node->newtree != NULL)
474  {
475  my_userdata data = { node->newtree, section };
476  node->newtree->visit(
477  wv::bind(&UniTransactionGen::deletion_visitor, this,
478  _1, _2),
479  (void *)&data, false, true);
480  }
481  }
482  else
483  cancel_values(node->newtree, section);
484  return;
485  }
486 
487  WvString value;
488  if (node->mode != BLANK)
489  value = base->get(section);
490 
491  if (node->mode == NEWVALUE &&
492  !value.isnull() &&
493  value != node->newvalue)
494  delta(section, value);
495 
496  UniConfChangeTree::Iter i(*node);
497  for (i.rewind(); i.next();)
498  cancel_changes(i.ptr(), UniConfKey(section, i->key()));
499 
500  if (node->mode != BLANK && value.isnull())
501  delta(section, WvString::null);
502 }
503 
505  WvStringParm value)
506 {
507  UniConfChangeTree *node = root;
508  for (int seg = 0;; node = node->findchild(key.segment(seg++)))
509  {
510  if (!node)
511  // If we couldn't find the next node, then we aren't changing
512  // the changed key or any of its children, and so a callback
513  // should be made.
514  break;
515  else if (node->mode == NEWTREE)
516  // Else if the next node has mode of NEWTREE, then we're changing
517  // the changed key and all of its children to whatever their
518  // values are in the stored tree, and so the callback should be
519  // ignored.
520  return;
521  else if (seg == key.numsegments())
522  {
523  // Else if this is the last node, then figure out what we
524  // should do.
525  if (node->mode == NEWVALUE)
526  // If we're replacing this key's value, then we should
527  // ignore the callback.
528  return;
529  else if (node->mode == NEWNODE)
530  {
531  // Else if we want to create this key, then use its
532  // was_null_or_empty flag to figure out if we need
533  // to issue a callback, and update it if necessary.
534  if (node->was_null_or_empty && !value)
535  return;
536  node->was_null_or_empty = !value;
537  if (value.isnull())
538  {
539  delta(key, WvString::empty);
540  return;
541  }
542  break;
543  }
544  else // i.e. node->mode == BLANK
545  // Else if we're doing nothing to this key, then a
546  // callback should be made.
547  break;
548  }
549  }
550 
551  // Make a normal callback.
552  delta(key, value);
553 }
554 
555 // Create and return a UniConfValueTree containing the value 'value' for
556 // the key given by the segments of 'key' at and after position 'seg', with
557 // parent 'parent' and key given by the segment of 'key' at position seg-1
558 // (which is the "root" key if seg == 0). Issue callbacks as necessary using
559 // all the segments of 'key'.
561  const UniConfKey &key,
562  int seg,
563  WvStringParm value)
564 {
565  UniConfValueTree *tree = 0;
566  for (; seg != key.numsegments();)
567  {
568  // Create any needed intermediate nodes, each with value equal to
569  // the empty string.
570  parent = new UniConfValueTree(parent,
571  key.segment(seg-1),
572  WvString::empty);
573  delta(key.first(seg++), WvString::empty);
574  if (!tree)
575  tree = parent;
576  }
577  // Create the last node with the specified value.
578  parent = new UniConfValueTree(parent,
579  key.segment(seg-1),
580  value);
581  delta(key, value);
582  if (!tree)
583  tree = parent;
584  return tree;
585 }
586 
588 {
589  UniConfGen::Iter *i = base->iterator(key);
590  if (i)
591  {
592  for (i->rewind(); i->next();)
593  deletion_simulator(UniConfKey(key, i->key()));
594  delete i;
595  }
596  delta(key, WvString::null);
597 }
598 
599 // Like create_value(), but make a UniConfChangeTree containing a *change*
600 // to value 'value'.
601 UniConfChangeTree *UniTransactionGen::create_change(UniConfChangeTree *parent,
602  const UniConfKey &key,
603  int seg,
604  WvStringParm value)
605 {
606  // if the key has a trailing slash, this should be a no-op: we don't
607  // want this to have any effect
608  if ((key.hastrailingslash()) && !value.isnull())
609  return parent;
610 
611  UniConfChangeTree *tree = 0;
612  for (; seg != key.numsegments(); seg++)
613  {
614  parent = new UniConfChangeTree(parent, key.segment(seg-1));
615  if (value.isnull())
616  // We don't do anything for intermediate nodes when deleting, ...
617  parent->mode = BLANK;
618  else
619  {
620  // ... but when set()'ing a non-null value, we want them to exist.
621  parent->mode = NEWNODE;
622  UniConfKey nodekey(key.first(seg));
623  WvString curr = base->get(nodekey);
624  parent->was_null_or_empty = !curr;
625  if (curr.isnull())
626  delta(nodekey, WvString::empty);
627  }
628  if (!tree)
629  tree = parent;
630  }
631  parent = new UniConfChangeTree(parent, key.segment(seg-1));
632  // Create the last node with the specified change.
633  if (value.isnull())
634  {
635  parent->mode = NEWTREE;
636  parent->newtree = 0;
637  if (base->exists(key))
638  deletion_simulator(key);
639  }
640  else
641  {
642  parent->mode = NEWVALUE;
643  parent->newvalue = WvString(value);
644  if (base->get(key) != value)
645  delta(key, value);
646  }
647  if (!tree)
648  tree = parent;
649  return tree;
650 }
651 
652 // Modify an existing UniConfValueTree to incorporate the set() of a
653 // particular value for a particular key. Return a possibly altered
654 // pointer to the root of the tree. 'seg' and 'key' are used like they
655 // are in create_value(), and callbacks are made similarly.
656 UniConfValueTree *UniTransactionGen::set_value(UniConfValueTree *node,
657  const UniConfKey &key,
658  int seg,
659  WvStringParm value)
660 {
661  // printf("set_value('%s', %d)\n", WvString(key).cstr(), value.isnull());
662  if (value.isnull())
663  {
664  // Delete the key if it exists.
665  if (node)
666  {
667  UniConfValueTree *subnode = node->find(
668  key.last(key.numsegments() - seg));
669  if (subnode)
670  {
671  hold_delta();
672  my_userdata data = { subnode, key };
673  subnode->visit(wv::bind(&UniTransactionGen::deletion_visitor,
674  this, _1, _2),
675  (void *)&data, false, true);
676  // printf("DELETE SUBNODE!\n");
677  delete subnode;
678  unhold_delta();
679  return subnode == node ? NULL : node;
680  }
681  else
682  return node;
683  }
684  else
685  return NULL;
686  }
687  else
688  {
689  // Switch to create_value() if we ever can't find the next node.
690  if (!node)
691  return create_value(NULL, key, seg, value);
692 
693  UniConfValueTree *subnode = node;
694  for (; seg != key.numsegments();)
695  {
696  UniConfKey segment(key.segment(seg++));
697  UniConfValueTree *child = subnode->findchild(segment);
698  // Switch to create_value() if we ever can't find the next node.
699  if (!child)
700  {
701  create_value(subnode, key, seg, value);
702  return node;
703  }
704  else
705  subnode = child;
706  }
707  // The node already existed and we've found it; set it.
708  if (value != subnode->value())
709  {
710  subnode->setvalue(value);
711  delta(key, value);
712  }
713  return node;
714  }
715 }
716 
718 {
719  UniConfGen::Iter *i = this->iterator(key);
720  if (i)
721  {
722  for (i->rewind(); i->next();)
723  deletion_simulator2(UniConfKey(key, i->key()));
724  delete i;
725  }
726  delta(key, WvString::null);
727 }
728 
729 // Like set_value(), but, again, for UniConfChangeTrees instead.
730 UniConfChangeTree *UniTransactionGen::set_change(UniConfChangeTree *node,
731  const UniConfKey &key,
732  int seg,
733  WvStringParm value)
734 {
735  // printf("set_change(key=%s,mode=%d) = '%s'\n",
736  // WvString(key).cstr(), node ? node->mode : 999, value.cstr());
737 
738  // Switch to create_change() if we ever can't find the next node,
739  // and switch to set_value() if we ever find a NEWTREE.
740  if (!node)
741  return create_change(NULL, key, seg, value);
742  else if (node->mode == NEWTREE)
743  {
744  node->newtree = set_value(node->newtree, key, seg, value);
745  return node;
746  }
747 
748  UniConfChangeTree *subnode = node;
749  for (; seg != key.numsegments();)
750  {
751  if (subnode->mode == BLANK && !value.isnull())
752  {
753  // If we're setting a non-null value and we weren't previously
754  // doing anything to this node, then now we want to create it.
755  subnode->mode = NEWNODE;
756  UniConfKey nodekey(key.first(seg));
757  WvString curr = base->get(nodekey);
758  subnode->was_null_or_empty = !curr;
759  if (curr.isnull())
760  delta(nodekey, WvString::empty);
761  }
762 
763  UniConfKey segment(key.segment(seg++));
764  UniConfChangeTree *next = subnode->findchild(segment);
765  // Switch to create_change() if we ever can't find the next node,
766  // and switch to set_value() if we ever find a NEWTREE.
767  if (!next)
768  {
769  create_change(subnode, key, seg, value);
770  return node;
771  }
772  else if (next->mode == NEWTREE)
773  {
774  next->newtree = set_value(next->newtree,
775  key, seg, value);
776  return node;
777  }
778  else
779  subnode = next;
780  }
781  // The node already existed, didn't have mode of NEWTREE, and we've
782  // found it; change it.
783  if (value.isnull())
784  {
785  if (subnode->mode != BLANK || base->exists(key))
786  deletion_simulator2(key);
787  subnode->zap();
788  subnode->mode = NEWTREE;
789  subnode->newtree = 0;
790  }
791  else if (subnode->mode == NEWVALUE)
792  {
793  if (subnode->newvalue != value)
794  {
795  subnode->newvalue = value;
796  delta(key, value);
797  }
798  }
799  else if (subnode->mode == BLANK)
800  {
801  if (base->get(key) != value)
802  delta(key, value);
803  subnode->mode = NEWVALUE;
804  subnode->newvalue = WvString(value);
805  }
806  else // i.e. subnode->mode == NEWNODE
807  {
808  WvString currval(base->get(key));
809  if ((!currval != !value) && (currval != value))
810  delta(key, value);
811  subnode->mode = NEWVALUE;
812  subnode->newvalue = WvString(value);
813  }
814  return node;
815 }
816 
817 // We'll say we're okay whenever the underlying generator is.
819 {
820  return base->isok();
821 }
822 
824 {
825 }
IUniConfGen::set
virtual void set(const UniConfKey &key, WvStringParm value)=0
Stores a string value for a key into the registry.
IUniConfGen::exists
virtual bool exists(const UniConfKey &key)=0
Without fetching its value, returns true if a key exists.
UniConfGen::Iter::value
virtual WvString value() const =0
Returns the value of the current key.
UniTransactionGen::apply_values
void apply_values(UniConfValueTree *newcontents, const UniConfKey &section)
A recursive helper function for apply_changes().
Definition: unitransactiongen.cc:353
UniTransactionGen::get
virtual WvString get(const UniConfKey &key)
Fetches a string value for a key from the registry.
Definition: unitransactiongen.cc:216
UniTransactionGen::flush_buffers
virtual void flush_buffers()
Flushes any commitment/notification buffers .
Definition: unitransactiongen.cc:823
IUniConfGen::get
virtual WvString get(const UniConfKey &key)=0
Fetches a string value for a key from the registry.
UniTransactionGen::cancel_changes
void cancel_changes(UniConfChangeTree *node, const UniConfKey &section)
A recursive helper function for refresh().
Definition: unitransactiongen.cc:466
UniListIter
An iterator that iterates through a constant list of keys.
Definition: unilistiter.h:27
UniTransactionGen::~UniTransactionGen
~UniTransactionGen()
Destroys the UniTransactionGen and the underlying generator.
Definition: unitransactiongen.cc:209
UniConfGen::Iter::key
virtual UniConfKey key() const =0
Returns the current key.
UniTransactionGen::iterator
virtual Iter * iterator(const UniConfKey &key)
Returns an iterator over the children of the specified key.
Definition: unitransactiongen.cc:310
my_userdata
Definition: unitransactiongen.cc:415
UniTransactionGen::apply_changes
void apply_changes(UniConfChangeTree *node, const UniConfKey &section)
A recursive helper function for commit().
Definition: unitransactiongen.cc:378
UniTransactionGen::cancel_values
void cancel_values(UniConfValueTree *newcontents, const UniConfKey &section)
A recursive helper function for cancel_changes().
Definition: unitransactiongen.cc:430
UniConfGen::unhold_delta
void unhold_delta()
Resumes notifications when each hold_delta() has been matched.
Definition: uniconfgen.cc:38
UniConfTree
A recursively composed dictionary for tree-structured data indexed by UniConfKey.
Definition: uniconftree.h:23
UniTransactionGen::deletion_simulator
void deletion_simulator(const UniConfKey &key)
A recursive helper function for create_change().
Definition: unitransactiongen.cc:587
WvString
WvString is an implementation of a simple and efficient printable-string class.
Definition: wvstring.h:329
GenStyleValueTreeIter::next
bool next()
Seeks to the next element in the sequence.
Definition: unitransactiongen.cc:89
GenStyleValueTreeIter::rewind
void rewind()
Rewinds the iterator.
Definition: unitransactiongen.cc:88
IUniConfGen
An abstract data container that backs a UniConf tree.
Definition: uniconfgen.h:39
UniConfTree::findchild
Sub * findchild(const UniConfKey &key) const
Finds the direct child node with the specified key.
Definition: uniconftree.h:71
UniHashTreeBase::key
const UniConfKey & key() const
Returns the key field.
Definition: unihashtree.h:40
UniConfValueTree::value
const WvString & value() const
Returns the value field.
Definition: uniconftree.h:163
UniConfTree::visit
void visit(const Visitor &visitor, void *userdata, bool preorder=true, bool postorder=false) const
Performs a traversal on this tree using the specified visitor function and traversal type(s).
Definition: uniconftree.h:108
WvFastString::isnull
bool isnull() const
returns true if this string is null
Definition: wvstring.h:290
UniTransactionGen::create_value
UniConfValueTree * create_value(UniConfValueTree *parent, const UniConfKey &key, int seg, WvStringParm value)
Four functions to implement the functionality of set() so that it isn't two pages long.
Definition: unitransactiongen.cc:560
GenStyleChangeTreeIter::value
WvString value() const
Returns the value of the current key.
Definition: unitransactiongen.cc:172
UniHashTreeBase::Iter
Definition: unihashtree.h:78
UniTransactionGen::gencallback
void gencallback(const UniConfKey &key, WvStringParm value)
The callback function for the underlying generator.
Definition: unitransactiongen.cc:504
UniTransactionGen::set
virtual void set(const UniConfKey &key, WvStringParm value)
Stores a string value for a key into the registry.
Definition: unitransactiongen.cc:253
GenStyleChangeTreeIter::rewind
void rewind()
Rewinds the iterator.
Definition: unitransactiongen.cc:120
UniTransactionGen::deletion_visitor
void deletion_visitor(const UniConfValueTree *node, void *userdata)
A UniConfTree visitor function for set_value(), cancel_values(), and cancel_changes().
Definition: unitransactiongen.cc:421
UniConfKey
Represents a UniConf key which is a path in a hierarchy structured much like the traditional Unix fil...
Definition: uniconfkey.h:38
UniConfValueTree::setvalue
void setvalue(WvStringParm value)
Sets the value field.
Definition: uniconftree.h:167
WvMoniker
A type-safe version of WvMonikerBase that lets you provide create functions for object types other th...
Definition: wvmoniker.h:61
UniTransactionGen
A UniConfGen that represents pending transactions to another generator.
Definition: unitransactiongen.h:80
UniTransactionGen::refresh
virtual bool refresh()
Refreshes information about a key recursively.
Definition: unitransactiongen.cc:292
UniConfChangeTree
Definition: unitransactiongen.cc:47
UniConfGen::delta
void delta(const UniConfKey &key, WvStringParm value)
Call this when a key's value or children have possibly changed.
Definition: uniconfgen.cc:77
IObject
Definition: IObject.h:65
GenStyleValueTreeIter
Definition: unitransactiongen.cc:74
IUniConfGen::commit
virtual void commit()=0
Commits any changes.
UniConfKey::first
UniConfKey first(int n=1) const
Returns the path formed by the n first segments of this path.
Definition: uniconfkey.h:314
UniConfTree< UniConfChangeTree >::parent
UniConfChangeTree * parent() const
Returns a pointer to the parent node, or NULL if there is none.
Definition: uniconftree.h:40
GenStyleChangeTreeIter
Definition: unitransactiongen.cc:102
GenStyleValueTreeIter::key
UniConfKey key() const
Returns the current key.
Definition: unitransactiongen.cc:90
UniTransactionGen::commit
virtual void commit()
Commits any changes.
Definition: unitransactiongen.cc:269
GenStyleValueTreeIter::value
WvString value() const
Returns the value of the current key.
Definition: unitransactiongen.cc:91
UniConfGen::Iter::rewind
virtual void rewind()=0
Rewinds the iterator.
UniConfTree::zap
void zap()
Removes and deletes all children of this node.
Definition: uniconftree.h:84
IUniConfGen::del_callback
virtual void del_callback(void *cookie)=0
Removes a callback for change notification.
UniConfTree::fullkey
UniConfKey fullkey(const Sub *ancestor=NULL) const
Returns full path of this node relative to an ancestor.
Definition: uniconftree.h:55
IUniConfGen::isok
virtual bool isok()=0
Determines if the generator is usable and working properly.
UniTransactionGen::UniTransactionGen
UniTransactionGen(IUniConfGen *_base)
Constructs a UniTransactionGen for the given underlying generator, which must be non-null.
Definition: unitransactiongen.cc:202
IUniConfGen::iterator
virtual Iter * iterator(const UniConfKey &key)=0
Returns an iterator over the children of the specified key.
IUniConfGen::refresh
virtual bool refresh()=0
Refreshes information about a key recursively.
UniTransactionGen::deletion_simulator2
void deletion_simulator2(const UniConfKey &key)
A recursive helper function for set_change().
Definition: unitransactiongen.cc:717
GenStyleChangeTreeIter::key
UniConfKey key() const
Returns the current key.
Definition: unitransactiongen.cc:162
UniConfValueTree
A plain UniConfTree that holds keys and values.
Definition: uniconftree.h:152
UniConfKey::hastrailingslash
bool hastrailingslash() const
Returns true if the key has a trailing slash.
Definition: uniconfkey.h:273
UniConfGen::Iter::next
virtual bool next()=0
Seeks to the next element in the sequence.
UniConfKey::segment
UniConfKey segment(int n) const
Returns the specified segment of the path.
Definition: uniconfkey.h:297
UniConfGen::NullIter
An iterator that's always empty.
Definition: uniconfgen.h:357
GenStyleChangeTreeIter::next
bool next()
Seeks to the next element in the sequence.
Definition: unitransactiongen.cc:126
IUniConfGen::add_callback
virtual void add_callback(void *cookie, const UniConfGenCallback &callback)=0
Adds a callback for change notification.
UniConfTree::find
Sub * find(const UniConfKey &key) const
Finds the sub-node with the specified key.
Definition: uniconftree.h:62
UniConfKey::last
UniConfKey last(int n=1) const
Returns the path formed by the n last segments of this path.
Definition: uniconfkey.h:324
UniListIter::autofill
void autofill(IUniConfGen::Iter *source)
Automatically fill the contents of this iterator by calling add() for each element of the 'source' it...
Definition: unilistiter.cc:26
UniConfKey::numsegments
int numsegments() const
Returns the number of segments in this path.
Definition: uniconfkey.h:287
UniConfGen::hold_delta
void hold_delta()
Pauses notifications until matched with a call to unhold_delta().
Definition: uniconfgen.cc:32
UniTransactionGen::isok
virtual bool isok()
Determines if the generator is usable and working properly.
Definition: unitransactiongen.cc:818
UniTransactionGen::setv
virtual void setv(const UniConfPairList &pairs)
Stores multiple key-value pairs into the registry.
Definition: unitransactiongen.cc:260
UniConfGen::Iter
An abstract iterator over keys and values in a generator.
Definition: uniconfgen.h:323