00001
00002
00003
00004
00005
00006
00007 #ifndef __WVGDBMHASH_H
00008 #define __WVGDBMHASH_H
00009
00010 #include "wvautoconf.h"
00011
00012 #ifndef HAVE_GDBM_H
00013 # error "Sorry, no gdbm support in wvstreams!"
00014 #endif
00015
00016 #include "wvhashtable.h"
00017 #include "wvserialize.h"
00018
00019 #include <gdbm.h>
00020
00021
00022
00023 class WvGdbmHashBase
00024 {
00025 public:
00026 WvGdbmHashBase(WvStringParm dbfile);
00027 ~WvGdbmHashBase();
00028
00029 int add(const datum &key, const datum &data, bool replace);
00030 int remove(const datum &key);
00031 datum find(const datum &key);
00032 bool exists(const datum &key);
00033 void zap();
00034
00035 class IterBase
00036 {
00037 public:
00038 IterBase(WvGdbmHashBase &_gdbmhash);
00039 ~IterBase();
00040 void rewind();
00041 void next();
00042
00043 protected:
00044 WvGdbmHashBase &gdbmhash;
00045 datum curkey, nextkey;
00046 datum curdata;
00047 };
00048 private:
00049 friend class IterBase;
00050 GDBM_FILE dbf;
00051 };
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 template <class K, class D>
00064 class WvGdbmHash : public WvGdbmHashBase
00065 {
00066 public:
00067
00068
00069
00070 template <typename T>
00071 class datumize : public datum
00072 {
00073 datumize(datumize &);
00074 public:
00075 WvDynBuf buf;
00076
00077 datumize(const T &t)
00078 {
00079 wv_serialize(buf, t);
00080 dsize = buf.used();
00081 dptr = (char *)buf.peek(0, buf.used());
00082 }
00083 };
00084
00085 template <typename T>
00086 static T undatumize(datum &data)
00087 {
00088 WvConstInPlaceBuf buf(data.dptr, data.dsize);
00089 return wv_deserialize<T>(buf);
00090 }
00091
00092 protected:
00093 D *saveddata;
00094
00095 public:
00096 WvGdbmHash(WvStringParm dbfile) : WvGdbmHashBase(dbfile)
00097 { saveddata = NULL; }
00098
00099 void add(const K &key, const D &data, bool replace = false)
00100 {
00101 int r = WvGdbmHashBase::add(datumize<K>(key),
00102 datumize<D>(data), replace);
00103 assert(!r && "Set the replace flag to replace existing elements.");
00104 }
00105
00106 void remove(const K &key)
00107 { WvGdbmHashBase::remove(datumize<K>(key)); }
00108
00109 D &find(const K &key)
00110 {
00111 if (saveddata)
00112 delete saveddata;
00113 datum s = WvGdbmHashBase::find(datumize<K>(key));
00114 saveddata = undatumize<D *>(s);
00115 free(s.dptr);
00116 return *saveddata;
00117 }
00118
00119 D &operator[] (const K &key)
00120 { return find(key); }
00121
00122 bool exists(const K &key)
00123 { return WvGdbmHashBase::exists(datumize<K>(key)); }
00124
00125 class Iter : public WvGdbmHashBase::IterBase
00126 {
00127 K *k;
00128 D *d;
00129 public:
00130 Iter(WvGdbmHash &_gdbmhash) : IterBase(_gdbmhash)
00131 { k = NULL; d = NULL; }
00132 ~Iter()
00133 {
00134 if (k) delete k;
00135 if (d) delete d;
00136 }
00137
00138 bool next()
00139 {
00140 if (!nextkey.dptr)
00141 return false;
00142 if (k) delete k;
00143 if (d) delete d;
00144 IterBase::next();
00145 if (curdata.dptr)
00146 {
00147 k = undatumize<K *>(curkey);
00148 d = undatumize<D *>(curdata);
00149 return true;
00150 }
00151 else
00152 {
00153 k = NULL;
00154 d = NULL;
00155 return false;
00156 }
00157 }
00158
00159 bool cur()
00160 { return curdata.dptr; }
00161
00162 K &key() const
00163 { return *k; }
00164
00165 D *ptr() const
00166 { return d; }
00167 WvIterStuff(D);
00168 };
00169 };
00170
00171 #endif // __WVGDBMHASH_H