Make WvStreams compile with gcc 4.4.
[wvstreams.git] / uniconf / unireplicategen.cc
blob205a01aefaaa2fe21382b0858f657d7188e8d418
1 /*
2 * Worldvisions Weaver Software:
3 * Copyright (C) 2002 Net Integration Technologies, Inc.
4 *
5 * A UniConf generator that replicates multiple generators, prioritized
6 * by order.
7 */
8 #include "uniconf.h"
9 #include "unireplicategen.h"
10 #include "wvmoniker.h"
11 #include "wvstringlist.h"
12 #include "wvtclstring.h"
13 #include "wvlinkerhack.h"
15 WV_LINK(UniReplicateGen);
18 #if 0
19 #define DPRINTF(format, args...) fprintf(stderr, format ,##args);
20 #else
21 #define DPRINTF if (0) printf
22 #endif
25 static IUniConfGen *creator(WvStringParm s, IObject *_obj)
27 IUniConfGenList gens;
29 DPRINTF("encoded_monikers = %s\n", s.cstr());
30 WvStringList monikers;
31 wvtcl_decode(monikers, s);
32 DPRINTF("monikers = %s\n", monikers.join(",").cstr());
34 WvStringList::Iter i(monikers);
35 for (i.rewind(); i.next(); )
37 if (_obj) _obj->addRef();
38 IUniConfGen *gen = wvcreate<IUniConfGen>(*i, _obj);
39 if (gen)
40 gens.append(gen, false);
42 if (_obj) _obj->release();
44 return new UniReplicateGen(gens);
47 static WvMoniker<IUniConfGen> reg("replicate", creator);
50 /***** UniReplicateGen *****/
52 UniReplicateGen::UniReplicateGen() : processing_callback(false)
57 UniReplicateGen::UniReplicateGen(const IUniConfGenList &_gens,
58 bool auto_free) : processing_callback(false)
60 IUniConfGenList::Iter i(_gens);
62 for (i.rewind(); i.next(); )
64 Gen *gen = new Gen(i.ptr(), auto_free);
65 if (gen)
67 gens.append(gen, true);
68 gen->gen->add_callback(this,
69 wv::bind(&UniReplicateGen::deltacallback,
70 this, gen, _1, _2));
74 replicate();
78 UniReplicateGen::~UniReplicateGen()
80 GenList::Iter i(gens);
81 for (i.rewind(); i.next(); )
82 i->gen->del_callback(this);
86 void UniReplicateGen::prepend(IUniConfGen *_gen, bool auto_free)
88 Gen *gen = new Gen(_gen, auto_free);
89 if (gen)
91 gens.prepend(gen, true);
92 gen->gen->add_callback(this, wv::bind(&UniReplicateGen::deltacallback,
93 this, gen, _1, _2));
95 replicate();
100 void UniReplicateGen::append(IUniConfGen *_gen, bool auto_free)
102 Gen *gen = new Gen(_gen, auto_free);
103 if (gen)
105 gens.append(gen, true);
106 gen->gen->add_callback(this, wv::bind(&UniReplicateGen::deltacallback,
107 this, gen, _1, _2));
109 replicate();
114 bool UniReplicateGen::isok()
116 return first_ok() != NULL;
120 bool UniReplicateGen::refresh()
122 bool result = true;
124 replicate_if_any_have_become_ok();
126 GenList::Iter i(gens);
127 for (i.rewind(); i.next(); )
129 if (!i->gen->refresh())
130 result = false;
133 return result;
137 void UniReplicateGen::commit()
139 replicate_if_any_have_become_ok();
141 GenList::Iter i(gens);
142 for (i.rewind(); i.next(); )
144 i->gen->commit();
149 void UniReplicateGen::deltacallback(Gen *src_gen, const UniConfKey &key,
150 WvStringParm value)
152 DPRINTF("UniReplicateGen::deltacallback(%s, %s)\n",
153 key.printable().cstr(), value.cstr());
155 if (!processing_callback)
157 DPRINTF("UniReplicateGen::deltacallback(): !processing_callback\n");
159 processing_callback = true;
161 GenList::Iter j(gens);
162 for (j.rewind(); j.next(); )
164 if (!j->isok())
165 continue;
167 if (j.ptr() != src_gen)
169 DPRINTF("UniReplicateGen::deltacallback: %p->set(%s, %s)\n",
170 j.ptr(), key.printable().cstr(), value.cstr());
171 j->gen->set(key, value);
175 delta(key, value);
177 processing_callback = false;
179 else
181 DPRINTF("UniReplicateGen::deltacallback(): processing_callback\n");
186 void UniReplicateGen::set(const UniConfKey &key, WvStringParm value)
188 DPRINTF("UniReplicateGen::set(%s, %s)\n",
189 key.printable().cstr(), value.cstr());
191 replicate_if_any_have_become_ok();
193 Gen *first = first_ok();
194 if (first)
195 first->gen->set(key, value);
196 else
197 DPRINTF("UniReplicateGen::set: first == NULL\n");
201 void UniReplicateGen::setv(const UniConfPairList &pairs)
203 DPRINTF("UniReplicateGen::setv\n");
205 replicate_if_any_have_become_ok();
207 Gen *first = first_ok();
208 if (first)
209 first->gen->setv(pairs);
210 else
211 DPRINTF("UniReplicateGen::setv: first == NULL\n");
215 WvString UniReplicateGen::get(const UniConfKey &key)
217 for (;;)
219 replicate_if_any_have_become_ok();
221 Gen *first = first_ok();
222 if (first)
224 WvString result = first->gen->get(key);
226 // It's possible that first has become !isok(); we must
227 // take care of this case carefully
228 if (!result && !first->isok())
230 Gen *new_first = first_ok();
231 if (new_first == first)
232 return result;
233 first = new_first;
235 else
236 return result;
238 else
239 return WvString::null;
244 UniConfGen::Iter *UniReplicateGen::iterator(const UniConfKey &key)
246 replicate_if_any_have_become_ok();
248 Gen *first = first_ok();
249 if (first)
250 return first->gen->iterator(key);
251 else
252 return NULL;
256 UniReplicateGen::Gen *UniReplicateGen::first_ok() const
258 GenList::Iter j(gens);
259 for (j.rewind(); j.next(); )
261 if (j->isok())
262 return j.ptr();
265 return NULL;
269 void UniReplicateGen::replicate(const UniConfKey &key)
271 DPRINTF("UniReplicateGen::replicate(%s)\n", key.printable().cstr());
273 hold_delta();
275 Gen *first = first_ok();
277 GenList::Iter j(gens);
278 for (j.rewind(); j.next(); )
280 DPRINTF("UniReplicateGen::replicate: %p\n", j.ptr());
282 if (!j->isok())
284 DPRINTF("UniReplicateGen::replicate: !isok()\n");
285 continue;
288 UniConfGen::Iter *i = j->gen->recursiveiterator(key);
289 if (!i)
291 DPRINTF("UniReplicateGen::replicate: no iterator\n");
292 continue;
295 for (i->rewind(); i->next(); )
297 DPRINTF("UniReplicateGen::replicate: key=%s, value=%s\n",
298 i->key().printable().cstr(), i->value().cstr());
300 if (j.ptr() == first)
302 DPRINTF("UniReplicateGen::replicate: deltacallback()\n");
303 deltacallback(first, i->key(), i->value());
305 else
307 if (!first->gen->exists(i->key()))
309 DPRINTF("UniReplicateGen::replicate: !exists()\n");
310 first->gen->set(i->key(), i->value());
312 else
314 DPRINTF("UniReplicateGen::replicate: exists()\n");
319 delete i;
322 unhold_delta();
324 DPRINTF("UniReplicateGen::replicate: done\n");
327 void UniReplicateGen::replicate_if_any_have_become_ok()
329 bool should_replicate = false;
331 GenList::Iter j(gens);
332 for (j.rewind(); j.next(); )
334 if (!j->was_ok && j->gen->isok())
336 j->was_ok = true;
338 should_replicate = true;
342 if (should_replicate)
344 DPRINTF("UniReplicateGen::replicate_if_any_have_become_ok: replicating\n");
345 replicate();