#ifndef CREATURELIB_SCRIPTAGGREGATOR_HPP #define CREATURELIB_SCRIPTAGGREGATOR_HPP #include #include #include "Script.hpp" #include "ScriptSet.hpp" #include "../../Core/Exceptions/NotReachableException.hpp" #include "ScriptWrapper.hpp" namespace CreatureLib::Battling{ class ScriptAggregator{ __gnu_cxx::__normal_iterator> _selfIterator; __gnu_cxx::__normal_iterator> _selfEnd; bool _isSetSet = false; std::__detail::_Node_const_iterator, false, true> _setIterator; std::__detail::_Node_const_iterator, false, true> _setEnd; public: ScriptAggregator(std::vector scripts){ _selfIterator = scripts.begin(); _selfEnd = scripts.end(); }; bool HasNext(){ return _selfIterator != _selfEnd || (_isSetSet && _setIterator != _setEnd); } Script* GetNext(){ // We can probably do this in a cleaner version once C++ 20 drops with Coroutine support. if (_isSetSet){ if (_setIterator == _setEnd){ _isSetSet = false; return GetNext(); } auto s = _setIterator->second; _setIterator.operator++(); if (_setIterator == _setEnd){ _isSetSet = false; } return s; } if (_selfIterator == _selfEnd) return nullptr; auto next = *_selfIterator; _selfIterator++; if (!next.IsSet()){ auto scriptPtr = next.GetScript(); if (scriptPtr == nullptr) return GetNext(); return *scriptPtr; } else{ auto set = next.GetScriptSet(); if (set->Count() == 0) return GetNext(); auto it = set->GetIterator(); _setIterator = it->begin(); _setEnd = it->end(); _isSetSet = true; return GetNext(); } throw NotReachableException(); } }; } #endif //CREATURELIB_SCRIPTAGGREGATOR_HPP