join.hpp 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. #pragma once
  2. #include "self_iterating_container.hpp"
  3. #include <iterator>
  4. namespace stream { namespace detail {
  5. template <typename C> class join_iterator {
  6. public:
  7. using reference = typename C::const_iterator::reference;
  8. public:
  9. join_iterator(iterator<C> && f, iterator<C> && l)
  10. : start_(std::move(f)), finish_(std::move(l)) {
  11. if (start_ != finish_) {
  12. current_ = *start_;
  13. advance();
  14. }
  15. }
  16. reference operator*() { return *current_; }
  17. join_iterator & operator++() {
  18. ++current_;
  19. advance();
  20. return *this;
  21. }
  22. bool operator==(join_iterator const & rhs) const {
  23. return start_ == rhs.start_;
  24. }
  25. private:
  26. void advance() {
  27. while (!current_ && start_ != finish_) {
  28. if (++start_ == finish_) { break; }
  29. current_ = *start_;
  30. }
  31. }
  32. iterator<C> start_;
  33. iterator<C> finish_;
  34. self_iterating_container<C> current_;
  35. };
  36. template <typename C> class join_stream {
  37. public:
  38. using T = typename C::value_type;
  39. explicit join_stream(stream_base<C> const & sb) : source_(sb) {}
  40. iterator<T> begin() {
  41. return {join_iterator<C>{source_.begin(), source_.end()}};
  42. }
  43. iterator<T> end() {
  44. return {join_iterator<C>{source_.end(), source_.end()}};
  45. }
  46. private:
  47. stream_base<C> source_;
  48. };
  49. template <typename C>
  50. stream_base<typename C::value_type> make_join(stream_base<C> const & sb) {
  51. return std::make_shared<join_stream<C>>(sb);
  52. }
  53. template <typename T>
  54. template <typename F>
  55. stream_base<traits::fmapped_t<T, F>> stream_base<T>::flatmap(F && func) && {
  56. return make_join(std::move(*this).map(func));
  57. }
  58. template <typename T>
  59. template <typename F>
  60. stream_base<traits::fmapped_t<T, F>>
  61. stream_base<T>::flatmap(F && func) const & {
  62. return make_join(map(func));
  63. }
  64. }}