hash.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // https://developers.google.com/protocol-buffers/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. // Author: kenton@google.com (Kenton Varda)
  31. //
  32. // Deals with the fact that hash_map is not defined everywhere.
  33. #ifndef GOOGLE_PROTOBUF_STUBS_HASH_H__
  34. #define GOOGLE_PROTOBUF_STUBS_HASH_H__
  35. #include <string.h>
  36. #include <google/protobuf/stubs/common.h>
  37. #define GOOGLE_PROTOBUF_HAVE_HASH_MAP 1
  38. #define GOOGLE_PROTOBUF_HAVE_HASH_SET 1
  39. // Use C++11 unordered_{map|set} if available.
  40. #if ((defined(_LIBCPP_STD_VER) && _LIBCPP_STD_VER >= 11) || \
  41. (((__cplusplus >= 201103L) || defined(__GXX_EXPERIMENTAL_CXX0X)) && \
  42. (__GLIBCXX__ > 20090421)))
  43. # define GOOGLE_PROTOBUF_HAS_CXX11_HASH
  44. // For XCode >= 4.6: the compiler is clang with libc++.
  45. // For earlier XCode version: the compiler is gcc-4.2.1 with libstdc++.
  46. // libc++ provides <unordered_map> and friends even in non C++11 mode,
  47. // and it does not provide the tr1 library. Therefore the following macro
  48. // checks against this special case.
  49. // Note that we should not test the __APPLE_CC__ version number or the
  50. // __clang__ macro, since the new compiler can still use -stdlib=libstdc++, in
  51. // which case <unordered_map> is not compilable without -std=c++11
  52. #elif defined(__APPLE_CC__)
  53. # if __GNUC__ >= 4
  54. # define GOOGLE_PROTOBUF_HAS_TR1
  55. # else
  56. // Not tested for gcc < 4... These setting can compile under 4.2.1 though.
  57. # define GOOGLE_PROTOBUF_HASH_NAMESPACE __gnu_cxx
  58. # include <ext/hash_map>
  59. # define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
  60. # include <ext/hash_set>
  61. # define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
  62. # endif
  63. // Version checks for gcc.
  64. #elif defined(__GNUC__)
  65. // For GCC 4.x+, use tr1::unordered_map/set; otherwise, follow the
  66. // instructions from:
  67. // https://gcc.gnu.org/onlinedocs/libstdc++/manual/backwards.html
  68. # if __GNUC__ >= 4
  69. # define GOOGLE_PROTOBUF_HAS_TR1
  70. # elif __GNUC__ >= 3
  71. # include <backward/hash_map>
  72. # define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
  73. # include <backward/hash_set>
  74. # define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
  75. # if __GNUC__ == 3 && __GNUC_MINOR__ == 0
  76. # define GOOGLE_PROTOBUF_HASH_NAMESPACE std // GCC 3.0
  77. # else
  78. # define GOOGLE_PROTOBUF_HASH_NAMESPACE __gnu_cxx // GCC 3.1 and later
  79. # endif
  80. # else
  81. # define GOOGLE_PROTOBUF_HASH_NAMESPACE
  82. # include <hash_map>
  83. # define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
  84. # include <hash_set>
  85. # define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
  86. # endif
  87. // GCC <= 4.1 does not define std::tr1::hash for `long long int` or `long long unsigned int`
  88. # if __GNUC__ == 4 && defined(__GNUC_MINOR__) && __GNUC_MINOR__ <= 1
  89. # undef GOOGLE_PROTOBUF_HAS_TR1
  90. # undef GOOGLE_PROTOBUF_HAVE_HASH_MAP
  91. # undef GOOGLE_PROTOBUF_HAVE_HASH_SET
  92. # endif
  93. // Version checks for MSC.
  94. // Apparently Microsoft decided to move hash_map *back* to the std namespace in
  95. // MSVC 2010:
  96. // http://blogs.msdn.com/vcblog/archive/2009/05/25/stl-breaking-changes-in-visual-studio-2010-beta-1.aspx
  97. // And.. they are moved back to stdext in MSVC 2013 (haven't checked 2012). That
  98. // said, use unordered_map for MSVC 2010 and beyond is our safest bet.
  99. #elif defined(_MSC_VER)
  100. # if _MSC_VER >= 1600 // Since Visual Studio 2010
  101. # define GOOGLE_PROTOBUF_HAS_CXX11_HASH
  102. # define GOOGLE_PROTOBUF_HASH_COMPARE std::hash_compare
  103. # elif _MSC_VER >= 1500 // Since Visual Studio 2008
  104. # define GOOGLE_PROTOBUF_HASH_NAMESPACE stdext
  105. # include <hash_map>
  106. # define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
  107. # include <hash_set>
  108. # define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
  109. # define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare
  110. # define GOOGLE_PROTOBUF_CONTAINERS_NEED_HASH_COMPARE
  111. # elif _MSC_VER >= 1310
  112. # define GOOGLE_PROTOBUF_HASH_NAMESPACE stdext
  113. # include <hash_map>
  114. # define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
  115. # include <hash_set>
  116. # define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
  117. # define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare
  118. # else
  119. # define GOOGLE_PROTOBUF_HASH_NAMESPACE std
  120. # include <hash_map>
  121. # define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
  122. # include <hash_set>
  123. # define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
  124. # define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare
  125. # endif
  126. // **ADD NEW COMPILERS SUPPORT HERE.**
  127. // For other compilers, undefine the macro and fallback to use std::map, in
  128. // google/protobuf/stubs/hash.h
  129. #else
  130. # undef GOOGLE_PROTOBUF_HAVE_HASH_MAP
  131. # undef GOOGLE_PROTOBUF_HAVE_HASH_SET
  132. #endif
  133. #if defined(GOOGLE_PROTOBUF_HAS_CXX11_HASH)
  134. # define GOOGLE_PROTOBUF_HASH_NAMESPACE std
  135. # include <unordered_map>
  136. # define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map
  137. # include <unordered_set>
  138. # define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set
  139. #elif defined(GOOGLE_PROTOBUF_HAS_TR1)
  140. # define GOOGLE_PROTOBUF_HASH_NAMESPACE std::tr1
  141. # include <tr1/unordered_map>
  142. # define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map
  143. # include <tr1/unordered_set>
  144. # define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set
  145. #endif
  146. # define GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START \
  147. namespace google { \
  148. namespace protobuf {
  149. # define GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END }}
  150. #undef GOOGLE_PROTOBUF_HAS_CXX11_HASH
  151. #undef GOOGLE_PROTOBUF_HAS_TR1
  152. #if defined(GOOGLE_PROTOBUF_HAVE_HASH_MAP) && \
  153. defined(GOOGLE_PROTOBUF_HAVE_HASH_SET)
  154. #else
  155. #define GOOGLE_PROTOBUF_MISSING_HASH
  156. #include <map>
  157. #include <set>
  158. #endif
  159. namespace google {
  160. namespace protobuf {
  161. #ifdef GOOGLE_PROTOBUF_MISSING_HASH
  162. #undef GOOGLE_PROTOBUF_MISSING_HASH
  163. // This system doesn't have hash_map or hash_set. Emulate them using map and
  164. // set.
  165. // Make hash<T> be the same as less<T>. Note that everywhere where custom
  166. // hash functions are defined in the protobuf code, they are also defined such
  167. // that they can be used as "less" functions, which is required by MSVC anyway.
  168. template <typename Key>
  169. struct hash {
  170. // Dummy, just to make derivative hash functions compile.
  171. int operator()(const Key& key) {
  172. GOOGLE_LOG(FATAL) << "Should never be called.";
  173. return 0;
  174. }
  175. inline bool operator()(const Key& a, const Key& b) const {
  176. return a < b;
  177. }
  178. };
  179. // Make sure char* is compared by value.
  180. template <>
  181. struct hash<const char*> {
  182. // Dummy, just to make derivative hash functions compile.
  183. int operator()(const char* key) {
  184. GOOGLE_LOG(FATAL) << "Should never be called.";
  185. return 0;
  186. }
  187. inline bool operator()(const char* a, const char* b) const {
  188. return strcmp(a, b) < 0;
  189. }
  190. };
  191. template <typename Key, typename Data,
  192. typename HashFcn = hash<Key>,
  193. typename EqualKey = std::equal_to<Key>,
  194. typename Alloc = std::allocator< std::pair<const Key, Data> > >
  195. class hash_map : public std::map<Key, Data, HashFcn, Alloc> {
  196. typedef std::map<Key, Data, HashFcn, Alloc> BaseClass;
  197. public:
  198. hash_map(int a = 0, const HashFcn& b = HashFcn(),
  199. const EqualKey& c = EqualKey(),
  200. const Alloc& d = Alloc()) : BaseClass(b, d) {}
  201. HashFcn hash_function() const { return HashFcn(); }
  202. };
  203. template <typename Key,
  204. typename HashFcn = hash<Key>,
  205. typename EqualKey = std::equal_to<Key> >
  206. class hash_set : public std::set<Key, HashFcn> {
  207. public:
  208. hash_set(int = 0) {}
  209. HashFcn hash_function() const { return HashFcn(); }
  210. };
  211. #elif defined(_MSC_VER) && !defined(_STLPORT_VERSION) && \
  212. !(defined(_LIBCPP_STD_VER) && _LIBCPP_STD_VER >= 11)
  213. template <typename Key>
  214. struct hash : public GOOGLE_PROTOBUF_HASH_COMPARE<Key> {
  215. };
  216. // MSVC's hash_compare<const char*> hashes based on the string contents but
  217. // compares based on the string pointer. WTF?
  218. class CstringLess {
  219. public:
  220. inline bool operator()(const char* a, const char* b) const {
  221. return strcmp(a, b) < 0;
  222. }
  223. };
  224. template <>
  225. struct hash<const char*>
  226. : public GOOGLE_PROTOBUF_HASH_COMPARE<const char*, CstringLess> {};
  227. #ifdef GOOGLE_PROTOBUF_CONTAINERS_NEED_HASH_COMPARE
  228. template <typename Key, typename HashFcn, typename EqualKey>
  229. struct InternalHashCompare : public GOOGLE_PROTOBUF_HASH_COMPARE<Key> {
  230. InternalHashCompare() {}
  231. InternalHashCompare(HashFcn hashfcn, EqualKey equalkey)
  232. : hashfcn_(hashfcn), equalkey_(equalkey) {}
  233. size_t operator()(const Key& key) const { return hashfcn_(key); }
  234. bool operator()(const Key& key1, const Key& key2) const {
  235. return !equalkey_(key1, key2);
  236. }
  237. HashFcn hashfcn_;
  238. EqualKey equalkey_;
  239. };
  240. template <typename Key, typename Data,
  241. typename HashFcn = hash<Key>,
  242. typename EqualKey = std::equal_to<Key>,
  243. typename Alloc = std::allocator< std::pair<const Key, Data> > >
  244. class hash_map
  245. : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
  246. Key, Data, InternalHashCompare<Key, HashFcn, EqualKey>, Alloc> {
  247. typedef GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
  248. Key, Data, InternalHashCompare<Key, HashFcn, EqualKey>, Alloc> BaseClass;
  249. public:
  250. hash_map(int a = 0, const HashFcn& b = HashFcn(),
  251. const EqualKey& c = EqualKey(), const Alloc& d = Alloc())
  252. : BaseClass(InternalHashCompare<Key, HashFcn, EqualKey>(b, c), d) {}
  253. HashFcn hash_function() const { return HashFcn(); }
  254. };
  255. template <typename Key, typename HashFcn = hash<Key>,
  256. typename EqualKey = std::equal_to<Key> >
  257. class hash_set
  258. : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS<
  259. Key, InternalHashCompare<Key, HashFcn, EqualKey> > {
  260. public:
  261. hash_set(int = 0) {}
  262. HashFcn hash_function() const { return HashFcn(); }
  263. };
  264. #else // GOOGLE_PROTOBUF_CONTAINERS_NEED_HASH_COMPARE
  265. template <typename Key, typename Data,
  266. typename HashFcn = hash<Key>,
  267. typename EqualKey = std::equal_to<Key>,
  268. typename Alloc = std::allocator< std::pair<const Key, Data> > >
  269. class hash_map
  270. : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
  271. Key, Data, HashFcn, EqualKey, Alloc> {
  272. typedef GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
  273. Key, Data, HashFcn, EqualKey, Alloc> BaseClass;
  274. public:
  275. hash_map(int a = 0, const HashFcn& b = HashFcn(),
  276. const EqualKey& c = EqualKey(),
  277. const Alloc& d = Alloc()) : BaseClass(a, b, c, d) {}
  278. HashFcn hash_function() const { return HashFcn(); }
  279. };
  280. template <typename Key, typename HashFcn = hash<Key>,
  281. typename EqualKey = std::equal_to<Key> >
  282. class hash_set
  283. : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS<
  284. Key, HashFcn, EqualKey> {
  285. public:
  286. hash_set(int = 0) {}
  287. HashFcn hash_function() const { return HashFcn(); }
  288. };
  289. #endif // GOOGLE_PROTOBUF_CONTAINERS_NEED_HASH_COMPARE
  290. #else // defined(_MSC_VER) && !defined(_STLPORT_VERSION)
  291. template <typename Key>
  292. struct hash : public GOOGLE_PROTOBUF_HASH_NAMESPACE::hash<Key> {
  293. };
  294. template <typename Key>
  295. struct hash<const Key*> {
  296. inline size_t operator()(const Key* key) const {
  297. return reinterpret_cast<size_t>(key);
  298. }
  299. };
  300. // Unlike the old SGI version, the TR1 "hash" does not special-case char*. So,
  301. // we go ahead and provide our own implementation.
  302. template <>
  303. struct hash<const char*> {
  304. inline size_t operator()(const char* str) const {
  305. size_t result = 0;
  306. for (; *str != '\0'; str++) {
  307. result = 5 * result + static_cast<size_t>(*str);
  308. }
  309. return result;
  310. }
  311. };
  312. template<>
  313. struct hash<bool> {
  314. size_t operator()(bool x) const {
  315. return static_cast<size_t>(x);
  316. }
  317. };
  318. template <typename Key, typename Data,
  319. typename HashFcn = hash<Key>,
  320. typename EqualKey = std::equal_to<Key>,
  321. typename Alloc = std::allocator< std::pair<const Key, Data> > >
  322. class hash_map
  323. : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
  324. Key, Data, HashFcn, EqualKey, Alloc> {
  325. typedef GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
  326. Key, Data, HashFcn, EqualKey, Alloc> BaseClass;
  327. public:
  328. hash_map(int a = 0, const HashFcn& b = HashFcn(),
  329. const EqualKey& c = EqualKey(),
  330. const Alloc& d = Alloc()) : BaseClass(a, b, c, d) {}
  331. HashFcn hash_function() const { return HashFcn(); }
  332. };
  333. template <typename Key, typename HashFcn = hash<Key>,
  334. typename EqualKey = std::equal_to<Key> >
  335. class hash_set
  336. : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS<
  337. Key, HashFcn, EqualKey> {
  338. public:
  339. hash_set(int = 0) {}
  340. HashFcn hash_function() const { return HashFcn(); }
  341. };
  342. #endif // !GOOGLE_PROTOBUF_MISSING_HASH
  343. template <>
  344. struct hash<string> {
  345. inline size_t operator()(const string& key) const {
  346. return hash<const char*>()(key.c_str());
  347. }
  348. static const size_t bucket_size = 4;
  349. static const size_t min_buckets = 8;
  350. inline bool operator()(const string& a, const string& b) const {
  351. return a < b;
  352. }
  353. };
  354. template <typename First, typename Second>
  355. struct hash<std::pair<First, Second> > {
  356. inline size_t operator()(const std::pair<First, Second>& key) const {
  357. size_t first_hash = hash<First>()(key.first);
  358. size_t second_hash = hash<Second>()(key.second);
  359. // FIXME(kenton): What is the best way to compute this hash? I have
  360. // no idea! This seems a bit better than an XOR.
  361. return first_hash * ((1 << 16) - 1) + second_hash;
  362. }
  363. static const size_t bucket_size = 4;
  364. static const size_t min_buckets = 8;
  365. inline bool operator()(const std::pair<First, Second>& a,
  366. const std::pair<First, Second>& b) const {
  367. return a < b;
  368. }
  369. };
  370. // Used by GCC/SGI STL only. (Why isn't this provided by the standard
  371. // library? :( )
  372. struct streq {
  373. inline bool operator()(const char* a, const char* b) const {
  374. return strcmp(a, b) == 0;
  375. }
  376. };
  377. } // namespace protobuf
  378. } // namespace google
  379. #endif // GOOGLE_PROTOBUF_STUBS_HASH_H__