#ifndef FOLLY_RANGE_H_
#define FOLLY_RANGE_H_
-#include "folly/Portability.h"
-#include "folly/FBString.h"
+#include <folly/Portability.h>
+#include <folly/FBString.h>
#include <algorithm>
#include <boost/operators.hpp>
#include <cstring>
#include <string>
#include <type_traits>
-// libc++ doesn't provide this header
-#if !FOLLY_USE_LIBCPP
+// libc++ doesn't provide this header, nor does msvc
+#ifdef FOLLY_HAVE_BITS_CXXCONFIG_H
// This file appears in two locations: inside fbcode and in the
// libstdc++ source code (when embedding fbstring as std::string).
// To aid in this schizophrenic use, two macros are defined in
#include <bits/c++config.h>
#endif
-#include "folly/CpuId.h"
-#include "folly/Traits.h"
-#include "folly/Likely.h"
+#include <folly/CpuId.h>
+#include <folly/Traits.h>
+#include <folly/Likely.h>
// Ignore shadowing warnings within this file, so includers can use -Wshadow.
#pragma GCC diagnostic push
return find(c, pos);
}
+ /**
+ * Determine whether the range contains the given subrange or item.
+ *
+ * Note: Call find() directly if the index is needed.
+ */
+ bool contains(const Range& other) const {
+ return find(other) != std::string::npos;
+ }
+
+ bool contains(const value_type& other) const {
+ return find(other) != std::string::npos;
+ }
+
void swap(Range& rhs) {
std::swap(b_, rhs.b_);
std::swap(e_, rhs.e_);
* folly::StringPiece s("sample string for split_next");
* auto p = s.split_step(' ');
*
- * // prints "sample"
+ * // prints "string for split_next"
* cout << s << endl;
*
- * // prints "string for split_next"
+ * // prints "sample"
* cout << p << endl;
*
* Example 2:
/**
* Convenience method that calls `split_step()` and passes the result to a
- * functor, returning whatever the functor does.
+ * functor, returning whatever the functor does. Any additional arguments
+ * `args` passed to this function are perfectly forwarded to the functor.
*
* Say you have a functor with this signature:
*
* // ...
* }
*
+ * struct Foo {
+ * void parse(folly::StringPiece s) {
+ * s.split_step(' ', parse_field, bar, 10);
+ * s.split_step('\t', parse_field, baz, 20);
+ *
+ * auto const kludge = [](folly::StringPiece x, int &out, int def) {
+ * if (x == "null") {
+ * out = 0;
+ * } else {
+ * parse_field(x, out, def);
+ * }
+ * };
+ *
+ * s.split_step('\t', kludge, gaz);
+ * s.split_step(' ', kludge, foo);
+ * }
+ *
+ * private:
+ * int bar;
+ * int baz;
+ * int gaz;
+ * int foo;
+ *
+ * static parse_field(folly::StringPiece s, int &out, int def) {
+ * try {
+ * out = folly::to<int>(s);
+ * } catch (std::exception const &) {
+ * value = def;
+ * }
+ * }
+ * };
+ *
* @author: Marcelo Juchem <marcelo@fb.com>
*/
- template <typename TProcess>
- auto split_step(value_type delimiter, TProcess &&process)
- -> decltype(process(std::declval<Range>()))
- { return process(split_step(delimiter)); }
-
- template <typename TProcess>
- auto split_step(Range delimiter, TProcess &&process)
- -> decltype(process(std::declval<Range>()))
- { return process(split_step(delimiter)); }
+ template <typename TProcess, typename... Args>
+ auto split_step(value_type delimiter, TProcess &&process, Args &&...args)
+ -> decltype(process(std::declval<Range>(), std::forward<Args>(args)...))
+ { return process(split_step(delimiter), std::forward<Args>(args)...); }
+
+ template <typename TProcess, typename... Args>
+ auto split_step(Range delimiter, TProcess &&process, Args &&...args)
+ -> decltype(process(std::declval<Range>(), std::forward<Args>(args)...))
+ { return process(split_step(delimiter), std::forward<Args>(args)...); }
private:
Iter b_, e_;