blob: 27b83ed49b17c4d57f36471ae7fcae3e8593d31e [file] [log] [blame]
temporal40ee5512008-07-10 02:12:20 +00001// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc.
3// http://code.google.com/p/protobuf/
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17// Author: kenton@google.com (Kenton Varda)
18//
19// Deals with the fact that hash_map is not defined everywhere.
20
21#ifndef GOOGLE_PROTOBUF_STUBS_HASH_H__
22#define GOOGLE_PROTOBUF_STUBS_HASH_H__
23
24#include <string.h>
25#include <google/protobuf/stubs/common.h>
26#include "config.h"
27
28#if defined(HAVE_HASH_MAP) && defined(HAVE_HASH_SET)
29#include HASH_MAP_H
30#include HASH_SET_H
31#else
kenton@google.com44103962008-09-19 16:53:32 +000032#define MISSING_HASH
33#include <map>
34#include <set>
temporal40ee5512008-07-10 02:12:20 +000035#endif
36
37namespace google {
38namespace protobuf {
39
kenton@google.com44103962008-09-19 16:53:32 +000040#ifdef MISSING_HASH
41
42// This system doesn't have hash_map or hash_set. Emulate them using map and
43// set.
44
45// Make hash<T> be the same as less<T>. Note that everywhere where custom
46// hash functions are defined in the protobuf code, they are also defined such
47// that they can be used as "less" functions, which is required by MSVC anyway.
48template <typename Key>
49struct hash {
50 // Dummy, just to make derivative hash functions compile.
51 int operator()(const Key& key) {
52 GOOGLE_LOG(FATAL) << "Should never be called.";
53 return 0;
54 }
55
56 inline bool operator()(const Key& a, const Key& b) const {
57 return a < b;
58 }
59};
60
61// Make sure char* is compared by value.
62template <>
63struct hash<const char*> {
64 // Dummy, just to make derivative hash functions compile.
65 int operator()(const char* key) {
66 GOOGLE_LOG(FATAL) << "Should never be called.";
67 return 0;
68 }
69
70 inline bool operator()(const char* a, const char* b) const {
71 return strcmp(a, b) < 0;
72 }
73};
74
75template <typename Key, typename Data,
76 typename HashFcn = hash<Key>,
77 typename EqualKey = int >
78class hash_map : public std::map<Key, Data, HashFcn> {
79};
80
81template <typename Key,
82 typename HashFcn = hash<Key>,
83 typename EqualKey = int >
84class hash_set : public std::set<Key, HashFcn> {
85};
86
87#elif defined(_MSC_VER)
temporal40ee5512008-07-10 02:12:20 +000088
89template <typename Key>
90struct hash : public HASH_NAMESPACE::hash_compare<Key> {
91};
92
93// MSVC's hash_compare<const char*> hashes based on the string contents but
94// compares based on the string pointer. WTF?
95class CstringLess {
96 public:
97 inline bool operator()(const char* a, const char* b) const {
98 return strcmp(a, b) < 0;
99 }
100};
101
102template <>
103struct hash<const char*>
104 : public HASH_NAMESPACE::hash_compare<const char*, CstringLess> {
105};
106
107template <typename Key, typename Data,
108 typename HashFcn = hash<Key>,
109 typename EqualKey = int >
110class hash_map : public HASH_NAMESPACE::hash_map<
111 Key, Data, HashFcn> {
112};
113
114template <typename Key,
115 typename HashFcn = hash<Key>,
116 typename EqualKey = int >
117class hash_set : public HASH_NAMESPACE::hash_set<
118 Key, HashFcn> {
119};
120
121#else
122
123template <typename Key>
124struct hash : public HASH_NAMESPACE::hash<Key> {
125};
126
127template <typename Key>
128struct hash<const Key*> {
129 inline size_t operator()(const Key* key) const {
130 return reinterpret_cast<size_t>(key);
131 }
132};
133
134template <>
135struct hash<const char*> : public HASH_NAMESPACE::hash<const char*> {
136};
137
138template <typename Key, typename Data,
139 typename HashFcn = hash<Key>,
140 typename EqualKey = std::equal_to<Key> >
141class hash_map : public HASH_NAMESPACE::hash_map<
142 Key, Data, HashFcn, EqualKey> {
143};
144
145template <typename Key,
146 typename HashFcn = hash<Key>,
147 typename EqualKey = std::equal_to<Key> >
148class hash_set : public HASH_NAMESPACE::hash_set<
149 Key, HashFcn, EqualKey> {
150};
151
152#endif
153
154template <>
155struct hash<string> {
156 inline size_t operator()(const string& key) const {
157 return hash<const char*>()(key.c_str());
158 }
159
160 static const size_t bucket_size = 4;
161 static const size_t min_buckets = 8;
162 inline size_t operator()(const string& a, const string& b) const {
163 return a < b;
164 }
165};
166
167} // namespace protobuf
168} // namespace google
169
170#endif // GOOGLE_PROTOBUF_STUBS_HASH_H__