| 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 |