Commit a7937a66 authored by HC Zhu's avatar HC Zhu Committed by Facebook Github Bot

Allow std::ignore in split()

Summary:
This allows a caller to throw away unwanted parts e.g.

```
std::string user;
folly::split('/', "ads_lla/admarket/adfox", std::ignore, user, std::ignore);

```

Reviewed By: yfeldblum

Differential Revision: D10057247

fbshipit-source-id: 8198d4cb207bbd2007635db1e5796759dccf367c
parent 061ea836
...@@ -332,16 +332,25 @@ inline char prepareDelim(char c) { ...@@ -332,16 +332,25 @@ inline char prepareDelim(char c) {
return c; return c;
} }
template <class OutputType>
void toOrIgnore(StringPiece input, OutputType& output) {
output = folly::to<OutputType>(input);
}
inline void toOrIgnore(StringPiece, decltype(std::ignore)&) {}
template <bool exact, class Delim, class OutputType> template <bool exact, class Delim, class OutputType>
bool splitFixed(const Delim& delimiter, StringPiece input, OutputType& output) { bool splitFixed(const Delim& delimiter, StringPiece input, OutputType& output) {
static_assert( static_assert(
exact || std::is_same<OutputType, StringPiece>::value || exact || std::is_same<OutputType, StringPiece>::value ||
IsSomeString<OutputType>::value, IsSomeString<OutputType>::value ||
"split<false>() requires that the last argument be a string type"); std::is_same<OutputType, decltype(std::ignore)>::value,
"split<false>() requires that the last argument be a string type "
"or std::ignore");
if (exact && UNLIKELY(std::string::npos != input.find(delimiter))) { if (exact && UNLIKELY(std::string::npos != input.find(delimiter))) {
return false; return false;
} }
output = folly::to<OutputType>(input); toOrIgnore(input, output);
return true; return true;
} }
...@@ -359,7 +368,7 @@ bool splitFixed( ...@@ -359,7 +368,7 @@ bool splitFixed(
StringPiece tail( StringPiece tail(
input.begin() + cut + detail::delimSize(delimiter), input.end()); input.begin() + cut + detail::delimSize(delimiter), input.end());
if (LIKELY(splitFixed<exact>(delimiter, tail, outTail...))) { if (LIKELY(splitFixed<exact>(delimiter, tail, outTail...))) {
outHead = folly::to<OutputType>(head); toOrIgnore(head, outHead);
return true; return true;
} }
return false; return false;
......
...@@ -479,6 +479,9 @@ namespace detail { ...@@ -479,6 +479,9 @@ namespace detail {
template <typename Void, typename OutputType> template <typename Void, typename OutputType>
struct IsConvertible : std::false_type {}; struct IsConvertible : std::false_type {};
template <>
struct IsConvertible<void, decltype(std::ignore)> : std::true_type {};
template <typename OutputType> template <typename OutputType>
struct IsConvertible< struct IsConvertible<
void_t<decltype(parseTo(StringPiece{}, std::declval<OutputType&>()))>, void_t<decltype(parseTo(StringPiece{}, std::declval<OutputType&>()))>,
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#endif #endif
#include <folly/String.h> #include <folly/String.h>
#include <tuple>
#include <cinttypes> #include <cinttypes>
#include <set> #include <set>
...@@ -954,6 +955,20 @@ TEST(Split, fixed_convert) { ...@@ -954,6 +955,20 @@ TEST(Split, fixed_convert) {
// Enable verifying that a line only contains one field // Enable verifying that a line only contains one field
EXPECT_TRUE(folly::split(' ', "hello", a)); EXPECT_TRUE(folly::split(' ', "hello", a));
EXPECT_FALSE(folly::split(' ', "hello world", a)); EXPECT_FALSE(folly::split(' ', "hello world", a));
// Test cases with std::ignore.
EXPECT_TRUE(folly::split(':', "a:13:14.7:b", std::ignore, b, c, d));
EXPECT_EQ(13, b);
EXPECT_NEAR(14.7, c, 1e-10);
EXPECT_EQ("b", d);
EXPECT_TRUE(folly::split(':', "a:13:14.7:b", std::ignore, b, c, std::ignore));
EXPECT_EQ(13, b);
EXPECT_NEAR(14.7, c, 1e-10);
EXPECT_TRUE(folly::split<false>(':', "a:13:14.7:b", a, b, std::ignore));
EXPECT_EQ("a", a);
EXPECT_EQ(13, b);
} }
namespace my { namespace my {
......
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