From be10bc46ca97cfa9ba2786de2584cb47c8ef3d2b Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sun, 12 Jun 2016 11:22:08 +0200 Subject: [PATCH] More elaborate error reporting --- src/ifcgeom/IfcRegisterConvertShape.h | 13 ++++++-- src/ifcgeom/IfcRegisterConvertShapes.h | 10 ++++-- src/ifcparse/IfcException.h | 18 +++++++++++ src/ifcparse/IfcParse.cpp | 42 ++++++++++++++++++++------ 4 files changed, 69 insertions(+), 14 deletions(-) diff --git a/src/ifcgeom/IfcRegisterConvertShape.h b/src/ifcgeom/IfcRegisterConvertShape.h index 192776555d..911132e8bc 100644 --- a/src/ifcgeom/IfcRegisterConvertShape.h +++ b/src/ifcgeom/IfcRegisterConvertShape.h @@ -6,8 +6,17 @@ if ( convert((T*)l,r) ) { \ success = true; \ } \ - } catch(...) { } \ - if ( !success) { \ + } catch (const std::exception& e) { \ + Logger::Message(Logger::LOG_ERROR, std::string(e.what()) + "\nFailed to convert:", l->entity); \ + return false; \ + } catch (const Standard_Failure& f) { \ + if (f.GetMessageString()) \ + Logger::Message(Logger::LOG_ERROR, std::string("Error in: ") + f.GetMessageString() + "\nFailed to convert:", l->entity); \ + else \ + Logger::Message(Logger::LOG_ERROR, "Failed to convert:", l->entity); \ + return false; \ + } \ + if (!success) { \ Logger::Message(Logger::LOG_ERROR,"Failed to convert:",l->entity); \ return false; \ } \ diff --git a/src/ifcgeom/IfcRegisterConvertShapes.h b/src/ifcgeom/IfcRegisterConvertShapes.h index 9da7ff1263..9f61849ba6 100644 --- a/src/ifcgeom/IfcRegisterConvertShapes.h +++ b/src/ifcgeom/IfcRegisterConvertShapes.h @@ -3,8 +3,14 @@ if ( l->is(T::Class()) ) { \ try { \ return convert((T*)l,r); \ - } catch (...) { } \ - Logger::Message(Logger::LOG_ERROR,"Failed to convert:",l->entity); \ + } catch (const std::exception& e) { \ + Logger::Message(Logger::LOG_ERROR, std::string(e.what()) + "\nFailed to convert:", l->entity); \ + } catch (const Standard_Failure& f) { \ + if (f.GetMessageString()) \ + Logger::Message(Logger::LOG_ERROR, std::string("Error in: ") + f.GetMessageString() + "\nFailed to convert:", l->entity); \ + else \ + Logger::Message(Logger::LOG_ERROR, "Failed to convert:", l->entity); \ + } \ return false; \ } #include "IfcRegisterDef.h" diff --git a/src/ifcparse/IfcException.h b/src/ifcparse/IfcException.h index 1f466a8d9e..29e5d97d4c 100644 --- a/src/ifcparse/IfcException.h +++ b/src/ifcparse/IfcException.h @@ -22,6 +22,8 @@ #include "IfcParse_Export.h" +#include + #include #include @@ -51,6 +53,22 @@ namespace IfcParse { : IfcException(e) {} ~IfcAttributeOutOfRangeException () throw () {} }; + + class IfcInvalidTokenException : public IfcException { + public: + IfcInvalidTokenException( + int token_start, + const std::string& token_string, + const std::string& expected_type + ) + : IfcException( + std::string("Token ") + token_string + " at " + + boost::lexical_cast(token_start) + + " invalid " + expected_type + ) + {} + ~IfcInvalidTokenException() throw () {} + }; } #ifdef _MSC_VER diff --git a/src/ifcparse/IfcParse.cpp b/src/ifcparse/IfcParse.cpp index 547c5ae7eb..f720a09986 100644 --- a/src/ifcparse/IfcParse.cpp +++ b/src/ifcparse/IfcParse.cpp @@ -40,6 +40,8 @@ #include "../ifcparse/IfcFile.h" #include "../ifcparse/IfcSIPrefix.h" +#define PERMISSIVE_FLOAT + using namespace IfcParse; // A static locale for the real number parser. strtod() is locale-dependent, causing issues @@ -511,31 +513,47 @@ bool TokenFunc::isBool(const Token& t) { } bool TokenFunc::isFloat(const Token& t) { +#ifdef PERMISSIVE_FLOAT + /// NB: We are being more permissive here then allowed by the standard return t.type == Token_FLOAT || t.type == Token_INT; +#else + return t.type == Token_FLOAT; +#endif } int TokenFunc::asInt(const Token& t) { - if (t.type != Token_INT) - throw IfcException("Token is not an integer"); + if (t.type != Token_INT) { + throw IfcInvalidTokenException(t.startPos, toString(t), "integer"); + } return t.value_int; } int TokenFunc::asIdentifier(const Token& t) { - if (t.type != Token_IDENTIFIER) - throw IfcException("Token is not an identifier"); + if (t.type != Token_IDENTIFIER) { + throw IfcInvalidTokenException(t.startPos, toString(t), "instance name"); + } return t.value_int; } bool TokenFunc::asBool(const Token& t) { - if (t.type != Token_BOOL) - throw IfcException("Token is not a boolean"); + if (t.type != Token_BOOL) { + throw IfcInvalidTokenException(t.startPos, toString(t), "boolean"); + } return t.value_bool; } double TokenFunc::asFloat(const Token& t) { - if (t.type != Token_FLOAT) - throw IfcException("Token is not a float"); - return t.value_double; +#ifdef PERMISSIVE_FLOAT + if (t.type == Token_INT) { + /// NB: We are being more permissive here then allowed by the standard + return t.value_int; + } else // ----> continues beyond preprocessor directive +#endif + if (t.type == Token_FLOAT) { + return t.value_double; + } else { + throw IfcInvalidTokenException(t.startPos, toString(t), "real"); + } } const std::string &TokenFunc::asStringRef(const Token& t) { @@ -550,7 +568,11 @@ const std::string &TokenFunc::asStringRef(const Token& t) { } std::string TokenFunc::asString(const Token& t) { - return asStringRef(t); + if (isString(t) || isEnumeration(t) || isBinary(t)) { + return asStringRef(t); + } else { + throw IfcInvalidTokenException(t.startPos, toString(t), "string"); + } } boost::dynamic_bitset<> TokenFunc::asBinary(const Token& t) {