blob: 33b7b91ab2fcbd8963fde20a8df6b873e76fa371 [file] [log] [blame]
temporal40ee5512008-07-10 02:12:20 +00001// Protocol Buffers - Google's data interchange format
kenton@google.com24bf56f2008-09-24 20:31:01 +00002// Copyright 2008 Google Inc. All rights reserved.
Feng Xiaoe4288622014-10-01 16:26:23 -07003// https://developers.google.com/protocol-buffers/
temporal40ee5512008-07-10 02:12:20 +00004//
kenton@google.com24bf56f2008-09-24 20:31:01 +00005// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
temporal40ee5512008-07-10 02:12:20 +00008//
kenton@google.com24bf56f2008-09-24 20:31:01 +00009// * 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.
temporal40ee5512008-07-10 02:12:20 +000018//
kenton@google.com24bf56f2008-09-24 20:31:01 +000019// 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.
temporal40ee5512008-07-10 02:12:20 +000030
31// Author: kenton@google.com (Kenton Varda)
32//
33// Deals with the fact that hash_map is not defined everywhere.
34
35#ifndef GOOGLE_PROTOBUF_STUBS_HASH_H__
36#define GOOGLE_PROTOBUF_STUBS_HASH_H__
37
38#include <string.h>
39#include <google/protobuf/stubs/common.h>
Jisi Liudf184fb2015-02-25 15:28:44 -080040#include <google/protobuf/stubs/pbconfig.h>
temporal40ee5512008-07-10 02:12:20 +000041
Jisi Liudf184fb2015-02-25 15:28:44 -080042#if defined(GOOGLE_PROTOBUF_HAVE_HASH_MAP) && \
43 defined(GOOGLE_PROTOBUF_HAVE_HASH_SET)
44#include GOOGLE_PROTOBUF_HASH_MAP_H
45#include GOOGLE_PROTOBUF_HASH_SET_H
temporal40ee5512008-07-10 02:12:20 +000046#else
Jisi Liudf184fb2015-02-25 15:28:44 -080047#define GOOGLE_PROTOBUF_MISSING_HASH
kenton@google.com44103962008-09-19 16:53:32 +000048#include <map>
49#include <set>
temporal40ee5512008-07-10 02:12:20 +000050#endif
51
52namespace google {
53namespace protobuf {
54
Jisi Liudf184fb2015-02-25 15:28:44 -080055#ifdef GOOGLE_PROTOBUF_MISSING_HASH
kenton@google.com44103962008-09-19 16:53:32 +000056
57// This system doesn't have hash_map or hash_set. Emulate them using map and
58// set.
59
60// Make hash<T> be the same as less<T>. Note that everywhere where custom
61// hash functions are defined in the protobuf code, they are also defined such
62// that they can be used as "less" functions, which is required by MSVC anyway.
63template <typename Key>
64struct hash {
65 // Dummy, just to make derivative hash functions compile.
66 int operator()(const Key& key) {
67 GOOGLE_LOG(FATAL) << "Should never be called.";
68 return 0;
69 }
70
71 inline bool operator()(const Key& a, const Key& b) const {
72 return a < b;
73 }
74};
75
76// Make sure char* is compared by value.
77template <>
78struct hash<const char*> {
79 // Dummy, just to make derivative hash functions compile.
80 int operator()(const char* key) {
81 GOOGLE_LOG(FATAL) << "Should never be called.";
82 return 0;
83 }
84
85 inline bool operator()(const char* a, const char* b) const {
86 return strcmp(a, b) < 0;
87 }
88};
89
90template <typename Key, typename Data,
91 typename HashFcn = hash<Key>,
92 typename EqualKey = int >
93class hash_map : public std::map<Key, Data, HashFcn> {
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000094 public:
95 hash_map(int = 0) {}
kenton@google.com44103962008-09-19 16:53:32 +000096};
97
98template <typename Key,
99 typename HashFcn = hash<Key>,
100 typename EqualKey = int >
101class hash_set : public std::set<Key, HashFcn> {
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000102 public:
103 hash_set(int = 0) {}
kenton@google.com44103962008-09-19 16:53:32 +0000104};
105
kenton@google.com3aa7a0d2009-08-17 20:34:29 +0000106#elif defined(_MSC_VER) && !defined(_STLPORT_VERSION)
temporal40ee5512008-07-10 02:12:20 +0000107
108template <typename Key>
Jisi Liudf184fb2015-02-25 15:28:44 -0800109struct hash : public GOOGLE_PROTOBUF_HASH_NAMESPACE::hash_compare<Key> {
temporal40ee5512008-07-10 02:12:20 +0000110};
111
112// MSVC's hash_compare<const char*> hashes based on the string contents but
113// compares based on the string pointer. WTF?
114class CstringLess {
115 public:
116 inline bool operator()(const char* a, const char* b) const {
117 return strcmp(a, b) < 0;
118 }
119};
120
121template <>
122struct hash<const char*>
Jisi Liudf184fb2015-02-25 15:28:44 -0800123 : public GOOGLE_PROTOBUF_HASH_NAMESPACE::hash_compare<
124 const char*, CstringLess> {};
temporal40ee5512008-07-10 02:12:20 +0000125
126template <typename Key, typename Data,
127 typename HashFcn = hash<Key>,
128 typename EqualKey = int >
Jisi Liudf184fb2015-02-25 15:28:44 -0800129class hash_map : public GOOGLE_PROTOBUF_HASH_NAMESPACE::hash_map<
temporal40ee5512008-07-10 02:12:20 +0000130 Key, Data, HashFcn> {
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000131 public:
132 hash_map(int = 0) {}
temporal40ee5512008-07-10 02:12:20 +0000133};
134
135template <typename Key,
136 typename HashFcn = hash<Key>,
137 typename EqualKey = int >
Jisi Liudf184fb2015-02-25 15:28:44 -0800138class hash_set : public GOOGLE_PROTOBUF_HASH_NAMESPACE::hash_set<
temporal40ee5512008-07-10 02:12:20 +0000139 Key, HashFcn> {
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000140 public:
141 hash_set(int = 0) {}
temporal40ee5512008-07-10 02:12:20 +0000142};
143
144#else
145
146template <typename Key>
Jisi Liudf184fb2015-02-25 15:28:44 -0800147struct hash : public GOOGLE_PROTOBUF_HASH_NAMESPACE::hash<Key> {
temporal40ee5512008-07-10 02:12:20 +0000148};
149
150template <typename Key>
151struct hash<const Key*> {
152 inline size_t operator()(const Key* key) const {
153 return reinterpret_cast<size_t>(key);
154 }
155};
156
kenton@google.comee7e9422009-12-21 18:58:23 +0000157// Unlike the old SGI version, the TR1 "hash" does not special-case char*. So,
158// we go ahead and provide our own implementation.
temporal40ee5512008-07-10 02:12:20 +0000159template <>
kenton@google.comee7e9422009-12-21 18:58:23 +0000160struct hash<const char*> {
161 inline size_t operator()(const char* str) const {
162 size_t result = 0;
163 for (; *str != '\0'; str++) {
164 result = 5 * result + *str;
165 }
166 return result;
167 }
temporal40ee5512008-07-10 02:12:20 +0000168};
169
Jisi Liudf184fb2015-02-25 15:28:44 -0800170template <typename Key, typename Data, typename HashFcn = hash<Key>,
Jisi Liu885b6122015-02-28 14:51:22 -0800171 typename EqualKey = std::equal_to<Key>,
172 typename Alloc = std::allocator< std::pair<const Key, Data> > >
Jisi Liudf184fb2015-02-25 15:28:44 -0800173class hash_map
174 : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
Jisi Liu885b6122015-02-28 14:51:22 -0800175 Key, Data, HashFcn, EqualKey, Alloc> {
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000176 public:
Jisi Liu885b6122015-02-28 14:51:22 -0800177 hash_map(int = 0, const HashFcn& = HashFcn(), const EqualKey& = EqualKey(),
178 const Alloc& = Alloc()) {}
temporal40ee5512008-07-10 02:12:20 +0000179};
180
Jisi Liudf184fb2015-02-25 15:28:44 -0800181template <typename Key, typename HashFcn = hash<Key>,
temporal40ee5512008-07-10 02:12:20 +0000182 typename EqualKey = std::equal_to<Key> >
Jisi Liudf184fb2015-02-25 15:28:44 -0800183class hash_set
184 : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS<
185 Key, HashFcn, EqualKey> {
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000186 public:
187 hash_set(int = 0) {}
temporal40ee5512008-07-10 02:12:20 +0000188};
189
Jisi Liudf184fb2015-02-25 15:28:44 -0800190#undef GOOGLE_PROTOBUF_MISSING_HASH
191#endif // !GOOGLE_PROTOBUF_MISSING_HASH
temporal40ee5512008-07-10 02:12:20 +0000192
193template <>
194struct hash<string> {
195 inline size_t operator()(const string& key) const {
196 return hash<const char*>()(key.c_str());
197 }
198
199 static const size_t bucket_size = 4;
200 static const size_t min_buckets = 8;
201 inline size_t operator()(const string& a, const string& b) const {
202 return a < b;
203 }
204};
205
kenton@google.comd37d46d2009-04-25 02:53:47 +0000206template <typename First, typename Second>
207struct hash<pair<First, Second> > {
208 inline size_t operator()(const pair<First, Second>& key) const {
209 size_t first_hash = hash<First>()(key.first);
210 size_t second_hash = hash<Second>()(key.second);
211
212 // FIXME(kenton): What is the best way to compute this hash? I have
213 // no idea! This seems a bit better than an XOR.
214 return first_hash * ((1 << 16) - 1) + second_hash;
215 }
216
217 static const size_t bucket_size = 4;
218 static const size_t min_buckets = 8;
219 inline size_t operator()(const pair<First, Second>& a,
220 const pair<First, Second>& b) const {
221 return a < b;
222 }
223};
224
225// Used by GCC/SGI STL only. (Why isn't this provided by the standard
226// library? :( )
227struct streq {
228 inline bool operator()(const char* a, const char* b) const {
229 return strcmp(a, b) == 0;
230 }
231};
232
temporal40ee5512008-07-10 02:12:20 +0000233} // namespace protobuf
234} // namespace google
235
236#endif // GOOGLE_PROTOBUF_STUBS_HASH_H__