* limitations under the License.
*/
-#ifndef FOLLY_STRING_INL_H_
-#define FOLLY_STRING_INL_H_
+#pragma once
#include <stdexcept>
#include <iterator>
-#ifndef FOLLY_BASE_STRING_H_
+#ifndef FOLLY_STRING_H_
#error This file may only be included from String.h
#endif
return *s.start();
}
-/*
- * These output conversion templates allow us to support multiple
- * output string types, even when we are using an arbitrary
- * OutputIterator.
- */
-template<class OutStringT> struct OutputConverter {};
-
-template<> struct OutputConverter<std::string> {
- std::string operator()(StringPiece sp) const {
- return sp.toString();
- }
-};
-
-template<> struct OutputConverter<fbstring> {
- fbstring operator()(StringPiece sp) const {
- return sp.toFbstring();
- }
-};
-
-template<> struct OutputConverter<StringPiece> {
- StringPiece operator()(StringPiece sp) const { return sp; }
-};
-
/*
* Shared implementation for all the split() overloads.
*
const size_t strSize = sp.size();
const size_t dSize = delimSize(delim);
- OutputConverter<OutStringT> conv;
-
if (dSize > strSize || dSize == 0) {
if (!ignoreEmpty || strSize > 0) {
- *out++ = conv(sp);
+ *out++ = to<OutStringT>(sp);
}
return;
}
for (size_t i = 0; i <= strSize - dSize; ++i) {
if (atDelim(&s[i], delim)) {
if (!ignoreEmpty || tokenSize > 0) {
- *out++ = conv(StringPiece(&s[tokenStartPos], tokenSize));
+ *out++ = to<OutStringT>(sp.subpiece(tokenStartPos, tokenSize));
}
tokenStartPos = i + dSize;
}
tokenSize = strSize - tokenStartPos;
if (!ignoreEmpty || tokenSize > 0) {
- *out++ = conv(StringPiece(&s[tokenStartPos], tokenSize));
+ *out++ = to<OutStringT>(sp.subpiece(tokenStartPos, tokenSize));
}
}
}
inline char prepareDelim(char c) { return c; }
-template <class Dst>
-struct convertTo {
- template <class Src>
- static Dst from(const Src& src) { return folly::to<Dst>(src); }
- static Dst from(const Dst& src) { return src; }
-};
-
-template<bool exact,
- class Delim,
- class OutputType>
-typename std::enable_if<IsSplitTargetType<OutputType>::value, bool>::type
-splitFixed(const Delim& delimiter,
- StringPiece input,
- OutputType& out) {
+template <bool exact, class Delim, class OutputType>
+bool splitFixed(const Delim& delimiter, StringPiece input, OutputType& output) {
+ static_assert(
+ exact || std::is_same<OutputType, StringPiece>::value ||
+ IsSomeString<OutputType>::value,
+ "split<false>() requires that the last argument be a string type");
if (exact && UNLIKELY(std::string::npos != input.find(delimiter))) {
return false;
}
- out = convertTo<OutputType>::from(input);
+ output = folly::to<OutputType>(input);
return true;
}
-template<bool exact,
- class Delim,
- class OutputType,
- class... OutputTypes>
-typename std::enable_if<IsSplitTargetType<OutputType>::value, bool>::type
-splitFixed(const Delim& delimiter,
- StringPiece input,
- OutputType& outHead,
- OutputTypes&... outTail) {
+template <bool exact, class Delim, class OutputType, class... OutputTypes>
+bool splitFixed(
+ const Delim& delimiter,
+ StringPiece input,
+ OutputType& outHead,
+ OutputTypes&... outTail) {
size_t cut = input.find(delimiter);
if (UNLIKELY(cut == std::string::npos)) {
return false;
StringPiece tail(input.begin() + cut + detail::delimSize(delimiter),
input.end());
if (LIKELY(splitFixed<exact>(delimiter, tail, outTail...))) {
- outHead = convertTo<OutputType>::from(head);
+ outHead = folly::to<OutputType>(head);
return true;
}
return false;
ignoreEmpty);
}
-template<bool exact,
- class Delim,
- class OutputType,
- class... OutputTypes>
-typename std::enable_if<IsSplitTargetType<OutputType>::value, bool>::type
-split(const Delim& delimiter,
- StringPiece input,
- OutputType& outHead,
- OutputTypes&... outTail) {
+template <bool exact, class Delim, class... OutputTypes>
+typename std::enable_if<
+ AllConvertible<OutputTypes...>::value && sizeof...(OutputTypes) >= 1,
+ bool>::type
+split(const Delim& delimiter, StringPiece input, OutputTypes&... outputs) {
return detail::splitFixed<exact>(
- detail::prepareDelim(delimiter),
- input,
- outHead,
- outTail...);
+ detail::prepareDelim(delimiter), input, outputs...);
}
namespace detail {
}
output.resize(input.size() / 2);
int j = 0;
- auto unhex = [](char c) -> int {
- return c >= '0' && c <= '9' ? c - '0' :
- c >= 'A' && c <= 'F' ? c - 'A' + 10 :
- c >= 'a' && c <= 'f' ? c - 'a' + 10 :
- -1;
- };
for (size_t i = 0; i < input.size(); i += 2) {
- int highBits = unhex(input[i]);
- int lowBits = unhex(input[i + 1]);
- if (highBits < 0 || lowBits < 0) {
+ int highBits = detail::hexTable[static_cast<uint8_t>(input[i])];
+ int lowBits = detail::hexTable[static_cast<uint8_t>(input[i + 1])];
+ if ((highBits | lowBits) & 0x10) {
+ // One of the characters wasn't a hex digit
return false;
}
output[j++] = (highBits << 4) + lowBits;
}
} // namespace folly
-
-#endif /* FOLLY_STRING_INL_H_ */