More logger changes

This commit is contained in:
Thomas Krijnen
2026-06-11 21:04:44 +02:00
parent 0c993d3292
commit 347a3c80bb
28 changed files with 418 additions and 284 deletions
+2 -2
View File
@@ -1279,11 +1279,11 @@ bool init_input_file(const std::string& filename, IfcParse::IfcFile*& ifc_file,
#ifdef WITH_IFCXML
if (boost::ends_with(boost::to_lower_copy(filename), ".ifcxml")) {
ifc_file = IfcParse::parse_ifcxml(filename);
ifc_file = IfcParse::parse_ifcxml(filename, logger);
} else
#endif
{
ifc_file = new IfcParse::IfcFile(IfcParse::uninitialized_tag{});
ifc_file = new IfcParse::IfcFile(IfcParse::uninitialized_tag{}, logger);
requires_init = true;
}
+1 -1
View File
@@ -129,7 +129,7 @@ namespace ifcopenshell {
const IfcGeom::ConversionResults& entity_shapes, const ifcopenshell::geometry::taxonomy::matrix4& entity_trsf, IfcGeom::ConversionResults& cut_shapes) = 0;
virtual bool unify_shapes(const IfcGeom::ConversionResults&, IfcGeom::ConversionResults&) { throw not_implemented_error(); }
virtual AbstractKernel* clone() const = 0;
virtual AbstractKernel* clone(Logger& logger) const = 0;
};
}
}
+40 -17
View File
@@ -167,7 +167,15 @@ bool IfcGeom::Iterator::initialize() {
return *initialization_outcome_;
}
void IfcGeom::Iterator::process_finished_rep(geometry_conversion_result* rep) {
void IfcGeom::Iterator::flush_worker_log(ifcopenshell::geometry::Converter* kernel) {
if (kernel && &kernel->logger() != &logger_) {
logger_.Append(kernel->logger());
}
}
void IfcGeom::Iterator::process_finished_rep(geometry_conversion_result* rep, ifcopenshell::geometry::Converter* kernel) {
flush_worker_log(kernel);
if (rep->elements.empty()) {
return;
}
@@ -193,8 +201,17 @@ void IfcGeom::Iterator::process_concurrently() {
}
kernel_pool.reserve(conc_threads);
worker_loggers_.reserve(conc_threads);
for (unsigned i = 0; i < conc_threads; ++i) {
kernel_pool.push_back(new ifcopenshell::geometry::Converter(std::unique_ptr<ifcopenshell::geometry::kernels::AbstractKernel>(converter_->kernel()->clone()), ifc_file, settings_, logger_));
worker_loggers_.emplace_back(std::make_unique<Logger>());
Logger& worker_logger = *worker_loggers_.back();
worker_logger.Verbosity(logger_.Verbosity());
worker_logger.OutputFormat(logger_.OutputFormat());
worker_logger.PrintPerformanceStatsOnElement(logger_.PrintPerformanceStatsOnElement());
if (worker_logger.OutputFormat() != Logger::FMT_INMEMORY) {
worker_logger.SetOutput(static_cast<std::ostream*>(nullptr), static_cast<std::ostream*>(nullptr));
}
kernel_pool.push_back(new ifcopenshell::geometry::Converter(std::unique_ptr<ifcopenshell::geometry::kernels::AbstractKernel>(converter_->kernel()->clone(worker_logger)), ifc_file, settings_, worker_logger));
}
std::vector<std::future<geometry_conversion_result*>> threadpool;
@@ -211,11 +228,12 @@ void IfcGeom::Iterator::process_concurrently() {
std::future_status status;
status = fu.wait_for(std::chrono::seconds(0));
if (status == std::future_status::ready) {
process_finished_rep(fu.get());
process_finished_rep(fu.get(), kernel_pool[i]);
std::swap(threadpool[i], threadpool.back());
threadpool.pop_back();
std::swap(kernel_pool[i], kernel_pool.back());
std::swap(worker_loggers_[i], worker_loggers_.back());
K = kernel_pool.back();
break;
} // if
@@ -231,14 +249,14 @@ void IfcGeom::Iterator::process_concurrently() {
try {
this->create_element_(kernel, settings, rep);
} catch (const std::exception& e) {
logger_.Error("GEO", 52,
kernel->logger().Error("GEO", 52,
std::string("Exception '") + e.what() +
std::string("' occurred while iterator was creating a shape: "),
rep->item->instance
);
had_error_processing_elements_ = true;
} catch (...) {
logger_.Error("GEO", 53,
kernel->logger().Error("GEO", 53,
"Unknown exception occurred while iteartor was creating a shape: ",
rep->item->instance
);
@@ -257,8 +275,8 @@ void IfcGeom::Iterator::process_concurrently() {
threadpool.emplace_back(std::move(fu));
}
for (auto& fu : threadpool) {
process_finished_rep(fu.get());
for (size_t i = 0; i < threadpool.size(); ++i) {
process_finished_rep(threadpool[i].get(), kernel_pool[i]);
}
finished_ = true;
@@ -344,6 +362,8 @@ const IfcUtil::IfcBaseClass* IfcGeom::Iterator::create_shape_model_for_next_enti
void IfcGeom::Iterator::create_element_(ifcopenshell::geometry::Converter* kernel, ifcopenshell::geometry::Settings settings, geometry_conversion_result* rep)
{
Logger& kernel_logger = kernel->logger();
if (!settings_.get<ifcopenshell::geometry::settings::NoParallelMapping>().get()) {
rep->item = kernel->mapping()->map(rep->representation);
if (!rep->item) {
@@ -360,20 +380,20 @@ void IfcGeom::Iterator::create_element_(ifcopenshell::geometry::Converter* kerne
const IfcUtil::IfcBaseEntity* product = product_node.first;
const auto& place = product_node.second;
logger_.SetProduct(product);
kernel_logger.SetProduct(product);
IfcGeom::BRepElement* brep = static_cast<IfcGeom::BRepElement*>(decorate_with_cache_(GeometrySerializer::READ_BREP, (std::string)product->get("GlobalId"), std::to_string(rep->item->instance->as<IfcUtil::IfcBaseEntity>()->id()), [kernel, settings, product, place, rep]() {
return kernel->create_brep_for_representation_and_product(rep->item, product, place);
}));
if (!brep) {
logger_.SetProduct(boost::none);
kernel_logger.SetProduct(boost::none);
return;
}
auto elem = process_based_on_settings(settings, brep);
auto elem = process_based_on_settings(settings, brep, kernel_logger);
if (!elem) {
logger_.SetProduct(boost::none);
kernel_logger.SetProduct(boost::none);
return;
}
@@ -385,11 +405,13 @@ void IfcGeom::Iterator::create_element_(ifcopenshell::geometry::Converter* kerne
const IfcUtil::IfcBaseEntity* product2 = p.first;
const auto& place2 = p.second;
kernel_logger.SetProduct(product2);
IfcGeom::BRepElement* brep2 = static_cast<IfcGeom::BRepElement*>(decorate_with_cache_(GeometrySerializer::READ_BREP, (std::string)product2->get("GlobalId"), std::to_string(rep->item->instance->as<IfcUtil::IfcBaseEntity>()->id()), [kernel, settings, product2, place2, brep]() {
return kernel->create_brep_for_processed_representation(product2, place2, brep);
}));
if (brep2) {
auto elem2 = process_based_on_settings(settings, brep2, dynamic_cast<IfcGeom::TriangulationElement*>(elem));
auto elem2 = process_based_on_settings(settings, brep2, kernel_logger, dynamic_cast<IfcGeom::TriangulationElement*>(elem));
if (elem2) {
rep->breps.push_back(brep2);
rep->elements.push_back(elem2);
@@ -397,16 +419,16 @@ void IfcGeom::Iterator::create_element_(ifcopenshell::geometry::Converter* kerne
}
}
logger_.SetProduct(boost::none);
kernel_logger.SetProduct(boost::none);
}
IfcGeom::Element* IfcGeom::Iterator::process_based_on_settings(ifcopenshell::geometry::Settings settings, IfcGeom::BRepElement* elem, IfcGeom::TriangulationElement* previous)
IfcGeom::Element* IfcGeom::Iterator::process_based_on_settings(ifcopenshell::geometry::Settings settings, IfcGeom::BRepElement* elem, Logger& logger, IfcGeom::TriangulationElement* previous)
{
if (settings.get<ifcopenshell::geometry::settings::IteratorOutput>().get() == ifcopenshell::geometry::settings::SERIALIZED) {
try {
return new IfcGeom::SerializedElement(*elem);
} catch (...) {
logger_.Message(Logger::LOG_ERROR, "GEO", 54, "Getting a serialized element from model failed.");
logger.Message(Logger::LOG_ERROR, "GEO", 54, "Getting a serialized element from model failed.");
return nullptr;
}
} else if (settings.get<ifcopenshell::geometry::settings::IteratorOutput>().get() == ifcopenshell::geometry::settings::TRIANGULATED) {
@@ -417,7 +439,7 @@ IfcGeom::Element* IfcGeom::Iterator::process_based_on_settings(ifcopenshell::geo
gid2 = gid2.substr(0, hyphen);
}
return decorate_with_cache_(GeometrySerializer::READ_TRIANGULATION, elem->guid(), gid2, [this, elem, previous]() {
return decorate_with_cache_(GeometrySerializer::READ_TRIANGULATION, elem->guid(), gid2, [&logger, elem, previous]() {
try {
if (!previous) {
return new TriangulationElement(*elem);
@@ -425,7 +447,7 @@ IfcGeom::Element* IfcGeom::Iterator::process_based_on_settings(ifcopenshell::geo
return new TriangulationElement(*elem, previous->geometry_pointer());
}
} catch (...) {
logger_.Message(Logger::LOG_ERROR, "GEO", 55, "Getting a triangulation element from model failed.");
logger.Message(Logger::LOG_ERROR, "GEO", 55, "Getting a triangulation element from model failed.");
}
return (TriangulationElement*)nullptr;
});
@@ -824,6 +846,7 @@ IfcGeom::Iterator::~Iterator() {
}
for (auto& k : kernel_pool) {
flush_worker_log(k);
delete k;
}
+6 -1
View File
@@ -79,6 +79,7 @@
#include <thread>
#include <chrono>
#include <atomic>
#include <memory>
namespace IfcGeom {
@@ -133,6 +134,7 @@ namespace IfcGeom {
// When multi-threaded
std::vector<ifcopenshell::geometry::Converter*> kernel_pool;
std::vector<std::unique_ptr<Logger>> worker_loggers_;
// The object is fetched beforehand to be sure that get() returns a valid element
TriangulationElement* current_triangulation;
@@ -200,8 +202,11 @@ namespace IfcGeom {
IfcGeom::Element* process_based_on_settings(
ifcopenshell::geometry::Settings settings,
IfcGeom::BRepElement* elem,
Logger& logger,
IfcGeom::TriangulationElement* previous = nullptr);
void flush_worker_log(ifcopenshell::geometry::Converter* kernel);
bool wait_for_element();
void log_timepoints() const;
@@ -293,7 +298,7 @@ namespace IfcGeom {
size_t processed_ = 0;
void process_finished_rep(geometry_conversion_result* rep);
void process_finished_rep(geometry_conversion_result* rep, ifcopenshell::geometry::Converter* kernel = nullptr);
void process_concurrently();
+3 -3
View File
@@ -156,14 +156,14 @@ namespace ifcopenshell {
}
return false;
}
virtual AbstractKernel* clone() const
virtual AbstractKernel* clone(Logger& logger) const
{
std::vector<std::unique_ptr<AbstractKernel>> ks;
for (auto& k : kernels_) {
ks.emplace_back(k->clone());
ks.emplace_back(k->clone(logger));
}
// @todo ugly
return new HybridKernel(geometry_library(), file_, const_cast<Settings&>(settings()), std::move(ks), logger());
return new HybridKernel(geometry_library(), file_, const_cast<Settings&>(settings()), std::move(ks), logger);
}
};
+33 -33
View File
@@ -1,4 +1,4 @@
/********************************************************************************
/********************************************************************************
* *
* This file is part of IfcOpenShell. *
* *
@@ -162,13 +162,13 @@ CGAL::Nef_polyhedron_3<Kernel_> ifcopenshell::geometry::utils::create_nef_polyhe
bool CgalKernel::convert(const taxonomy::shell::ptr l, cgal_shape_t& shape) {
for (auto& f : l->children) {
if (f->basis && f->basis->kind() != taxonomy::PLANE) {
logger_.Error("UNS", 3, "CGAL Kernel: Non-planar faces not supported at the moment");
logger().Error("UNS", 3, "CGAL Kernel: Non-planar faces not supported at the moment");
throw not_supported_error();
}
for (auto& w : f->children) {
for (auto& e : w->children) {
if (e->basis && e->basis->kind() == taxonomy::BSPLINE_CURVE) {
logger_.Error("UNS", 4, "CGAL Kernel: B-spline edge curves not supported at the moment");
logger().Error("UNS", 4, "CGAL Kernel: B-spline edge curves not supported at the moment");
throw not_supported_error();
}
}
@@ -197,9 +197,9 @@ bool CgalKernel::convert(const taxonomy::shell::ptr l, cgal_shape_t& shape) {
double volume = diag(0) * diag(1) * diag(2);
// @todo volume van be zero also..
double density = num_points / volume;
logger_.Notice("GEO", 77, "Density " + boost::lexical_cast<std::string>(density), l->instance);
logger().Notice("GEO", 77, "Density " + boost::lexical_cast<std::string>(density), l->instance);
if (density > 5000) {
logger_.Notice("GEO", 78, "Substituted element with " + boost::lexical_cast<std::string>(density) + " vertices / m3 with a bounding box");
logger().Notice("GEO", 78, "Substituted element with " + boost::lexical_cast<std::string>(density) + " vertices / m3 with a bounding box");
CGAL::Point_3<Kernel_> lower(minmax.first(0), minmax.first(1), minmax.first(2));
CGAL::Point_3<Kernel_> upper(minmax.second(0), minmax.second(1), minmax.second(2));
shape = utils::create_cube(lower, upper);
@@ -215,7 +215,7 @@ bool CgalKernel::convert(const taxonomy::shell::ptr l, cgal_shape_t& shape) {
} catch (...) {}
if (!success) {
logger_.Message(Logger::LOG_WARNING, "GEO", 79, "Failed to convert face:", f->instance);
logger().Message(Logger::LOG_WARNING, "GEO", 79, "Failed to convert face:", f->instance);
continue;
}
@@ -237,7 +237,7 @@ bool CgalKernel::convert(const taxonomy::face::ptr face, std::list<cgal_face_t>&
}
if (face->children.size() > 1 && num_outer_bounds > 1 && face->children.size() != num_outer_bounds) {
logger_.Message(Logger::LOG_ERROR, "GEO", 80, "Invalid configuration of boundaries for:", face->instance);
logger().Message(Logger::LOG_ERROR, "GEO", 80, "Invalid configuration of boundaries for:", face->instance);
return false;
}
@@ -250,7 +250,7 @@ bool CgalKernel::convert(const taxonomy::face::ptr face, std::list<cgal_face_t>&
cgal_wire_t wire;
if (!convert(bound, wire)) {
logger_.Message(Logger::LOG_ERROR, "GEO", 81, "Failed to process face boundary loop", bound->instance);
logger().Message(Logger::LOG_ERROR, "GEO", 81, "Failed to process face boundary loop", bound->instance);
return false;
}
@@ -704,7 +704,7 @@ bool CgalKernel::convert(const taxonomy::loop::ptr loop, cgal_wire_t& result) {
if (d < 1.e-5) {
points.erase(points.end() - 1);
} else {
logger_.Warning("GEO", 82, "Loop not closed", loop->instance);
logger().Warning("GEO", 82, "Loop not closed", loop->instance);
}
}
@@ -718,7 +718,7 @@ bool CgalKernel::convert(const taxonomy::loop::ptr loop, cgal_wire_t& result) {
// A loop should consist of at least three vertices
std::size_t original_count = polygon.size();
if (original_count < 3) {
logger_.Warning("GEO", 83, "Not enough edges for:", loop->instance);
logger().Warning("GEO", 83, "Not enough edges for:", loop->instance);
return false;
}
@@ -729,14 +729,14 @@ bool CgalKernel::convert(const taxonomy::loop::ptr loop, cgal_wire_t& result) {
std::size_t count = polygon.size();
if (original_count - count != 0) {
std::stringstream ss; ss << (original_count - count) << " edges removed for:";
logger_.Warning("GEO", 84, ss.str(), loop->instance);
logger().Warning("GEO", 84, ss.str(), loop->instance);
}
{
std::set<cgal_point_t> visited_points;
for (auto& p : polygon) {
if (visited_points.find(p) != visited_points.end()) {
logger_.Error("GEO", 85, "Skipping self-intersecting loop", loop->instance);
logger().Error("GEO", 85, "Skipping self-intersecting loop", loop->instance);
// @todo signal somehow that occt kernel might be able to solve this
// @todo implement cycle detection using Arrangement_2, but that only works in exact kernel
return false;
@@ -758,7 +758,7 @@ bool CgalKernel::convert(const taxonomy::loop::ptr loop, cgal_wire_t& result) {
}
if (do_segments_intersect(segments)) {
logger_.Message(Logger::LOG_WARNING, "GEO", 86, "Skipping self-intersecting loop", loop->instance);
logger().Message(Logger::LOG_WARNING, "GEO", 86, "Skipping self-intersecting loop", loop->instance);
return false;
}
@@ -786,7 +786,7 @@ bool CgalKernel::convert(const taxonomy::loop::ptr loop, cgal_wire_t& result) {
*/
if (count < 3) {
logger_.Message(Logger::LOG_ERROR, "GEO", 87, "Not enough edges for:", loop->instance);
logger().Message(Logger::LOG_ERROR, "GEO", 87, "Not enough edges for:", loop->instance);
return false;
}
@@ -820,7 +820,7 @@ bool CgalKernel::convert_impl(const taxonomy::shell::ptr shell, ConversionResult
bool CgalKernel::convert_impl(const taxonomy::solid::ptr solid, ConversionResults& results) {
if (solid->children.size() > 1) {
logger_.Error("UNS", 5, "Multiple shells in solid not supported at the moment");
logger().Error("UNS", 5, "Multiple shells in solid not supported at the moment");
return false;
}
cgal_shape_t shape;
@@ -965,7 +965,7 @@ bool ifcopenshell::geometry::kernels::CgalKernel::convert_openings(const IfcUtil
try {
a.convert_to_polyhedron(a_poly);
} catch (...) {
logger_.Message(Logger::LOG_ERROR, "GEO", 88, "Could not convert from Nef:", entity);
logger().Message(Logger::LOG_ERROR, "GEO", 88, "Could not convert from Nef:", entity);
return false;
}
@@ -1190,7 +1190,7 @@ bool CgalKernel::process_extrusion(const cgal_face_t& bottom_face, taxonomy::dir
bool CgalKernel::convert(const taxonomy::extrusion::ptr extrusion, cgal_shape_t &shape) {
const double& height = extrusion->depth;
if (height < settings_.get<settings::Precision>().get()) {
logger_.Message(Logger::LOG_ERROR, "GEO", 89, "Non-positive extrusion height encountered for:", extrusion->instance);
logger().Message(Logger::LOG_ERROR, "GEO", 89, "Non-positive extrusion height encountered for:", extrusion->instance);
return false;
}
@@ -1326,13 +1326,13 @@ bool CgalKernel::preprocess_boolean_operand(const IfcUtil::IfcBaseClass* log_ref
cgal_shape_t shape = shape_const;
if (!shape.is_valid()) {
logger_.Message(Logger::LOG_ERROR, "GEO", 90, "Conversion to Nef will fail. Invalid geometry:", log_reference);
logger().Message(Logger::LOG_ERROR, "GEO", 90, "Conversion to Nef will fail. Invalid geometry:", log_reference);
return false;
}
if (!shape.is_closed()) {
// TODO: There can be substractions to remove parts of non-volumetric objects. Maybe iterate over all faces of an entity and put them in a Nef_polyhedron_3 through Boolean union? Highly inefficient but maybe desirable...
logger_.Message(Logger::LOG_ERROR, "UNS", 6, "Subtraction of openings not supported for non-closed geometry:", log_reference);
logger().Message(Logger::LOG_ERROR, "UNS", 6, "Subtraction of openings not supported for non-closed geometry:", log_reference);
return false;
}
@@ -1341,18 +1341,18 @@ bool CgalKernel::preprocess_boolean_operand(const IfcUtil::IfcBaseClass* log_ref
try {
success = CGAL::Polygon_mesh_processing::triangulate_faces(shape);
} catch (CGAL::Failure_exception& e) {
logger_.Notice("GEO", 91, e);
logger_.Message(Logger::LOG_ERROR, "GEO", 92, "Triangulation of geometry crashed:", log_reference);
logger().Notice("GEO", 91, e);
logger().Message(Logger::LOG_ERROR, "GEO", 92, "Triangulation of geometry crashed:", log_reference);
return false;
}
if (!success) {
logger_.Message(Logger::LOG_ERROR, "GEO", 93, "Triangulation of geometry failed:", log_reference);
logger().Message(Logger::LOG_ERROR, "GEO", 93, "Triangulation of geometry failed:", log_reference);
return false;
}
if (CGAL::Polygon_mesh_processing::does_self_intersect(shape)) {
logger_.Message(Logger::LOG_ERROR, "GEO", 94, "Conversion to Nef will fail. Self-intersecting geometry:", log_reference);
logger().Message(Logger::LOG_ERROR, "GEO", 94, "Conversion to Nef will fail. Self-intersecting geometry:", log_reference);
return false;
}
@@ -1424,8 +1424,8 @@ bool CgalKernel::preprocess_boolean_operand(const IfcUtil::IfcBaseClass* log_ref
try {
result = CGAL::Nef_polyhedron_3<Kernel_>(shape);
} catch (CGAL::Failure_exception& e) {
logger_.Notice("GEO", 95, e);
logger_.Message(Logger::LOG_ERROR, "GEO", 96, "Could not convert geometry to Nef:", log_reference);
logger().Notice("GEO", 95, e);
logger().Message(Logger::LOG_ERROR, "GEO", 96, "Could not convert geometry to Nef:", log_reference);
return false;
}
@@ -1497,8 +1497,8 @@ bool CgalKernel::preprocess_boolean_operand(const IfcUtil::IfcBaseClass* log_ref
// @todo don't dilate in 3 dimensions but only in the XY plane, orthogonal to wall axis.
result = CGAL::minkowski_sum_3(result, precision_cube_);
} catch (CGAL::Failure_exception& e) {
logger_.Notice("GEO", 97, e);
logger_.Message(Logger::LOG_ERROR, "GEO", 98, "Could not dilate boolean operand", log_reference);
logger().Notice("GEO", 97, e);
logger().Message(Logger::LOG_ERROR, "GEO", 98, "Could not dilate boolean operand", log_reference);
return false;
}
}
@@ -1523,8 +1523,8 @@ bool CgalKernel::preprocess_boolean_operand(const IfcUtil::IfcBaseClass* log_ref
cgal_shape_t convert_back;
result.convert_to_polyhedron(convert_back);
} catch (CGAL::Failure_exception& e) {
logger_.Notice("GEO", 99, e);
logger_.Message(Logger::LOG_WARNING, "GEO", 100, "Final conversion will likely fail. Could not convert geometry from Nef:", log_reference);
logger().Notice("GEO", 99, e);
logger().Message(Logger::LOG_WARNING, "GEO", 100, "Final conversion will likely fail. Could not convert geometry from Nef:", log_reference);
}
return true;
@@ -1846,7 +1846,7 @@ bool CgalKernel::convert_impl(const taxonomy::boolean_result::ptr br, Conversion
// even-odd fill rule will result in incorrect results.
// See for example the Duplex model roof.
logger_.Notice("GEO", 101, "Holes are not disjoint");
logger().Notice("GEO", 101, "Holes are not disjoint");
CGAL::Polygon_set_2<Kernel_> result;
auto it = loops.begin();
@@ -1899,7 +1899,7 @@ bool CgalKernel::convert_impl(const taxonomy::boolean_result::ptr br, Conversion
);
});
logger_.Notice("GEO", 102, "Processed boolean operation as 2d arrangement");
logger().Notice("GEO", 102, "Processed boolean operation as 2d arrangement");
return true;
@@ -1985,7 +1985,7 @@ bool CgalKernel::convert_impl(const taxonomy::boolean_result::ptr br, Conversion
ps.push_back({ p.x(), p.y() });
}
if (!ps.is_simple()) {
logger_.Warning("GEO", 103, "Polygonal boundary not simple", face->children[0]->instance);
logger().Warning("GEO", 103, "Polygonal boundary not simple", face->children[0]->instance);
continue;
}
@@ -2131,7 +2131,7 @@ bool CgalKernel::convert_impl(const taxonomy::boolean_result::ptr br, Conversion
try {
a.convert_to_polyhedron(a_poly);
} catch (...) {
logger_.Message(Logger::LOG_ERROR, "GEO", 104, "Could not convert geometry with openings from Nef:", br->instance);
logger().Message(Logger::LOG_ERROR, "GEO", 104, "Could not convert geometry with openings from Nef:", br->instance);
return false;
}
+2 -2
View File
@@ -97,8 +97,8 @@ namespace ifcopenshell {
: AbstractKernel("cgal", settings, logger)
{}
virtual AbstractKernel* clone() const {
return new CgalKernel(settings(), logger());
virtual AbstractKernel* clone(Logger& logger) const {
return new CgalKernel(settings(), logger);
}
virtual bool supports_boolean_operations() const {
@@ -118,8 +118,8 @@ public:
, precision_(settings.get<ifcopenshell::geometry::settings::Precision>().get())
{}
virtual AbstractKernel* clone() const {
return new OpenCascadeKernel(settings(), logger());
virtual AbstractKernel* clone(Logger& logger) const {
return new OpenCascadeKernel(settings(), logger);
}
virtual bool supports_boolean_operations() const { return true; }
+5 -3
View File
@@ -216,6 +216,7 @@ struct cant_curve_segment_function {
class curve_segment_evaluator {
private:
mapping* mapping_ = nullptr;
Logger& logger_;
const IfcSchema::IfcCurveSegment* inst_ = nullptr; // this curve segment instance
double length_unit_;
double start_;
@@ -234,6 +235,7 @@ class curve_segment_evaluator {
public:
curve_segment_evaluator(mapping* mapping, const IfcSchema::IfcCurveSegment* inst, double length_unit)
: mapping_(mapping),
logger_(mapping->logger()),
inst_(inst),
length_unit_(length_unit),
parent_curve_(inst->ParentCurve()) {
@@ -1136,18 +1138,18 @@ class curve_segment_evaluator {
// A numerical solution is required.
// This functor finds the value of x such that s(x) - u = 0, where u is the input value and s is the
// computed curve length.
x_at_dist_along = [curve_length_fn,mapping=mapping_](double u) -> double {
x_at_dist_along = [curve_length_fn, this](double u) -> double {
std::uintmax_t max_iter = 9000;
auto tol = [](double a, double b) { return fabs(b - a) < 1.0E-11; };
auto x = u; // start by assuming u = x (it's not, but it will be close)
try {
// set up the root finding function that evaluates s(x) - u
auto f = [curve_length_fn, u,mapping=mapping](double x) -> double { return curve_length_fn(x) - u; };
auto f = [curve_length_fn, u](double x) -> double { return curve_length_fn(x) - u; };
// use a root finder to get x
auto result = boost::math::tools::bracket_and_solve_root(f, x, 2.0, true, tol, max_iter);
x = result.first;
} catch (...) {
mapping->logger().Warning("GEO", 253, "root solver failed");
logger_.Warning("GEO", 253, "root solver failed");
}
return x;
};
+45 -45
View File
@@ -119,11 +119,11 @@ std::tuple<typename aggregate_of<Ifc4x3_add2::IfcObjectDefinition>::ptr, typenam
{
auto pt = file.addDoublet<Ifc4x3_add2::IfcCartesianPoint>(xBT, yBT);
auto design_parameters = new Ifc4x3_add2::IfcAlignmentHorizontalSegment(boost::none, boost::none, pt, angleBT, 0.0, 0.0, tangent_run, boost::none, Ifc4x3_add2::IfcAlignmentHorizontalSegmentTypeEnum::IfcAlignmentHorizontalSegmentType_LINE);
auto alignment_segment = new Ifc4x3_add2::IfcAlignmentSegment(IfcParse::IfcGlobalId(), nullptr, boost::none, boost::none, boost::none, nullptr, nullptr, design_parameters);
auto alignment_segment = new Ifc4x3_add2::IfcAlignmentSegment(IfcParse::IfcGlobalId(file.logger()), nullptr, boost::none, boost::none, boost::none, nullptr, nullptr, design_parameters);
horizontal_segments->push(alignment_segment);
if (include_geometry) {
horizontal_curve_segments->push(mapAlignmentHorizontalSegment(design_parameters).first);
horizontal_curve_segments->push(mapAlignmentHorizontalSegment(design_parameters, file.logger()).first);
}
}
@@ -131,11 +131,11 @@ std::tuple<typename aggregate_of<Ifc4x3_add2::IfcObjectDefinition>::ptr, typenam
{
auto pc = file.addDoublet<Ifc4x3_add2::IfcCartesianPoint>(xPC, yPC);
auto design_parameters = new Ifc4x3_add2::IfcAlignmentHorizontalSegment(boost::none, boost::none, pc, angleBT, radius, radius, lc, boost::none, Ifc4x3_add2::IfcAlignmentHorizontalSegmentTypeEnum::IfcAlignmentHorizontalSegmentType_CIRCULARARC);
auto alignment_segment = new Ifc4x3_add2::IfcAlignmentSegment(IfcParse::IfcGlobalId(), nullptr, boost::none, boost::none, boost::none, nullptr, nullptr, design_parameters);
auto alignment_segment = new Ifc4x3_add2::IfcAlignmentSegment(IfcParse::IfcGlobalId(file.logger()), nullptr, boost::none, boost::none, boost::none, nullptr, nullptr, design_parameters);
horizontal_segments->push(alignment_segment);
if (include_geometry) {
horizontal_curve_segments->push(mapAlignmentHorizontalSegment(design_parameters).first);
horizontal_curve_segments->push(mapAlignmentHorizontalSegment(design_parameters, file.logger()).first);
}
}
@@ -152,19 +152,19 @@ std::tuple<typename aggregate_of<Ifc4x3_add2::IfcObjectDefinition>::ptr, typenam
auto tangent_run = sqrt(dx * dx + dy * dy);
auto pt = file.addDoublet<Ifc4x3_add2::IfcCartesianPoint>(xBT, yBT);
auto design_parameters = new Ifc4x3_add2::IfcAlignmentHorizontalSegment(boost::none, boost::none, pt, angleBT, 0.0, 0.0, tangent_run, boost::none, Ifc4x3_add2::IfcAlignmentHorizontalSegmentTypeEnum::IfcAlignmentHorizontalSegmentType_LINE);
auto alignment_segment = new Ifc4x3_add2::IfcAlignmentSegment(IfcParse::IfcGlobalId(), nullptr, boost::none, boost::none, boost::none, nullptr, nullptr, design_parameters);
auto alignment_segment = new Ifc4x3_add2::IfcAlignmentSegment(IfcParse::IfcGlobalId(file.logger()), nullptr, boost::none, boost::none, boost::none, nullptr, nullptr, design_parameters);
horizontal_segments->push(alignment_segment);
if (include_geometry) {
horizontal_curve_segments->push(mapAlignmentHorizontalSegment(design_parameters).first);
horizontal_curve_segments->push(mapAlignmentHorizontalSegment(design_parameters, file.logger()).first);
}
// create zero length terminator segment
auto poe = file.addDoublet<Ifc4x3_add2::IfcCartesianPoint>(xPI, yPI);
design_parameters = new Ifc4x3_add2::IfcAlignmentHorizontalSegment(boost::none, boost::none, poe, angleBT, 0.0, 0.0, 0.0, boost::none, Ifc4x3_add2::IfcAlignmentHorizontalSegmentTypeEnum::IfcAlignmentHorizontalSegmentType_LINE);
alignment_segment = new Ifc4x3_add2::IfcAlignmentSegment(IfcParse::IfcGlobalId(), nullptr, boost::none, boost::none, boost::none, nullptr, nullptr, design_parameters);
alignment_segment = new Ifc4x3_add2::IfcAlignmentSegment(IfcParse::IfcGlobalId(file.logger()), nullptr, boost::none, boost::none, boost::none, nullptr, nullptr, design_parameters);
horizontal_segments->push(alignment_segment);
if (include_geometry) {
auto segment = mapAlignmentHorizontalSegment(design_parameters).first;
auto segment = mapAlignmentHorizontalSegment(design_parameters, file.logger()).first;
segment->setTransition(Ifc4x3_add2::IfcTransitionCode::IfcTransitionCode_DISCONTINUOUS);
horizontal_curve_segments->push(segment);
}
@@ -186,10 +186,10 @@ Ifc4x3_add2::IfcAlignment* addHorizontalAlignment(IfcHierarchyHelper<Ifc4x3_add2
//
// Create the horizontal alignment (IfcAlignmentHorizontal) and nest alignment segments
//
auto horizontal_alignment = new Ifc4x3_add2::IfcAlignmentHorizontal(IfcParse::IfcGlobalId(), nullptr, alignment_name + std::string(" - Horizontal"), boost::none, boost::none, nullptr, nullptr);
auto horizontal_alignment = new Ifc4x3_add2::IfcAlignmentHorizontal(IfcParse::IfcGlobalId(file.logger()), nullptr, alignment_name + std::string(" - Horizontal"), boost::none, boost::none, nullptr, nullptr);
file.addEntity(horizontal_alignment);
auto nests_horizontal_segments = new Ifc4x3_add2::IfcRelNests(IfcParse::IfcGlobalId(), nullptr, boost::none, std::string("Nests horizontal alignment segments with horizontal alignment"), horizontal_alignment, horizontal_segments);
auto nests_horizontal_segments = new Ifc4x3_add2::IfcRelNests(IfcParse::IfcGlobalId(file.logger()), nullptr, boost::none, std::string("Nests horizontal alignment segments with horizontal alignment"), horizontal_alignment, horizontal_segments);
file.addEntity(nests_horizontal_segments);
//
@@ -220,7 +220,7 @@ Ifc4x3_add2::IfcAlignment* addHorizontalAlignment(IfcHierarchyHelper<Ifc4x3_add2
}
// create the alignment
auto alignment = new Ifc4x3_add2::IfcAlignment(IfcParse::IfcGlobalId(), nullptr, alignment_name, boost::none, boost::none, placement, product_definition_shape, boost::none);
auto alignment = new Ifc4x3_add2::IfcAlignment(IfcParse::IfcGlobalId(file.logger()), nullptr, alignment_name, boost::none, boost::none, placement, product_definition_shape, boost::none);
file.addEntity(alignment);
@@ -260,10 +260,10 @@ std::tuple<typename aggregate_of<Ifc4x3_add2::IfcObjectDefinition>::ptr, typenam
{
auto gradient_length = dxBG - length/2;
auto design_parameters = new Ifc4x3_add2::IfcAlignmentVerticalSegment(boost::none, boost::none, xPBG, gradient_length, yPBG, start_slope, start_slope, boost::none, Ifc4x3_add2::IfcAlignmentVerticalSegmentTypeEnum::IfcAlignmentVerticalSegmentType_CONSTANTGRADIENT);
auto alignment_segment = new Ifc4x3_add2::IfcAlignmentSegment(IfcParse::IfcGlobalId(), nullptr, boost::none, boost::none, boost::none, nullptr, nullptr, design_parameters);
auto alignment_segment = new Ifc4x3_add2::IfcAlignmentSegment(IfcParse::IfcGlobalId(file.logger()), nullptr, boost::none, boost::none, boost::none, nullptr, nullptr, design_parameters);
vertical_segments->push(alignment_segment);
if (include_geometry) {
vertical_curve_segments->push(mapAlignmentVerticalSegment(design_parameters).first);
vertical_curve_segments->push(mapAlignmentVerticalSegment(design_parameters, file.logger()).first);
}
}
@@ -274,10 +274,10 @@ std::tuple<typename aggregate_of<Ifc4x3_add2::IfcObjectDefinition>::ptr, typenam
double yBVC = yPVI - start_slope * length / 2;
auto design_parameters = new Ifc4x3_add2::IfcAlignmentVerticalSegment(boost::none, boost::none, xBVC, length, yBVC, start_slope, end_slope, 1 / k, Ifc4x3_add2::IfcAlignmentVerticalSegmentTypeEnum::IfcAlignmentVerticalSegmentType_PARABOLICARC);
auto alignment_segment = new Ifc4x3_add2::IfcAlignmentSegment(IfcParse::IfcGlobalId(), nullptr, boost::none, boost::none, boost::none, nullptr, nullptr, design_parameters);
auto alignment_segment = new Ifc4x3_add2::IfcAlignmentSegment(IfcParse::IfcGlobalId(file.logger()), nullptr, boost::none, boost::none, boost::none, nullptr, nullptr, design_parameters);
vertical_segments->push(alignment_segment);
if (include_geometry) {
vertical_curve_segments->push(mapAlignmentVerticalSegment(design_parameters).first);
vertical_curve_segments->push(mapAlignmentVerticalSegment(design_parameters, file.logger()).first);
}
}
@@ -294,18 +294,18 @@ std::tuple<typename aggregate_of<Ifc4x3_add2::IfcObjectDefinition>::ptr, typenam
auto gradient_length = dx;
auto design_parameters = new Ifc4x3_add2::IfcAlignmentVerticalSegment(boost::none, boost::none, xPBG, gradient_length, yPBG, slope, slope, boost::none, Ifc4x3_add2::IfcAlignmentVerticalSegmentTypeEnum::IfcAlignmentVerticalSegmentType_CONSTANTGRADIENT);
auto alignment_segment = new Ifc4x3_add2::IfcAlignmentSegment(IfcParse::IfcGlobalId(), nullptr, boost::none, boost::none, boost::none, nullptr, nullptr, design_parameters);
auto alignment_segment = new Ifc4x3_add2::IfcAlignmentSegment(IfcParse::IfcGlobalId(file.logger()), nullptr, boost::none, boost::none, boost::none, nullptr, nullptr, design_parameters);
vertical_segments->push(alignment_segment);
if (include_geometry) {
vertical_curve_segments->push(mapAlignmentVerticalSegment(design_parameters).first);
vertical_curve_segments->push(mapAlignmentVerticalSegment(design_parameters, file.logger()).first);
}
// create zero length terminator segment
design_parameters = new Ifc4x3_add2::IfcAlignmentVerticalSegment(boost::none, boost::none, xPVI, 0.0, yPVI, slope, slope, boost::none, Ifc4x3_add2::IfcAlignmentVerticalSegmentTypeEnum::IfcAlignmentVerticalSegmentType_CONSTANTGRADIENT);
alignment_segment = new Ifc4x3_add2::IfcAlignmentSegment(IfcParse::IfcGlobalId(), nullptr, boost::none, boost::none, boost::none, nullptr, nullptr, design_parameters);
alignment_segment = new Ifc4x3_add2::IfcAlignmentSegment(IfcParse::IfcGlobalId(file.logger()), nullptr, boost::none, boost::none, boost::none, nullptr, nullptr, design_parameters);
vertical_segments->push(alignment_segment);
if (include_geometry) {
auto segment = mapAlignmentVerticalSegment(design_parameters).first;
auto segment = mapAlignmentVerticalSegment(design_parameters, file.logger()).first;
segment->setTransition(Ifc4x3_add2::IfcTransitionCode::IfcTransitionCode_DISCONTINUOUS);
vertical_curve_segments->push(segment);
}
@@ -329,19 +329,19 @@ Ifc4x3_add2::IfcAlignment* addAlignment(IfcHierarchyHelper<Ifc4x3_add2>& file, c
//
// Create the horizontal alignment (IfcAlignmentHorizontal) and nest the segments
//
auto horizontal_alignment = new Ifc4x3_add2::IfcAlignmentHorizontal(IfcParse::IfcGlobalId(), nullptr, alignment_name + std::string(" - Horizontal"), boost::none, boost::none, nullptr, nullptr);
auto horizontal_alignment = new Ifc4x3_add2::IfcAlignmentHorizontal(IfcParse::IfcGlobalId(file.logger()), nullptr, alignment_name + std::string(" - Horizontal"), boost::none, boost::none, nullptr, nullptr);
file.addEntity(horizontal_alignment);
auto nests_horizontal_segments = new Ifc4x3_add2::IfcRelNests(IfcParse::IfcGlobalId(), nullptr, boost::none, std::string("Nests horizontal alignment segments with horizontal alignment"), horizontal_alignment, horizontal_segments);
auto nests_horizontal_segments = new Ifc4x3_add2::IfcRelNests(IfcParse::IfcGlobalId(file.logger()), nullptr, boost::none, std::string("Nests horizontal alignment segments with horizontal alignment"), horizontal_alignment, horizontal_segments);
file.addEntity(nests_horizontal_segments);
//
// Create the vertical alignment (IfcAlignmentVertical) and nest the segments
//
auto vertical_profile = new Ifc4x3_add2::IfcAlignmentVertical(IfcParse::IfcGlobalId(), nullptr, alignment_name + std::string("- Vertical"), boost::none, boost::none, nullptr, nullptr);
auto vertical_profile = new Ifc4x3_add2::IfcAlignmentVertical(IfcParse::IfcGlobalId(file.logger()), nullptr, alignment_name + std::string("- Vertical"), boost::none, boost::none, nullptr, nullptr);
file.addEntity(vertical_profile);
auto nests_vertical_segments = new Ifc4x3_add2::IfcRelNests(IfcParse::IfcGlobalId(), nullptr, boost::none, std::string("Nests vertical alignment segments with vertical alignment"), vertical_profile, vertical_segments);
auto nests_vertical_segments = new Ifc4x3_add2::IfcRelNests(IfcParse::IfcGlobalId(file.logger()), nullptr, boost::none, std::string("Nests vertical alignment segments with vertical alignment"), vertical_profile, vertical_segments);
file.addEntity(nests_vertical_segments);
Ifc4x3_add2::IfcLocalPlacement* placement = nullptr;
@@ -383,7 +383,7 @@ Ifc4x3_add2::IfcAlignment* addAlignment(IfcHierarchyHelper<Ifc4x3_add2>& file, c
// Create the IfcAlignment
//
auto alignment = new Ifc4x3_add2::IfcAlignment(IfcParse::IfcGlobalId(), nullptr, alignment_name, boost::none, boost::none, placement, product_definition_shape, boost::none);
auto alignment = new Ifc4x3_add2::IfcAlignment(IfcParse::IfcGlobalId(file.logger()), nullptr, alignment_name, boost::none, boost::none, placement, product_definition_shape, boost::none);
file.addEntity(alignment);
// Nest the IfcAlignmentHorizontal and IfcAlignmentVertical with the IfcAlignment to complete the business logic
@@ -393,31 +393,31 @@ Ifc4x3_add2::IfcAlignment* addAlignment(IfcHierarchyHelper<Ifc4x3_add2>& file, c
alignment_layout_list->push(horizontal_alignment);
alignment_layout_list->push(vertical_profile);
auto nests_alignment_layouts = new Ifc4x3_add2::IfcRelNests(IfcParse::IfcGlobalId(), nullptr, std::string("Nest horizontal and vertical alignment layouts with the alignment"), boost::none, alignment, alignment_layout_list);
auto nests_alignment_layouts = new Ifc4x3_add2::IfcRelNests(IfcParse::IfcGlobalId(file.logger()), nullptr, std::string("Nest horizontal and vertical alignment layouts with the alignment"), boost::none, alignment, alignment_layout_list);
file.addEntity(nests_alignment_layouts);
return alignment;
}
std::pair<Ifc4x3_add2::IfcCurveSegment*, Ifc4x3_add2::IfcCurveSegment*> mapAlignmentSegment(const Ifc4x3_add2::IfcAlignmentSegment* segment) {
std::pair<Ifc4x3_add2::IfcCurveSegment*, Ifc4x3_add2::IfcCurveSegment*> mapAlignmentSegment(const Ifc4x3_add2::IfcAlignmentSegment* segment, Logger& logger) {
std::pair<Ifc4x3_add2::IfcCurveSegment*, Ifc4x3_add2::IfcCurveSegment*> result(nullptr, nullptr);
auto design_parameters = segment->DesignParameters();
auto horizontal = design_parameters->as<Ifc4x3_add2::IfcAlignmentHorizontalSegment>();
auto vertical = design_parameters->as<Ifc4x3_add2::IfcAlignmentVerticalSegment>();
auto cant = design_parameters->as<Ifc4x3_add2::IfcAlignmentCantSegment>();
if (horizontal) {
result = mapAlignmentHorizontalSegment(horizontal);
result = mapAlignmentHorizontalSegment(horizontal, logger);
} else if (vertical) {
result = mapAlignmentVerticalSegment(vertical);
result = mapAlignmentVerticalSegment(vertical, logger);
} else if (cant) {
result = mapAlignmentCantSegment(cant);
result = mapAlignmentCantSegment(cant, logger);
} else {
Logger::Root().Error("VAL", 8, std::string("Unexpected IfcAlignmentSegment subtype encountered"));
logger.Error("VAL", 8, std::string("Unexpected IfcAlignmentSegment subtype encountered"));
}
return result;
}
std::pair<Ifc4x3_add2::IfcCurveSegment*, Ifc4x3_add2::IfcCurveSegment*> mapAlignmentHorizontalSegment(const Ifc4x3_add2::IfcAlignmentHorizontalSegment* segment) {
std::pair<Ifc4x3_add2::IfcCurveSegment*, Ifc4x3_add2::IfcCurveSegment*> mapAlignmentHorizontalSegment(const Ifc4x3_add2::IfcAlignmentHorizontalSegment* segment, Logger& logger) {
std::pair<Ifc4x3_add2::IfcCurveSegment*, Ifc4x3_add2::IfcCurveSegment*> result(nullptr, nullptr);
auto start_point = segment->StartPoint();
auto start_direction = segment->StartDirection();
@@ -661,15 +661,15 @@ std::pair<Ifc4x3_add2::IfcCurveSegment*, Ifc4x3_add2::IfcCurveSegment*> mapAlign
result.first = curve_segment;
} else if (type == Ifc4x3_add2::IfcAlignmentHorizontalSegmentTypeEnum::IfcAlignmentHorizontalSegmentType_VIENNESEBEND) {
Logger::Root().Warning("UNS", 22, std::string("mapping of AlignmentHorizontalSegmentType VIENNESEBEND not supported"));
logger.Warning("UNS", 22, std::string("mapping of AlignmentHorizontalSegmentType VIENNESEBEND not supported"));
} else {
Logger::Root().Error("VAL", 9, std::string("unexpected AlignmentHorizontalSegmentType encountered"));
logger.Error("VAL", 9, std::string("unexpected AlignmentHorizontalSegmentType encountered"));
}
return result;
}
std::pair<Ifc4x3_add2::IfcCurveSegment*, Ifc4x3_add2::IfcCurveSegment*> mapAlignmentVerticalSegment(const Ifc4x3_add2::IfcAlignmentVerticalSegment* segment) {
std::pair<Ifc4x3_add2::IfcCurveSegment*, Ifc4x3_add2::IfcCurveSegment*> mapAlignmentVerticalSegment(const Ifc4x3_add2::IfcAlignmentVerticalSegment* segment, Logger& logger) {
std::pair<Ifc4x3_add2::IfcCurveSegment*, Ifc4x3_add2::IfcCurveSegment*> result(nullptr, nullptr);
auto start_distance_along = segment->StartDistAlong();
auto horizontal_length = segment->HorizontalLength();
@@ -732,7 +732,7 @@ std::pair<Ifc4x3_add2::IfcCurveSegment*, Ifc4x3_add2::IfcCurveSegment*> mapAlign
result.first = curve_segment;
} else if (type == Ifc4x3_add2::IfcAlignmentVerticalSegmentTypeEnum::IfcAlignmentVerticalSegmentType_CLOTHOID) {
Logger::Root().Warning("UNS", 23, std::string("mapping of AlignmentVerticalSegmentType CLOTHOID not supported"));
logger.Warning("UNS", 23, std::string("mapping of AlignmentVerticalSegmentType CLOTHOID not supported"));
} else if (type == Ifc4x3_add2::IfcAlignmentVerticalSegmentTypeEnum::IfcAlignmentVerticalSegmentType_CIRCULARARC) {
auto start_angle = atan(start_gradient);
auto end_angle = atan(end_gradient);
@@ -760,31 +760,31 @@ std::pair<Ifc4x3_add2::IfcCurveSegment*, Ifc4x3_add2::IfcCurveSegment*> mapAlign
result.first = curve_segment;
} else {
Logger::Root().Error("VAL", 10, std::string("unexpected AlignmentVerticalSegmentType encountered"));
logger.Error("VAL", 10, std::string("unexpected AlignmentVerticalSegmentType encountered"));
}
return result;
}
std::pair<Ifc4x3_add2::IfcCurveSegment*, Ifc4x3_add2::IfcCurveSegment*> mapAlignmentCantSegment(const Ifc4x3_add2::IfcAlignmentCantSegment* segment) {
std::pair<Ifc4x3_add2::IfcCurveSegment*, Ifc4x3_add2::IfcCurveSegment*> mapAlignmentCantSegment(const Ifc4x3_add2::IfcAlignmentCantSegment* segment, Logger& logger) {
std::pair<Ifc4x3_add2::IfcCurveSegment*, Ifc4x3_add2::IfcCurveSegment*> result(nullptr, nullptr);
auto type = segment->PredefinedType();
if (type == Ifc4x3_add2::IfcAlignmentCantSegmentTypeEnum::IfcAlignmentCantSegmentType_BLOSSCURVE) {
Logger::Root().Warning("UNS", 24, std::string("mapping of AlignmentCantSegmentType BLOSSCURVE not supported"));
logger.Warning("UNS", 24, std::string("mapping of AlignmentCantSegmentType BLOSSCURVE not supported"));
} else if (type == Ifc4x3_add2::IfcAlignmentCantSegmentTypeEnum::IfcAlignmentCantSegmentType_CONSTANTCANT) {
Logger::Root().Warning("UNS", 25, std::string("mapping of AlignmentCantSegmentType CONSTANTCANT not supported"));
logger.Warning("UNS", 25, std::string("mapping of AlignmentCantSegmentType CONSTANTCANT not supported"));
} else if (type == Ifc4x3_add2::IfcAlignmentCantSegmentTypeEnum::IfcAlignmentCantSegmentType_COSINECURVE) {
Logger::Root().Warning("UNS", 26, std::string("mapping of AlignmentCantSegmentType COSINECURVE not supported"));
logger.Warning("UNS", 26, std::string("mapping of AlignmentCantSegmentType COSINECURVE not supported"));
} else if (type == Ifc4x3_add2::IfcAlignmentCantSegmentTypeEnum::IfcAlignmentCantSegmentType_HELMERTCURVE) {
Logger::Root().Warning("UNS", 27, std::string("mapping of AlignmentCantSegmentType HELMERTCURVE not supported"));
logger.Warning("UNS", 27, std::string("mapping of AlignmentCantSegmentType HELMERTCURVE not supported"));
} else if (type == Ifc4x3_add2::IfcAlignmentCantSegmentTypeEnum::IfcAlignmentCantSegmentType_LINEARTRANSITION) {
Logger::Root().Warning("UNS", 28, std::string("mapping of AlignmentCantSegmentType LINEARTRANSTION not supported"));
logger.Warning("UNS", 28, std::string("mapping of AlignmentCantSegmentType LINEARTRANSTION not supported"));
} else if (type == Ifc4x3_add2::IfcAlignmentCantSegmentTypeEnum::IfcAlignmentCantSegmentType_SINECURVE) {
Logger::Root().Warning("UNS", 29, std::string("mapping of AlignmentCantSegmentType SINECURVE not supported"));
logger.Warning("UNS", 29, std::string("mapping of AlignmentCantSegmentType SINECURVE not supported"));
} else if (type == Ifc4x3_add2::IfcAlignmentCantSegmentTypeEnum::IfcAlignmentCantSegmentType_VIENNESEBEND) {
Logger::Root().Warning("UNS", 30, std::string("mapping of AlignmentCantSegmentType VIENNESEBEND not supported"));
logger.Warning("UNS", 30, std::string("mapping of AlignmentCantSegmentType VIENNESEBEND not supported"));
} else {
Logger::Root().Error("VAL", 11, std::string("unexpected AlignmentCantSegmentType encountered"));
logger.Error("VAL", 11, std::string("unexpected AlignmentCantSegmentType encountered"));
}
return result;
}
+5 -5
View File
@@ -49,11 +49,11 @@ IFC_PARSE_API Ifc4x3_add2::IfcAlignment* addAlignment(IfcHierarchyHelper<Ifc4x3_
// Maps horizontal alignment business logic to geometry.
// Bloss curves have two geometry elements for one horizontal alignment segment. That is the reason for returning a pair.
// Typically the first element of the pair will have the geometry and the second element will be nullptr
IFC_PARSE_API std::pair<Ifc4x3_add2::IfcCurveSegment*, Ifc4x3_add2::IfcCurveSegment*> mapAlignmentSegment(const Ifc4x3_add2::IfcAlignmentSegment* segment);
IFC_PARSE_API std::pair<Ifc4x3_add2::IfcCurveSegment*, Ifc4x3_add2::IfcCurveSegment*> mapAlignmentHorizontalSegment(const Ifc4x3_add2::IfcAlignmentHorizontalSegment* segment);
IFC_PARSE_API std::pair<Ifc4x3_add2::IfcCurveSegment*, Ifc4x3_add2::IfcCurveSegment*> mapAlignmentVerticalSegment(const Ifc4x3_add2::IfcAlignmentVerticalSegment* segment);
IFC_PARSE_API std::pair<Ifc4x3_add2::IfcCurveSegment*, Ifc4x3_add2::IfcCurveSegment*> mapAlignmentCantSegment(const Ifc4x3_add2::IfcAlignmentCantSegment* segment);
IFC_PARSE_API std::pair<Ifc4x3_add2::IfcCurveSegment*, Ifc4x3_add2::IfcCurveSegment*> mapAlignmentSegment(const Ifc4x3_add2::IfcAlignmentSegment* segment, Logger& logger = Logger::Root());
IFC_PARSE_API std::pair<Ifc4x3_add2::IfcCurveSegment*, Ifc4x3_add2::IfcCurveSegment*> mapAlignmentHorizontalSegment(const Ifc4x3_add2::IfcAlignmentHorizontalSegment* segment, Logger& logger = Logger::Root());
IFC_PARSE_API std::pair<Ifc4x3_add2::IfcCurveSegment*, Ifc4x3_add2::IfcCurveSegment*> mapAlignmentVerticalSegment(const Ifc4x3_add2::IfcAlignmentVerticalSegment* segment, Logger& logger = Logger::Root());
IFC_PARSE_API std::pair<Ifc4x3_add2::IfcCurveSegment*, Ifc4x3_add2::IfcCurveSegment*> mapAlignmentCantSegment(const Ifc4x3_add2::IfcAlignmentCantSegment* segment, Logger& logger = Logger::Root());
#endif
#endif
#endif
+7 -5
View File
@@ -77,7 +77,9 @@
using namespace IfcParse;
IfcCharacterDecoder::IfcCharacterDecoder(IfcParse::FileReader* stream) {
IfcCharacterDecoder::IfcCharacterDecoder(IfcParse::FileReader* stream, Logger& logger)
: logger_(logger)
{
stream_ = stream;
codepage_ = 0;
}
@@ -86,7 +88,7 @@ IfcCharacterDecoder::~IfcCharacterDecoder() {
}
namespace {
std::string read_string(IfcParse::FileReader& stream_, IfcParse::IfcCharacterDecoder::ConversionMode mode, char substitution_character) {
std::string read_string(IfcParse::FileReader& stream_, Logger& logger, IfcParse::IfcCharacterDecoder::ConversionMode mode, char substitution_character) {
std::u32string builder_;
unsigned int parse_state = 0;
@@ -137,7 +139,7 @@ namespace {
parse_state += PAGE;
} else if (IS_HEXADECIMAL(current_char) && EXPECTS_HEX(parse_state)) {
if (IS_LOWERCASE_HEX(current_char)) {
Logger::Root().Warning("SYN", 2, "Lowercase hexadecimal character '" + std::string(1, current_char) +
logger.Warning("SYN", 2, "Lowercase hexadecimal character '" + std::string(1, current_char) +
"' found at offset " + std::to_string(stream_.tell()) +
". It is recommended to use uppercase for hexadecimal.");
}
@@ -211,13 +213,13 @@ namespace {
} // namespace
IfcCharacterDecoder::operator std::string() {
return read_string(*stream_, mode, substitution_character);
return read_string(*stream_, logger_, mode, substitution_character);
}
std::string IfcCharacterDecoder::get(size_t& ptr) {
auto local_stream = *stream_;
local_stream.seek(ptr);
auto s = read_string(local_stream, mode, substitution_character);
auto s = read_string(local_stream, logger_, mode, substitution_character);
ptr = local_stream.tell();
return s;
}
+3 -1
View File
@@ -28,6 +28,7 @@
#define IFCCHARACTERDECODER_H
#include "FileReader.h"
#include "IfcLogger.h"
#include <string>
@@ -42,6 +43,7 @@ namespace IfcParse {
class IFC_PARSE_API IfcCharacterDecoder {
private:
IfcParse::FileReader* stream_;
Logger& logger_;
int codepage_;
public:
@@ -52,7 +54,7 @@ class IFC_PARSE_API IfcCharacterDecoder {
};
static ConversionMode mode;
static char substitution_character;
IfcCharacterDecoder(IfcParse::FileReader* stream);
IfcCharacterDecoder(IfcParse::FileReader* stream, Logger& logger = Logger::Root());
~IfcCharacterDecoder();
// Only advances the underlying token stream read pointer
// to the next token.
+23 -23
View File
@@ -59,7 +59,7 @@ namespace {
constexpr bool is_type_in_variant_v = is_type_in_variant<Variant, T>::value;
template <typename Fn>
void dispatch_token(boost::optional<size_t> instance_id, int attribute_id, IfcParse::Token t, IfcParse::declaration* decl, Fn fn) {
void dispatch_token(boost::optional<size_t> instance_id, int attribute_id, IfcParse::Token t, IfcParse::declaration* decl, Logger& logger, Fn fn) {
if (t.type == IfcParse::Token_BINARY) {
fn(IfcParse::TokenFunc::asBinary(t));
} else if (IfcParse::TokenFunc::isBool(t)) {
@@ -72,10 +72,10 @@ namespace {
try {
fn(EnumerationReference(decl->as_enumeration_type(), decl->as_enumeration_type()->lookup_enum_offset(s)));
} catch (IfcParse::IfcException& e) {
Logger::Root().Error("VAL", 12, "An enumeration literal '" + s + "' is not valid for type '" + decl->name() + "' at offset " + std::to_string(t.startPos));
logger.Error("VAL", 12, "An enumeration literal '" + s + "' is not valid for type '" + decl->name() + "' at offset " + std::to_string(t.startPos));
}
} else {
Logger::Root().Error("VAL", 13, "An enumeration literal '" + s + "' is not expected at attribute index '" + std::to_string(attribute_id) + "' at offset " + std::to_string(t.startPos));
logger.Error("VAL", 13, "An enumeration literal '" + s + "' is not expected at attribute index '" + std::to_string(attribute_id) + "' at offset " + std::to_string(t.startPos));
}
} else if (t.type == IfcParse::Token_FLOAT) {
fn(IfcParse::TokenFunc::asFloat(t));
@@ -92,7 +92,7 @@ namespace {
}
template <size_t Depth, typename Fn>
void construct_(boost::optional<size_t> instance_id, int attribute_id, IfcParse::parse_context& p, const IfcParse::aggregation_type* aggr, Fn fn) {
void construct_(boost::optional<size_t> instance_id, int attribute_id, IfcParse::parse_context& p, const IfcParse::aggregation_type* aggr, Logger& logger, Fn fn) {
if (p.tokens_.empty()) {
// @todo instead of ugly if-else we could also default initialize the respective
// variant types below.
@@ -135,7 +135,7 @@ namespace {
possible_aggregation_types_t aggregate_storage;
auto append_to_aggregate_storage = [&aggregate_storage](const auto& v) {
auto append_to_aggregate_storage = [&aggregate_storage, &logger](const auto& v) {
if constexpr (is_type_in_variant_v<possible_aggregation_types_t, std::vector<std::decay_t<decltype(v)>>>) {
if (aggregate_storage.index() == 0) {
aggregate_storage = std::vector<std::decay_t<decltype(v)>>{ v };
@@ -194,7 +194,7 @@ namespace {
}
}, aggregate_storage);
Logger::Root().Error("VAL", 14, "Inconsistent aggregate valuation while attempting to append " + std::string(typeid(decltype(v)).name()) + " to an aggregate of " + current);
logger.Error("VAL", 14, "Inconsistent aggregate valuation while attempting to append " + std::string(typeid(decltype(v)).name()) + " to an aggregate of " + current);
// @todo boolean -> logical upgrade
// wait a second... there are no aggregate of bool / logical in the schema..
@@ -213,19 +213,19 @@ namespace {
}
} else {
// @todo would be cool if we can trace this back to file offset
Logger::Root().Error("UNS", 31, std::string("Aggregates of ") + typeid(decltype(v)).name() + " are not supported in the IfcOpenShell parser");
logger.Error("UNS", 31, std::string("Aggregates of ") + typeid(decltype(v)).name() + " are not supported in the IfcOpenShell parser");
}
};
for (auto& t : p.tokens_) {
std::visit([&aggregate_storage, &append_to_aggregate_storage, aggr, instance_id, attribute_id](const auto& v) {
std::visit([&aggregate_storage, &append_to_aggregate_storage, aggr, instance_id, attribute_id, &logger](const auto& v) {
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, IfcParse::Token>) {
// @todo get aggregate of enumeration
dispatch_token(instance_id, attribute_id, v, aggr && aggr->type_of_element()->as_named_type() ? aggr->type_of_element()->as_named_type()->declared_type() : nullptr, append_to_aggregate_storage);
dispatch_token(instance_id, attribute_id, v, aggr && aggr->type_of_element()->as_named_type() ? aggr->type_of_element()->as_named_type()->declared_type() : nullptr, logger, append_to_aggregate_storage);
} else if constexpr (std::is_same_v<std::decay_t<decltype(v)>, IfcParse::parse_context*>) {
// nested list
if constexpr (Depth < 3) {
construct_<Depth + 1>(instance_id, attribute_id, *v, nullptr, append_to_aggregate_storage);
construct_<Depth + 1>(instance_id, attribute_id, *v, nullptr, logger, append_to_aggregate_storage);
}
} else {
append_to_aggregate_storage(IfcParse::reference_or_simple_type{ v });
@@ -237,7 +237,7 @@ namespace {
}
}
IfcEntityInstanceData IfcParse::parse_context::construct(boost::optional<size_t> name, unresolved_references& references_to_resolve, const IfcParse::declaration* decl, boost::optional<size_t> expected_size, int resolve_reference_index, bool coerce_attribute_count) {
IfcEntityInstanceData IfcParse::parse_context::construct(boost::optional<size_t> name, unresolved_references& references_to_resolve, const IfcParse::declaration* decl, boost::optional<size_t> expected_size, int resolve_reference_index, Logger& logger, bool coerce_attribute_count) {
std::vector<const IfcParse::parameter_type*> parameter_types;
std::unique_ptr<IfcParse::named_type> transient_named_type;
@@ -263,9 +263,9 @@ IfcEntityInstanceData IfcParse::parse_context::construct(boost::optional<size_t>
{
size_t expected = expected_size ? *expected_size : parameter_types.size();
if (decl != nullptr && decl->schema() == &Header_section_schema::get_schema()) {
Logger::Root().Warning("VAL", 15, "Expected " + std::to_string(expected) + " attribute values, found " + std::to_string(tokens_.size()) + " for header entity " + decl->name());
logger.Warning("VAL", 15, "Expected " + std::to_string(expected) + " attribute values, found " + std::to_string(tokens_.size()) + " for header entity " + decl->name());
} else {
Logger::Root().Warning("VAL", 16, "Expected " + std::to_string(expected) + " attribute values, found " + std::to_string(tokens_.size()) + (name ? std::string(" for instance #" + std::to_string(*name)) : std::string("")));
logger.Warning("VAL", 16, "Expected " + std::to_string(expected) + " attribute values, found " + std::to_string(tokens_.size()) + (name ? std::string(" for instance #" + std::to_string(*name)) : std::string("")));
}
}
@@ -292,9 +292,9 @@ IfcEntityInstanceData IfcParse::parse_context::construct(boost::optional<size_t>
auto index = (uint8_t) std::distance(tokens_.begin(), it);
std::visit([this, &storage, name, &references_to_resolve, index, param_type, resolve_reference_index](const auto& v) {
std::visit([this, &storage, name, &references_to_resolve, index, param_type, resolve_reference_index, &logger](const auto& v) {
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, IfcParse::Token>) {
dispatch_token(name, index, v, param_type && param_type->as_named_type() ? param_type->as_named_type()->declared_type() : nullptr, [this, &storage, name, &references_to_resolve, index, resolve_reference_index](auto v) {
dispatch_token(name, index, v, param_type && param_type->as_named_type() ? param_type->as_named_type()->declared_type() : nullptr, logger, [this, &storage, name, &references_to_resolve, index, resolve_reference_index](auto v) {
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, IfcParse::reference_or_simple_type>) {
if (name) {
references_to_resolve.push_back(std::make_pair(
@@ -316,7 +316,7 @@ IfcEntityInstanceData IfcParse::parse_context::construct(boost::optional<size_t>
pt = pt->as_named_type()->declared_type()->as_type_declaration()->declared_type();
}
}
construct_<0>(name, index, *v, pt ? pt->as_aggregation_type() : nullptr, [this, &storage, name, &references_to_resolve, index, resolve_reference_index](const auto& v) {
construct_<0>(name, index, *v, pt ? pt->as_aggregation_type() : nullptr, logger, [this, &storage, name, &references_to_resolve, index, resolve_reference_index](const auto& v) {
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, std::vector<reference_or_simple_type>>) {
if (name) {
references_to_resolve.push_back({ { (uint32_t) *name, resolve_reference_index == -1 ? index : (uint8_t)resolve_reference_index }, v });
@@ -719,13 +719,13 @@ std::optional<std::tuple<size_t, const IfcParse::declaration*, IfcEntityInstance
try {
entity_type = schema_->declaration_by_name(TokenFunc::asStringRef(token_stream_[2]));
} catch (const IfcException& ex) {
Logger::Root().Message(Logger::LOG_ERROR, "SYN", 3, std::string(ex.what()) + " at offset " + std::to_string(token_stream_[2].startPos));
logger_.get().Message(Logger::LOG_ERROR, "SYN", 3, std::string(ex.what()) + " at offset " + std::to_string(token_stream_[2].startPos));
current_id = 0;
goto advance;
}
if (entity_type->as_entity() == nullptr) {
Logger::Root().Message(Logger::LOG_ERROR, "SYN", 4, "Non entity type " + entity_type->name() + " at offset " + std::to_string(token_stream_[2].startPos));
logger_.get().Message(Logger::LOG_ERROR, "SYN", 4, "Non entity type " + entity_type->name() + " at offset " + std::to_string(token_stream_[2].startPos));
goto advance;
}
@@ -744,7 +744,7 @@ std::optional<std::tuple<size_t, const IfcParse::declaration*, IfcEntityInstance
storage_.load(current_id, entity_type->as_entity(), ps, -1);
} catch (const IfcInvalidTokenException& e) {
good_ = file_open_status::INVALID_SYNTAX;
Logger::Root().Error("SYN", 5, e);
logger_.get().Error("SYN", 5, e);
break;
}
@@ -753,10 +753,10 @@ std::optional<std::tuple<size_t, const IfcParse::declaration*, IfcEntityInstance
if (((++progress_) % 1000) == 0) {
std::stringstream ss;
ss << "\r#" << current_id;
Logger::Root().Status(ss.str(), false);
logger_.get().Status(ss.str(), false);
}
auto data = ps.construct(current_id, references_to_resolve_, entity_type, boost::none, -1, coerce_attribute_count);
auto data = ps.construct(current_id, references_to_resolve_, entity_type, boost::none, -1, logger_.get(), coerce_attribute_count);
return_value.emplace(
(size_t)current_id,
@@ -769,9 +769,9 @@ std::optional<std::tuple<size_t, const IfcParse::declaration*, IfcEntityInstance
try {
next_token = lexer_->Next();
} catch (const IfcException& e) {
Logger::Root().Message(Logger::LOG_ERROR, "SYN", 6, std::string(e.what()) + ". Parsing terminated");
logger_.get().Message(Logger::LOG_ERROR, "SYN", 6, std::string(e.what()) + ". Parsing terminated");
} catch (...) {
Logger::Root().Message(Logger::LOG_ERROR, "SYN", 7, "Parsing terminated");
logger_.get().Message(Logger::LOG_ERROR, "SYN", 7, "Parsing terminated");
}
if (!lexer_->stream->eof() && next_token.type == Token_NONE) {
+16 -12
View File
@@ -27,6 +27,7 @@
#include "storage.h"
#include "file_open_status.h"
#include <functional>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>
@@ -96,6 +97,7 @@ private:
const IfcParse::schema_definition* schema_;
IfcParse::impl::in_memory_file_storage storage_;
IfcParse::file_open_status good_ = IfcParse::file_open_status::SUCCESS;
std::reference_wrapper<Logger> logger_;
int progress_;
IfcParse::unresolved_references references_to_resolve_;
int yielded_header_instances_ = 0;
@@ -144,13 +146,13 @@ private:
void pushPage(const std::string& page);
InstanceStreamer();
InstanceStreamer(Logger& logger = Logger::Root());
InstanceStreamer(const std::string& fn, bool mmap=false);
InstanceStreamer(const std::string& fn, bool mmap=false, Logger& logger = Logger::Root());
InstanceStreamer(void* data, int length);
InstanceStreamer(void* data, int length, Logger& logger = Logger::Root());
InstanceStreamer(const IfcParse::schema_definition* schema, IfcParse::IfcSpfLexer* lexer);
InstanceStreamer(const IfcParse::schema_definition* schema, IfcParse::IfcSpfLexer* lexer, Logger& logger = Logger::Root());
void bypassTypes(const std::set<std::string>& type_names);
@@ -199,6 +201,7 @@ public:
private:
file_open_status good_ = file_open_status::SUCCESS;
std::reference_wrapper<Logger> logger_;
const IfcParse::schema_definition* schema_;
const IfcParse::declaration* ifcroot_type_;
@@ -229,7 +232,7 @@ public:
/// </summary>
/// <param name="path">UTF-8 file path to an IFC-SPF file</param>
/// <param name="mmap">Whether to use memory-mapped I/O</param>
IfcFile(const std::string& path, bool mmap);
IfcFile(const std::string& path, bool mmap, Logger& logger = Logger::Root());
#endif
/// <summary>
/// Constructs an IfcFile object from a file path, supports IFC-SPF and the IfcOpenShell-specific RocksDB format.
@@ -237,23 +240,23 @@ public:
/// <param name="path">UTF-8 file path to an IFC-SPF file or RocksDB database directory</param>
/// <param name="ty">File type of the path</param>
/// <param name="readonly">Whether to open in read-only mode, only supported on RocksDB databases</param>
IfcFile(const std::string& path, filetype ty=FT_AUTODETECT, bool readonly=false);
IfcFile(const std::string& path, filetype ty=FT_AUTODETECT, bool readonly=false, Logger& logger = Logger::Root());
/// <summary>
/// Constructs an IfcFile object from a stream containing IFC-SPF data.
/// </summary>
IfcFile(std::istream& stream, int length);
IfcFile(std::istream& stream, int length, Logger& logger = Logger::Root());
/// <summary>
/// Constructs an IfcFile object from a memory buffer containing IFC-SPF data.
/// </summary>
IfcFile(void* data, int length);
IfcFile(void* data, int length, Logger& logger = Logger::Root());
/// <summary>
/// Constructs an IfcFile object from a given IFC SPF stream.
/// </summary>
/// <param name="stream">A pointer to an IfcParse::FileReader object representing the input IFC SPF data stream.</param>
IfcFile(IfcParse::FileReader* stream);
IfcFile(IfcParse::FileReader* stream, Logger& logger = Logger::Root());
/// <summary>
/// Constructs an IfcFile object with the specified schema, file type, and file path.
@@ -262,12 +265,12 @@ public:
/// <param name="schema">Pointer to the schema definition to use. Defaults to the IFC4 schema if not specified.</param>
/// <param name="ty">The file type to use for the file. Defaults to FT_AUTODETECT.</param>
/// <param name="path">The file system path to the IFC file. Defaults to an empty string.</param>
IfcFile(const IfcParse::schema_definition* schema = IfcParse::schema_by_name("IFC4"), filetype ty = FT_AUTODETECT, const std::string& path = "");
IfcFile(const IfcParse::schema_definition* schema = IfcParse::schema_by_name("IFC4"), filetype ty = FT_AUTODETECT, const std::string& path = "", Logger& logger = Logger::Root());
/// <summary>
/// Constructs an unitialized IfcFile object. Call initialize() later on. Allows to specify which types to bypass during load.
/// </summary>
IfcFile(const uninitialized_tag&);
IfcFile(const uninitialized_tag&, Logger& logger = Logger::Root());
bool initialize(const std::string& path, filetype ty = FT_AUTODETECT, bool readonly = false);
#ifdef USE_MMAP
@@ -281,6 +284,7 @@ public:
~IfcFile();
IfcParse::file_open_status good() const { return good_; }
Logger& logger() const { return logger_.get(); }
/// Returns the first entity in the range of instances contained in the model,
/// in arbitrary order
@@ -443,7 +447,7 @@ public:
};
#ifdef WITH_IFCXML
IFC_PARSE_API IfcFile* parse_ifcxml(const std::string& filename);
IFC_PARSE_API IfcFile* parse_ifcxml(const std::string& filename, Logger& logger = Logger::Root());
#endif
namespace impl {
+4 -4
View File
@@ -94,7 +94,7 @@ void expand(const std::string& s, std::vector<unsigned char>& v) {
static boost::uuids::basic_random_generator<boost::mt19937> gen;
#endif
IfcParse::IfcGlobalId::IfcGlobalId() {
IfcParse::IfcGlobalId::IfcGlobalId(Logger& logger) {
uuid_data_ = gen();
std::vector<unsigned char> v(uuid_data_.size());
std::copy(uuid_data_.begin(), uuid_data_.end(), v.begin());
@@ -111,12 +111,12 @@ IfcParse::IfcGlobalId::IfcGlobalId() {
boost::uuids::uuid test_uuid;
std::copy(test_vector.begin(), test_vector.end(), test_uuid.begin());
if (uuid_data_ != test_uuid) {
Logger::Root().Message(Logger::LOG_ERROR, "SYS", 34, "Internal error generating GlobalId");
logger.Message(Logger::LOG_ERROR, "SYS", 34, "Internal error generating GlobalId");
}
#endif
}
IfcParse::IfcGlobalId::IfcGlobalId(const std::string& string)
IfcParse::IfcGlobalId::IfcGlobalId(const std::string& string, Logger& logger)
: string_data_(string) {
std::vector<unsigned char> result;
expand(string_data_, result);
@@ -130,7 +130,7 @@ IfcParse::IfcGlobalId::IfcGlobalId(const std::string& string)
#ifndef NDEBUG
const std::string test_string = compress(&uuid_data_.data[0]);
if (string_data_ != test_string) {
Logger::Root().Message(Logger::LOG_ERROR, "SYS", 35, "Internal error generating GlobalId");
logger.Message(Logger::LOG_ERROR, "SYS", 35, "Internal error generating GlobalId");
}
#endif
}
+3 -2
View File
@@ -21,6 +21,7 @@
#define IFCGLOBALID_H
#include "ifc_parse_api.h"
#include "IfcLogger.h"
#include <boost/uuid/uuid.hpp>
#include <string>
@@ -36,8 +37,8 @@ class IFC_PARSE_API IfcGlobalId {
public:
static const unsigned int length = 22;
IfcGlobalId();
IfcGlobalId(const std::string&);
IfcGlobalId(Logger& logger = Logger::Root());
IfcGlobalId(const std::string&, Logger& logger = Logger::Root());
operator const std::string&() const;
operator const boost::uuids::uuid&() const;
const std::string& formatted() const;
+5 -5
View File
@@ -129,7 +129,7 @@ typename Schema::IfcProject* IfcHierarchyHelper<Schema>::addProject(typename Sch
typename Schema::IfcUnitAssignment* unit_assignment = new typename Schema::IfcUnitAssignment(units);
typename Schema::IfcProject* project = new typename Schema::IfcProject(IfcParse::IfcGlobalId(),
typename Schema::IfcProject* project = new typename Schema::IfcProject(IfcParse::IfcGlobalId(this->logger()),
owner_hist,
boost::none,
boost::none,
@@ -159,7 +159,7 @@ void IfcHierarchyHelper<Schema>::relatePlacements(typename Schema::IfcProduct* p
if (local_place != parent->ObjectPlacement()) {
local_place->setPlacementRelTo(parent->ObjectPlacement());
} else {
Logger::Root().Notice("SYN", 8, "Placement cannot be relative to self");
this->logger().Notice("SYN", 8, "Placement cannot be relative to self");
}
}
}
@@ -180,7 +180,7 @@ typename Schema::IfcSite* IfcHierarchyHelper<Schema>::addSite(typename Schema::I
proj = addProject(owner_hist);
}
typename Schema::IfcSite* site = new typename Schema::IfcSite(IfcParse::IfcGlobalId(),
typename Schema::IfcSite* site = new typename Schema::IfcSite(IfcParse::IfcGlobalId(this->logger()),
owner_hist,
boost::none,
boost::none,
@@ -214,7 +214,7 @@ typename Schema::IfcBuilding* IfcHierarchyHelper<Schema>::addBuilding(typename S
if (!site) {
site = addSite(0, owner_hist);
}
typename Schema::IfcBuilding* building = new typename Schema::IfcBuilding(IfcParse::IfcGlobalId(),
typename Schema::IfcBuilding* building = new typename Schema::IfcBuilding(IfcParse::IfcGlobalId(this->logger()),
owner_hist,
boost::none,
boost::none,
@@ -249,7 +249,7 @@ typename Schema::IfcBuildingStorey* IfcHierarchyHelper<Schema>::addBuildingStore
if (!building) {
building = addBuilding(0, owner_hist);
}
typename Schema::IfcBuildingStorey* storey = new typename Schema::IfcBuildingStorey(IfcParse::IfcGlobalId(),
typename Schema::IfcBuildingStorey* storey = new typename Schema::IfcBuildingStorey(IfcParse::IfcGlobalId(this->logger()),
owner_hist,
boost::none,
boost::none,
+5 -5
View File
@@ -362,7 +362,7 @@ void set_children_of_relation(IfcUtil::IfcBaseClass* t, aggregate_of_instance::p
template <typename Schema>
class IFC_PARSE_API IfcHierarchyHelper : public IfcParse::IfcFile {
public:
IfcHierarchyHelper() : IfcParse::IfcFile(&Schema::get_schema()) {}
IfcHierarchyHelper(Logger& logger = Logger::Root()) : IfcParse::IfcFile(&Schema::get_schema(), IfcParse::FT_AUTODETECT, "", logger) {}
template <class T>
T* addTriplet(double x, double y, double z) {
@@ -436,7 +436,7 @@ class IFC_PARSE_API IfcHierarchyHelper : public IfcParse::IfcFile {
}
typename Schema::IfcObject::list::ptr related_objects(new aggregate_of<typename Schema::IfcObject>());
related_objects->push(related_object->template as<typename Schema::IfcObject>());
typename Schema::IfcRelDefinesByType* t = new typename Schema::IfcRelDefinesByType(IfcParse::IfcGlobalId(), owner_hist, boost::none, boost::none, related_objects, relating_object->template as<typename Schema::IfcTypeObject>());
typename Schema::IfcRelDefinesByType* t = new typename Schema::IfcRelDefinesByType(IfcParse::IfcGlobalId(this->logger()), owner_hist, boost::none, boost::none, related_objects, relating_object->template as<typename Schema::IfcTypeObject>());
addEntity(t);
}
@@ -454,9 +454,9 @@ class IFC_PARSE_API IfcHierarchyHelper : public IfcParse::IfcFile {
break;
}
} catch (std::exception& e) {
Logger::Root().Error("SYN", 9, e);
this->logger().Error("SYN", 9, e);
} catch (...) {
Logger::Root().Error("SYN", 10, "Unknown error in addRelatedObject()");
this->logger().Error("SYN", 10, "Unknown error in addRelatedObject()");
}
}
if (!found) {
@@ -471,7 +471,7 @@ class IFC_PARSE_API IfcHierarchyHelper : public IfcParse::IfcFile {
related_objects->push(related_object);
T* t = create(&T::Class())->template as<T>();
t->set_attribute_value(0, (std::string)IfcParse::IfcGlobalId());
t->set_attribute_value(0, (std::string)IfcParse::IfcGlobalId(this->logger()));
t->set_attribute_value(1, owner_hist);
int relating_index = 4;
int related_index = 5;
+42 -10
View File
@@ -32,8 +32,6 @@
#include <iomanip>
#include <iostream>
static my_thread_local std::map<const Logger*, const IfcUtil::IfcBaseClass*> current_products_;
namespace {
std::string get_time(bool with_milliseconds = false) {
@@ -139,16 +137,11 @@ Logger& Logger::Root() {
}
const IfcUtil::IfcBaseClass* Logger::current_product() const {
auto it = current_products_.find(this);
return it == current_products_.end() ? nullptr : it->second;
return current_product_;
}
void Logger::current_product(const IfcUtil::IfcBaseClass* product) {
if (product) {
current_products_[this] = product;
} else {
current_products_.erase(this);
}
current_product_ = product;
}
void Logger::SetProduct(boost::optional<const IfcUtil::IfcBaseClass*> product) {
@@ -206,7 +199,7 @@ void Logger::Message(Logger::Severity type, const char (&code_prefix)[4], uint16
}
if (format_ == FMT_INMEMORY) {
log_messages_.emplace_back(type, code_prefix, code_number, message, instance);
log_messages_.emplace_back(type, code_prefix, code_number, message, instance, current_product());
} else if (((log2_ != nullptr) || (wlog2_ != nullptr))) {
if (format_ == FMT_PLAIN) {
if (log2_ != nullptr) {
@@ -251,9 +244,48 @@ void Logger::ProgressBar(int progress) {
}
std::string Logger::GetLog() {
std::lock_guard<std::mutex> lock(mutex_);
return log_stream_.str();
}
void Logger::ClearLog() {
std::lock_guard<std::mutex> lock(mutex_);
log_stream_.str(std::string());
log_stream_.clear();
log_messages_.clear();
}
void Logger::Append(Logger& logger) {
if (&logger == this) {
return;
}
std::scoped_lock lock(mutex_, logger.mutex_);
if (logger.max_severity_ > max_severity_) {
max_severity_ = logger.max_severity_;
}
if (format_ == FMT_INMEMORY) {
log_messages_.insert(log_messages_.end(), logger.log_messages_.begin(), logger.log_messages_.end());
} else {
const std::string log = logger.log_stream_.str();
if (!log.empty()) {
if (log2_ != nullptr) {
*log2_ << log;
} else if (wlog2_ != nullptr) {
*wlog2_ << string_as<wchar_t>(log);
} else {
log_stream_ << log;
}
}
}
logger.log_stream_.str(std::string());
logger.log_stream_.clear();
logger.log_messages_.clear();
}
void Logger::PrintPerformanceStats() {
std::vector<std::pair<double, std::string>> items;
for (auto& stat : performance_statistics_) {
+12 -2
View File
@@ -31,14 +31,15 @@
#include <mutex>
#include <sstream>
#include <string>
#include <vector>
class IFC_PARSE_API log_message {
public:
char code[7];
int severity;
std::string message, instance;
std::string message, instance, product;
log_message(int severity, const char (&code_prefix)[4], uint16_t code_number, const std::string& message, const IfcUtil::IfcBaseInterface* inst = 0)
log_message(int severity, const char (&code_prefix)[4], uint16_t code_number, const std::string& message, const IfcUtil::IfcBaseInterface* inst = 0, const IfcUtil::IfcBaseClass* current_product = 0)
: severity(severity)
, message(message)
{
@@ -48,6 +49,11 @@ class IFC_PARSE_API log_message {
inst->data().toString(nullptr, nullptr, 0, oss, true);
instance = oss.str();
}
if (current_product) {
std::ostringstream oss;
current_product->toString(oss);
product = oss.str();
}
}
};
@@ -79,6 +85,7 @@ class IFC_PARSE_API Logger {
std::wostream* wlog2_ = nullptr;
std::stringstream log_stream_;
const IfcUtil::IfcBaseClass* current_product_ = nullptr;
Severity verbosity_ = LOG_NOTICE;
Format format_ = FMT_PLAIN;
@@ -134,8 +141,11 @@ class IFC_PARSE_API Logger {
void ProgressBar(int progress);
std::string GetLog();
void ClearLog();
void Append(Logger& logger);
void PrintPerformanceStats();
void PrintPerformanceStatsOnElement(bool b) { print_perf_stats_on_element_ = b; }
bool PrintPerformanceStatsOnElement() const { return print_perf_stats_on_element_; }
const std::vector<log_message>& log_messages() const { return log_messages_; }
};
+94 -63
View File
@@ -102,9 +102,11 @@ void init_locale() {
#endif
IfcSpfLexer::IfcSpfLexer(IfcParse::FileReader* stream_) {
IfcSpfLexer::IfcSpfLexer(IfcParse::FileReader* stream_, Logger& logger)
: logger_(logger)
{
stream = stream_;
decoder_ = new IfcCharacterDecoder(stream_);
decoder_ = new IfcCharacterDecoder(stream_, logger_);
}
IfcSpfLexer::~IfcSpfLexer() {
@@ -320,7 +322,7 @@ Token IfcParse::GeneralTokenPtr(IfcSpfLexer* lexer, size_t start, const std::str
if (first == '#') {
token.type = Token_IDENTIFIER;
if (!ParseInt(tokenStr.c_str() + 1, token.value_int)) {
Logger::Root().Message(Logger::LOG_ERROR, "SYN", 11, "Token '" + tokenStr + "' at offset " + std::to_string(token.startPos) + " is not valid");
lexer->logger().Message(Logger::LOG_ERROR, "SYN", 11, "Token '" + tokenStr + "' at offset " + std::to_string(token.startPos) + " is not valid");
token.type = Token_OPERATOR;
token.value_char = '$';
}
@@ -562,13 +564,13 @@ void IfcParse::impl::in_memory_file_storage::load(boost::optional<size_t> entity
// type) and to be able to actually register the references in
// the 2nd pass.
load(entity_instance_name, entity, ps, attribute_index == -1 ? (int)attribute_index_within_data : attribute_index);
auto* simple_type_instance = (schema ? schema : file->schema())->instantiate(decl, ps.construct(entity_instance_name, *references_to_resolve, decl, boost::none, attribute_index == -1 ? (int)attribute_index_within_data : attribute_index));
auto* simple_type_instance = (schema ? schema : file->schema())->instantiate(decl, ps.construct(entity_instance_name, *references_to_resolve, decl, boost::none, attribute_index == -1 ? (int)attribute_index_within_data : attribute_index, logger()));
read_simple_type_instances.emplace_back(simple_type_instance);
//@todo decide addEntity(((IfcUtil::IfcBaseClass*)*entity));
context.push(simple_type_instance);
simple_type_instance->file_ = file;
} catch (IfcException& e) {
Logger::Root().Message(Logger::LOG_ERROR, "SYN", 12, std::string(e.what()) + " at offset " + std::to_string(next.startPos));
logger().Message(Logger::LOG_ERROR, "SYN", 12, std::string(e.what()) + " at offset " + std::to_string(next.startPos));
// #4070 We didn't actually capture an aggregate entry, undo length increment.
return_value--;
}
@@ -592,7 +594,7 @@ IfcEntityInstanceData IfcParse::impl::in_memory_file_storage::read(unsigned int
parse_context pc;
tokens->Next();
load(i, ty->as_entity(), pc, -1);
return IfcEntityInstanceData(pc.construct(i, *references_to_resolve, ty, boost::none, -1));
return IfcEntityInstanceData(pc.construct(i, *references_to_resolve, ty, boost::none, -1, logger()));
}
void IfcParse::impl::in_memory_file_storage::try_read_semicolon() const {
@@ -663,7 +665,7 @@ void IfcParse::impl::rocks_db_file_storage::unregister_inverse(unsigned id_from,
if (it != vals.end()) {
vals.erase(it);
} else {
Logger::Root().Error("VAL", 17, "Unregistering non-existant inverse #" + std::to_string(id_from) + " on instance #" + std::to_string(inst_id) + " at attribute " + std::to_string(attribute_index));
file->logger().Error("VAL", 17, "Unregistering non-existant inverse #" + std::to_string(id_from) + " on instance #" + std::to_string(inst_id) + " at attribute " + std::to_string(attribute_index));
}
s.resize(vals.size() * sizeof(uint32_t));
memcpy(s.data(), vals.data(), s.size());
@@ -1122,7 +1124,7 @@ IfcUtil::IfcBaseClass::set_attribute_value(size_t i, const T& t) {
}
}
} catch (IfcParse::IfcException& e) {
Logger::Root().Error("SYN", 13, e);
file_->logger().Error("SYN", 13, e);
}
}
@@ -1159,11 +1161,11 @@ IfcUtil::IfcBaseClass::set_attribute_value(size_t i, const T& t) {
auto guid = (std::string) new_attribute;
auto it = file_->internal_guid_map().find(guid);
if (it != file_->internal_guid_map().end()) {
Logger::Root().Warning("VAL", 18, "Duplicate guid " + guid);
file_->logger().Warning("VAL", 18, "Duplicate guid " + guid);
}
file_->internal_guid_map().insert({ guid, this });
} catch (IfcParse::IfcException& e) {
Logger::Root().Error("SYN", 14, e);
file_->logger().Error("SYN", 14, e);
}
}
}
@@ -1182,7 +1184,13 @@ IfcUtil::IfcBaseClass::set_attribute_value(const std::string& s, const T& t) {
// Creates the maps
//
#ifdef USE_MMAP
IfcFile::IfcFile(const std::string& fn, bool mmap) {
IfcFile::IfcFile(const std::string& fn, bool mmap, Logger& logger)
: logger_(logger)
, schema_(nullptr)
, ifcroot_type_(nullptr)
, max_id_(0)
, _header(this, logger)
{
initialize(fn, mmap);
}
@@ -1194,7 +1202,7 @@ bool IfcParse::IfcFile::initialize(const std::string& fn, bool mmap) {
s = std::make_unique<FileReader>(fn);
}
storage_.emplace<1>(this);
storage_.emplace<1>(this, logger_.get());
std::get<impl::in_memory_file_storage>(storage_).read_from_stream(&*s, schema_, max_id_, types_to_bypass_loading_);
if ((good_ = std::get<impl::in_memory_file_storage>(storage_).good_)) {
@@ -1209,8 +1217,8 @@ bool IfcParse::IfcFile::initialize(const std::string& fn, bool mmap) {
}
#endif
IfcFile::IfcFile(const uninitialized_tag&)
: schema_(nullptr), max_id_(0), _header(this), good_(file_open_status::UNKNOWN), ifcroot_type_(nullptr) {}
IfcFile::IfcFile(const uninitialized_tag&, Logger& logger)
: logger_(logger), schema_(nullptr), ifcroot_type_(nullptr), max_id_(0), _header(this, logger), good_(file_open_status::UNKNOWN) {}
bool IfcParse::IfcFile::initialize(const std::string& path, filetype ty, bool readonly) {
if (ty == FT_AUTODETECT) {
@@ -1218,7 +1226,7 @@ bool IfcParse::IfcFile::initialize(const std::string& path, filetype ty, bool re
}
if (ty == FT_IFCSPF) {
FileReader s(path);
storage_.emplace<1>(this);
storage_.emplace<1>(this, logger_.get());
std::get<impl::in_memory_file_storage>(storage_).read_from_stream(&s, schema_, max_id_, types_to_bypass_loading_);
if ((good_ = std::get<impl::in_memory_file_storage>(storage_).good_)) {
@@ -1261,17 +1269,22 @@ void IfcParse::IfcFile::bypass_type(const std::string& type_name) {
types_to_bypass_loading_.insert(type_name);
}
IfcFile::IfcFile(const std::string& path, filetype ty, bool readonly)
: schema_(nullptr)
IfcFile::IfcFile(const std::string& path, filetype ty, bool readonly, Logger& logger)
: logger_(logger)
, schema_(nullptr)
, ifcroot_type_(nullptr)
, max_id_(0)
, _header(this)
, _header(this, logger)
{
initialize(path, ty, readonly);
}
IfcFile::IfcFile(std::istream& stream, int length)
: schema_(nullptr)
IfcFile::IfcFile(std::istream& stream, int length, Logger& logger)
: logger_(logger)
, schema_(nullptr)
, ifcroot_type_(nullptr)
, max_id_(0)
, _header(this, logger)
{
FileReader s(FileReader::caller_fed_tag{});
@@ -1280,7 +1293,7 @@ IfcFile::IfcFile(std::istream& stream, int length)
stream.read(string_data.data(), length);
s.pushNextPage(string_data);
storage_.emplace<1>(this);
storage_.emplace<1>(this, logger_.get());
std::get<impl::in_memory_file_storage>(storage_).read_from_stream(&s, schema_, max_id_, types_to_bypass_loading_);
good_ = std::get<impl::in_memory_file_storage>(storage_).good_;
ifcroot_type_ = schema_ ? schema_->declaration_by_name("IfcRoot") : nullptr;
@@ -1290,13 +1303,16 @@ IfcFile::IfcFile(std::istream& stream, int length)
byguid_ = decltype(byguid_)(&std::get<impl::in_memory_file_storage>(storage_).byguid_);
}
IfcFile::IfcFile(void* data, int length)
: schema_(nullptr)
IfcFile::IfcFile(void* data, int length, Logger& logger)
: logger_(logger)
, schema_(nullptr)
, ifcroot_type_(nullptr)
, max_id_(0)
, _header(this, logger)
{
FileReader s(std::string((char*)data, length), FileReader::caller_fed_tag{});
storage_.emplace<1>(this);
storage_.emplace<1>(this, logger_.get());
std::get<impl::in_memory_file_storage>(storage_).read_from_stream(&s, schema_, max_id_, types_to_bypass_loading_);
good_ = std::get<impl::in_memory_file_storage>(storage_).good_;
ifcroot_type_ = schema_ ? schema_->declaration_by_name("IfcRoot") : nullptr;
@@ -1306,11 +1322,14 @@ IfcFile::IfcFile(void* data, int length)
byguid_ = decltype(byguid_)(&std::get<impl::in_memory_file_storage>(storage_).byguid_);
}
IfcFile::IfcFile(IfcParse::FileReader* s)
: schema_(nullptr)
IfcFile::IfcFile(IfcParse::FileReader* s, Logger& logger)
: logger_(logger)
, schema_(nullptr)
, ifcroot_type_(nullptr)
, max_id_(0)
, _header(this, logger)
{
storage_.emplace<1>(this);
storage_.emplace<1>(this, logger_.get());
std::get<impl::in_memory_file_storage>(storage_).read_from_stream(s, schema_, max_id_, types_to_bypass_loading_);
good_ = std::get<impl::in_memory_file_storage>(storage_).good_;
ifcroot_type_ = schema_ ? schema_->declaration_by_name("IfcRoot") : nullptr;
@@ -1320,16 +1339,18 @@ IfcFile::IfcFile(IfcParse::FileReader* s)
byguid_ = decltype(byguid_)(&std::get<impl::in_memory_file_storage>(storage_).byguid_);
}
IfcFile::IfcFile(const IfcParse::schema_definition* schema, filetype ty, const std::string& path)
: schema_(schema)
IfcFile::IfcFile(const IfcParse::schema_definition* schema, filetype ty, const std::string& path, Logger& logger)
: logger_(logger)
, schema_(schema)
, ifcroot_type_(schema_->declaration_by_name("IfcRoot"))
, max_id_(0)
, _header(this, logger)
{
if (ty == FT_AUTODETECT) {
ty = guess_file_type(path);
}
if (ty == FT_IFCSPF) {
storage_.emplace<1>(this);
storage_.emplace<1>(this, logger_.get());
byid_ = decltype(byid_)(&std::get<impl::in_memory_file_storage>(storage_).byid_);
byref_excl_ = decltype(byref_excl_)(&std::get<impl::in_memory_file_storage>(storage_).byref_excl_);
@@ -1347,13 +1368,12 @@ IfcFile::IfcFile(const IfcParse::schema_definition* schema, filetype ty, const s
} else {
throw std::runtime_error("Unsupported file format");
}
_header = IfcSpfHeader(this);
setDefaultHeaderValues();
}
bool IfcParse::InstanceStreamer::hasSemicolon() const {
auto local_stream = stream_->clone();
auto local_lexer = IfcSpfLexer(&local_stream);
auto local_lexer = IfcSpfLexer(&local_stream, logger_.get());
Token t;
try {
t = local_lexer.Next();
@@ -1376,7 +1396,7 @@ bool IfcParse::InstanceStreamer::hasSemicolon() const {
size_t IfcParse::InstanceStreamer::semicolonCount() const {
auto local_stream = stream_->clone();
auto local_lexer = IfcSpfLexer(&local_stream);
auto local_lexer = IfcSpfLexer(&local_stream, logger_.get());
Token t;
size_t count = 0;
try {
@@ -1402,7 +1422,7 @@ void IfcParse::InstanceStreamer::pushPage(const std::string& page)
{
stream_->pushNextPage(page);
if (good_ == file_open_status::NO_HEADER) {
header_ = new IfcParse::IfcSpfHeader(lexer_);
header_ = new IfcParse::IfcSpfHeader(lexer_, logger_.get());
if (header_->tryRead() && header_->file_schema()->schema_identifiers().size() == 1) {
try {
schema_ = IfcParse::schema_by_name(header_->file_schema()->schema_identifiers().front());
@@ -1417,29 +1437,35 @@ void IfcParse::InstanceStreamer::pushPage(const std::string& page)
}
}
IfcParse::InstanceStreamer::InstanceStreamer()
IfcParse::InstanceStreamer::InstanceStreamer(Logger& logger)
: stream_(new FileReader(FileReader::caller_fed_tag{}))
, lexer_(new IfcSpfLexer(stream_))
, lexer_(new IfcSpfLexer(stream_, logger))
, header_(nullptr)
, token_stream_(3, Token{})
, schema_(nullptr)
, storage_(nullptr, logger)
, logger_(logger)
, progress_(0)
{
init_locale();
good_ = file_open_status::NO_HEADER;
}
IfcParse::InstanceStreamer::InstanceStreamer(const std::string& fn, bool mmap)
IfcParse::InstanceStreamer::InstanceStreamer(const std::string& fn, bool mmap, Logger& logger)
: stream_(mmap ? new FileReader(fn, FileReader::mmap_tag{}) : new FileReader(fn))
, lexer_(new IfcSpfLexer(stream_))
, lexer_(new IfcSpfLexer(stream_, logger))
, header_(nullptr)
, token_stream_(3, Token{})
, schema_(nullptr)
, storage_(nullptr, logger)
, logger_(logger)
, progress_(0)
{
init_locale();
good_ = file_open_status::NO_HEADER;
if (stream_->size() && !stream_->eof()) {
header_ = new IfcParse::IfcSpfHeader(lexer_);
header_ = new IfcParse::IfcSpfHeader(lexer_, logger_.get());
if (header_->tryRead() && header_->file_schema()->schema_identifiers().size() == 1) {
try {
schema_ = IfcParse::schema_by_name(header_->file_schema()->schema_identifiers().front());
@@ -1454,18 +1480,21 @@ IfcParse::InstanceStreamer::InstanceStreamer(const std::string& fn, bool mmap)
}
}
IfcParse::InstanceStreamer::InstanceStreamer(void* data, int length)
IfcParse::InstanceStreamer::InstanceStreamer(void* data, int length, Logger& logger)
: stream_(new FileReader(std::string((char*) data, length), FileReader::caller_fed_tag{}))
, lexer_(new IfcSpfLexer(stream_))
, lexer_(new IfcSpfLexer(stream_, logger))
, header_(nullptr)
, token_stream_(3, Token{})
, schema_(nullptr)
, storage_(nullptr, logger)
, logger_(logger)
, progress_(0)
{
init_locale();
good_ = file_open_status::NO_HEADER;
if (stream_->size() && !stream_->eof()) {
header_ = new IfcParse::IfcSpfHeader(lexer_);
header_ = new IfcParse::IfcSpfHeader(lexer_, logger_.get());
if (header_->tryRead() && header_->file_schema()->schema_identifiers().size() == 1) {
try {
schema_ = IfcParse::schema_by_name(header_->file_schema()->schema_identifiers().front());
@@ -1480,12 +1509,14 @@ IfcParse::InstanceStreamer::InstanceStreamer(void* data, int length)
}
}
IfcParse::InstanceStreamer::InstanceStreamer(const IfcParse::schema_definition* schema, IfcParse::IfcSpfLexer* lexer)
IfcParse::InstanceStreamer::InstanceStreamer(const IfcParse::schema_definition* schema, IfcParse::IfcSpfLexer* lexer, Logger& logger)
: stream_(nullptr)
, lexer_(lexer)
, header_(nullptr)
, token_stream_(3, Token{})
, schema_(schema)
, storage_(nullptr, logger)
, logger_(logger)
, progress_(0)
{
init_locale();
@@ -1509,7 +1540,7 @@ void IfcParse::impl::in_memory_file_storage::read_from_stream(IfcParse::FileRead
return;
}
tokens = new IfcSpfLexer(s);
tokens = new IfcSpfLexer(s, logger());
std::vector<std::string> schemas;
@@ -1531,21 +1562,21 @@ void IfcParse::impl::in_memory_file_storage::read_from_stream(IfcParse::FileRead
schema = IfcParse::schema_by_name(schemas.front());
} catch (const IfcParse::IfcException& e) {
good_ = file_open_status::UNSUPPORTED_SCHEMA;
Logger::Root().Error("SYN", 15, e);
logger().Error("SYN", 15, e);
}
}
if (schema == nullptr) {
Logger::Root().Message(Logger::LOG_ERROR, "UNS", 32, "No support for file schema encountered (" + boost::algorithm::join(schemas, ", ") + ")");
logger().Message(Logger::LOG_ERROR, "UNS", 32, "No support for file schema encountered (" + boost::algorithm::join(schemas, ", ") + ")");
return;
}
auto ifcroot_type_ = schema->declaration_by_name("IfcRoot");
InstanceStreamer streamer(schema, tokens);
InstanceStreamer streamer(schema, tokens, logger());
streamer.bypassTypes(typed_to_bypass);
Logger::Root().Status("Scanning file...");
logger().Status("Scanning file...");
while (streamer) {
@@ -1569,11 +1600,11 @@ void IfcParse::impl::in_memory_file_storage::read_from_stream(IfcParse::FileRead
if (byguid_.find(guid) != byguid_.end()) {
std::stringstream ss;
ss << "Instance encountered with non-unique GlobalId " << guid;
Logger::Root().Message(Logger::LOG_WARNING, "SYN", 16, ss.str());
logger().Message(Logger::LOG_WARNING, "SYN", 16, ss.str());
}
byguid_[guid] = instance;
} catch (const IfcException& ex) {
Logger::Root().Message(Logger::LOG_ERROR, "SYN", 17, ex.what());
logger().Message(Logger::LOG_ERROR, "SYN", 17, ex.what());
}
}
@@ -1589,7 +1620,7 @@ void IfcParse::impl::in_memory_file_storage::read_from_stream(IfcParse::FileRead
if (byid_.find(current_id) != byid_.end()) {
std::stringstream ss;
ss << "Overwriting instance with name #" << current_id;
Logger::Root().Message(Logger::LOG_WARNING, "SYN", 18, ss.str());
logger().Message(Logger::LOG_WARNING, "SYN", 18, ss.str());
}
// byidentity_[instance->identity()] = instance;
@@ -1612,7 +1643,7 @@ void IfcParse::impl::in_memory_file_storage::read_from_stream(IfcParse::FileRead
inst->file_ = file;
}
Logger::Root().Status("\rDone scanning file ");
logger().Status("\rDone scanning file ");
delete tokens;
@@ -1632,7 +1663,7 @@ void IfcParse::impl::in_memory_file_storage::read_from_stream(IfcParse::FileRead
}
auto it = byid_.find(*name);
if (it == byid_.end()) {
Logger::Root().Error("SYN", 19, "Instance reference #" + std::to_string(*name) + " used by instance #" + std::to_string(ref) + " at attribute index " + std::to_string(refattr) + " not found at offset " + std::to_string(name->file_offset));
logger().Error("SYN", 19, "Instance reference #" + std::to_string(*name) + " used by instance #" + std::to_string(ref) + " at attribute index " + std::to_string(refattr) + " not found at offset " + std::to_string(name->file_offset));
} else {
auto* storage = &byid_[p.first.name_]->data();
auto attr_index = p.first.index_;
@@ -1649,7 +1680,7 @@ void IfcParse::impl::in_memory_file_storage::read_from_stream(IfcParse::FileRead
if (storage->has_attribute_value<Blank>(nullptr, nullptr, 0, attr_index)) {
storage->set_attribute_value(nullptr, nullptr, 0, attr_index, it->second);
} else {
Logger::Root().Error("SYN", 20, "Duplicate definition for instance reference");
logger().Error("SYN", 20, "Duplicate definition for instance reference");
}
}
} else if (auto* inst = std::get_if<IfcUtil::IfcBaseClass*>(v)) {
@@ -1665,7 +1696,7 @@ void IfcParse::impl::in_memory_file_storage::read_from_stream(IfcParse::FileRead
}
auto it = byid_.find(*name);
if (it == byid_.end()) {
Logger::Root().Error("SYN", 21, "Instance reference #" + std::to_string(*name) + " used by instance #" + std::to_string(ref) + " at attribute index " + std::to_string(refattr) + " not found at offset " + std::to_string(name->file_offset));
logger().Error("SYN", 21, "Instance reference #" + std::to_string(*name) + " used by instance #" + std::to_string(ref) + " at attribute index " + std::to_string(refattr) + " not found at offset " + std::to_string(name->file_offset));
} else {
instances->push(it->second);
}
@@ -1689,7 +1720,7 @@ void IfcParse::impl::in_memory_file_storage::read_from_stream(IfcParse::FileRead
if (storage->has_attribute_value<Blank>(nullptr, nullptr, 0, attr_index)) {
storage->set_attribute_value(nullptr, nullptr, 0, attr_index, instances);
} else {
Logger::Root().Error("SYN", 22, "Duplicate definition for instance reference");
logger().Error("SYN", 22, "Duplicate definition for instance reference");
}
} else if (auto* vvv = std::get_if<std::vector<std::vector<reference_or_simple_type>>>(&p.second)) {
aggregate_of_aggregate_of_instance::ptr instances(new aggregate_of_aggregate_of_instance);
@@ -1702,7 +1733,7 @@ void IfcParse::impl::in_memory_file_storage::read_from_stream(IfcParse::FileRead
}
auto it = byid_.find(*name);
if (it == byid_.end()) {
Logger::Root().Error("SYN", 23, "Instance reference #" + std::to_string(*name) + " used by instance #" + std::to_string(ref) + " at attribute index " + std::to_string(refattr) + " not found at offset " + std::to_string(name->file_offset));
logger().Error("SYN", 23, "Instance reference #" + std::to_string(*name) + " used by instance #" + std::to_string(ref) + " at attribute index " + std::to_string(refattr) + " not found at offset " + std::to_string(name->file_offset));
} else {
inner.push_back(it->second);
}
@@ -1728,12 +1759,12 @@ void IfcParse::impl::in_memory_file_storage::read_from_stream(IfcParse::FileRead
if (storage->has_attribute_value<Blank>(nullptr, nullptr, 0, attr_index)) {
storage->set_attribute_value(nullptr, nullptr, 0, attr_index, instances);
} else {
Logger::Root().Error("SYN", 24, "Duplicate definition for instance reference");
logger().Error("SYN", 24, "Duplicate definition for instance reference");
}
}
}
Logger::Root().Status("Done resolving references");
logger().Status("Done resolving references");
}
void IfcFile::recalculate_id_counter() {
@@ -1893,7 +1924,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id)
}
}
} catch (...) {
Logger::Root().Message(Logger::LOG_ERROR, "SYN", 25, "Failed to visit forward references of", entity);
logger().Message(Logger::LOG_ERROR, "SYN", 25, "Failed to visit forward references of", entity);
}
// See whether the instance is already part of a file
@@ -2066,11 +2097,11 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id)
if (byguid_.find(guid) != byguid_.end()) {
std::stringstream ss;
ss << "Overwriting entity with guid " << guid;
Logger::Root().Message(Logger::LOG_WARNING, "SYN", 26, ss.str());
logger().Message(Logger::LOG_WARNING, "SYN", 26, ss.str());
}
byguid_.insert({ guid, new_entity });
} catch (const std::exception& ex) {
Logger::Root().Message(Logger::LOG_ERROR, "SYN", 27, ex.what());
logger().Message(Logger::LOG_ERROR, "SYN", 27, ex.what());
}
}
@@ -2243,7 +2274,7 @@ void IfcFile::process_deletion_(IfcUtil::IfcBaseClass* entity) {
if (it != byguid_.end()) {
byguid_.erase(it);
} else {
Logger::Root().Warning("VAL", 19, "GlobalId on rooted instance not encountered in map");
logger().Warning("VAL", 19, "GlobalId on rooted instance not encountered in map");
}
}
+3 -1
View File
@@ -110,6 +110,7 @@ Token GeneralTokenPtr(IfcSpfLexer* tokens, size_t start, const std::string& data
class IFC_PARSE_API IfcSpfLexer {
private:
IfcCharacterDecoder* decoder_;
Logger& logger_;
size_t skipWhitespace() const;
size_t skipComment() const;
@@ -120,7 +121,8 @@ class IFC_PARSE_API IfcSpfLexer {
}
FileReader* stream;
// IfcFile* file;
IfcSpfLexer(FileReader* stream);
IfcSpfLexer(FileReader* stream, Logger& logger = Logger::Root());
Logger& logger() const { return logger_; }
Token Next();
~IfcSpfLexer();
void TokenString(size_t offset, std::string& result);
+16 -9
View File
@@ -30,12 +30,12 @@ static const char* const DATA = "DATA";
using namespace IfcParse;
namespace {
IfcEntityInstanceData read_from_spf_file(IfcParse::impl::in_memory_file_storage* storage, const IfcParse::entity* decl) {
IfcEntityInstanceData read_from_spf_file(IfcParse::impl::in_memory_file_storage* storage, const IfcParse::entity* decl, Logger& logger) {
if (storage != nullptr) {
parse_context pc;
storage->tokens->Next();
storage->load(-1, nullptr, pc, -1);
return pc.construct(boost::none, *storage->references_to_resolve, decl, decl->as_entity()->attribute_count(), -1);
return pc.construct(boost::none, *storage->references_to_resolve, decl, decl->as_entity()->attribute_count(), -1, logger);
} else {
// std::unreachable();
return IfcEntityInstanceData(in_memory_attribute_storage(10));
@@ -66,14 +66,19 @@ void IfcSpfHeader::readTerminal(const std::string& term, Trail trail) {
}
}
IfcParse::IfcSpfHeader::IfcSpfHeader(IfcParse::IfcFile* file)
IfcParse::IfcSpfHeader::IfcSpfHeader(IfcParse::IfcFile* file, Logger& logger)
: file_(file),
logger_(logger),
file_description_(nullptr),
file_name_(nullptr),
file_schema_(nullptr)
{
Header_section_schema::get_schema();
if (file != nullptr) {
logger_ = file->logger();
}
if (file == nullptr) {
// overwritten later in IfcFile::setDefaultHeaderValues() when we know the schema identifier
file_description_ = new Header_section_schema::file_description({}, "");
@@ -101,11 +106,12 @@ IfcParse::IfcSpfHeader::IfcSpfHeader(IfcParse::IfcFile* file)
}
}
IfcParse::IfcSpfHeader::IfcSpfHeader(IfcParse::IfcSpfLexer* lexer)
IfcParse::IfcSpfHeader::IfcSpfHeader(IfcParse::IfcSpfLexer* lexer, Logger& logger)
: logger_(logger)
{
Header_section_schema::get_schema();
storage_ = new impl::in_memory_file_storage;
storage_ = new impl::in_memory_file_storage(nullptr, logger_.get());
storage_->tokens = lexer;
file_ = nullptr;
@@ -128,6 +134,7 @@ void IfcParse::IfcSpfHeader::file(IfcParse::IfcFile* file)
{
this->file_ = file;
if (file != nullptr) {
logger_ = file->logger();
storage_ = std::visit([this](auto& m) -> decltype(storage_) {
if constexpr (std::is_same_v<std::decay_t<decltype(m)>, impl::in_memory_file_storage>) {
return &m;
@@ -153,19 +160,19 @@ void IfcSpfHeader::read() {
readTerminal(Header_section_schema::file_description::Class().name_uc(), NONE);
delete file_description_;
file_description_ = new Header_section_schema::file_description(read_from_spf_file(storage_, &Header_section_schema::file_description::Class()));
file_description_ = new Header_section_schema::file_description(read_from_spf_file(storage_, &Header_section_schema::file_description::Class(), logger_.get()));
file_description_->file_ = file_;
readSemicolon();
readTerminal(Header_section_schema::file_name::Class().name_uc(), NONE);
delete file_name_;
file_name_ = new Header_section_schema::file_name(read_from_spf_file(storage_, &Header_section_schema::file_name::Class()));
file_name_ = new Header_section_schema::file_name(read_from_spf_file(storage_, &Header_section_schema::file_name::Class(), logger_.get()));
file_name_->file_ = file_;
readSemicolon();
readTerminal(Header_section_schema::file_schema::Class().name_uc(), NONE);
delete file_schema_;
file_schema_ = new Header_section_schema::file_schema(read_from_spf_file(storage_, &Header_section_schema::file_schema::Class()));
file_schema_ = new Header_section_schema::file_schema(read_from_spf_file(storage_, &Header_section_schema::file_schema::Class(), logger_.get()));
file_schema_->file_ = file_;
readSemicolon();
}
@@ -175,7 +182,7 @@ bool IfcSpfHeader::tryRead() {
read();
return true;
} catch (const std::exception& e) {
Logger::Root().Error("SYN", 28, e);
logger_.get().Error("SYN", 28, e);
return false;
}
}
+6 -2
View File
@@ -25,6 +25,8 @@
#include "Header_section_schema.h"
#include "storage.h"
#include <functional>
namespace IfcParse {
class IfcFile;
@@ -32,6 +34,7 @@ class IfcFile;
class IFC_PARSE_API IfcSpfHeader {
private:
IfcFile* file_;
std::reference_wrapper<Logger> logger_;
IfcParse::impl::in_memory_file_storage* storage_ = nullptr;
mutable Header_section_schema::file_description* file_description_;
@@ -45,13 +48,14 @@ class IFC_PARSE_API IfcSpfHeader {
void readTerminal(const std::string& term, Trail trail);
public:
explicit IfcSpfHeader(IfcParse::IfcFile* file = nullptr);
explicit IfcSpfHeader(IfcParse::IfcSpfLexer* lexer);
explicit IfcSpfHeader(IfcParse::IfcFile* file = nullptr, Logger& logger = Logger::Root());
explicit IfcSpfHeader(IfcParse::IfcSpfLexer* lexer, Logger& logger = Logger::Root());
~IfcSpfHeader();
IfcParse::IfcFile* file() { return file_; }
void file(IfcParse::IfcFile* file);
Logger& logger() const { return logger_.get(); }
void read();
bool tryRead();
+28 -23
View File
@@ -206,11 +206,18 @@ class stack_node {
};
struct ifcxml_parse_state {
explicit ifcxml_parse_state(Logger& logger)
: file(nullptr)
, dialect(ifcxml_dialect_unknown)
, logger(logger)
{}
IfcParse::IfcFile* file;
std::vector<stack_node> stack;
std::map<std::string, int> idmap;
std::vector<std::tuple<IfcUtil::IfcBaseEntity*, size_t, std::string>> forward_references;
ifcxml_dialect dialect;
Logger& logger;
};
// ifc4 allows for aggregates to be concatenated using whitespace.
@@ -227,7 +234,7 @@ std::vector<T> split(const std::string& value) {
return r;
}
boost::any parse_attribute_value(const IfcParse::parameter_type* ty, const std::string& value) {
boost::any parse_attribute_value(const IfcParse::parameter_type* ty, const std::string& value, Logger& logger) {
boost::any any;
auto cpp_type = IfcUtil::from_parameter_type(ty);
@@ -255,7 +262,7 @@ boost::any parse_attribute_value(const IfcParse::parameter_type* ty, const std::
}
if (any.empty()) {
Logger::Root().Error("SYN", 29, "Attribute '" + value + "' not successfully parsed");
logger.Error("SYN", 29, "Attribute '" + value + "' not successfully parsed");
}
return any;
@@ -293,7 +300,7 @@ static void end_element(void* user, const xmlChar* tag) {
// ignore uos ex:iso_10303_28 (ifc2x3) and ifc:ifcXML (ifc4)
if (tagname != "uos" && tagname != "ex:iso_10303_28" && tagname != "ifc:ifcXML" && tagname != "ifcXML") {
if (state->stack.empty()) {
Logger::Root().Error("SYN", 30, "Mismatch in parse stack due to previous errors");
state->logger.Error("SYN", 30, "Mismatch in parse stack due to previous errors");
} else {
state->stack.pop_back();
}
@@ -318,9 +325,9 @@ static void process_characters(void* user, const xmlChar* character, int len) {
const auto* pt = state->stack.back().inst()->declaration().as_type_declaration()->declared_type();
boost::any val;
try {
val = parse_attribute_value(pt, txt);
val = parse_attribute_value(pt, txt, state->logger);
} catch (const std::exception& e) {
Logger::Root().Error("SYN", 31, e, state->stack.back().inst());
state->logger.Error("SYN", 31, e, state->stack.back().inst());
}
if (!val.empty()) {
// type declaration always at idx 0
@@ -348,13 +355,13 @@ static void process_characters(void* user, const xmlChar* character, int len) {
} else if (tagname == "documentation") {
header.file_description()->setdescription({txt});
} else {
Logger::Root().Error("SYN", 32, "Unrecognized header entry " + tagname);
state->logger.Error("SYN", 32, "Unrecognized header entry " + tagname);
}
} else if (state_type == stack_node::node_instance_attribute) {
const auto* pt = state->stack.back().inst()->declaration().as_entity()->attribute_by_index(state->stack.back().idx())->type_of_attribute();
auto cpp_type = IfcUtil::from_parameter_type(pt);
if (cpp_type != IfcUtil::Argument_ENTITY_INSTANCE) {
auto val = parse_attribute_value(pt, txt);
auto val = parse_attribute_value(pt, txt, state->logger);
if (!val.empty()) {
visit_any([&state](auto& v) {
state->stack.back().inst()->set_attribute_value(state->stack.back().idx(), v);
@@ -363,7 +370,7 @@ static void process_characters(void* user, const xmlChar* character, int len) {
}
} else if (state_type == stack_node::node_aggregate_element) {
const auto* pt = state->stack.back().aggregate_elem_type();
auto val = parse_attribute_value(pt, txt);
auto val = parse_attribute_value(pt, txt, state->logger);
if (!val.empty()) {
(*(state->stack.rbegin() + 1)).aggregate_elements.push_back(val);
}
@@ -417,12 +424,12 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs)
if (it != end) {
std::string schema_name(&it->front(), it->size());
boost::to_upper(schema_name);
state->file = new IfcParse::IfcFile(IfcParse::schema_by_name(schema_name));
state->file = new IfcParse::IfcFile(IfcParse::schema_by_name(schema_name), IfcParse::FT_AUTODETECT, "", state->logger);
state->dialect = ifcxml_dialect_ifc4;
}
goto end;
} else if (tagname == "ex:iso_10303_28" && attrname == "xsi:schemaLocation" && boost::starts_with(value, "http://www.iai-tech.org/ifcXML/IFC2x3")) {
state->file = new IfcParse::IfcFile(IfcParse::schema_by_name("IFC2X3"));
state->file = new IfcParse::IfcFile(IfcParse::schema_by_name("IFC2X3"), IfcParse::FT_AUTODETECT, "", state->logger);
state->dialect = ifcxml_dialect_ifc2x3;
goto end;
}
@@ -491,14 +498,14 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs)
auto idx = entity->attribute_index(pair.first);
if (idx != -1) {
const auto* attr = entity->attribute_by_index(idx);
auto val = parse_attribute_value(attr->type_of_attribute(), pair.second);
auto val = parse_attribute_value(attr->type_of_attribute(), pair.second, state->logger);
if (!val.empty()) {
visit_any([&untyped, idx](auto& v) {
untyped.set_attribute_value(idx, v);
}, val);
}
} else {
Logger::Root().Error("SYN", 33, "Unknown attribute '" + pair.first + "' on entity '" + entity->name() + "' with value '" + pair.second + "'");
state->logger.Error("SYN", 33, "Unknown attribute '" + pair.first + "' on entity '" + entity->name() + "' with value '" + pair.second + "'");
}
}
}
@@ -556,7 +563,7 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs)
try {
decl = state->file->schema()->declaration_by_name(tagname_copy);
} catch (const std::exception& e) {
Logger::Root().Error("SYN", 34, e);
state->logger.Error("SYN", 34, e);
}
if (decl != nullptr) {
auto inst_or_ref = create_instance(decl);
@@ -571,7 +578,7 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs)
} else if (state_type == stack_node::node_instance) {
const IfcParse::entity* current = state->stack.back().inst()->declaration().as_entity();
if (current == nullptr) {
Logger::Root().Error("SYN", 35, "'" + state->stack.back().inst()->declaration().name() + "' is not an entity, unable to set attribute '" + tagname + "'");
state->logger.Error("SYN", 35, "'" + state->stack.back().inst()->declaration().name() + "' is not an entity, unable to set attribute '" + tagname + "'");
// We need to push something on the stack. Likely there has been some extra indirection that is not understood.
state->stack.push_back(state->stack.back());
} else {
@@ -582,7 +589,7 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs)
return attr->name() == tagname;
});
if (found == inverses.end()) {
Logger::Root().Error("SYN", 36, "Unknown attribute " + tagname);
state->logger.Error("SYN", 36, "Unknown attribute " + tagname);
state->stack.push_back(state->stack.back());
} else {
if ((*found)->bound1() == 0 && (*found)->bound2() == 1) {
@@ -595,7 +602,7 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs)
inst->set_attribute_value(idx, state->stack.back().inst());
state->stack.push_back(stack_node::instance(id, inst));
} else {
Logger::Root().Error("SYN", 37, "Unknown attribute " + tagname);
state->logger.Error("SYN", 37, "Unknown attribute " + tagname);
state->stack.push_back(state->stack.back());
}
} else {
@@ -642,7 +649,7 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs)
try {
decl = state->file->schema()->declaration_by_name(tagname);
} catch (const std::exception& e) {
Logger::Root().Error("SYN", 38, e);
state->logger.Error("SYN", 38, e);
}
if (decl == nullptr) {
@@ -651,7 +658,7 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs)
const IfcParse::entity* entity = decl->as_entity();
if ((entity == nullptr) && state_type != stack_node::node_instance_attribute) {
Logger::Root().Error("SYN", 39, "Not an entity definition " + tagname);
state->logger.Error("SYN", 39, "Not an entity definition " + tagname);
goto end;
}
@@ -665,7 +672,7 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs)
if (inst != nullptr) {
inst->set_attribute_value(idx, state->stack.back().inst());
} else {
Logger::Root().Error("SYN", 40, "Internal error, inverse attribute not processed");
state->logger.Error("SYN", 40, "Internal error, inverse attribute not processed");
}
} else if (state_type == stack_node::node_instance_attribute) {
state->stack.back().inst()->set_attribute_value(state->stack.back().idx(), inst);
@@ -688,12 +695,10 @@ end:
return;
}
IFC_PARSE_API IfcParse::IfcFile* IfcParse::parse_ifcxml(const std::string& filename) {
IFC_PARSE_API IfcParse::IfcFile* IfcParse::parse_ifcxml(const std::string& filename, Logger& logger) {
throw std::runtime_error("IFC-XML import temporarily disabled");
ifcxml_parse_state state;
state.file = nullptr;
state.dialect = ifcxml_dialect_unknown;
ifcxml_parse_state state(logger);
xmlSAXHandler handler;
memset(&handler, 0, sizeof(xmlSAXHandler));
+6 -2
View File
@@ -20,9 +20,11 @@ namespace rocksdb {
#include "map_transformer.h"
#include "set_to_map_transformer.h"
#include "file_open_status.h"
#include "IfcLogger.h"
#include <boost/unordered_map.hpp>
#include <functional>
#include <variant>
#include <iterator>
#include <cstdint>
@@ -187,7 +189,7 @@ namespace IfcParse {
void push(IfcUtil::IfcBaseClass* inst);
IfcEntityInstanceData construct(boost::optional<size_t> name, unresolved_references& references_to_resolve, const IfcParse::declaration* decl, boost::optional<size_t> expected_size, int resolve_reference_index, bool coerce_attribute_count=true);
IfcEntityInstanceData construct(boost::optional<size_t> name, unresolved_references& references_to_resolve, const IfcParse::declaration* decl, boost::optional<size_t> expected_size, int resolve_reference_index, Logger& logger, bool coerce_attribute_count=true);
};
namespace impl {
@@ -198,6 +200,7 @@ namespace IfcParse {
}
IfcParse::IfcSpfLexer* tokens;
std::reference_wrapper<Logger> logger_;
// IfcParse::FileReader* stream;
// Either one of these needs to be set
@@ -219,9 +222,10 @@ namespace IfcParse {
typedef std::map<inverse_attr_record, std::vector<uint32_t>> entities_by_ref_t;
typedef entity_instance_by_name_t::iterator iterator;
in_memory_file_storage(IfcParse::IfcFile* f = nullptr) : tokens(nullptr), file(f), schema(nullptr) {}
in_memory_file_storage(IfcParse::IfcFile* f = nullptr, Logger& logger = Logger::Root()) : tokens(nullptr), logger_(logger), file(f), schema(nullptr) {}
in_memory_file_storage(const in_memory_file_storage&) = delete;
in_memory_file_storage(const in_memory_file_storage&&) = delete;
Logger& logger() const { return logger_.get(); }
class type_iterator : public entities_by_type_t::const_iterator {
+1 -1
View File
@@ -19,7 +19,7 @@ RocksDbSerializer::RocksDbSerializer(IfcParse::IfcFile* file, const std::string&
options.merge_operator.reset(new ConcatenateIdMergeOperator());
rocksdb::Status status = rocksdb::DB::Open(options, rocksdb_filename, &db_);*/
output_file_ = new IfcParse::IfcFile(file->schema(), IfcParse::FT_ROCKSDB, rocksdb_filename_);
output_file_ = new IfcParse::IfcFile(file->schema(), IfcParse::FT_ROCKSDB, rocksdb_filename_, logger);
// We promise never to add the same instance twice
output_file_->check_existance_before_adding = false;