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

Add bidi support to IteratorFacade

Summary: [Folly] Add bidi support to IteratorFacade

Reviewed By: aary

Differential Revision: D10477733

fbshipit-source-id: 6779580a4fdea88d29fb51454da04c9605b026bb
parent 611dae9a
...@@ -50,10 +50,11 @@ namespace folly { ...@@ -50,10 +50,11 @@ namespace folly {
namespace detail { namespace detail {
/** /**
* Currently this only supports forward iteration. The derived class must * Currently this only supports forward and bidirectional iteration. The
* must have definitions for these three methods: * derived class must must have definitions for these methods:
* *
* void increment(); * void increment();
* void decrement(); // optional, to be used with bidirectional
* reference dereference() const; * reference dereference() const;
* bool equal([appropriate iterator type] const& rhs) const; * bool equal([appropriate iterator type] const& rhs) const;
* *
...@@ -63,15 +64,18 @@ namespace detail { ...@@ -63,15 +64,18 @@ namespace detail {
* Template parameters: * Template parameters:
* D: the deriving class (CRTP) * D: the deriving class (CRTP)
* V: value type * V: value type
* Tag: the iterator category, one of:
* std::forward_iterator_tag
* std::bidirectional_iterator_tag
*/ */
template <class D, class V> template <class D, class V, class Tag>
class IteratorFacade { class IteratorFacade {
public: public:
using value_type = V; using value_type = V;
using reference = value_type&; using reference = value_type&;
using pointer = value_type*; using pointer = value_type*;
using difference_type = ssize_t; using difference_type = ssize_t;
using iterator_category = std::forward_iterator_tag; using iterator_category = Tag;
bool operator==(D const& rhs) const { bool operator==(D const& rhs) const {
return asDerivedConst().equal(rhs); return asDerivedConst().equal(rhs);
...@@ -119,6 +123,17 @@ class IteratorFacade { ...@@ -119,6 +123,17 @@ class IteratorFacade {
return ret; return ret;
} }
D& operator--() {
asDerived().decrement();
return asDerived();
}
D operator--(int) {
auto ret = asDerived(); // copy
asDerived().decrement();
return ret;
}
private: private:
D& asDerived() { D& asDerived() {
return static_cast<D&>(*this); return static_cast<D&>(*this);
...@@ -138,10 +153,10 @@ class IteratorFacade { ...@@ -138,10 +153,10 @@ class IteratorFacade {
* I: the wrapper iterator type * I: the wrapper iterator type
* V: value type * V: value type
*/ */
template <class D, class I, class V> template <class D, class I, class V, class Tag>
class IteratorAdaptor : public IteratorFacade<D, V> { class IteratorAdaptor : public IteratorFacade<D, V, Tag> {
public: public:
using Super = IteratorFacade<D, V>; using Super = IteratorFacade<D, V, Tag>;
using value_type = typename Super::value_type; using value_type = typename Super::value_type;
using iterator_category = typename Super::iterator_category; using iterator_category = typename Super::iterator_category;
using reference = typename Super::reference; using reference = typename Super::reference;
...@@ -149,10 +164,15 @@ class IteratorAdaptor : public IteratorFacade<D, V> { ...@@ -149,10 +164,15 @@ class IteratorAdaptor : public IteratorFacade<D, V> {
using difference_type = typename Super::difference_type; using difference_type = typename Super::difference_type;
explicit IteratorAdaptor(I base) : base_(base) {} explicit IteratorAdaptor(I base) : base_(base) {}
void increment() { void increment() {
++base_; ++base_;
} }
void decrement() {
--base_;
}
V& dereference() const { V& dereference() const {
return *base_; return *base_;
} }
......
...@@ -249,11 +249,13 @@ inline dynamic::ObjectMaker dynamic::object(dynamic a, dynamic b) { ...@@ -249,11 +249,13 @@ inline dynamic::ObjectMaker dynamic::object(dynamic a, dynamic b) {
struct dynamic::item_iterator : detail::IteratorAdaptor< struct dynamic::item_iterator : detail::IteratorAdaptor<
dynamic::item_iterator, dynamic::item_iterator,
dynamic::ObjectImpl::iterator, dynamic::ObjectImpl::iterator,
std::pair<dynamic const, dynamic>> { std::pair<dynamic const, dynamic>,
std::forward_iterator_tag> {
using Super = detail::IteratorAdaptor< using Super = detail::IteratorAdaptor<
dynamic::item_iterator, dynamic::item_iterator,
dynamic::ObjectImpl::iterator, dynamic::ObjectImpl::iterator,
std::pair<dynamic const, dynamic>>; std::pair<dynamic const, dynamic>,
std::forward_iterator_tag>;
/* implicit */ item_iterator(dynamic::ObjectImpl::iterator b) : Super(b) {} /* implicit */ item_iterator(dynamic::ObjectImpl::iterator b) : Super(b) {}
using object_type = dynamic::ObjectImpl; using object_type = dynamic::ObjectImpl;
...@@ -262,11 +264,13 @@ struct dynamic::item_iterator : detail::IteratorAdaptor< ...@@ -262,11 +264,13 @@ struct dynamic::item_iterator : detail::IteratorAdaptor<
struct dynamic::value_iterator : detail::IteratorAdaptor< struct dynamic::value_iterator : detail::IteratorAdaptor<
dynamic::value_iterator, dynamic::value_iterator,
dynamic::ObjectImpl::iterator, dynamic::ObjectImpl::iterator,
dynamic> { dynamic,
std::forward_iterator_tag> {
using Super = detail::IteratorAdaptor< using Super = detail::IteratorAdaptor<
dynamic::value_iterator, dynamic::value_iterator,
dynamic::ObjectImpl::iterator, dynamic::ObjectImpl::iterator,
dynamic>; dynamic,
std::forward_iterator_tag>;
/* implicit */ value_iterator(dynamic::ObjectImpl::iterator b) : Super(b) {} /* implicit */ value_iterator(dynamic::ObjectImpl::iterator b) : Super(b) {}
using object_type = dynamic::ObjectImpl; using object_type = dynamic::ObjectImpl;
...@@ -280,11 +284,13 @@ struct dynamic::const_item_iterator ...@@ -280,11 +284,13 @@ struct dynamic::const_item_iterator
: detail::IteratorAdaptor< : detail::IteratorAdaptor<
dynamic::const_item_iterator, dynamic::const_item_iterator,
dynamic::ObjectImpl::const_iterator, dynamic::ObjectImpl::const_iterator,
std::pair<dynamic const, dynamic> const> { std::pair<dynamic const, dynamic> const,
std::forward_iterator_tag> {
using Super = detail::IteratorAdaptor< using Super = detail::IteratorAdaptor<
dynamic::const_item_iterator, dynamic::const_item_iterator,
dynamic::ObjectImpl::const_iterator, dynamic::ObjectImpl::const_iterator,
std::pair<dynamic const, dynamic> const>; std::pair<dynamic const, dynamic> const,
std::forward_iterator_tag>;
/* implicit */ const_item_iterator(dynamic::ObjectImpl::const_iterator b) /* implicit */ const_item_iterator(dynamic::ObjectImpl::const_iterator b)
: Super(b) {} : Super(b) {}
/* implicit */ const_item_iterator(const_item_iterator const& i) /* implicit */ const_item_iterator(const_item_iterator const& i)
...@@ -297,11 +303,13 @@ struct dynamic::const_item_iterator ...@@ -297,11 +303,13 @@ struct dynamic::const_item_iterator
struct dynamic::const_key_iterator : detail::IteratorAdaptor< struct dynamic::const_key_iterator : detail::IteratorAdaptor<
dynamic::const_key_iterator, dynamic::const_key_iterator,
dynamic::ObjectImpl::const_iterator, dynamic::ObjectImpl::const_iterator,
dynamic const> { dynamic const,
std::forward_iterator_tag> {
using Super = detail::IteratorAdaptor< using Super = detail::IteratorAdaptor<
dynamic::const_key_iterator, dynamic::const_key_iterator,
dynamic::ObjectImpl::const_iterator, dynamic::ObjectImpl::const_iterator,
dynamic const>; dynamic const,
std::forward_iterator_tag>;
/* implicit */ const_key_iterator(dynamic::ObjectImpl::const_iterator b) /* implicit */ const_key_iterator(dynamic::ObjectImpl::const_iterator b)
: Super(b) {} : Super(b) {}
...@@ -315,11 +323,13 @@ struct dynamic::const_key_iterator : detail::IteratorAdaptor< ...@@ -315,11 +323,13 @@ struct dynamic::const_key_iterator : detail::IteratorAdaptor<
struct dynamic::const_value_iterator : detail::IteratorAdaptor< struct dynamic::const_value_iterator : detail::IteratorAdaptor<
dynamic::const_value_iterator, dynamic::const_value_iterator,
dynamic::ObjectImpl::const_iterator, dynamic::ObjectImpl::const_iterator,
dynamic const> { dynamic const,
std::forward_iterator_tag> {
using Super = detail::IteratorAdaptor< using Super = detail::IteratorAdaptor<
dynamic::const_value_iterator, dynamic::const_value_iterator,
dynamic::ObjectImpl::const_iterator, dynamic::ObjectImpl::const_iterator,
dynamic const>; dynamic const,
std::forward_iterator_tag>;
/* implicit */ const_value_iterator(dynamic::ObjectImpl::const_iterator b) /* implicit */ const_value_iterator(dynamic::ObjectImpl::const_iterator b)
: Super(b) {} : Super(b) {}
/* implicit */ const_value_iterator(value_iterator i) : Super(i.base()) {} /* implicit */ const_value_iterator(value_iterator i) : Super(i.base()) {}
......
...@@ -1610,8 +1610,10 @@ inline std::unique_ptr<IOBuf> IOBuf::maybeCopyBuffer( ...@@ -1610,8 +1610,10 @@ inline std::unique_ptr<IOBuf> IOBuf::maybeCopyBuffer(
return copyBuffer(buf.data(), buf.size(), headroom, minTailroom); return copyBuffer(buf.data(), buf.size(), headroom, minTailroom);
} }
class IOBuf::Iterator class IOBuf::Iterator : public detail::IteratorFacade<
: public detail::IteratorFacade<IOBuf::Iterator, ByteRange const> { IOBuf::Iterator,
ByteRange const,
std::forward_iterator_tag> {
public: public:
// Note that IOBufs are stored as a circular list without a guard node, // Note that IOBufs are stored as a circular list without a guard node,
// so pos == end is ambiguous (it may mean "begin" or "end"). To solve // so pos == end is ambiguous (it may mean "begin" or "end"). To solve
......
...@@ -24,7 +24,8 @@ using namespace folly::detail; ...@@ -24,7 +24,8 @@ using namespace folly::detail;
using namespace folly; using namespace folly;
namespace { namespace {
struct IntArrayIterator : IteratorFacade<IntArrayIterator, int const> { struct IntArrayIterator
: IteratorFacade<IntArrayIterator, int const, std::forward_iterator_tag> {
explicit IntArrayIterator(int const* a) : a_(a) {} explicit IntArrayIterator(int const* a) : a_(a) {}
void increment() { void increment() {
++a_; ++a_;
...@@ -68,8 +69,16 @@ TEST(IteratorsTest, SimpleIteratorFacade) { ...@@ -68,8 +69,16 @@ TEST(IteratorsTest, SimpleIteratorFacade) {
namespace { namespace {
// Simple iterator adaptor: wraps an int pointer. // Simple iterator adaptor: wraps an int pointer.
struct IntPointerIter : IteratorAdaptor<IntPointerIter, int const*, int const> { struct IntPointerIter : IteratorAdaptor<
using Super = IteratorAdaptor<IntPointerIter, int const*, int const>; IntPointerIter,
int const*,
int const,
std::forward_iterator_tag> {
using Super = IteratorAdaptor<
IntPointerIter,
int const*,
int const,
std::forward_iterator_tag>;
explicit IntPointerIter(int const* ptr) : Super(ptr) {} explicit IntPointerIter(int const* ptr) : Super(ptr) {}
}; };
} // namespace } // namespace
...@@ -104,20 +113,32 @@ TEST(IteratorsTest, IterAdaptorWithPointer) { ...@@ -104,20 +113,32 @@ TEST(IteratorsTest, IterAdaptorWithPointer) {
namespace { namespace {
// More complex case: wrap a map iterator, but these provide either the key or // More complex case: wrap a map iterator, but these provide either the key or
// value. // value.
struct IntMapKeyIter struct IntMapKeyIter : IteratorAdaptor<
: IteratorAdaptor<IntMapKeyIter, std::map<int, int>::iterator, int const> { IntMapKeyIter,
using Super = std::map<int, int>::iterator,
IteratorAdaptor<IntMapKeyIter, std::map<int, int>::iterator, int const>; int const,
std::forward_iterator_tag> {
using Super = IteratorAdaptor<
IntMapKeyIter,
std::map<int, int>::iterator,
int const,
std::forward_iterator_tag>;
explicit IntMapKeyIter(std::map<int, int>::iterator iter) : Super(iter) {} explicit IntMapKeyIter(std::map<int, int>::iterator iter) : Super(iter) {}
int const& dereference() const { int const& dereference() const {
return base()->first; return base()->first;
} }
}; };
struct IntMapValueIter struct IntMapValueIter : IteratorAdaptor<
: IteratorAdaptor<IntMapValueIter, std::map<int, int>::iterator, int> { IntMapValueIter,
using Super = std::map<int, int>::iterator,
IteratorAdaptor<IntMapValueIter, std::map<int, int>::iterator, int>; int,
std::forward_iterator_tag> {
using Super = IteratorAdaptor<
IntMapValueIter,
std::map<int, int>::iterator,
int,
std::forward_iterator_tag>;
explicit IntMapValueIter(std::map<int, int>::iterator iter) : Super(iter) {} explicit IntMapValueIter(std::map<int, int>::iterator iter) : Super(iter) {}
int& dereference() const { int& dereference() const {
return base()->second; return base()->second;
...@@ -160,11 +181,13 @@ namespace { ...@@ -160,11 +181,13 @@ namespace {
struct IntMapValueIterConst : IteratorAdaptor< struct IntMapValueIterConst : IteratorAdaptor<
IntMapValueIterConst, IntMapValueIterConst,
std::map<int, int>::const_iterator, std::map<int, int>::const_iterator,
int const> { int const,
std::forward_iterator_tag> {
using Super = IteratorAdaptor< using Super = IteratorAdaptor<
IntMapValueIterConst, IntMapValueIterConst,
std::map<int, int>::const_iterator, std::map<int, int>::const_iterator,
int const>; int const,
std::forward_iterator_tag>;
explicit IntMapValueIterConst(std::map<int, int>::const_iterator iter) explicit IntMapValueIterConst(std::map<int, int>::const_iterator iter)
: Super(iter) {} : Super(iter) {}
/* implicit */ IntMapValueIterConst(IntMapValueIter const& rhs) /* implicit */ IntMapValueIterConst(IntMapValueIter const& rhs)
......
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