Unify extension check for importers.

This enables proper checking for all kinds of extensions (including the
ones with multiple dots) for all importers and internal usage.
pull/5157/head
Marco Feuerstein 2023-07-04 09:25:45 +02:00
parent e08cb0b5b8
commit 506baa21e6
3 changed files with 34 additions and 35 deletions

View File

@ -229,27 +229,30 @@ void BaseImporter::GetExtensionList(std::set<std::string> &extensions) {
const char *ext0,
const char *ext1,
const char *ext2) {
std::string::size_type pos = pFile.find_last_of('.');
// no file extension - can't read
if (pos == std::string::npos) {
return false;
std::set<std::string> extensions;
for (const char* ext : {ext0, ext1, ext2}) {
if (ext == nullptr) continue;
extensions.emplace(ext);
}
return HasExtension(pFile, extensions);
}
const char *ext_real = &pFile[pos + 1];
if (!ASSIMP_stricmp(ext_real, ext0)) {
return true;
// ------------------------------------------------------------------------------------------------
// Check for file extension
/*static*/ bool BaseImporter::HasExtension(const std::string &pFile, const std::set<std::string> &extensions) {
// CAUTION: Do not just search for the extension!
// GetExtension() returns the part after the *last* dot, but some extensions
// have dots inside them, e.g. ogre.mesh.xml. Compare the entire end of the
// string.
for (std::set<std::string>::const_iterator it = extensions.cbegin(); it != extensions.cend(); ++it) {
// Yay for C++<20 not having std::string::ends_with()
const std::string extension = "." + *it;
if (extension.length() > pFile.length()) continue;
// Possible optimization: Fetch the lowercase filename!
if (0 == ASSIMP_stricmp(pFile.c_str() + pFile.length() - extension.length(), extension.c_str())) {
return true;
}
}
// check for other, optional, file extensions
if (ext1 && !ASSIMP_stricmp(ext_real, ext1)) {
return true;
}
if (ext2 && !ASSIMP_stricmp(ext_real, ext2)) {
return true;
}
return false;
}

View File

@ -637,24 +637,10 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) {
std::set<std::string> extensions;
pimpl->mImporter[a]->GetExtensionList(extensions);
// CAUTION: Do not just search for the extension!
// GetExtension() returns the part after the *last* dot, but some extensions have dots
// inside them, e.g. ogre.mesh.xml. Compare the entire end of the string.
for (std::set<std::string>::const_iterator it = extensions.cbegin(); it != extensions.cend(); ++it) {
// Yay for C++<20 not having std::string::ends_with()
std::string extension = "." + *it;
if (extension.length() <= pFile.length()) {
// Possible optimization: Fetch the lowercase filename!
if (0 == ASSIMP_stricmp(pFile.c_str() + pFile.length() - extension.length(), extension.c_str())) {
ImporterAndIndex candidate = { pimpl->mImporter[a], a };
possibleImporters.push_back(candidate);
break;
}
}
if (BaseImporter::HasExtension(pFile, extensions)) {
ImporterAndIndex candidate = { pimpl->mImporter[a], a };
possibleImporters.push_back(candidate);
}
}
// If just one importer supports this extension, pick it and close the case.

View File

@ -275,6 +275,16 @@ public: // static utilities
const char *ext1 = nullptr,
const char *ext2 = nullptr);
// -------------------------------------------------------------------
/** @brief Check whether a file has one of the passed file extensions
* @param pFile Input file
* @param extensions Extensions to check for. Lowercase characters only, no dot!
* @note Case-insensitive
*/
static bool HasExtension(
const std::string &pFile,
const std::set<std::string> &extensions);
// -------------------------------------------------------------------
/** @brief Extract file extension from a string
* @param pFile Input file