diff --git a/apps/components_tests/esm3/readerscache.cpp b/apps/components_tests/esm3/readerscache.cpp index f222a29bf8..1cb9a85fb6 100644 --- a/apps/components_tests/esm3/readerscache.cpp +++ b/apps/components_tests/esm3/readerscache.cpp @@ -88,4 +88,31 @@ namespace EXPECT_EQ(reader->getFileOffset(), sInitialOffset); } } + + TEST_F(ESM3ReadersCacheWithContentFile, CachedSizeAndName) + { + ESM::ReadersCache readers(2); + { + readers.get(0)->openRaw(std::make_unique("123"), "closed0.omwaddon"); + readers.get(1)->openRaw(std::make_unique("12345"), "closed1.omwaddon"); + readers.get(2)->openRaw(std::make_unique("1234567"), "free.omwaddon"); + } + auto busy = readers.get(3); + busy->openRaw(std::make_unique("123456789"), "busy.omwaddon"); + + EXPECT_EQ(readers.getFileSize(0), 3); + EXPECT_EQ(readers.getName(0), "closed0.omwaddon"); + + EXPECT_EQ(readers.getFileSize(1), 5); + EXPECT_EQ(readers.getName(1), "closed1.omwaddon"); + + EXPECT_EQ(readers.getFileSize(2), 7); + EXPECT_EQ(readers.getName(2), "free.omwaddon"); + + EXPECT_EQ(readers.getFileSize(3), 9); + EXPECT_EQ(readers.getName(3), "busy.omwaddon"); + + // not-yet-seen indices give zero for their size + EXPECT_EQ(readers.getFileSize(4), 0); + } } diff --git a/components/esm3/esmreader.cpp b/components/esm3/esmreader.cpp index 4f69b8edef..adb0d1c103 100644 --- a/components/esm3/esmreader.cpp +++ b/components/esm3/esmreader.cpp @@ -73,10 +73,10 @@ namespace ESM int index = getIndex(); for (int i = 0; i < getIndex(); i++) { - const ESM::ReadersCache::BusyItem reader = readers.get(static_cast(i)); - if (reader->getFileSize() == 0) + if (readers.getFileSize(static_cast(i)) == 0) continue; // Content file in non-ESM format - const auto fnamecandidate = Files::pathToUnicodeString(reader->getName().filename()); + const auto fnamecandidate + = Files::pathToUnicodeString(readers.getName(static_cast(i)).filename()); if (Misc::StringUtils::ciEqual(fname, fnamecandidate)) { index = i; diff --git a/components/esm3/readerscache.cpp b/components/esm3/readerscache.cpp index 732a2a22ba..34ceff5ffd 100644 --- a/components/esm3/readerscache.cpp +++ b/components/esm3/readerscache.cpp @@ -47,6 +47,7 @@ namespace ESM { it->mReader.open(*it->mName); it->mName.reset(); + it->mFileSize.reset(); } mBusyItems.splice(mBusyItems.end(), mClosedItems, it); break; @@ -57,6 +58,46 @@ namespace ESM return BusyItem(*this, it); } + const std::filesystem::path& ReadersCache::getName(std::size_t index) const + { + const auto indexIt = mIndex.find(index); + if (indexIt == mIndex.end()) + throw std::logic_error("ESMReader at index " + std::to_string(index) + " has not been created yet"); + switch (indexIt->second->mState) + { + case State::Busy: + case State::Free: + return indexIt->second->mReader.getName(); + case State::Closed: + if (indexIt->second->mName) + return *indexIt->second->mName; + throw std::logic_error("ESMReader at index " + std::to_string(index) + " has forgotten its filename"); + default: + throw std::logic_error("ESMReader at index " + std::to_string(index) + " in unknown state"); + } + } + + std::size_t ReadersCache::getFileSize(std::size_t index) + { + const auto indexIt = mIndex.find(index); + if (indexIt == mIndex.end()) + return 0; + switch (indexIt->second->mState) + { + case State::Busy: + case State::Free: + if (!indexIt->second->mReader.getName().empty()) + return indexIt->second->mReader.getFileSize(); + throw std::logic_error("ESMReader at index " + std::to_string(index) + " has not been opened yet"); + case State::Closed: + if (indexIt->second->mFileSize) + return *indexIt->second->mFileSize; + throw std::logic_error("ESMReader at index " + std::to_string(index) + " has forgotten its file size"); + default: + throw std::logic_error("ESMReader at index " + std::to_string(index) + " in unknown state"); + } + } + void ReadersCache::closeExtraReaders() { while (!mFreeItems.empty() && mBusyItems.size() + mFreeItems.size() + 1 > mCapacity) @@ -65,6 +106,7 @@ namespace ESM if (it->mReader.isOpen()) { it->mName = it->mReader.getName(); + it->mFileSize = it->mReader.getFileSize(); it->mReader.close(); } mClosedItems.splice(mClosedItems.end(), mFreeItems, it); diff --git a/components/esm3/readerscache.hpp b/components/esm3/readerscache.hpp index 80ca5d1ef3..3f6ac01874 100644 --- a/components/esm3/readerscache.hpp +++ b/components/esm3/readerscache.hpp @@ -26,6 +26,7 @@ namespace ESM State mState = State::Busy; ESMReader mReader; std::optional mName; + std::optional mFileSize; Item() = default; }; @@ -55,6 +56,10 @@ namespace ESM BusyItem get(std::size_t index); + const std::filesystem::path& getName(std::size_t index) const; + + std::size_t getFileSize(std::size_t index); + void clear(); private: