Commit 062bb26d authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

Apply clang-format to folly/gen/

Summary: [Folly] Apply `clang-format` to `folly/gen/`.

Reviewed By: Orvid

Differential Revision: D9671968

fbshipit-source-id: 1164cf0d236914b5fd7ed35d5d41c785935e876b
parent d98241e2
This diff is collapsed.
...@@ -86,8 +86,8 @@ namespace gen { ...@@ -86,8 +86,8 @@ namespace gen {
class Less { class Less {
public: public:
template <class First, class Second> template <class First, class Second>
auto operator()(const First& first, const Second& second) const -> auto operator()(const First& first, const Second& second) const
decltype(first < second) { -> decltype(first < second) {
return first < second; return first < second;
} }
}; };
...@@ -95,8 +95,8 @@ class Less { ...@@ -95,8 +95,8 @@ class Less {
class Greater { class Greater {
public: public:
template <class First, class Second> template <class First, class Second>
auto operator()(const First& first, const Second& second) const -> auto operator()(const First& first, const Second& second) const
decltype(first > second) { -> decltype(first > second) {
return first > second; return first > second;
} }
}; };
...@@ -105,8 +105,8 @@ template <int n> ...@@ -105,8 +105,8 @@ template <int n>
class Get { class Get {
public: public:
template <class Value> template <class Value>
auto operator()(Value&& value) const -> auto operator()(Value&& value) const
decltype(std::get<n>(std::forward<Value>(value))) { -> decltype(std::get<n>(std::forward<Value>(value))) {
return std::get<n>(std::forward<Value>(value)); return std::get<n>(std::forward<Value>(value));
} }
}; };
...@@ -115,12 +115,12 @@ template <class Class, class Result> ...@@ -115,12 +115,12 @@ template <class Class, class Result>
class MemberFunction { class MemberFunction {
public: public:
typedef Result (Class::*MemberPtr)(); typedef Result (Class::*MemberPtr)();
private: private:
MemberPtr member_; MemberPtr member_;
public: public:
explicit MemberFunction(MemberPtr member) explicit MemberFunction(MemberPtr member) : member_(member) {}
: member_(member)
{}
Result operator()(Class&& x) const { Result operator()(Class&& x) const {
return (x.*member_)(); return (x.*member_)();
...@@ -136,15 +136,15 @@ class MemberFunction { ...@@ -136,15 +136,15 @@ class MemberFunction {
}; };
template <class Class, class Result> template <class Class, class Result>
class ConstMemberFunction{ class ConstMemberFunction {
public: public:
typedef Result (Class::*MemberPtr)() const; typedef Result (Class::*MemberPtr)() const;
private: private:
MemberPtr member_; MemberPtr member_;
public: public:
explicit ConstMemberFunction(MemberPtr member) explicit ConstMemberFunction(MemberPtr member) : member_(member) {}
: member_(member)
{}
Result operator()(const Class& x) const { Result operator()(const Class& x) const {
return (x.*member_)(); return (x.*member_)();
...@@ -158,13 +158,13 @@ class ConstMemberFunction{ ...@@ -158,13 +158,13 @@ class ConstMemberFunction{
template <class Class, class FieldType> template <class Class, class FieldType>
class Field { class Field {
public: public:
typedef FieldType (Class::*FieldPtr); typedef FieldType(Class::*FieldPtr);
private: private:
FieldPtr field_; FieldPtr field_;
public: public:
explicit Field(FieldPtr field) explicit Field(FieldPtr field) : field_(field) {}
: field_(field)
{}
const FieldType& operator()(const Class& x) const { const FieldType& operator()(const Class& x) const {
return x.*field_; return x.*field_;
...@@ -190,8 +190,8 @@ class Field { ...@@ -190,8 +190,8 @@ class Field {
class Move { class Move {
public: public:
template <class Value> template <class Value>
auto operator()(Value&& value) const -> auto operator()(Value&& value) const
decltype(std::move(std::forward<Value>(value))) { -> decltype(std::move(std::forward<Value>(value))) {
return std::move(std::forward<Value>(value)); return std::move(std::forward<Value>(value));
} }
}; };
...@@ -206,9 +206,7 @@ class Negate { ...@@ -206,9 +206,7 @@ class Negate {
public: public:
Negate() = default; Negate() = default;
explicit Negate(Predicate pred) explicit Negate(Predicate pred) : pred_(std::move(pred)) {}
: pred_(std::move(pred))
{}
template <class Arg> template <class Arg>
bool operator()(Arg&& arg) const { bool operator()(Arg&& arg) const {
...@@ -274,7 +272,6 @@ struct ValueTypeOfRange { ...@@ -274,7 +272,6 @@ struct ValueTypeOfRange {
using StorageType = typename std::decay<RefType>::type; using StorageType = typename std::decay<RefType>::type;
}; };
/* /*
* Sources * Sources
*/ */
...@@ -577,7 +574,7 @@ Map mapOp(Operator op) { ...@@ -577,7 +574,7 @@ Map mapOp(Operator op) {
*/ */
enum MemberType { enum MemberType {
Const, Const,
Mutable Mutable,
}; };
/** /**
...@@ -588,14 +585,14 @@ enum MemberType { ...@@ -588,14 +585,14 @@ enum MemberType {
template <MemberType Constness> template <MemberType Constness>
struct ExprIsConst { struct ExprIsConst {
enum { enum {
value = Constness == Const value = Constness == Const,
}; };
}; };
template <MemberType Constness> template <MemberType Constness>
struct ExprIsMutable { struct ExprIsMutable {
enum { enum {
value = Constness == Mutable value = Constness == Mutable,
}; };
}; };
...@@ -605,8 +602,8 @@ template < ...@@ -605,8 +602,8 @@ template <
class Return, class Return,
class Mem = ConstMemberFunction<Class, Return>, class Mem = ConstMemberFunction<Class, Return>,
class Map = detail::Map<Mem>> class Map = detail::Map<Mem>>
typename std::enable_if<ExprIsConst<Constness>::value, Map>::type typename std::enable_if<ExprIsConst<Constness>::value, Map>::type member(
member(Return (Class::*member)() const) { Return (Class::*member)() const) {
return Map(Mem(member)); return Map(Mem(member));
} }
...@@ -616,8 +613,8 @@ template < ...@@ -616,8 +613,8 @@ template <
class Return, class Return,
class Mem = MemberFunction<Class, Return>, class Mem = MemberFunction<Class, Return>,
class Map = detail::Map<Mem>> class Map = detail::Map<Mem>>
typename std::enable_if<ExprIsMutable<Constness>::value, Map>::type typename std::enable_if<ExprIsMutable<Constness>::value, Map>::type member(
member(Return (Class::*member)()) { Return (Class::*member)()) {
return Map(Mem(member)); return Map(Mem(member));
} }
...@@ -671,10 +668,8 @@ template < ...@@ -671,10 +668,8 @@ template <
class Selector = Identity, class Selector = Identity,
class Comparer = Less, class Comparer = Less,
class Order = detail::Order<Selector, Comparer>> class Order = detail::Order<Selector, Comparer>>
Order orderBy(Selector selector = Selector(), Order orderBy(Selector selector = Selector(), Comparer comparer = Comparer()) {
Comparer comparer = Comparer()) { return Order(std::move(selector), std::move(comparer));
return Order(std::move(selector),
std::move(comparer));
} }
template < template <
...@@ -793,10 +788,8 @@ Composed all(Predicate pred = Predicate()) { ...@@ -793,10 +788,8 @@ Composed all(Predicate pred = Predicate()) {
} }
template <class Seed, class Fold, class FoldLeft = detail::FoldLeft<Seed, Fold>> template <class Seed, class Fold, class FoldLeft = detail::FoldLeft<Seed, Fold>>
FoldLeft foldl(Seed seed = Seed(), FoldLeft foldl(Seed seed = Seed(), Fold fold = Fold()) {
Fold fold = Fold()) { return FoldLeft(std::move(seed), std::move(fold));
return FoldLeft(std::move(seed),
std::move(fold));
} }
template <class Reducer, class Reduce = detail::Reduce<Reducer>> template <class Reducer, class Reduce = detail::Reduce<Reducer>>
......
...@@ -37,9 +37,10 @@ template <class Container> ...@@ -37,9 +37,10 @@ template <class Container>
class Interleave : public Operator<Interleave<Container>> { class Interleave : public Operator<Interleave<Container>> {
// see comment about copies in CopiedSource // see comment about copies in CopiedSource
const std::shared_ptr<const Container> container_; const std::shared_ptr<const Container> container_;
public: public:
explicit Interleave(Container container) explicit Interleave(Container container)
: container_(new Container(std::move(container))) {} : container_(new Container(std::move(container))) {}
template <class Value, class Source> template <class Value, class Source>
class Generator : public GenImpl<Value, Generator<Value, Source>> { class Generator : public GenImpl<Value, Generator<Value, Source>> {
...@@ -47,31 +48,32 @@ class Interleave : public Operator<Interleave<Container>> { ...@@ -47,31 +48,32 @@ class Interleave : public Operator<Interleave<Container>> {
const std::shared_ptr<const Container> container_; const std::shared_ptr<const Container> container_;
typedef const typename Container::value_type& ConstRefType; typedef const typename Container::value_type& ConstRefType;
static_assert(std::is_same<const Value&, ConstRefType>::value, static_assert(
"Only matching types may be interleaved"); std::is_same<const Value&, ConstRefType>::value,
"Only matching types may be interleaved");
public: public:
explicit Generator(Source source, explicit Generator(
const std::shared_ptr<const Container> container) Source source,
: source_(std::move(source)), const std::shared_ptr<const Container> container)
container_(container) { } : source_(std::move(source)), container_(container) {}
template <class Handler> template <class Handler>
bool apply(Handler&& handler) const { bool apply(Handler&& handler) const {
auto iter = container_->begin(); auto iter = container_->begin();
return source_.apply([&](const Value& value) -> bool { return source_.apply([&](const Value& value) -> bool {
if (iter == container_->end()) { if (iter == container_->end()) {
return false; return false;
} }
if (!handler(value)) { if (!handler(value)) {
return false; return false;
} }
if (!handler(*iter)) { if (!handler(*iter)) {
return false; return false;
} }
iter++; iter++;
return true; return true;
}); });
} }
}; };
...@@ -97,9 +99,10 @@ template <class Container> ...@@ -97,9 +99,10 @@ template <class Container>
class Zip : public Operator<Zip<Container>> { class Zip : public Operator<Zip<Container>> {
// see comment about copies in CopiedSource // see comment about copies in CopiedSource
const std::shared_ptr<const Container> container_; const std::shared_ptr<const Container> container_;
public: public:
explicit Zip(Container container) explicit Zip(Container container)
: container_(new Container(std::move(container))) {} : container_(new Container(std::move(container))) {}
template < template <
class Value1, class Value1,
...@@ -108,30 +111,30 @@ class Zip : public Operator<Zip<Container>> { ...@@ -108,30 +111,30 @@ class Zip : public Operator<Zip<Container>> {
class Result = std::tuple< class Result = std::tuple<
typename std::decay<Value1>::type, typename std::decay<Value1>::type,
typename std::decay<Value2>::type>> typename std::decay<Value2>::type>>
class Generator : public GenImpl<Result, class Generator
Generator<Value1,Source,Value2,Result>> { : public GenImpl<Result, Generator<Value1, Source, Value2, Result>> {
Source source_; Source source_;
const std::shared_ptr<const Container> container_; const std::shared_ptr<const Container> container_;
public: public:
explicit Generator(Source source, explicit Generator(
const std::shared_ptr<const Container> container) Source source,
: source_(std::move(source)), const std::shared_ptr<const Container> container)
container_(container) { } : source_(std::move(source)), container_(container) {}
template <class Handler> template <class Handler>
bool apply(Handler&& handler) const { bool apply(Handler&& handler) const {
auto iter = container_->begin(); auto iter = container_->begin();
return (source_.apply([&](Value1 value) -> bool { return (source_.apply([&](Value1 value) -> bool {
if (iter == container_->end()) { if (iter == container_->end()) {
return false; return false;
} }
if (!handler(std::make_tuple(std::forward<Value1>(value), *iter))) { if (!handler(std::make_tuple(std::forward<Value1>(value), *iter))) {
return false; return false;
} }
++iter; ++iter;
return true; return true;
})); }));
} }
}; };
...@@ -147,48 +150,45 @@ class Zip : public Operator<Zip<Container>> { ...@@ -147,48 +150,45 @@ class Zip : public Operator<Zip<Container>> {
}; };
template <class... Types1, class... Types2> template <class... Types1, class... Types2>
auto add_to_tuple(std::tuple<Types1...> t1, std::tuple<Types2...> t2) -> auto add_to_tuple(std::tuple<Types1...> t1, std::tuple<Types2...> t2)
std::tuple<Types1..., Types2...> { -> std::tuple<Types1..., Types2...> {
return std::tuple_cat(std::move(t1), std::move(t2)); return std::tuple_cat(std::move(t1), std::move(t2));
} }
template <class... Types1, class Type2> template <class... Types1, class Type2>
auto add_to_tuple(std::tuple<Types1...> t1, Type2&& t2) -> auto add_to_tuple(std::tuple<Types1...> t1, Type2&& t2) -> decltype(
decltype(std::tuple_cat(std::move(t1), std::tuple_cat(std::move(t1), std::make_tuple(std::forward<Type2>(t2)))) {
std::make_tuple(std::forward<Type2>(t2)))) { return std::tuple_cat(
return std::tuple_cat(std::move(t1), std::move(t1), std::make_tuple(std::forward<Type2>(t2)));
std::make_tuple(std::forward<Type2>(t2)));
} }
template <class Type1, class... Types2> template <class Type1, class... Types2>
auto add_to_tuple(Type1&& t1, std::tuple<Types2...> t2) -> auto add_to_tuple(Type1&& t1, std::tuple<Types2...> t2) -> decltype(
decltype(std::tuple_cat(std::make_tuple(std::forward<Type1>(t1)), std::tuple_cat(std::make_tuple(std::forward<Type1>(t1)), std::move(t2))) {
std::move(t2))) { return std::tuple_cat(
return std::tuple_cat(std::make_tuple(std::forward<Type1>(t1)), std::make_tuple(std::forward<Type1>(t1)), std::move(t2));
std::move(t2));
} }
template <class Type1, class Type2> template <class Type1, class Type2>
auto add_to_tuple(Type1&& t1, Type2&& t2) -> auto add_to_tuple(Type1&& t1, Type2&& t2) -> decltype(
decltype(std::make_tuple(std::forward<Type1>(t1), std::make_tuple(std::forward<Type1>(t1), std::forward<Type2>(t2))) {
std::forward<Type2>(t2))) { return std::make_tuple(std::forward<Type1>(t1), std::forward<Type2>(t2));
return std::make_tuple(std::forward<Type1>(t1),
std::forward<Type2>(t2));
} }
// Merges a 2-tuple into a single tuple (get<0> could already be a tuple) // Merges a 2-tuple into a single tuple (get<0> could already be a tuple)
class MergeTuples { class MergeTuples {
public: public:
template <class Tuple> template <class Tuple>
auto operator()(Tuple&& value) const -> auto operator()(Tuple&& value) const -> decltype(add_to_tuple(
decltype(add_to_tuple(std::get<0>(std::forward<Tuple>(value)), std::get<0>(std::forward<Tuple>(value)),
std::get<1>(std::forward<Tuple>(value)))) { std::get<1>(std::forward<Tuple>(value)))) {
static_assert(std::tuple_size< static_assert(
typename std::remove_reference<Tuple>::type std::tuple_size<typename std::remove_reference<Tuple>::type>::value ==
>::value == 2, 2,
"Can only merge tuples of size 2"); "Can only merge tuples of size 2");
return add_to_tuple(std::get<0>(std::forward<Tuple>(value)), return add_to_tuple(
std::get<1>(std::forward<Tuple>(value))); std::get<0>(std::forward<Tuple>(value)),
std::get<1>(std::forward<Tuple>(value)));
} }
}; };
......
...@@ -108,8 +108,7 @@ template < ...@@ -108,8 +108,7 @@ template <
class Left, class Left,
class Right, class Right,
class Composed = detail::Composed<Left, Right>> class Composed = detail::Composed<Left, Right>>
Composed operator|(const Operator<Left>& left, Composed operator|(const Operator<Left>& left, const Operator<Right>& right) {
const Operator<Right>& right) {
return Composed(left.self(), right.self()); return Composed(left.self(), right.self());
} }
...@@ -117,8 +116,7 @@ template < ...@@ -117,8 +116,7 @@ template <
class Left, class Left,
class Right, class Right,
class Composed = detail::Composed<Left, Right>> class Composed = detail::Composed<Left, Right>>
Composed operator|(const Operator<Left>& left, Composed operator|(const Operator<Left>& left, Operator<Right>&& right) {
Operator<Right>&& right) {
return Composed(left.self(), std::move(right.self())); return Composed(left.self(), std::move(right.self()));
} }
...@@ -126,8 +124,7 @@ template < ...@@ -126,8 +124,7 @@ template <
class Left, class Left,
class Right, class Right,
class Composed = detail::Composed<Left, Right>> class Composed = detail::Composed<Left, Right>>
Composed operator|(Operator<Left>&& left, Composed operator|(Operator<Left>&& left, const Operator<Right>& right) {
const Operator<Right>& right) {
return Composed(std::move(left.self()), right.self()); return Composed(std::move(left.self()), right.self());
} }
...@@ -135,8 +132,7 @@ template < ...@@ -135,8 +132,7 @@ template <
class Left, class Left,
class Right, class Right,
class Composed = detail::Composed<Left, Right>> class Composed = detail::Composed<Left, Right>>
Composed operator|(Operator<Left>&& left, Composed operator|(Operator<Left>&& left, Operator<Right>&& right) {
Operator<Right>&& right) {
return Composed(std::move(left.self()), std::move(right.self())); return Composed(std::move(left.self()), std::move(right.self()));
} }
...@@ -176,10 +172,10 @@ class GenImpl : public FBounded<Self> { ...@@ -176,10 +172,10 @@ class GenImpl : public FBounded<Self> {
template <class Body> template <class Body>
void foreach(Body&& body) const { void foreach(Body&& body) const {
this->self().apply([&](Value value) -> bool { this->self().apply([&](Value value) -> bool {
static_assert(!infinite, "Cannot call foreach on infinite GenImpl"); static_assert(!infinite, "Cannot call foreach on infinite GenImpl");
body(std::forward<Value>(value)); body(std::forward<Value>(value));
return true; return true;
}); });
} }
// Child classes should override if the sequence generated is *definitely* // Child classes should override if the sequence generated is *definitely*
...@@ -201,11 +197,12 @@ template < ...@@ -201,11 +197,12 @@ template <
class RightValue, class RightValue,
class Right, class Right,
class Chain = detail::Chain<LeftValue, Left, Right>> class Chain = detail::Chain<LeftValue, Left, Right>>
Chain operator+(const GenImpl<LeftValue, Left>& left, Chain operator+(
const GenImpl<RightValue, Right>& right) { const GenImpl<LeftValue, Left>& left,
const GenImpl<RightValue, Right>& right) {
static_assert( static_assert(
std::is_same<LeftValue, RightValue>::value, std::is_same<LeftValue, RightValue>::value,
"Generators may ony be combined if Values are the exact same type."); "Generators may ony be combined if Values are the exact same type.");
return Chain(left.self(), right.self()); return Chain(left.self(), right.self());
} }
...@@ -215,11 +212,12 @@ template < ...@@ -215,11 +212,12 @@ template <
class RightValue, class RightValue,
class Right, class Right,
class Chain = detail::Chain<LeftValue, Left, Right>> class Chain = detail::Chain<LeftValue, Left, Right>>
Chain operator+(const GenImpl<LeftValue, Left>& left, Chain operator+(
GenImpl<RightValue, Right>&& right) { const GenImpl<LeftValue, Left>& left,
GenImpl<RightValue, Right>&& right) {
static_assert( static_assert(
std::is_same<LeftValue, RightValue>::value, std::is_same<LeftValue, RightValue>::value,
"Generators may ony be combined if Values are the exact same type."); "Generators may ony be combined if Values are the exact same type.");
return Chain(left.self(), std::move(right.self())); return Chain(left.self(), std::move(right.self()));
} }
...@@ -229,11 +227,12 @@ template < ...@@ -229,11 +227,12 @@ template <
class RightValue, class RightValue,
class Right, class Right,
class Chain = detail::Chain<LeftValue, Left, Right>> class Chain = detail::Chain<LeftValue, Left, Right>>
Chain operator+(GenImpl<LeftValue, Left>&& left, Chain operator+(
const GenImpl<RightValue, Right>& right) { GenImpl<LeftValue, Left>&& left,
const GenImpl<RightValue, Right>& right) {
static_assert( static_assert(
std::is_same<LeftValue, RightValue>::value, std::is_same<LeftValue, RightValue>::value,
"Generators may ony be combined if Values are the exact same type."); "Generators may ony be combined if Values are the exact same type.");
return Chain(std::move(left.self()), right.self()); return Chain(std::move(left.self()), right.self());
} }
...@@ -243,11 +242,12 @@ template < ...@@ -243,11 +242,12 @@ template <
class RightValue, class RightValue,
class Right, class Right,
class Chain = detail::Chain<LeftValue, Left, Right>> class Chain = detail::Chain<LeftValue, Left, Right>>
Chain operator+(GenImpl<LeftValue, Left>&& left, Chain operator+(
GenImpl<RightValue, Right>&& right) { GenImpl<LeftValue, Left>&& left,
GenImpl<RightValue, Right>&& right) {
static_assert( static_assert(
std::is_same<LeftValue, RightValue>::value, std::is_same<LeftValue, RightValue>::value,
"Generators may ony be combined if Values are the exact same type."); "Generators may ony be combined if Values are the exact same type.");
return Chain(std::move(left.self()), std::move(right.self())); return Chain(std::move(left.self()), std::move(right.self()));
} }
...@@ -257,10 +257,10 @@ Chain operator+(GenImpl<LeftValue, Left>&& left, ...@@ -257,10 +257,10 @@ Chain operator+(GenImpl<LeftValue, Left>&& left,
*/ */
template <class Value, class Gen, class Handler> template <class Value, class Gen, class Handler>
typename std::enable_if< typename std::enable_if<
IsCompatibleSignature<Handler, void(Value)>::value>::type IsCompatibleSignature<Handler, void(Value)>::value>::type
operator|(const GenImpl<Value, Gen>& gen, Handler&& handler) { operator|(const GenImpl<Value, Gen>& gen, Handler&& handler) {
static_assert(!Gen::infinite, static_assert(
"Cannot pull all values from an infinite sequence."); !Gen::infinite, "Cannot pull all values from an infinite sequence.");
gen.self().foreach(std::forward<Handler>(handler)); gen.self().foreach(std::forward<Handler>(handler));
} }
...@@ -269,9 +269,9 @@ operator|(const GenImpl<Value, Gen>& gen, Handler&& handler) { ...@@ -269,9 +269,9 @@ operator|(const GenImpl<Value, Gen>& gen, Handler&& handler) {
* gen | [](Value v) -> bool { return shouldContinue(); }; * gen | [](Value v) -> bool { return shouldContinue(); };
*/ */
template <class Value, class Gen, class Handler> template <class Value, class Gen, class Handler>
typename std::enable_if< typename std::
IsCompatibleSignature<Handler, bool(Value)>::value, bool>::type enable_if<IsCompatibleSignature<Handler, bool(Value)>::value, bool>::type
operator|(const GenImpl<Value, Gen>& gen, Handler&& handler) { operator|(const GenImpl<Value, Gen>& gen, Handler&& handler) {
return gen.self().apply(std::forward<Handler>(handler)); return gen.self().apply(std::forward<Handler>(handler));
} }
...@@ -281,14 +281,14 @@ operator|(const GenImpl<Value, Gen>& gen, Handler&& handler) { ...@@ -281,14 +281,14 @@ operator|(const GenImpl<Value, Gen>& gen, Handler&& handler) {
* gen | map(square) | sum * gen | map(square) | sum
*/ */
template <class Value, class Gen, class Op> template <class Value, class Gen, class Op>
auto operator|(const GenImpl<Value, Gen>& gen, const Operator<Op>& op) -> auto operator|(const GenImpl<Value, Gen>& gen, const Operator<Op>& op)
decltype(op.self().compose(gen.self())) { -> decltype(op.self().compose(gen.self())) {
return op.self().compose(gen.self()); return op.self().compose(gen.self());
} }
template <class Value, class Gen, class Op> template <class Value, class Gen, class Op>
auto operator|(GenImpl<Value, Gen>&& gen, const Operator<Op>& op) -> auto operator|(GenImpl<Value, Gen>&& gen, const Operator<Op>& op)
decltype(op.self().compose(std::move(gen.self()))) { -> decltype(op.self().compose(std::move(gen.self()))) {
return op.self().compose(std::move(gen.self())); return op.self().compose(std::move(gen.self()));
} }
...@@ -309,12 +309,12 @@ template <class First, class Second> ...@@ -309,12 +309,12 @@ template <class First, class Second>
class Composed : public Operator<Composed<First, Second>> { class Composed : public Operator<Composed<First, Second>> {
First first_; First first_;
Second second_; Second second_;
public: public:
Composed() = default; Composed() = default;
Composed(First first, Second second) Composed(First first, Second second)
: first_(std::move(first)) : first_(std::move(first)), second_(std::move(second)) {}
, second_(std::move(second)) {}
template < template <
class Source, class Source,
...@@ -348,20 +348,18 @@ class Composed : public Operator<Composed<First, Second>> { ...@@ -348,20 +348,18 @@ class Composed : public Operator<Composed<First, Second>> {
* int total = nums | sum; * int total = nums | sum;
*/ */
template <class Value, class First, class Second> template <class Value, class First, class Second>
class Chain : public GenImpl<Value, class Chain : public GenImpl<Value, Chain<Value, First, Second>> {
Chain<Value, First, Second>> {
First first_; First first_;
Second second_; Second second_;
public: public:
explicit Chain(First first, Second second) explicit Chain(First first, Second second)
: first_(std::move(first)) : first_(std::move(first)), second_(std::move(second)) {}
, second_(std::move(second)) {}
template <class Handler> template <class Handler>
bool apply(Handler&& handler) const { bool apply(Handler&& handler) const {
return first_.apply(std::forward<Handler>(handler)) return first_.apply(std::forward<Handler>(handler)) &&
&& second_.apply(std::forward<Handler>(handler)); second_.apply(std::forward<Handler>(handler));
} }
template <class Body> template <class Body>
......
...@@ -29,8 +29,7 @@ namespace detail { ...@@ -29,8 +29,7 @@ namespace detail {
class FileReader : public GenImpl<ByteRange, FileReader> { class FileReader : public GenImpl<ByteRange, FileReader> {
public: public:
FileReader(File file, std::unique_ptr<IOBuf> buffer) FileReader(File file, std::unique_ptr<IOBuf> buffer)
: file_(std::move(file)), : file_(std::move(file)), buffer_(std::move(buffer)) {
buffer_(std::move(buffer)) {
buffer_->clear(); buffer_->clear();
} }
...@@ -65,8 +64,7 @@ class FileReader : public GenImpl<ByteRange, FileReader> { ...@@ -65,8 +64,7 @@ class FileReader : public GenImpl<ByteRange, FileReader> {
class FileWriter : public Operator<FileWriter> { class FileWriter : public Operator<FileWriter> {
public: public:
FileWriter(File file, std::unique_ptr<IOBuf> buffer) FileWriter(File file, std::unique_ptr<IOBuf> buffer)
: file_(std::move(file)), : file_(std::move(file)), buffer_(std::move(buffer)) {
buffer_(std::move(buffer)) {
if (buffer_) { if (buffer_) {
buffer_->clear(); buffer_->clear();
} }
...@@ -102,8 +100,8 @@ class FileWriter : public Operator<FileWriter> { ...@@ -102,8 +100,8 @@ class FileWriter : public Operator<FileWriter> {
n = ::write(file_.fd(), v.data(), v.size()); n = ::write(file_.fd(), v.data(), v.size());
} while (n == -1 && errno == EINTR); } while (n == -1 && errno == EINTR);
if (n == -1) { if (n == -1) {
throw std::system_error(errno, std::system_category(), throw std::system_error(
"write() failed"); errno, std::system_category(), "write() failed");
} }
v.advance(size_t(n)); v.advance(size_t(n));
} }
...@@ -121,9 +119,11 @@ class FileWriter : public Operator<FileWriter> { ...@@ -121,9 +119,11 @@ class FileWriter : public Operator<FileWriter> {
}; };
inline auto byLineImpl(File file, char delim, bool keepDelimiter) { inline auto byLineImpl(File file, char delim, bool keepDelimiter) {
// clang-format off
return fromFile(std::move(file)) return fromFile(std::move(file))
| eachAs<StringPiece>() | eachAs<StringPiece>()
| resplit(delim, keepDelimiter); | resplit(delim, keepDelimiter);
// clang-format on
} }
} // namespace detail } // namespace detail
......
...@@ -35,7 +35,7 @@ class FileWriter; ...@@ -35,7 +35,7 @@ class FileWriter;
* to hold each value). * to hold each value).
*/ */
template <class S = detail::FileReader> template <class S = detail::FileReader>
S fromFile(File file, size_t bufferSize=4096) { S fromFile(File file, size_t bufferSize = 4096) {
return S(std::move(file), IOBuf::create(bufferSize)); return S(std::move(file), IOBuf::create(bufferSize));
} }
...@@ -52,7 +52,7 @@ S fromFile(File file, std::unique_ptr<IOBuf> buffer) { ...@@ -52,7 +52,7 @@ S fromFile(File file, std::unique_ptr<IOBuf> buffer) {
* If bufferSize is 0, writes will be unbuffered. * If bufferSize is 0, writes will be unbuffered.
*/ */
template <class S = detail::FileWriter> template <class S = detail::FileWriter>
S toFile(File file, size_t bufferSize=4096) { S toFile(File file, size_t bufferSize = 4096) {
return S(std::move(file), bufferSize ? nullptr : IOBuf::create(bufferSize)); return S(std::move(file), bufferSize ? nullptr : IOBuf::create(bufferSize));
} }
......
...@@ -45,8 +45,12 @@ class ClosableMPMCQueue { ...@@ -45,8 +45,12 @@ class ClosableMPMCQueue {
CHECK(!consumers()); CHECK(!consumers());
} }
void openProducer() { ++producers_; } void openProducer() {
void openConsumer() { ++consumers_; } ++producers_;
}
void openConsumer() {
++consumers_;
}
void closeInputProducer() { void closeInputProducer() {
size_t producers = producers_--; size_t producers = producers_--;
...@@ -159,13 +163,15 @@ class Parallel : public Operator<Parallel<Ops>> { ...@@ -159,13 +163,15 @@ class Parallel : public Operator<Parallel<Ops>> {
decltype(std::declval<Ops>().compose(Empty<InputDecayed&&>())), decltype(std::declval<Ops>().compose(Empty<InputDecayed&&>())),
class Output = typename Composed::ValueType, class Output = typename Composed::ValueType,
class OutputDecayed = typename std::decay<Output>::type> class OutputDecayed = typename std::decay<Output>::type>
class Generator : public GenImpl<OutputDecayed&&, class Generator : public GenImpl<
Generator<Input, OutputDecayed&&,
Source, Generator<
InputDecayed, Input,
Composed, Source,
Output, InputDecayed,
OutputDecayed>> { Composed,
Output,
OutputDecayed>> {
const Source source_; const Source source_;
const Ops ops_; const Ops ops_;
const size_t threads_; const size_t threads_;
...@@ -269,9 +275,13 @@ class Parallel : public Operator<Parallel<Ops>> { ...@@ -269,9 +275,13 @@ class Parallel : public Operator<Parallel<Ops>> {
CHECK(!outQueue_.producers()); CHECK(!outQueue_.producers());
} }
void closeInputProducer() { inQueue_.closeInputProducer(); } void closeInputProducer() {
inQueue_.closeInputProducer();
}
void closeOutputConsumer() { outQueue_.closeOutputConsumer(); } void closeOutputConsumer() {
outQueue_.closeOutputConsumer();
}
bool writeUnlessClosed(Input&& input) { bool writeUnlessClosed(Input&& input) {
return inQueue_.writeUnlessClosed(std::forward<Input>(input)); return inQueue_.writeUnlessClosed(std::forward<Input>(input));
......
...@@ -58,7 +58,6 @@ Chunked chunked(Container& container, int chunkSize = 256) { ...@@ -58,7 +58,6 @@ Chunked chunked(Container& container, int chunkSize = 256) {
return Chunked(chunkSize, folly::range(container.begin(), container.end())); return Chunked(chunkSize, folly::range(container.begin(), container.end()));
} }
/** /**
* parallel - A parallelization operator. * parallel - A parallelization operator.
* *
......
...@@ -47,12 +47,12 @@ template <class Predicate> ...@@ -47,12 +47,12 @@ template <class Predicate>
class PMap : public Operator<PMap<Predicate>> { class PMap : public Operator<PMap<Predicate>> {
Predicate pred_; Predicate pred_;
size_t nThreads_; size_t nThreads_;
public: public:
PMap() = default; PMap() = default;
PMap(Predicate pred, size_t nThreads) PMap(Predicate pred, size_t nThreads)
: pred_(std::move(pred)), : pred_(std::move(pred)), nThreads_(nThreads) {}
nThreads_(nThreads) { }
template < template <
class Value, class Value,
...@@ -75,8 +75,7 @@ class PMap : public Operator<PMap<Predicate>> { ...@@ -75,8 +75,7 @@ class PMap : public Operator<PMap<Predicate>> {
public: public:
ExecutionPipeline(const Predicate& pred, size_t nThreads) ExecutionPipeline(const Predicate& pred, size_t nThreads)
: pred_(pred), : pred_(pred), pipeline_(nThreads, nThreads) {
pipeline_(nThreads, nThreads) {
workers_.reserve(nThreads); workers_.reserve(nThreads);
for (size_t i = 0; i < nThreads; i++) { for (size_t i = 0; i < nThreads; i++) {
workers_.push_back(std::thread([this] { this->predApplier(); })); workers_.push_back(std::thread([this] { this->predApplier(); }));
...@@ -86,7 +85,9 @@ class PMap : public Operator<PMap<Predicate>> { ...@@ -86,7 +85,9 @@ class PMap : public Operator<PMap<Predicate>> {
~ExecutionPipeline() { ~ExecutionPipeline() {
assert(pipeline_.sizeGuess() == 0); assert(pipeline_.sizeGuess() == 0);
assert(done_.load()); assert(done_.load());
for (auto& w : workers_) { w.join(); } for (auto& w : workers_) {
w.join();
}
} }
void stop() { void stop() {
...@@ -131,8 +132,7 @@ class PMap : public Operator<PMap<Predicate>> { ...@@ -131,8 +132,7 @@ class PMap : public Operator<PMap<Predicate>> {
if (pipeline_.template readStage<0>(ticket, in)) { if (pipeline_.template readStage<0>(ticket, in)) {
wake_.cancelWait(); wake_.cancelWait();
Output out = pred_(std::move(in)); Output out = pred_(std::move(in));
pipeline_.template blockingWriteStage<0>(ticket, pipeline_.template blockingWriteStage<0>(ticket, std::move(out));
std::move(out));
continue; continue;
} }
...@@ -149,10 +149,9 @@ class PMap : public Operator<PMap<Predicate>> { ...@@ -149,10 +149,9 @@ class PMap : public Operator<PMap<Predicate>> {
public: public:
Generator(Source source, const Predicate& pred, size_t nThreads) Generator(Source source, const Predicate& pred, size_t nThreads)
: source_(std::move(source)), : source_(std::move(source)),
pred_(pred), pred_(pred),
nThreads_(nThreads ? nThreads : sysconf(_SC_NPROCESSORS_ONLN)) { nThreads_(nThreads ? nThreads : sysconf(_SC_NPROCESSORS_ONLN)) {}
}
template <class Body> template <class Body>
void foreach(Body&& body) const { void foreach(Body&& body) const {
......
...@@ -39,7 +39,7 @@ class PMap; ...@@ -39,7 +39,7 @@ class PMap;
* caller thread. * caller thread.
*/ */
template <class Predicate, class PMap = detail::PMap<Predicate>> template <class Predicate, class PMap = detail::PMap<Predicate>>
PMap pmap(Predicate pred = Predicate(), size_t nThreads = 0) { PMap pmap(Predicate pred = Predicate(), size_t nThreads = 0) {
return PMap(std::move(pred), nThreads); return PMap(std::move(pred), nThreads);
} }
} // namespace gen } // namespace gen
......
...@@ -34,9 +34,8 @@ namespace detail { ...@@ -34,9 +34,8 @@ namespace detail {
* Returns the number of trailing bytes of "prefix" that make up the * Returns the number of trailing bytes of "prefix" that make up the
* delimiter, or 0 if the delimiter was not found. * delimiter, or 0 if the delimiter was not found.
*/ */
inline size_t splitPrefix(StringPiece& in, inline size_t
StringPiece& prefix, splitPrefix(StringPiece& in, StringPiece& prefix, char delimiter) {
char delimiter) {
size_t found = in.find(delimiter); size_t found = in.find(delimiter);
if (found != StringPiece::npos) { if (found != StringPiece::npos) {
++found; ++found;
...@@ -51,9 +50,8 @@ inline size_t splitPrefix(StringPiece& in, ...@@ -51,9 +50,8 @@ inline size_t splitPrefix(StringPiece& in,
/** /**
* As above, but supports multibyte delimiters. * As above, but supports multibyte delimiters.
*/ */
inline size_t splitPrefix(StringPiece& in, inline size_t
StringPiece& prefix, splitPrefix(StringPiece& in, StringPiece& prefix, StringPiece delimiter) {
StringPiece delimiter) {
auto found = in.find(delimiter); auto found = in.find(delimiter);
if (found != StringPiece::npos) { if (found != StringPiece::npos) {
found += delimiter.size(); found += delimiter.size();
...@@ -68,9 +66,7 @@ inline size_t splitPrefix(StringPiece& in, ...@@ -68,9 +66,7 @@ inline size_t splitPrefix(StringPiece& in,
/** /**
* As above, but splits by any of the EOL terms: \r, \n, or \r\n. * As above, but splits by any of the EOL terms: \r, \n, or \r\n.
*/ */
inline size_t splitPrefix(StringPiece& in, inline size_t splitPrefix(StringPiece& in, StringPiece& prefix, MixedNewlines) {
StringPiece& prefix,
MixedNewlines) {
const auto kCRLF = "\r\n"; const auto kCRLF = "\r\n";
const size_t kLenCRLF = 2; const size_t kLenCRLF = 2;
...@@ -171,7 +167,7 @@ bool StreamSplitter<Callback>::operator()(StringPiece in) { ...@@ -171,7 +167,7 @@ bool StreamSplitter<Callback>::operator()(StringPiece in) {
} else if (maxLength_ && buffer_.length() + in.size() >= maxLength_) { } else if (maxLength_ && buffer_.length() + in.size() >= maxLength_) {
// Send all of buffer_, plus a bit of in, to the callback // Send all of buffer_, plus a bit of in, to the callback
if (!detail::consumeBufferPlus( if (!detail::consumeBufferPlus(
pieceCb_, buffer_, in, maxLength_ - buffer_.length())) { pieceCb_, buffer_, in, maxLength_ - buffer_.length())) {
return false; return false;
} }
// Post-conditions: // Post-conditions:
...@@ -183,7 +179,7 @@ bool StreamSplitter<Callback>::operator()(StringPiece in) { ...@@ -183,7 +179,7 @@ bool StreamSplitter<Callback>::operator()(StringPiece in) {
// len(buffer + in) < maxLength_. // len(buffer + in) < maxLength_.
// Send lines to callback directly from input (no buffer) // Send lines to callback directly from input (no buffer)
while (found) { // Buffer guaranteed to be empty while (found) { // Buffer guaranteed to be empty
if (!detail::consumeFixedSizeChunks(pieceCb_, prefix, maxLength_)) { if (!detail::consumeFixedSizeChunks(pieceCb_, prefix, maxLength_)) {
return false; return false;
} }
...@@ -192,7 +188,7 @@ bool StreamSplitter<Callback>::operator()(StringPiece in) { ...@@ -192,7 +188,7 @@ bool StreamSplitter<Callback>::operator()(StringPiece in) {
// No more delimiters left; consume 'in' until it is shorter than maxLength_ // No more delimiters left; consume 'in' until it is shorter than maxLength_
if (maxLength_) { if (maxLength_) {
while (in.size() >= maxLength_) { // Buffer is guaranteed to be empty while (in.size() >= maxLength_) { // Buffer is guaranteed to be empty
if (!pieceCb_(StringPiece(in.begin(), maxLength_))) { if (!pieceCb_(StringPiece(in.begin(), maxLength_))) {
return false; return false;
} }
...@@ -200,7 +196,7 @@ bool StreamSplitter<Callback>::operator()(StringPiece in) { ...@@ -200,7 +196,7 @@ bool StreamSplitter<Callback>::operator()(StringPiece in) {
} }
} }
if (!in.empty()) { // Buffer may be nonempty if (!in.empty()) { // Buffer may be nonempty
// Incomplete line left, append to buffer // Incomplete line left, append to buffer
buffer_.reserve(0, in.size()); buffer_.reserve(0, in.size());
memcpy(buffer_.writableTail(), in.data(), in.size()); memcpy(buffer_.writableTail(), in.data(), in.size());
...@@ -274,18 +270,17 @@ class SplitStringSource ...@@ -274,18 +270,17 @@ class SplitStringSource
: public GenImpl<StringPiece, SplitStringSource<DelimiterType>> { : public GenImpl<StringPiece, SplitStringSource<DelimiterType>> {
StringPiece source_; StringPiece source_;
DelimiterType delimiter_; DelimiterType delimiter_;
public: public:
SplitStringSource(const StringPiece source, SplitStringSource(const StringPiece source, DelimiterType delimiter)
DelimiterType delimiter) : source_(source), delimiter_(std::move(delimiter)) {}
: source_(source)
, delimiter_(std::move(delimiter)) { }
template <class Body> template <class Body>
bool apply(Body&& body) const { bool apply(Body&& body) const {
StringPiece rest(source_); StringPiece rest(source_);
StringPiece prefix; StringPiece prefix;
while (size_t delim_len = splitPrefix(rest, prefix, this->delimiter_)) { while (size_t delim_len = splitPrefix(rest, prefix, this->delimiter_)) {
prefix.subtract(delim_len); // Remove the delimiter prefix.subtract(delim_len); // Remove the delimiter
if (!body(prefix)) { if (!body(prefix)) {
return false; return false;
} }
...@@ -308,10 +303,9 @@ class SplitStringSource ...@@ -308,10 +303,9 @@ class SplitStringSource
template <class Delimiter, class Output> template <class Delimiter, class Output>
class Unsplit : public Operator<Unsplit<Delimiter, Output>> { class Unsplit : public Operator<Unsplit<Delimiter, Output>> {
Delimiter delimiter_; Delimiter delimiter_;
public: public:
explicit Unsplit(const Delimiter& delimiter) explicit Unsplit(const Delimiter& delimiter) : delimiter_(delimiter) {}
: delimiter_(delimiter) {
}
template <class Source, class Value> template <class Source, class Value>
Output compose(const GenImpl<Value, Source>& source) const { Output compose(const GenImpl<Value, Source>& source) const {
...@@ -332,10 +326,10 @@ template <class Delimiter, class OutputBuffer> ...@@ -332,10 +326,10 @@ template <class Delimiter, class OutputBuffer>
class UnsplitBuffer : public Operator<UnsplitBuffer<Delimiter, OutputBuffer>> { class UnsplitBuffer : public Operator<UnsplitBuffer<Delimiter, OutputBuffer>> {
Delimiter delimiter_; Delimiter delimiter_;
OutputBuffer* outputBuffer_; OutputBuffer* outputBuffer_;
public: public:
UnsplitBuffer(const Delimiter& delimiter, OutputBuffer* outputBuffer) UnsplitBuffer(const Delimiter& delimiter, OutputBuffer* outputBuffer)
: delimiter_(delimiter) : delimiter_(delimiter), outputBuffer_(outputBuffer) {
, outputBuffer_(outputBuffer) {
CHECK(outputBuffer); CHECK(outputBuffer);
} }
...@@ -355,18 +349,19 @@ class UnsplitBuffer : public Operator<UnsplitBuffer<Delimiter, OutputBuffer>> { ...@@ -355,18 +349,19 @@ class UnsplitBuffer : public Operator<UnsplitBuffer<Delimiter, OutputBuffer>> {
} }
}; };
/** /**
* Hack for static for-like constructs * Hack for static for-like constructs
*/ */
template <class Target, class = void> template <class Target, class = void>
inline Target passthrough(Target target) { return target; } inline Target passthrough(Target target) {
return target;
}
FOLLY_PUSH_WARNING FOLLY_PUSH_WARNING
#ifdef __clang__ #ifdef __clang__
// Clang isn't happy with eatField() hack below. // Clang isn't happy with eatField() hack below.
#pragma GCC diagnostic ignored "-Wreturn-stack-address" #pragma GCC diagnostic ignored "-Wreturn-stack-address"
#endif // __clang__ #endif // __clang__
/** /**
* ParseToTuple - For splitting a record and immediatlely converting it to a * ParseToTuple - For splitting a record and immediatlely converting it to a
...@@ -381,9 +376,9 @@ FOLLY_PUSH_WARNING ...@@ -381,9 +376,9 @@ FOLLY_PUSH_WARNING
template <class TargetContainer, class Delimiter, class... Targets> template <class TargetContainer, class Delimiter, class... Targets>
class SplitTo { class SplitTo {
Delimiter delimiter_; Delimiter delimiter_;
public: public:
explicit SplitTo(Delimiter delimiter) explicit SplitTo(Delimiter delimiter) : delimiter_(delimiter) {}
: delimiter_(delimiter) {}
TargetContainer operator()(StringPiece line) const { TargetContainer operator()(StringPiece line) const {
int i = 0; int i = 0;
...@@ -391,9 +386,10 @@ class SplitTo { ...@@ -391,9 +386,10 @@ class SplitTo {
// HACK(tjackson): Used for referencing fields[] corresponding to variadic // HACK(tjackson): Used for referencing fields[] corresponding to variadic
// template parameters. // template parameters.
auto eatField = [&]() -> StringPiece& { return fields[i++]; }; auto eatField = [&]() -> StringPiece& { return fields[i++]; };
if (!split(delimiter_, if (!split(
line, delimiter_,
detail::passthrough<StringPiece&, Targets>(eatField())...)) { line,
detail::passthrough<StringPiece&, Targets>(eatField())...)) {
throw std::runtime_error("field count mismatch"); throw std::runtime_error("field count mismatch");
} }
i = 0; i = 0;
......
...@@ -92,7 +92,6 @@ S lines(StringPiece source) { ...@@ -92,7 +92,6 @@ S lines(StringPiece source) {
* assert(result == "a b c"); * assert(result == "a b c");
*/ */
// NOTE: The template arguments are reversed to allow the user to cleanly // NOTE: The template arguments are reversed to allow the user to cleanly
// specify the output type while still inferring the type of the delimiter. // specify the output type while still inferring the type of the delimiter.
template < template <
...@@ -142,34 +141,33 @@ UnsplitBuffer unsplit(const char* delimiter, OutputBuffer* outputBuffer) { ...@@ -142,34 +141,33 @@ UnsplitBuffer unsplit(const char* delimiter, OutputBuffer* outputBuffer) {
template <class... Targets> template <class... Targets>
detail::Map<detail::SplitTo<std::tuple<Targets...>, char, Targets...>> detail::Map<detail::SplitTo<std::tuple<Targets...>, char, Targets...>>
eachToTuple(char delim) { eachToTuple(char delim) {
return detail::Map< return detail::Map<detail::SplitTo<std::tuple<Targets...>, char, Targets...>>(
detail::SplitTo<std::tuple<Targets...>, char, Targets...>>( detail::SplitTo<std::tuple<Targets...>, char, Targets...>(delim));
detail::SplitTo<std::tuple<Targets...>, char, Targets...>(delim));
} }
template <class... Targets> template <class... Targets>
detail::Map<detail::SplitTo<std::tuple<Targets...>, fbstring, Targets...>> detail::Map<detail::SplitTo<std::tuple<Targets...>, fbstring, Targets...>>
eachToTuple(StringPiece delim) { eachToTuple(StringPiece delim) {
return detail::Map< return detail::Map<
detail::SplitTo<std::tuple<Targets...>, fbstring, Targets...>>( detail::SplitTo<std::tuple<Targets...>, fbstring, Targets...>>(
detail::SplitTo<std::tuple<Targets...>, fbstring, Targets...>(delim)); detail::SplitTo<std::tuple<Targets...>, fbstring, Targets...>(delim));
} }
template <class First, class Second> template <class First, class Second>
detail::Map<detail::SplitTo<std::pair<First, Second>, char, First, Second>> detail::Map<detail::SplitTo<std::pair<First, Second>, char, First, Second>>
eachToPair(char delim) { eachToPair(char delim) {
return detail::Map< return detail::Map<
detail::SplitTo<std::pair<First, Second>, char, First, Second>>( detail::SplitTo<std::pair<First, Second>, char, First, Second>>(
detail::SplitTo<std::pair<First, Second>, char, First, Second>(delim)); detail::SplitTo<std::pair<First, Second>, char, First, Second>(delim));
} }
template <class First, class Second> template <class First, class Second>
detail::Map<detail::SplitTo<std::pair<First, Second>, fbstring, First, Second>> detail::Map<detail::SplitTo<std::pair<First, Second>, fbstring, First, Second>>
eachToPair(StringPiece delim) { eachToPair(StringPiece delim) {
return detail::Map< return detail::Map<
detail::SplitTo<std::pair<First, Second>, fbstring, First, Second>>( detail::SplitTo<std::pair<First, Second>, fbstring, First, Second>>(
detail::SplitTo<std::pair<First, Second>, fbstring, First, Second>( detail::SplitTo<std::pair<First, Second>, fbstring, First, Second>(
to<fbstring>(delim))); to<fbstring>(delim)));
} }
/** /**
...@@ -196,12 +194,12 @@ eachToPair(StringPiece delim) { ...@@ -196,12 +194,12 @@ eachToPair(StringPiece delim) {
*/ */
template <class Callback> template <class Callback>
class StreamSplitter { class StreamSplitter {
public: public:
StreamSplitter(char delimiter, StreamSplitter(
Callback&& pieceCb, char delimiter,
uint64_t maxLength = 0, Callback&& pieceCb,
uint64_t initialCapacity = 0) uint64_t maxLength = 0,
uint64_t initialCapacity = 0)
: buffer_(IOBuf::CREATE, initialCapacity), : buffer_(IOBuf::CREATE, initialCapacity),
delimiter_(delimiter), delimiter_(delimiter),
maxLength_(maxLength), maxLength_(maxLength),
...@@ -232,14 +230,13 @@ class StreamSplitter { ...@@ -232,14 +230,13 @@ class StreamSplitter {
// Holds the current "incomplete" chunk so that chunks can span calls to () // Holds the current "incomplete" chunk so that chunks can span calls to ()
IOBuf buffer_; IOBuf buffer_;
char delimiter_; char delimiter_;
uint64_t maxLength_; // The callback never gets more chars than this uint64_t maxLength_; // The callback never gets more chars than this
Callback pieceCb_; Callback pieceCb_;
}; };
template <class Callback> // Helper to enable template deduction template <class Callback> // Helper to enable template deduction
StreamSplitter<Callback> streamSplitter(char delimiter, StreamSplitter<Callback>
Callback&& pieceCb, streamSplitter(char delimiter, Callback&& pieceCb, uint64_t capacity = 0) {
uint64_t capacity = 0) {
return StreamSplitter<Callback>(delimiter, std::move(pieceCb), capacity); return StreamSplitter<Callback>(delimiter, std::move(pieceCb), capacity);
} }
......
...@@ -25,10 +25,11 @@ using namespace folly::gen; ...@@ -25,10 +25,11 @@ using namespace folly::gen;
using folly::fbstring; using folly::fbstring;
using std::pair; using std::pair;
using std::set; using std::set;
using std::vector;
using std::tuple; using std::tuple;
using std::vector;
static std::atomic<int> testSize(1000); static std::atomic<int> testSize(1000);
// clang-format off
static vector<int> testVector = static vector<int> testVector =
seq(1, testSize.load()) seq(1, testSize.load())
| mapped([](int) { return rand(); }) | mapped([](int) { return rand(); })
...@@ -44,6 +45,7 @@ static vector<fbstring> strings = ...@@ -44,6 +45,7 @@ static vector<fbstring> strings =
from(testVector) from(testVector)
| eachTo<fbstring>() | eachTo<fbstring>()
| as<vector>(); | as<vector>();
// clang-format on
auto square = [](int x) { return x * x; }; auto square = [](int x) { return x * x; };
...@@ -91,20 +93,24 @@ BENCHMARK_DRAW_LINE(); ...@@ -91,20 +93,24 @@ BENCHMARK_DRAW_LINE();
BENCHMARK(Member, iters) { BENCHMARK(Member, iters) {
int s = 0; int s = 0;
while(iters--) { while (iters--) {
// clang-format off
s += from(strings) s += from(strings)
| member(&fbstring::size) | member(&fbstring::size)
| sum; | sum;
// clang-format on
} }
folly::doNotOptimizeAway(s); folly::doNotOptimizeAway(s);
} }
BENCHMARK_RELATIVE(MapMember, iters) { BENCHMARK_RELATIVE(MapMember, iters) {
int s = 0; int s = 0;
while(iters--) { while (iters--) {
// clang-format off
s += from(strings) s += from(strings)
| map([](const fbstring& x) { return x.size(); }) | map([](const fbstring& x) { return x.size(); })
| sum; | sum;
// clang-format on
} }
folly::doNotOptimizeAway(s); folly::doNotOptimizeAway(s);
} }
...@@ -126,11 +132,13 @@ BENCHMARK(Count_Vector_NoGen, iters) { ...@@ -126,11 +132,13 @@ BENCHMARK(Count_Vector_NoGen, iters) {
BENCHMARK_RELATIVE(Count_Vector_Gen, iters) { BENCHMARK_RELATIVE(Count_Vector_Gen, iters) {
int s = 0; int s = 0;
while (iters--) { while (iters--) {
// clang-format off
s += from(testVector) s += from(testVector)
| filter([](int i) { | filter([](int i) {
return i * 2 < rand(); return i * 2 < rand();
}) })
| count; | count;
// clang-format on
} }
folly::doNotOptimizeAway(s); folly::doNotOptimizeAway(s);
} }
...@@ -356,7 +364,7 @@ BENCHMARK(Sample, iters) { ...@@ -356,7 +364,7 @@ BENCHMARK(Sample, iters) {
// Sample 176.48ms 5.67 // Sample 176.48ms 5.67
// ============================================================================ // ============================================================================
int main(int argc, char *argv[]) { int main(int argc, char* argv[]) {
gflags::ParseCommandLineFlags(&argc, &argv, true); gflags::ParseCommandLineFlags(&argc, &argv, true);
folly::runBenchmarks(); folly::runBenchmarks();
return 0; return 0;
......
This diff is collapsed.
...@@ -18,15 +18,18 @@ ...@@ -18,15 +18,18 @@
#include <folly/Benchmark.h> #include <folly/Benchmark.h>
#define BENCH_GEN_IMPL(gen, prefix) \ #define BENCH_GEN_IMPL(gen, prefix) \
static bool FB_ANONYMOUS_VARIABLE(benchGen) = ( \ static bool FB_ANONYMOUS_VARIABLE(benchGen) = \
::folly::addBenchmark(__FILE__, prefix FB_STRINGIZE(gen), \ (::folly::addBenchmark( \
[](unsigned iters){ \ __FILE__, \
const unsigned num = iters; \ prefix FB_STRINGIZE(gen), \
while (iters--) { \ [](unsigned iters) { \
folly::doNotOptimizeAway(gen); \ const unsigned num = iters; \
} \ while (iters--) { \
return num; \ folly::doNotOptimizeAway(gen); \
}), true) } \
return num; \
}), \
true)
#define BENCH_GEN(gen) BENCH_GEN_IMPL(gen, "") #define BENCH_GEN(gen) BENCH_GEN_IMPL(gen, "")
#define BENCH_GEN_REL(gen) BENCH_GEN_IMPL(gen, "%") #define BENCH_GEN_REL(gen) BENCH_GEN_IMPL(gen, "%")
...@@ -26,11 +26,10 @@ ...@@ -26,11 +26,10 @@
using namespace folly::gen; using namespace folly::gen;
using namespace folly; using namespace folly;
using std::string; using std::string;
using std::vector;
using std::tuple; using std::tuple;
using std::vector;
const folly::gen::detail::Map< const folly::gen::detail::Map<folly::gen::detail::MergeTuples> gTupleFlatten{};
folly::gen::detail::MergeTuples> gTupleFlatten{};
auto even = [](int i) -> bool { return i % 2 == 0; }; auto even = [](int i) -> bool { return i % 2 == 0; };
auto odd = [](int i) -> bool { return i % 2 == 1; }; auto odd = [](int i) -> bool { return i % 2 == 1; };
...@@ -46,8 +45,7 @@ TEST(CombineGen, Interleave) { ...@@ -46,8 +45,7 @@ TEST(CombineGen, Interleave) {
auto base = seq(1) | filter(odd) | take(3); auto base = seq(1) | filter(odd) | take(3);
auto toInterleave = seq(1) | filter(even) | take(50); auto toInterleave = seq(1) | filter(even) | take(50);
auto interleaved = base | interleave(toInterleave | as<vector>()); auto interleaved = base | interleave(toInterleave | as<vector>());
EXPECT_EQ(interleaved | as<vector>(), EXPECT_EQ(interleaved | as<vector>(), vector<int>({1, 2, 3, 4, 5, 6}));
vector<int>({1, 2, 3, 4, 5, 6}));
} }
} }
...@@ -56,9 +54,7 @@ TEST(CombineGen, Zip) { ...@@ -56,9 +54,7 @@ TEST(CombineGen, Zip) {
// We rely on std::move(fbvector) emptying the source vector // We rely on std::move(fbvector) emptying the source vector
auto zippee = fbvector<string>{"one", "two", "three"}; auto zippee = fbvector<string>{"one", "two", "three"};
{ {
auto combined = base0 auto combined = base0 | zip(zippee) | as<vector>();
| zip(zippee)
| as<vector>();
ASSERT_EQ(combined.size(), 3); ASSERT_EQ(combined.size(), 3);
EXPECT_EQ(std::get<0>(combined[0]), 1); EXPECT_EQ(std::get<0>(combined[0]), 1);
EXPECT_EQ(std::get<1>(combined[0]), "one"); EXPECT_EQ(std::get<1>(combined[0]), "one");
...@@ -67,13 +63,11 @@ TEST(CombineGen, Zip) { ...@@ -67,13 +63,11 @@ TEST(CombineGen, Zip) {
EXPECT_EQ(std::get<0>(combined[2]), 3); EXPECT_EQ(std::get<0>(combined[2]), 3);
EXPECT_EQ(std::get<1>(combined[2]), "three"); EXPECT_EQ(std::get<1>(combined[2]), "three");
ASSERT_FALSE(zippee.empty()); ASSERT_FALSE(zippee.empty());
EXPECT_FALSE(zippee.front().empty()); // shouldn't have been move'd EXPECT_FALSE(zippee.front().empty()); // shouldn't have been move'd
} }
{ // same as top, but using std::move. { // same as top, but using std::move.
auto combined = base0 auto combined = base0 | zip(std::move(zippee)) | as<vector>();
| zip(std::move(zippee))
| as<vector>();
ASSERT_EQ(combined.size(), 3); ASSERT_EQ(combined.size(), 3);
EXPECT_EQ(std::get<0>(combined[0]), 1); EXPECT_EQ(std::get<0>(combined[0]), 1);
EXPECT_TRUE(zippee.empty()); EXPECT_TRUE(zippee.empty());
...@@ -81,9 +75,8 @@ TEST(CombineGen, Zip) { ...@@ -81,9 +75,8 @@ TEST(CombineGen, Zip) {
{ // same as top, but base is truncated { // same as top, but base is truncated
auto baseFinite = seq(1) | take(1); auto baseFinite = seq(1) | take(1);
auto combined = baseFinite auto combined =
| zip(vector<string>{"one", "two", "three"}) baseFinite | zip(vector<string>{"one", "two", "three"}) | as<vector>();
| as<vector>();
ASSERT_EQ(combined.size(), 1); ASSERT_EQ(combined.size(), 1);
EXPECT_EQ(std::get<0>(combined[0]), 1); EXPECT_EQ(std::get<0>(combined[0]), 1);
EXPECT_EQ(std::get<1>(combined[0]), "one"); EXPECT_EQ(std::get<1>(combined[0]), "one");
...@@ -91,66 +84,77 @@ TEST(CombineGen, Zip) { ...@@ -91,66 +84,77 @@ TEST(CombineGen, Zip) {
} }
TEST(CombineGen, TupleFlatten) { TEST(CombineGen, TupleFlatten) {
vector<tuple<int,string>> intStringTupleVec{ vector<tuple<int, string>> intStringTupleVec{
tuple<int,string>{1, "1"}, tuple<int, string>{1, "1"},
tuple<int,string>{2, "2"}, tuple<int, string>{2, "2"},
tuple<int,string>{3, "3"}, tuple<int, string>{3, "3"},
}; };
vector<tuple<char>> charTupleVec{ vector<tuple<char>> charTupleVec{
tuple<char>{'A'}, tuple<char>{'A'},
tuple<char>{'B'}, tuple<char>{'B'},
tuple<char>{'C'}, tuple<char>{'C'},
tuple<char>{'D'}, tuple<char>{'D'},
}; };
vector<double> doubleVec{ vector<double> doubleVec{
1.0, 1.0,
4.0, 4.0,
9.0, 9.0,
16.0, 16.0,
25.0, 25.0,
}; };
// clang-format off
auto zipped1 = from(intStringTupleVec) auto zipped1 = from(intStringTupleVec)
| zip(charTupleVec) | zip(charTupleVec)
| assert_type<tuple<tuple<int, string>, tuple<char>>>() | assert_type<tuple<tuple<int, string>, tuple<char>>>()
| as<vector>(); | as<vector>();
// clang-format on
EXPECT_EQ(std::get<0>(zipped1[0]), std::make_tuple(1, "1")); EXPECT_EQ(std::get<0>(zipped1[0]), std::make_tuple(1, "1"));
EXPECT_EQ(std::get<1>(zipped1[0]), std::make_tuple('A')); EXPECT_EQ(std::get<1>(zipped1[0]), std::make_tuple('A'));
// clang-format off
auto zipped2 = from(zipped1) auto zipped2 = from(zipped1)
| gTupleFlatten | gTupleFlatten
| assert_type<tuple<int, string, char>&&>() | assert_type<tuple<int, string, char>&&>()
| as<vector>(); | as<vector>();
// clang-format on
ASSERT_EQ(zipped2.size(), 3); ASSERT_EQ(zipped2.size(), 3);
EXPECT_EQ(zipped2[0], std::make_tuple(1, "1", 'A')); EXPECT_EQ(zipped2[0], std::make_tuple(1, "1", 'A'));
// clang-format off
auto zipped3 = from(charTupleVec) auto zipped3 = from(charTupleVec)
| zip(intStringTupleVec) | zip(intStringTupleVec)
| gTupleFlatten | gTupleFlatten
| assert_type<tuple<char, int, string>&&>() | assert_type<tuple<char, int, string>&&>()
| as<vector>(); | as<vector>();
// clang-format on
ASSERT_EQ(zipped3.size(), 3); ASSERT_EQ(zipped3.size(), 3);
EXPECT_EQ(zipped3[0], std::make_tuple('A', 1, "1")); EXPECT_EQ(zipped3[0], std::make_tuple('A', 1, "1"));
// clang-format off
auto zipped4 = from(intStringTupleVec) auto zipped4 = from(intStringTupleVec)
| zip(doubleVec) | zip(doubleVec)
| gTupleFlatten | gTupleFlatten
| assert_type<tuple<int, string, double>&&>() | assert_type<tuple<int, string, double>&&>()
| as<vector>(); | as<vector>();
// clang-format on
ASSERT_EQ(zipped4.size(), 3); ASSERT_EQ(zipped4.size(), 3);
EXPECT_EQ(zipped4[0], std::make_tuple(1, "1", 1.0)); EXPECT_EQ(zipped4[0], std::make_tuple(1, "1", 1.0));
// clang-format off
auto zipped5 = from(doubleVec) auto zipped5 = from(doubleVec)
| zip(doubleVec) | zip(doubleVec)
| assert_type<tuple<double, double>>() | assert_type<tuple<double, double>>()
| gTupleFlatten // essentially a no-op | gTupleFlatten // essentially a no-op
| assert_type<tuple<double, double>&&>() | assert_type<tuple<double, double>&&>()
| as<vector>(); | as<vector>();
// clang-format on
ASSERT_EQ(zipped5.size(), 5); ASSERT_EQ(zipped5.size(), 5);
EXPECT_EQ(zipped5[0], std::make_tuple(1.0, 1.0)); EXPECT_EQ(zipped5[0], std::make_tuple(1.0, 1.0));
// clang-format off
auto zipped6 = from(intStringTupleVec) auto zipped6 = from(intStringTupleVec)
| zip(charTupleVec) | zip(charTupleVec)
| gTupleFlatten | gTupleFlatten
...@@ -158,11 +162,12 @@ TEST(CombineGen, TupleFlatten) { ...@@ -158,11 +162,12 @@ TEST(CombineGen, TupleFlatten) {
| gTupleFlatten | gTupleFlatten
| assert_type<tuple<int, string, char, double>&&>() | assert_type<tuple<int, string, char, double>&&>()
| as<vector>(); | as<vector>();
// clang-format on
ASSERT_EQ(zipped6.size(), 3); ASSERT_EQ(zipped6.size(), 3);
EXPECT_EQ(zipped6[0], std::make_tuple(1, "1", 'A', 1.0)); EXPECT_EQ(zipped6[0], std::make_tuple(1, "1", 'A', 1.0));
} }
int main(int argc, char *argv[]) { int main(int argc, char* argv[]) {
testing::InitGoogleTest(&argc, argv); testing::InitGoogleTest(&argc, argv);
gflags::ParseCommandLineFlags(&argc, &argv, true); gflags::ParseCommandLineFlags(&argc, &argv, true);
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();
......
...@@ -36,7 +36,7 @@ BENCHMARK(ByLine_Pipes, iters) { ...@@ -36,7 +36,7 @@ BENCHMARK(ByLine_Pipes, iters) {
wfd = p[1]; wfd = p[1];
thread = std::thread([wfd, iters] { thread = std::thread([wfd, iters] {
char x = 'x'; char x = 'x';
PCHECK(::write(wfd, &x, 1) == 1); // signal startup PCHECK(::write(wfd, &x, 1) == 1); // signal startup
FILE* f = fdopen(wfd, "w"); FILE* f = fdopen(wfd, "w");
PCHECK(f); PCHECK(f);
for (size_t i = 1; i <= iters; ++i) { for (size_t i = 1; i <= iters; ++i) {
...@@ -45,7 +45,7 @@ BENCHMARK(ByLine_Pipes, iters) { ...@@ -45,7 +45,7 @@ BENCHMARK(ByLine_Pipes, iters) {
fclose(f); fclose(f);
}); });
char buf; char buf;
PCHECK(::read(rfd, &buf, 1) == 1); // wait for startup PCHECK(::read(rfd, &buf, 1) == 1); // wait for startup
} }
CHECK_ERR(rfd); CHECK_ERR(rfd);
...@@ -66,7 +66,7 @@ BENCHMARK(ByLine_Pipes, iters) { ...@@ -66,7 +66,7 @@ BENCHMARK(ByLine_Pipes, iters) {
// ByLine_Pipes 148.63ns 6.73M // ByLine_Pipes 148.63ns 6.73M
// ============================================================================ // ============================================================================
int main(int argc, char *argv[]) { int main(int argc, char* argv[]) {
gflags::ParseCommandLineFlags(&argc, &argv, true); gflags::ParseCommandLineFlags(&argc, &argv, true);
folly::runBenchmarks(); folly::runBenchmarks();
return 0; return 0;
......
...@@ -58,8 +58,8 @@ TEST(FileGen, ByLine) { ...@@ -58,8 +58,8 @@ TEST(FileGen, ByLine) {
} }
TEST(FileGen, ByLineFull) { TEST(FileGen, ByLineFull) {
auto cases = std::vector<std::string> { auto cases = std::vector<std::string>{
stripLeftMargin(R"( stripLeftMargin(R"(
Hello world Hello world
This is the second line This is the second line
...@@ -67,11 +67,12 @@ TEST(FileGen, ByLineFull) { ...@@ -67,11 +67,12 @@ TEST(FileGen, ByLineFull) {
a few empty lines above a few empty lines above
incomplete last line)"), incomplete last line)"),
"complete last line\n", "complete last line\n",
"\n", "\n",
""}; "",
};
for (auto& lines : cases) { for (auto& lines : cases) {
test::TemporaryFile file("ByLineFull"); test::TemporaryFile file("ByLineFull");
...@@ -113,8 +114,9 @@ TEST(FileGenBufferedTest, FileWriterSimple) { ...@@ -113,8 +114,9 @@ TEST(FileGenBufferedTest, FileWriterSimple) {
auto squares = seq(1, 100) | map([](int x) { return x * x; }); auto squares = seq(1, 100) | map([](int x) { return x * x; });
squares | map(toLine) | eachAs<StringPiece>() | toFile(File(file.fd())); squares | map(toLine) | eachAs<StringPiece>() | toFile(File(file.fd()));
EXPECT_EQ(squares | sum, EXPECT_EQ(
byLine(File(file.path().string().c_str())) | eachTo<int>() | sum); squares | sum,
byLine(File(file.path().string().c_str())) | eachTo<int>() | sum);
} }
INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P(
......
...@@ -25,17 +25,18 @@ ...@@ -25,17 +25,18 @@
#include <folly/gen/Parallel.h> #include <folly/gen/Parallel.h>
#include <folly/gen/test/Bench.h> #include <folly/gen/test/Bench.h>
DEFINE_int32(
DEFINE_int32(threads, threads,
std::max(1, (int32_t) sysconf(_SC_NPROCESSORS_CONF) / 2), std::max(1, (int32_t)sysconf(_SC_NPROCESSORS_CONF) / 2),
"Num threads."); "Num threads.");
using namespace folly::gen; using namespace folly::gen;
using std::vector; using std::vector;
constexpr int kFib = 28; // unit of work
constexpr int kFib = 28; // unit of work size_t fib(int n) {
size_t fib(int n) { return n <= 1 ? 1 : fib(n - 1) + fib(n - 2); } return n <= 1 ? 1 : fib(n - 1) + fib(n - 2);
}
static auto isPrimeSlow = [](int n) { static auto isPrimeSlow = [](int n) {
if (n < 2) { if (n < 2) {
...@@ -50,8 +51,7 @@ static auto isPrimeSlow = [](int n) { ...@@ -50,8 +51,7 @@ static auto isPrimeSlow = [](int n) {
return true; return true;
}; };
static auto primes = static auto primes = seq(1, 1 << 20) | filter(isPrimeSlow) | as<vector>();
seq(1, 1 << 20) | filter(isPrimeSlow) | as<vector>();
static auto stopc(int n) { static auto stopc(int n) {
return [=](int d) { return d * d > n; }; return [=](int d) { return d * d > n; };
...@@ -78,9 +78,7 @@ static auto sleepyWork = [](int i) { ...@@ -78,9 +78,7 @@ static auto sleepyWork = [](int i) {
return i; return i;
}; };
static auto sleepAndWork = [](int i) { static auto sleepAndWork = [](int i) { return factorsSlow(i) + sleepyWork(i); };
return factorsSlow(i) + sleepyWork(i);
};
auto start = 1 << 20; auto start = 1 << 20;
auto v = seq(start) | take(1 << 20) | as<vector>(); auto v = seq(start) | take(1 << 20) | as<vector>();
...@@ -116,19 +114,26 @@ BENCHMARK_DRAW_LINE(); ...@@ -116,19 +114,26 @@ BENCHMARK_DRAW_LINE();
const int fibs = 1000; const int fibs = 1000;
BENCH_GEN(seq(1, fibs) | map([](int) { return fib(kFib); }) | sum); BENCH_GEN(seq(1, fibs) | map([](int) { return fib(kFib); }) | sum);
BENCH_GEN_REL(seq(1, fibs) | // clang-format off
parallel(map([](int) { return fib(kFib); }) | sub(sum)) | sum); BENCH_GEN_REL(
seq(1, fibs)
| parallel(map([](int) { return fib(kFib); }) | sub(sum))
| sum);
// clang-format on
BENCH_GEN_REL([] { BENCH_GEN_REL([] {
// clang-format off
auto threads = seq(1, int(FLAGS_threads)) auto threads = seq(1, int(FLAGS_threads))
| map([](int i) { | map([](int i) {
return std::thread([=] { return std::thread([=] {
return range((i + 0) * fibs / FLAGS_threads, return range(
(i + 1) * fibs / FLAGS_threads) | (i + 0) * fibs / FLAGS_threads, (i + 1) * fibs / FLAGS_threads)
map([](int) { return fib(kFib); }) | sum; | map([](int) { return fib(kFib); })
}); | sum;
}) });
| as<vector>(); })
| as<vector>();
from(threads) | [](std::thread &thread) { thread.join(); }; from(threads) | [](std::thread &thread) { thread.join(); };
// clang-format on
return 1; return 1;
}()); }());
BENCHMARK_DRAW_LINE(); BENCHMARK_DRAW_LINE();
...@@ -160,7 +165,7 @@ seq(1, fibs) | parallel(map([](int) { return fi 1698.07% 87.96ms 11.37 ...@@ -160,7 +165,7 @@ seq(1, fibs) | parallel(map([](int) { return fi 1698.07% 87.96ms 11.37
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
============================================================================ ============================================================================
#endif #endif
int main(int argc, char *argv[]) { int main(int argc, char* argv[]) {
gflags::ParseCommandLineFlags(&argc, &argv, true); gflags::ParseCommandLineFlags(&argc, &argv, true);
folly::runBenchmarks(); folly::runBenchmarks();
return 0; return 0;
......
...@@ -26,18 +26,18 @@ ...@@ -26,18 +26,18 @@
using namespace folly::gen; using namespace folly::gen;
DEFINE_int32(threads, DEFINE_int32(
std::max(1, (int32_t) sysconf(_SC_NPROCESSORS_CONF) / 2), threads,
"Num threads."); std::max(1, (int32_t)sysconf(_SC_NPROCESSORS_CONF) / 2),
"Num threads.");
constexpr int kFib = 35; // unit of work constexpr int kFib = 35; // unit of work
size_t fib(int n) { return n <= 1 ? 1 : fib(n-1) * fib(n-2); } size_t fib(int n) {
return n <= 1 ? 1 : fib(n - 1) * fib(n - 2);
}
BENCHMARK(FibSumMap, n) { BENCHMARK(FibSumMap, n) {
auto result = auto result = seq(1, (int)n) | map([](int) { return fib(kFib); }) | sum;
seq(1, (int) n)
| map([](int) { return fib(kFib); })
| sum;
folly::doNotOptimizeAway(result); folly::doNotOptimizeAway(result);
} }
...@@ -45,10 +45,12 @@ BENCHMARK_RELATIVE(FibSumPmap, n) { ...@@ -45,10 +45,12 @@ BENCHMARK_RELATIVE(FibSumPmap, n) {
// Schedule more work: enough so that each worker thread does the // Schedule more work: enough so that each worker thread does the
// same amount as one FibSumMap. // same amount as one FibSumMap.
const size_t kNumThreads = FLAGS_threads; const size_t kNumThreads = FLAGS_threads;
// clang-format off
auto result = auto result =
seq(1, (int) (n * kNumThreads)) seq(1, (int)(n * kNumThreads))
| pmap([](int) { return fib(kFib); }, kNumThreads) | pmap([](int) { return fib(kFib); }, kNumThreads)
| sum; | sum;
// clang-format on
folly::doNotOptimizeAway(result); folly::doNotOptimizeAway(result);
} }
...@@ -58,16 +60,15 @@ BENCHMARK_RELATIVE(FibSumThreads, n) { ...@@ -58,16 +60,15 @@ BENCHMARK_RELATIVE(FibSumThreads, n) {
std::vector<std::thread> workers; std::vector<std::thread> workers;
workers.reserve(kNumThreads); workers.reserve(kNumThreads);
auto fn = [n] { auto fn = [n] {
auto result = auto result = seq(1, (int)n) | map([](int) { return fib(kFib); }) | sum;
seq(1, (int) n)
| map([](int) { return fib(kFib); })
| sum;
folly::doNotOptimizeAway(result); folly::doNotOptimizeAway(result);
}; };
for (size_t i = 0; i < kNumThreads; i++) { for (size_t i = 0; i < kNumThreads; i++) {
workers.push_back(std::thread(fn)); workers.push_back(std::thread(fn));
} }
for (auto& w : workers) { w.join(); } for (auto& w : workers) {
w.join();
}
} }
/* /*
...@@ -84,7 +85,7 @@ BENCHMARK_RELATIVE(FibSumThreads, n) { ...@@ -84,7 +85,7 @@ BENCHMARK_RELATIVE(FibSumThreads, n) {
sys0m0.016s sys0m0.016s
*/ */
int main(int argc, char *argv[]) { int main(int argc, char* argv[]) {
gflags::ParseCommandLineFlags(&argc, &argv, true); gflags::ParseCommandLineFlags(&argc, &argv, true);
folly::runBenchmarks(); folly::runBenchmarks();
return 0; return 0;
......
...@@ -29,6 +29,7 @@ using namespace folly::gen; ...@@ -29,6 +29,7 @@ using namespace folly::gen;
TEST(Pmap, InfiniteEquivalent) { TEST(Pmap, InfiniteEquivalent) {
// apply // apply
{ {
// clang-format off
auto mapResult auto mapResult
= seq(1) = seq(1)
| map([](int x) { return x * x; }) | map([](int x) { return x * x; })
...@@ -40,12 +41,14 @@ TEST(Pmap, InfiniteEquivalent) { ...@@ -40,12 +41,14 @@ TEST(Pmap, InfiniteEquivalent) {
| pmap([](int x) { return x * x; }, 4) | pmap([](int x) { return x * x; }, 4)
| until([](int x) { return x > 1000 * 1000; }) | until([](int x) { return x > 1000 * 1000; })
| as<std::vector<int>>(); | as<std::vector<int>>();
// clang-format on
EXPECT_EQ(pmapResult, mapResult); EXPECT_EQ(pmapResult, mapResult);
} }
// foreach // foreach
{ {
// clang-format off
auto mapResult auto mapResult
= seq(1, 10) = seq(1, 10)
| map([](int x) { return x * x; }) | map([](int x) { return x * x; })
...@@ -55,6 +58,7 @@ TEST(Pmap, InfiniteEquivalent) { ...@@ -55,6 +58,7 @@ TEST(Pmap, InfiniteEquivalent) {
= seq(1, 10) = seq(1, 10)
| pmap([](int x) { return x * x; }, 4) | pmap([](int x) { return x * x; }, 4)
| as<std::vector<int>>(); | as<std::vector<int>>();
// clang-format on
EXPECT_EQ(pmapResult, mapResult); EXPECT_EQ(pmapResult, mapResult);
} }
...@@ -63,6 +67,7 @@ TEST(Pmap, InfiniteEquivalent) { ...@@ -63,6 +67,7 @@ TEST(Pmap, InfiniteEquivalent) {
TEST(Pmap, Empty) { TEST(Pmap, Empty) {
// apply // apply
{ {
// clang-format off
auto mapResult auto mapResult
= seq(1) = seq(1)
| map([](int x) { return x * x; }) | map([](int x) { return x * x; })
...@@ -74,6 +79,7 @@ TEST(Pmap, Empty) { ...@@ -74,6 +79,7 @@ TEST(Pmap, Empty) {
| pmap([](int x) { return x * x; }, 4) | pmap([](int x) { return x * x; }, 4)
| until([](int) { return true; }) | until([](int) { return true; })
| as<std::vector<int>>(); | as<std::vector<int>>();
// clang-format on
EXPECT_EQ(mapResult.size(), 0); EXPECT_EQ(mapResult.size(), 0);
EXPECT_EQ(pmapResult, mapResult); EXPECT_EQ(pmapResult, mapResult);
...@@ -81,6 +87,7 @@ TEST(Pmap, Empty) { ...@@ -81,6 +87,7 @@ TEST(Pmap, Empty) {
// foreach // foreach
{ {
// clang-format off
auto mapResult auto mapResult
= empty<int>() = empty<int>()
| map([](int x) { return x * x; }) | map([](int x) { return x * x; })
...@@ -90,6 +97,7 @@ TEST(Pmap, Empty) { ...@@ -90,6 +97,7 @@ TEST(Pmap, Empty) {
= empty<int>() = empty<int>()
| pmap([](int x) { return x * x; }, 4) | pmap([](int x) { return x * x; }, 4)
| as<std::vector<int>>(); | as<std::vector<int>>();
// clang-format on
EXPECT_EQ(mapResult.size(), 0); EXPECT_EQ(mapResult.size(), 0);
EXPECT_EQ(pmapResult, mapResult); EXPECT_EQ(pmapResult, mapResult);
...@@ -99,6 +107,7 @@ TEST(Pmap, Empty) { ...@@ -99,6 +107,7 @@ TEST(Pmap, Empty) {
TEST(Pmap, Rvalues) { TEST(Pmap, Rvalues) {
// apply // apply
{ {
// clang-format off
auto mapResult auto mapResult
= seq(1) = seq(1)
| map([](int x) { return std::make_unique<int>(x); }) | map([](int x) { return std::make_unique<int>(x); })
...@@ -116,12 +125,14 @@ TEST(Pmap, Rvalues) { ...@@ -116,12 +125,14 @@ TEST(Pmap, Rvalues) {
| pmap([](std::unique_ptr<int> x) { return *x; }) | pmap([](std::unique_ptr<int> x) { return *x; })
| take(1000) | take(1000)
| sum; | sum;
// clang-format on
EXPECT_EQ(pmapResult, mapResult); EXPECT_EQ(pmapResult, mapResult);
} }
// foreach // foreach
{ {
// clang-format off
auto mapResult auto mapResult
= seq(1, 1000) = seq(1, 1000)
| map([](int x) { return std::make_unique<int>(x); }) | map([](int x) { return std::make_unique<int>(x); })
...@@ -137,12 +148,13 @@ TEST(Pmap, Rvalues) { ...@@ -137,12 +148,13 @@ TEST(Pmap, Rvalues) {
return std::make_unique<int>(*x * *x); }) return std::make_unique<int>(*x * *x); })
| pmap([](std::unique_ptr<int> x) { return *x; }) | pmap([](std::unique_ptr<int> x) { return *x; })
| sum; | sum;
// clang-format on
EXPECT_EQ(pmapResult, mapResult); EXPECT_EQ(pmapResult, mapResult);
} }
} }
int main(int argc, char *argv[]) { int main(int argc, char* argv[]) {
testing::InitGoogleTest(&argc, argv); testing::InitGoogleTest(&argc, argv);
gflags::ParseCommandLineFlags(&argc, &argv, true); gflags::ParseCommandLineFlags(&argc, &argv, true);
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();
......
...@@ -57,55 +57,55 @@ struct { ...@@ -57,55 +57,55 @@ struct {
} }
} makeUnique; } makeUnique;
static auto primes = seq(1, 1 << 14) static auto primes = seq(1, 1 << 14) | filter(isPrime) | as<vector<size_t>>();
| filter(isPrime)
| as<vector<size_t>>();
static auto primeFactors = [](int n) { static auto primeFactors = [](int n) {
return from(primes) return from(primes) | filter([&](int d) { return 0 == n % d; }) | count;
| filter([&](int d) { return 0 == n % d; })
| count;
}; };
TEST(ParallelTest, Serial) { TEST(ParallelTest, Serial) {
EXPECT_EQ( EXPECT_EQ(
seq(1,10) | map(square) | filter(even) | sum, seq(1, 10) | map(square) | filter(even) | sum,
seq(1,10) | parallel(map(square) | filter(even)) | sum); seq(1, 10) | parallel(map(square) | filter(even)) | sum);
} }
auto heavyWork = map(primeFactors); auto heavyWork = map(primeFactors);
TEST(ParallelTest, ComputeBound64) { TEST(ParallelTest, ComputeBound64) {
int length = 1 << 10; int length = 1 << 10;
EXPECT_EQ(seq<size_t>(1, length) | heavyWork | sum, EXPECT_EQ(
seq<size_t>(1, length) | parallel(heavyWork) | sum); seq<size_t>(1, length) | heavyWork | sum,
seq<size_t>(1, length) | parallel(heavyWork) | sum);
} }
TEST(ParallelTest, Take) { TEST(ParallelTest, Take) {
int length = 1 << 18; int length = 1 << 18;
int limit = 1 << 14; int limit = 1 << 14;
EXPECT_EQ(seq(1, length) | take(limit) | count, EXPECT_EQ(
seq(1, length) | parallel(heavyWork) | take(limit) | count); seq(1, length) | take(limit) | count,
seq(1, length) | parallel(heavyWork) | take(limit) | count);
} }
TEST(ParallelTest, Unique) { TEST(ParallelTest, Unique) {
auto uniqued = from(primes) | map(makeUnique) | as<vector>(); auto uniqued = from(primes) | map(makeUnique) | as<vector>();
EXPECT_EQ(primes.size(), EXPECT_EQ(
from(primes) | parallel(map(makeUnique)) | primes.size(),
parallel(dereference | map(makeUnique)) | dereference | count); from(primes) | parallel(map(makeUnique)) |
EXPECT_EQ(2, parallel(dereference | map(makeUnique)) | dereference | count);
from(primes) | parallel(map(makeUnique)) | EXPECT_EQ(
parallel(dereference | map(makeUnique)) | dereference | 2,
take(2) | count); from(primes) | parallel(map(makeUnique)) |
parallel(dereference | map(makeUnique)) | dereference | take(2) |
count);
} }
TEST(ParallelTest, PSum) { TEST(ParallelTest, PSum) {
EXPECT_EQ(from(primes) | map(sleepyWork) | sum, EXPECT_EQ(
from(primes) | parallel(map(sleepyWork) | sub(sum)) | sum); from(primes) | map(sleepyWork) | sum,
from(primes) | parallel(map(sleepyWork) | sub(sum)) | sum);
} }
int main(int argc, char *argv[]) { int main(int argc, char* argv[]) {
testing::InitGoogleTest(&argc, argv); testing::InitGoogleTest(&argc, argv);
gflags::ParseCommandLineFlags(&argc, &argv, true); gflags::ParseCommandLineFlags(&argc, &argv, true);
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();
......
...@@ -28,16 +28,14 @@ using namespace folly; ...@@ -28,16 +28,14 @@ using namespace folly;
using namespace folly::gen; using namespace folly::gen;
using std::pair; using std::pair;
using std::set; using std::set;
using std::vector;
using std::tuple; using std::tuple;
using std::vector;
namespace { namespace {
static std::atomic<int> testSize(1000); static std::atomic<int> testSize(1000);
static vector<fbstring> testStrVector static vector<fbstring> testStrVector =
= seq(1, testSize.load()) seq(1, testSize.load()) | eachTo<fbstring>() | as<vector>();
| eachTo<fbstring>()
| as<vector>();
static auto testFileContent = from(testStrVector) | unsplit('\n'); static auto testFileContent = from(testStrVector) | unsplit('\n');
const char* const kLine = "The quick brown fox jumped over the lazy dog.\n"; const char* const kLine = "The quick brown fox jumped over the lazy dog.\n";
...@@ -61,7 +59,9 @@ void initStringResplitterBenchmark() { ...@@ -61,7 +59,9 @@ void initStringResplitterBenchmark() {
} }
} }
size_t len(folly::StringPiece s) { return s.size(); } size_t len(folly::StringPiece s) {
return s.size();
}
} // namespace } // namespace
...@@ -94,7 +94,6 @@ BENCHMARK(StringSplit_Old, iters) { ...@@ -94,7 +94,6 @@ BENCHMARK(StringSplit_Old, iters) {
folly::doNotOptimizeAway(s); folly::doNotOptimizeAway(s);
} }
BENCHMARK_RELATIVE(StringSplit_Gen_Vector, iters) { BENCHMARK_RELATIVE(StringSplit_Gen_Vector, iters) {
size_t s = 0; size_t s = 0;
StringPiece line(kLine); StringPiece line(kLine);
...@@ -196,9 +195,7 @@ BENCHMARK_DRAW_LINE(); ...@@ -196,9 +195,7 @@ BENCHMARK_DRAW_LINE();
void StringUnsplit_Gen(size_t iters, size_t joinSize) { void StringUnsplit_Gen(size_t iters, size_t joinSize) {
std::vector<fbstring> v; std::vector<fbstring> v;
BENCHMARK_SUSPEND { BENCHMARK_SUSPEND {
FOR_EACH_RANGE (i, 0, joinSize) { FOR_EACH_RANGE (i, 0, joinSize) { v.push_back(to<fbstring>(rand())); }
v.push_back(to<fbstring>(rand()));
}
} }
size_t s = 0; size_t s = 0;
fbstring buffer; fbstring buffer;
...@@ -231,20 +228,23 @@ BENCHMARK_RELATIVE_PARAM(Lines_Gen, 3e3) ...@@ -231,20 +228,23 @@ BENCHMARK_RELATIVE_PARAM(Lines_Gen, 3e3)
BENCHMARK_DRAW_LINE(); BENCHMARK_DRAW_LINE();
fbstring records // clang-format off
= seq<size_t>(1, 1000) fbstring records = seq<size_t>(1, 1000)
| mapped([](size_t i) { | mapped([](size_t i) {
return folly::to<fbstring>(i, ' ', i * i, ' ', i * i * i); return folly::to<fbstring>(i, ' ', i * i, ' ', i * i * i);
}) })
| unsplit('\n'); | unsplit('\n');
// clang-format o
BENCHMARK(Records_EachToTuple, iters) { BENCHMARK(Records_EachToTuple, iters) {
size_t s = 0; size_t s = 0;
for (size_t i = 0; i < iters; i += 1000) { for (size_t i = 0; i < iters; i += 1000) {
// clang-format off
s += split(records, '\n') s += split(records, '\n')
| eachToTuple<int, size_t, StringPiece>(' ') | eachToTuple<int, size_t, StringPiece>(' ')
| get<1>() | get<1>()
| sum; | sum;
// clang-format on
} }
folly::doNotOptimizeAway(s); folly::doNotOptimizeAway(s);
} }
...@@ -253,18 +253,20 @@ BENCHMARK_RELATIVE(Records_VectorStringPieceReused, iters) { ...@@ -253,18 +253,20 @@ BENCHMARK_RELATIVE(Records_VectorStringPieceReused, iters) {
size_t s = 0; size_t s = 0;
std::vector<StringPiece> fields; std::vector<StringPiece> fields;
for (size_t i = 0; i < iters; i += 1000) { for (size_t i = 0; i < iters; i += 1000) {
// clang-format off
s += split(records, '\n') s += split(records, '\n')
| mapped([&](StringPiece line) { | mapped([&](StringPiece line) {
fields.clear(); fields.clear();
folly::split(' ', line, fields); folly::split(' ', line, fields);
CHECK(fields.size() == 3); CHECK(fields.size() == 3);
return std::make_tuple( return std::make_tuple(
folly::to<int>(fields[0]), folly::to<int>(fields[0]),
folly::to<size_t>(fields[1]), folly::to<size_t>(fields[1]),
StringPiece(fields[2])); StringPiece(fields[2]));
}) })
| get<1>() | get<1>()
| sum; | sum;
// clang-format on
} }
folly::doNotOptimizeAway(s); folly::doNotOptimizeAway(s);
} }
...@@ -272,18 +274,20 @@ BENCHMARK_RELATIVE(Records_VectorStringPieceReused, iters) { ...@@ -272,18 +274,20 @@ BENCHMARK_RELATIVE(Records_VectorStringPieceReused, iters) {
BENCHMARK_RELATIVE(Records_VectorStringPiece, iters) { BENCHMARK_RELATIVE(Records_VectorStringPiece, iters) {
size_t s = 0; size_t s = 0;
for (size_t i = 0; i < iters; i += 1000) { for (size_t i = 0; i < iters; i += 1000) {
// clang-format off
s += split(records, '\n') s += split(records, '\n')
| mapped([](StringPiece line) { | mapped([](StringPiece line) {
std::vector<StringPiece> fields; std::vector<StringPiece> fields;
folly::split(' ', line, fields); folly::split(' ', line, fields);
CHECK(fields.size() == 3); CHECK(fields.size() == 3);
return std::make_tuple( return std::make_tuple(
folly::to<int>(fields[0]), folly::to<int>(fields[0]),
folly::to<size_t>(fields[1]), folly::to<size_t>(fields[1]),
StringPiece(fields[2])); StringPiece(fields[2]));
}) })
| get<1>() | get<1>()
| sum; | sum;
// clang-format on
} }
folly::doNotOptimizeAway(s); folly::doNotOptimizeAway(s);
} }
...@@ -291,18 +295,20 @@ BENCHMARK_RELATIVE(Records_VectorStringPiece, iters) { ...@@ -291,18 +295,20 @@ BENCHMARK_RELATIVE(Records_VectorStringPiece, iters) {
BENCHMARK_RELATIVE(Records_VectorString, iters) { BENCHMARK_RELATIVE(Records_VectorString, iters) {
size_t s = 0; size_t s = 0;
for (size_t i = 0; i < iters; i += 1000) { for (size_t i = 0; i < iters; i += 1000) {
// clang-format off
s += split(records, '\n') s += split(records, '\n')
| mapped([](StringPiece line) { | mapped([](StringPiece line) {
std::vector<std::string> fields; std::vector<std::string> fields;
folly::split(' ', line, fields); folly::split(' ', line, fields);
CHECK(fields.size() == 3); CHECK(fields.size() == 3);
return std::make_tuple( return std::make_tuple(
folly::to<int>(fields[0]), folly::to<int>(fields[0]),
folly::to<size_t>(fields[1]), folly::to<size_t>(fields[1]),
StringPiece(fields[2])); StringPiece(fields[2]));
}) })
| get<1>() | get<1>()
| sum; | sum;
// clang-format on
} }
folly::doNotOptimizeAway(s); folly::doNotOptimizeAway(s);
} }
...@@ -338,7 +344,7 @@ BENCHMARK_RELATIVE(Records_VectorString, iters) { ...@@ -338,7 +344,7 @@ BENCHMARK_RELATIVE(Records_VectorString, iters) {
// Records_VectorString 16.70% 607.47us 1.65K // Records_VectorString 16.70% 607.47us 1.65K
// ============================================================================ // ============================================================================
int main(int argc, char *argv[]) { int main(int argc, char* argv[]) {
gflags::ParseCommandLineFlags(&argc, &argv, true); gflags::ParseCommandLineFlags(&argc, &argv, true);
initStringResplitterBenchmark(); initStringResplitterBenchmark();
runBenchmarks(); runBenchmarks();
......
...@@ -149,69 +149,83 @@ TEST(StringGen, ResplitKeepDelimiter) { ...@@ -149,69 +149,83 @@ TEST(StringGen, ResplitKeepDelimiter) {
TEST(StringGen, EachToTuple) { TEST(StringGen, EachToTuple) {
{ {
auto lines = "2:1.414:yo 3:1.732:hi"; auto lines = "2:1.414:yo 3:1.732:hi";
// clang-format off
auto actual auto actual
= split(lines, ' ') = split(lines, ' ')
| eachToTuple<int, double, std::string>(':') | eachToTuple<int, double, std::string>(':')
| as<vector>(); | as<vector>();
vector<tuple<int, double, std::string>> expected { // clang-format on
make_tuple(2, 1.414, "yo"), vector<tuple<int, double, std::string>> expected{
make_tuple(3, 1.732, "hi"), make_tuple(2, 1.414, "yo"),
make_tuple(3, 1.732, "hi"),
}; };
EXPECT_EQ(expected, actual); EXPECT_EQ(expected, actual);
} }
{ {
auto lines = "2 3"; auto lines = "2 3";
// clang-format off
auto actual auto actual
= split(lines, ' ') = split(lines, ' ')
| eachToTuple<int>(',') | eachToTuple<int>(',')
| as<vector>(); | as<vector>();
vector<tuple<int>> expected { // clang-format on
make_tuple(2), vector<tuple<int>> expected{
make_tuple(3), make_tuple(2),
make_tuple(3),
}; };
EXPECT_EQ(expected, actual); EXPECT_EQ(expected, actual);
} }
{ {
// StringPiece target // StringPiece target
auto lines = "1:cat 2:dog"; auto lines = "1:cat 2:dog";
// clang-format off
auto actual auto actual
= split(lines, ' ') = split(lines, ' ')
| eachToTuple<int, StringPiece>(':') | eachToTuple<int, StringPiece>(':')
| as<vector>(); | as<vector>();
vector<tuple<int, StringPiece>> expected { // clang-format on
make_tuple(1, "cat"), vector<tuple<int, StringPiece>> expected{
make_tuple(2, "dog"), make_tuple(1, "cat"),
make_tuple(2, "dog"),
}; };
EXPECT_EQ(expected, actual); EXPECT_EQ(expected, actual);
} }
{ {
// Empty field // Empty field
auto lines = "2:tjackson:4 3::5"; auto lines = "2:tjackson:4 3::5";
// clang-format off
auto actual auto actual
= split(lines, ' ') = split(lines, ' ')
| eachToTuple<int, fbstring, int>(':') | eachToTuple<int, fbstring, int>(':')
| as<vector>(); | as<vector>();
vector<tuple<int, fbstring, int>> expected { // clang-format on
make_tuple(2, "tjackson", 4), vector<tuple<int, fbstring, int>> expected{
make_tuple(3, "", 5), make_tuple(2, "tjackson", 4),
make_tuple(3, "", 5),
}; };
EXPECT_EQ(expected, actual); EXPECT_EQ(expected, actual);
} }
{ {
// Excess fields // Excess fields
auto lines = "1:2 3:4:5"; auto lines = "1:2 3:4:5";
EXPECT_THROW((split(lines, ' ') // clang-format off
| eachToTuple<int, int>(':') EXPECT_THROW(
| as<vector>()), (split(lines, ' ')
std::runtime_error); | eachToTuple<int, int>(':')
| as<vector>()),
std::runtime_error);
// clang-format on
} }
{ {
// Missing fields // Missing fields
auto lines = "1:2:3 4:5"; auto lines = "1:2:3 4:5";
EXPECT_THROW((split(lines, ' ') // clang-format off
| eachToTuple<int, int, int>(':') EXPECT_THROW(
| as<vector>()), (split(lines, ' ')
std::runtime_error); | eachToTuple<int, int, int>(':')
| as<vector>()),
std::runtime_error);
// clang-format on
} }
} }
...@@ -219,40 +233,48 @@ TEST(StringGen, EachToPair) { ...@@ -219,40 +233,48 @@ TEST(StringGen, EachToPair) {
{ {
// char delimiters // char delimiters
auto lines = "2:1.414 3:1.732"; auto lines = "2:1.414 3:1.732";
// clang-format off
auto actual auto actual
= split(lines, ' ') = split(lines, ' ')
| eachToPair<int, double>(':') | eachToPair<int, double>(':')
| as<std::map<int, double>>(); | as<std::map<int, double>>();
std::map<int, double> expected { // clang-format on
{ 3, 1.732 }, std::map<int, double> expected{
{ 2, 1.414 }, {3, 1.732},
{2, 1.414},
}; };
EXPECT_EQ(expected, actual); EXPECT_EQ(expected, actual);
} }
{ {
// string delimiters // string delimiters
auto lines = "ab=>cd ef=>gh"; auto lines = "ab=>cd ef=>gh";
// clang-format off
auto actual auto actual
= split(lines, ' ') = split(lines, ' ')
| eachToPair<string, string>("=>") | eachToPair<string, string>("=>")
| as<std::map<string, string>>(); | as<std::map<string, string>>();
std::map<string, string> expected { // clang-format on
{ "ab", "cd" }, std::map<string, string> expected{
{ "ef", "gh" }, {"ab", "cd"},
{"ef", "gh"},
}; };
EXPECT_EQ(expected, actual); EXPECT_EQ(expected, actual);
} }
} }
void checkResplitMaxLength(vector<string> ins, void checkResplitMaxLength(
char delim, vector<string> ins,
uint64_t maxLength, char delim,
vector<string> outs) { uint64_t maxLength,
vector<string> outs) {
vector<std::string> pieces; vector<std::string> pieces;
auto splitter = streamSplitter(delim, [&pieces](StringPiece s) { auto splitter = streamSplitter(
pieces.push_back(string(s.begin(), s.end())); delim,
return true; [&pieces](StringPiece s) {
}, maxLength); pieces.push_back(string(s.begin(), s.end()));
return true;
},
maxLength);
for (const auto& in : ins) { for (const auto& in : ins) {
splitter(in); splitter(in);
} }
...@@ -270,22 +292,21 @@ void checkResplitMaxLength(vector<string> ins, ...@@ -270,22 +292,21 @@ void checkResplitMaxLength(vector<string> ins,
} }
TEST(StringGen, ResplitMaxLength) { TEST(StringGen, ResplitMaxLength) {
// clang-format off
checkResplitMaxLength( checkResplitMaxLength(
{"hel", "lo,", ", world", ", goodbye, m", "ew"}, ',', 5, {"hel", "lo,", ", world", ", goodbye, m", "ew"}, ',', 5,
{"hello", ",", ",", " worl", "d,", " good", "bye,", " mew"} {"hello", ",", ",", " worl", "d,", " good", "bye,", " mew"});
);
// " meow" cannot be "end of stream", since it's maxLength long // " meow" cannot be "end of stream", since it's maxLength long
checkResplitMaxLength( checkResplitMaxLength(
{"hel", "lo,", ", world", ", goodbye, m", "eow"}, ',', 5, {"hel", "lo,", ", world", ", goodbye, m", "eow"}, ',', 5,
{"hello", ",", ",", " worl", "d,", " good", "bye,", " meow", ""} {"hello", ",", ",", " worl", "d,", " good", "bye,", " meow", ""});
);
checkResplitMaxLength( checkResplitMaxLength(
{"||", "", "", "", "|a|b", "cdefghijklmn", "|opqrst", {"||", "", "", "", "|a|b", "cdefghijklmn", "|opqrst",
"uvwx|y|||", "z", "0123456789", "|", ""}, '|', 2, "uvwx|y|||", "z", "0123456789", "|", ""}, '|', 2,
{"|", "|", "|", "a|", "bc", "de", "fg", "hi", "jk", "lm", "n|", "op", "qr", {"|", "|", "|", "a|", "bc", "de", "fg", "hi", "jk", "lm", "n|", "op",
"st", "uv", "wx", "|", "y|", "|", "|", "z0", "12", "34", "56", "78", "9|", "qr", "st", "uv", "wx", "|", "y|", "|", "|", "z0", "12", "34", "56",
""} "78", "9|", ""});
); // clang-format on
} }
template <typename F> template <typename F>
...@@ -299,7 +320,6 @@ void runUnsplitSuite(F fn) { ...@@ -299,7 +320,6 @@ void runUnsplitSuite(F fn) {
} }
TEST(StringGen, Unsplit) { TEST(StringGen, Unsplit) {
auto basicFn = [](StringPiece s) { auto basicFn = [](StringPiece s) {
EXPECT_EQ(split(s, ',') | unsplit(','), s); EXPECT_EQ(split(s, ',') | unsplit(','), s);
}; };
...@@ -307,8 +327,7 @@ TEST(StringGen, Unsplit) { ...@@ -307,8 +327,7 @@ TEST(StringGen, Unsplit) {
auto existingBuffer = [](StringPiece s) { auto existingBuffer = [](StringPiece s) {
folly::fbstring buffer("asdf"); folly::fbstring buffer("asdf");
split(s, ',') | unsplit(',', &buffer); split(s, ',') | unsplit(',', &buffer);
auto expected = folly::to<folly::fbstring>( auto expected = folly::to<folly::fbstring>("asdf", s.empty() ? "" : ",", s);
"asdf", s.empty() ? "" : ",", s);
EXPECT_EQ(expected, buffer); EXPECT_EQ(expected, buffer);
}; };
...@@ -334,16 +353,21 @@ TEST(StringGen, Unsplit) { ...@@ -334,16 +353,21 @@ TEST(StringGen, Unsplit) {
TEST(StringGen, Batch) { TEST(StringGen, Batch) {
std::vector<std::string> chunks{ std::vector<std::string> chunks{
"on", "e\nt", "w", "o", "\nthr", "ee\nfo", "ur\n", "on", "e\nt", "w", "o", "\nthr", "ee\nfo", "ur\n"};
}; std::vector<std::string> lines{"one", "two", "three", "four"};
std::vector<std::string> lines{
"one", "two", "three", "four",
};
EXPECT_EQ(4, from(chunks) | resplit('\n') | count); EXPECT_EQ(4, from(chunks) | resplit('\n') | count);
EXPECT_EQ(4, from(chunks) | resplit('\n') | batch(2) | rconcat | count); EXPECT_EQ(4, from(chunks) | resplit('\n') | batch(2) | rconcat | count);
EXPECT_EQ(4, from(chunks) | resplit('\n') | batch(3) | rconcat | count); EXPECT_EQ(4, from(chunks) | resplit('\n') | batch(3) | rconcat | count);
EXPECT_EQ(lines, from(chunks) | resplit('\n') | eachTo<std::string>() | // clang-format off
batch(3) | rconcat | as<vector>()); EXPECT_EQ(
lines,
from(chunks)
| resplit('\n')
| eachTo<std::string>()
| batch(3)
| rconcat
| as<vector>());
// clang-format on
} }
TEST(StringGen, UncurryTuple) { TEST(StringGen, UncurryTuple) {
......
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