+static_assert(AllConvertible<float>::value, "");
+static_assert(AllConvertible<int>::value, "");
+static_assert(AllConvertible<bool>::value, "");
+static_assert(AllConvertible<int>::value, "");
+static_assert(!AllConvertible<std::vector<int>>::value, "");
+
+template <bool exact = true, class Delim, class... OutputTypes>
+typename std::enable_if<
+ AllConvertible<OutputTypes...>::value && sizeof...(OutputTypes) >= 1,
+ bool>::type
+split(const Delim& delimiter, StringPiece input, OutputTypes&... outputs);
+
+/*
+ * Join list of tokens.
+ *
+ * Stores a string representation of tokens in the same order with
+ * deliminer between each element.
+ */
+
+template <class Delim, class Iterator, class String>
+void join(const Delim& delimiter,
+ Iterator begin,
+ Iterator end,
+ String& output);
+
+template <class Delim, class Container, class String>
+void join(const Delim& delimiter,
+ const Container& container,
+ String& output) {
+ join(delimiter, container.begin(), container.end(), output);
+}
+
+template <class Delim, class Value, class String>
+void join(const Delim& delimiter,
+ const std::initializer_list<Value>& values,
+ String& output) {
+ join(delimiter, values.begin(), values.end(), output);
+}
+
+template <class Delim, class Container>
+std::string join(const Delim& delimiter,
+ const Container& container) {
+ std::string output;
+ join(delimiter, container.begin(), container.end(), output);
+ return output;
+}
+
+template <class Delim, class Value>
+std::string join(const Delim& delimiter,
+ const std::initializer_list<Value>& values) {
+ std::string output;
+ join(delimiter, values.begin(), values.end(), output);
+ return output;
+}
+
+template <
+ class Delim,
+ class Iterator,
+ typename std::enable_if<std::is_same<
+ typename std::iterator_traits<Iterator>::iterator_category,
+ std::random_access_iterator_tag>::value>::type* = nullptr>
+std::string join(const Delim& delimiter, Iterator begin, Iterator end) {
+ std::string output;
+ join(delimiter, begin, end, output);
+ return output;
+}
+
+/**
+ * Returns a subpiece with all whitespace removed from the front of @sp.
+ * Whitespace means any of [' ', '\n', '\r', '\t'].
+ */
+StringPiece ltrimWhitespace(StringPiece sp);
+
+/**
+ * Returns a subpiece with all whitespace removed from the back of @sp.
+ * Whitespace means any of [' ', '\n', '\r', '\t'].
+ */
+StringPiece rtrimWhitespace(StringPiece sp);
+
+/**
+ * Returns a subpiece with all whitespace removed from the back and front of @sp.
+ * Whitespace means any of [' ', '\n', '\r', '\t'].
+ */
+inline StringPiece trimWhitespace(StringPiece sp) {
+ return ltrimWhitespace(rtrimWhitespace(sp));
+}
+
+/**
+ * Returns a subpiece with all whitespace removed from the front of @sp.
+ * Whitespace means any of [' ', '\n', '\r', '\t'].
+ * DEPRECATED: @see ltrimWhitespace @see rtrimWhitespace
+ */
+inline StringPiece skipWhitespace(StringPiece sp) {
+ return ltrimWhitespace(sp);
+}
+
+/**
+ * Strips the leading and the trailing whitespace-only lines. Then looks for
+ * the least indented non-whitespace-only line and removes its amount of
+ * leading whitespace from every line. Assumes leading whitespace is either all
+ * spaces or all tabs.
+ *
+ * Purpose: including a multiline string literal in source code, indented to
+ * the level expected from context.
+ */
+std::string stripLeftMargin(std::string s);
+
+/**
+ * Fast, in-place lowercasing of ASCII alphabetic characters in strings.
+ * Leaves all other characters unchanged, including those with the 0x80
+ * bit set.
+ * @param str String to convert
+ * @param length Length of str, in bytes
+ */
+void toLowerAscii(char* str, size_t length);
+
+inline void toLowerAscii(MutableStringPiece str) {
+ toLowerAscii(str.begin(), str.size());
+}
+
+inline void toLowerAscii(std::string& str) {
+ // str[0] is legal also if the string is empty.
+ toLowerAscii(&str[0], str.size());
+}
+
+template <
+ class Iterator = const char*,
+ class Base = folly::Range<boost::u8_to_u32_iterator<Iterator>>>
+class UTF8Range : public Base {
+ public:
+ /* implicit */ UTF8Range(const folly::Range<Iterator> baseRange)
+ : Base(boost::u8_to_u32_iterator<Iterator>(
+ baseRange.begin(), baseRange.begin(), baseRange.end()),
+ boost::u8_to_u32_iterator<Iterator>(
+ baseRange.end(), baseRange.begin(), baseRange.end())) {}
+ /* implicit */ UTF8Range(const std::string& baseString)
+ : Base(folly::Range<Iterator>(baseString)) {}
+};
+
+using UTF8StringPiece = UTF8Range<const char*>;
+
+} // namespace folly