00001
00002
00003
00004
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
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
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
00253 if (size() != rhs.size())
00254 {
00255 return false;
00256 }
00257
00258
00259
00260
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 }
00282
00283 #endif // BALL_DATATYPE_HASHMAP_H