join.hpp 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. #pragma once
  2. #include <iterator>
  3. #include "self_iterating_contianer.hpp"
  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 { return start_ == rhs.start_; }
  23. private:
  24. void advance() {
  25. while (!current_ && start_ != finish_) {
  26. if (++start_ == finish_) { break; }
  27. current_ = *start_;
  28. }
  29. }
  30. iterator<C> start_;
  31. iterator<C> finish_;
  32. self_iterating_container<C> current_;
  33. };
  34. template <typename C> class join_stream {
  35. public:
  36. using T = typename C::value_type;
  37. explicit join_stream(stream_base<C> const & sb) : source_(sb) {}
  38. iterator<T> begin() {
  39. return {join_iterator<C>{source_.begin(), source_.end()}};
  40. }
  41. iterator<T> end() {
  42. return {join_iterator<C>{source_.end(), source_.end()}};
  43. }
  44. private:
  45. stream_base<C> source_;
  46. };
  47. template <typename C>
  48. stream_base<typename C::value_type> make_join(stream_base<C> const & sb) {
  49. return std::make_shared<join_stream<C>>(sb);
  50. }
  51. template <typename T>
  52. template <typename F>
  53. stream_base<traits::fmapped_t<T, F>> stream_base<T>::flatmap(F && func) && {
  54. return make_join(std::move(*this).map(func));
  55. }
  56. template <typename T>
  57. template <typename F>
  58. stream_base<traits::fmapped_t<T, F>>
  59. stream_base<T>::flatmap(F && func) const & {
  60. return make_join(map(func));
  61. }
  62. }}