join.hpp 2.8 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. template <typename C> class join_iterator {
  13. public:
  14. using reference = typename C::const_iterator::reference;
  15. public:
  16. join_iterator(iterator<C> && f, iterator<C> && l)
  17. : start_(std::move(f)), finish_(std::move(l)) {
  18. if (start_ != finish_) {
  19. mem_ = *(start_);
  20. curr_ = mem_.begin();
  21. end_ = mem_.end();
  22. advance();
  23. }
  24. }
  25. join_iterator(join_iterator const & other) {
  26. JOIN_CTOR()
  27. }
  28. join_iterator(join_iterator && other){
  29. JOIN_CTOR(std::move)
  30. }
  31. join_iterator & operator=(join_iterator const & other) {
  32. JOIN_CTOR()
  33. return *this;
  34. }
  35. join_iterator & operator=(join_iterator && other) {
  36. JOIN_CTOR(std::move)
  37. return *this;
  38. }
  39. reference operator*() { return *curr_; }
  40. join_iterator & operator++() {
  41. ++curr_;
  42. advance();
  43. return *this;
  44. }
  45. bool operator==(join_iterator const & rhs) const { return start_ == rhs.start_; }
  46. private:
  47. void advance() {
  48. while (curr_ == end_ && start_ != finish_) {
  49. if (++start_ == finish_) { break; }
  50. mem_ = *start_;
  51. curr_ = mem_.begin();
  52. end_ = mem_.end();
  53. }
  54. }
  55. iterator<C> start_;
  56. iterator<C> finish_;
  57. C mem_;
  58. typename C::const_iterator curr_;
  59. typename C::const_iterator end_;
  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. iterator<T> begin() {
  66. return {join_iterator<C>{source_.begin(), source_.end()}};
  67. }
  68. 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. }}