mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-23 07:42:41 +00:00
Configurable pointer type; std::from_chars(); aggregate inverses in vector; skip parse_context
This commit is contained in:
@@ -81,7 +81,11 @@ namespace {
|
|||||||
try {
|
try {
|
||||||
module = manager.load(path);
|
module = manager.load(path);
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
|
#ifdef IFOPSH_PLUGIN_DEBUG
|
||||||
std::cerr << "[ifcopenshell.plugin] skip kernel plugin " << path << ": " << e.what() << std::endl;
|
std::cerr << "[ifcopenshell.plugin] skip kernel plugin " << path << ": " << e.what() << std::endl;
|
||||||
|
#else
|
||||||
|
static_cast<void>(e);
|
||||||
|
#endif
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (module.meta().kind_ != ifcopenshell::plugin::kind::kernel) {
|
if (module.meta().kind_ != ifcopenshell::plugin::kind::kernel) {
|
||||||
|
|||||||
@@ -9,19 +9,27 @@ uint32_t express::Base::identity() const { return data()->identity(); }
|
|||||||
uint32_t express::Base::id() const { return data()->id(); }
|
uint32_t express::Base::id() const { return data()->id(); }
|
||||||
|
|
||||||
const instance_data* express::Base::data() const {
|
const instance_data* express::Base::data() const {
|
||||||
|
#ifdef IFOPSH_SAFE_INSTANCE
|
||||||
auto sp = data_.lock();
|
auto sp = data_.lock();
|
||||||
if (sp) {
|
if (sp) {
|
||||||
return sp.get();
|
return sp.get();
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error("Trying to access deleted instance reference");
|
throw std::runtime_error("Trying to access deleted instance reference");
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
return data_;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
instance_data* express::Base::data() {
|
instance_data* express::Base::data() {
|
||||||
|
#ifdef IFOPSH_SAFE_INSTANCE
|
||||||
auto sp = data_.lock();
|
auto sp = data_.lock();
|
||||||
if (sp) {
|
if (sp) {
|
||||||
return sp.get();
|
return sp.get();
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error("Trying to access deleted instance reference");
|
throw std::runtime_error("Trying to access deleted instance reference");
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
return data_;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
+30
-5
@@ -31,6 +31,23 @@
|
|||||||
class aggregate_of_instance;
|
class aggregate_of_instance;
|
||||||
|
|
||||||
namespace ifcopenshell {
|
namespace ifcopenshell {
|
||||||
|
|
||||||
|
#ifdef IFOPSH_SAFE_INSTANCE
|
||||||
|
using pointer_type = std::weak_ptr<instance_data>;
|
||||||
|
using shared_pointer_type = shared_pointer_type;
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
shared_pointer_type make_pointer_type(Args&&... args) {
|
||||||
|
return std::make_shared<T>(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
using pointer_type = instance_data*;
|
||||||
|
using shared_pointer_type = instance_data*;
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
shared_pointer_type make_pointer_type(Args&&... args) {
|
||||||
|
return new T(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
class file;
|
class file;
|
||||||
namespace impl {
|
namespace impl {
|
||||||
struct in_memory_file_storage;
|
struct in_memory_file_storage;
|
||||||
@@ -49,12 +66,16 @@ class DeclaredType;
|
|||||||
|
|
||||||
class IFC_PARSE_API Base {
|
class IFC_PARSE_API Base {
|
||||||
protected:
|
protected:
|
||||||
std::weak_ptr<instance_data> data_;
|
ifcopenshell::pointer_type data_;
|
||||||
const instance_data* data() const;
|
const instance_data* data() const;
|
||||||
instance_data* data();
|
instance_data* data();
|
||||||
public:
|
public:
|
||||||
operator bool() const {
|
operator bool() const {
|
||||||
|
#ifdef IFOPSH_SAFE_INSTANCE
|
||||||
return !data_.expired();
|
return !data_.expired();
|
||||||
|
#else
|
||||||
|
return data_ != nullptr;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator<(const Base& other) const {
|
bool operator<(const Base& other) const {
|
||||||
@@ -69,12 +90,16 @@ class IFC_PARSE_API Base {
|
|||||||
return !(*this == other);
|
return !(*this == other);
|
||||||
}
|
}
|
||||||
|
|
||||||
Base() {};
|
Base() {
|
||||||
|
#ifndef IFOPSH_SAFE_INSTANCE
|
||||||
|
data_ = nullptr;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
Base(std::nullopt_t) noexcept : Base() {}
|
Base(std::nullopt_t) noexcept : Base() {}
|
||||||
Base(const std::weak_ptr<instance_data>& data) : data_(data) {}
|
Base(const ifcopenshell::pointer_type& data) : data_(data) {}
|
||||||
|
|
||||||
// @todo try and make this private over time too
|
// @todo try and make this private over time too
|
||||||
const std::weak_ptr<instance_data>& data_weak() const { return data_; }
|
const ifcopenshell::pointer_type& data_weak() const { return data_; }
|
||||||
|
|
||||||
const ifcopenshell::declaration& declaration() const;
|
const ifcopenshell::declaration& declaration() const;
|
||||||
|
|
||||||
@@ -150,7 +175,7 @@ class IFC_PARSE_API Select : public Base {
|
|||||||
public:
|
public:
|
||||||
Select() {}
|
Select() {}
|
||||||
Select(std::nullopt_t) noexcept : Base() {}
|
Select(std::nullopt_t) noexcept : Base() {}
|
||||||
Select(const std::weak_ptr<instance_data>& data) : Base(data) {}
|
Select(const ifcopenshell::pointer_type& data) : Base(data) {}
|
||||||
Select(const Base& base) : Base(base.data_weak()) {}
|
Select(const Base& base) : Base(base.data_weak()) {}
|
||||||
|
|
||||||
Base concrete() const {
|
Base concrete() const {
|
||||||
|
|||||||
+2
-332
@@ -10,336 +10,6 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
ifcopenshell::parse_context::~parse_context() {
|
|
||||||
for (auto& t : tokens_) {
|
|
||||||
std::visit([](auto& v) {
|
|
||||||
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, parse_context*>) {
|
|
||||||
delete v;
|
|
||||||
}
|
|
||||||
}, t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ifcopenshell::parse_context& ifcopenshell::parse_context::push() {
|
|
||||||
auto* pc = new parse_context;
|
|
||||||
tokens_.push_back(pc);
|
|
||||||
return *pc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ifcopenshell::parse_context::push(token t) {
|
|
||||||
tokens_.push_back(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ifcopenshell::parse_context::push(const express::Base& inst) {
|
|
||||||
tokens_.push_back(inst);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
template<typename Variant, typename T>
|
|
||||||
struct is_type_in_variant;
|
|
||||||
|
|
||||||
// Specialization when there are multiple types in the variant
|
|
||||||
template<typename T, typename First, typename... Rest>
|
|
||||||
struct is_type_in_variant<std::variant<First, Rest...>, T>
|
|
||||||
{
|
|
||||||
static constexpr bool value = std::is_same<T, First>::value || is_type_in_variant<std::variant<Rest...>, T>::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Specialization when there is only one type left in the variant
|
|
||||||
template<typename T, typename Last>
|
|
||||||
struct is_type_in_variant<std::variant<Last>, T>
|
|
||||||
{
|
|
||||||
static constexpr bool value = std::is_same<T, Last>::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Variant, typename T>
|
|
||||||
constexpr bool is_type_in_variant_v = is_type_in_variant<Variant, T>::value;
|
|
||||||
|
|
||||||
template <typename Fn>
|
|
||||||
void dispatch_token(std::optional<size_t> instance_id, int attribute_id, ifcopenshell::token t, ifcopenshell::declaration* decl, Fn fn) {
|
|
||||||
if (t.is_binary()) {
|
|
||||||
fn(t.as_binary());
|
|
||||||
} else if (t.is_bool()) {
|
|
||||||
fn(t.as_bool());
|
|
||||||
} else if (t.is_logical()) {
|
|
||||||
fn(t.as_logical());
|
|
||||||
} else if (t.is_enumeration()) {
|
|
||||||
const auto& s = t.as_string();
|
|
||||||
if (decl && decl->as_enumeration_type()) {
|
|
||||||
try {
|
|
||||||
fn(enumeration_reference(decl->as_enumeration_type(), decl->as_enumeration_type()->lookup_enum_offset(s)));
|
|
||||||
} catch (ifcopenshell::exception& e) {
|
|
||||||
logger::error("An enumeration literal '" + s + "' is not valid for type '" + decl->name() + "' at offset " + std::to_string(t.start_pos));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
logger::error("An enumeration literal '" + s + "' is not expected at attribute index '" + std::to_string(attribute_id) + "' at offset " + std::to_string(t.start_pos));
|
|
||||||
}
|
|
||||||
} else if (t.is_int()) {
|
|
||||||
// @nb make sure is_int() comes before is_float()
|
|
||||||
fn(t.as_int());
|
|
||||||
} else if (t.is_float()) {
|
|
||||||
fn(t.as_float());
|
|
||||||
} else if (t.is_identifier()) {
|
|
||||||
fn(ifcopenshell::reference_or_simple_type{ifcopenshell::instance_reference{(int) t.as_identifier(), t.start_pos}});
|
|
||||||
} else if (t.is_string()) {
|
|
||||||
fn(t.as_string());
|
|
||||||
} else if (t.is_operator('*')) {
|
|
||||||
// This is only in place for the validator
|
|
||||||
fn(derived{});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <size_t Depth, typename Fn>
|
|
||||||
void construct_(std::optional<size_t> instance_id, int attribute_id, ifcopenshell::parse_context& p, const ifcopenshell::aggregation_type* aggr, Fn fn) {
|
|
||||||
if (p.tokens_.empty()) {
|
|
||||||
// @todo instead of ugly if-else we could also default initialize the respective
|
|
||||||
// variant types below.
|
|
||||||
if (aggr) {
|
|
||||||
auto aggr_type = ifcopenshell::make_aggregate(ifcopenshell::from_parameter_type(aggr->type_of_element()));
|
|
||||||
if (aggr_type == ifcopenshell::Argument_AGGREGATE_OF_INT) {
|
|
||||||
fn(std::vector<int>{});
|
|
||||||
} else if (aggr_type == ifcopenshell::Argument_AGGREGATE_OF_DOUBLE) {
|
|
||||||
fn(std::vector<double>{});
|
|
||||||
} else if (aggr_type == ifcopenshell::Argument_AGGREGATE_OF_STRING) {
|
|
||||||
fn(std::vector<std::string>{});
|
|
||||||
} else if (aggr_type == ifcopenshell::Argument_AGGREGATE_OF_BINARY) {
|
|
||||||
fn(std::vector<boost::dynamic_bitset<>>{});
|
|
||||||
} else if (aggr_type == ifcopenshell::Argument_AGGREGATE_OF_ENTITY_INSTANCE) {
|
|
||||||
fn(std::vector<express::Base>{});
|
|
||||||
} else if (aggr_type == ifcopenshell::Argument_AGGREGATE_OF_AGGREGATE_OF_INT) {
|
|
||||||
fn(std::vector<std::vector<int>>{});
|
|
||||||
} else if (aggr_type == ifcopenshell::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE) {
|
|
||||||
fn(std::vector<std::vector<double>>{});
|
|
||||||
} else if (aggr_type == ifcopenshell::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE) {
|
|
||||||
fn(std::vector<std::vector<express::Base>>{});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef std::variant<
|
|
||||||
blank,
|
|
||||||
|
|
||||||
std::vector<int>,
|
|
||||||
std::vector<double>,
|
|
||||||
std::vector<std::string>,
|
|
||||||
std::vector<boost::dynamic_bitset<>>,
|
|
||||||
std::vector<ifcopenshell::reference_or_simple_type>,
|
|
||||||
|
|
||||||
std::vector<std::vector<int>>,
|
|
||||||
std::vector<std::vector<double>>,
|
|
||||||
std::vector<std::vector<ifcopenshell::reference_or_simple_type>>
|
|
||||||
> possible_aggregation_types_t;
|
|
||||||
|
|
||||||
possible_aggregation_types_t aggregate_storage;
|
|
||||||
|
|
||||||
auto append_to_aggregate_storage = [&aggregate_storage](const auto& v) {
|
|
||||||
if constexpr (is_type_in_variant_v<possible_aggregation_types_t, std::vector<std::decay_t<decltype(v)>>>) {
|
|
||||||
if (aggregate_storage.index() == 0) {
|
|
||||||
aggregate_storage = std::vector<std::decay_t<decltype(v)>>{ v };
|
|
||||||
} else {
|
|
||||||
if (auto* vec_ptr = std::get_if<std::vector<std::decay_t<decltype(v)>>>(&aggregate_storage)) {
|
|
||||||
vec_ptr->push_back(v);
|
|
||||||
} else {
|
|
||||||
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, int>) {
|
|
||||||
auto* vec_ptr2 = std::get_if<std::vector<double>>(&aggregate_storage);
|
|
||||||
if (vec_ptr2) {
|
|
||||||
// double[] + int
|
|
||||||
vec_ptr2->push_back((double) v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, double>) {
|
|
||||||
auto* vec_ptr2 = std::get_if<std::vector<int>>(&aggregate_storage);
|
|
||||||
if (vec_ptr2) {
|
|
||||||
// int[] -> double[] + double
|
|
||||||
std::vector<double> ps(vec_ptr2->begin(), vec_ptr2->end());
|
|
||||||
ps.push_back(v);
|
|
||||||
aggregate_storage = ps;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, std::vector<int>>) {
|
|
||||||
auto* vec_ptr2 = std::get_if<std::vector<std::vector<double>>>(&aggregate_storage);
|
|
||||||
if (vec_ptr2) {
|
|
||||||
// double[][] + int[]
|
|
||||||
std::vector<double> vd(v.begin(), v.end());
|
|
||||||
vec_ptr2->push_back(vd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, std::vector<double>>) {
|
|
||||||
auto* vec_ptr2 = std::get_if<std::vector<std::vector<int>>>(&aggregate_storage);
|
|
||||||
if (vec_ptr2) {
|
|
||||||
// int[][] -> double[][] + double[]
|
|
||||||
std::vector<std::vector<double>> vvd;
|
|
||||||
for (auto& vv : *vec_ptr2) {
|
|
||||||
std::vector<double> vd(vv.begin(), vv.end());
|
|
||||||
vvd.push_back(vd);
|
|
||||||
}
|
|
||||||
vvd.push_back(v);
|
|
||||||
aggregate_storage = vvd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// @todo would be cool if we can trace this back to file offset
|
|
||||||
auto current = std::visit([](auto v) {
|
|
||||||
if constexpr (!std::is_same_v<decltype(v), blank>) {
|
|
||||||
return std::string(typeid(typename decltype(v)::value_type).name());
|
|
||||||
} else {
|
|
||||||
// Cannot occur as aggregate_storage.which() == 0
|
|
||||||
// is another branch several statements up. But is
|
|
||||||
// needed for consistency of return type.
|
|
||||||
return std::string{};
|
|
||||||
}
|
|
||||||
}, aggregate_storage);
|
|
||||||
|
|
||||||
logger::error("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..
|
|
||||||
//
|
|
||||||
// if constexpr (std::is_same_v<std::decay_t<decltype(v)>, bool>) {
|
|
||||||
// auto* vec_ptr = boost::get<std::vector<boost::tribool>(&aggregate_storage);
|
|
||||||
// vec_ptr->push_back(v);
|
|
||||||
// }
|
|
||||||
// if constexpr (std::is_same_v<std::decay_t<decltype(v)>, boost::tribool>) {
|
|
||||||
// auto* vec_ptr = boost::get<std::vector<bool>(&aggregate_storage);
|
|
||||||
// std::vector<boost::tribool> ps(vec_ptr->begin(), vec_ptr->end());
|
|
||||||
// ps.push_back(v);
|
|
||||||
// aggregate_storage = ps;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// @todo would be cool if we can trace this back to file offset
|
|
||||||
logger::error(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) {
|
|
||||||
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, ifcopenshell::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);
|
|
||||||
} else if constexpr (std::is_same_v<std::decay_t<decltype(v)>, ifcopenshell::parse_context*>) {
|
|
||||||
// nested list
|
|
||||||
if constexpr (Depth < 3) {
|
|
||||||
construct_<Depth + 1>(instance_id, attribute_id, *v, nullptr, append_to_aggregate_storage);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
append_to_aggregate_storage(ifcopenshell::reference_or_simple_type{ v });
|
|
||||||
}
|
|
||||||
}, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::visit(fn, aggregate_storage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<instance_data> ifcopenshell::parse_context::construct(ifcopenshell::file* owner, std::optional<size_t> name, unresolved_references& references_to_resolve, const ifcopenshell::declaration* decl, std::optional<size_t> expected_size, int resolve_reference_index, bool coerce_attribute_count) {
|
|
||||||
std::vector<const ifcopenshell::parameter_type*> parameter_types;
|
|
||||||
std::unique_ptr<ifcopenshell::named_type> transient_named_type;
|
|
||||||
|
|
||||||
if ((decl != nullptr) && (decl->as_type_declaration() != nullptr)) {
|
|
||||||
parameter_types = { decl->as_type_declaration()->declared_type() };
|
|
||||||
} else if ((decl != nullptr) && (decl->as_enumeration_type() != nullptr)) {
|
|
||||||
transient_named_type.reset(new ifcopenshell::named_type(const_cast<ifcopenshell::declaration*>(decl)));
|
|
||||||
parameter_types = { &*transient_named_type };
|
|
||||||
} else if ((decl != nullptr) && (decl->as_entity() != nullptr)) {
|
|
||||||
const auto& entity_attrs = decl->as_entity()->all_attributes();
|
|
||||||
std::transform(
|
|
||||||
entity_attrs.begin(),
|
|
||||||
entity_attrs.end(),
|
|
||||||
std::back_inserter(parameter_types),
|
|
||||||
[](auto* attr) {
|
|
||||||
return attr->type_of_attribute();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (((decl != nullptr) && (tokens_.size() != parameter_types.size())) ||
|
|
||||||
expected_size && *expected_size != tokens_.size())
|
|
||||||
{
|
|
||||||
size_t expected = expected_size ? *expected_size : parameter_types.size();
|
|
||||||
if (decl != nullptr && decl->schema() == &Header_section_schema::get_schema()) {
|
|
||||||
logger::warning("Expected " + std::to_string(expected) + " attribute values, found " + std::to_string(tokens_.size()) + " for header entity " + decl->name());
|
|
||||||
} else {
|
|
||||||
logger::warning("Expected " + std::to_string(expected) + " attribute values, found " + std::to_string(tokens_.size()) + (name ? std::string(" for instance #" + std::to_string(*name)) : std::string("")));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tokens_.empty()) {
|
|
||||||
return std::make_shared<instance_data>(owner, decl, name.value_or(0), in_memory_attribute_storage(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
in_memory_attribute_storage storage(coerce_attribute_count
|
|
||||||
? (decl != nullptr
|
|
||||||
? (std::min)(parameter_types.size(), tokens_.size())
|
|
||||||
: tokens_.size())
|
|
||||||
: tokens_.size()
|
|
||||||
);
|
|
||||||
|
|
||||||
auto it = tokens_.begin();
|
|
||||||
auto kt = parameter_types.begin();
|
|
||||||
for (; it != tokens_.end() && ((decl == nullptr) || kt != parameter_types.end()); ++it) {
|
|
||||||
auto& token = *it;
|
|
||||||
// @todo coerce to expected type, e.g empty -> std::vector<int>, bool -> logical
|
|
||||||
const ifcopenshell::parameter_type* param_type = nullptr;
|
|
||||||
if (decl != nullptr) {
|
|
||||||
param_type = *kt;
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, ifcopenshell::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) {
|
|
||||||
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, ifcopenshell::reference_or_simple_type>) {
|
|
||||||
if (name) {
|
|
||||||
references_to_resolve.push_back(std::make_pair(
|
|
||||||
// @todo previously this was storage but apparently the
|
|
||||||
// pointer is not constant with the moving and temporary nature
|
|
||||||
// maybe it ought to be and in that case a pointer is more direct
|
|
||||||
mutable_attribute_value{ (uint32_t) *name, resolve_reference_index == -1 ? index : (uint8_t) resolve_reference_index },
|
|
||||||
v
|
|
||||||
));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
storage.set(index, v);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if constexpr (std::is_same_v<std::decay_t<decltype(v)>, ifcopenshell::parse_context*>) {
|
|
||||||
const auto *pt = param_type;
|
|
||||||
if (pt) {
|
|
||||||
while (pt->as_named_type() && pt->as_named_type()->declared_type()->as_type_declaration()) {
|
|
||||||
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) {
|
|
||||||
if constexpr (std::is_same_v<std::decay_t<decltype(v)>, std::vector<reference_or_simple_type>>) {
|
|
||||||
if (name) {
|
|
||||||
references_to_resolve.push_back({ { (uint32_t) *name, resolve_reference_index == -1 ? index : (uint8_t)resolve_reference_index }, v });
|
|
||||||
}
|
|
||||||
} else if constexpr (std::is_same_v<std::decay_t<decltype(v)>, std::vector<std::vector<reference_or_simple_type>>>) {
|
|
||||||
if (name) {
|
|
||||||
references_to_resolve.push_back({ { (uint32_t) *name, resolve_reference_index == -1 ? index : (uint8_t)resolve_reference_index }, v });
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
storage.set(index, v);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
storage.set(index, v);
|
|
||||||
}
|
|
||||||
}, token);
|
|
||||||
|
|
||||||
if (decl != nullptr) {
|
|
||||||
++kt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::make_shared<instance_data>(owner, decl, (decl && decl->as_entity()) ? name.value_or(0) : 0, std::move(storage));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
ifcopenshell::IfcBaseClass* ifcopenshell::impl::rocks_db_file_storage::rocksdb_instance_iterator::operator*() const {
|
ifcopenshell::IfcBaseClass* ifcopenshell::impl::rocks_db_file_storage::rocksdb_instance_iterator::operator*() const {
|
||||||
auto it = storage_->byid_.find(*read_id_());
|
auto it = storage_->byid_.find(*read_id_());
|
||||||
@@ -391,7 +61,7 @@ express::Base ifcopenshell::impl::rocks_db_file_storage::assert_existance(size_t
|
|||||||
}
|
}
|
||||||
// @nb note that in case of type declarations we pass the identity as the number so
|
// @nb note that in case of type declarations we pass the identity as the number so
|
||||||
// that we can read back the attributes from the db (we cannot assign to identity).
|
// that we can read back the attributes from the db (we cannot assign to identity).
|
||||||
auto data = std::make_shared<instance_data>(file, decl, number, rocks_db_attribute_storage{});
|
auto data = ifcopenshell::make_pointer_type<instance_data>(file, decl, number, rocks_db_attribute_storage{});
|
||||||
if (r == ifcopenshell::impl::rocks_db_file_storage::entityinstance_ref) {
|
if (r == ifcopenshell::impl::rocks_db_file_storage::entityinstance_ref) {
|
||||||
instance_cache_.insert({number, data});
|
instance_cache_.insert({number, data});
|
||||||
} else {
|
} else {
|
||||||
@@ -674,7 +344,7 @@ express::Base ifcopenshell::impl::in_memory_file_storage::create(const ifcopensh
|
|||||||
} else {
|
} else {
|
||||||
throw std::runtime_error("Requires and entity or type declaration");
|
throw std::runtime_error("Requires and entity or type declaration");
|
||||||
}
|
}
|
||||||
auto data = std::make_shared<instance_data>(file, decl, instance_name, decl->as_entity() ? in_memory_attribute_storage(decl->as_entity()->attribute_count()) : in_memory_attribute_storage(1));
|
auto data = ifcopenshell::make_pointer_type<instance_data>(file, decl, instance_name, decl->as_entity() ? in_memory_attribute_storage(decl->as_entity()->attribute_count()) : in_memory_attribute_storage(1));
|
||||||
if (instance_name) {
|
if (instance_name) {
|
||||||
byid_.insert({instance_name, data});
|
byid_.insert({instance_name, data});
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+3
-2
@@ -107,6 +107,7 @@ private:
|
|||||||
bool yield_header_instances_ = true;
|
bool yield_header_instances_ = true;
|
||||||
std::vector<const declaration*> types_to_bypass_;
|
std::vector<const declaration*> types_to_bypass_;
|
||||||
std::vector<unsigned> bypassed_instances_;
|
std::vector<unsigned> bypassed_instances_;
|
||||||
|
std::vector<bool> types_to_bypass_materialized_;
|
||||||
|
|
||||||
void initialize_header();
|
void initialize_header();
|
||||||
spf_header& ensure_header();
|
spf_header& ensure_header();
|
||||||
@@ -143,7 +144,7 @@ private:
|
|||||||
return storage_.byref_excl_;
|
return storage_.byref_excl_;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::shared_ptr<instance_data>> steal_instances() {
|
std::vector<shared_pointer_type> steal_instances() {
|
||||||
return storage_.steal_instances();
|
return storage_.steal_instances();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,7 +172,7 @@ private:
|
|||||||
|
|
||||||
~instance_streamer() = default;
|
~instance_streamer() = default;
|
||||||
|
|
||||||
std::optional<std::tuple<size_t, const ifcopenshell::declaration*, std::shared_ptr<instance_data>>> read_instance();
|
std::optional<std::tuple<size_t, const ifcopenshell::declaration*, shared_pointer_type>> read_instance();
|
||||||
};
|
};
|
||||||
|
|
||||||
class uninitialized_tag {};
|
class uninitialized_tag {};
|
||||||
|
|||||||
+582
-228
File diff suppressed because it is too large
Load Diff
@@ -11,16 +11,16 @@ using namespace ifcopenshell;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
std::shared_ptr<instance_data> make_header_entity(ifcopenshell::file* file, const ifcopenshell::entity& decl) {
|
shared_pointer_type make_header_entity(ifcopenshell::file* file, const ifcopenshell::entity& decl) {
|
||||||
const bool in_memory = file == nullptr || std::visit([](auto& storage) {
|
const bool in_memory = file == nullptr || std::visit([](auto& storage) {
|
||||||
return std::is_same_v<std::decay_t<decltype(storage)>, ifcopenshell::impl::in_memory_file_storage>;
|
return std::is_same_v<std::decay_t<decltype(storage)>, ifcopenshell::impl::in_memory_file_storage>;
|
||||||
}, file->storage_);
|
}, file->storage_);
|
||||||
|
|
||||||
if (in_memory) {
|
if (in_memory) {
|
||||||
return std::make_shared<instance_data>(file, &decl, 0, in_memory_attribute_storage(decl.attribute_count()));
|
return ifcopenshell::make_pointer_type<instance_data>(file, &decl, 0, in_memory_attribute_storage(decl.attribute_count()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_shared<instance_data>(file, &decl, 0, rocks_db_attribute_storage{});
|
return ifcopenshell::make_pointer_type<instance_data>(file, &decl, 0, rocks_db_attribute_storage{});
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@@ -60,15 +60,15 @@ void ifcopenshell::spf_header::owner_file(ifcopenshell::file* file) {
|
|||||||
file_ = file;
|
file_ = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ifcopenshell::spf_header::set_file_description(const std::shared_ptr<instance_data>& data) {
|
void ifcopenshell::spf_header::set_file_description(const shared_pointer_type& data) {
|
||||||
header_entities_[0] = data;
|
header_entities_[0] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ifcopenshell::spf_header::set_file_name(const std::shared_ptr<instance_data>& data) {
|
void ifcopenshell::spf_header::set_file_name(const shared_pointer_type& data) {
|
||||||
header_entities_[1] = data;
|
header_entities_[1] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ifcopenshell::spf_header::set_file_schema(const std::shared_ptr<instance_data>& data) {
|
void ifcopenshell::spf_header::set_file_schema(const shared_pointer_type& data) {
|
||||||
header_entities_[2] = data;
|
header_entities_[2] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class IFC_PARSE_API spf_header {
|
|||||||
private:
|
private:
|
||||||
ifcopenshell::file* file_;
|
ifcopenshell::file* file_;
|
||||||
|
|
||||||
std::array<std::shared_ptr<instance_data>, 3> header_entities_;
|
std::array<shared_pointer_type, 3> header_entities_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit spf_header(ifcopenshell::file* owner_file);
|
explicit spf_header(ifcopenshell::file* owner_file);
|
||||||
@@ -43,9 +43,9 @@ class IFC_PARSE_API spf_header {
|
|||||||
ifcopenshell::file* owner_file() { return file_; }
|
ifcopenshell::file* owner_file() { return file_; }
|
||||||
void owner_file(ifcopenshell::file* file);
|
void owner_file(ifcopenshell::file* file);
|
||||||
|
|
||||||
void set_file_description(const std::shared_ptr<instance_data>& description_data);
|
void set_file_description(const shared_pointer_type& description_data);
|
||||||
void set_file_name(const std::shared_ptr<instance_data>& name_data);
|
void set_file_name(const shared_pointer_type& name_data);
|
||||||
void set_file_schema(const std::shared_ptr<instance_data>& schema_data);
|
void set_file_schema(const shared_pointer_type& schema_data);
|
||||||
|
|
||||||
const Header_section_schema::file_description file_description() const;
|
const Header_section_schema::file_description file_description() const;
|
||||||
const Header_section_schema::file_name file_name() const;
|
const Header_section_schema::file_name file_name() const;
|
||||||
|
|||||||
+210
-37
@@ -28,7 +28,11 @@ namespace rocksdb {
|
|||||||
#include <boost/unordered_map.hpp>
|
#include <boost/unordered_map.hpp>
|
||||||
|
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstdint>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
@@ -37,6 +41,7 @@ namespace rocksdb {
|
|||||||
#include <list>
|
#include <list>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#ifndef SWIG
|
#ifndef SWIG
|
||||||
|
|
||||||
@@ -131,7 +136,7 @@ namespace ifcopenshell {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef std::variant<instance_reference, express::Base> reference_or_simple_type;
|
typedef std::variant<instance_reference, express::Base> reference_or_simple_type;
|
||||||
typedef std::list<std::pair<mutable_attribute_value, std::variant<reference_or_simple_type, std::vector<reference_or_simple_type>, std::vector<std::vector<reference_or_simple_type>>>>> unresolved_references;
|
typedef std::vector<std::pair<mutable_attribute_value, std::variant<reference_or_simple_type, std::vector<reference_or_simple_type>, std::vector<std::vector<reference_or_simple_type>>>>> unresolved_references;
|
||||||
|
|
||||||
class file;
|
class file;
|
||||||
template <typename Reader>
|
template <typename Reader>
|
||||||
@@ -205,38 +210,206 @@ namespace ifcopenshell {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IFC_PARSE_API parse_context {
|
|
||||||
std::vector<
|
|
||||||
std::variant<
|
|
||||||
express::Base,
|
|
||||||
token,
|
|
||||||
parse_context*
|
|
||||||
>> tokens_;
|
|
||||||
|
|
||||||
parse_context() {}
|
|
||||||
~parse_context();
|
|
||||||
|
|
||||||
parse_context(const parse_context& other) = delete;
|
|
||||||
parse_context& operator=(const parse_context& other) = delete;
|
|
||||||
|
|
||||||
parse_context(parse_context&& other) = default;
|
|
||||||
parse_context& operator=(parse_context&& other) = default;
|
|
||||||
|
|
||||||
parse_context& push();
|
|
||||||
|
|
||||||
void push(token next_token);
|
|
||||||
|
|
||||||
void push(const express::Base& instance);
|
|
||||||
|
|
||||||
std::shared_ptr<instance_data> construct(ifcopenshell::file* owner_file, std::optional<size_t> instance_name, unresolved_references& references_to_resolve, const ifcopenshell::declaration* declaration, std::optional<size_t> expected_size, int resolve_reference_index, bool coerce_attribute_count = true);
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace impl {
|
namespace impl {
|
||||||
|
struct inverse_record {
|
||||||
|
uint32_t referenced_id;
|
||||||
|
uint32_t source_id;
|
||||||
|
uint16_t source_entity;
|
||||||
|
int16_t attribute_index;
|
||||||
|
};
|
||||||
|
|
||||||
|
class inverse_index {
|
||||||
|
public:
|
||||||
|
typedef std::map<std::tuple<short, short>, std::vector<uint32_t>> legacy_bucket_t;
|
||||||
|
typedef std::unordered_map<int, legacy_bucket_t> legacy_map_t;
|
||||||
|
typedef legacy_map_t::key_type key_type;
|
||||||
|
typedef legacy_map_t::mapped_type mapped_type;
|
||||||
|
typedef legacy_map_t::value_type value_type;
|
||||||
|
typedef legacy_map_t::iterator iterator;
|
||||||
|
typedef legacy_map_t::const_iterator const_iterator;
|
||||||
|
typedef std::vector<inverse_record>::const_iterator record_iterator;
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable std::vector<inverse_record> records_;
|
||||||
|
mutable bool sorted_ = true;
|
||||||
|
mutable std::unique_ptr<legacy_map_t> materialized_;
|
||||||
|
|
||||||
|
static bool record_less(const inverse_record& a, const inverse_record& b) {
|
||||||
|
if (a.referenced_id != b.referenced_id) {
|
||||||
|
return a.referenced_id < b.referenced_id;
|
||||||
|
}
|
||||||
|
if (a.source_entity != b.source_entity) {
|
||||||
|
return a.source_entity < b.source_entity;
|
||||||
|
}
|
||||||
|
if (a.attribute_index != b.attribute_index) {
|
||||||
|
return a.attribute_index < b.attribute_index;
|
||||||
|
}
|
||||||
|
return a.source_id < b.source_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool referenced_less(const inverse_record& a, uint32_t referenced_id) {
|
||||||
|
return a.referenced_id < referenced_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool referenced_less(uint32_t referenced_id, const inverse_record& a) {
|
||||||
|
return referenced_id < a.referenced_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void invalidate_materialized() const {
|
||||||
|
materialized_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
legacy_map_t& materialize() const {
|
||||||
|
if (!materialized_) {
|
||||||
|
materialized_ = std::make_unique<legacy_map_t>();
|
||||||
|
materialized_->reserve(records_.size());
|
||||||
|
for (const auto& record : records_) {
|
||||||
|
(*materialized_)[(int)record.referenced_id][{(short)record.source_entity, (short)record.attribute_index}].push_back(record.source_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *materialized_;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
inverse_index() = default;
|
||||||
|
|
||||||
|
inverse_index(const inverse_index& other)
|
||||||
|
: records_(other.records_)
|
||||||
|
, sorted_(other.sorted_)
|
||||||
|
{}
|
||||||
|
|
||||||
|
inverse_index& operator=(const inverse_index& other) {
|
||||||
|
if (this != &other) {
|
||||||
|
records_ = other.records_;
|
||||||
|
sorted_ = other.sorted_;
|
||||||
|
materialized_.reset();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inverse_index(inverse_index&&) noexcept = default;
|
||||||
|
inverse_index& operator=(inverse_index&&) noexcept = default;
|
||||||
|
|
||||||
|
void reserve(size_t size) {
|
||||||
|
records_.reserve(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(uint32_t referenced_id, uint32_t source_id, uint16_t source_entity, int attribute_index) {
|
||||||
|
records_.push_back({referenced_id, source_id, source_entity, (int16_t)attribute_index});
|
||||||
|
sorted_ = false;
|
||||||
|
invalidate_materialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool remove(uint32_t referenced_id, uint32_t source_id, uint16_t source_entity, int attribute_index) {
|
||||||
|
const inverse_record needle{referenced_id, source_id, source_entity, (int16_t)attribute_index};
|
||||||
|
auto it = std::find_if(records_.begin(), records_.end(), [&needle](const inverse_record& record) {
|
||||||
|
return record.referenced_id == needle.referenced_id &&
|
||||||
|
record.source_id == needle.source_id &&
|
||||||
|
record.source_entity == needle.source_entity &&
|
||||||
|
record.attribute_index == needle.attribute_index;
|
||||||
|
});
|
||||||
|
if (it == records_.end()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
records_.erase(it);
|
||||||
|
invalidate_materialized();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove_source(uint32_t source_id) {
|
||||||
|
records_.erase(std::remove_if(records_.begin(), records_.end(), [source_id](const inverse_record& record) {
|
||||||
|
return record.source_id == source_id;
|
||||||
|
}), records_.end());
|
||||||
|
invalidate_materialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sort() const {
|
||||||
|
if (!sorted_) {
|
||||||
|
std::sort(records_.begin(), records_.end(), record_less);
|
||||||
|
sorted_ = true;
|
||||||
|
invalidate_materialized();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<record_iterator, record_iterator> equal_range(uint32_t referenced_id) const {
|
||||||
|
sort();
|
||||||
|
return std::equal_range(records_.begin(), records_.end(), referenced_id, [](const auto& a, const auto& b) {
|
||||||
|
if constexpr (std::is_same_v<std::decay_t<decltype(a)>, inverse_record>) {
|
||||||
|
return referenced_less(a, b);
|
||||||
|
} else {
|
||||||
|
return referenced_less(a, b);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<inverse_record>& records() const {
|
||||||
|
sort();
|
||||||
|
return records_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const {
|
||||||
|
return records_.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const {
|
||||||
|
return records_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
records_.clear();
|
||||||
|
sorted_ = true;
|
||||||
|
materialized_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator begin() {
|
||||||
|
return materialize().begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator end() {
|
||||||
|
return materialize().end();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator begin() const {
|
||||||
|
return materialize().begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator end() const {
|
||||||
|
return materialize().end();
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator find(const key_type& key) {
|
||||||
|
return materialize().find(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator find(const key_type& key) const {
|
||||||
|
return materialize().find(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t erase(const key_type& key) {
|
||||||
|
const auto old_size = records_.size();
|
||||||
|
records_.erase(std::remove_if(records_.begin(), records_.end(), [key](const inverse_record& record) {
|
||||||
|
return record.referenced_id == (uint32_t)key;
|
||||||
|
}), records_.end());
|
||||||
|
invalidate_materialized();
|
||||||
|
return old_size - records_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<iterator, bool> insert(const value_type& value) {
|
||||||
|
for (const auto& bucket : value.second) {
|
||||||
|
for (auto source_id : bucket.second) {
|
||||||
|
add((uint32_t)value.first, source_id, (uint16_t)std::get<0>(bucket.first), std::get<1>(bucket.first));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto it = find(value.first);
|
||||||
|
return {it, true};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct IFC_PARSE_API in_memory_file_storage {
|
struct IFC_PARSE_API in_memory_file_storage {
|
||||||
|
|
||||||
std::vector<std::shared_ptr<instance_data>> read_simple_type_instances;
|
std::vector<shared_pointer_type> read_simple_type_instances;
|
||||||
std::vector<std::shared_ptr<instance_data>> steal_instances() {
|
std::vector<shared_pointer_type> steal_instances() {
|
||||||
return read_simple_type_instances;
|
return std::move(read_simple_type_instances);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Either one of these needs to be set
|
// Either one of these needs to be set
|
||||||
@@ -246,14 +419,14 @@ namespace ifcopenshell {
|
|||||||
unresolved_references* references_to_resolve = nullptr;
|
unresolved_references* references_to_resolve = nullptr;
|
||||||
|
|
||||||
typedef std::map<const ifcopenshell::declaration*, std::vector<express::Base>> entities_by_type_t;
|
typedef std::map<const ifcopenshell::declaration*, std::vector<express::Base>> entities_by_type_t;
|
||||||
typedef boost::unordered_map<uint32_t, std::shared_ptr<instance_data>> entity_instance_by_name_storage_t;
|
typedef boost::unordered_map<uint32_t, shared_pointer_type> entity_instance_by_name_storage_t;
|
||||||
typedef map_transformer<entity_instance_by_name_storage_t, std::function<express::Base(std::shared_ptr<instance_data>)>> entity_instance_by_name_t;
|
typedef map_transformer<entity_instance_by_name_storage_t, std::function<express::Base(shared_pointer_type)>> entity_instance_by_name_t;
|
||||||
typedef boost::unordered_map<uint32_t, std::shared_ptr<instance_data>> type_instance_by_name_t;
|
typedef boost::unordered_map<uint32_t, shared_pointer_type> type_instance_by_name_t;
|
||||||
typedef std::map<std::string, express::Base> entity_instance_by_guid_t;
|
typedef std::map<std::string, express::Base> entity_instance_by_guid_t;
|
||||||
typedef std::unordered_map<int, std::map<std::tuple<short, short>, std::vector<uint32_t>>> entities_by_ref_t;
|
typedef inverse_index entities_by_ref_t;
|
||||||
typedef entity_instance_by_name_t::iterator iterator;
|
typedef entity_instance_by_name_t::iterator iterator;
|
||||||
|
|
||||||
in_memory_file_storage(ifcopenshell::file* owner_file = nullptr) : file(owner_file), schema(nullptr), byid_read_(&byid_, [this](const std::shared_ptr<instance_data>& data) { return express::Base(data); }) {};
|
in_memory_file_storage(ifcopenshell::file* owner_file = nullptr) : file(owner_file), schema(nullptr), byid_read_(&byid_, [this](const shared_pointer_type& data) { return express::Base(data); }) {};
|
||||||
in_memory_file_storage(const in_memory_file_storage& other) = delete;
|
in_memory_file_storage(const in_memory_file_storage& other) = delete;
|
||||||
in_memory_file_storage(const in_memory_file_storage&& other) = delete;
|
in_memory_file_storage(const in_memory_file_storage&& other) = delete;
|
||||||
|
|
||||||
@@ -299,7 +472,7 @@ namespace ifcopenshell {
|
|||||||
entity_instance_by_name_t byid_read_;
|
entity_instance_by_name_t byid_read_;
|
||||||
|
|
||||||
template <typename Reader>
|
template <typename Reader>
|
||||||
void load(ifcopenshell::spf_lexer<Reader>* tokens, std::optional<size_t> entity_instance_name, const ifcopenshell::entity* entity, parse_context& context, int attribute_index = -1);
|
shared_pointer_type load(ifcopenshell::spf_lexer<Reader>* tokens, std::optional<size_t> entity_instance_name, const ifcopenshell::declaration* declaration, const ifcopenshell::entity* entity, int attribute_index = -1, bool coerce_attribute_count = true);
|
||||||
template <typename Reader>
|
template <typename Reader>
|
||||||
void try_read_semicolon(ifcopenshell::spf_lexer<Reader>* tokens) const;
|
void try_read_semicolon(ifcopenshell::spf_lexer<Reader>* tokens) const;
|
||||||
|
|
||||||
@@ -353,7 +526,7 @@ namespace ifcopenshell {
|
|||||||
// to make sure that instance pointer are constant during file lifetime
|
// to make sure that instance pointer are constant during file lifetime
|
||||||
// cache instances because we want stable pointers
|
// cache instances because we want stable pointers
|
||||||
// @todo this is silly, but we cannot have the same type, this should be just a pointer then on the file side?
|
// @todo this is silly, but we cannot have the same type, this should be just a pointer then on the file side?
|
||||||
typedef std::map<uint32_t, std::shared_ptr<instance_data>> entity_by_iden_cache_t;
|
typedef std::map<uint32_t, shared_pointer_type> entity_by_iden_cache_t;
|
||||||
entity_by_iden_cache_t instance_cache_, type_instance_cache_;
|
entity_by_iden_cache_t instance_cache_, type_instance_cache_;
|
||||||
std::mutex instance_cache_mutex_;
|
std::mutex instance_cache_mutex_;
|
||||||
|
|
||||||
|
|||||||
@@ -54,10 +54,14 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void plugin_debug(const std::string& message) {
|
void plugin_debug(const std::string& message) {
|
||||||
|
#ifdef IFOPSH_PLUGIN_DEBUG
|
||||||
#if defined(_MSC_VER) && defined(_UNICODE)
|
#if defined(_MSC_VER) && defined(_UNICODE)
|
||||||
std::wcerr << "[ifcopenshell.plugin] " << message.c_str() << std::endl;
|
std::wcerr << "[ifcopenshell.plugin] " << message.c_str() << std::endl;
|
||||||
#else
|
#else
|
||||||
std::cerr << "[ifcopenshell.plugin] " << message << std::endl;
|
std::cerr << "[ifcopenshell.plugin] " << message << std::endl;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
static_cast<void>(message);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -78,14 +78,11 @@
|
|||||||
await micropip.install("typing-extensions");
|
await micropip.install("typing-extensions");
|
||||||
document.querySelector("#status2").innerHTML = "Loading IfcOpenShell";
|
document.querySelector("#status2").innerHTML = "Loading IfcOpenShell";
|
||||||
|
|
||||||
// await micropip.install("wheels/ifcopenshell-0.8.6-cp313-cp313-emscripten_4_0_9_wasm32.whl");
|
await micropip.install("wheels/modular/0.8.6+424e70a/ifcopenshell-0.8.6+424e70a-cp313-cp313-pyodide_2025_0_wasm32.whl");
|
||||||
|
await micropip.install("wheels/modular/0.8.6+424e70a/ifcopenshell_parse_schema_ifc4-0.8.6+424e70a-cp313-cp313-pyodide_2025_0_wasm32.whl");
|
||||||
await micropip.install("wheels/modular/0.8.6-b1899b1/ifcopenshell-0.8.6+b1899b1-cp313-cp313-pyodide_2025_0_wasm32.whl");
|
await micropip.install("wheels/modular/0.8.6+424e70a/ifcopenshell_geometry_mapping_ifc4-0.8.6+424e70a-cp313-cp313-pyodide_2025_0_wasm32.whl");
|
||||||
await micropip.install("wheels/modular/0.8.6-b1899b1/ifcopenshell_parse_schema_ifc4-0.8.6+b1899b1-cp313-cp313-pyodide_2025_0_wasm32.whl");
|
await micropip.install("wheels/modular/0.8.6+424e70a/ifcopenshell_pure_python-0.8.6+424e70a-py3-none-any.whl");
|
||||||
await micropip.install("wheels/modular/0.8.6-b1899b1/ifcopenshell_geometry_mapping_ifc4-0.8.6+b1899b1-cp313-cp313-pyodide_2025_0_wasm32.whl");
|
await micropip.install("wheels/modular/0.8.6+424e70a/ifcopenshell_geometry_kernel_manifold-0.8.6+424e70a-cp313-cp313-pyodide_2025_0_wasm32.whl");
|
||||||
await micropip.install("wheels/modular/0.8.6-b1899b1/ifcopenshell_pure_python-0.8.6+b1899b1-py3-none-any.whl");
|
|
||||||
await micropip.install("wheels/modular/0.8.6-b1899b1/ifcopenshell_geometry_kernel_cgalsimple-0.8.6+b1899b1-cp313-cp313-pyodide_2025_0_wasm32.whl");
|
|
||||||
await micropip.install("wheels/modular/0.8.6-b1899b1/ifcopenshell_geometry_kernel_opencascade-0.8.6+b1899b1-cp313-cp313-pyodide_2025_0_wasm32.whl");
|
|
||||||
|
|
||||||
document.body.className = '';
|
document.body.className = '';
|
||||||
|
|
||||||
@@ -295,7 +292,7 @@
|
|||||||
'settings': s,
|
'settings': s,
|
||||||
'file_or_filename': ifc,
|
'file_or_filename': ifc,
|
||||||
'exclude': ['IfcSpace', 'IfcOpeningElement'],
|
'exclude': ['IfcSpace', 'IfcOpeningElement'],
|
||||||
'geometry_library': 'hybrid-cgal-simple-opencascade'
|
'geometry_library': 'manifold'
|
||||||
});
|
});
|
||||||
|
|
||||||
let last_mesh_id = null;
|
let last_mesh_id = null;
|
||||||
@@ -372,7 +369,7 @@
|
|||||||
addObjToScene(ifcopenshell_geom.create_shape.callKwargs({
|
addObjToScene(ifcopenshell_geom.create_shape.callKwargs({
|
||||||
'settings': s,
|
'settings': s,
|
||||||
'inst': el,
|
'inst': el,
|
||||||
'geometry_library': 'hybrid-cgal-simple-opencascade'
|
'geometry_library': 'manifold'
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user