Make WvStreams compile with gcc 4.4.
[wvstreams.git] / uniconf / unitempgen.cc
blobe019e9a53ae7337c032a404fbccb1e10b6c978b6
1 /*
2 * Worldvisions Weaver Software:
3 * Copyright (C) 2002-2005 Net Integration Technologies, Inc.
4 *
5 * A UniConf generator that stores keys in memory.
6 */
7 #include "unitempgen.h"
8 #include "wvmoniker.h"
9 #include "wvlog.h"
10 #include "wvstringcache.h"
11 #include "unilistiter.h"
12 #include "wvlinkerhack.h"
14 WV_LINK(UniTempGen);
16 static IUniConfGen *creator(WvStringParm, IObject*)
18 return new UniTempGen();
21 static WvMoniker<IUniConfGen> reg("temp", creator);
24 /***** UniTempGen *****/
26 UniTempGen::UniTempGen()
27 : root(NULL)
32 UniTempGen::~UniTempGen()
34 delete root;
38 WvString UniTempGen::get(const UniConfKey &key)
40 if (root)
42 // Look for an empty section at the end.
43 if (!key.isempty() && key.last().isempty())
44 return WvString::null;
45 UniConfValueTree *node = root->find(key);
46 if (node)
47 return node->value();
49 return WvString::null;
52 void UniTempGen::notify_deleted(const UniConfValueTree *node, void *)
54 delta(node->fullkey(), WvString::null);
57 void UniTempGen::set(const UniConfKey &_key, WvStringParm _value)
59 WvString value(scache.get(_value));
61 hold_delta();
62 UniConfKey key = _key;
63 // FIXME: Use key.hastrailingslash(), it's shorter and easier and faster
64 bool trailing_slash = false;
65 if (!key.isempty())
67 // Look for an empty section at the end.
68 UniConfKey last = key;
69 key = last.pop(last.numsegments() - 1);
70 if (last.isempty())
71 trailing_slash = true;
72 else
73 key = _key;
76 if (value.isnull())
78 // remove a subtree
79 if (root)
81 UniConfValueTree *node = root->find(key);
82 if (node)
84 hold_delta();
85 // Issue notifications for every key that gets deleted.
86 node->visit(wv::bind(&UniTempGen::notify_deleted, this,
87 _1, _2),
88 NULL, false, true);
89 delete node;
90 if (node == root)
91 root = NULL;
92 dirty = true;
93 unhold_delta();
97 else if (!trailing_slash)
99 UniConfValueTree *node = root;
100 UniConfValueTree *prev = NULL;
101 UniConfKey prevkey;
103 UniConfKey::Iter it(key);
104 it.rewind();
105 for (;;)
107 bool more = it.next(); // not the last node in the key?
109 if (!node)
111 // we'll have to create the sub-node, since we couldn't
112 // find the most recent part of the key.
113 node = new UniConfValueTree(prev, prevkey,
114 more ? WvString::empty : value);
115 dirty = true;
116 if (!prev) // we just created the root
117 root = node;
118 if (more)
119 delta(node->fullkey(), WvString::empty); // AUTO-VIVIFIED
120 else
122 delta(node->fullkey(), value); // ADDED
123 break; // done!
126 else if (!more)
128 // don't have to create the most recent sub-node, but there
129 // are no more sub-nodes; that means we're changing the value
130 // of an existing node.
131 if (value != node->value())
133 node->setvalue(value);
134 dirty = true;
135 delta(node->fullkey(), value); // CHANGED
137 break;
139 prevkey = *it;
140 prev = node;
141 node = prev->findchild(prevkey);
143 assert(node);
146 unhold_delta();
150 void UniTempGen::setv(const UniConfPairList &pairs)
152 setv_naive(pairs);
156 bool UniTempGen::haschildren(const UniConfKey &key)
158 if (root)
160 UniConfValueTree *node = root->find(key);
161 return node != NULL && node->haschildren();
163 return false;
167 UniConfGen::Iter *UniTempGen::iterator(const UniConfKey &key)
169 if (root)
171 UniConfValueTree *node = root->find(key);
172 if (node)
174 ListIter *it = new ListIter(this);
175 UniConfValueTree::Iter i(*node);
176 for (i.rewind(); i.next(); )
177 it->add(i->key(), i->value());
178 return it;
181 return NULL;
185 void UniTempGen::commit()
187 UniConfGen::commit();
191 bool UniTempGen::refresh()
193 return UniConfGen::refresh();