00001
00002
00003
00004
00005
00006
00007
00008 #ifndef __WVBDBHASH_H
00009 #define __WVBDBHASH_H
00010
00011 #include "wvautoconf.h"
00012
00013 #ifndef WITH_BDB
00014 # error "Sorry, no Berkeley DB support in WvStreams!"
00015 #endif
00016
00017 #include "wvhashtable.h"
00018 #include "wvserialize.h"
00019 #include "wverror.h"
00020
00021
00022 class WvBdbHashBase : public WvError
00023 {
00024 WvString dbfile;
00025 bool persist_dbfile;
00026
00027 public:
00028
00029
00030 struct datum
00031 {
00032 void *dptr;
00033 size_t dsize;
00034 };
00035
00036 WvBdbHashBase(WvStringParm _dbfile, bool persist_dbfile = true);
00037 ~WvBdbHashBase();
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 void opendb(WvStringParm _dbfile, bool persist_dbfile = true);
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 void closedb();
00064
00065 void add(const datum &key, const datum &data, bool replace);
00066 void remove(const datum &key);
00067 datum find(const datum &key);
00068 bool exists(const datum &key);
00069
00070
00071
00072
00073
00074 void zap();
00075
00076 class IterBase
00077 {
00078 public:
00079 IterBase(WvBdbHashBase &_bdbhash);
00080 ~IterBase();
00081
00082 void rewind();
00083 void rewind(const datum &firstkey, datum &key, datum &data);
00084 void next(datum &key, datum &data);
00085 void xunlink(const datum &key);
00086 void update(const datum &key, const datum &data);
00087
00088 protected:
00089 WvBdbHashBase &bdbhash;
00090 datum rewindto;
00091 };
00092
00093 private:
00094 friend class IterBase;
00095 struct __db *dbf;
00096 };
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 template <class K, class D>
00115 class WvBdbHash : public WvBdbHashBase
00116 {
00117 public:
00118
00119
00120
00121 template <typename T>
00122 class datumize : public datum
00123 {
00124 datumize(datumize &);
00125
00126 void init(const T &t)
00127 {
00128 wv_serialize(buf, t);
00129 dsize = buf.used();
00130 dptr = (char *)buf.peek(0, buf.used());
00131 }
00132
00133 public:
00134 WvDynBuf buf;
00135
00136 datumize(const T &t)
00137 { init(t); }
00138
00139 datumize(const T *t)
00140 {
00141 if (t) { init(*t); }
00142 else { dsize = 0; dptr = 0; }
00143 }
00144 };
00145
00146 template <typename T>
00147 static T undatumize(datum &data)
00148 {
00149 WvConstInPlaceBuf buf(data.dptr, data.dsize);
00150 return wv_deserialize<T>(buf);
00151 }
00152
00153 protected:
00154 D *saveddata;
00155
00156 public:
00157 WvBdbHash(WvStringParm dbfile = WvString::null, bool persist = true) :
00158 WvBdbHashBase(dbfile, persist) { saveddata = NULL; }
00159
00160 void add(const K &key, const D &data, bool replace = false)
00161 {
00162 WvBdbHashBase::add(datumize<K>(key),
00163 datumize<D>(data), replace);
00164 }
00165
00166 void remove(const K &key)
00167 { WvBdbHashBase::remove(datumize<K>(key)); }
00168
00169 D &find(const K &key)
00170 {
00171 if (saveddata)
00172 delete saveddata;
00173 datum s = WvBdbHashBase::find(datumize<K>(key));
00174 saveddata = undatumize<D *>(s);
00175 return *saveddata;
00176 }
00177
00178 D &operator[] (const K &key)
00179 { return find(key); }
00180
00181 bool exists(const K &key)
00182 { return WvBdbHashBase::exists(datumize<K>(key)); }
00183
00184 int count()
00185 {
00186 int res = 0;
00187 Iter i(*this);
00188 for (i.rewind(); i.next(); )
00189 res++;
00190 return res;
00191 }
00192
00193 bool isempty()
00194 {
00195 Iter i(*this);
00196 i.rewind();
00197 return !i.next();
00198 }
00199
00200 D &first()
00201 {
00202 Iter i(*this);
00203 i.rewind(); i.next();
00204 return i();
00205 }
00206
00207 class Iter : public WvBdbHashBase::IterBase
00208 {
00209 K *k;
00210 D *d;
00211
00212 public:
00213 Iter(WvBdbHash &_bdbhash) : IterBase(_bdbhash)
00214 { k = NULL; d = NULL; }
00215 ~Iter()
00216 {
00217 delete k;
00218 delete d;
00219 }
00220
00221 void rewind()
00222 {
00223 IterBase::rewind();
00224 delete k; k = NULL;
00225 delete d; d = NULL;
00226 }
00227
00228 void rewind(const K &firstkey)
00229 {
00230 WvBdbHash::datumize<K> key(k);
00231 WvBdbHash::datumize<D> data(d);
00232
00233 IterBase::rewind(WvBdbHash::datumize<K>(firstkey), key, data);
00234 delete k;
00235 delete d;
00236 if (data.dptr)
00237 {
00238 k = undatumize<K *>(key);
00239 d = undatumize<D *>(data);
00240 }
00241 else
00242 {
00243 k = NULL;
00244 d = NULL;
00245 }
00246 }
00247
00248 bool next()
00249 {
00250 WvBdbHash::datumize<K> key(k);
00251 datum data = { 0, 0 };
00252 IterBase::next(key, data);
00253 delete k;
00254 delete d;
00255 if (bdbhash.isok() && data.dptr)
00256 {
00257 k = undatumize<K *>(key);
00258 d = undatumize<D *>(data);
00259 return true;
00260 }
00261 k = NULL;
00262 d = NULL;
00263 return false;
00264 }
00265
00266 void unlink()
00267 { xunlink(); next(); }
00268
00269 void xunlink()
00270 { IterBase::xunlink(WvBdbHash::datumize<K>(k)); }
00271
00272 void save()
00273 { IterBase::update(WvBdbHash::datumize<K>(k),
00274 WvBdbHash::datumize<D>(d)); }
00275
00276 bool cur()
00277 { return d; }
00278
00279 K &key() const
00280 { assert(k); return *k; }
00281
00282 D *ptr() const
00283 { return d; }
00284
00285 WvIterStuff(D);
00286
00287 };
00288
00289 };
00290
00291 #endif // __WVBDBHASH_H