Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

uniconfkey.cc

Go to the documentation of this file.
00001 /* 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 2002 Net Integration Technologies, Inc. 00004 * 00005 * A UniConf hierarchical key path abstraction. 00006 */ 00007 #include "wvstream.h" 00008 #include "uniconfkey.h" 00009 #include <climits> 00010 #include <assert.h> 00011 #include <strutils.h> 00012 00013 UniConfKey UniConfKey::EMPTY; 00014 UniConfKey UniConfKey::ANY("*"); 00015 UniConfKey UniConfKey::RECURSIVE_ANY("..."); 00016 00017 00018 UniConfKey::UniConfKey() : 00019 path("") // important to ensure we don't get nil paths everywhere 00020 // since for the moment we are not equipped to deal with them 00021 { 00022 } 00023 00024 00025 void UniConfKey::init(WvStringParm key) 00026 { 00027 assert(!key.isnull()); 00028 00029 // canonicalize the key by removing leading/trailing slashes, and 00030 // changing multiple slashes in a row to single slashes. 00031 00032 if (key[0] == '/' || *(strchr(key, 0)-1) == '/' || strstr(key, "//")) 00033 { 00034 path.setsize(strlen(key) + 1); 00035 char *optr = path.edit(); 00036 const char *iptr = key + int(strspn(key, "/")); 00037 00038 while (*iptr) 00039 { 00040 if (*iptr == '/') 00041 { 00042 // if there's more than one slash, this finds the last one: 00043 iptr += strspn(iptr, "/") - 1; 00044 00045 // if there's nothing after the slash, it's a terminating 00046 // slash; stop now. 00047 if (!iptr[1]) break; 00048 00049 // if we get here, it's exactly one intermediate slash. 00050 } 00051 00052 *optr++ = *iptr++; 00053 } 00054 00055 *optr = 0; 00056 } 00057 else // easy: already in good shape! Use WvString's optimized copying. 00058 path = key; 00059 } 00060 00061 00062 UniConfKey::UniConfKey(const UniConfKey &other) : path(other.path) 00063 { 00064 } 00065 00066 00067 UniConfKey::UniConfKey(const UniConfKey &_path, const UniConfKey &_key) 00068 { 00069 if (!_path.path) 00070 path = _key; 00071 else if (!_key.path) 00072 path = _path; 00073 else 00074 path = WvString("%s/%s", _path, _key.path); 00075 } 00076 00077 00078 void UniConfKey::append(const UniConfKey &_key) 00079 { 00080 if (!path) 00081 path = _key.path; 00082 else if (!!_key.path) 00083 path = WvString("%s/%s", path, _key.path); 00084 } 00085 00086 00087 void UniConfKey::prepend(const UniConfKey &_key) 00088 { 00089 if (!path) 00090 path = _key.path; 00091 else if (!!_key.path) 00092 path = WvString("%s/%s", _key.path, path); 00093 } 00094 00095 00096 bool UniConfKey::isempty() const 00097 { 00098 return !path; 00099 } 00100 00101 00102 bool UniConfKey::iswild() const 00103 { 00104 // FIXME: not precise 00105 return strchr(path, '*') || strstr(path, "..."); 00106 } 00107 00108 00109 int UniConfKey::numsegments() const 00110 { 00111 if (!path) 00112 return 0; 00113 00114 int n = 1; // all non-null paths have at least one segment 00115 for (const char *cptr = path; *cptr; cptr++) 00116 { 00117 if (*cptr == '/') 00118 n++; 00119 } 00120 return n; 00121 } 00122 00123 00124 UniConfKey UniConfKey::segment(int n) const 00125 { 00126 return range(n, n + 1); 00127 } 00128 00129 00130 UniConfKey UniConfKey::first(int n) const 00131 { 00132 return range(0, n); 00133 } 00134 00135 00136 UniConfKey UniConfKey::last(int n) const 00137 { 00138 return range(numsegments() - n, INT_MAX); 00139 } 00140 00141 00142 UniConfKey UniConfKey::removefirst(int n) const 00143 { 00144 return range(n, INT_MAX); 00145 } 00146 00147 00148 UniConfKey UniConfKey::removelast(int n) const 00149 { 00150 return range(0, numsegments() - n); 00151 } 00152 00153 00154 UniConfKey UniConfKey::range(int i, int j) const 00155 { 00156 if (!path) return *this; 00157 00158 const char *sptr, *eptr; 00159 int count; 00160 00161 // find the beginning 00162 for (sptr = path, count = 0; *sptr && count < i; sptr++) 00163 { 00164 if (*sptr == '/') 00165 count++; 00166 } 00167 00168 // find the end 00169 for (eptr = sptr; *eptr; eptr++) 00170 { 00171 if (*eptr == '/') 00172 count++; 00173 00174 if (count >= j) 00175 break; // don't want to increment eptr 00176 } 00177 00178 // optimization: they got the whole key! Don't copy. 00179 if (sptr == path && !*eptr) 00180 return *this; 00181 00182 // otherwise, return a new key. 00183 UniConfKey result; // avoid running the normalizing constructor 00184 int len = eptr - sptr; 00185 if (len) 00186 { 00187 result.path.setsize(len + 1); 00188 char *cptr = result.path.edit(); 00189 strncpy(cptr, sptr, len); 00190 cptr[len] = 0; 00191 } 00192 return result; 00193 } 00194 00195 00196 WvString UniConfKey::printable() const 00197 { 00198 return path; 00199 } 00200 00201 00202 UniConfKey &UniConfKey::operator= (const UniConfKey &other) 00203 { 00204 path = other.path; 00205 return *this; 00206 } 00207 00208 00209 int UniConfKey::compareto(const UniConfKey &other) const 00210 { 00211 return strcasecmp(path, other.path); 00212 } 00213 00214 00215 bool UniConfKey::matches(const UniConfKey &pattern) const 00216 { 00217 // TODO: optimize this function 00218 if (*this == pattern) 00219 return true; 00220 00221 UniConfKey head(pattern.first()); 00222 00223 // handle * wildcard 00224 if (head == UniConfKey::ANY) 00225 { 00226 if (isempty()) 00227 return false; 00228 return removefirst().matches(pattern.removefirst()); 00229 } 00230 00231 // handle ... wildcard 00232 if (head == UniConfKey::RECURSIVE_ANY) 00233 { 00234 UniConfKey tail(pattern.removefirst()); 00235 if (tail.isempty()) 00236 return true; // recursively matches anything 00237 for (int n = 0; ; ++n) 00238 { 00239 UniConfKey part(removefirst(n)); 00240 if (part.matches(tail)) 00241 return true; 00242 if (part.isempty()) 00243 break; 00244 } 00245 return false; 00246 } 00247 00248 // no other wildcard arrangements currently supported 00249 return false; 00250 } 00251 00252 00253 bool UniConfKey::suborsame(const UniConfKey &key) const 00254 { 00255 UniConfKey k = key.first(numsegments()); 00256 00257 if (k == *this) 00258 return true; 00259 return false; 00260 } 00261

Generated on Tue Oct 5 01:09:19 2004 for WvStreams by doxygen 1.3.7