| #ifndef _RIVE_IMPORT_STACK_HPP_ | |
| #define _RIVE_IMPORT_STACK_HPP_ | |
| #include "rive/status_code.hpp" | |
| #include <algorithm> | |
| #include <unordered_map> | |
| #include <vector> | |
| #include <algorithm> | |
| #include <memory> | |
| namespace rive | |
| { | |
| class ImportStackObject | |
| { | |
| public: | |
| virtual ~ImportStackObject() {} | |
| virtual StatusCode resolve() { return StatusCode::Ok; } | |
| virtual bool readNullObject() { return false; } | |
| }; | |
| class ImportStack | |
| { | |
| public: | |
| template <typename T = ImportStackObject> T* latest(uint16_t coreType) | |
| { | |
| auto itr = m_latests.find(coreType); | |
| if (itr == m_latests.end()) | |
| { | |
| return nullptr; | |
| } | |
| return static_cast<T*>(itr->second.get()); | |
| } | |
| StatusCode makeLatest(uint16_t coreType, std::unique_ptr<ImportStackObject> object) | |
| { | |
| // Clean up the old object in the stack. | |
| auto itr = m_latests.find(coreType); | |
| if (itr != m_latests.end()) | |
| { | |
| auto stackObject = itr->second.get(); | |
| // Remove it from latests. | |
| auto lastAddedItr = std::find(m_lastAdded.begin(), m_lastAdded.end(), stackObject); | |
| if (lastAddedItr != m_lastAdded.end()) | |
| { | |
| m_lastAdded.erase(lastAddedItr); | |
| } | |
| StatusCode code = stackObject->resolve(); | |
| if (code != StatusCode::Ok) | |
| { | |
| m_latests.erase(coreType); | |
| return code; | |
| } | |
| } | |
| // Set the new one. | |
| if (object == nullptr) | |
| { | |
| m_latests.erase(coreType); | |
| } | |
| else | |
| { | |
| m_lastAdded.push_back(object.get()); | |
| m_latests[coreType] = std::move(object); | |
| } | |
| return StatusCode::Ok; | |
| } | |
| StatusCode resolve() | |
| { | |
| StatusCode returnCode = StatusCode::Ok; | |
| // Reverse iterate the last added import stack objects and resolve them. | |
| // If any don't resolve, capture the return code and stop resolving. | |
| for (auto itr = m_lastAdded.rbegin(); itr != m_lastAdded.rend(); itr++) | |
| { | |
| StatusCode code = (*itr)->resolve(); | |
| if (code != StatusCode::Ok) | |
| { | |
| returnCode = code; | |
| break; | |
| } | |
| } | |
| m_latests.clear(); | |
| m_lastAdded.clear(); | |
| return returnCode; | |
| } | |
| bool readNullObject() | |
| { | |
| for (auto itr = m_lastAdded.rbegin(); itr != m_lastAdded.rend(); itr++) | |
| { | |
| if ((*itr)->readNullObject()) | |
| { | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| private: | |
| std::unordered_map<uint16_t, std::unique_ptr<ImportStackObject>> m_latests; | |
| std::vector<ImportStackObject*> m_lastAdded; | |
| }; | |
| } // namespace rive | |
| #endif |