Make WvStreams compile with gcc 4.4.
[wvstreams.git] / uniconf / uniconfroot.cc
blob40a489496107bb23d4e7ea8489bbffe4a82ac2b8
1 /*
2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
4 *
5 * Defines the root management class for UniConf. To create any kind of
6 * UniConf tree, you'll need one of these.
7 */
8 #include "uniconfroot.h"
9 #include "wvlinkerhack.h"
11 WV_LINK_TO(UniGenHack);
14 UniConfRoot::UniConfRoot():
15 UniConf(this),
16 watchroot(NULL)
18 mounts.add_callback(this, wv::bind(&UniConfRoot::gen_callback, this,
19 _1, _2));
23 UniConfRoot::UniConfRoot(WvStringParm moniker, bool refresh):
24 UniConf(this),
25 watchroot(NULL)
27 mounts.mount("/", moniker, refresh);
28 mounts.add_callback(this, wv::bind(&UniConfRoot::gen_callback, this,
29 _1, _2));
33 UniConfRoot::UniConfRoot(UniConfGen *gen, bool refresh):
34 UniConf(this),
35 watchroot(NULL)
37 mounts.mountgen("/", gen, refresh);
38 mounts.add_callback(this, wv::bind(&UniConfRoot::gen_callback, this,
39 _1, _2));
43 // make sure the given subtree of callback information is empty
44 static bool watchout(UniWatchInfoTree *t)
46 bool fail = false;
48 UniWatchInfoTree::Iter i(*t);
49 for (i.rewind(); i.next(); )
51 UniWatchInfoTree *w = i.ptr();
53 if (w->haschildren())
54 if (watchout(w))
55 fail = true;
57 if (!w->watches.isempty())
59 fail = true;
60 if (1)
61 fprintf(stderr, "Remaining watch: '%s' (%zd)\n",
62 w->fullkey().printable().cstr(), w->watches.count());
66 return fail;
70 UniConfRoot::~UniConfRoot()
72 // first, unmount everything. Some of the mounts might have waiting
73 // callbacks. (I hope not, but... things like UniUnwrapGen might get
74 // confusing.)
75 mounts.zap();
77 // if the list of callbacks is non-empty, someone is either very buggy
78 // (they disappeared without deleting their callback, so they could cause
79 // crashes), or they're not getting what they expected (we disappeared
80 // before they did, so they won't be getting their callback).
81 assert(!watchout(&watchroot));
83 mounts.del_callback(this);
87 void UniConfRoot::add_callback(void *cookie, const UniConfKey &key,
88 const UniConfCallback &callback, bool recurse)
90 UniWatchInfo *w = new UniWatchInfo(cookie, recurse, callback);
92 UniWatchInfoTree *node = &watchroot;
94 UniConfKey::Iter i(key);
95 for (i.rewind(); i.next(); )
97 UniWatchInfoTree *prev = node;
98 node = node->findchild(i());
99 if (!node)
100 node = new UniWatchInfoTree(prev, i());
102 node->watches.append(w, true);
106 void UniConfRoot::del_callback(void *cookie, const UniConfKey &key,
107 bool recurse)
109 UniWatchInfoTree *node = watchroot.find(key);
110 if (node)
112 UniWatchInfoList::Iter i(node->watches);
113 for (i.rewind(); i.next(); )
115 // remove the watch if it matches
116 if (i->cookie == cookie && i->recurse == recurse)
118 i.xunlink();
119 break;
122 // prune the branch if needed
123 prune(node);
128 void UniConfRoot::add_setbool(const UniConfKey &key, bool *flag, bool recurse)
130 add_callback(flag, key, wv::bind(&UniConfRoot::setbool_callback, flag,
131 _1, _2),
132 recurse);
136 void UniConfRoot::del_setbool(const UniConfKey &key, bool *flag, bool recurse)
138 del_callback(flag, key, recurse);
142 void UniConfRoot::check(UniWatchInfoTree *node,
143 const UniConfKey &key, int segleft)
145 UniWatchInfoList::Iter i(node->watches);
146 for (i.rewind(); i.next(); )
148 if (!i->recursive() && segleft > 0)
149 continue;
151 i->notify(UniConf(this, key.removelast(segleft)), key.last(segleft));
156 void UniConfRoot::deletioncheck(UniWatchInfoTree *node, const UniConfKey &key)
158 UniWatchInfoTree::Iter i(*node);
159 for (i.rewind(); i.next(); )
161 UniWatchInfoTree *w = i.ptr();
162 UniConfKey subkey(key, w->key());
164 // pretend that we wiped out just this key
165 check(w, subkey, 0);
166 deletioncheck(w, subkey);
171 void UniConfRoot::prune(UniWatchInfoTree *node)
173 while (node != & watchroot && ! node->isessential())
175 UniWatchInfoTree *next = node->parent();
176 delete node;
177 node = next;
182 void UniConfRoot::gen_callback(const UniConfKey &key, WvStringParm value)
184 hold_delta();
185 UniWatchInfoTree *node = & watchroot;
186 int segs = key.numsegments();
188 // check root node
189 check(node, key, segs);
191 // look for watches on key and its ancestors
192 for (int s = 0; s < segs; )
194 node = node->findchild(key.segment(s));
195 s++;
196 if (!node)
197 goto done; // no descendents so we can stop
198 check(node, key, segs - s);
201 // look for watches on descendents of key if node was deleted
202 if (value.isnull())
203 deletioncheck(node, key);
205 done:
206 unhold_delta();