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