Commit 3ed4f961 authored by Marcelo Juchem's avatar Marcelo Juchem Committed by Anton Likhtarov

Allowing additional arguments to be passed to split_step's functor

Summary: more flexibility for using functors with split_step

Test Plan: unit tests added + arc unit

Reviewed By: ldbrandy@fb.com

Subscribers: folly@lists

FB internal diff: D1362644
parent 867b291c
......@@ -611,7 +611,8 @@ public:
/**
* 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:
*
......@@ -636,17 +637,49 @@ public:
* // ...
* }
*
* 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_;
......
......@@ -439,6 +439,7 @@ TEST(StringPiece, split_step_char_delimiter) {
folly::StringPiece p(s);
EXPECT_EQ(s, p.begin());
EXPECT_EQ(e, p.end());
EXPECT_EQ(s, p);
auto x = p.split_step(' ');
EXPECT_EQ(std::next(s, 5), p.begin());
......@@ -496,6 +497,7 @@ TEST(StringPiece, split_step_range_delimiter) {
folly::StringPiece p(s);
EXPECT_EQ(s, p.begin());
EXPECT_EQ(e, p.end());
EXPECT_EQ(s, p);
auto x = p.split_step(" ");
EXPECT_EQ(std::next(s, 6), p.begin());
......@@ -560,6 +562,7 @@ TEST(StringPiece, split_step_with_process_char_delimiter) {
folly::StringPiece p(s);
EXPECT_EQ(s, p.begin());
EXPECT_EQ(e, p.end());
EXPECT_EQ(s, p);
EXPECT_EQ(1, (p.split_step(' ', [&](folly::StringPiece x) {
EXPECT_EQ(std::next(s, 5), p.begin());
......@@ -642,6 +645,7 @@ TEST(StringPiece, split_step_with_process_range_delimiter) {
folly::StringPiece p(s);
EXPECT_EQ(s, p.begin());
EXPECT_EQ(e, p.end());
EXPECT_EQ(s, p);
EXPECT_EQ(1, (p.split_step(" ", [&](folly::StringPiece x) {
EXPECT_EQ(std::next(s, 6), p.begin());
......@@ -721,6 +725,82 @@ TEST(StringPiece, split_step_with_process_range_delimiter) {
EXPECT_NO_THROW(p.split_step(' ', split_step_with_process_noop));
}
TEST(StringPiece, split_step_with_process_char_delimiter_additional_args) {
// 0 1 2
// 012345678901234567890123456
auto const s = "this is just a test string";
auto const e = std::next(s, std::strlen(s));
auto const delimiter = ' ';
EXPECT_EQ('\0', *e);
folly::StringPiece p(s);
EXPECT_EQ(s, p.begin());
EXPECT_EQ(e, p.end());
EXPECT_EQ(s, p);
auto const functor = [](
folly::StringPiece s,
folly::StringPiece expected
) {
EXPECT_EQ(expected, s);
return expected;
};
auto const checker = [&](folly::StringPiece expected) {
EXPECT_EQ(expected, p.split_step(delimiter, functor, expected));
};
checker("this");
checker("is");
checker("just");
checker("");
checker("a");
checker("test");
checker("string");
checker("");
checker("");
EXPECT_TRUE(p.empty());
}
TEST(StringPiece, split_step_with_process_range_delimiter_additional_args) {
// 0 1 2 3
// 0123456789012345678901234567890123
auto const s = "this is just a test string";
auto const e = std::next(s, std::strlen(s));
auto const delimiter = " ";
EXPECT_EQ('\0', *e);
folly::StringPiece p(s);
EXPECT_EQ(s, p.begin());
EXPECT_EQ(e, p.end());
EXPECT_EQ(s, p);
auto const functor = [](
folly::StringPiece s,
folly::StringPiece expected
) {
EXPECT_EQ(expected, s);
return expected;
};
auto const checker = [&](folly::StringPiece expected) {
EXPECT_EQ(expected, p.split_step(delimiter, functor, expected));
};
checker("this");
checker("is");
checker("just");
checker("");
checker("a");
checker(" test");
checker("string");
checker("");
checker("");
EXPECT_TRUE(p.empty());
}
TEST(qfind, UInt32_Ranges) {
vector<uint32_t> a({1, 2, 3, 260, 5});
vector<uint32_t> b({2, 3, 4});
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment