WvStreams
uniconfkey.h
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