From 347a3c80bb1dc6b920c89ce6af6313efbd91f4c5 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Thu, 11 Jun 2026 21:04:44 +0200 Subject: [PATCH] More logger changes --- src/ifcconvert/IfcConvert.cpp | 4 +- src/ifcgeom/AbstractKernel.h | 2 +- src/ifcgeom/Iterator.cpp | 57 +++++-- src/ifcgeom/Iterator.h | 7 +- src/ifcgeom/hybrid_kernel.h | 6 +- src/ifcgeom/kernels/cgal/CgalKernel.cpp | 66 ++++---- src/ifcgeom/kernels/cgal/CgalKernel.h | 4 +- .../kernels/opencascade/OpenCascadeKernel.h | 4 +- src/ifcgeom/mapping/IfcCurveSegment.cpp | 8 +- src/ifcparse/IfcAlignmentHelper.cpp | 90 +++++----- src/ifcparse/IfcAlignmentHelper.h | 10 +- src/ifcparse/IfcCharacterDecoder.cpp | 12 +- src/ifcparse/IfcCharacterDecoder.h | 4 +- src/ifcparse/IfcFile.cpp | 46 ++--- src/ifcparse/IfcFile.h | 28 ++-- src/ifcparse/IfcGlobalId.cpp | 8 +- src/ifcparse/IfcGlobalId.h | 5 +- src/ifcparse/IfcHierarchyHelper.cpp | 10 +- src/ifcparse/IfcHierarchyHelper.h | 10 +- src/ifcparse/IfcLogger.cpp | 52 ++++-- src/ifcparse/IfcLogger.h | 14 +- src/ifcparse/IfcParse.cpp | 157 +++++++++++------- src/ifcparse/IfcParse.h | 4 +- src/ifcparse/IfcSpfHeader.cpp | 25 ++- src/ifcparse/IfcSpfHeader.h | 8 +- src/ifcparse/parse_ifcxml.cpp | 51 +++--- src/ifcparse/storage.h | 8 +- src/serializers/RocksDbSerializer.cpp | 2 +- 28 files changed, 418 insertions(+), 284 deletions(-) diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp index ea72305cb6..acd5421638 100644 --- a/src/ifcconvert/IfcConvert.cpp +++ b/src/ifcconvert/IfcConvert.cpp @@ -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; } diff --git a/src/ifcgeom/AbstractKernel.h b/src/ifcgeom/AbstractKernel.h index 400c2b38f6..24abf84ce3 100644 --- a/src/ifcgeom/AbstractKernel.h +++ b/src/ifcgeom/AbstractKernel.h @@ -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; }; } } diff --git a/src/ifcgeom/Iterator.cpp b/src/ifcgeom/Iterator.cpp index c55a4ee95b..914d55f20a 100644 --- a/src/ifcgeom/Iterator.cpp +++ b/src/ifcgeom/Iterator.cpp @@ -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(converter_->kernel()->clone()), ifc_file, settings_, logger_)); + worker_loggers_.emplace_back(std::make_unique()); + 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(nullptr), static_cast(nullptr)); + } + kernel_pool.push_back(new ifcopenshell::geometry::Converter(std::unique_ptr(converter_->kernel()->clone(worker_logger)), ifc_file, settings_, worker_logger)); } std::vector> 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().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(decorate_with_cache_(GeometrySerializer::READ_BREP, (std::string)product->get("GlobalId"), std::to_string(rep->item->instance->as()->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(decorate_with_cache_(GeometrySerializer::READ_BREP, (std::string)product2->get("GlobalId"), std::to_string(rep->item->instance->as()->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(elem)); + auto elem2 = process_based_on_settings(settings, brep2, kernel_logger, dynamic_cast(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().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().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; } diff --git a/src/ifcgeom/Iterator.h b/src/ifcgeom/Iterator.h index a10021b943..5b849da362 100644 --- a/src/ifcgeom/Iterator.h +++ b/src/ifcgeom/Iterator.h @@ -79,6 +79,7 @@ #include #include #include +#include namespace IfcGeom { @@ -133,6 +134,7 @@ namespace IfcGeom { // When multi-threaded std::vector kernel_pool; + std::vector> 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(); diff --git a/src/ifcgeom/hybrid_kernel.h b/src/ifcgeom/hybrid_kernel.h index 5f8a672261..d19b587ebc 100644 --- a/src/ifcgeom/hybrid_kernel.h +++ b/src/ifcgeom/hybrid_kernel.h @@ -156,14 +156,14 @@ namespace ifcopenshell { } return false; } - virtual AbstractKernel* clone() const + virtual AbstractKernel* clone(Logger& logger) const { std::vector> 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()), std::move(ks), logger()); + return new HybridKernel(geometry_library(), file_, const_cast(settings()), std::move(ks), logger); } }; diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.cpp b/src/ifcgeom/kernels/cgal/CgalKernel.cpp index 6a0935559b..f0747338d3 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.cpp +++ b/src/ifcgeom/kernels/cgal/CgalKernel.cpp @@ -1,4 +1,4 @@ -/******************************************************************************** +/******************************************************************************** * * * This file is part of IfcOpenShell. * * * @@ -162,13 +162,13 @@ CGAL::Nef_polyhedron_3 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(density), l->instance); + logger().Notice("GEO", 77, "Density " + boost::lexical_cast(density), l->instance); if (density > 5000) { - logger_.Notice("GEO", 78, "Substituted element with " + boost::lexical_cast(density) + " vertices / m3 with a bounding box"); + logger().Notice("GEO", 78, "Substituted element with " + boost::lexical_cast(density) + " vertices / m3 with a bounding box"); CGAL::Point_3 lower(minmax.first(0), minmax.first(1), minmax.first(2)); CGAL::Point_3 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& } 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_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 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().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(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 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; } diff --git a/src/ifcgeom/kernels/cgal/CgalKernel.h b/src/ifcgeom/kernels/cgal/CgalKernel.h index 1c9af2546e..cf48c6e15a 100644 --- a/src/ifcgeom/kernels/cgal/CgalKernel.h +++ b/src/ifcgeom/kernels/cgal/CgalKernel.h @@ -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 { diff --git a/src/ifcgeom/kernels/opencascade/OpenCascadeKernel.h b/src/ifcgeom/kernels/opencascade/OpenCascadeKernel.h index 359ccbd01d..9bbd0d0f72 100644 --- a/src/ifcgeom/kernels/opencascade/OpenCascadeKernel.h +++ b/src/ifcgeom/kernels/opencascade/OpenCascadeKernel.h @@ -118,8 +118,8 @@ public: , precision_(settings.get().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; } diff --git a/src/ifcgeom/mapping/IfcCurveSegment.cpp b/src/ifcgeom/mapping/IfcCurveSegment.cpp index 04907655e3..ce49fd73b7 100644 --- a/src/ifcgeom/mapping/IfcCurveSegment.cpp +++ b/src/ifcgeom/mapping/IfcCurveSegment.cpp @@ -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; }; diff --git a/src/ifcparse/IfcAlignmentHelper.cpp b/src/ifcparse/IfcAlignmentHelper.cpp index 5edba1022c..b64b243d21 100644 --- a/src/ifcparse/IfcAlignmentHelper.cpp +++ b/src/ifcparse/IfcAlignmentHelper.cpp @@ -119,11 +119,11 @@ std::tuple::ptr, typenam { auto pt = file.addDoublet(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::ptr, typenam { auto pc = file.addDoublet(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::ptr, typenam auto tangent_run = sqrt(dx * dx + dy * dy); auto pt = file.addDoublet(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(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::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::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::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& 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& 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& 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 mapAlignmentSegment(const Ifc4x3_add2::IfcAlignmentSegment* segment) { +std::pair mapAlignmentSegment(const Ifc4x3_add2::IfcAlignmentSegment* segment, Logger& logger) { std::pair result(nullptr, nullptr); auto design_parameters = segment->DesignParameters(); auto horizontal = design_parameters->as(); auto vertical = design_parameters->as(); auto cant = design_parameters->as(); 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 mapAlignmentHorizontalSegment(const Ifc4x3_add2::IfcAlignmentHorizontalSegment* segment) { +std::pair mapAlignmentHorizontalSegment(const Ifc4x3_add2::IfcAlignmentHorizontalSegment* segment, Logger& logger) { std::pair result(nullptr, nullptr); auto start_point = segment->StartPoint(); auto start_direction = segment->StartDirection(); @@ -661,15 +661,15 @@ std::pair 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 mapAlignmentVerticalSegment(const Ifc4x3_add2::IfcAlignmentVerticalSegment* segment) { +std::pair mapAlignmentVerticalSegment(const Ifc4x3_add2::IfcAlignmentVerticalSegment* segment, Logger& logger) { std::pair result(nullptr, nullptr); auto start_distance_along = segment->StartDistAlong(); auto horizontal_length = segment->HorizontalLength(); @@ -732,7 +732,7 @@ std::pair 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 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 mapAlignmentCantSegment(const Ifc4x3_add2::IfcAlignmentCantSegment* segment) { +std::pair mapAlignmentCantSegment(const Ifc4x3_add2::IfcAlignmentCantSegment* segment, Logger& logger) { std::pair 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; } diff --git a/src/ifcparse/IfcAlignmentHelper.h b/src/ifcparse/IfcAlignmentHelper.h index 444cedd3fd..b01a39be08 100644 --- a/src/ifcparse/IfcAlignmentHelper.h +++ b/src/ifcparse/IfcAlignmentHelper.h @@ -49,11 +49,11 @@ IFC_PARSE_API Ifc4x3_add2::IfcAlignment* addAlignment(IfcHierarchyHelper mapAlignmentSegment(const Ifc4x3_add2::IfcAlignmentSegment* segment); -IFC_PARSE_API std::pair mapAlignmentHorizontalSegment(const Ifc4x3_add2::IfcAlignmentHorizontalSegment* segment); -IFC_PARSE_API std::pair mapAlignmentVerticalSegment(const Ifc4x3_add2::IfcAlignmentVerticalSegment* segment); -IFC_PARSE_API std::pair mapAlignmentCantSegment(const Ifc4x3_add2::IfcAlignmentCantSegment* segment); +IFC_PARSE_API std::pair mapAlignmentSegment(const Ifc4x3_add2::IfcAlignmentSegment* segment, Logger& logger = Logger::Root()); +IFC_PARSE_API std::pair mapAlignmentHorizontalSegment(const Ifc4x3_add2::IfcAlignmentHorizontalSegment* segment, Logger& logger = Logger::Root()); +IFC_PARSE_API std::pair mapAlignmentVerticalSegment(const Ifc4x3_add2::IfcAlignmentVerticalSegment* segment, Logger& logger = Logger::Root()); +IFC_PARSE_API std::pair mapAlignmentCantSegment(const Ifc4x3_add2::IfcAlignmentCantSegment* segment, Logger& logger = Logger::Root()); #endif -#endif \ No newline at end of file +#endif diff --git a/src/ifcparse/IfcCharacterDecoder.cpp b/src/ifcparse/IfcCharacterDecoder.cpp index 10606a9cf6..019499a49e 100644 --- a/src/ifcparse/IfcCharacterDecoder.cpp +++ b/src/ifcparse/IfcCharacterDecoder.cpp @@ -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; } diff --git a/src/ifcparse/IfcCharacterDecoder.h b/src/ifcparse/IfcCharacterDecoder.h index e978a5b4c2..416c2ac9f9 100644 --- a/src/ifcparse/IfcCharacterDecoder.h +++ b/src/ifcparse/IfcCharacterDecoder.h @@ -28,6 +28,7 @@ #define IFCCHARACTERDECODER_H #include "FileReader.h" +#include "IfcLogger.h" #include @@ -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. diff --git a/src/ifcparse/IfcFile.cpp b/src/ifcparse/IfcFile.cpp index 7b45430088..1648842bcf 100644 --- a/src/ifcparse/IfcFile.cpp +++ b/src/ifcparse/IfcFile.cpp @@ -59,7 +59,7 @@ namespace { constexpr bool is_type_in_variant_v = is_type_in_variant::value; template - void dispatch_token(boost::optional instance_id, int attribute_id, IfcParse::Token t, IfcParse::declaration* decl, Fn fn) { + void dispatch_token(boost::optional 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 - void construct_(boost::optional instance_id, int attribute_id, IfcParse::parse_context& p, const IfcParse::aggregation_type* aggr, Fn fn) { + void construct_(boost::optional 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>>) { if (aggregate_storage.index() == 0) { aggregate_storage = std::vector>{ 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, 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, IfcParse::parse_context*>) { // nested list if constexpr (Depth < 3) { - construct_(instance_id, attribute_id, *v, nullptr, append_to_aggregate_storage); + construct_(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 name, unresolved_references& references_to_resolve, const IfcParse::declaration* decl, boost::optional expected_size, int resolve_reference_index, bool coerce_attribute_count) { +IfcEntityInstanceData IfcParse::parse_context::construct(boost::optional name, unresolved_references& references_to_resolve, const IfcParse::declaration* decl, boost::optional expected_size, int resolve_reference_index, Logger& logger, bool coerce_attribute_count) { std::vector parameter_types; std::unique_ptr transient_named_type; @@ -263,9 +263,9 @@ IfcEntityInstanceData IfcParse::parse_context::construct(boost::optional { 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 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, 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, 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 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::vector>) { 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::optionaldeclaration_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::optionalas_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::optionalNext(); } 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) { diff --git a/src/ifcparse/IfcFile.h b/src/ifcparse/IfcFile.h index 1092bb5e4f..5ccfc1944d 100644 --- a/src/ifcparse/IfcFile.h +++ b/src/ifcparse/IfcFile.h @@ -27,6 +27,7 @@ #include "storage.h" #include "file_open_status.h" +#include #include #include #include @@ -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_; 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& type_names); @@ -199,6 +201,7 @@ public: private: file_open_status good_ = file_open_status::SUCCESS; + std::reference_wrapper logger_; const IfcParse::schema_definition* schema_; const IfcParse::declaration* ifcroot_type_; @@ -229,7 +232,7 @@ public: /// /// UTF-8 file path to an IFC-SPF file /// Whether to use memory-mapped I/O - IfcFile(const std::string& path, bool mmap); + IfcFile(const std::string& path, bool mmap, Logger& logger = Logger::Root()); #endif /// /// Constructs an IfcFile object from a file path, supports IFC-SPF and the IfcOpenShell-specific RocksDB format. @@ -237,23 +240,23 @@ public: /// UTF-8 file path to an IFC-SPF file or RocksDB database directory /// File type of the path /// Whether to open in read-only mode, only supported on RocksDB databases - 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()); /// /// Constructs an IfcFile object from a stream containing IFC-SPF data. /// - IfcFile(std::istream& stream, int length); + IfcFile(std::istream& stream, int length, Logger& logger = Logger::Root()); /// /// Constructs an IfcFile object from a memory buffer containing IFC-SPF data. /// - IfcFile(void* data, int length); + IfcFile(void* data, int length, Logger& logger = Logger::Root()); /// /// Constructs an IfcFile object from a given IFC SPF stream. /// /// A pointer to an IfcParse::FileReader object representing the input IFC SPF data stream. - IfcFile(IfcParse::FileReader* stream); + IfcFile(IfcParse::FileReader* stream, Logger& logger = Logger::Root()); /// /// Constructs an IfcFile object with the specified schema, file type, and file path. @@ -262,12 +265,12 @@ public: /// Pointer to the schema definition to use. Defaults to the IFC4 schema if not specified. /// The file type to use for the file. Defaults to FT_AUTODETECT. /// The file system path to the IFC file. Defaults to an empty string. - 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()); /// /// Constructs an unitialized IfcFile object. Call initialize() later on. Allows to specify which types to bypass during load. /// - 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 { diff --git a/src/ifcparse/IfcGlobalId.cpp b/src/ifcparse/IfcGlobalId.cpp index af2e4893f5..975bb0df5d 100644 --- a/src/ifcparse/IfcGlobalId.cpp +++ b/src/ifcparse/IfcGlobalId.cpp @@ -94,7 +94,7 @@ void expand(const std::string& s, std::vector& v) { static boost::uuids::basic_random_generator gen; #endif -IfcParse::IfcGlobalId::IfcGlobalId() { +IfcParse::IfcGlobalId::IfcGlobalId(Logger& logger) { uuid_data_ = gen(); std::vector 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 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 } diff --git a/src/ifcparse/IfcGlobalId.h b/src/ifcparse/IfcGlobalId.h index d9f3cb5155..f281e08f2e 100644 --- a/src/ifcparse/IfcGlobalId.h +++ b/src/ifcparse/IfcGlobalId.h @@ -21,6 +21,7 @@ #define IFCGLOBALID_H #include "ifc_parse_api.h" +#include "IfcLogger.h" #include #include @@ -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; diff --git a/src/ifcparse/IfcHierarchyHelper.cpp b/src/ifcparse/IfcHierarchyHelper.cpp index cc3b198e91..2566e204f0 100644 --- a/src/ifcparse/IfcHierarchyHelper.cpp +++ b/src/ifcparse/IfcHierarchyHelper.cpp @@ -129,7 +129,7 @@ typename Schema::IfcProject* IfcHierarchyHelper::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::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::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::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::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, diff --git a/src/ifcparse/IfcHierarchyHelper.h b/src/ifcparse/IfcHierarchyHelper.h index e397f1f89a..c4c9500572 100644 --- a/src/ifcparse/IfcHierarchyHelper.h +++ b/src/ifcparse/IfcHierarchyHelper.h @@ -362,7 +362,7 @@ void set_children_of_relation(IfcUtil::IfcBaseClass* t, aggregate_of_instance::p template 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 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()); related_objects->push(related_object->template as()); - typename Schema::IfcRelDefinesByType* t = new typename Schema::IfcRelDefinesByType(IfcParse::IfcGlobalId(), owner_hist, boost::none, boost::none, related_objects, relating_object->template as()); + typename Schema::IfcRelDefinesByType* t = new typename Schema::IfcRelDefinesByType(IfcParse::IfcGlobalId(this->logger()), owner_hist, boost::none, boost::none, related_objects, relating_object->template as()); 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->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; diff --git a/src/ifcparse/IfcLogger.cpp b/src/ifcparse/IfcLogger.cpp index 2146146098..0b454b8563 100644 --- a/src/ifcparse/IfcLogger.cpp +++ b/src/ifcparse/IfcLogger.cpp @@ -32,8 +32,6 @@ #include #include -static my_thread_local std::map 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 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 lock(mutex_); return log_stream_.str(); } +void Logger::ClearLog() { + std::lock_guard 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(log); + } else { + log_stream_ << log; + } + } + } + + logger.log_stream_.str(std::string()); + logger.log_stream_.clear(); + logger.log_messages_.clear(); +} + void Logger::PrintPerformanceStats() { std::vector> items; for (auto& stat : performance_statistics_) { diff --git a/src/ifcparse/IfcLogger.h b/src/ifcparse/IfcLogger.h index ac5a817d5a..19fcdd9738 100644 --- a/src/ifcparse/IfcLogger.h +++ b/src/ifcparse/IfcLogger.h @@ -31,14 +31,15 @@ #include #include #include +#include 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_messages() const { return log_messages_; } }; diff --git a/src/ifcparse/IfcParse.cpp b/src/ifcparse/IfcParse.cpp index ca10bc4ef1..1fb3d2a170 100644 --- a/src/ifcparse/IfcParse.cpp +++ b/src/ifcparse/IfcParse.cpp @@ -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 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(fn); } - storage_.emplace<1>(this); + storage_.emplace<1>(this, logger_.get()); std::get(storage_).read_from_stream(&*s, schema_, max_id_, types_to_bypass_loading_); if ((good_ = std::get(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(storage_).read_from_stream(&s, schema_, max_id_, types_to_bypass_loading_); if ((good_ = std::get(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(storage_).read_from_stream(&s, schema_, max_id_, types_to_bypass_loading_); good_ = std::get(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(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(storage_).read_from_stream(&s, schema_, max_id_, types_to_bypass_loading_); good_ = std::get(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(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(storage_).read_from_stream(s, schema_, max_id_, types_to_bypass_loading_); good_ = std::get(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(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(storage_).byid_); byref_excl_ = decltype(byref_excl_)(&std::get(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 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(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(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(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>>(&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(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"); } } diff --git a/src/ifcparse/IfcParse.h b/src/ifcparse/IfcParse.h index a034fde218..547220b00b 100644 --- a/src/ifcparse/IfcParse.h +++ b/src/ifcparse/IfcParse.h @@ -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); diff --git a/src/ifcparse/IfcSpfHeader.cpp b/src/ifcparse/IfcSpfHeader.cpp index a55319696d..fd4c80e51a 100644 --- a/src/ifcparse/IfcSpfHeader.cpp +++ b/src/ifcparse/IfcSpfHeader.cpp @@ -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, 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; } } diff --git a/src/ifcparse/IfcSpfHeader.h b/src/ifcparse/IfcSpfHeader.h index 6d47617316..fb6438745b 100644 --- a/src/ifcparse/IfcSpfHeader.h +++ b/src/ifcparse/IfcSpfHeader.h @@ -25,6 +25,8 @@ #include "Header_section_schema.h" #include "storage.h" +#include + namespace IfcParse { class IfcFile; @@ -32,6 +34,7 @@ class IfcFile; class IFC_PARSE_API IfcSpfHeader { private: IfcFile* file_; + std::reference_wrapper 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(); diff --git a/src/ifcparse/parse_ifcxml.cpp b/src/ifcparse/parse_ifcxml.cpp index 66ac6a98a8..8ebb4c4fe3 100644 --- a/src/ifcparse/parse_ifcxml.cpp +++ b/src/ifcparse/parse_ifcxml.cpp @@ -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; std::map idmap; std::vector> forward_references; ifcxml_dialect dialect; + Logger& logger; }; // ifc4 allows for aggregates to be concatenated using whitespace. @@ -227,7 +234,7 @@ std::vector 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)); diff --git a/src/ifcparse/storage.h b/src/ifcparse/storage.h index 39e5139040..8c46d59640 100644 --- a/src/ifcparse/storage.h +++ b/src/ifcparse/storage.h @@ -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 +#include #include #include #include @@ -187,7 +189,7 @@ namespace IfcParse { void push(IfcUtil::IfcBaseClass* inst); - IfcEntityInstanceData construct(boost::optional name, unresolved_references& references_to_resolve, const IfcParse::declaration* decl, boost::optional expected_size, int resolve_reference_index, bool coerce_attribute_count=true); + IfcEntityInstanceData construct(boost::optional name, unresolved_references& references_to_resolve, const IfcParse::declaration* decl, boost::optional 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_; // IfcParse::FileReader* stream; // Either one of these needs to be set @@ -219,9 +222,10 @@ namespace IfcParse { typedef std::map> 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 { diff --git a/src/serializers/RocksDbSerializer.cpp b/src/serializers/RocksDbSerializer.cpp index 112445d3f6..6ac8ec114b 100644 --- a/src/serializers/RocksDbSerializer.cpp +++ b/src/serializers/RocksDbSerializer.cpp @@ -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;