WvStreams
|
00001 /* -*- Mode: C++ -*- 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 2002 Net Integration Technologies, Inc. 00004 * 00005 * UniConfKeys are paths in the UniConf hierarchy. 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