join.hpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. #pragma once
  2. #include <iterator>
  3. namespace stream { namespace detail {
  4. #define JOIN_CTOR( mod ) \
  5. start_ = mod(other.start_); \
  6. finish_ = mod(other.finish_); \
  7. std::ptrdiff_t n = std::distance(other.mem_.cbegin(), other.curr_); \
  8. mem_ = mod(other.mem_); \
  9. curr_ = mem_.begin(); \
  10. std::advance(curr_, n); \
  11. end_ = mem_.end();
  12. namespace join {
  13. template <typename C>
  14. class iterator {
  15. private:
  16. using impl_t = ::stream::iterator<C>;
  17. using local_iterator = typename C::const_iterator;
  18. public:
  19. using reference = typename local_iterator::reference;
  20. public:
  21. iterator(impl_t && f, impl_t && l)
  22. : start_(std::move(f)), finish_(std::move(l)) {
  23. if (start_ != finish_) {
  24. mem_ = *(start_);
  25. curr_ = mem_.begin();
  26. end_ = mem_.end();
  27. advance();
  28. }
  29. }
  30. iterator(iterator const & other) { JOIN_CTOR( ) }
  31. iterator(iterator && other) { JOIN_CTOR( std::move ) }
  32. iterator & operator=(iterator const & other) {
  33. JOIN_CTOR( )
  34. return *this;
  35. }
  36. iterator & operator=(iterator && other) {
  37. JOIN_CTOR( std::move )
  38. return *this;
  39. }
  40. reference operator*() { return *curr_; }
  41. iterator& operator++() {
  42. ++curr_;
  43. advance();
  44. return *this;
  45. }
  46. DELEGATE_ITERATOR_IMPL_BASE(start_)
  47. private:
  48. void advance() {
  49. while (curr_ == end_ && start_ != finish_) {
  50. if ( ++start_ == finish_ ) { break; }
  51. mem_ = *start_;
  52. curr_ = mem_.begin();
  53. end_ = mem_.end();
  54. }
  55. }
  56. impl_t start_, finish_;
  57. C mem_;
  58. local_iterator curr_, end_;
  59. };
  60. }
  61. template <typename C>
  62. class join_stream {
  63. public:
  64. using T = typename C::value_type;
  65. explicit join_stream(stream_base<C> const& sb) : source_(sb) {}
  66. ::stream::iterator<T> begin() {
  67. return {join::iterator<C>{source_.begin(), source_.end()}};
  68. }
  69. ::stream::iterator<T> end() {
  70. return {join::iterator<C>{source_.end(), source_.end()}};
  71. }
  72. private:
  73. stream_base<C> source_;
  74. };
  75. template <typename C>
  76. stream_base<typename C::value_type> make_join(stream_base<C> const& sb) {
  77. return std::make_shared<join_stream<C>>(sb);
  78. }
  79. template <typename T>
  80. template <typename F>
  81. stream_base<traits::fmapped_t<T, F>> stream_base<T>::flatmap(F&& func) && {
  82. return make_join(std::move(*this).map(func));
  83. }
  84. template <typename T>
  85. template <typename F>
  86. stream_base<traits::fmapped_t<T, F>> stream_base<T>::flatmap(F&& func) const & {
  87. return make_join(map(func));
  88. }
  89. } }