00001
00002
00003
00004
00005
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("")
00020
00021 {
00022 }
00023
00024
00025 void UniConfKey::init(WvStringParm key)
00026 {
00027 assert(!key.isnull());
00028
00029
00030
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
00043 iptr += strspn(iptr, "/") - 1;
00044
00045
00046
00047 if (!iptr[1]) break;
00048
00049
00050 }
00051
00052 *optr++ = *iptr++;
00053 }
00054
00055 *optr = 0;
00056 }
00057 else
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
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;
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
00162 for (sptr = path, count = 0; *sptr && count < i; sptr++)
00163 {
00164 if (*sptr == '/')
00165 count++;
00166 }
00167
00168
00169 for (eptr = sptr; *eptr; eptr++)
00170 {
00171 if (*eptr == '/')
00172 count++;
00173
00174 if (count >= j)
00175 break;
00176 }
00177
00178
00179 if (sptr == path && !*eptr)
00180 return *this;
00181
00182
00183 UniConfKey result;
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
00218 if (*this == pattern)
00219 return true;
00220
00221 UniConfKey head(pattern.first());
00222
00223
00224 if (head == UniConfKey::ANY)
00225 {
00226 if (isempty())
00227 return false;
00228 return removefirst().matches(pattern.removefirst());
00229 }
00230
00231
00232 if (head == UniConfKey::RECURSIVE_ANY)
00233 {
00234 UniConfKey tail(pattern.removefirst());
00235 if (tail.isempty())
00236 return true;
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
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