2019-05-22 20:15:35 +00:00
|
|
|
/*
|
2020-07-20 16:35:17 +00:00
|
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
2019-05-22 20:15:35 +00:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*
|
2020-07-20 16:35:17 +00:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2019-05-22 20:15:35 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <algorithm>
|
2020-07-20 16:35:17 +00:00
|
|
|
#include <cassert>
|
2019-05-22 20:15:35 +00:00
|
|
|
#include <string>
|
|
|
|
|
|
|
|
#include <folly/Likely.h>
|
|
|
|
|
|
|
|
namespace folly {
|
|
|
|
|
|
|
|
namespace detail {
|
|
|
|
|
|
|
|
/***
|
|
|
|
* The qfind_first_byte_of_* functions are declared here, before Range.h, so
|
|
|
|
* they cannot take StringPiece values. But they're there to operate on
|
|
|
|
* StringPiece values. Dependency cycles: fun.
|
|
|
|
*
|
|
|
|
* StringPieceLite is here to break that dependency cycle.
|
|
|
|
*/
|
|
|
|
class StringPieceLite {
|
|
|
|
public:
|
|
|
|
StringPieceLite(const char* b, const char* e) : b_(b), e_(e) {}
|
|
|
|
template <typename Range>
|
|
|
|
/* implicit */ StringPieceLite(const Range& r)
|
|
|
|
: StringPieceLite(r.data(), r.data() + r.size()) {}
|
|
|
|
const char* data() const {
|
|
|
|
return b_;
|
|
|
|
}
|
|
|
|
const char* begin() const {
|
|
|
|
return b_;
|
|
|
|
}
|
|
|
|
const char* end() const {
|
|
|
|
return e_;
|
|
|
|
}
|
|
|
|
size_t size() const {
|
|
|
|
return size_t(e_ - b_);
|
|
|
|
}
|
|
|
|
bool empty() const {
|
|
|
|
return size() == 0;
|
|
|
|
}
|
|
|
|
const char& operator[](size_t i) const {
|
2020-07-20 16:35:17 +00:00
|
|
|
assert(size() > i);
|
2019-05-22 20:15:35 +00:00
|
|
|
return b_[i];
|
|
|
|
}
|
|
|
|
template <typename Range>
|
|
|
|
explicit operator Range() const {
|
|
|
|
return Range(begin(), end());
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
const char* b_;
|
|
|
|
const char* e_;
|
|
|
|
};
|
|
|
|
|
|
|
|
inline size_t qfind_first_byte_of_std(
|
|
|
|
const StringPieceLite haystack,
|
|
|
|
const StringPieceLite needles) {
|
|
|
|
auto ret = std::find_first_of(
|
|
|
|
haystack.begin(),
|
|
|
|
haystack.end(),
|
|
|
|
needles.begin(),
|
|
|
|
needles.end(),
|
|
|
|
[](char a, char b) { return a == b; });
|
|
|
|
return ret == haystack.end() ? std::string::npos : ret - haystack.begin();
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t qfind_first_byte_of_bitset(
|
|
|
|
const StringPieceLite haystack,
|
|
|
|
const StringPieceLite needles);
|
|
|
|
|
|
|
|
size_t qfind_first_byte_of_byteset(
|
|
|
|
const StringPieceLite haystack,
|
|
|
|
const StringPieceLite needles);
|
|
|
|
|
|
|
|
inline size_t qfind_first_byte_of_nosse(
|
|
|
|
const StringPieceLite haystack,
|
|
|
|
const StringPieceLite needles) {
|
|
|
|
if (UNLIKELY(needles.empty() || haystack.empty())) {
|
|
|
|
return std::string::npos;
|
|
|
|
}
|
|
|
|
// The thresholds below were empirically determined by benchmarking.
|
|
|
|
// This is not an exact science since it depends on the CPU, the size of
|
|
|
|
// needles, and the size of haystack.
|
|
|
|
if ((needles.size() >= 4 && haystack.size() <= 10) ||
|
|
|
|
(needles.size() >= 16 && haystack.size() <= 64) || needles.size() >= 32) {
|
|
|
|
return qfind_first_byte_of_byteset(haystack, needles);
|
|
|
|
}
|
|
|
|
return qfind_first_byte_of_std(haystack, needles);
|
|
|
|
}
|
|
|
|
} // namespace detail
|
|
|
|
} // namespace folly
|