case_ignored_flat_map.h 2.59 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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
17 18 19

// Date: Sun Dec  4 14:57:27 CST 2016

20 21
#ifndef BUTIL_CASE_IGNORED_FLAT_MAP_H
#define BUTIL_CASE_IGNORED_FLAT_MAP_H
gejun's avatar
gejun committed
22

23
#include "butil/containers/flat_map.h"
gejun's avatar
gejun committed
24

25
namespace butil {
gejun's avatar
gejun committed
26 27 28 29

// 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) {
30
    extern const signed char* const g_tolower_map;
gejun's avatar
gejun committed
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
    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 {
52
    // NOTE: No overload for butil::StringPiece. It needs strncasecmp
gejun's avatar
gejun committed
53 54 55 56 57 58 59 60 61 62 63
    // 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>
64
class CaseIgnoredFlatMap : public butil::FlatMap<
gejun's avatar
gejun committed
65 66
    std::string, T, CaseIgnoredHasher, CaseIgnoredEqual> {};

jamesge's avatar
jamesge committed
67
class CaseIgnoredFlatSet : public butil::FlatSet<
gejun's avatar
gejun committed
68 69
    std::string, CaseIgnoredHasher, CaseIgnoredEqual> {};

70
} // namespace butil
gejun's avatar
gejun committed
71

72
#endif  // BUTIL_CASE_IGNORED_FLAT_MAP_H