diff --git a/code/AssetLib/3DS/3DSLoader.cpp b/code/AssetLib/3DS/3DSLoader.cpp index 47ff361b3..0ec8b872a 100644 --- a/code/AssetLib/3DS/3DSLoader.cpp +++ b/code/AssetLib/3DS/3DSLoader.cpp @@ -111,20 +111,9 @@ Discreet3DSImporter::~Discreet3DSImporter() { // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool Discreet3DSImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { - std::string extension = GetExtension(pFile); - if (extension == "3ds" || extension == "prj") { - return true; - } - - if (!extension.length() || checkSig) { - uint16_t token[3]; - token[0] = 0x4d4d; - token[1] = 0x3dc2; - //token[2] = 0x3daa; - return CheckMagicToken(pIOHandler, pFile, token, 2, 0, 2); - } - return false; +bool Discreet3DSImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { + static const uint16_t token[] = { 0x4d4d, 0x3dc2 /*, 0x3daa */ }; + return CheckMagicToken(pIOHandler, pFile, token, AI_COUNT_OF(token), 0, sizeof token[0]); } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/3MF/D3MFImporter.cpp b/code/AssetLib/3MF/D3MFImporter.cpp index fc02df7bd..5b0f34c3a 100644 --- a/code/AssetLib/3MF/D3MFImporter.cpp +++ b/code/AssetLib/3MF/D3MFImporter.cpp @@ -90,24 +90,12 @@ D3MFImporter::~D3MFImporter() { // empty } -bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bool checkSig) const { - const std::string extension(GetExtension(filename)); - if (extension == desc.mFileExtensions) { - return true; - } - - if (!extension.length() || checkSig) { - if (nullptr == pIOHandler) { - return false; - } - if (!ZipArchiveIOSystem::isZipArchive(pIOHandler, filename)) { - return false; - } - D3MFOpcPackage opcPackage(pIOHandler, filename); - return opcPackage.validate(); +bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bool /*checkSig*/) const { + if (!ZipArchiveIOSystem::isZipArchive(pIOHandler, filename)) { + return false; } - - return false; + D3MF::D3MFOpcPackage opcPackage(pIOHandler, filename); + return opcPackage.validate(); } void D3MFImporter::SetupProperties(const Importer*) { diff --git a/code/AssetLib/AC/ACLoader.cpp b/code/AssetLib/AC/ACLoader.cpp index fe9f34f4e..e93624b3e 100644 --- a/code/AssetLib/AC/ACLoader.cpp +++ b/code/AssetLib/AC/ACLoader.cpp @@ -152,18 +152,9 @@ AC3DImporter::~AC3DImporter() { // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool AC3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { - std::string extension = GetExtension(pFile); - - // fixme: are acc and ac3d *really* used? Some sources say they are - if (extension == "ac" || extension == "ac3d" || extension == "acc") { - return true; - } - if (!extension.length() || checkSig) { - uint32_t token = AI_MAKE_MAGIC("AC3D"); - return CheckMagicToken(pIOHandler, pFile, &token, 1, 0); - } - return false; +bool AC3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { + static const uint32_t tokens[] = { AI_MAKE_MAGIC("AC3D") }; + return CheckMagicToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens)); } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/AMF/AMFImporter.cpp b/code/AssetLib/AMF/AMFImporter.cpp index b44391e1f..4103dcdf4 100644 --- a/code/AssetLib/AMF/AMFImporter.cpp +++ b/code/AssetLib/AMF/AMFImporter.cpp @@ -503,19 +503,9 @@ void AMFImporter::ParseNode_Metadata(XmlNode &node) { mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph. } -bool AMFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const { - const std::string extension = GetExtension(pFile); - - if (extension == "amf") { - return true; - } - - if (extension.empty() || pCheckSig) { - static const char * const tokens[] = { " pStream(pIOHandler->Open(pFile, "rb")); - unsigned char data[4]; - if (!pStream || 4 != pStream->Read(data, 1, 4)) { - return false; - } - return !memcmp(data, "3DMO", 4) /* bin */ - || !memcmp(data, "3dmo", 4) /* ASCII */ - ; +bool M3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { + /* + * don't use CheckMagicToken because that checks with swapped bytes too, leading to false + * positives. This magic is not uint32_t, but char[4], so memcmp is the best way + */ + std::unique_ptr pStream(pIOHandler->Open(pFile, "rb")); + unsigned char data[4]; + if (4 != pStream->Read(data, 1, 4)) { + return false; } - return false; + return !memcmp(data, "3DMO", 4) /* bin */ +#ifdef M3D_ASCII + || !memcmp(data, "3dmo", 4) /* ASCII */ +#endif + ; } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/MD2/MD2Loader.cpp b/code/AssetLib/MD2/MD2Loader.cpp index 7be31bce3..99ab3f521 100644 --- a/code/AssetLib/MD2/MD2Loader.cpp +++ b/code/AssetLib/MD2/MD2Loader.cpp @@ -107,19 +107,10 @@ MD2Importer::~MD2Importer() // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool MD2Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const +bool MD2Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const { - const std::string extension = GetExtension(pFile); - if (extension == "md2") - return true; - - // if check for extension is not enough, check for the magic tokens - if (!extension.length() || checkSig) { - uint32_t tokens[1]; - tokens[0] = AI_MD2_MAGIC_NUMBER_LE; - return CheckMagicToken(pIOHandler,pFile,tokens,1); - } - return false; + static const uint32_t tokens[] = { AI_MD2_MAGIC_NUMBER_LE }; + return CheckMagicToken(pIOHandler,pFile,tokens,AI_COUNT_OF(tokens)); } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/MD3/MD3Loader.cpp b/code/AssetLib/MD3/MD3Loader.cpp index 898b82626..6120bd8cb 100644 --- a/code/AssetLib/MD3/MD3Loader.cpp +++ b/code/AssetLib/MD3/MD3Loader.cpp @@ -349,18 +349,9 @@ MD3Importer::~MD3Importer() {} // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool MD3Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { - const std::string extension = GetExtension(pFile); - if (extension == "md3") - return true; - - // if check for extension is not enough, check for the magic tokens - if (!extension.length() || checkSig) { - uint32_t tokens[1]; - tokens[0] = AI_MD3_MAGIC_NUMBER_LE; - return CheckMagicToken(pIOHandler, pFile, tokens, 1); - } - return false; +bool MD3Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { + static const uint32_t tokens[] = { AI_MD3_MAGIC_NUMBER_LE }; + return CheckMagicToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens)); } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/MD5/MD5Loader.cpp b/code/AssetLib/MD5/MD5Loader.cpp index e289620cd..2d5da4d92 100644 --- a/code/AssetLib/MD5/MD5Loader.cpp +++ b/code/AssetLib/MD5/MD5Loader.cpp @@ -100,20 +100,9 @@ MD5Importer::~MD5Importer() { // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool MD5Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { - const std::string extension = GetExtension(pFile); - - if (extension == "md5anim" || extension == "md5mesh" || extension == "md5camera") - return true; - else if (!extension.length() || checkSig) { - if (!pIOHandler) { - return true; - } - static const char * const tokens[] = { "MD5Version" }; - return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1); - } - - return false; +bool MD5Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { + static const char *tokens[] = { "MD5Version" }; + return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens)); } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/MDC/MDCLoader.cpp b/code/AssetLib/MDC/MDCLoader.cpp index 659e0cfb7..7810800de 100644 --- a/code/AssetLib/MDC/MDCLoader.cpp +++ b/code/AssetLib/MDC/MDCLoader.cpp @@ -111,19 +111,9 @@ MDCImporter::~MDCImporter() { // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool MDCImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { - const std::string extension = GetExtension(pFile); - if (extension == "mdc") { - return true; - } - - // if check for extension is not enough, check for the magic tokens - if (!extension.length() || checkSig) { - uint32_t tokens[1]; - tokens[0] = AI_MDC_MAGIC_NUMBER_LE; - return CheckMagicToken(pIOHandler, pFile, tokens, 1); - } - return false; +bool MDCImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { + static const uint32_t tokens[] = { AI_MDC_MAGIC_NUMBER_LE }; + return CheckMagicToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens)); } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/MDL/MDLLoader.cpp b/code/AssetLib/MDL/MDLLoader.cpp index a7eb218d3..1e90c8e71 100644 --- a/code/AssetLib/MDL/MDLLoader.cpp +++ b/code/AssetLib/MDL/MDLLoader.cpp @@ -104,23 +104,18 @@ MDLImporter::~MDLImporter() { // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool MDLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { - const std::string extension = GetExtension(pFile); - - // if check for extension is not enough, check for the magic tokens - if (extension == "mdl" || !extension.length() || checkSig) { - uint32_t tokens[8]; - tokens[0] = AI_MDL_MAGIC_NUMBER_LE_HL2a; - tokens[1] = AI_MDL_MAGIC_NUMBER_LE_HL2b; - tokens[2] = AI_MDL_MAGIC_NUMBER_LE_GS7; - tokens[3] = AI_MDL_MAGIC_NUMBER_LE_GS5b; - tokens[4] = AI_MDL_MAGIC_NUMBER_LE_GS5a; - tokens[5] = AI_MDL_MAGIC_NUMBER_LE_GS4; - tokens[6] = AI_MDL_MAGIC_NUMBER_LE_GS3; - tokens[7] = AI_MDL_MAGIC_NUMBER_LE; - return CheckMagicToken(pIOHandler, pFile, tokens, 8, 0); - } - return false; +bool MDLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { + static const uint32_t tokens[] = { + AI_MDL_MAGIC_NUMBER_LE_HL2a, + AI_MDL_MAGIC_NUMBER_LE_HL2b, + AI_MDL_MAGIC_NUMBER_LE_GS7, + AI_MDL_MAGIC_NUMBER_LE_GS5b, + AI_MDL_MAGIC_NUMBER_LE_GS5a, + AI_MDL_MAGIC_NUMBER_LE_GS4, + AI_MDL_MAGIC_NUMBER_LE_GS3, + AI_MDL_MAGIC_NUMBER_LE + }; + return CheckMagicToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens)); } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/MMD/MMDImporter.cpp b/code/AssetLib/MMD/MMDImporter.cpp index b8c04491e..e0e68f7c5 100644 --- a/code/AssetLib/MMD/MMDImporter.cpp +++ b/code/AssetLib/MMD/MMDImporter.cpp @@ -89,14 +89,9 @@ MMDImporter::~MMDImporter() { // ------------------------------------------------------------------------------------------------ // Returns true, if file is an pmx file. bool MMDImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, - bool checkSig) const { - if (!checkSig) { - return SimpleExtensionCheck(pFile, "pmx"); - } else { - // Check file Header - static const char * const pTokens[] = { "PMX " }; - return SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 1); - } + bool /*checkSig*/) const { + static const char *tokens[] = { "PMX " }; + return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens)); } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/MS3D/MS3DLoader.cpp b/code/AssetLib/MS3D/MS3DLoader.cpp index 0c35587f9..fc2ed042b 100644 --- a/code/AssetLib/MS3D/MS3DLoader.cpp +++ b/code/AssetLib/MS3D/MS3DLoader.cpp @@ -88,26 +88,12 @@ MS3DImporter::MS3DImporter() // Destructor, private as well MS3DImporter::~MS3DImporter() {} - // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool MS3DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const +bool MS3DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const { - // first call - simple extension check - const std::string extension = GetExtension(pFile); - if (extension == "ms3d") { - return true; - } - - // second call - check for magic identifiers - else if (!extension.length() || checkSig) { - if (!pIOHandler) { - return true; - } - static const char * const tokens[] = {"MS3D000000"}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); - } - return false; + static const char* tokens[] = { "MS3D000000" }; + return SearchFileHeaderForToken(pIOHandler,pFile,tokens,AI_COUNT_OF(tokens)); } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/NDO/NDOLoader.cpp b/code/AssetLib/NDO/NDOLoader.cpp index 32e8cb5f8..37c543692 100644 --- a/code/AssetLib/NDO/NDOLoader.cpp +++ b/code/AssetLib/NDO/NDOLoader.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2022, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -82,19 +80,10 @@ NDOImporter::~NDOImporter() // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool NDOImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const +bool NDOImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const { - // check file extension - const std::string extension = GetExtension(pFile); - - if( extension == "ndo") - return true; - - if ((checkSig || !extension.length()) && pIOHandler) { - static const char * const tokens[] = {"nendo"}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1,5); - } - return false; + static const char* tokens[] = {"nendo"}; + return SearchFileHeaderForToken(pIOHandler,pFile,tokens,AI_COUNT_OF(tokens),5); } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/NFF/NFFLoader.cpp b/code/AssetLib/NFF/NFFLoader.cpp index 94ad65cb6..a7e8bd616 100644 --- a/code/AssetLib/NFF/NFFLoader.cpp +++ b/code/AssetLib/NFF/NFFLoader.cpp @@ -83,8 +83,8 @@ NFFImporter::~NFFImporter() {} // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool NFFImporter::CanRead(const std::string &pFile, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const { - return SimpleExtensionCheck(pFile, "nff", "enff"); +bool NFFImporter::CanRead(const std::string & /*pFile*/, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const { + return false; } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/OFF/OFFLoader.cpp b/code/AssetLib/OFF/OFFLoader.cpp index 41ee74da5..640e79249 100644 --- a/code/AssetLib/OFF/OFFLoader.cpp +++ b/code/AssetLib/OFF/OFFLoader.cpp @@ -83,19 +83,10 @@ OFFImporter::~OFFImporter() // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool OFFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const +bool OFFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const { - const std::string extension = GetExtension(pFile); - - if (extension == "off") - return true; - else if (!extension.length() || checkSig) - { - if (!pIOHandler)return true; - static const char * const tokens[] = {"off"}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1,3); - } - return false; + static const char* tokens[] = { "off" }; + return SearchFileHeaderForToken(pIOHandler,pFile,tokens,AI_COUNT_OF(tokens),3); } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/Obj/ObjFileImporter.cpp b/code/AssetLib/Obj/ObjFileImporter.cpp index 3e56e3137..fd062552f 100644 --- a/code/AssetLib/Obj/ObjFileImporter.cpp +++ b/code/AssetLib/Obj/ObjFileImporter.cpp @@ -87,16 +87,10 @@ ObjFileImporter::~ObjFileImporter() { } // ------------------------------------------------------------------------------------------------ -// Returns true, if file is an obj file. -bool ObjFileImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { - if (!checkSig) { - //Check File Extension - return SimpleExtensionCheck(pFile, "obj"); - } else { - // Check file Header - static const char *pTokens[] = { "mtllib", "usemtl", "v ", "vt ", "vn ", "o ", "g ", "s ", "f " }; - return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 9, 200, false, true); - } +// Returns true if file is an obj file. +bool ObjFileImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { + static const char *tokens[] = { "mtllib", "usemtl", "v ", "vt ", "vn ", "o ", "g ", "s ", "f " }; + return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens), 200, false, true); } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/Ogre/OgreImporter.cpp b/code/AssetLib/Ogre/OgreImporter.cpp index ceb80e91c..a3db01902 100644 --- a/code/AssetLib/Ogre/OgreImporter.cpp +++ b/code/AssetLib/Ogre/OgreImporter.cpp @@ -73,14 +73,13 @@ void OgreImporter::SetupProperties(const Importer *pImp) { m_detectTextureTypeFromFilename = pImp->GetPropertyBool(AI_CONFIG_IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME, false); } -bool OgreImporter::CanRead(const std::string &pFile, Assimp::IOSystem *pIOHandler, bool checkSig) const { - if (!checkSig) { - return EndsWith(pFile, ".mesh.xml", false) || EndsWith(pFile, ".mesh", false); - } - +bool OgreImporter::CanRead(const std::string &pFile, Assimp::IOSystem *pIOHandler, bool /*checkSig*/) const { if (EndsWith(pFile, ".mesh.xml", false)) { - static const char * const tokens[] = { "" }; - return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1); + static const char *tokens[] = { "" }; + return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens)); + } else { + /// @todo Read and validate first header chunk? + return false; } /// @todo Read and validate first header chunk? diff --git a/code/AssetLib/OpenGEX/OpenGEXImporter.cpp b/code/AssetLib/OpenGEX/OpenGEXImporter.cpp index 92cfe65b2..c8e47933d 100644 --- a/code/AssetLib/OpenGEX/OpenGEXImporter.cpp +++ b/code/AssetLib/OpenGEX/OpenGEXImporter.cpp @@ -290,16 +290,9 @@ OpenGEXImporter::~OpenGEXImporter() { } //------------------------------------------------------------------------------------------------ -bool OpenGEXImporter::CanRead(const std::string &file, IOSystem *pIOHandler, bool checkSig) const { - bool canRead(false); - if (!checkSig) { - canRead = SimpleExtensionCheck(file, "ogex"); - } else { - static const char * const token[] = { "Metric", "GeometryNode", "VertexArray (attrib", "IndexArray" }; - canRead = SearchFileHeaderForToken(pIOHandler, file, token, 4); - } - - return canRead; +bool OpenGEXImporter::CanRead(const std::string &file, IOSystem *pIOHandler, bool /*checkSig*/) const { + static const char *tokens[] = { "Metric", "GeometryNode", "VertexArray (attrib", "IndexArray" }; + return SearchFileHeaderForToken(pIOHandler, file, tokens, AI_COUNT_OF(tokens)); } //------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/Ply/PlyLoader.cpp b/code/AssetLib/Ply/PlyLoader.cpp index 4d422cea4..6cf1a1c74 100644 --- a/code/AssetLib/Ply/PlyLoader.cpp +++ b/code/AssetLib/Ply/PlyLoader.cpp @@ -100,24 +100,9 @@ PLYImporter::~PLYImporter() { // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool PLYImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { - const std::string extension = GetExtension(pFile); - - if (extension == "ply") { - return true; - } - - if (!extension.length() || checkSig) { - if (!pIOHandler) { - return true; - } - static const char * const tokens[] = { - "ply" - }; - return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1); - } - - return false; +bool PLYImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { + static const char *tokens[] = { "ply" }; + return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens)); } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp b/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp index 111da625b..f98d1264a 100644 --- a/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp +++ b/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp @@ -156,12 +156,8 @@ Q3BSPFileImporter::~Q3BSPFileImporter() { } // ------------------------------------------------------------------------------------------------ -// Returns true, if the loader can read this. -bool Q3BSPFileImporter::CanRead(const std::string &rFile, IOSystem * /*pIOHandler*/, bool checkSig) const { - if (!checkSig) { - return SimpleExtensionCheck(rFile, "pk3", "bsp"); - } - +// Returns true if the loader can read this. +bool Q3BSPFileImporter::CanRead(const std::string &/*rFile*/, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const { return false; } diff --git a/code/AssetLib/Q3D/Q3DLoader.cpp b/code/AssetLib/Q3D/Q3DLoader.cpp index c637ab4cb..c773bbfcd 100644 --- a/code/AssetLib/Q3D/Q3DLoader.cpp +++ b/code/AssetLib/Q3D/Q3DLoader.cpp @@ -84,18 +84,9 @@ Q3DImporter::~Q3DImporter() { // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool Q3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { - const std::string extension = GetExtension(pFile); - - if (extension == "q3s" || extension == "q3o") - return true; - else if (!extension.length() || checkSig) { - if (!pIOHandler) - return true; - static const char * const tokens[] = { "quick3Do", "quick3Ds" }; - return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 2); - } - return false; +bool Q3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { + static const char *tokens[] = { "quick3Do", "quick3Ds" }; + return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens)); } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/Raw/RawLoader.cpp b/code/AssetLib/Raw/RawLoader.cpp index d472430f1..26b6896b1 100644 --- a/code/AssetLib/Raw/RawLoader.cpp +++ b/code/AssetLib/Raw/RawLoader.cpp @@ -84,8 +84,8 @@ RAWImporter::~RAWImporter() { // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool RAWImporter::CanRead(const std::string &pFile, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const { - return SimpleExtensionCheck(pFile, "raw"); +bool RAWImporter::CanRead(const std::string & /*pFile*/, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const { + return false; } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/SIB/SIBImporter.cpp b/code/AssetLib/SIB/SIBImporter.cpp index 2efb7f399..904e2896a 100644 --- a/code/AssetLib/SIB/SIBImporter.cpp +++ b/code/AssetLib/SIB/SIBImporter.cpp @@ -217,8 +217,8 @@ SIBImporter::~SIBImporter() { // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool SIBImporter::CanRead(const std::string &pFile, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const { - return SimpleExtensionCheck(pFile, "sib"); +bool SIBImporter::CanRead(const std::string & /*pFile*/, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const { + return false; } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/SMD/SMDLoader.cpp b/code/AssetLib/SMD/SMDLoader.cpp index f1e4db660..af5b49524 100644 --- a/code/AssetLib/SMD/SMDLoader.cpp +++ b/code/AssetLib/SMD/SMDLoader.cpp @@ -101,9 +101,9 @@ SMDImporter::~SMDImporter() { // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool SMDImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool) const { +bool SMDImporter::CanRead( const std::string& /*pFile*/, IOSystem* /*pIOHandler*/, bool) const { // fixme: auto format detection - return SimpleExtensionCheck(pFile,"smd","vta"); + return false; } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/STL/STLLoader.cpp b/code/AssetLib/STL/STLLoader.cpp index 67869c683..8de57f1ee 100644 --- a/code/AssetLib/STL/STLLoader.cpp +++ b/code/AssetLib/STL/STLLoader.cpp @@ -140,22 +140,9 @@ STLImporter::~STLImporter() { // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool STLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { - const std::string extension = GetExtension(pFile); - - if (extension == "stl") { - return true; - } - - if (!extension.length() || checkSig) { - if (!pIOHandler) { - return true; - } - static const char * const tokens[] = { "STL", "solid" }; - return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 2); - } - - return false; +bool STLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { + static const char *tokens[] = { "STL", "solid" }; + return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens)); } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/Terragen/TerragenLoader.cpp b/code/AssetLib/Terragen/TerragenLoader.cpp index 0556702ff..c9c91db8f 100644 --- a/code/AssetLib/Terragen/TerragenLoader.cpp +++ b/code/AssetLib/Terragen/TerragenLoader.cpp @@ -81,27 +81,9 @@ TerragenImporter::~TerragenImporter() { // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool TerragenImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { - // check file extension - std::string extension = GetExtension(pFile); - - if (extension == "ter") - return true; - - if (!extension.length() || checkSig) { - /* If CanRead() is called in order to check whether we - * support a specific file extension in general pIOHandler - * might be nullptr and it's our duty to return true here. - */ - if (!pIOHandler) { - return true; - } - - static const char * const tokens[] = { "terragen" }; - return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1); - } - - return false; +bool TerragenImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { + static const char *tokens[] = { "terragen" }; + return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens)); } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/Unreal/UnrealLoader.cpp b/code/AssetLib/Unreal/UnrealLoader.cpp index b0b326b54..a1e96a058 100644 --- a/code/AssetLib/Unreal/UnrealLoader.cpp +++ b/code/AssetLib/Unreal/UnrealLoader.cpp @@ -176,8 +176,8 @@ UnrealImporter::~UnrealImporter() {} // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool UnrealImporter::CanRead(const std::string &pFile, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const { - return SimpleExtensionCheck(pFile, "3d", "uc"); +bool UnrealImporter::CanRead(const std::string & /*pFile*/, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const { + return false; } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/X/XFileImporter.cpp b/code/AssetLib/X/XFileImporter.cpp index 2c0e05ece..d23eb576c 100644 --- a/code/AssetLib/X/XFileImporter.cpp +++ b/code/AssetLib/X/XFileImporter.cpp @@ -88,17 +88,9 @@ XFileImporter::~XFileImporter() { // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool XFileImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const { - std::string extension = GetExtension(pFile); - if(extension == "x") { - return true; - } - if (!extension.length() || checkSig) { - uint32_t token[1]; - token[0] = AI_MAKE_MAGIC("xof "); - return CheckMagicToken(pIOHandler,pFile,token,1,0); - } - return false; +bool XFileImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const { + static const uint32_t token[] = { AI_MAKE_MAGIC("xof ") }; + return CheckMagicToken(pIOHandler,pFile,token,AI_COUNT_OF(token)); } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/XGL/XGLLoader.cpp b/code/AssetLib/XGL/XGLLoader.cpp index 4cec756e3..b003f852a 100644 --- a/code/AssetLib/XGL/XGLLoader.cpp +++ b/code/AssetLib/XGL/XGLLoader.cpp @@ -104,25 +104,9 @@ XGLImporter::~XGLImporter() { // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool XGLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { - /* NOTE: A simple check for the file extension is not enough - * here. XGL and ZGL are ok, but xml is too generic - * and might be collada as well. So open the file and - * look for typical signal tokens. - */ - const std::string extension = GetExtension(pFile); - - if (extension == "xgl" || extension == "zgl") { - return true; - } - - if (extension == "xml" || checkSig) { - ai_assert(pIOHandler != nullptr); - static const char * const tokens[] = { "", "", "" }; - return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 3); - } - - return false; +bool XGLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { + static const char *tokens[] = { "", "", "" }; + return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens)); } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/glTF/glTFImporter.cpp b/code/AssetLib/glTF/glTFImporter.cpp index 72103993d..81db12eba 100644 --- a/code/AssetLib/glTF/glTFImporter.cpp +++ b/code/AssetLib/glTF/glTFImporter.cpp @@ -93,24 +93,14 @@ const aiImporterDesc *glTFImporter::GetInfo() const { } bool glTFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /* checkSig */) const { - const std::string &extension = GetExtension(pFile); - - if (extension != "gltf" && extension != "glb") { + glTF::Asset asset(pIOHandler); + try { + asset.Load(pFile, GetExtension(pFile) == "glb"); + std::string version = asset.asset.version; + return !version.empty() && version[0] == '1'; + } catch (...) { return false; } - - if (pIOHandler) { - glTF::Asset asset(pIOHandler); - try { - asset.Load(pFile, extension == "glb"); - std::string version = asset.asset.version; - return !version.empty() && version[0] == '1'; - } catch (...) { - return false; - } - } - - return false; } inline void SetMaterialColorProperty(std::vector &embeddedTexIdxs, Asset & /*r*/, glTF::TexProperty prop, aiMaterial *mat, diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index bf8690ad2..963752519 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -111,18 +111,15 @@ const aiImporterDesc *glTF2Importer::GetInfo() const { return &desc; } -bool glTF2Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig ) const { - const std::string &extension = GetExtension(pFile); - - if (!checkSig && (extension != "gltf") && (extension != "glb")) - return false; - - if (pIOHandler) { - glTF2::Asset asset(pIOHandler); - return asset.CanRead(pFile, extension == "glb"); - } - - return false; +bool glTF2Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /* checkSig */) const { + try { + glTF2::Asset asset(pIOHandler); + asset.Load(pFile, GetExtension(pFile) == "glb"); + std::string version = asset.asset.version; + return !version.empty() && version[0] == '2'; + } catch(...) { + return false; + } } static aiTextureMapMode ConvertWrappingMode(SamplerWrap gltfWrapMode) { diff --git a/code/Common/BaseImporter.cpp b/code/Common/BaseImporter.cpp index 5e186bb19..e400f5c29 100644 --- a/code/Common/BaseImporter.cpp +++ b/code/Common/BaseImporter.cpp @@ -156,8 +156,8 @@ void BaseImporter::GetExtensionList(std::set &extensions) { // ------------------------------------------------------------------------------------------------ /*static*/ bool BaseImporter::SearchFileHeaderForToken(IOSystem *pIOHandler, const std::string &pFile, - const char * const *tokens, - unsigned int numTokens, + const char **tokens, + std::size_t numTokens, unsigned int searchBytes /* = 200 */, bool tokensSol /* false */, bool noAlphaBeforeTokens /* false */) { @@ -225,32 +225,6 @@ void BaseImporter::GetExtensionList(std::set &extensions) { return false; } -// ------------------------------------------------------------------------------------------------ -// Simple check for file extension -/*static*/ bool BaseImporter::SimpleExtensionCheck(const std::string &pFile, - 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; - - const char *ext_real = &pFile[pos + 1]; - if (!ASSIMP_stricmp(ext_real, ext0)) - 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; -} - // ------------------------------------------------------------------------------------------------ // Get file extension from path std::string BaseImporter::GetExtension(const std::string &file) { @@ -271,7 +245,7 @@ std::string BaseImporter::GetExtension(const std::string &file) { // ------------------------------------------------------------------------------------------------ // Check for magic bytes at the beginning of the file. /* static */ bool BaseImporter::CheckMagicToken(IOSystem *pIOHandler, const std::string &pFile, - const void *_magic, unsigned int num, unsigned int offset, unsigned int size) { + const void *_magic, std::size_t num, unsigned int offset, unsigned int size) { ai_assert(size <= 16); ai_assert(_magic); diff --git a/code/Common/Importer.cpp b/code/Common/Importer.cpp index 1d67c9def..52b6097e7 100644 --- a/code/Common/Importer.cpp +++ b/code/Common/Importer.cpp @@ -617,29 +617,71 @@ 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 possibleImporters; + for (unsigned int a = 0; a < pimpl->mImporter.size(); a++) { + + // Every importer has a list of supported extensions. + std::set 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::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::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) { // not so bad yet ... try format auto detection. - const std::string::size_type s = pFile.find_last_of('.'); - if (s != std::string::npos) { - ASSIMP_LOG_INFO("File extension not known, trying signature-based detection"); - for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) { - if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, true)) { - imp = pimpl->mImporter[a]; - SetPropertyInteger("importerIndex", a); - break; - } + ASSIMP_LOG_INFO("File extension not known, trying signature-based detection"); + for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) { + if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, true)) { + imp = pimpl->mImporter[a]; + SetPropertyInteger("importerIndex", a); + break; } } // Put a proper error message if no suitable importer was found diff --git a/include/assimp/BaseImporter.h b/include/assimp/BaseImporter.h index 9351c69da..e7aafef23 100644 --- a/include/assimp/BaseImporter.h +++ b/include/assimp/BaseImporter.h @@ -95,20 +95,15 @@ public: // ------------------------------------------------------------------- /** Returns whether the class can handle the format of the given file. * - * The implementation should be as quick as possible. A check for - * the file extension is enough. If no suitable loader is found with - * this strategy, CanRead() is called again, the 'checkSig' parameter - * set to true this time. Now the implementation is expected to - * perform a full check of the file structure, possibly searching the - * first bytes of the file for magic identifiers or keywords. + * The implementation is expected to perform a full check of the file + * structure, possibly searching the first bytes of the file for magic + * identifiers or keywords. * * @param pFile Path and file name of the file to be examined. * @param pIOHandler The IO handler to use for accessing any file. - * @param checkSig Set to true if this method is called a second time. - * This time, the implementation may take more time to examine the - * contents of the file to be loaded for magic bytes, keywords, etc - * to be able to load files with unknown/not existent file extensions. - * @return true if the class can read this file, false if not. + * @param checkSig Legacy; do not use. + * @return true if the class can read this file, false if not or if + * unsure. */ virtual bool CanRead( const std::string &pFile, @@ -259,26 +254,12 @@ public: // static utilities static bool SearchFileHeaderForToken( IOSystem *pIOSystem, const std::string &file, - const char * const *tokens, - unsigned int numTokens, + const char **tokens, + std::size_t numTokens, unsigned int searchBytes = 200, bool tokensSol = false, bool noAlphaBeforeTokens = false); - // ------------------------------------------------------------------- - /** @brief Check whether a file has a specific file extension - * @param pFile Input file - * @param ext0 Extension to check for. Lowercase characters only, no dot! - * @param ext1 Optional second extension - * @param ext2 Optional third extension - * @note Case-insensitive - */ - static bool SimpleExtensionCheck( - const std::string &pFile, - const char *ext0, - const char *ext1 = nullptr, - const char *ext2 = nullptr); - // ------------------------------------------------------------------- /** @brief Extract file extension from a string * @param pFile Input file @@ -305,7 +286,7 @@ public: // static utilities IOSystem *pIOHandler, const std::string &pFile, const void *magic, - unsigned int num, + std::size_t num, unsigned int offset = 0, unsigned int size = 4); diff --git a/include/assimp/defs.h b/include/assimp/defs.h index 232125aa9..9c4422584 100644 --- a/include/assimp/defs.h +++ b/include/assimp/defs.h @@ -331,4 +331,6 @@ static const ai_real ai_epsilon = (ai_real)0.00001; #define AI_DEBUG_INVALIDATE_PTR(x) #endif +#define AI_COUNT_OF(X) (sizeof(X) / sizeof((X)[0])) + #endif // !! AI_DEFINES_H_INC