/*
- * Copyright 2013 Facebook, Inc.
+ * Copyright 2014 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
template<class OutStringT, class DelimT, class OutputIterator>
void internalSplit(DelimT delim, StringPiece sp, OutputIterator out,
bool ignoreEmpty) {
- assert(sp.start() != nullptr);
+ assert(sp.empty() || sp.start() != nullptr);
const char* s = sp.start();
const size_t strSize = sp.size();
}
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) {
+ if (exact && UNLIKELY(std::string::npos != input.find(delimiter))) {
+ return false;
+ }
+ out = convertTo<OutputType>::from(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) {
+ size_t cut = input.find(delimiter);
+ if (UNLIKELY(cut == std::string::npos)) {
+ return false;
+ }
+ StringPiece head(input.begin(), input.begin() + cut);
+ StringPiece tail(input.begin() + cut + detail::delimSize(delimiter),
+ input.end());
+ if (LIKELY(splitFixed<exact>(delimiter, tail, outTail...))) {
+ outHead = convertTo<OutputType>::from(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) {
+ return detail::splitFixed<exact>(
+ detail::prepareDelim(delimiter),
+ input,
+ outHead,
+ outTail...);
+}
+
namespace detail {
+/*
+ * If a type can have its string size determined cheaply, we can more
+ * efficiently append it in a loop (see internalJoinAppend). Note that the
+ * struct need not conform to the std::string api completely (ex. does not need
+ * to implement append()).
+ */
+template <class T> struct IsSizableString {
+ enum { value = IsSomeString<T>::value
+ || std::is_same<T, StringPiece>::value };
+};
+
template <class Iterator>
-struct IsStringContainerIterator :
- IsSomeString<typename std::iterator_traits<Iterator>::value_type> {
+struct IsSizableStringContainerIterator :
+ IsSizableString<typename std::iterator_traits<Iterator>::value_type> {
};
template <class Delim, class Iterator, class String>
}
template <class Delim, class Iterator, class String>
-typename std::enable_if<IsStringContainerIterator<Iterator>::value>::type
+typename std::enable_if<IsSizableStringContainerIterator<Iterator>::value>::type
internalJoin(Delim delimiter,
Iterator begin,
Iterator end,
}
template <class Delim, class Iterator, class String>
-typename std::enable_if<!IsStringContainerIterator<Iterator>::value>::type
+typename
+std::enable_if<!IsSizableStringContainerIterator<Iterator>::value>::type
internalJoin(Delim delimiter,
Iterator begin,
Iterator end,
} // namespace folly
#endif /* FOLLY_STRING_INL_H_ */
-