#pragma once #include #include "Iterator.h" #include "ReferenceCounter.h" namespace Framework { namespace Exceptions { class EndOfSupplier { const char* msg; public: EndOfSupplier() : msg("End of Supplier") {} }; } // namespace Exceptions template class Supplier : public ReferenceCounter { public: Supplier() : ReferenceCounter() {} virtual ~Supplier() {} virtual T next() noexcept(false) = 0; }; template class IteratorSupplier : public Supplier { private: BasicIterator* iterator; public: IteratorSupplier(BasicIterator* iterator) : Supplier(), iterator(iterator) {} ~IteratorSupplier() { delete iterator; } T next() noexcept(false) override { if (!*iterator) { throw Exceptions::EndOfSupplier(); } T val = iterator->val(); iterator->plusPlus(); return val; } }; template class FilteredSupplier : public Supplier { private: Supplier* supplier; std::function filter; public: FilteredSupplier(Supplier* supplier, std::function filter) : Supplier(), supplier(supplier), filter(filter) {} ~FilteredSupplier() { supplier->release(); } T next() noexcept(false) override { T val = supplier->next(); while (!filter(val)) { val = supplier->next(); } return val; } }; template class MappedSupplier : public Supplier { private: Supplier* supplier; std::function mapper; public: MappedSupplier(Supplier* supplier, std::function mapper) : Supplier(), supplier(supplier), mapper(mapper) {} ~MappedSupplier() { supplier->release(); } R next() noexcept(false) override { return mapper(supplier->next()); } }; template class Stream; template class FlatMappedSupplier : public Supplier { private: Supplier* supplier; std::function*(T)> mapper; Supplier* currentSupplier; public: FlatMappedSupplier( Supplier* supplier, std::function*(T)> mapper) : Supplier(), supplier(supplier), mapper(mapper), currentSupplier(nullptr) {} ~FlatMappedSupplier() { if (currentSupplier != nullptr) { currentSupplier->release(); } supplier->release(); } R next() noexcept(false) override { while (true) { if (currentSupplier == nullptr) { currentSupplier = mapper(supplier->next()); } try { return currentSupplier->next(); } catch (Exceptions::EndOfSupplier) { currentSupplier->release(); currentSupplier = nullptr; } } } }; } // namespace Framework