00001
00002
00003
00004
00005
00006
00007 #ifndef __UNICONFKEY_H
00008 #define __UNICONFKEY_H
00009
00010 #include "wvstring.h"
00011 #include "wvlinklist.h"
00012 #include <limits.h>
00013
00014
00038 class UniConfKey
00039 {
00040 class Segment : public WvString
00041 {
00042 public:
00043 Segment() :
00044 WvString(WvString::empty)
00045 {
00046 }
00047 Segment(WvStringParm str) :
00048 WvString((!str)? WvString::empty: str)
00049 {
00050 }
00051 Segment(const Segment &segment) :
00052 WvString(segment)
00053 {
00054 }
00055
00056 bool iswild() const
00057 {
00058 return *this == "*" || *this == "...";
00059 }
00060 };
00061
00062 class SegmentVector
00063 {
00064 int _size, _used;
00065 Segment *vec;
00066 public:
00067 SegmentVector(int size) :
00068 _size(size),
00069 _used(0),
00070 vec(new Segment[_size])
00071 {
00072 }
00073 ~SegmentVector()
00074 {
00075 deletev vec;
00076 }
00077
00078 void resize(int size, int shift = 0)
00079 {
00080 if (size <= _size)
00081 {
00082 if (shift > 0)
00083 {
00084 for (int i=_used-1; i>=0; --i)
00085 vec[i+shift] = vec[i];
00086 _used += shift;
00087 }
00088 return;
00089 }
00090 Segment *old_vec = vec;
00091 vec = new Segment[size];
00092 if (old_vec)
00093 {
00094 int limit = size-shift;
00095 if (limit > _size)
00096 limit = _size;
00097 if (limit > _used)
00098 limit = _used;
00099 for (int i=0; i<limit; ++i)
00100 vec[i+shift] = old_vec[i];
00101 deletev old_vec;
00102 }
00103 _size = size;
00104 _used += shift;
00105 }
00106 void zap()
00107 {
00108 _used = 0;
00109 }
00110 int size() const
00111 {
00112 return _size;
00113 }
00114 int used() const
00115 {
00116 return _used;
00117 }
00118
00119 void append(const Segment &segment)
00120 {
00121 vec[_used++] = segment;
00122 }
00123 void append(WvStringParm string)
00124 {
00125 append(Segment(string));
00126 }
00127 void replace(int index, const Segment &segment)
00128 {
00129 vec[index] = segment;
00130 if (index >= _used)
00131 _used = index + 1;
00132 }
00133 void replace(int index, WvStringParm string)
00134 {
00135 replace(index, Segment(string));
00136 }
00137 const Segment &operator [](int index) const
00138 {
00139 return vec[index];
00140 }
00141 };
00142
00143 struct Store
00144 {
00145 SegmentVector segments;
00146 int ref_count;
00147
00148 Store(int size, int _ref_count, WvStringParm key = WvString::null);
00149 };
00150
00151 Store *store;
00152 int left, right;
00153
00154 static Store EMPTY_store;
00155 static Store ANY_store;
00156 static Store RECURSIVE_ANY_store;
00158 UniConfKey(Store *_store, int _left, int _right) :
00159 store(_store),
00160 left(_left),
00161 right(_right)
00162 {
00163 store->ref_count++;
00164 }
00165
00166 void unique();
00167 void normalize();
00168 UniConfKey &collapse();
00169
00170 public:
00171 static UniConfKey EMPTY;
00172 static UniConfKey ANY;
00173 static UniConfKey RECURSIVE_ANY;
00176 UniConfKey() :
00177 store(&EMPTY_store),
00178 left(0),
00179 right(0)
00180 {
00181 store->ref_count++;
00182 }
00183
00192 UniConfKey(WvStringParm key) :
00193 store(new Store(4, 1, key)),
00194 left(0),
00195 right(store->segments.used())
00196 {
00197 }
00198
00208 UniConfKey(const char *key) :
00209 store(new Store(4, 1, WvFastString(key))),
00210 left(0),
00211 right(store->segments.used())
00212 {
00213 }
00214
00216 UniConfKey(int key) :
00217 store(new Store(1, 1, WvFastString(key))),
00218 left(0),
00219 right(store->segments.used())
00220 {
00221 }
00222
00227 UniConfKey(const UniConfKey &other) :
00228 store(other.store),
00229 left(other.left),
00230 right(other.right)
00231 {
00232 store->ref_count++;
00233 }
00234
00240 UniConfKey(const UniConfKey &path, const UniConfKey &key);
00241
00242 ~UniConfKey()
00243 {
00244 if (--store->ref_count == 0)
00245 delete store;
00246 }
00247
00252 void append(const UniConfKey &other);
00253
00258 void prepend(const UniConfKey &other);
00259
00264 bool isempty() const
00265 {
00266 return right == left;
00267 }
00268
00270 bool iswild() const;
00271
00273 bool hastrailingslash() const
00274 {
00275 return right > left && !store->segments[right-1];
00276 }
00277
00287 int numsegments() const
00288 {
00289 return right - left;
00290 }
00291
00297 UniConfKey segment(int n) const
00298 {
00299 return range(n, n + 1);
00300 }
00301
00307 UniConfKey pop(int n = 1);
00308
00314 UniConfKey first(int n = 1) const
00315 {
00316 return range(0, n);
00317 }
00318
00324 UniConfKey last(int n = 1) const
00325 {
00326 return range(numsegments() - n, INT_MAX);
00327 }
00328
00335 UniConfKey removefirst(int n = 1) const
00336 {
00337 return range(n, INT_MAX);
00338 }
00339
00346 UniConfKey removelast(int n = 1) const
00347 {
00348 return range(0, numsegments() - n);
00349 }
00350
00357 UniConfKey range(int i, int j) const;
00358
00370 WvString printable() const;
00371 operator WvString() const
00372 { return printable(); }
00373
00377 const char *cstr() const
00378 { return printable(); }
00379
00384 UniConfKey &operator= (const UniConfKey &other)
00385 {
00386 if (--store->ref_count == 0)
00387 delete store;
00388 store = other.store;
00389 left = other.left;
00390 right = other.right;
00391 ++store->ref_count;
00392 return *this;
00393 }
00394
00402 int compareto(const UniConfKey &other) const;
00403
00414 bool matches(const UniConfKey &pattern) const;
00415
00416
00420 bool suborsame(const UniConfKey &key) const;
00421 bool suborsame(const UniConfKey &key, UniConfKey &subkey) const;
00422
00428 UniConfKey subkey(const UniConfKey &key) const;
00429
00435 bool operator== (const UniConfKey &other) const
00436 { return compareto(other) == 0; }
00437
00443 bool operator!= (const UniConfKey &other) const
00444 { return compareto(other) != 0; }
00445
00451 bool operator< (const UniConfKey &other) const
00452 { return compareto(other) < 0; }
00453
00454 class Iter;
00455
00456 friend unsigned WvHash(const UniConfKey &k);
00457 };
00458
00459
00460 DeclareWvList(UniConfKey);
00461
00463 class UniConfKey::Iter
00464 {
00465 const UniConfKey &key;
00466 int seg, max;
00467 UniConfKey curseg;
00468
00469 public:
00470 Iter(const UniConfKey &_key) : key(_key)
00471 { }
00472
00473 void rewind()
00474 { seg = -1; max = key.numsegments(); }
00475
00476 bool cur()
00477 { return seg >= 0 && seg < max; }
00478
00479 bool next()
00480 { seg++; curseg = key.segment(seg); return cur(); }
00481
00482 const UniConfKey *ptr() const
00483 { return &curseg; }
00484
00485 WvIterStuff(const UniConfKey);
00486 };
00487
00488 #endif // __UNICONFKEY_H