| 3771 | |
| 3772 | template <typename T> |
| 3773 | class RepeatGenerator : public IGenerator<T> { |
| 3774 | GeneratorWrapper<T> m_generator; |
| 3775 | mutable std::vector<T> m_returned; |
| 3776 | size_t m_target_repeats; |
| 3777 | size_t m_current_repeat = 0; |
| 3778 | size_t m_repeat_index = 0; |
| 3779 | public: |
| 3780 | RepeatGenerator(size_t repeats, GeneratorWrapper<T>&& generator): |
| 3781 | m_generator(std::move(generator)), |
| 3782 | m_target_repeats(repeats) |
| 3783 | { |
| 3784 | assert(m_target_repeats > 0 && "Repeat generator must repeat at least once"); |
| 3785 | } |
| 3786 | |
| 3787 | T const& get() const override { |
| 3788 | if (m_current_repeat == 0) { |
| 3789 | m_returned.push_back(m_generator.get()); |
| 3790 | return m_returned.back(); |
| 3791 | } |
| 3792 | return m_returned[m_repeat_index]; |
| 3793 | } |
| 3794 | |
| 3795 | bool next() override { |
| 3796 | // There are 2 basic cases: |
| 3797 | // 1) We are still reading the generator |
| 3798 | // 2) We are reading our own cache |
| 3799 | |
| 3800 | // In the first case, we need to poke the underlying generator. |
| 3801 | // If it happily moves, we are left in that state, otherwise it is time to start reading from our cache |
| 3802 | if (m_current_repeat == 0) { |
| 3803 | const auto success = m_generator.next(); |
| 3804 | if (!success) { |
| 3805 | ++m_current_repeat; |
| 3806 | } |
| 3807 | return m_current_repeat < m_target_repeats; |
| 3808 | } |
| 3809 | |
| 3810 | // In the second case, we need to move indices forward and check that we haven't run up against the end |
| 3811 | ++m_repeat_index; |
| 3812 | if (m_repeat_index == m_returned.size()) { |
| 3813 | m_repeat_index = 0; |
| 3814 | ++m_current_repeat; |
| 3815 | } |
| 3816 | return m_current_repeat < m_target_repeats; |
| 3817 | } |
| 3818 | }; |
| 3819 | |
| 3820 | template <typename T> |
| 3821 | GeneratorWrapper<T> repeat(size_t repeats, GeneratorWrapper<T>&& generator) { |