WvStreams
|
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, IObject *_obj) 00021 { 00022 return new UniDefGen(wvcreate<IUniConfGen>(s, _obj)); 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 bool UniDefGen::keymap(const UniConfKey &unmapped_key, UniConfKey &mapped_key) 00114 { 00115 WvString tmp_key(unmapped_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 mapped_key = finddefault(unmapped_key, p, q); 00123 if (!mapped_key.numsegments()) 00124 mapped_key = unmapped_key; 00125 // fprintf(stderr, "mapping '%s' -> '%s'\n", key.cstr(), result.cstr()); 00126 00127 return true; 00128 } 00129 00130 00131 WvString UniDefGen::get(const UniConfKey &key) 00132 { 00133 UniConfKey mapped_key; 00134 if (keymap(key, mapped_key)) 00135 return replacewildcard(key, mapped_key, 00136 inner() ? inner()->get(mapped_key) : WvString()); 00137 else 00138 return WvString::null; 00139 } 00140 00141 00142 void UniDefGen::set(const UniConfKey &key, WvStringParm value) 00143 { 00144 // no keymap() on set() 00145 if (inner()) 00146 inner()->set(key, value); 00147 }