case_ignored_flat_map.h 2.42 KB
Newer Older
gejun's avatar
gejun committed
1
// Copyright (c) 2016 Baidu, Inc.
gejun's avatar
gejun committed
2 3 4 5 6 7 8 9 10 11 12 13
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
gejun's avatar
gejun committed
14

gejun's avatar
gejun committed
15
// Author: Ge,Jun (gejun@baidu.com)
gejun's avatar
gejun committed
16 17
// Date: Sun Dec  4 14:57:27 CST 2016

18 19
#ifndef BUTIL_CASE_IGNORED_FLAT_MAP_H
#define BUTIL_CASE_IGNORED_FLAT_MAP_H
gejun's avatar
gejun committed
20

21
#include "butil/containers/flat_map.h"
gejun's avatar
gejun committed
22

23
namespace butil {
gejun's avatar
gejun committed
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49

// NOTE: Using ascii_tolower instead of ::tolower shortens 150ns in
// FlatMapTest.perf_small_string_map (with -O2 added, -O0 by default)
inline char ascii_tolower(char c) {
    extern const char* const g_tolower_map;
    return g_tolower_map[(int)c];
}

struct CaseIgnoredHasher {
    size_t operator()(const std::string& s) const {
        std::size_t result = 0;                                               
        for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) {
            result = result * 101 + ascii_tolower(*i);
        }
        return result;
    }
    size_t operator()(const char* s) const {
        std::size_t result = 0;                                               
        for (; *s; ++s) {
            result = result * 101 + ascii_tolower(*s);
        }
        return result;
    }
};

struct CaseIgnoredEqual {
50
    // NOTE: No overload for butil::StringPiece. It needs strncasecmp
gejun's avatar
gejun committed
51 52 53 54 55 56 57 58 59 60 61
    // which is much slower than strcasecmp in micro-benchmarking. As a
    // result, methods in HttpHeader does not accept StringPiece as well.
    bool operator()(const std::string& s1, const std::string& s2) const {
        return s1.size() == s2.size() &&
            strcasecmp(s1.c_str(), s2.c_str()) == 0;
    }
    bool operator()(const std::string& s1, const char* s2) const
    { return strcasecmp(s1.c_str(), s2) == 0; }
};

template <typename T>
62
class CaseIgnoredFlatMap : public butil::FlatMap<
gejun's avatar
gejun committed
63 64
    std::string, T, CaseIgnoredHasher, CaseIgnoredEqual> {};

65
class CaseIgnoredFlatSet : public butil::FlatMap<
gejun's avatar
gejun committed
66 67
    std::string, CaseIgnoredHasher, CaseIgnoredEqual> {};

68
} // namespace butil
gejun's avatar
gejun committed
69

70
#endif  // BUTIL_CASE_IGNORED_FLAT_MAP_H