From b1ed751b836a1613f532953e7de9c7bff9a4cc86 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Thu, 23 Jul 2020 15:07:24 +0100 Subject: [PATCH] Provide an API for accessing internal errors. --- code/Common/BaseImporter.cpp | 8 +++++++- code/Common/Importer.cpp | 14 ++++++++++++-- code/Common/Importer.h | 8 +++++++- include/assimp/BaseImporter.h | 16 ++++++++++++++-- include/assimp/Exceptional.h | 23 ++++++++++++----------- include/assimp/Importer.hpp | 11 +++++++++++ 6 files changed, 63 insertions(+), 17 deletions(-) diff --git a/code/Common/BaseImporter.cpp b/code/Common/BaseImporter.cpp index bcea076be..73e473527 100644 --- a/code/Common/BaseImporter.cpp +++ b/code/Common/BaseImporter.cpp @@ -130,11 +130,17 @@ aiScene *BaseImporter::ReadFile(Importer *pImp, const std::string &pFile, IOSyst // passes scale into ScaleProcess UpdateImporterScale(pImp); - } catch (const std::exception &err) { + } catch( const DeadlyImportError& err ) { // extract error description m_ErrorText = err.what(); ASSIMP_LOG_ERROR(m_ErrorText); return nullptr; + } catch( const std::exception& err ) { + // extract error description + m_ErrorText = "Internal error"; + ASSIMP_LOG_ERROR(err.what()); + m_internalException = std::current_exception(); + return nullptr; } // return what we gathered from the import. diff --git a/code/Common/Importer.cpp b/code/Common/Importer.cpp index fc50336b4..de72d3bc8 100644 --- a/code/Common/Importer.cpp +++ b/code/Common/Importer.cpp @@ -387,6 +387,7 @@ void Importer::FreeScene( ) { pimpl->mScene = nullptr; pimpl->mErrorString = ""; + pimpl->mInternalException = std::exception_ptr(); ASSIMP_END_EXCEPTION_REGION(void); } @@ -399,6 +400,13 @@ const char* Importer::GetErrorString() const { return pimpl->mErrorString.c_str(); } +const std::exception_ptr& Importer::GetInternalException() const { + ai_assert(nullptr != pimpl); + + // Must remain valid as long as ReadFile() or FreeFile() are not called + return pimpl->mInternalException; +} + // ------------------------------------------------------------------------------------------------ // Enable extra-verbose mode void Importer::SetExtraVerbose(bool bDo) { @@ -426,6 +434,7 @@ aiScene* Importer::GetOrphanedScene() { pimpl->mScene = nullptr; pimpl->mErrorString = ""; // reset error string + pimpl->mInternalException = std::exception_ptr(); ASSIMP_END_EXCEPTION_REGION(aiScene*); return s; @@ -502,7 +511,7 @@ const aiScene* Importer::ReadFileFromMemory( const void* pBuffer, ReadFile(fbuff,pFlags); SetIOHandler(io); - ASSIMP_END_EXCEPTION_REGION_WITH_ERROR_STRING(const aiScene*, pimpl->mErrorString); + ASSIMP_END_EXCEPTION_REGION_WITH_ERROR_STRING(const aiScene*, pimpl->mErrorString, pimpl->mInternalException); return pimpl->mScene; } @@ -709,6 +718,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) { // if failed, extract the error string else if( !pimpl->mScene) { pimpl->mErrorString = imp->GetErrorText(); + pimpl->mInternalException = imp->GetInternalException(); } // clear any data allocated by post-process steps @@ -733,7 +743,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) { #endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS // either successful or failure - the pointer expresses it anyways - ASSIMP_END_EXCEPTION_REGION_WITH_ERROR_STRING(const aiScene*, pimpl->mErrorString); + ASSIMP_END_EXCEPTION_REGION_WITH_ERROR_STRING(const aiScene*, pimpl->mErrorString, pimpl->mInternalException); return pimpl->mScene; } diff --git a/code/Common/Importer.h b/code/Common/Importer.h index eaf42e9c5..b9c223429 100644 --- a/code/Common/Importer.h +++ b/code/Common/Importer.h @@ -97,9 +97,14 @@ public: /** The imported data, if ReadFile() was successful, nullptr otherwise. */ aiScene* mScene; - /** The error description, if there was one. */ + /** The error description, if there was one. In the case of a + * failure not caused by a DeadlyImportError, mInternalException will + * carry the exception and this will be just "Internal error". */ std::string mErrorString; + /** Any exception which wasn't a DeadlyImportError */ + std::exception_ptr mInternalException; + /** List of integer properties */ IntPropertyMap mIntProperties; @@ -133,6 +138,7 @@ ImporterPimpl::ImporterPimpl() AI_NO_EXCEPT , mPostProcessingSteps() , mScene( nullptr ) , mErrorString() +, mInternalException() , mIntProperties() , mFloatProperties() , mStringProperties() diff --git a/include/assimp/BaseImporter.h b/include/assimp/BaseImporter.h index 06c337853..946a9da7c 100644 --- a/include/assimp/BaseImporter.h +++ b/include/assimp/BaseImporter.h @@ -150,6 +150,15 @@ public: return m_ErrorText; } + // ------------------------------------------------------------------- + /** Returns the exception of the last non-DeadlyImportError that occurred. + * @return A description of the last error that occurred. An empty + * string if there was no error. + */ + const std::exception_ptr& GetInternalException() const { + return m_internalException; + } + // ------------------------------------------------------------------- /** Called prior to ReadFile(). * The function is a request to the importer to update its configuration @@ -410,9 +419,12 @@ private: /* Pushes state into importer for the importer scale */ virtual void UpdateImporterScale(Importer *pImp); - protected: - /// Error description in case there was one. +protected: + /// Error description when a DeadlyImportError occurred during import. + /// In case of other errors, this will just be "Internal error" std::string m_ErrorText; + /// Any exception which wasn't due to the asset being incorrect. + std::exception_ptr m_internalException; /// Currently set progress handler. ProgressHandler *m_progress; }; diff --git a/include/assimp/Exceptional.h b/include/assimp/Exceptional.h index c10b2f982..bcd5fb7af 100644 --- a/include/assimp/Exceptional.h +++ b/include/assimp/Exceptional.h @@ -123,17 +123,18 @@ struct ExceptionSwallower { { \ try { -#define ASSIMP_END_EXCEPTION_REGION_WITH_ERROR_STRING(type, ASSIMP_END_EXCEPTION_REGION_errorString) \ - } \ - catch (const DeadlyImportError &e) { \ - ASSIMP_END_EXCEPTION_REGION_errorString = e.what(); \ - return ExceptionSwallower()(); \ - } \ - catch (...) { \ - ASSIMP_END_EXCEPTION_REGION_errorString = "Unknown exception"; \ - return ExceptionSwallower()(); \ - } \ - } +#define ASSIMP_END_EXCEPTION_REGION_WITH_ERROR_STRING(type, ASSIMP_END_EXCEPTION_REGION_errorString, ASSIMP_END_EXCEPTION_REGION_internalError) \ + } \ + catch (const DeadlyImportError &e) { \ + ASSIMP_END_EXCEPTION_REGION_errorString = e.what(); \ + return ExceptionSwallower()(); \ + } \ + catch (...) { \ + ASSIMP_END_EXCEPTION_REGION_errorString = "Internal error"; \ + ASSIMP_END_EXCEPTION_REGION_internalError = std::current_exception(); \ + return ExceptionSwallower()(); \ + } \ +} #define ASSIMP_END_EXCEPTION_REGION(type) \ } \ diff --git a/include/assimp/Importer.hpp b/include/assimp/Importer.hpp index 80eae78b3..9d1594982 100644 --- a/include/assimp/Importer.hpp +++ b/include/assimp/Importer.hpp @@ -495,6 +495,17 @@ public: * following methods is called: #ReadFile(), #FreeScene(). */ const char *GetErrorString() const; + // ------------------------------------------------------------------- + /** Returns Returns an internal exception if one occurred during import. + * + * Returns the last non-DeadlyImportError exception which occurred. + * @return The last exception which occurred which wasn't a + * DeadlyImportError. + * + * @note The returned value remains valid until one of the + * following methods is called: #ReadFile(), #FreeScene(). */ + const std::exception_ptr& GetInternalException() const; + // ------------------------------------------------------------------- /** Returns the scene loaded by the last successful call to ReadFile() *