hashMap.h

Go to the documentation of this file.
00001 // -*- Mode: C++; tab-width: 2; -*-
00002 // vi: set ts=2:
00003 //
00004 // $Id: hashMap.h,v 1.41 2005/12/23 17:01:42 amoll Exp $ 
00005 //
00006 
00007 #ifndef BALL_DATATYPE_HASHMAP_H
00008 #define BALL_DATATYPE_HASHMAP_H
00009 
00010 #ifndef BALL_COMMON_H
00011 # include <BALL/common.h>
00012 #endif
00013 
00014 #ifndef BALL_COMMON_HASH_H
00015 # include <BALL/COMMON/hash.h>
00016 #endif
00017 
00018 #ifndef BALL_DATATYPE_TRIPLE_H
00019 # include <BALL/DATATYPE/triple.h>
00020 #endif
00021 
00022 #ifndef BALL_DATATYPE_QUADRUPLE_H
00023 # include <BALL/DATATYPE/quadruple.h>
00024 #endif
00025 
00026 #include <utility>
00027 #include <algorithm>
00028 
00029 #ifdef BALL_HAS_UNORDERED_MAP
00030 
00031 #if defined(BALL_HAS_STD_UNORDERED_MAP)
00032 # include <unordered_map>
00033 #elif defined(BALL_HAS_TR1_UNORDERED_MAP)
00034 # include <tr1/unordered_map>
00035 #elif defined(BALL_HAS_BOOST_UNORDERED_MAP)
00036 # include <boost/unordered_map.hpp>
00037 #endif
00038 
00039 #elif defined(BALL_EXT_INCLUDE_PREFIX)
00040 # include <ext/hash_map>
00041 # include <ext/hash_fun.h>
00042 #else
00043 # include <hash_map>
00044 # include <hash_fun.h>
00045 #endif
00046 
00047 #if defined(BALL_HAS_UNORDERED_MAP) && !defined(BALL_HAS_BOOST_UNORDERED_MAP)
00048 
00049 #ifdef BALL_EXTEND_HASH_IN_STD_NS
00050 namespace std
00051 {
00052 #endif // BALL_EXTEND_HASH_IN_STD_NS
00053 
00054 #ifdef BALL_HAS_TR1_UNORDERED_MAP
00055   namespace tr1
00056   {
00057 #endif // BALL_HAS_TR1_UNORDERED_MAP
00058     
00059     // borrowed from boost
00060     template<typename T> 
00061     void hash_combine_ala_boost(size_t & seed, T const & v)
00062     {
00063       hash<T> h;
00064       seed ^= h(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
00065     }
00066 
00067     template<class A, class B>
00068     struct hash<pair<A, B> > : public std::unary_function<pair<A,B>, size_t>
00069     {
00070       inline size_t
00071       operator()(pair<A, B> p) const
00072       {
00073         size_t seed = 0;
00074         hash_combine_ala_boost(seed, p.first);
00075         hash_combine_ala_boost(seed, p.second);
00076 
00077         return seed;
00078       }
00079     };
00080 
00081     template <class A, class B, class C>
00082     struct hash< ::BALL::Triple<A, B, C> > : public std::unary_function< ::BALL::Triple<A, B, C>, size_t>
00083     {
00084       inline size_t
00085       operator()(::BALL::Triple<A, B, C> t) const
00086       {
00087         size_t seed = 0;
00088         hash_combine_ala_boost(seed, t.first);
00089         hash_combine_ala_boost(seed, t.second);
00090         hash_combine_ala_boost(seed, t.third);
00091 
00092         return seed;
00093       }
00094     };
00095 
00096     template <class A, class B, class C, class D>
00097     struct hash< const ::BALL::Quadruple<A, B, C, D> > : public std::unary_function< const ::BALL::Quadruple<A, B, C, D>, size_t> 
00098     {
00099       inline size_t
00100       operator()(const ::BALL::Quadruple<A, B, C, D> q) const
00101       {
00102         size_t seed = 0;
00103         hash_combine_ala_boost(seed, q.first);
00104         hash_combine_ala_boost(seed, q.second);
00105         hash_combine_ala_boost(seed, q.third);
00106         hash_combine_ala_boost(seed, q.fourth);
00107 
00108         return seed;
00109       }
00110     };
00111 
00112 #ifndef BALL_COMPILER_MSVC
00113     template<>
00114     struct hash<const ::BALL::String&> : public std::unary_function<const ::BALL::String &, size_t>
00115     {
00116       inline size_t
00117       operator()(const ::BALL::String& s) const
00118       {
00119         hash<const string&> h;
00120         return h(s);
00121       }
00122     };
00123 #endif
00124 
00125     template<>
00126     struct hash< ::BALL::String > : public std::unary_function< ::BALL::String, size_t >
00127     {
00128       inline size_t
00129       operator()( ::BALL::String s) const
00130       {
00131         hash<string> h;
00132         return h(s);
00133       }
00134     };
00135 #ifdef BALL_HAS_TR1_UNORDERED_MAP
00136   }
00137 #endif // BALL_HAS_TR1_UNORDERED_MAP
00138 
00139 #ifdef BALL_EXTEND_HASH_IN_STD_NS
00140 }
00141 #endif // BALL_EXTEND_HASH_IN_STD_NS
00142 
00143 #endif // if defined(BALL_HAS_UNORDERED_MAP) && !defined(BALL_HAS_BOOST_UNORDERED_MAP)
00144 
00145 #ifdef BALL_HAS_HASH_MAP
00146 namespace BALL_MAP_NAMESPACE
00147 {
00148   template<class T>
00149   struct hash<T*>
00150   {
00151     size_t operator()(const T* x) const { return (size_t)x; }
00152   };
00153 
00154   template<>
00155   struct hash<BALL::String>
00156   {
00157     size_t operator () (const BALL::String& s) const {return __stl_hash_string(s.c_str());}
00158   };
00159 
00160 #ifdef BALL_NEEDS_LONGSIZE_HASH
00161   template<>
00162   struct hash<BALL::LongSize>
00163   {
00164     size_t operator()(BALL::LongSize x) const { return (size_t)x; }
00165   };
00166 #endif
00167 }
00168 #endif // BALL_HAS_HASH_MAP
00169 
00170 namespace BALL
00171 {
00177   template <class Key, class T>
00178   class HashMap
00179     : public BALL_MAP_NAME
00180   {
00181     public:
00182 
00188       class IllegalKey
00189         : public Exception::GeneralException
00190       {
00191         public:
00192         IllegalKey(const char* file, int line)
00193           : Exception::GeneralException(file, line)
00194         {
00195         }
00196       };
00197       
00199 
00200       typedef BALL_MAP_NAME Base;
00201       typedef typename Base::value_type ValueType;
00202       typedef Key KeyType;
00203       typedef typename Base::value_type* PointerType;
00204       typedef typename Base::iterator Iterator;
00205       typedef typename Base::const_iterator ConstIterator;
00207 
00209       inline bool has(const Key& key) const
00210       {
00211         return Base::find(key)!=Base::end();
00212       }
00213 
00219       const T& operator [] (const Key& key) const;
00220 
00222       T& operator [] (const Key& key);
00223       
00225       bool operator == (const HashMap<Key, T>& rhs) const;
00226       
00227       Size size() const { return BALL_MAP_NAME::size(); }
00228   };
00229   
00230   //******************************************************************************************
00231   // Implementations of template methods
00232   //******************************************************************************************
00233   
00234   template <class Key, class T>
00235   const T& HashMap<Key, T>::operator [] (const Key& key) const
00236   {
00237     ConstIterator it = find(key);
00238     if (it == Base::end())
00239     {
00240       throw IllegalKey(__FILE__, __LINE__);
00241     }
00242     else
00243     {
00244       return it->second;
00245     }
00246   }
00247 
00248 
00249   template <class Key, class T>
00250   bool HashMap<Key, T>::operator == (const HashMap<Key, T>& rhs) const
00251   {
00252     // No equality if sizes differ.
00253     if (size() != rhs.size()) 
00254     {
00255       return false; 
00256     }
00257 
00258     // Equality if bothe have the same size and every element of lhs is 
00259     // is contained in lhs. Testing the other way round is obviously
00260     // unnecessary.
00261     ConstIterator it(BALL_MAP_NAME::begin());
00262     for (; it != BALL_MAP_NAME::end(); ++it)
00263     {
00264       if (!rhs.has(it->first)) return false;
00265     }
00266     return true;
00267   }
00268   
00269   template <class Key, class T>
00270   T& HashMap<Key, T>::operator [] (const Key& key)
00271     
00272   {
00273     Iterator it = find(key);
00274     if (it == Base::end())
00275     {
00276       it = insert(ValueType(key, T())).first;
00277     }
00278     return it->second;
00279   }
00280 
00281 } // namespace BALL
00282 
00283 #endif // BALL_DATATYPE_HASHMAP_H