1 | // Licensed to the Apache Software Foundation (ASF) under one |
2 | // or more contributor license agreements. See the NOTICE file |
3 | // distributed with this work for additional information |
4 | // regarding copyright ownership. The ASF licenses this file |
5 | // to you under the Apache License, Version 2.0 (the |
6 | // "License"); you may not use this file except in compliance |
7 | // with the License. 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, |
12 | // software distributed under the License is distributed on an |
13 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | // KIND, either express or implied. See the License for the |
15 | // specific language governing permissions and limitations |
16 | // under the License. |
17 | |
18 | // Date: Sun Dec 4 14:57:27 CST 2016 |
19 | |
20 | #ifndef BUTIL_CASE_IGNORED_FLAT_MAP_H |
21 | #define BUTIL_CASE_IGNORED_FLAT_MAP_H |
22 | |
23 | #include "butil/containers/flat_map.h" |
24 | |
25 | namespace butil { |
26 | |
27 | // NOTE: Using ascii_tolower instead of ::tolower shortens 150ns in |
28 | // FlatMapTest.perf_small_string_map (with -O2 added, -O0 by default) |
29 | inline char ascii_tolower(char c) { |
30 | extern const char* const g_tolower_map; |
31 | return g_tolower_map[(int)c]; |
32 | } |
33 | |
34 | struct CaseIgnoredHasher { |
35 | size_t operator()(const std::string& s) const { |
36 | std::size_t result = 0; |
37 | for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) { |
38 | result = result * 101 + ascii_tolower(*i); |
39 | } |
40 | return result; |
41 | } |
42 | size_t operator()(const char* s) const { |
43 | std::size_t result = 0; |
44 | for (; *s; ++s) { |
45 | result = result * 101 + ascii_tolower(*s); |
46 | } |
47 | return result; |
48 | } |
49 | }; |
50 | |
51 | struct CaseIgnoredEqual { |
52 | // NOTE: No overload for butil::StringPiece. It needs strncasecmp |
53 | // which is much slower than strcasecmp in micro-benchmarking. As a |
54 | // result, methods in HttpHeader does not accept StringPiece as well. |
55 | bool operator()(const std::string& s1, const std::string& s2) const { |
56 | return s1.size() == s2.size() && |
57 | strcasecmp(s1.c_str(), s2.c_str()) == 0; |
58 | } |
59 | bool operator()(const std::string& s1, const char* s2) const |
60 | { return strcasecmp(s1.c_str(), s2) == 0; } |
61 | }; |
62 | |
63 | template <typename T> |
64 | class CaseIgnoredFlatMap : public butil::FlatMap< |
65 | std::string, T, CaseIgnoredHasher, CaseIgnoredEqual> {}; |
66 | |
67 | class CaseIgnoredFlatSet : public butil::FlatSet< |
68 | std::string, CaseIgnoredHasher, CaseIgnoredEqual> {}; |
69 | |
70 | } // namespace butil |
71 | |
72 | #endif // BUTIL_CASE_IGNORED_FLAT_MAP_H |
73 | |