00001
00002
00003
00004
00005
00006
00007 #include "unitempgen.h"
00008 #include "wvmoniker.h"
00009 #include "wvlog.h"
00010 #include "wvstringcache.h"
00011 #include "unilistiter.h"
00012
00013 static IUniConfGen *creator(WvStringParm)
00014 {
00015 return new UniTempGen();
00016 }
00017
00018 static WvMoniker<IUniConfGen> reg("temp", creator);
00019
00020
00021
00022
00023 UniTempGen::UniTempGen()
00024 : root(NULL)
00025 {
00026 }
00027
00028
00029 UniTempGen::~UniTempGen()
00030 {
00031 delete root;
00032 }
00033
00034
00035 WvString UniTempGen::get(const UniConfKey &key)
00036 {
00037 if (root)
00038 {
00039
00040 if (!key.isempty() && key.last().isempty())
00041 return WvString::null;
00042 UniConfValueTree *node = root->find(key);
00043 if (node)
00044 return node->value();
00045 }
00046 return WvString::null;
00047 }
00048
00049 void UniTempGen::notify_deleted(const UniConfValueTree *node, void *)
00050 {
00051 delta(node->fullkey(), WvString::null);
00052 }
00053
00054 void UniTempGen::set(const UniConfKey &_key, WvStringParm _value)
00055 {
00056 WvString value(scache.get(_value));
00057
00058 hold_delta();
00059 UniConfKey key = _key;
00060 bool trailing_slash = false;
00061 if (!key.isempty())
00062 {
00063
00064 UniConfKey last = key;
00065 key = last.pop(last.numsegments() - 1);
00066 if (last.isempty())
00067 trailing_slash = true;
00068 else
00069 key = _key;
00070 }
00071
00072 if (value.isnull())
00073 {
00074
00075 if (root)
00076 {
00077 UniConfValueTree *node = root->find(key);
00078 if (node)
00079 {
00080 hold_delta();
00081
00082 node->visit(UniConfValueTree::Visitor(this,
00083 &UniTempGen::notify_deleted), NULL, false, true);
00084 delete node;
00085 if (node == root)
00086 root = NULL;
00087 dirty = true;
00088 unhold_delta();
00089 }
00090 }
00091 }
00092 else if (!trailing_slash)
00093 {
00094 UniConfValueTree *node = root;
00095 UniConfValueTree *prev = NULL;
00096 UniConfKey prevkey;
00097
00098 UniConfKey::Iter it(key);
00099 it.rewind();
00100 for (;;)
00101 {
00102 bool more = it.next();
00103
00104 if (!node)
00105 {
00106
00107
00108 node = new UniConfValueTree(prev, scache.get(prevkey),
00109 more ? scache.get("") : value);
00110 dirty = true;
00111 if (!prev)
00112 root = node;
00113 if (more)
00114 delta(node->fullkey(), WvString::empty);
00115 else
00116 {
00117 delta(node->fullkey(), value);
00118 break;
00119 }
00120 }
00121 else if (!more)
00122 {
00123
00124
00125
00126 if (value != node->value())
00127 {
00128 node->setvalue(value);
00129 dirty = true;
00130 delta(node->fullkey(), value);
00131 }
00132 break;
00133 }
00134 prevkey = *it;
00135 prev = node;
00136 node = prev->findchild(prevkey);
00137 }
00138 assert(node);
00139 }
00140
00141 unhold_delta();
00142 }
00143
00144
00145 void UniTempGen::setv(const UniConfPairList &pairs)
00146 {
00147 setv_naive(pairs);
00148 }
00149
00150
00151 bool UniTempGen::haschildren(const UniConfKey &key)
00152 {
00153 if (root)
00154 {
00155 UniConfValueTree *node = root->find(key);
00156 return node != NULL && node->haschildren();
00157 }
00158 return false;
00159 }
00160
00161
00162 UniConfGen::Iter *UniTempGen::iterator(const UniConfKey &key)
00163 {
00164 if (root)
00165 {
00166 UniConfValueTree *node = root->find(key);
00167 if (node)
00168 {
00169 ListIter *it = new ListIter(this);
00170 UniConfValueTree::Iter i(*node);
00171 for (i.rewind(); i.next(); )
00172 it->add(i->key(), i->value());
00173 return it;
00174 }
00175 }
00176 return NULL;
00177 }
00178
00179
00180 void UniTempGen::commit()
00181 {
00182 scache.clean();
00183 UniConfGen::commit();
00184 }
00185
00186
00187 bool UniTempGen::refresh()
00188 {
00189 scache.clean();
00190 return UniConfGen::refresh();
00191 }