join.hpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  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> class iterator {
  14. private:
  15. using impl_t = ::stream::iterator<C>;
  16. using local_iterator = typename C::const_iterator;
  17. public:
  18. using reference = typename local_iterator::reference;
  19. public:
  20. iterator(impl_t && f, impl_t && l)
  21. : start_(std::move(f)), finish_(std::move(l)) {
  22. if (start_ != finish_) {
  23. mem_ = *(start_);
  24. curr_ = mem_.begin();
  25. end_ = mem_.end();
  26. advance();
  27. }
  28. }
  29. iterator(iterator const & other){JOIN_CTOR()} iterator(iterator && other){
  30. JOIN_CTOR(std::move)}
  31. iterator &
  32. 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> class join_stream {
  62. public:
  63. using T = typename C::value_type;
  64. explicit join_stream(stream_base<C> const & sb) : source_(sb) {}
  65. ::stream::iterator<T> begin() {
  66. return {join::iterator<C>{source_.begin(), source_.end()}};
  67. }
  68. ::stream::iterator<T> end() {
  69. return {join::iterator<C>{source_.end(), source_.end()}};
  70. }
  71. private:
  72. stream_base<C> source_;
  73. };
  74. template <typename C>
  75. stream_base<typename C::value_type> make_join(stream_base<C> const & sb) {
  76. return std::make_shared<join_stream<C>>(sb);
  77. }
  78. template <typename T>
  79. template <typename F>
  80. stream_base<traits::fmapped_t<T, F>> stream_base<T>::flatmap(F && func) && {
  81. return make_join(std::move(*this).map(func));
  82. }
  83. template <typename T>
  84. template <typename F>
  85. stream_base<traits::fmapped_t<T, F>>
  86. stream_base<T>::flatmap(F && func) const & {
  87. return make_join(map(func));
  88. }
  89. }}