unidefgen.cc

00001 /*
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 2002 Net Integration Technologies, Inc.
00004  * 
00005  * UniDefGen is a UniConfGen for retrieving data with defaults
00006  */
00007 #include "unidefgen.h"
00008 #include "wvmoniker.h"
00009 //#include "wvstream.h"
00010 #include <ctype.h>
00011 #include <stdlib.h>
00012 
00013 #include "wvlinkerhack.h"
00014 
00015 WV_LINK(UniDefGen);
00016 
00017 
00018 // if 'obj' is non-NULL and is a UniConfGen, wrap that; otherwise wrap the
00019 // given moniker.
00020 static IUniConfGen *creator(WvStringParm s)
00021 {
00022     return new UniDefGen(wvcreate<IUniConfGen>(s));
00023 }
00024 
00025 // this name is too confusing.  We should deprecate it.
00026 static WvMoniker<IUniConfGen> reg("default", creator);
00027 
00028 // a better name for the same thing.
00029 static WvMoniker<IUniConfGen> reg2("wildcard", creator);
00030 
00031 
00032 UniConfKey UniDefGen::finddefault(const UniConfKey &key, char *p, char *q)
00033 {
00034     UniConfKey result;
00035     
00036     if (!p)
00037     {
00038         q++;
00039         if (inner() && inner()->exists(q))
00040             return q;
00041         else
00042             return UniConfKey();
00043     }
00044 
00045     // pop the first segment of p to r
00046     char *r = strchr(p, '/');
00047     if (r)
00048         *r++ = '\0';
00049 
00050     // append p to q
00051     char *s = strchr(q, '\0');
00052     *s++ = '/';
00053     *s = 0;
00054     q = strcat(q, p);
00055 
00056     // try this literal path
00057     result = finddefault(key, r, q);
00058     if (result.numsegments())
00059         return result;
00060 
00061     // replace what used to be p with a *
00062     *s++ = '*';
00063     *s = '\0';
00064     result = finddefault(key, r, q);
00065 
00066     if (r)
00067         *--r = '/';
00068     
00069     return result;
00070 }
00071 
00072 
00073 WvString UniDefGen::replacewildcard(const UniConfKey &key,
00074                             const UniConfKey &defkey, WvStringParm in)
00075 {
00076     // check if the result wants a wildcard ('*n')
00077     if (in.len() < 2 || in[0] != '*')
00078         return in;
00079 
00080     const char *s = in.cstr();
00081     int idx = atoi(s+1);
00082     if (idx == 0)
00083         return in;
00084 
00085     // search backwards for segment num of the n'th wildcard
00086     UniConfKey k(defkey);
00087     int loc = key.numsegments();
00088     for (int i = 0; i < idx; i++)
00089     {
00090         if (i != 0)
00091         {
00092             k = k.removelast();
00093             loc--;
00094         }
00095         while (!k.last().iswild())
00096         {
00097             k = k.removelast();
00098             loc--;
00099             if (k.isempty())
00100             {
00101                 // oops, ran out of segments!
00102                 return WvString();
00103             }
00104         }
00105     }
00106 
00107 
00108     // pull the literal from that segment num of the key
00109     return key.segment(loc-1);
00110 }
00111 
00112 
00113 UniConfKey UniDefGen::keymap(const UniConfKey &key)
00114 {
00115     WvString tmp_key(key), tmp("");
00116     char *p = tmp_key.edit();
00117 
00118     tmp.setsize(strlen(tmp_key) * 2);
00119     char *q = tmp.edit();
00120     *q = '\0';
00121 
00122     UniConfKey result = finddefault(key, p, q);
00123     if (!result.numsegments())
00124         result = key;
00125     // fprintf(stderr, "mapping '%s' -> '%s'\n", key.cstr(), result.cstr());
00126     return result;
00127 }
00128 
00129 
00130 WvString UniDefGen::get(const UniConfKey &key)
00131 {
00132     UniConfKey defkey = keymap(key);
00133 
00134     return replacewildcard(key, defkey,
00135                            inner() ? inner()->get(defkey) : WvString());
00136 }
00137 
00138 
00139 void UniDefGen::set(const UniConfKey &key, WvStringParm value)
00140 {
00141     // no keymap() on set()
00142     if (inner())
00143         inner()->set(key, value);
00144 }

Generated on Sun Sep 24 20:10:48 2006 for WvStreams by  doxygen 1.4.7