OLD | NEW |
1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
4 // | 4 // |
5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
7 // met: | 7 // met: |
8 // | 8 // |
9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
(...skipping 19 matching lines...) Expand all Loading... |
30 | 30 |
31 // Author: kenton@google.com (Kenton Varda) | 31 // Author: kenton@google.com (Kenton Varda) |
32 // | 32 // |
33 // Deals with the fact that hash_map is not defined everywhere. | 33 // Deals with the fact that hash_map is not defined everywhere. |
34 | 34 |
35 #ifndef GOOGLE_PROTOBUF_STUBS_HASH_H__ | 35 #ifndef GOOGLE_PROTOBUF_STUBS_HASH_H__ |
36 #define GOOGLE_PROTOBUF_STUBS_HASH_H__ | 36 #define GOOGLE_PROTOBUF_STUBS_HASH_H__ |
37 | 37 |
38 #include <string.h> | 38 #include <string.h> |
39 #include <google/protobuf/stubs/common.h> | 39 #include <google/protobuf/stubs/common.h> |
40 | 40 #include <google/protobuf/stubs/pbconfig.h> |
41 #define GOOGLE_PROTOBUF_HAVE_HASH_MAP 1 | |
42 #define GOOGLE_PROTOBUF_HAVE_HASH_SET 1 | |
43 | |
44 // Use C++11 unordered_{map|set} if available. | |
45 #if ((__cplusplus >= 201103L) && \ | |
46 ((defined(__GLIBCXX__) && (__GLIBCXX__ > 20090421)) || \ | |
47 (defined(_LIBCPP_VERSION) && (_LIBCPP_STD_VER >= 11)))) | |
48 # define GOOGLE_PROTOBUF_HAS_CXX11_HASH | |
49 | |
50 // For XCode >= 4.6: the compiler is clang with libc++. | |
51 // For earlier XCode version: the compiler is gcc-4.2.1 with libstdc++. | |
52 // libc++ provides <unordered_map> and friends even in non C++11 mode, | |
53 // and it does not provide the tr1 library. Therefore the following macro | |
54 // checks against this special case. | |
55 // Note that we should not test the __APPLE_CC__ version number or the | |
56 // __clang__ macro, since the new compiler can still use -stdlib=libstdc++, in | |
57 // which case <unordered_map> is not compilable without -std=c++11 | |
58 #elif defined(__APPLE_CC__) | |
59 # if __GNUC__ >= 4 | |
60 # define GOOGLE_PROTOBUF_HAS_TR1 | |
61 # else | |
62 // Not tested for gcc < 4... These setting can compile under 4.2.1 though. | |
63 # define GOOGLE_PROTOBUF_HASH_NAMESPACE __gnu_cxx | |
64 # include <ext/hash_map> | |
65 # define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map | |
66 # include <ext/hash_set> | |
67 # define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set | |
68 # endif | |
69 | |
70 // Version checks for gcc. | |
71 #elif defined(__GNUC__) | |
72 // For GCC 4.x+, use tr1::unordered_map/set; otherwise, follow the | |
73 // instructions from: | |
74 // https://gcc.gnu.org/onlinedocs/libstdc++/manual/backwards.html | |
75 # if __GNUC__ >= 4 | |
76 # define GOOGLE_PROTOBUF_HAS_TR1 | |
77 # elif __GNUC__ >= 3 | |
78 # include <backward/hash_map> | |
79 # define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map | |
80 # include <backward/hash_set> | |
81 # define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set | |
82 # if __GNUC__ == 3 && __GNUC_MINOR__ == 0 | |
83 # define GOOGLE_PROTOBUF_HASH_NAMESPACE std // GCC 3.0 | |
84 # else | |
85 # define GOOGLE_PROTOBUF_HASH_NAMESPACE __gnu_cxx // GCC 3.1 and later | |
86 # endif | |
87 # else | |
88 # define GOOGLE_PROTOBUF_HASH_NAMESPACE | |
89 # include <hash_map> | |
90 # define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map | |
91 # include <hash_set> | |
92 # define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set | |
93 # endif | |
94 | |
95 // Version checks for MSC. | |
96 // Apparently Microsoft decided to move hash_map *back* to the std namespace in | |
97 // MSVC 2010: | |
98 // http://blogs.msdn.com/vcblog/archive/2009/05/25/stl-breaking-changes-in-visua
l-studio-2010-beta-1.aspx | |
99 // And.. they are moved back to stdext in MSVC 2013 (haven't checked 2012). That | |
100 // said, use unordered_map for MSVC 2010 and beyond is our safest bet. | |
101 #elif defined(_MSC_VER) | |
102 # if _MSC_VER >= 1600 // Since Visual Studio 2010 | |
103 # define GOOGLE_PROTOBUF_HAS_CXX11_HASH | |
104 # define GOOGLE_PROTOBUF_HASH_COMPARE std::hash_compare | |
105 # elif _MSC_VER >= 1500 // Since Visual Studio 2008 | |
106 # define GOOGLE_PROTOBUF_HAS_TR1 | |
107 # define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare | |
108 # elif _MSC_VER >= 1310 | |
109 # define GOOGLE_PROTOBUF_HASH_NAMESPACE stdext | |
110 # include <hash_map> | |
111 # define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map | |
112 # include <hash_set> | |
113 # define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set | |
114 # define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare | |
115 # else | |
116 # define GOOGLE_PROTOBUF_HASH_NAMESPACE std | |
117 # include <hash_map> | |
118 # define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map | |
119 # include <hash_set> | |
120 # define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set | |
121 # define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare | |
122 # endif | |
123 | |
124 // **ADD NEW COMPILERS SUPPORT HERE.** | |
125 // For other compilers, undefine the macro and fallback to use std::map, in | |
126 // google/protobuf/stubs/hash.h | |
127 #else | |
128 # undef GOOGLE_PROTOBUF_HAVE_HASH_MAP | |
129 # undef GOOGLE_PROTOBUF_HAVE_HASH_SET | |
130 #endif | |
131 | |
132 #if defined(GOOGLE_PROTOBUF_HAS_CXX11_HASH) | |
133 # define GOOGLE_PROTOBUF_HASH_NAMESPACE std | |
134 # include <unordered_map> | |
135 # define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map | |
136 # include <unordered_set> | |
137 # define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set | |
138 #elif defined(GOOGLE_PROTOBUF_HAS_TR1) | |
139 # define GOOGLE_PROTOBUF_HASH_NAMESPACE std::tr1 | |
140 # include <tr1/unordered_map> | |
141 # define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map | |
142 # include <tr1/unordered_set> | |
143 # define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set | |
144 #endif | |
145 | |
146 #undef GOOGLE_PROTOBUF_HAS_CXX11_HASH | |
147 #undef GOOGLE_PROTOBUF_HAS_TR1 | |
148 | 41 |
149 #if defined(GOOGLE_PROTOBUF_HAVE_HASH_MAP) && \ | 42 #if defined(GOOGLE_PROTOBUF_HAVE_HASH_MAP) && \ |
150 defined(GOOGLE_PROTOBUF_HAVE_HASH_SET) | 43 defined(GOOGLE_PROTOBUF_HAVE_HASH_SET) |
| 44 #include GOOGLE_PROTOBUF_HASH_MAP_H |
| 45 #include GOOGLE_PROTOBUF_HASH_SET_H |
151 #else | 46 #else |
152 #define GOOGLE_PROTOBUF_MISSING_HASH | 47 #define GOOGLE_PROTOBUF_MISSING_HASH |
153 #include <map> | 48 #include <map> |
154 #include <set> | 49 #include <set> |
155 #endif | 50 #endif |
156 | 51 |
157 namespace google { | 52 namespace google { |
158 namespace protobuf { | 53 namespace protobuf { |
159 | 54 |
160 #ifdef GOOGLE_PROTOBUF_MISSING_HASH | 55 #ifdef GOOGLE_PROTOBUF_MISSING_HASH |
161 #undef GOOGLE_PROTOBUF_MISSING_HASH | |
162 | 56 |
163 // This system doesn't have hash_map or hash_set. Emulate them using map and | 57 // This system doesn't have hash_map or hash_set. Emulate them using map and |
164 // set. | 58 // set. |
165 | 59 |
166 // Make hash<T> be the same as less<T>. Note that everywhere where custom | 60 // Make hash<T> be the same as less<T>. Note that everywhere where custom |
167 // hash functions are defined in the protobuf code, they are also defined such | 61 // hash functions are defined in the protobuf code, they are also defined such |
168 // that they can be used as "less" functions, which is required by MSVC anyway. | 62 // that they can be used as "less" functions, which is required by MSVC anyway. |
169 template <typename Key> | 63 template <typename Key> |
170 struct hash { | 64 struct hash { |
171 // Dummy, just to make derivative hash functions compile. | 65 // Dummy, just to make derivative hash functions compile. |
(...skipping 18 matching lines...) Expand all Loading... |
190 | 84 |
191 inline bool operator()(const char* a, const char* b) const { | 85 inline bool operator()(const char* a, const char* b) const { |
192 return strcmp(a, b) < 0; | 86 return strcmp(a, b) < 0; |
193 } | 87 } |
194 }; | 88 }; |
195 | 89 |
196 template <typename Key, typename Data, | 90 template <typename Key, typename Data, |
197 typename HashFcn = hash<Key>, | 91 typename HashFcn = hash<Key>, |
198 typename EqualKey = std::equal_to<Key>, | 92 typename EqualKey = std::equal_to<Key>, |
199 typename Alloc = std::allocator< std::pair<const Key, Data> > > | 93 typename Alloc = std::allocator< std::pair<const Key, Data> > > |
200 class hash_map : public std::map<Key, Data, HashFcn, Alloc> { | 94 class hash_map : public std::map<Key, Data, HashFcn, EqualKey, Alloc> { |
201 typedef std::map<Key, Data, HashFcn, Alloc> BaseClass; | |
202 | |
203 public: | 95 public: |
204 hash_map(int a = 0, const HashFcn& b = HashFcn(), | 96 hash_map(int = 0, const HashFcn& = HashFcn(), const EqualKey& = EqualKey(), |
205 const EqualKey& c = EqualKey(), | 97 const Alloc& = Alloc()) {} |
206 const Alloc& d = Alloc()) : BaseClass(b, d) {} | |
207 }; | 98 }; |
208 | 99 |
209 template <typename Key, | 100 template <typename Key, |
210 typename HashFcn = hash<Key>, | 101 typename HashFcn = hash<Key>, |
211 typename EqualKey = std::equal_to<Key> > | 102 typename EqualKey = std::equal_to<Key> > |
212 class hash_set : public std::set<Key, HashFcn> { | 103 class hash_set : public std::set<Key, HashFcn> { |
213 public: | 104 public: |
214 hash_set(int = 0) {} | 105 hash_set(int = 0) {} |
215 }; | 106 }; |
216 | 107 |
217 #elif defined(_MSC_VER) && !defined(_STLPORT_VERSION) | 108 #elif defined(_MSC_VER) && !defined(_STLPORT_VERSION) |
218 | 109 |
219 template <typename Key> | 110 template <typename Key> |
220 struct hash : public GOOGLE_PROTOBUF_HASH_COMPARE<Key> { | 111 struct hash : public GOOGLE_PROTOBUF_HASH_NAMESPACE::hash_compare<Key> { |
221 }; | 112 }; |
222 | 113 |
223 // MSVC's hash_compare<const char*> hashes based on the string contents but | 114 // MSVC's hash_compare<const char*> hashes based on the string contents but |
224 // compares based on the string pointer. WTF? | 115 // compares based on the string pointer. WTF? |
225 class CstringLess { | 116 class CstringLess { |
226 public: | 117 public: |
227 inline bool operator()(const char* a, const char* b) const { | 118 inline bool operator()(const char* a, const char* b) const { |
228 return strcmp(a, b) < 0; | 119 return strcmp(a, b) < 0; |
229 } | 120 } |
230 }; | 121 }; |
231 | 122 |
232 template <> | 123 template <> |
233 struct hash<const char*> | 124 struct hash<const char*> |
234 : public GOOGLE_PROTOBUF_HASH_COMPARE<const char*, CstringLess> {}; | 125 : public GOOGLE_PROTOBUF_HASH_NAMESPACE::hash_compare< |
| 126 const char*, CstringLess> {}; |
235 | 127 |
236 template <typename Key, typename Data, | 128 template <typename Key, typename Data, |
237 typename HashFcn = hash<Key>, | 129 typename HashFcn = hash<Key>, |
238 typename EqualKey = std::equal_to<Key>, | 130 typename EqualKey = std::equal_to<Key>, |
239 typename Alloc = std::allocator< std::pair<const Key, Data> > > | 131 typename Alloc = std::allocator< std::pair<const Key, Data> > > |
240 class hash_map | 132 class hash_map |
241 : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS< | 133 : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS< |
242 Key, Data, HashFcn, EqualKey, Alloc> { | 134 Key, Data, HashFcn, EqualKey, Alloc> { |
243 typedef GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS< | |
244 Key, Data, HashFcn, EqualKey, Alloc> BaseClass; | |
245 | |
246 public: | 135 public: |
247 hash_map(int a = 0, const HashFcn& b = HashFcn(), | 136 hash_map(int = 0, const HashFcn& = HashFcn(), const EqualKey& = EqualKey(), |
248 const EqualKey& c = EqualKey(), | 137 const Alloc& = Alloc()) {} |
249 const Alloc& d = Alloc()) : BaseClass(a, b, c, d) {} | |
250 }; | 138 }; |
251 | 139 |
252 template <typename Key, typename HashFcn = hash<Key>, | 140 template <typename Key, typename HashFcn = hash<Key>, |
253 typename EqualKey = std::equal_to<Key> > | 141 typename EqualKey = std::equal_to<Key> > |
254 class hash_set | 142 class hash_set |
255 : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS< | 143 : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS< |
256 Key, HashFcn, EqualKey> { | 144 Key, HashFcn, EqualKey> { |
257 public: | 145 public: |
258 hash_set(int = 0) {} | 146 hash_set(int = 0) {} |
259 }; | 147 }; |
(...skipping 17 matching lines...) Expand all Loading... |
277 struct hash<const char*> { | 165 struct hash<const char*> { |
278 inline size_t operator()(const char* str) const { | 166 inline size_t operator()(const char* str) const { |
279 size_t result = 0; | 167 size_t result = 0; |
280 for (; *str != '\0'; str++) { | 168 for (; *str != '\0'; str++) { |
281 result = 5 * result + *str; | 169 result = 5 * result + *str; |
282 } | 170 } |
283 return result; | 171 return result; |
284 } | 172 } |
285 }; | 173 }; |
286 | 174 |
287 template<> | |
288 struct hash<bool> { | |
289 size_t operator()(bool x) const { | |
290 return static_cast<size_t>(x); | |
291 } | |
292 }; | |
293 | |
294 template <typename Key, typename Data, | 175 template <typename Key, typename Data, |
295 typename HashFcn = hash<Key>, | 176 typename HashFcn = hash<Key>, |
296 typename EqualKey = std::equal_to<Key>, | 177 typename EqualKey = std::equal_to<Key>, |
297 typename Alloc = std::allocator< std::pair<const Key, Data> > > | 178 typename Alloc = std::allocator< std::pair<const Key, Data> > > |
298 class hash_map | 179 class hash_map |
299 : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS< | 180 : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS< |
300 Key, Data, HashFcn, EqualKey, Alloc> { | 181 Key, Data, HashFcn, EqualKey, Alloc> { |
301 typedef GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS< | |
302 Key, Data, HashFcn, EqualKey, Alloc> BaseClass; | |
303 | |
304 public: | 182 public: |
305 hash_map(int a = 0, const HashFcn& b = HashFcn(), | 183 hash_map(int = 0, const HashFcn& = HashFcn(), const EqualKey& = EqualKey(), |
306 const EqualKey& c = EqualKey(), | 184 const Alloc& = Alloc()) {} |
307 const Alloc& d = Alloc()) : BaseClass(a, b, c, d) {} | |
308 }; | 185 }; |
309 | 186 |
310 template <typename Key, typename HashFcn = hash<Key>, | 187 template <typename Key, typename HashFcn = hash<Key>, |
311 typename EqualKey = std::equal_to<Key> > | 188 typename EqualKey = std::equal_to<Key> > |
312 class hash_set | 189 class hash_set |
313 : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS< | 190 : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS< |
314 Key, HashFcn, EqualKey> { | 191 Key, HashFcn, EqualKey> { |
315 public: | 192 public: |
316 hash_set(int = 0) {} | 193 hash_set(int = 0) {} |
317 }; | 194 }; |
318 | 195 |
| 196 #undef GOOGLE_PROTOBUF_MISSING_HASH |
319 #endif // !GOOGLE_PROTOBUF_MISSING_HASH | 197 #endif // !GOOGLE_PROTOBUF_MISSING_HASH |
320 | 198 |
321 template <> | 199 template <> |
322 struct hash<string> { | 200 struct hash<string> { |
323 inline size_t operator()(const string& key) const { | 201 inline size_t operator()(const string& key) const { |
324 return hash<const char*>()(key.c_str()); | 202 return hash<const char*>()(key.c_str()); |
325 } | 203 } |
326 | 204 |
327 static const size_t bucket_size = 4; | 205 static const size_t bucket_size = 4; |
328 static const size_t min_buckets = 8; | 206 static const size_t min_buckets = 8; |
329 inline bool operator()(const string& a, const string& b) const { | 207 inline size_t operator()(const string& a, const string& b) const { |
330 return a < b; | 208 return a < b; |
331 } | 209 } |
332 }; | 210 }; |
333 | 211 |
334 template <typename First, typename Second> | 212 template <typename First, typename Second> |
335 struct hash<pair<First, Second> > { | 213 struct hash<pair<First, Second> > { |
336 inline size_t operator()(const pair<First, Second>& key) const { | 214 inline size_t operator()(const pair<First, Second>& key) const { |
337 size_t first_hash = hash<First>()(key.first); | 215 size_t first_hash = hash<First>()(key.first); |
338 size_t second_hash = hash<Second>()(key.second); | 216 size_t second_hash = hash<Second>()(key.second); |
339 | 217 |
340 // FIXME(kenton): What is the best way to compute this hash? I have | 218 // FIXME(kenton): What is the best way to compute this hash? I have |
341 // no idea! This seems a bit better than an XOR. | 219 // no idea! This seems a bit better than an XOR. |
342 return first_hash * ((1 << 16) - 1) + second_hash; | 220 return first_hash * ((1 << 16) - 1) + second_hash; |
343 } | 221 } |
344 | 222 |
345 static const size_t bucket_size = 4; | 223 static const size_t bucket_size = 4; |
346 static const size_t min_buckets = 8; | 224 static const size_t min_buckets = 8; |
347 inline bool operator()(const pair<First, Second>& a, | 225 inline size_t operator()(const pair<First, Second>& a, |
348 const pair<First, Second>& b) const { | 226 const pair<First, Second>& b) const { |
349 return a < b; | 227 return a < b; |
350 } | 228 } |
351 }; | 229 }; |
352 | 230 |
353 // Used by GCC/SGI STL only. (Why isn't this provided by the standard | 231 // Used by GCC/SGI STL only. (Why isn't this provided by the standard |
354 // library? :( ) | 232 // library? :( ) |
355 struct streq { | 233 struct streq { |
356 inline bool operator()(const char* a, const char* b) const { | 234 inline bool operator()(const char* a, const char* b) const { |
357 return strcmp(a, b) == 0; | 235 return strcmp(a, b) == 0; |
358 } | 236 } |
359 }; | 237 }; |
360 | 238 |
361 } // namespace protobuf | 239 } // namespace protobuf |
362 } // namespace google | 240 } // namespace google |
363 | 241 |
364 #endif // GOOGLE_PROTOBUF_STUBS_HASH_H__ | 242 #endif // GOOGLE_PROTOBUF_STUBS_HASH_H__ |
OLD | NEW |