BALL  1.4.2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
hashMap.h
Go to the documentation of this file.
1 // -*- Mode: C++; tab-width: 2; -*-
2 // vi: set ts=2:
3 //
4 
5 #ifndef BALL_DATATYPE_HASHMAP_H
6 #define BALL_DATATYPE_HASHMAP_H
7 
8 #ifndef BALL_COMMON_H
9 # include <BALL/common.h>
10 #endif
11 
12 #ifndef BALL_COMMON_HASH_H
13 # include <BALL/COMMON/hash.h>
14 #endif
15 
16 #ifndef BALL_DATATYPE_TRIPLE_H
17 # include <BALL/DATATYPE/triple.h>
18 #endif
19 
20 #ifndef BALL_DATATYPE_QUADRUPLE_H
21 # include <BALL/DATATYPE/quadruple.h>
22 #endif
23 
24 #include <utility>
25 #include <algorithm>
26 
27 #ifdef BALL_HAS_UNORDERED_MAP
28 
29 #if defined(BALL_HAS_STD_UNORDERED_MAP)
30 # include <unordered_map>
31 #elif defined(BALL_HAS_TR1_UNORDERED_MAP)
32 # include <tr1/unordered_map>
33 #elif defined(BALL_HAS_BOOST_UNORDERED_MAP)
34 # include <boost/unordered_map.hpp>
35 #endif
36 
37 #elif defined(BALL_HAS_HASH_MAP)
38 #if defined(BALL_EXT_INCLUDE_PREFIX)
39 # include <ext/hash_map>
40 # include <ext/hash_fun.h>
41 #else
42 # include <hash_map>
43 # include <hash_fun.h>
44 #endif
45 #else
46 # include <map>
47 #endif
48 
49 #if defined(BALL_HAS_UNORDERED_MAP) && !defined(BALL_HAS_BOOST_UNORDERED_MAP)
50 
51 #ifdef BALL_EXTEND_HASH_IN_STD_NS
52 namespace std
53 {
54 #endif // BALL_EXTEND_HASH_IN_STD_NS
55 
56 #ifdef BALL_HAS_TR1_UNORDERED_MAP
57  namespace tr1
58  {
59 #endif // BALL_HAS_TR1_UNORDERED_MAP
60 
61  // borrowed from boost
62  template<typename T>
63  void hash_combine_ala_boost(size_t & seed, T const & v)
64  {
65  hash<T> h;
66  seed ^= h(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
67  }
68 
69  template<class A, class B>
70  struct hash<pair<A, B> > : public std::unary_function<pair<A,B>, size_t>
71  {
72  inline size_t
73  operator()(pair<A, B> p) const
74  {
75  size_t seed = 0;
76  hash_combine_ala_boost(seed, p.first);
77  hash_combine_ala_boost(seed, p.second);
78 
79  return seed;
80  }
81  };
82 
83  template <class A, class B, class C>
84  struct hash< ::BALL::Triple<A, B, C> > : public std::unary_function< ::BALL::Triple<A, B, C>, size_t>
85  {
86  inline size_t
87  operator()(::BALL::Triple<A, B, C> t) const
88  {
89  size_t seed = 0;
90  hash_combine_ala_boost(seed, t.first);
91  hash_combine_ala_boost(seed, t.second);
92  hash_combine_ala_boost(seed, t.third);
93 
94  return seed;
95  }
96  };
97 
98  template <class A, class B, class C, class D>
99  struct hash< ::BALL::Quadruple<A, B, C, D> > : public std::unary_function< const ::BALL::Quadruple<A, B, C, D>, size_t>
100  {
101  inline size_t
102  operator()( ::BALL::Quadruple<A, B, C, D> q) const
103  {
104  size_t seed = 0;
105  hash_combine_ala_boost(seed, q.first);
106  hash_combine_ala_boost(seed, q.second);
107  hash_combine_ala_boost(seed, q.third);
108  hash_combine_ala_boost(seed, q.fourth);
109 
110  return seed;
111  }
112  };
113 
114 #ifndef BALL_COMPILER_MSVC
115  template<>
116  struct hash<const ::BALL::String&> : public std::unary_function<const ::BALL::String &, size_t>
117  {
118  inline size_t
119  operator()(const ::BALL::String& s) const
120  {
121  hash<const string&> h;
122  return h(s);
123  }
124  };
125 #endif
126 
127  template<>
128  struct hash< ::BALL::String > : public std::unary_function< ::BALL::String, size_t >
129  {
130  inline size_t
131  operator()( ::BALL::String s) const
132  {
133  hash<string> h;
134  return h(s);
135  }
136  };
137 #ifdef BALL_HAS_TR1_UNORDERED_MAP
138  }
139 #endif // BALL_HAS_TR1_UNORDERED_MAP
140 
141 #ifdef BALL_EXTEND_HASH_IN_STD_NS
142 }
143 #endif // BALL_EXTEND_HASH_IN_STD_NS
144 
145 #endif // if defined(BALL_HAS_UNORDERED_MAP) && !defined(BALL_HAS_BOOST_UNORDERED_MAP)
146 
147 #ifdef BALL_HAS_HASH_MAP
148 namespace BALL_MAP_NAMESPACE
149 {
150  template<class T>
151  struct hash<T*>
152  {
153  size_t operator()(const T* x) const { return (size_t)x; }
154  };
155 
156  template<>
157  struct hash<BALL::String>
158  {
159  size_t operator () (const BALL::String& s) const {return __stl_hash_string(s.c_str());}
160  };
161 
162 #ifdef BALL_NEEDS_LONGSIZE_HASH
163  template<>
164  struct hash<BALL::LongSize>
165  {
166  size_t operator()(BALL::LongSize x) const { return (size_t)x; }
167  };
168 #endif
169 }
170 #endif // BALL_HAS_HASH_MAP
171 
172 namespace BALL
173 {
179  template <class Key, class T>
180  class HashMap
181  : public BALL_MAP_NAME
182  {
183  public:
184 
192  {
193  public:
194  IllegalKey(const char* file, int line)
195  : Exception::GeneralException(file, line)
196  {
197  }
198  };
199 
201 
202  typedef BALL_MAP_NAME Base;
203  typedef typename Base::value_type ValueType;
204  typedef Key KeyType;
205  typedef typename Base::value_type* PointerType;
206  typedef typename Base::iterator Iterator;
207  typedef typename Base::const_iterator ConstIterator;
209 
211  inline bool has(const Key& key) const
212  {
213  return Base::find(key)!=Base::end();
214  }
215 
221  const T& operator [] (const Key& key) const;
222 
224  T& operator [] (const Key& key);
225 
227  bool operator == (const HashMap<Key, T>& rhs) const;
228 
229  Size size() const { return BALL_MAP_NAME::size(); }
230  };
231 
232  //******************************************************************************************
233  // Implementations of template methods
234  //******************************************************************************************
235 
236  template <class Key, class T>
237  const T& HashMap<Key, T>::operator [] (const Key& key) const
238  {
239  ConstIterator it = this->find(key);
240  if (it == Base::end())
241  {
242  throw IllegalKey(__FILE__, __LINE__);
243  }
244  else
245  {
246  return it->second;
247  }
248  }
249 
250 
251  template <class Key, class T>
253  {
254  // No equality if sizes differ.
255  if (size() != rhs.size())
256  {
257  return false;
258  }
259 
260  // Equality if bothe have the same size and every element of lhs is
261  // is contained in lhs. Testing the other way round is obviously
262  // unnecessary.
263  ConstIterator it(BALL_MAP_NAME::begin());
264  for (; it != BALL_MAP_NAME::end(); ++it)
265  {
266  if (!rhs.has(it->first)) return false;
267  }
268  return true;
269  }
270 
271  template <class Key, class T>
272  T& HashMap<Key, T>::operator [] (const Key& key)
273  {
274  return BALL_MAP_NAME::operator[] (key);
275  }
276 
277 } // namespace BALL
278 
279 #endif // BALL_DATATYPE_HASHMAP_H