WvStreams
unifastregetgen.cc
00001 /* -*- Mode: C++ -*-
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 2002-2005 Net Integration Technologies, Inc.
00004  * 
00005  * A lightweight but slightly dangerous version of UniCacheGen.
00006  */
00007 #include <wvassert.h>
00008 
00009 #include "unifastregetgen.h"
00010 #include "uniconftree.h"
00011 #include "wvmoniker.h"
00012 
00013 // if 'obj' is non-NULL and is a UniConfGen, wrap that; otherwise wrap the
00014 // given moniker.
00015 static IUniConfGen *creator(WvStringParm s, IObject *_obj)
00016 {
00017     return new UniFastRegetGen(wvcreate<IUniConfGen>(s, _obj));
00018 }
00019 
00020 static WvMoniker<IUniConfGen> reg("fast-reget", creator);
00021 
00022 
00023 UniFastRegetGen::UniFastRegetGen(IUniConfGen *_inner) :
00024     UniFilterGen(_inner),
00025     tree(NULL)
00026 {
00027     tree = new UniConfValueTree(NULL, "/", UniFilterGen::get("/"));
00028 }
00029 
00030 
00031 UniFastRegetGen::~UniFastRegetGen()
00032 {
00033     if (tree)
00034     {
00035         delete tree;
00036         tree = NULL;
00037     }
00038 }
00039 
00040 
00041 void UniFastRegetGen::gencallback(const UniConfKey &key, WvStringParm value)
00042 {
00043     if (tree == NULL)
00044         return; // initialising
00045 
00046     UniConfValueTree *t = tree->find(key);
00047     if (t) // never previously retrieved; don't cache it
00048         t->setvalue(value);
00049     UniFilterGen::gencallback(key, value);
00050 }
00051 
00052 
00053 WvString UniFastRegetGen::get(const UniConfKey &key)
00054 {
00055     if (!tree)
00056     {
00057         wvassert(tree, "key: '%s'", key);
00058         abort();
00059     }
00060 
00061     // Keys with trailing slashes can't have values set on them
00062     if (key.hastrailingslash())
00063         return WvString::null;
00064 
00065     UniConfValueTree *t = tree->find(key);
00066     if (!t)
00067     {
00068         UniConfKey parentkey(key.removelast());
00069         get(parentkey); // guaranteed to create parent node
00070         t = tree->find(parentkey);
00071         assert(t);
00072         
00073         WvString value;
00074         if (!t->value().isnull()) // if parent is null, child guaranteed null
00075             value = UniFilterGen::get(key);
00076         new UniConfValueTree(t, key.last(), value);
00077         return value;
00078     }
00079     else
00080         return t->value();
00081 }
00082 
00083 
00084 bool UniFastRegetGen::exists(const UniConfKey &key)
00085 {
00086     // even if inner generator has a more efficient version of exists(),
00087     // do it this way so we can cache the result.
00088     return !get(key).isnull();
00089 }
00090 
00091 
00092 bool UniFastRegetGen::haschildren(const UniConfKey &key)
00093 {
00094     if (!tree)
00095     {
00096         wvassert(tree, "key: '%s'", key);
00097         abort();
00098     }
00099 
00100     // if we already know the node is null, we can short circuit this one
00101     UniConfValueTree *t = tree->find(key);
00102     if (t && t->value().isnull())
00103         return false; // definitely no children
00104     return UniFilterGen::haschildren(key);
00105 }