00001
00002
00003
00004
00005
00006
00007 #ifndef __UNICONFKEY_H
00008 #define __UNICONFKEY_H
00009
00010 #include "wvstring.h"
00011 #include "wvlinklist.h"
00012
00013
00014
00015
00016 #undef ANY
00017
00018
00042 class UniConfKey
00043 {
00044 class Segment : public WvString
00045 {
00046 public:
00047 Segment() :
00048 WvString(WvString::empty)
00049 {
00050 }
00051 Segment(WvStringParm str) :
00052 WvString((!str)? WvString::empty: str)
00053 {
00054 }
00055 Segment(const Segment &segment) :
00056 WvString(segment)
00057 {
00058 }
00059
00060 bool iswild() const
00061 {
00062 return *this == "*" || *this == "...";
00063 }
00064 };
00065
00066 class SegmentVector
00067 {
00068 int _size, _used;
00069 Segment *vec;
00070 public:
00071 SegmentVector(int size) :
00072 _size(size),
00073 _used(0),
00074 vec(new Segment[_size])
00075 {
00076 }
00077 ~SegmentVector()
00078 {
00079 deletev vec;
00080 }
00081
00082 void resize(int size, int shift = 0)
00083 {
00084 if (size <= _size)
00085 {
00086 if (shift > 0)
00087 {
00088 for (int i=_used-1; i>=0; --i)
00089 vec[i+shift] = vec[i];
00090 _used += shift;
00091 }
00092 return;
00093 }
00094 Segment *old_vec = vec;
00095 vec = new Segment[size];
00096 if (old_vec)
00097 {
00098 int limit = size-shift;
00099 if (limit > _size)
00100 limit = _size;
00101 if (limit > _used)
00102 limit = _used;
00103 for (int i=0; i<limit; ++i)
00104 vec[i+shift] = old_vec[i];
00105 deletev old_vec;
00106 }
00107 _size = size;
00108 _used += shift;
00109 }
00110 void zap()
00111 {
00112 _used = 0;
00113 }
00114 int size() const
00115 {
00116 return _size;
00117 }
00118 int used() const
00119 {
00120 return _used;
00121 }
00122
00123 void append(const Segment &segment)
00124 {
00125 vec[_used++] = segment;
00126 }
00127 void append(WvStringParm string)
00128 {
00129 append(Segment(string));
00130 }
00131 void replace(int index, const Segment &segment)
00132 {
00133 vec[index] = segment;
00134 if (index >= _used)
00135 _used = index + 1;
00136 }
00137 void replace(int index, WvStringParm string)
00138 {
00139 replace(index, Segment(string));
00140 }
00141 const Segment &operator [](int index) const
00142 {
00143 return vec[index];
00144 }
00145 };
00146
00147 struct Store
00148 {
00149 SegmentVector segments;
00150 int ref_count;
00151
00152 Store(int size, int _ref_count, WvStringParm key = WvString::null);
00153 };
00154
00155 Store *store;
00156 int left, right;
00157
00158 static Store EMPTY_store;
00159 static Store ANY_store;
00160 static Store RECURSIVE_ANY_store;
00162 UniConfKey(Store *_store, int _left, int _right) :
00163 store(_store),
00164 left(_left),
00165 right(_right)
00166 {
00167 store->ref_count++;
00168 }
00169
00170 void unique();
00171 void normalize();
00172 UniConfKey &collapse();
00173
00174 public:
00175 static UniConfKey EMPTY;
00176 static UniConfKey ANY;
00177 static UniConfKey RECURSIVE_ANY;
00180 UniConfKey() :
00181 store(&EMPTY_store),
00182 left(0),
00183 right(0)
00184 {
00185 store->ref_count++;
00186 }
00187
00196 UniConfKey(WvStringParm key) :
00197 store(new Store(4, 1, key)),
00198 left(0),
00199 right(store->segments.used())
00200 {
00201 }
00202
00212 UniConfKey(const char *key) :
00213 store(new Store(4, 1, WvFastString(key))),
00214 left(0),
00215 right(store->segments.used())
00216 {
00217 }
00218
00220 UniConfKey(int key) :
00221 store(new Store(1, 1, WvFastString(key))),
00222 left(0),
00223 right(store->segments.used())
00224 {
00225 }
00226
00231 UniConfKey(const UniConfKey &other) :
00232 store(other.store),
00233 left(other.left),
00234 right(other.right)
00235 {
00236 store->ref_count++;
00237 }
00238
00244 UniConfKey(const UniConfKey &path, const UniConfKey &key);
00245
00246 ~UniConfKey()
00247 {
00248 if (--store->ref_count == 0)
00249 delete store;
00250 }
00251
00256 void append(const UniConfKey &other);
00257
00262 void prepend(const UniConfKey &other);
00263
00268 bool isempty() const
00269 {
00270 return right == left;
00271 }
00272
00274 bool iswild() const;
00275
00277 bool hastrailingslash() const
00278 {
00279 return right > left && !store->segments[right-1];
00280 }
00281
00291 int numsegments() const
00292 {
00293 return right - left;
00294 }
00295
00301 UniConfKey segment(int n) const
00302 {
00303 return range(n, n + 1);
00304 }
00305
00311 UniConfKey pop(int n = 1);
00312
00318 UniConfKey first(int n = 1) const
00319 {
00320 return range(0, n);
00321 }
00322
00328 UniConfKey last(int n = 1) const
00329 {
00330 return range(numsegments() - n, __INT_MAX__);
00331 }
00332
00339 UniConfKey removefirst(int n = 1) const
00340 {
00341 return range(n, __INT_MAX__);
00342 }
00343
00350 UniConfKey removelast(int n = 1) const
00351 {
00352 return range(0, numsegments() - n);
00353 }
00354
00361 UniConfKey range(int i, int j) const;
00362
00374 WvString printable() const;
00375 operator WvString() const
00376 { return printable(); }
00377
00381 const char *cstr() const
00382 { return printable(); }
00383
00388 UniConfKey &operator= (const UniConfKey &other)
00389 {
00390 if (--store->ref_count == 0)
00391 delete store;
00392 store = other.store;
00393 left = other.left;
00394 right = other.right;
00395 ++store->ref_count;
00396 return *this;
00397 }
00398
00406 int compareto(const UniConfKey &other) const;
00407
00418 bool matches(const UniConfKey &pattern) const;
00419
00420
00424 bool suborsame(const UniConfKey &key) const;
00425 bool suborsame(const UniConfKey &key, UniConfKey &subkey) const;
00426
00432 UniConfKey subkey(const UniConfKey &key) const;
00433
00439 bool operator== (const UniConfKey &other) const
00440 { return compareto(other) == 0; }
00441
00447 bool operator!= (const UniConfKey &other) const
00448 { return compareto(other) != 0; }
00449
00455 bool operator< (const UniConfKey &other) const
00456 { return compareto(other) < 0; }
00457
00458 class Iter;
00459
00460 friend unsigned WvHash(const UniConfKey &k);
00461 };
00462
00463
00464 DeclareWvList(UniConfKey);
00465
00467 class UniConfKey::Iter
00468 {
00469 const UniConfKey &key;
00470 int seg, max;
00471 UniConfKey curseg;
00472
00473 public:
00474 Iter(const UniConfKey &_key) : key(_key)
00475 { }
00476
00477 void rewind()
00478 { seg = -1; max = key.numsegments(); }
00479
00480 bool cur()
00481 { return seg >= 0 && seg < max; }
00482
00483 bool next()
00484 { seg++; curseg = key.segment(seg); return cur(); }
00485
00486 const UniConfKey *ptr() const
00487 { return &curseg; }
00488
00489 WvIterStuff(const UniConfKey);
00490 };
00491
00492 #endif // __UNICONFKEY_H