#1311 better error handling during parse for schema and header

This commit is contained in:
Thomas Krijnen
2021-02-15 11:11:14 +01:00
parent 459faec01a
commit bfc695c756
3 changed files with 68 additions and 16 deletions
@@ -54,16 +54,36 @@ from . import guid
from .file import file
from .entity_instance import entity_instance
READ_ERROR = ifcopenshell_wrapper.file_open_status.READ_ERROR
NO_HEADER = ifcopenshell_wrapper.file_open_status.NO_HEADER
UNSUPPORTED_SCHEMA = ifcopenshell_wrapper.file_open_status.UNSUPPORTED_SCHEMA
class Error(Exception):
pass
class SchemaError(Error):
pass
def open(fn):
f = ifcopenshell_wrapper.open(os.path.abspath(fn))
if f.good():
return file(f)
else:
raise IOError("Unable to open file for reading")
exc, msg = {
READ_ERROR: (IOError, "Unable to open file for reading"),
NO_HEADER: (Error, "Unable to parse IFC SPF header"),
UNSUPPORTED_SCHEMA: (
SchemaError,
"Unsupported schema: %s" % ",".join(f.header.file_schema.schema_identifiers),
),
}[f.good().value()]
raise exc(msg)
def create_entity(type, schema='IFC4', *args, **kwargs):
def create_entity(type, schema="IFC4", *args, **kwargs):
e = entity_instance((schema, type))
attrs = list(enumerate(args)) + [(e.wrapped_data.get_argument_index(name), arg) for name, arg in kwargs.items()]
for idx, arg in attrs:
+33 -2
View File
@@ -33,6 +33,36 @@
namespace IfcParse {
class IFC_PARSE_API file_open_status {
public:
enum file_open_enum {
SUCCESS,
READ_ERROR,
NO_HEADER,
UNSUPPORTED_SCHEMA
};
private:
file_open_enum error_;
public:
file_open_status(file_open_enum error)
: error_(error)
{}
operator file_open_enum() const {
return error_;
}
file_open_enum value() const {
return error_;
}
operator bool() const {
return error_ == SUCCESS;
}
};
/// This class provides several static convenience functions and variables
/// and provide access to the entities in an IFC file
class IFC_PARSE_API IfcFile {
@@ -78,7 +108,8 @@ public:
private:
typedef std::map<IfcUtil::IfcBaseClass*, IfcUtil::IfcBaseClass*> entity_entity_map_t;
bool parsing_complete_, good_;
bool parsing_complete_;
file_open_status good_ = file_open_status::SUCCESS;
const IfcParse::schema_definition* schema_;
const IfcParse::declaration* ifcroot_type_;
@@ -116,7 +147,7 @@ public:
virtual ~IfcFile();
bool good() const { return good_; }
file_open_status good() const { return good_; }
/// Returns the first entity in the file, this probably is the entity
/// with the lowest id (EXPRESS ENTITY_INSTANCE_NAME)
+13 -12
View File
@@ -1326,7 +1326,6 @@ IfcFile::IfcFile(IfcParse::IfcSpfStream* s) {
IfcFile::IfcFile(const IfcParse::schema_definition* schema)
: parsing_complete_(true)
, good_(true)
, schema_(schema)
, ifcroot_type_(schema_->declaration_by_name("IfcRoot"))
, MaxId(0)
@@ -1341,8 +1340,6 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) {
// number parsing. See comment above on line 41.
init_locale();
good_ = false;
parsing_complete_ = false;
MaxId = 0;
tokens = 0;
@@ -1353,24 +1350,30 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) {
stream = s;
if (!stream->valid) {
good_ = file_open_status::READ_ERROR;
return;
}
tokens = new IfcSpfLexer(stream, this);
_header.file(this);
_header.tryRead();
std::vector<std::string> schemas;
try {
schemas = _header.file_schema().schema_identifiers();
} catch (...) {
// Purposely empty catch block
_header.file(this);
if (_header.tryRead()) {
try {
schemas = _header.file_schema().schema_identifiers();
} catch (...) {
// Purposely empty catch block
}
} else {
good_ = file_open_status::NO_HEADER;
}
if (schemas.size() == 1) {
try {
schema_ = IfcParse::schema_by_name(schemas.front());
} catch (const IfcParse::IfcException& e) {
good_ = file_open_status::UNSUPPORTED_SCHEMA;
Logger::Error(e);
}
}
@@ -1381,8 +1384,6 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) {
return;
}
good_ = true;
ifcroot_type_ = schema_->declaration_by_name("IfcRoot");
boost::circular_buffer<Token> token_stream(3, Token());