hash_vec.hpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) Sergey P. Derevyago, 2008-2009.
00003  *
00004  * Permission to copy, use, modify, sell and distribute this software is granted
00005  * provided this copyright notice appears in all copies.
00006  * This software is provided "as is" without express or implied warranty, and
00007  * with no claim as to its suitability for any purpose.
00008  *
00009  */
00010 
00017 #ifndef __DERS__HASH_VEC_HPP__
00018 #define __DERS__HASH_VEC_HPP__
00019 
00020 #include <ders/config.hpp>
00021 #include <algorithm>
00022 #include <ders/text.hpp>
00023 
00024 namespace ders {  // ::ders
00025 
00026 using namespace std;
00027 
00028 namespace detail {  // ::ders::detail
00029 
00030 template<class Key, class Val>
00031 struct hash_vec_nodes {
00032        struct node {
00033               Key key;
00034               Val val;
00035               int next;
00036 
00037               node(const Key& k, const Val& v) : key(k), val(v), next(-1) {}
00038        };
00039 
00040        int resd;
00041        int used;
00042        node* nodes;
00043 
00044        hash_vec_nodes(int rsrv);
00045        ~hash_vec_nodes();
00046 
00047        void create_at(int pos, const Key& k, const Val& v);
00048        void destroy_at(int pos);
00049        void move_to(int to, int from);
00050 };
00051 
00052 template<class Key, class Val>
00053 hash_vec_nodes<Key, Val>::hash_vec_nodes(int rsrv) :
00054   resd(rsrv), used(0), nodes(0)
00055 {
00056  assert(resd>0);
00057  nodes=static_cast<node*>(operator new(sizeof(node)*resd));
00058 }
00059 
00060 template<class Key, class Val>
00061 hash_vec_nodes<Key, Val>::~hash_vec_nodes()
00062 {
00063  for (int i=0; i<used; i++) destroy_at(i);
00064  operator delete(nodes);
00065 }
00066 
00067 template<class Key, class Val>
00068 inline void hash_vec_nodes<Key, Val>::create_at(int pos, const Key& k, const
00069   Val& v)
00070 {
00071  new(nodes+pos) node(k, v);
00072 }
00073 
00074 template<class Key, class Val>
00075 inline void hash_vec_nodes<Key, Val>::destroy_at(int pos)
00076 {
00077  nodes[pos].~node();
00078 }
00079 
00080 template<class Key, class Val>
00081 inline void hash_vec_nodes<Key, Val>::move_to(int to, int from)
00082 {
00083  memcpy(nodes+to, nodes+from, sizeof(*nodes));
00084 }
00085 
00086 size_t calc_hash(const void* ptr, int n);
00087 
00088 }  // namespace ::ders::detail
00089 
00093 template<class Key>
00094 struct key_hash {
00095 };
00096 
00097 #define TRIVIAL_KEY_HASH(type)                       \
00098 template<>                                           \
00099 struct key_hash<type> {                              \
00100        size_t operator()(type k) const { return k; } \
00101 }
00102 
00103 TRIVIAL_KEY_HASH(char);
00104 TRIVIAL_KEY_HASH(unsigned char);
00105 TRIVIAL_KEY_HASH(signed char);
00106 TRIVIAL_KEY_HASH(short);
00107 TRIVIAL_KEY_HASH(unsigned short);
00108 TRIVIAL_KEY_HASH(int);
00109 TRIVIAL_KEY_HASH(unsigned int);
00110 TRIVIAL_KEY_HASH(long);
00111 TRIVIAL_KEY_HASH(unsigned long);
00112 
00113 #undef TRIVIAL_KEY_HASH
00114 
00115 template<class T>
00116 struct key_hash<T*> {
00117        size_t operator()(T* k) const { return reinterpret_cast<size_t>(k); }
00118 };
00119 
00120 template<>
00121 struct key_hash<sh_text> {
00122        size_t operator()(const sh_text& t) const
00123        { return detail::calc_hash(t->begin(), t->size()); }
00124 };
00125 
00129 template<class Key>
00130 struct key_eql {
00131        bool operator()(const Key& key1, const Key& key2) const
00132        { return (key1==key2) ? true : false; }
00133 };
00134 
00138 template<class Key, class Val, class KeyHash=key_hash<Key>, class KeyEql=
00139   key_eql<Key> >
00140 class hash_vec {
00141       typedef detail::hash_vec_nodes<Key, Val> nodes;
00142 
00143       KeyHash khash;
00144       KeyEql keql;
00145       int* hndx;
00146       nodes nds;
00147 
00148       int* root(const Key& k) const  { return hndx+khash(k)%nds.resd; }
00149       int* find(int* root, const Key& k) const;
00150 
00151       hash_vec(const hash_vec&);
00152       hash_vec& operator=(const hash_vec&);
00153 
00154  public:
00155       hash_vec(int rsrv, const KeyHash& kh=KeyHash(), const KeyEql& ke=
00156         KeyEql());
00157       ~hash_vec() { operator delete(hndx); }
00158 
00159       int size() const { return nds.used; }
00160       int capacity() const { return nds.resd; }
00161       void reserve(int n);
00162 
00163       const Key& key(int pos) const;
00164       Val& val(int pos);
00165       const Val& val(int pos) const;
00166 
00167       int insert(const Key& k, const Val& v);
00168       int find(const Key& k) const { return *find(root(k), k); }
00169       void erase(int pos);
00170 };
00171 
00172 template<class Key, class Val, class KeyHash, class KeyEql>
00173 int* hash_vec<Key, Val, KeyHash, KeyEql>::find(int* root, const Key& k) const
00174 {
00175  for (int* ptr=root; ; ptr=&nds.nodes[*ptr].next)
00176      if (*ptr==-1 || keql(nds.nodes[*ptr].key, k)) return ptr;
00177 }
00178 
00179 template<class Key, class Val, class KeyHash, class KeyEql>
00180 hash_vec<Key, Val, KeyHash, KeyEql>::hash_vec(int rsrv, const KeyHash& kh, const
00181   KeyEql& ke) : khash(kh), keql(ke), hndx(0), nds(rsrv)
00182 {
00183  hndx=static_cast<int*>(operator new(sizeof(int)*nds.resd));
00184  fill_n(hndx, nds.resd, -1);
00185 }
00186 
00187 template<class Key, class Val, class KeyHash, class KeyEql>
00188 void hash_vec<Key, Val, KeyHash, KeyEql>::reserve(int n)
00189 {
00190  assert(n>0);
00191  if (nds.resd>=n) return;
00192 
00193  int* hndx2=static_cast<int*>(operator new(sizeof(int)*n));
00194 
00195  typedef typename nodes::node node;
00196  node* nodes2;
00197  try { nodes2=static_cast<node*>(operator new(sizeof(node)*n)); }
00198  catch (...) {
00199        operator delete(hndx);
00200        throw;
00201  }
00202 
00203  fill_n(hndx2, n, -1);
00204 
00205  memcpy(nodes2, nds.nodes, sizeof(*nodes2)*nds.used);
00206  for (int i=0; i<nds.used; i++) nodes2[i].next=-1;
00207 
00208  for (int i=0; i<nds.used; i++) {
00209      int* pnode=hndx2+khash(nodes2[i].key)%n;
00210      nodes2[i].next=*pnode;
00211      *pnode=i;
00212  }
00213 
00214  operator delete(hndx);
00215  hndx=hndx2;
00216 
00217  operator delete(nds.nodes);
00218  nds.nodes=nodes2;
00219  nds.resd=n;
00220 }
00221 
00222 template<class Key, class Val, class KeyHash, class KeyEql>
00223 inline const Key& hash_vec<Key, Val, KeyHash, KeyEql>::key(int pos) const
00224 {
00225  assert(pos>=0 && pos<size());
00226  return nds.nodes[pos].key;
00227 }
00228 
00229 template<class Key, class Val, class KeyHash, class KeyEql>
00230 inline Val& hash_vec<Key, Val, KeyHash, KeyEql>::val(int pos)
00231 {
00232  assert(pos>=0 && pos<size());
00233  return nds.nodes[pos].val;
00234 }
00235 
00236 template<class Key, class Val, class KeyHash, class KeyEql>
00237 inline const Val& hash_vec<Key, Val, KeyHash, KeyEql>::val(int pos) const
00238 {
00239  assert(pos>=0 && pos<size());
00240  return nds.nodes[pos].val;
00241 }
00242 
00243 template<class Key, class Val, class KeyHash, class KeyEql>
00244 int hash_vec<Key, Val, KeyHash, KeyEql>::insert(const Key& k, const Val& v)
00245 {
00246  assert(nds.used<=nds.resd);
00247  if (nds.used==nds.resd) reserve(nds.resd*2+1);
00248 
00249  int* pnode=find(root(k), k);
00250  if (*pnode!=-1) return -1;
00251 
00252  nds.create_at(nds.used, k, v);
00253  return *pnode=nds.used++;
00254 }
00255 
00256 template<class Key, class Val, class KeyHash, class KeyEql>
00257 void hash_vec<Key, Val, KeyHash, KeyEql>::erase(int pos)
00258 {
00259  assert(pos>=0 && pos<size());
00260 
00261  const Key& k=nds.nodes[pos].key;
00262  int* pnode=find(root(k), k);
00263  assert(*pnode==pos);
00264 
00265  int tail=nds.nodes[pos].next;
00266 
00267  nds.destroy_at(pos);
00268  *pnode=-1;
00269 
00270  if (tail!=-1) {
00271     int* ptr=root(nds.nodes[tail].key);
00272     while (*ptr!=-1) ptr=&nds.nodes[*ptr].next;
00273 
00274     *ptr=tail;
00275  }
00276 
00277  int last=nds.used-1;
00278  if (pos!=last) {
00279     const Key& lkey=nds.nodes[last].key;
00280     int* nlast=find(root(lkey), lkey);
00281     assert(*nlast==last);
00282 
00283     nds.move_to(pos, last);
00284     *nlast=pos;
00285  }
00286 
00287  nds.used--;
00288 }
00289 
00290 }  // namespace ::ders
00291 
00292 #endif  // __DERS__HASH_VEC_HPP__
00293 

Generated on Tue Dec 8 11:35:32 2009 for derslib by  doxygen 1.5.5