unitempgen.cc

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 
00013 static IUniConfGen *creator(WvStringParm)
00014 {
00015     return new UniTempGen();
00016 }
00017 
00018 static WvMoniker<IUniConfGen> reg("temp", creator);
00019 
00020 
00021 /***** UniTempGen *****/
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         // Look for an empty section at the end.
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     // FIXME: Use key.hastrailingslash(), it's shorter and easier and faster
00061     bool trailing_slash = false;
00062     if (!key.isempty())
00063     {
00064         // Look for an empty section at the end.
00065         UniConfKey last = key;
00066         key = last.pop(last.numsegments() - 1);
00067         if (last.isempty())
00068             trailing_slash = true;
00069         else
00070             key = _key;
00071     }
00072 
00073     if (value.isnull())
00074     {
00075         // remove a subtree
00076         if (root)
00077         {
00078             UniConfValueTree *node = root->find(key);
00079             if (node)
00080             {
00081                 hold_delta();
00082                 // Issue notifications for every key that gets deleted.
00083                 node->visit(UniConfValueTree::Visitor(this,
00084                     &UniTempGen::notify_deleted), NULL, false, true);
00085                 delete node;
00086                 if (node == root)
00087                     root = NULL;
00088                 dirty = true;
00089                 unhold_delta();
00090             }
00091         }
00092     }
00093     else if (!trailing_slash)
00094     {
00095         UniConfValueTree *node = root;
00096         UniConfValueTree *prev = NULL;
00097         UniConfKey prevkey;
00098         
00099         UniConfKey::Iter it(key);
00100         it.rewind();
00101         for (;;)
00102         {
00103             bool more = it.next(); // not the last node in the key?
00104             
00105             if (!node)
00106             {
00107                 // we'll have to create the sub-node, since we couldn't
00108                 // find the most recent part of the key.
00109                 node = new UniConfValueTree(prev, prevkey,
00110                                             more ? WvString::empty : value);
00111                 dirty = true;
00112                 if (!prev) // we just created the root
00113                     root = node;
00114                 if (more)
00115                     delta(node->fullkey(), WvString::empty); // AUTO-VIVIFIED
00116                 else
00117                 {
00118                     delta(node->fullkey(), value); // ADDED
00119                     break; // done!
00120                 }
00121             }
00122             else if (!more)
00123             {
00124                 // don't have to create the most recent sub-node, but there
00125                 // are no more sub-nodes; that means we're changing the value
00126                 // of an existing node.
00127                 if (value != node->value())
00128                 {
00129                     node->setvalue(value);
00130                     dirty = true;
00131                     delta(node->fullkey(), value); // CHANGED
00132                 }
00133                 break;
00134             }
00135             prevkey = *it;
00136             prev = node;
00137             node = prev->findchild(prevkey);
00138         }
00139         assert(node);
00140     }
00141     
00142     unhold_delta();
00143 }
00144 
00145 
00146 void UniTempGen::setv(const UniConfPairList &pairs)
00147 {
00148     setv_naive(pairs);
00149 }
00150 
00151 
00152 bool UniTempGen::haschildren(const UniConfKey &key)
00153 {
00154     if (root)
00155     {
00156         UniConfValueTree *node = root->find(key);
00157         return node != NULL && node->haschildren();
00158     }
00159     return false;
00160 }
00161 
00162 
00163 UniConfGen::Iter *UniTempGen::iterator(const UniConfKey &key)
00164 {
00165     if (root)
00166     {
00167         UniConfValueTree *node = root->find(key);
00168         if (node)
00169         {
00170             ListIter *it = new ListIter(this);
00171             UniConfValueTree::Iter i(*node);
00172             for (i.rewind(); i.next(); )
00173                 it->add(i->key(), i->value());
00174             return it;
00175         }
00176     }
00177     return NULL;
00178 }
00179 
00180 
00181 void UniTempGen::commit()
00182 {
00183     UniConfGen::commit();
00184 }
00185 
00186 
00187 bool UniTempGen::refresh()
00188 {
00189     return UniConfGen::refresh();
00190 }

Generated on Thu Jan 24 16:50:55 2008 for WvStreams by  doxygen 1.5.4