From d4e26746a32404d620c8e847335ba096668fee17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Mocquillon?= Date: Mon, 6 Sep 2021 21:56:32 +0200 Subject: [PATCH 1/3] Use recurse subdirectory iterator to iterate over the VFS without exposing internal details --- apps/niftest/niftest.cpp | 5 +-- apps/opencs/model/world/resources.cpp | 4 +- apps/openmw/mwgui/loadingscreen.cpp | 23 ++++------ apps/openmw/mwrender/animation.cpp | 36 ++++------------ apps/openmw/mwsound/soundmanagerimp.cpp | 18 ++------ components/fontloader/fontloader.cpp | 18 ++------ components/vfs/manager.cpp | 10 ++--- components/vfs/manager.hpp | 56 +++++++++++++++++++++++-- 8 files changed, 82 insertions(+), 88 deletions(-) diff --git a/apps/niftest/niftest.cpp b/apps/niftest/niftest.cpp index 2e81885c75..cb6205ef5c 100644 --- a/apps/niftest/niftest.cpp +++ b/apps/niftest/niftest.cpp @@ -52,11 +52,8 @@ void readVFS(VFS::Archive* anArchive,std::string archivePath = "") myManager.addArchive(anArchive); myManager.buildIndex(); - std::map files=myManager.getIndex(); - for(auto it=files.begin(); it!=files.end(); ++it) + for(const auto& name : myManager.getRecursiveDirectoryIterator("")) { - std::string name = it->first; - try{ if(isNIF(name)) { diff --git a/apps/opencs/model/world/resources.cpp b/apps/opencs/model/world/resources.cpp index 2544886f3e..cd9f58e848 100644 --- a/apps/opencs/model/world/resources.cpp +++ b/apps/opencs/model/world/resources.cpp @@ -23,10 +23,8 @@ void CSMWorld::Resources::recreate(const VFS::Manager* vfs, const char * const * size_t baseSize = mBaseDirectory.size(); - const std::map& index = vfs->getIndex(); - for (std::map::const_iterator it = index.begin(); it != index.end(); ++it) + for (const auto& filepath : vfs->getRecursiveDirectoryIterator("")) { - std::string filepath = it->first; if (filepath.size()& index = mResourceSystem->getVFS()->getIndex(); std::string pattern = "Splash/"; mResourceSystem->getVFS()->normalizeFilename(pattern); /* priority given to the left */ const std::array supported_extensions {{".tga", ".dds", ".ktx", ".png", ".bmp", ".jpeg", ".jpg"}}; - auto found = index.lower_bound(pattern); - while (found != index.end()) + for (const auto& name : mResourceSystem->getVFS()->getRecursiveDirectoryIterator(pattern)) { - const std::string& name = found->first; - if (name.size() >= pattern.size() && name.substr(0, pattern.size()) == pattern) + size_t pos = name.find_last_of('.'); + if (pos != std::string::npos) { - size_t pos = name.find_last_of('.'); - if (pos != std::string::npos) + for (auto const& extension : supported_extensions) { - for(auto const& extension: supported_extensions) + if (name.compare(pos, name.size() - pos, extension) == 0) { - if (name.compare(pos, name.size() - pos, extension) == 0) - { - mSplashScreens.push_back(found->first); - break; /* based on priority */ - } + mSplashScreens.push_back(name); + break; /* based on priority */ } } } - else - break; - ++found; } if (mSplashScreens.empty()) Log(Debug::Warning) << "Warning: no splash screens found!"; diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index a04724c70a..4eafd05f5f 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -591,8 +591,6 @@ namespace MWRender void Animation::loadAllAnimationsInFolder(const std::string &model, const std::string &baseModel) { - const std::map& index = mResourceSystem->getVFS()->getIndex(); - std::string animationPath = model; if (animationPath.find("meshes") == 0) { @@ -602,19 +600,11 @@ namespace MWRender mResourceSystem->getVFS()->normalizeFilename(animationPath); - std::map::const_iterator found = index.lower_bound(animationPath); - while (found != index.end()) + for (const auto& name : mResourceSystem->getVFS()->getRecursiveDirectoryIterator(animationPath)) { - const std::string& name = found->first; - if (name.size() >= animationPath.size() && name.substr(0, animationPath.size()) == animationPath) - { - size_t pos = name.find_last_of('.'); - if (pos != std::string::npos && name.compare(pos, name.size()-pos, ".kf") == 0) - addSingleAnimSource(name, baseModel); - } - else - break; - ++found; + size_t pos = name.find_last_of('.'); + if (pos != std::string::npos && name.compare(pos, name.size() - pos, ".kf") == 0) + addSingleAnimSource(name, baseModel); } } @@ -1295,8 +1285,6 @@ namespace MWRender if (model.empty()) return; - const std::map& index = resourceSystem->getVFS()->getIndex(); - std::string animationPath = model; if (animationPath.find("meshes") == 0) { @@ -1306,19 +1294,11 @@ namespace MWRender resourceSystem->getVFS()->normalizeFilename(animationPath); - std::map::const_iterator found = index.lower_bound(animationPath); - while (found != index.end()) + for (const auto& name : resourceSystem->getVFS()->getRecursiveDirectoryIterator(animationPath)) { - const std::string& name = found->first; - if (name.size() >= animationPath.size() && name.substr(0, animationPath.size()) == animationPath) - { - size_t pos = name.find_last_of('.'); - if (pos != std::string::npos && name.compare(pos, name.size()-pos, ".nif") == 0) - loadBonesFromFile(node, name, resourceSystem); - } - else - break; - ++found; + size_t pos = name.find_last_of('.'); + if (pos != std::string::npos && name.compare(pos, name.size() - pos, ".nif") == 0) + loadBonesFromFile(node, name, resourceSystem); } } diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index fc9735d576..f5c3231c99 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -294,20 +294,12 @@ namespace MWSound if (mMusicFiles.find(playlist) == mMusicFiles.end()) { std::vector filelist; - const std::map& index = mVFS->getIndex(); std::string pattern = "Music/" + playlist; mVFS->normalizeFilename(pattern); - std::map::const_iterator found = index.lower_bound(pattern); - while (found != index.end()) - { - if (found->first.size() >= pattern.size() && found->first.substr(0, pattern.size()) == pattern) - filelist.push_back(found->first); - else - break; - ++found; - } + for (const auto& name : mVFS->getRecursiveDirectoryIterator(pattern)) + filelist.push_back(name); mMusicFiles[playlist] = filelist; } @@ -327,13 +319,11 @@ namespace MWSound if (mMusicFiles.find("Title") == mMusicFiles.end()) { std::vector filelist; - const std::map& index = mVFS->getIndex(); // Is there an ini setting for this filename or something? std::string filename = "music/special/morrowind title.mp3"; - auto found = index.find(filename); - if (found != index.end()) + if (mVFS->exists(filename)) { - filelist.emplace_back(found->first); + filelist.emplace_back(filename); mMusicFiles["Title"] = filelist; } else diff --git a/components/fontloader/fontloader.cpp b/components/fontloader/fontloader.cpp index 487b7bd70b..998e9c0c64 100644 --- a/components/fontloader/fontloader.cpp +++ b/components/fontloader/fontloader.cpp @@ -191,24 +191,14 @@ namespace Gui void FontLoader::loadBitmapFonts(bool exportToFile) { - const std::map& index = mVFS->getIndex(); - std::string pattern = "Fonts/"; mVFS->normalizeFilename(pattern); - std::map::const_iterator found = index.lower_bound(pattern); - while (found != index.end()) + for (const auto& name : mVFS->getRecursiveDirectoryIterator(pattern)) { - const std::string& name = found->first; - if (name.size() >= pattern.size() && name.substr(0, pattern.size()) == pattern) - { - size_t pos = name.find_last_of('.'); - if (pos != std::string::npos && name.compare(pos, name.size()-pos, ".fnt") == 0) - loadBitmapFont(name, exportToFile); - } - else - break; - ++found; + size_t pos = name.find_last_of('.'); + if (pos != std::string::npos && name.compare(pos, name.size() - pos, ".fnt") == 0) + loadBitmapFont(name, exportToFile); } } diff --git a/components/vfs/manager.cpp b/components/vfs/manager.cpp index 045fe3cf5c..f799719e31 100644 --- a/components/vfs/manager.cpp +++ b/components/vfs/manager.cpp @@ -86,11 +86,6 @@ namespace VFS return mIndex.find(normalized) != mIndex.end(); } - const std::map& Manager::getIndex() const - { - return mIndex; - } - void Manager::normalizeFilename(std::string &name) const { normalize_path(name, mStrict); @@ -107,4 +102,9 @@ namespace VFS } return {}; } + + RecursiveDirectoryIterator Manager::getRecursiveDirectoryIterator(const std::string& path) const + { + return RecursiveDirectoryIterator(mIndex, path); + } } diff --git a/components/vfs/manager.hpp b/components/vfs/manager.hpp index 5a09a995eb..8656f3bf10 100644 --- a/components/vfs/manager.hpp +++ b/components/vfs/manager.hpp @@ -12,6 +12,51 @@ namespace VFS class Archive; class File; + class RecursiveDirectoryIterator; + RecursiveDirectoryIterator end(const RecursiveDirectoryIterator& iter); + + class RecursiveDirectoryIterator + { + public: + RecursiveDirectoryIterator(const std::map& index, const std::string& path) + : mPath(path) + , mIndex(&index) + , mIt(index.lower_bound(path)) + {} + + RecursiveDirectoryIterator(const RecursiveDirectoryIterator&) = default; + + const std::string& operator*() const { return mIt->first; } + const std::string* operator->() const { return &mIt->first; } + + bool operator!=(const RecursiveDirectoryIterator& other) { return mPath != other.mPath || mIt != other.mIt; } + + RecursiveDirectoryIterator& operator++() + { + if (++mIt == mIndex->end() || !starts_with(mIt->first, mPath)) + *this = end(*this); + return *this; + } + + friend RecursiveDirectoryIterator end(const RecursiveDirectoryIterator& iter); + + private: + static bool starts_with(const std::string& text, const std::string& start) { return text.rfind(start, 0) == 0; } + + std::string mPath; + const std::map* mIndex; + std::map::const_iterator mIt; + }; + + inline RecursiveDirectoryIterator begin(RecursiveDirectoryIterator iter) { return iter; } + + inline RecursiveDirectoryIterator end(const RecursiveDirectoryIterator& iter) + { + RecursiveDirectoryIterator result(iter); + result.mIt = result.mIndex->end(); + return result; + } + /// @brief The main class responsible for loading files from a virtual file system. /// @par Various archive types (e.g. directories on the filesystem, or compressed archives) /// can be registered, and will be merged into a single file tree. If the same filename is @@ -40,10 +85,6 @@ namespace VFS /// @note May be called from any thread once the index has been built. bool exists(const std::string& name) const; - /// Get a complete list of files from all archives - /// @note May be called from any thread once the index has been built. - const std::map& getIndex() const; - /// Normalize the given filename, making slashes/backslashes consistent, and lower-casing if mStrict is false. /// @note May be called from any thread once the index has been built. void normalizeFilename(std::string& name) const; @@ -59,6 +100,13 @@ namespace VFS Files::IStreamPtr getNormalized(const std::string& normalizedName) const; std::string getArchive(const std::string& name) const; + + /// Recursivly iterate over the elements of the given path + /// In practice it return all files of the VFS starting with the given path + /// @note the path is normalized + /// @note May be called from any thread once the index has been built. + RecursiveDirectoryIterator getRecursiveDirectoryIterator(const std::string& path) const; + private: bool mStrict; From c2df0949e2d739830bf3c3838f644cfdd9bb3371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Mocquillon?= Date: Mon, 6 Sep 2021 22:01:41 +0200 Subject: [PATCH 2/3] Change normalizeFilename signature --- apps/openmw/mwgui/loadingscreen.cpp | 5 +---- apps/openmw/mwrender/animation.cpp | 4 ---- apps/openmw/mwsound/sound_buffer.cpp | 2 +- apps/openmw/mwsound/soundmanagerimp.cpp | 15 +++------------ components/fontloader/fontloader.cpp | 5 +---- components/resource/bulletshapemanager.cpp | 9 +++------ components/resource/imagemanager.cpp | 3 +-- components/resource/keyframemanager.cpp | 3 +-- components/resource/scenemanager.cpp | 14 ++++---------- components/vfs/manager.cpp | 8 +++++--- components/vfs/manager.hpp | 2 +- 11 files changed, 21 insertions(+), 49 deletions(-) diff --git a/apps/openmw/mwgui/loadingscreen.cpp b/apps/openmw/mwgui/loadingscreen.cpp index 2d65e4e508..7f454925fd 100644 --- a/apps/openmw/mwgui/loadingscreen.cpp +++ b/apps/openmw/mwgui/loadingscreen.cpp @@ -66,13 +66,10 @@ namespace MWGui void LoadingScreen::findSplashScreens() { - std::string pattern = "Splash/"; - mResourceSystem->getVFS()->normalizeFilename(pattern); - /* priority given to the left */ const std::array supported_extensions {{".tga", ".dds", ".ktx", ".png", ".bmp", ".jpeg", ".jpg"}}; - for (const auto& name : mResourceSystem->getVFS()->getRecursiveDirectoryIterator(pattern)) + for (const auto& name : mResourceSystem->getVFS()->getRecursiveDirectoryIterator("Splash/")) { size_t pos = name.find_last_of('.'); if (pos != std::string::npos) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 4eafd05f5f..3df902e469 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -598,8 +598,6 @@ namespace MWRender } animationPath.replace(animationPath.size()-3, 3, "/"); - mResourceSystem->getVFS()->normalizeFilename(animationPath); - for (const auto& name : mResourceSystem->getVFS()->getRecursiveDirectoryIterator(animationPath)) { size_t pos = name.find_last_of('.'); @@ -1292,8 +1290,6 @@ namespace MWRender } animationPath.replace(animationPath.size()-4, 4, "/"); - resourceSystem->getVFS()->normalizeFilename(animationPath); - for (const auto& name : resourceSystem->getVFS()->getRecursiveDirectoryIterator(animationPath)) { size_t pos = name.find_last_of('.'); diff --git a/apps/openmw/mwsound/sound_buffer.cpp b/apps/openmw/mwsound/sound_buffer.cpp index cb71cb56d2..e64e89d775 100644 --- a/apps/openmw/mwsound/sound_buffer.cpp +++ b/apps/openmw/mwsound/sound_buffer.cpp @@ -131,7 +131,7 @@ namespace MWSound max = std::max(min, max); Sound_Buffer& sfx = mSoundBuffers.emplace_back("Sound/" + sound.mSound, volume, min, max); - mVfs->normalizeFilename(sfx.mResourceName); + sfx.mResourceName = mVfs->normalizeFilename(sfx.mResourceName); mBufferNameMap.emplace(soundId, &sfx); return &sfx; diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index f5c3231c99..d2422870d7 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -295,10 +295,7 @@ namespace MWSound { std::vector filelist; - std::string pattern = "Music/" + playlist; - mVFS->normalizeFilename(pattern); - - for (const auto& name : mVFS->getRecursiveDirectoryIterator(pattern)) + for (const auto& name : mVFS->getRecursiveDirectoryIterator("Music/" + playlist)) filelist.push_back(name); mMusicFiles[playlist] = filelist; @@ -345,10 +342,7 @@ namespace MWSound if(!mOutput->isInitialized()) return; - std::string voicefile = "Sound/"+filename; - - mVFS->normalizeFilename(voicefile); - DecoderPtr decoder = loadVoice(voicefile); + DecoderPtr decoder = loadVoice(mVFS->normalizeFilename("Sound/" + filename)); if (!decoder) return; @@ -379,10 +373,7 @@ namespace MWSound if(!mOutput->isInitialized()) return; - std::string voicefile = "Sound/"+filename; - - mVFS->normalizeFilename(voicefile); - DecoderPtr decoder = loadVoice(voicefile); + DecoderPtr decoder = loadVoice(mVFS->normalizeFilename("Sound/" + filename)); if (!decoder) return; diff --git a/components/fontloader/fontloader.cpp b/components/fontloader/fontloader.cpp index 998e9c0c64..9ba62f7694 100644 --- a/components/fontloader/fontloader.cpp +++ b/components/fontloader/fontloader.cpp @@ -191,10 +191,7 @@ namespace Gui void FontLoader::loadBitmapFonts(bool exportToFile) { - std::string pattern = "Fonts/"; - mVFS->normalizeFilename(pattern); - - for (const auto& name : mVFS->getRecursiveDirectoryIterator(pattern)) + for (const auto& name : mVFS->getRecursiveDirectoryIterator("Fonts/")) { size_t pos = name.find_last_of('.'); if (pos != std::string::npos && name.compare(pos, name.size() - pos, ".fnt") == 0) diff --git a/components/resource/bulletshapemanager.cpp b/components/resource/bulletshapemanager.cpp index b1b0f74176..98878df152 100644 --- a/components/resource/bulletshapemanager.cpp +++ b/components/resource/bulletshapemanager.cpp @@ -121,8 +121,7 @@ BulletShapeManager::~BulletShapeManager() osg::ref_ptr BulletShapeManager::getShape(const std::string &name) { - std::string normalized = name; - mVFS->normalizeFilename(normalized); + const std::string normalized = mVFS->normalizeFilename(name); osg::ref_ptr shape; osg::ref_ptr obj = mCache->getRefFromObjectCache(normalized); @@ -180,8 +179,7 @@ osg::ref_ptr BulletShapeManager::getShape(const std::string & osg::ref_ptr BulletShapeManager::cacheInstance(const std::string &name) { - std::string normalized = name; - mVFS->normalizeFilename(normalized); + const std::string normalized = mVFS->normalizeFilename(name); osg::ref_ptr instance = createInstance(normalized); if (instance) @@ -191,8 +189,7 @@ osg::ref_ptr BulletShapeManager::cacheInstance(const std::s osg::ref_ptr BulletShapeManager::getInstance(const std::string &name) { - std::string normalized = name; - mVFS->normalizeFilename(normalized); + const std::string normalized = mVFS->normalizeFilename(name); osg::ref_ptr obj = mInstanceCache->takeFromObjectCache(normalized); if (obj.get()) diff --git a/components/resource/imagemanager.cpp b/components/resource/imagemanager.cpp index 37e76359ff..ba46b5cce9 100644 --- a/components/resource/imagemanager.cpp +++ b/components/resource/imagemanager.cpp @@ -83,8 +83,7 @@ namespace Resource osg::ref_ptr ImageManager::getImage(const std::string &filename) { - std::string normalized = filename; - mVFS->normalizeFilename(normalized); + const std::string normalized = mVFS->normalizeFilename(filename); osg::ref_ptr obj = mCache->getRefFromObjectCache(normalized); if (obj) diff --git a/components/resource/keyframemanager.cpp b/components/resource/keyframemanager.cpp index 444d2bd7aa..6d431fb3a5 100644 --- a/components/resource/keyframemanager.cpp +++ b/components/resource/keyframemanager.cpp @@ -133,8 +133,7 @@ namespace Resource osg::ref_ptr KeyframeManager::get(const std::string &name) { - std::string normalized = name; - mVFS->normalizeFilename(normalized); + const std::string normalized = mVFS->normalizeFilename(name); osg::ref_ptr obj = mCache->getRefFromObjectCache(normalized); if (obj) diff --git a/components/resource/scenemanager.cpp b/components/resource/scenemanager.cpp index 33a9ab99a1..ec6bea02d7 100644 --- a/components/resource/scenemanager.cpp +++ b/components/resource/scenemanager.cpp @@ -358,10 +358,7 @@ namespace Resource bool SceneManager::checkLoaded(const std::string &name, double timeStamp) { - std::string normalized = name; - mVFS->normalizeFilename(normalized); - - return mCache->checkInObjectCache(normalized, timeStamp); + return mCache->checkInObjectCache(mVFS->normalizeFilename(name), timeStamp); } /// @brief Callback to read image files from the VFS. @@ -533,8 +530,7 @@ namespace Resource osg::ref_ptr SceneManager::getTemplate(const std::string &name, bool compile) { - std::string normalized = name; - mVFS->normalizeFilename(normalized); + std::string normalized = mVFS->normalizeFilename(name); osg::ref_ptr obj = mCache->getRefFromObjectCache(normalized); if (obj) @@ -603,8 +599,7 @@ namespace Resource osg::ref_ptr SceneManager::cacheInstance(const std::string &name) { - std::string normalized = name; - mVFS->normalizeFilename(normalized); + const std::string normalized = mVFS->normalizeFilename(name); osg::ref_ptr node = createInstance(normalized); @@ -642,8 +637,7 @@ namespace Resource osg::ref_ptr SceneManager::getInstance(const std::string &name) { - std::string normalized = name; - mVFS->normalizeFilename(normalized); + const std::string normalized = mVFS->normalizeFilename(name); osg::ref_ptr obj = mInstanceCache->takeFromObjectCache(normalized); if (obj.get()) diff --git a/components/vfs/manager.cpp b/components/vfs/manager.cpp index f799719e31..1cb8745497 100644 --- a/components/vfs/manager.cpp +++ b/components/vfs/manager.cpp @@ -86,9 +86,11 @@ namespace VFS return mIndex.find(normalized) != mIndex.end(); } - void Manager::normalizeFilename(std::string &name) const + std::string Manager::normalizeFilename(const std::string& name) const { - normalize_path(name, mStrict); + std::string result = name; + normalize_path(result, mStrict); + return result; } std::string Manager::getArchive(const std::string& name) const @@ -105,6 +107,6 @@ namespace VFS RecursiveDirectoryIterator Manager::getRecursiveDirectoryIterator(const std::string& path) const { - return RecursiveDirectoryIterator(mIndex, path); + return RecursiveDirectoryIterator(mIndex, normalizeFilename(path)); } } diff --git a/components/vfs/manager.hpp b/components/vfs/manager.hpp index 8656f3bf10..b98d8021d4 100644 --- a/components/vfs/manager.hpp +++ b/components/vfs/manager.hpp @@ -87,7 +87,7 @@ namespace VFS /// Normalize the given filename, making slashes/backslashes consistent, and lower-casing if mStrict is false. /// @note May be called from any thread once the index has been built. - void normalizeFilename(std::string& name) const; + [[nodiscard]] std::string normalizeFilename(const std::string& name) const; /// Retrieve a file by name. /// @note Throws an exception if the file can not be found. From 681728209735520de5daf3657cc5c754783c5028 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Mocquillon?= Date: Sat, 11 Sep 2021 15:49:47 +0200 Subject: [PATCH 3/3] Move getFileExtension to common header and use instead of repeating same code --- apps/openmw/mwgui/loadingscreen.cpp | 21 +++++++-------------- apps/openmw/mwrender/animation.cpp | 7 +++---- components/fontloader/fontloader.cpp | 4 ++-- components/misc/pathhelpers.hpp | 19 +++++++++++++++++++ components/resource/bulletshapemanager.cpp | 8 ++------ components/resource/imagemanager.cpp | 6 ++---- components/resource/keyframemanager.cpp | 4 ++-- components/resource/scenemanager.cpp | 13 +++---------- 8 files changed, 40 insertions(+), 42 deletions(-) create mode 100644 components/misc/pathhelpers.hpp diff --git a/apps/openmw/mwgui/loadingscreen.cpp b/apps/openmw/mwgui/loadingscreen.cpp index 7f454925fd..ef8eea0104 100644 --- a/apps/openmw/mwgui/loadingscreen.cpp +++ b/apps/openmw/mwgui/loadingscreen.cpp @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -66,23 +67,15 @@ namespace MWGui void LoadingScreen::findSplashScreens() { - /* priority given to the left */ - const std::array supported_extensions {{".tga", ".dds", ".ktx", ".png", ".bmp", ".jpeg", ".jpg"}}; + auto isSupportedExtension = [](const std::string_view& ext) { + static const std::array supported_extensions{ {"tga", "dds", "ktx", "png", "bmp", "jpeg", "jpg"} }; + return !ext.empty() && std::find(supported_extensions.begin(), supported_extensions.end(), ext) != supported_extensions.end(); + }; for (const auto& name : mResourceSystem->getVFS()->getRecursiveDirectoryIterator("Splash/")) { - size_t pos = name.find_last_of('.'); - if (pos != std::string::npos) - { - for (auto const& extension : supported_extensions) - { - if (name.compare(pos, name.size() - pos, extension) == 0) - { - mSplashScreens.push_back(name); - break; /* based on priority */ - } - } - } + if (isSupportedExtension(Misc::getFileExtension(name))) + mSplashScreens.push_back(name); } if (mSplashScreens.empty()) Log(Debug::Warning) << "Warning: no splash screens found!"; diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 3df902e469..1dc42db47c 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -600,8 +601,7 @@ namespace MWRender for (const auto& name : mResourceSystem->getVFS()->getRecursiveDirectoryIterator(animationPath)) { - size_t pos = name.find_last_of('.'); - if (pos != std::string::npos && name.compare(pos, name.size() - pos, ".kf") == 0) + if (Misc::getFileExtension(name) == "kf") addSingleAnimSource(name, baseModel); } } @@ -1292,8 +1292,7 @@ namespace MWRender for (const auto& name : resourceSystem->getVFS()->getRecursiveDirectoryIterator(animationPath)) { - size_t pos = name.find_last_of('.'); - if (pos != std::string::npos && name.compare(pos, name.size() - pos, ".nif") == 0) + if (Misc::getFileExtension(name) == "nif") loadBonesFromFile(node, name, resourceSystem); } } diff --git a/components/fontloader/fontloader.cpp b/components/fontloader/fontloader.cpp index 9ba62f7694..da43cc38ec 100644 --- a/components/fontloader/fontloader.cpp +++ b/components/fontloader/fontloader.cpp @@ -17,6 +17,7 @@ #include +#include #include #include @@ -193,8 +194,7 @@ namespace Gui { for (const auto& name : mVFS->getRecursiveDirectoryIterator("Fonts/")) { - size_t pos = name.find_last_of('.'); - if (pos != std::string::npos && name.compare(pos, name.size() - pos, ".fnt") == 0) + if (Misc::getFileExtension(name) == "fnt") loadBitmapFont(name, exportToFile); } } diff --git a/components/misc/pathhelpers.hpp b/components/misc/pathhelpers.hpp new file mode 100644 index 0000000000..88913a1f7b --- /dev/null +++ b/components/misc/pathhelpers.hpp @@ -0,0 +1,19 @@ +#ifndef OPENMW_COMPONENTS_MISC_PATHHELPERS_H +#define OPENMW_COMPONENTS_MISC_PATHHELPERS_H + +#include + +namespace Misc +{ + inline std::string_view getFileExtension(std::string_view file) + { + if (auto extPos = file.find_last_of('.'); extPos != std::string::npos) + { + file.remove_prefix(extPos + 1); + return file; + } + return {}; + } +} + +#endif diff --git a/components/resource/bulletshapemanager.cpp b/components/resource/bulletshapemanager.cpp index 98878df152..0d0f81962b 100644 --- a/components/resource/bulletshapemanager.cpp +++ b/components/resource/bulletshapemanager.cpp @@ -8,6 +8,7 @@ #include +#include #include #include @@ -129,12 +130,7 @@ osg::ref_ptr BulletShapeManager::getShape(const std::string & shape = osg::ref_ptr(static_cast(obj.get())); else { - size_t extPos = normalized.find_last_of('.'); - std::string ext; - if (extPos != std::string::npos && extPos+1 < normalized.size()) - ext = normalized.substr(extPos+1); - - if (ext == "nif") + if (Misc::getFileExtension(normalized) == "nif") { NifBullet::BulletNifLoader loader; shape = loader.load(*mNifFileManager->get(normalized)); diff --git a/components/resource/imagemanager.cpp b/components/resource/imagemanager.cpp index ba46b5cce9..a544b7b621 100644 --- a/components/resource/imagemanager.cpp +++ b/components/resource/imagemanager.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include "objectcache.hpp" @@ -102,10 +103,7 @@ namespace Resource return mWarningImage; } - size_t extPos = normalized.find_last_of('.'); - std::string ext; - if (extPos != std::string::npos && extPos+1 < normalized.size()) - ext = normalized.substr(extPos+1); + const std::string ext(Misc::getFileExtension(normalized)); osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension(ext); if (!reader) { diff --git a/components/resource/keyframemanager.cpp b/components/resource/keyframemanager.cpp index 6d431fb3a5..01a8639aa2 100644 --- a/components/resource/keyframemanager.cpp +++ b/components/resource/keyframemanager.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "animation.hpp" @@ -141,8 +142,7 @@ namespace Resource else { osg::ref_ptr loaded (new SceneUtil::KeyframeHolder); - std::string ext = Resource::getFileExtension(normalized); - if (ext == "kf") + if (Misc::getFileExtension(normalized) == "kf") { NifOsg::Loader::loadKf(Nif::NIFFilePtr(new Nif::NIFFile(mVFS->getNormalized(normalized), normalized)), *loaded.get()); } diff --git a/components/resource/scenemanager.cpp b/components/resource/scenemanager.cpp index ec6bea02d7..76e73da384 100644 --- a/components/resource/scenemanager.cpp +++ b/components/resource/scenemanager.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -388,12 +389,12 @@ namespace Resource osg::ref_ptr load (const std::string& normalizedFilename, const VFS::Manager* vfs, Resource::ImageManager* imageManager, Resource::NifFileManager* nifFileManager) { - std::string ext = Resource::getFileExtension(normalizedFilename); + auto ext = Misc::getFileExtension(normalizedFilename); if (ext == "nif") return NifOsg::Loader::load(nifFileManager->get(normalizedFilename), imageManager); else { - osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension(ext); + osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension(std::string(ext)); if (!reader) { std::stringstream errormsg; @@ -816,12 +817,4 @@ namespace Resource shaderVisitor->setTranslucentFramebuffer(translucentFramebuffer); return shaderVisitor; } - - std::string getFileExtension(const std::string& file) - { - size_t extPos = file.find_last_of('.'); - if (extPos != std::string::npos && extPos+1 < file.size()) - return file.substr(extPos+1); - return std::string(); - } }