WvStreams
|
00001 /* 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 2002-2005 Net Integration Technologies, Inc. 00004 * 00005 * A UniConf generator that stores keys in memory. 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 /***** UniTempGen *****/ 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 // Look for an empty section at the end. 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 // FIXME: Use key.hastrailingslash(), it's shorter and easier and faster 00064 bool trailing_slash = false; 00065 if (!key.isempty()) 00066 { 00067 // Look for an empty section at the end. 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 // remove a subtree 00079 if (root) 00080 { 00081 UniConfValueTree *node = root->find(key); 00082 if (node) 00083 { 00084 hold_delta(); 00085 // Issue notifications for every key that gets deleted. 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(); // not the last node in the key? 00108 00109 if (!node) 00110 { 00111 // we'll have to create the sub-node, since we couldn't 00112 // find the most recent part of the key. 00113 node = new UniConfValueTree(prev, prevkey, 00114 more ? WvString::empty : value); 00115 dirty = true; 00116 if (!prev) // we just created the root 00117 root = node; 00118 if (more) 00119 delta(node->fullkey(), WvString::empty); // AUTO-VIVIFIED 00120 else 00121 { 00122 delta(node->fullkey(), value); // ADDED 00123 break; // done! 00124 } 00125 } 00126 else if (!more) 00127 { 00128 // don't have to create the most recent sub-node, but there 00129 // are no more sub-nodes; that means we're changing the value 00130 // of an existing node. 00131 if (value != node->value()) 00132 { 00133 node->setvalue(value); 00134 dirty = true; 00135 delta(node->fullkey(), value); // CHANGED 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 }