#ifndef OPENMW_COMPONENTS_ESM3_INFOORDER_H #define OPENMW_COMPONENTS_ESM3_INFOORDER_H #include "components/esm/refid.hpp" #include #include #include #include #include namespace ESM { template class InfoOrder { public: const std::list& getOrderedInfo() const { return mOrderedInfo; } template void insertInfo(V&& value, bool deleted) { static_assert(std::is_same_v, T>); auto it = mInfoPositions.find(value.mId); if (it != mInfoPositions.end()) { bool samePrev = it->second.mPosition->mPrev == value.mPrev; *it->second.mPosition = std::forward(value); it->second.mDeleted = deleted; if (samePrev) return; } else it = mInfoPositions.emplace(value.mId, Item{ .mPosition = mOrderedInfo.end(), .mDeleted = deleted }) .first; Item& item = it->second; const auto insertOrSplice = [&](typename std::list::const_iterator before) { if (item.mPosition == mOrderedInfo.end()) item.mPosition = mOrderedInfo.insert(before, std::forward(value)); else mOrderedInfo.splice(before, mOrderedInfo, item.mPosition); }; if (value.mPrev.empty()) { insertOrSplice(mOrderedInfo.begin()); return; } const auto prevIt = mInfoPositions.find(value.mPrev); if (prevIt != mInfoPositions.end()) { insertOrSplice(std::next(prevIt->second.mPosition)); return; } insertOrSplice(mOrderedInfo.end()); } void removeInfo(const RefId& infoRefId) { const auto it = mInfoPositions.find(infoRefId); if (it == mInfoPositions.end()) return; mOrderedInfo.erase(it->second.mPosition); mInfoPositions.erase(it); } void removeDeleted() { for (auto it = mInfoPositions.begin(); it != mInfoPositions.end();) { if (!it->second.mDeleted) { ++it; continue; } mOrderedInfo.erase(it->second.mPosition); it = mInfoPositions.erase(it); } } void extractOrderedInfo(std::list& info) { info = mOrderedInfo; mInfoPositions.clear(); } private: struct Item { typename std::list::iterator mPosition; bool mDeleted = false; }; std::list mOrderedInfo; std::unordered_map mInfoPositions; }; } #endif