tpl_dynLhash.H

00001 
00002 /*
00003   This file is part of Aleph system
00004 
00005   Copyright (c) 2002, 2003, 2004, 2005, 2006
00006   UNIVERSITY LOS ANDES (ULA) Merida - REPÚBLICA BOLIVARIANA DE VENEZUELA  
00007 
00008   - Center of Studies in Microelectronics & Distributed Systems (CEMISID) 
00009   - ULA Computer Science Department
00010   - FUNDACITE Mérida - Ministerio de Ciencia y Tecnología
00011 
00012   PERMISSION TO USE, COPY, MODIFY AND DISTRIBUTE THIS SOFTWARE AND ITS
00013   DOCUMENTATION IS HEREBY GRANTED, PROVIDED THAT BOTH THE COPYRIGHT
00014   NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES OF THE
00015   SOFTWARE, DERIVATIVE WORKS OR MODIFIED VERSIONS, AND ANY PORTIONS
00016   THEREOF, AND THAT BOTH NOTICES APPEAR IN SUPPORTING DOCUMENTATION.
00017 
00018   Aleph is distributed in the hope that it will be useful, but WITHOUT
00019   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00020   or FITNESS FOR A PARTICULAR PURPOSE.
00021 
00022   UNIVERSIDAD DE LOS ANDES requests users of this software to return to 
00023 
00024   Leandro Leon
00025   CEMISID 
00026   Ed La Hechicera 
00027   3er piso, ala sur
00028   Facultad de Ingenieria 
00029   Universidad de Los Andes 
00030   Merida - REPÚBLICA BOLIVARIANA DE VENEZUELA    or
00031 
00032   lrleon@ula.ve
00033 
00034   any improvements or extensions that they make and grant Universidad 
00035   de Los Andes (ULA) the rights to redistribute these changes. 
00036 
00037   Aleph is (or was) granted by: 
00038   - Consejo de Desarrollo Cientifico, Humanistico, Tecnico de la ULA 
00039     (CDCHT)
00040   - Fundacite Mérida
00041 */
00042 
00043 
00044 # ifndef TPL_DYNLHASH_H
00045 # define TPL_DYNLHASH_H
00046 
00047 # include <tpl_lhash.H>
00048 
00049 using namespace Aleph;
00050 
00051 namespace Aleph {
00052 
00077     template <typename Key, typename Record, class Cmp = Aleph::equal_to<Key> >
00078 class DynLhashTable : public LhashTable<Key>
00079 {
00080 
00081 private:
00082 
00083   struct DLBucket : public LhashTable<Key>::Bucket
00084   {
00085     Record record;
00086 
00087     DLBucket(const Key & key, const Record & _record)
00088       : LhashTable<Key>::Bucket(key), record(_record)
00089     { /* Empty */ }
00090   };
00091   static DLBucket * record_to_bucket(Record * rec)
00092   {
00093     DLBucket * ret_val = 0;
00094     size_t offset = reinterpret_cast<size_t>(&ret_val->record);
00095     return reinterpret_cast<DLBucket*>(reinterpret_cast<size_t>(rec) - 
00096                                        offset);
00097   }
00098   class DLProxy
00099   {
00100     DynLhashTable & table;
00101     const Key &     key;
00102     DLBucket *      bucket;
00103 
00104   public:
00105 
00106     DLProxy(DynLhashTable & _table, const Key& _key)
00107       : table(_table), key(_key)
00108     {
00109       Record * record = table.search(key);
00110       bucket = record not_eq NULL ? record_to_bucket(record) : NULL;
00111     }
00112 
00113     operator const Record & () const throw(std::exception, std::invalid_argument)
00114     {
00115       if (bucket == NULL)
00116         throw std::invalid_argument("access to unexisting entry");
00117     
00118       return bucket->record;
00119     }
00120 
00121     DLProxy& operator = (const Record& record) 
00122       throw(std::exception, std::bad_alloc) 
00123     {
00124       if (bucket != NULL)
00125         {
00126           bucket->record = record;
00127           return *this;
00128         }
00129 
00130       bucket = new DLBucket (key, record);
00131       table.LhashTable<Key>::insert(bucket);
00132 
00133       return *this;
00134     }
00135 
00136     DLProxy& operator = (const DLProxy& proxy) 
00137       throw(std::exception, std::bad_alloc, std::invalid_argument)
00138     {
00139       if (proxy.bucket == NULL)
00140         throw std::invalid_argument("access to unexisting entry");
00141 
00142       if (bucket != NULL)
00143         {
00144           bucket->record = proxy.bucket->record;
00145           return *this;
00146         }
00147 
00148       bucket = new DLBucket (key, proxy.bucket->record);
00149       table.LhashTable<Key>::insert(bucket);
00150 
00151       return *this;
00152     }
00153   };
00154 
00155 public:
00156 
00157 
00159   typedef typename DynLhashTable<Key, Record>::Hash_Fct Hash_Fct;
00160 
00164   DynLhashTable(Hash_Fct hash_fct, const size_t & len = DefaultPrime) 
00165     throw (std::exception, std::bad_alloc) : LhashTable<Key>(hash_fct, len)
00166   {
00167     // Empty 
00168   }
00169 
00170 
00174   Record * insert(const Key & key, const Record & record)
00175 
00176     throw (std::exception, std::bad_alloc)
00177 
00178   {
00179     DLBucket * bucket = new DLBucket (key, record);
00180 
00181     LhashTable<Key>::insert(bucket);
00182 
00183     return &bucket->record;
00184   }
00188   Record * search(const Key & key)
00189   {
00190     DLBucket * bucket = static_cast<DLBucket*>(LhashTable<Key>::search(key));
00191 
00192     return bucket != NULL ? &bucket->record : NULL;
00193   }
00196   void remove(Record * record)
00197   {
00198     DLBucket* bucket = record_to_bucket(record);
00199 
00200     LhashTable<Key>::remove(bucket);
00201 
00202     delete bucket;
00203   }
00204   DLProxy operator [] (const Key& key) const
00205     throw(std::exception, std::invalid_argument) 
00206   {
00207     return DLProxy ( const_cast<DynLhashTable&>(*this), key);
00208   }
00209 
00210   DLProxy operator [] (const Key& key) 
00211     throw(std::exception, std::bad_alloc, std::invalid_argument) 
00212   {
00213     return DLProxy (*this, key);
00214   }
00215 };
00216 
00217 } // end namespace Aleph
00218 
00219 # endif // TPL_DYNLHASH_H
00220 

Leandro R. León