| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- //
- // join_iterator.h
- // iterator
- //
- // Created by Sam Jaffe on 2/7/17.
- //
- #pragma once
- #include <iterator>
- #include <memory>
- #include <utility>
- #include <iterator/capture_iterator.h>
- #include <iterator/end_aware_iterator.h>
- #include <iterator/facade.h>
- #include <iterator/forwards.h>
- #include <iterator/detail/macro.h>
- namespace iterator {
- template <typename It>
- class joining_iterator : public facade<joining_iterator<It>> {
- private:
- template <typename Ot> friend class joining_iterator;
- constexpr static bool requires_caching = detail::is_rvalue_iterator_v<It>;
- public:
- using sentinel_type = sentinel_t;
- using outer_iterator_t =
- std::conditional_t<requires_caching,
- capture_iterator<end_aware_iterator<It>>,
- end_aware_iterator<It>>;
- using inner_iterator_t =
- end_aware_iterator<detail::iter<DEREF_TYPE(outer_iterator_t)>>;
- private:
- outer_iterator_t outer_;
- inner_iterator_t inner_;
- public:
- joining_iterator() = default;
- template <typename Ot>
- joining_iterator(joining_iterator<Ot> const & other) : outer_(other.outer_) {
- safely_init_inner_iterator(other.outer_, other.inner_);
- }
- template <typename C, REQUIRES(detail::is_container_v<C>)>
- joining_iterator(C && container) : outer_(FWD(container)) {
- update_iterator();
- }
- joining_iterator(outer_iterator_t outer) : outer_(outer) {
- update_iterator();
- }
- joining_iterator(outer_iterator_t const & outer,
- inner_iterator_t const & inner)
- : outer_(outer) {
- safely_init_inner_iterator(outer, inner);
- }
- void increment() {
- if ((++inner_).at_end()) {
- ++outer_;
- update_iterator();
- }
- }
- decltype(auto) dereference() const { return *inner_; }
- bool at_end() const { return outer_.at_end(); }
- bool equal_to(joining_iterator const & other) const {
- return outer_ == other.outer_ && inner_ == other.inner_;
- }
- auto outer_iterator() const { return outer_; }
- auto inner_iterator() const { return inner_; }
- private:
- template <typename OuterIt, typename InnerIt>
- void safely_init_inner_iterator(OuterIt const & outer,
- InnerIt const & inner) {
- if constexpr (requires_caching) {
- inner_ = *outer_;
- std::advance(inner_, std::distance(InnerIt(*outer), inner));
- } else {
- inner_ = inner;
- }
- }
- void update_iterator() {
- while (!outer_.at_end() && (inner_ = *outer_).at_end()) {
- ++outer_;
- }
- }
- };
- template <typename C>
- joining_iterator(C &&) -> joining_iterator<detail::iter<C>>;
- template <typename JI>
- joining_iterator(end_aware_iterator<JI>) -> joining_iterator<JI>;
- }
- MAKE_ITERATOR_FACADE_TYPEDEFS_T(::iterator::joining_iterator);
- #include <iterator/detail/undef.h>
|