Simplified importer search and fixed a few bugs

The search for a matching importer had a few issues, see #3791. There were two different mechanisms to determine whether an importer accepts a specific file extension:
1. `aiImporterDesc::mFileExtensions`, which was forwarded to the UI via `BaseImporter::GetExtensionList()`.
2. `BaseImporter::CanRead()` when called with `checkSig == false`, which determines whether to actually use that importer.
Both were redundant and got out of sync repeatedly. I removed 2. completely and replaced it with 1., thereby syncing UI/import and shortening all `BaseImporter::CanRead()` implementations.

Further bugfixes:
- fixed glTF2 importer throwing exceptions when checking whether it can load a file
- removed `BaseImporter::SimpleExtensionCheck()` because it is no longer used and had a bug with case sensitivity

Since the `checkSig` parameter in `BaseImporter::CanRead()` is now useless, it can be removed completely. I’m not sure if this would break ABI compatiblity, so I’ll submit it with a later pull request.
This commit is contained in:
Krishty
2021-04-24 00:17:50 +02:00
parent 9dc66b0003
commit b00de10eb3
51 changed files with 246 additions and 659 deletions

View File

@@ -617,16 +617,61 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) {
profiler->BeginRegion("total");
}
// Find an worker class which can handle the file
BaseImporter* imp = nullptr;
// Find an worker class which can handle the file extension.
// Multiple importers may be able to handle the same extension (.xml!); gather them all.
SetPropertyInteger("importerIndex", -1);
for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) {
struct ImporterAndIndex {
BaseImporter * importer;
unsigned int index;
};
std::vector<ImporterAndIndex> possibleImporters;
for (unsigned int a = 0; a < pimpl->mImporter.size(); a++) {
// Every importer has a list of supported extensions.
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( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, false)) {
imp = pimpl->mImporter[a];
SetPropertyInteger("importerIndex", a);
break;
}
}
// If just one importer supports this extension, pick it and close the case.
BaseImporter* imp = nullptr;
if (1 == possibleImporters.size()) {
imp = possibleImporters[0].importer;
SetPropertyInteger("importerIndex", possibleImporters[0].index);
}
// If multiple importers claim this file extension, ask them to look at the actual file data to decide.
// This can happen e.g. with XML (COLLADA vs. Irrlicht).
else {
for (std::vector<ImporterAndIndex>::const_iterator it = possibleImporters.begin(); it < possibleImporters.end(); ++it) {
BaseImporter & importer = *it->importer;
ASSIMP_LOG_INFO("Found a possible importer: " + std::string(importer.GetInfo()->mName) + "; trying signature-based detection");
if (importer.CanRead( pFile, pimpl->mIOHandler, true)) {
imp = &importer;
SetPropertyInteger("importerIndex", it->index);
break;
}
}
}
if (!imp) {