hash.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  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. Otherwise, libc++ always support
  40. // unordered_{map|set}
  41. #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X) || \
  42. defined(_LIBCPP_VERSION)
  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. // Version checks for MSC.
  88. // Apparently Microsoft decided to move hash_map *back* to the std namespace in
  89. // MSVC 2010:
  90. // http://blogs.msdn.com/vcblog/archive/2009/05/25/stl-breaking-changes-in-visual-studio-2010-beta-1.aspx
  91. // And.. they are moved back to stdext in MSVC 2013 (haven't checked 2012). That
  92. // said, use unordered_map for MSVC 2010 and beyond is our safest bet.
  93. #elif defined(_MSC_VER)
  94. # if _MSC_VER >= 1600 // Since Visual Studio 2010
  95. # define GOOGLE_PROTOBUF_HAS_CXX11_HASH
  96. # define GOOGLE_PROTOBUF_HASH_COMPARE std::hash_compare
  97. # elif _MSC_VER >= 1500 // Since Visual Studio 2008
  98. # undef GOOGLE_PROTOBUF_HAVE_HASH_MAP
  99. # undef GOOGLE_PROTOBUF_HAVE_HASH_SET
  100. # elif _MSC_VER >= 1310
  101. # define GOOGLE_PROTOBUF_HASH_NAMESPACE stdext
  102. # include <hash_map>
  103. # define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
  104. # include <hash_set>
  105. # define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
  106. # define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare
  107. # else
  108. # define GOOGLE_PROTOBUF_HASH_NAMESPACE std
  109. # include <hash_map>
  110. # define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
  111. # include <hash_set>
  112. # define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
  113. # define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare
  114. # endif
  115. // **ADD NEW COMPILERS SUPPORT HERE.**
  116. // For other compilers, undefine the macro and fallback to use std::map, in
  117. // google/protobuf/stubs/hash.h
  118. #else
  119. # undef GOOGLE_PROTOBUF_HAVE_HASH_MAP
  120. # undef GOOGLE_PROTOBUF_HAVE_HASH_SET
  121. #endif
  122. #if defined(GOOGLE_PROTOBUF_HAS_CXX11_HASH)
  123. # define GOOGLE_PROTOBUF_HASH_NAMESPACE std
  124. # include <unordered_map>
  125. # define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map
  126. # include <unordered_set>
  127. # define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set
  128. #elif defined(GOOGLE_PROTOBUF_HAS_TR1)
  129. # define GOOGLE_PROTOBUF_HASH_NAMESPACE std::tr1
  130. # include <tr1/unordered_map>
  131. # define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map
  132. # include <tr1/unordered_set>
  133. # define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set
  134. #endif
  135. # define GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START \
  136. namespace google { \
  137. namespace protobuf {
  138. # define GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END }}
  139. #undef GOOGLE_PROTOBUF_HAS_CXX11_HASH
  140. #undef GOOGLE_PROTOBUF_HAS_TR1
  141. #if defined(GOOGLE_PROTOBUF_HAVE_HASH_MAP) && \
  142. defined(GOOGLE_PROTOBUF_HAVE_HASH_SET)
  143. #else
  144. #define GOOGLE_PROTOBUF_MISSING_HASH
  145. #include <map>
  146. #include <set>
  147. #endif
  148. namespace google {
  149. namespace protobuf {
  150. #ifdef GOOGLE_PROTOBUF_MISSING_HASH
  151. #undef GOOGLE_PROTOBUF_MISSING_HASH
  152. // This system doesn't have hash_map or hash_set. Emulate them using map and
  153. // set.
  154. // Make hash<T> be the same as less<T>. Note that everywhere where custom
  155. // hash functions are defined in the protobuf code, they are also defined such
  156. // that they can be used as "less" functions, which is required by MSVC anyway.
  157. template <typename Key>
  158. struct hash {
  159. // Dummy, just to make derivative hash functions compile.
  160. int operator()(const Key& key) {
  161. GOOGLE_LOG(FATAL) << "Should never be called.";
  162. return 0;
  163. }
  164. inline bool operator()(const Key& a, const Key& b) const {
  165. return a < b;
  166. }
  167. };
  168. // Make sure char* is compared by value.
  169. template <>
  170. struct hash<const char*> {
  171. // Dummy, just to make derivative hash functions compile.
  172. int operator()(const char* key) {
  173. GOOGLE_LOG(FATAL) << "Should never be called.";
  174. return 0;
  175. }
  176. inline bool operator()(const char* a, const char* b) const {
  177. return strcmp(a, b) < 0;
  178. }
  179. };
  180. template <typename Key, typename Data,
  181. typename HashFcn = hash<Key>,
  182. typename EqualKey = std::equal_to<Key>,
  183. typename Alloc = std::allocator< std::pair<const Key, Data> > >
  184. class hash_map : public std::map<Key, Data, HashFcn, Alloc> {
  185. typedef std::map<Key, Data, HashFcn, Alloc> BaseClass;
  186. public:
  187. hash_map(int a = 0, const HashFcn& b = HashFcn(),
  188. const EqualKey& c = EqualKey(),
  189. const Alloc& d = Alloc()) : BaseClass(b, d) {}
  190. };
  191. template <typename Key,
  192. typename HashFcn = hash<Key>,
  193. typename EqualKey = std::equal_to<Key> >
  194. class hash_set : public std::set<Key, HashFcn> {
  195. public:
  196. hash_set(int = 0) {}
  197. };
  198. #elif defined(_MSC_VER) && !defined(_STLPORT_VERSION)
  199. template <typename Key>
  200. struct hash : public GOOGLE_PROTOBUF_HASH_COMPARE<Key> {
  201. };
  202. // MSVC's hash_compare<const char*> hashes based on the string contents but
  203. // compares based on the string pointer. WTF?
  204. class CstringLess {
  205. public:
  206. inline bool operator()(const char* a, const char* b) const {
  207. return strcmp(a, b) < 0;
  208. }
  209. };
  210. template <>
  211. struct hash<const char*>
  212. : public GOOGLE_PROTOBUF_HASH_COMPARE<const char*, CstringLess> {};
  213. template <typename Key, typename Data,
  214. typename HashFcn = hash<Key>,
  215. typename EqualKey = std::equal_to<Key>,
  216. typename Alloc = std::allocator< std::pair<const Key, Data> > >
  217. class hash_map
  218. : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
  219. Key, Data, HashFcn, EqualKey, Alloc> {
  220. typedef GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
  221. Key, Data, HashFcn, EqualKey, Alloc> BaseClass;
  222. public:
  223. hash_map(int a = 0, const HashFcn& b = HashFcn(),
  224. const EqualKey& c = EqualKey(),
  225. const Alloc& d = Alloc()) : BaseClass(a, b, c, d) {}
  226. };
  227. template <typename Key, typename HashFcn = hash<Key>,
  228. typename EqualKey = std::equal_to<Key> >
  229. class hash_set
  230. : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS<
  231. Key, HashFcn, EqualKey> {
  232. public:
  233. hash_set(int = 0) {}
  234. };
  235. #else
  236. template <typename Key>
  237. struct hash : public GOOGLE_PROTOBUF_HASH_NAMESPACE::hash<Key> {
  238. };
  239. template <typename Key>
  240. struct hash<const Key*> {
  241. inline size_t operator()(const Key* key) const {
  242. return reinterpret_cast<size_t>(key);
  243. }
  244. };
  245. // Unlike the old SGI version, the TR1 "hash" does not special-case char*. So,
  246. // we go ahead and provide our own implementation.
  247. template <>
  248. struct hash<const char*> {
  249. inline size_t operator()(const char* str) const {
  250. size_t result = 0;
  251. for (; *str != '\0'; str++) {
  252. result = 5 * result + *str;
  253. }
  254. return result;
  255. }
  256. };
  257. template<>
  258. struct hash<bool> {
  259. size_t operator()(bool x) const {
  260. return static_cast<size_t>(x);
  261. }
  262. };
  263. template <typename Key, typename Data,
  264. typename HashFcn = hash<Key>,
  265. typename EqualKey = std::equal_to<Key>,
  266. typename Alloc = std::allocator< std::pair<const Key, Data> > >
  267. class hash_map
  268. : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
  269. Key, Data, HashFcn, EqualKey, Alloc> {
  270. typedef GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
  271. Key, Data, HashFcn, EqualKey, Alloc> BaseClass;
  272. public:
  273. hash_map(int a = 0, const HashFcn& b = HashFcn(),
  274. const EqualKey& c = EqualKey(),
  275. const Alloc& d = Alloc()) : BaseClass(a, b, c, d) {}
  276. };
  277. template <typename Key, typename HashFcn = hash<Key>,
  278. typename EqualKey = std::equal_to<Key> >
  279. class hash_set
  280. : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS<
  281. Key, HashFcn, EqualKey> {
  282. public:
  283. hash_set(int = 0) {}
  284. };
  285. #endif // !GOOGLE_PROTOBUF_MISSING_HASH
  286. template <>
  287. struct hash<string> {
  288. inline size_t operator()(const string& key) const {
  289. return hash<const char*>()(key.c_str());
  290. }
  291. static const size_t bucket_size = 4;
  292. static const size_t min_buckets = 8;
  293. inline bool operator()(const string& a, const string& b) const {
  294. return a < b;
  295. }
  296. };
  297. template <typename First, typename Second>
  298. struct hash<pair<First, Second> > {
  299. inline size_t operator()(const pair<First, Second>& key) const {
  300. size_t first_hash = hash<First>()(key.first);
  301. size_t second_hash = hash<Second>()(key.second);
  302. // FIXME(kenton): What is the best way to compute this hash? I have
  303. // no idea! This seems a bit better than an XOR.
  304. return first_hash * ((1 << 16) - 1) + second_hash;
  305. }
  306. static const size_t bucket_size = 4;
  307. static const size_t min_buckets = 8;
  308. inline bool operator()(const pair<First, Second>& a,
  309. const pair<First, Second>& b) const {
  310. return a < b;
  311. }
  312. };
  313. // Used by GCC/SGI STL only. (Why isn't this provided by the standard
  314. // library? :( )
  315. struct streq {
  316. inline bool operator()(const char* a, const char* b) const {
  317. return strcmp(a, b) == 0;
  318. }
  319. };
  320. } // namespace protobuf
  321. } // namespace google
  322. #endif // GOOGLE_PROTOBUF_STUBS_HASH_H__