Some successes writing and reading

This commit is contained in:
Thomas Krijnen
2025-02-27 22:07:31 +01:00
parent c58c8269af
commit ce4407ff3c
19 changed files with 678 additions and 527 deletions
+14 -10
View File
@@ -206,7 +206,7 @@ size_t read_filters_from_file(const std::string&, inclusion_filter&, inclusion_t
void parse_filter(geom_filter &, const std::vector<std::string>&);
std::vector<IfcGeom::filter_t> setup_filters(const std::vector<geom_filter>&, const std::string&);
bool init_input_file(const std::string& filename, IfcParse::IfcFile*& ifc_file, bool no_progress, bool mmap);
bool init_input_file(const std::string& filename, IfcParse::IfcFile*& ifc_file, bool no_progress, bool mmap, bool rocksdb);
// from https://stackoverflow.com/questions/31696328/boost-program-options-using-zero-parameter-options-multiple-times
struct verbosity_counter {
@@ -239,6 +239,7 @@ int main(int argc, char** argv) {
path_t cache_file;
std::string log_format;
std::string geometry_kernel;
std::string input_format;
po::options_description generic_options("Command line options");
verbosity_counter vcounter;
@@ -254,6 +255,7 @@ int main(int argc, char** argv) {
("yes,y", "answer 'yes' automatically to possible confirmation queries (e.g. overwriting an existing output file)")
("no-progress", "suppress possible progress bar type of prints that use carriage return")
("log-format", po::value<std::string>(&log_format), "log format: plain or json")
("input-format", po::value<std::string>(&input_format), "input format: ifcspf, ifcxml, rocksdb")
("log-file", new po::typed_value<path_t, char_t>(&log_file), "redirect log output to file");
po::options_description fileio_options;
@@ -564,10 +566,12 @@ int main(int argc, char** argv) {
}
const path_t input_filename = vmap["input-file"].as<path_t>();
if (!file_exists(IfcUtil::path::to_utf8(input_filename))) {
/*
// todo also allow rocksdb dir
if (!file_exists(IfcUtil::path::to_utf8(input_filename))) {
cerr_ << "[Error] Input file '" << input_filename << "' does not exist" << std::endl;
return EXIT_FAILURE;
}
}*/
// If no output filename is specified a Wavefront OBJ file will be output
// to maintain backwards compatibility with the obsolete IfcObj executable.
@@ -658,7 +662,7 @@ int main(int argc, char** argv) {
if (output_extension == XML) {
int exit_code = EXIT_FAILURE;
try {
if (init_input_file(IfcUtil::path::to_utf8(input_filename), ifc_file, no_progress || quiet, mmap)) {
if (init_input_file(IfcUtil::path::to_utf8(input_filename), ifc_file, no_progress || quiet, mmap, input_format=="rocksdb")) {
time_t start, end;
time(&start);
XmlSerializer s(ifc_file, IfcUtil::path::to_utf8(output_temp_filename));
@@ -678,7 +682,7 @@ int main(int argc, char** argv) {
} else if (output_extension == IFC) {
int exit_code = EXIT_FAILURE;
try {
if (init_input_file(IfcUtil::path::to_utf8(input_filename), ifc_file, no_progress || quiet, mmap)) {
if (init_input_file(IfcUtil::path::to_utf8(input_filename), ifc_file, no_progress || quiet, mmap, input_format == "rocksdb")) {
time_t start, end;
time(&start);
std::ofstream fs(output_filename.c_str());
@@ -704,11 +708,11 @@ int main(int argc, char** argv) {
else if (output_extension == RDB) {
int exit_code = EXIT_FAILURE;
try {
if (init_input_file(IfcUtil::path::to_utf8(input_filename), ifc_file, no_progress || quiet, mmap)) {
if (init_input_file(IfcUtil::path::to_utf8(input_filename), ifc_file, no_progress || quiet, mmap, input_format == "rocksdb")) {
time_t start, end;
time(&start);
RocksDbSerializer s(ifc_file, IfcUtil::path::to_utf8(output_filename));
Logger::Status("Populating RockDB Key-Value store...");
Logger::Status("Populating RocksDB Key-Value store...");
s.finalize();
time(&end);
Logger::Status("Done! Conversion took " + format_duration(start, end));
@@ -937,7 +941,7 @@ int main(int argc, char** argv) {
time_t start,end;
time(&start);
if (!init_input_file(IfcUtil::path::to_utf8(input_filename), ifc_file, no_progress || quiet, mmap)) {
if (!init_input_file(IfcUtil::path::to_utf8(input_filename), ifc_file, no_progress || quiet, mmap, input_format == "rocksdb")) {
write_log(!quiet);
serializer.reset();
IfcUtil::path::delete_file(IfcUtil::path::to_utf8(output_temp_filename)); /**< @todo Windows Unicode support */
@@ -1270,7 +1274,7 @@ void write_log(bool header) {
#include <boost/algorithm/string/predicate.hpp>
bool init_input_file(const std::string& filename, IfcParse::IfcFile*& ifc_file, bool no_progress, bool mmap) {
bool init_input_file(const std::string& filename, IfcParse::IfcFile*& ifc_file, bool no_progress, bool mmap, bool rocksdb) {
time_t start, end;
// Prevent IfcFile::Init() prints by setting output to null temporarily
@@ -1289,7 +1293,7 @@ bool init_input_file(const std::string& filename, IfcParse::IfcFile*& ifc_file,
ifc_file = new IfcParse::IfcFile(filename, mmap);
#else
(void)mmap;
ifc_file = new IfcParse::IfcFile(filename);
ifc_file = new IfcParse::IfcFile(filename, rocksdb ? IfcParse::rocksdb : IfcParse::ifcspf);
#endif
}
+2 -2
View File
@@ -72,8 +72,8 @@ namespace IfcGeom {
friend bool operator < (const Element& element1, const Element& element2) {
if (element1.type() == "IfcBuildingStorey" && element2.type() == "IfcBuildingStorey") {
size_t attr_index = element1.product()->declaration().as_entity()->attribute_index("Elevation");
auto elev_attr1 = element1.product()->data().get_attribute_value(attr_index);
auto elev_attr2 = element2.product()->data().get_attribute_value(attr_index);
auto elev_attr1 = element1.product()->get_attribute_value(attr_index);
auto elev_attr2 = element2.product()->get_attribute_value(attr_index);
if (!elev_attr1.isNull() && !elev_attr2.isNull()) {
double elev1 = elev_attr1;
@@ -174,12 +174,10 @@ class EarlyBoundCodeWriter:
def begin_schema(self):
self.names.sort(key=str.lower)
schema_name = self.schema_name
schema_name = self.schema_name.upper()
num_names = len(self.names)
self.statements.append("declaration* %(schema_name)s_types[%(num_names)d] = {nullptr};" % locals())
self.statements.append("{string_pool_placeholder}")
self.statements.append("{factory_placeholder}")
# self.statements.append(
@@ -194,10 +192,11 @@ class EarlyBoundCodeWriter:
# #endif
# """
# )
self.statements.append("IfcParse::schema_definition* %s_populate_schema() {" % self.schema_name)
self.statements.append("IfcParse::schema_definition* %s_populate_schema() {" % self.schema_name.upper())
self.statements.append("{string_pool_placeholder}")
def typedef(self, name, declared_type):
schema_name = self.schema_name
schema_name = self.schema_name.upper()
index_in_schema = self.names.index(name)
ref = self.strings.append(name)
self.statements.append(
@@ -206,7 +205,7 @@ class EarlyBoundCodeWriter:
)
def enumeration(self, name, enum):
schema_name = self.schema_name
schema_name = self.schema_name.upper()
index_in_schema = self.names.index(name)
ref = self.strings.append(name)
items = ",".join(self.strings.append(v) for v in enum.values)
@@ -216,7 +215,7 @@ class EarlyBoundCodeWriter:
)
def entity(self, name, type):
schema_name = self.schema_name
schema_name = self.schema_name.upper()
index_in_schema = self.names.index(name)
ref = self.strings.append(name)
supertype = "0" if len(type.supertypes) == 0 else "%s_types[%d]" % (self.schema_name, self.names.index(type.supertypes[0]))
@@ -227,7 +226,7 @@ class EarlyBoundCodeWriter:
)
def select(self, name, type):
schema_name = self.schema_name
schema_name = self.schema_name.upper()
index_in_schema = self.names.index(name)
ref = self.strings.append(name)
items = ",".join(
@@ -239,7 +238,7 @@ class EarlyBoundCodeWriter:
)
def entity_attributes(self, name, attribute_definitions, is_derived):
schema_name = self.schema_name
schema_name = self.schema_name.upper()
index_in_schema = self.names.index(name)
def _():
index_in_schema = self.names.index(name)
@@ -253,7 +252,7 @@ class EarlyBoundCodeWriter:
self.statements.append(" ((entity*)%(schema_name)s_types[%(index_in_schema)d])->set_attributes({%(attributes)s}, {%(derived)s});" % locals())
def inverse_attributes(self, name, inv_attrs):
schema_name = self.schema_name
schema_name = self.schema_name.upper()
index_in_schema = self.names.index(name)
def _():
schema_name = self.schema_name
@@ -269,16 +268,16 @@ class EarlyBoundCodeWriter:
self.statements.append(" ((entity*) %(schema_name)s_types[%(index_in_schema)d])->set_inverse_attributes({%(attributes)s});" % locals())
def entity_subtypes(self, name, tys):
schema_name = self.schema_name
schema_name = self.schema_name.upper()
index_in_schema = self.names.index(name)
subtypes = ",".join(map(lambda t: ("((entity*) %%(schema_name)s_types[%d])" % self.names.index(t)), tys)) % locals()
self.statements.append(" ((entity*) %(schema_name)s_types[%(index_in_schema)d])->set_subtypes({%(subtypes)s});" % locals())
def finalize(self, can_be_instantiated_set):
schema_name = self.schema_name
schema_name = self.schema_name.upper()
schema_name_title = self.schema_name.capitalize()
def _():
schema_name = self.schema_name
schema_name = self.schema_name.upper()
schema_name_title = self.schema_name.capitalize()
for type_name in self.names:
index_in_schema = self.names.index(type_name)
@@ -378,6 +377,7 @@ class SchemaClass(codegen.Base):
def transform_to_indexed(fn):
def wrapper(*args, **kwargs):
schema_name_upper = mapping.schema.name.upper()
declared_type = fn(*args, **kwargs)
if 'simple_type' in declared_type:
pass
@@ -387,7 +387,7 @@ class SchemaClass(codegen.Base):
old_decl = match.group(1)
name = old_decl.lower().replace(schema_name.lower() + '_', '').replace('_type', '')
idx = [n.lower() for n in x.names].index(name)
declared_type = declared_type.replace(old_decl, '%(schema_name)s_types[%(idx)d]' % locals())
declared_type = declared_type.replace(old_decl, '%(schema_name_upper)s_types[%(idx)d]' % locals())
return declared_type
return wrapper if code == EarlyBoundCodeWriter else fn
+16 -16
View File
@@ -6,12 +6,9 @@
using namespace std::string_literals;
using namespace IfcParse;
declaration* header_section_schema_types[5] = {nullptr};
declaration* HEADER_SECTION_SCHEMA_types[5] = {nullptr};
const std::string strings[] = {"schema_name"s,"time_stamp_text"s,"file_description"s,"file_name"s,"file_schema"s,"description"s,"implementation_level"s,"name"s,"time_stamp"s,"author"s,"organization"s,"preprocessor_version"s,"originating_system"s,"authorisation"s,"schema_identifiers"s,"header_section_schema"s};
class header_section_schema_instance_factory : public IfcParse::instance_factory {
class HEADER_SECTION_SCHEMA_instance_factory : public IfcParse::instance_factory {
virtual IfcUtil::IfcBaseClass* operator()(const IfcParse::declaration* decl, IfcEntityInstanceData&& data) const {
switch(decl->index_in_schema()) {
case 0: return new ::Header_section_schema::file_description(std::move(data));
@@ -25,16 +22,19 @@ class header_section_schema_instance_factory : public IfcParse::instance_factory
}
};
IfcParse::schema_definition* header_section_schema_populate_schema() {
header_section_schema_types[3] = new type_declaration(strings[0], 3, new simple_type(simple_type::string_type));
header_section_schema_types[4] = new type_declaration(strings[1], 4, new simple_type(simple_type::string_type));
header_section_schema_types[0] = new entity(strings[2], false, 0, (entity*) 0);
header_section_schema_types[1] = new entity(strings[3], false, 1, (entity*) 0);
header_section_schema_types[2] = new entity(strings[4], false, 2, (entity*) 0);
((entity*)header_section_schema_types[0])->set_attributes({new attribute(strings[5], new aggregation_type(aggregation_type::list_type, 1, -1, new simple_type(simple_type::string_type)), false),new attribute(strings[6], new simple_type(simple_type::string_type), false)}, {false,false});
((entity*)header_section_schema_types[1])->set_attributes({new attribute(strings[7], new simple_type(simple_type::string_type), false),new attribute(strings[8], new named_type(header_section_schema_types[4]), false),new attribute(strings[9], new aggregation_type(aggregation_type::list_type, 1, -1, new simple_type(simple_type::string_type)), false),new attribute(strings[10], new aggregation_type(aggregation_type::list_type, 1, -1, new simple_type(simple_type::string_type)), false),new attribute(strings[11], new simple_type(simple_type::string_type), false),new attribute(strings[12], new simple_type(simple_type::string_type), false),new attribute(strings[13], new simple_type(simple_type::string_type), false)}, {false,false,false,false,false,false,false});
((entity*)header_section_schema_types[2])->set_attributes({new attribute(strings[14], new aggregation_type(aggregation_type::list_type, 1, -1, new named_type(header_section_schema_types[3])), false)}, {false});
return new schema_definition(strings[15], {header_section_schema_types[0],header_section_schema_types[1],header_section_schema_types[2],header_section_schema_types[3],header_section_schema_types[4]}, new header_section_schema_instance_factory());
IfcParse::schema_definition* HEADER_SECTION_SCHEMA_populate_schema() {
const std::string strings[] = {"schema_name"s,"time_stamp_text"s,"file_description"s,"file_name"s,"file_schema"s,"description"s,"implementation_level"s,"name"s,"time_stamp"s,"author"s,"organization"s,"preprocessor_version"s,"originating_system"s,"authorisation"s,"schema_identifiers"s,"HEADER_SECTION_SCHEMA"s};
HEADER_SECTION_SCHEMA_types[3] = new type_declaration(strings[0], 3, new simple_type(simple_type::string_type));
HEADER_SECTION_SCHEMA_types[4] = new type_declaration(strings[1], 4, new simple_type(simple_type::string_type));
HEADER_SECTION_SCHEMA_types[0] = new entity(strings[2], false, 0, (entity*) 0);
HEADER_SECTION_SCHEMA_types[1] = new entity(strings[3], false, 1, (entity*) 0);
HEADER_SECTION_SCHEMA_types[2] = new entity(strings[4], false, 2, (entity*) 0);
((entity*)HEADER_SECTION_SCHEMA_types[0])->set_attributes({new attribute(strings[5], new aggregation_type(aggregation_type::list_type, 1, -1, new simple_type(simple_type::string_type)), false),new attribute(strings[6], new simple_type(simple_type::string_type), false)}, {false,false});
((entity*)HEADER_SECTION_SCHEMA_types[1])->set_attributes({new attribute(strings[7], new simple_type(simple_type::string_type), false),new attribute(strings[8], new named_type(HEADER_SECTION_SCHEMA_types[4]), false),new attribute(strings[9], new aggregation_type(aggregation_type::list_type, 1, -1, new simple_type(simple_type::string_type)), false),new attribute(strings[10], new aggregation_type(aggregation_type::list_type, 1, -1, new simple_type(simple_type::string_type)), false),new attribute(strings[11], new simple_type(simple_type::string_type), false),new attribute(strings[12], new simple_type(simple_type::string_type), false),new attribute(strings[13], new simple_type(simple_type::string_type), false)}, {false,false,false,false,false,false,false});
((entity*)HEADER_SECTION_SCHEMA_types[2])->set_attributes({new attribute(strings[14], new aggregation_type(aggregation_type::list_type, 1, -1, new named_type(HEADER_SECTION_SCHEMA_types[3])), false)}, {false});
return new schema_definition(strings[15], {HEADER_SECTION_SCHEMA_types[0],HEADER_SECTION_SCHEMA_types[1],HEADER_SECTION_SCHEMA_types[2],HEADER_SECTION_SCHEMA_types[3],HEADER_SECTION_SCHEMA_types[4]}, new HEADER_SECTION_SCHEMA_instance_factory());
}
static std::unique_ptr<schema_definition> schema;
@@ -44,7 +44,7 @@ void Header_section_schema::clear_schema() {
const schema_definition& Header_section_schema::get_schema() {
if (!schema) {
schema.reset(header_section_schema_populate_schema());
schema.reset(HEADER_SECTION_SCHEMA_populate_schema());
}
return *schema;
}
+81 -45
View File
@@ -43,8 +43,8 @@ namespace {
!std::is_same_v<std::remove_cv_t<std::remove_pointer_t<T>>, IfcUtil::IfcBaseClass>)
{
std::string str;
array_.db_ptr->db->Get(rocksdb::ReadOptions{}, "a|" + std::to_string(instance_name_) + "|" + std::to_string(index_), &str);
impl::deserialize(str, val);
array_.db_ptr->db->Get(rocksdb::ReadOptions{}, "i|" + std::to_string(instance_name_) + "|" + std::to_string(index_), &str);
impl::deserialize(array_.db_ptr, str, val);
}
return val;
}
@@ -57,7 +57,7 @@ namespace {
return array_.storage_ptr->has<T>(index_);
} else {
std::string str;
array_.db_ptr->db->Get(rocksdb::ReadOptions{}, "a|" + std::to_string(instance_name_) + "|" + std::to_string(index_), &str);
array_.db_ptr->db->Get(rocksdb::ReadOptions{}, "i|" + std::to_string(instance_name_) + "|" + std::to_string(index_), &str);
return str[0] == TypeEncoder::encode_type<T>();
}
}
@@ -68,7 +68,7 @@ namespace {
return array_.storage_ptr->index(index_);
} else {
std::string str;
array_.db_ptr->db->Get(rocksdb::ReadOptions{}, "a|" + std::to_string(instance_name_) + "|" + std::to_string(index_), &str);
array_.db_ptr->db->Get(rocksdb::ReadOptions{}, "i|" + std::to_string(instance_name_) + "|" + std::to_string(index_), &str);
return (size_t) str[0] - 'A';
}
}
@@ -107,11 +107,11 @@ AttributeValue::operator std::string() const
return dispatch_get_<EnumerationReference>(array_, storage_model_, instance_name_, index_).value();
} else {
std::string str;
array_.db_ptr->db->Get(rocksdb::ReadOptions{}, "a|" + std::to_string(instance_name_) + "|" + std::to_string(index_), &str);
array_.db_ptr->db->Get(rocksdb::ReadOptions{}, "i|" + std::to_string(instance_name_) + "|" + std::to_string(index_), &str);
size_t v;
memcpy(&v, str.data() + 1, sizeof(size_t));
auto decl = schema_->declarations()[v]->as_enumeration_type();
memcpy(&v, str.data() + 5, sizeof(size_t));
memcpy(&v, str.data() + 1 + sizeof(size_t), sizeof(size_t));
return decl->lookup_enum_value(v);
}
}
@@ -124,7 +124,7 @@ AttributeValue::operator EnumerationReference() const
return dispatch_get_<EnumerationReference>(array_, storage_model_, instance_name_, index_);
} else {
std::string str;
array_.db_ptr->db->Get(rocksdb::ReadOptions{}, "a|" + std::to_string(instance_name_) + "|" + std::to_string(index_), &str);
array_.db_ptr->db->Get(rocksdb::ReadOptions{}, "i|" + std::to_string(instance_name_) + "|" + std::to_string(index_), &str);
size_t v;
memcpy(&v, str.data() + 1, sizeof(size_t));
auto decl = schema_->declarations()[v]->as_enumeration_type();
@@ -144,12 +144,17 @@ AttributeValue::operator IfcUtil::IfcBaseClass* () const
return dispatch_get_<IfcUtil::IfcBaseClass*>(array_, storage_model_, instance_name_, index_);
} else {
std::string str;
array_.db_ptr->db->Get(rocksdb::ReadOptions{}, "a|" + std::to_string(instance_name_) + "|" + std::to_string(index_), &str);
array_.db_ptr->db->Get(rocksdb::ReadOptions{}, "i|" + std::to_string(instance_name_) + "|" + std::to_string(index_), &str);
size_t v;
memcpy(&v, str.data() + 1, sizeof(size_t));
auto decl = schema_->declarations()[v]->as_enumeration_type();
memcpy(&v, str.data() + 5, sizeof(size_t));
return array_.db_ptr->assert_existance(v);
memcpy(&v, str.data() + 2, sizeof(size_t));
if (str[1] == 'e') {
// entity reference, by #Name
return array_.db_ptr->assert_existance(v, IfcParse::impl::rocks_db_file_storage::by_name);
} else if (str[1] == 't') {
// type reference by Identity
return array_.db_ptr->assert_existance(v, IfcParse::impl::rocks_db_file_storage::by_identity);
}
}
}
@@ -216,7 +221,7 @@ bool impl::serialize(std::string& val, const IfcUtil::IfcBaseClass* t)
val[0] = TypeEncoder::encode_type<IfcUtil::IfcBaseClass*>();
// 1 = entity - stored by id (entity name)
// 2 = type - stored by identity (internal counter in class)
val[1] = t->declaration().as_entity() ? 1 : 2;
val[1] = t->declaration().as_entity() ? 'e' : 't';
size_t iden = t->declaration().as_entity() ? t->id() : t->identity();
memcpy(val.data() + 2, &iden, s);
return true;
@@ -230,16 +235,24 @@ bool impl::serialize(std::string& val, const EnumerationReference& v)
size_t vv = v.enumeration()->index_in_schema();
memcpy(val.data() + 1, &vv, sizeof(size_t));
vv = v.index();
memcpy(val.data() + 1, &vv, sizeof(size_t));
memcpy(val.data() + 1 + sizeof(size_t), &vv, sizeof(size_t));
return true;
}
bool impl::serialize(std::string& val, const aggregate_of_instance::ptr& t)
{
std::vector<size_t> ids;
// @nb this has to be identity, because needs to work for typedecls as well
std::transform(t->begin(), t->end(), std::back_inserter(ids), [](auto& x) { return x->identity(); });
return false;
// no attempt at alignment
val.resize(t->size() * (sizeof(size_t) + 1) + 1);
val[0] = TypeEncoder::encode_type<EnumerationReference>();
char* ptr = val.data() + 1;
for (auto it = t->begin(); it != t->end(); ++it) {
*ptr = (*it)->declaration().as_entity() ? 'e' : 't';
ptr++;
size_t iden = (*it)->declaration().as_entity() ? (*it)->id() : (*it)->identity();
memcpy(ptr, &iden, sizeof(size_t));
ptr += sizeof(size_t);
}
return true;
}
bool impl::serialize(std::string& val, const aggregate_of_aggregate_of_instance::ptr& t)
@@ -282,7 +295,7 @@ bool impl::serialize(std::string& val, const boost::dynamic_bitset<>& t)
return false;
}
bool impl::deserialize(std::string& val, boost::logic::tribool& t) {
bool impl::deserialize(IfcParse::impl::rocks_db_file_storage*, const std::string& val, boost::logic::tribool& t) {
if (val[0] != TypeEncoder::encode_type<boost::logic::tribool>()) {
return false;
}
@@ -297,7 +310,7 @@ bool impl::deserialize(std::string& val, boost::logic::tribool& t) {
}
}
bool impl::deserialize(std::string& val, boost::dynamic_bitset<>& t) {
bool impl::deserialize(IfcParse::impl::rocks_db_file_storage*, const std::string& val, boost::dynamic_bitset<>& t) {
if (val[0] != TypeEncoder::encode_type<boost::dynamic_bitset<>>()) {
return false;
}
@@ -305,41 +318,64 @@ bool impl::deserialize(std::string& val, boost::dynamic_bitset<>& t) {
return true;
}
bool impl::deserialize(std::string& val, aggregate_of_instance::ptr& t) {
return false;
bool impl::deserialize(IfcParse::impl::rocks_db_file_storage* storage, const std::string& val, aggregate_of_instance::ptr& t) {
t.reset(new aggregate_of_instance);
// val[0] = TypeEncoder::encode_type<EnumerationReference>();
auto n = (val.size() - 1) / (sizeof(size_t) + 1);
for (int i = 0; i < n; ++i) {
auto ptr = val.data() + 1 + (sizeof(size_t) + 1) * i;
auto tt = *ptr;
ptr++;
size_t v;
memcpy(&v, ptr, sizeof(size_t));
if (tt == 'e') {
t->push(storage->assert_existance(v, IfcParse::impl::rocks_db_file_storage::by_name));
} else if (tt == 't') {
t->push(storage->assert_existance(v, IfcParse::impl::rocks_db_file_storage::by_identity));
} else {
throw std::runtime_error("");
}
}
return true;
}
bool impl::deserialize(std::string& val, aggregate_of_aggregate_of_instance::ptr& t) {
bool impl::deserialize(IfcParse::impl::rocks_db_file_storage*, const std::string& val, aggregate_of_aggregate_of_instance::ptr& t) {
return false;
}
template<typename T>
void rocks_db_attribute_storage::set(std::size_t index, const T& value)
void rocks_db_attribute_storage::set(void* storage, const IfcParse::declaration* decl, std::size_t identity, std::size_t index, const T& value)
{
const bool is_header = decl->schema() == &Header_section_schema::get_schema();
IfcParse::impl::rocks_db_file_storage* rdb_storage = (IfcParse::impl::rocks_db_file_storage*)storage;
std::string v;
impl::serialize(v, value);
fs_->db->Put(rocksdb::WriteOptions{}, prefix_ + ("|" + std::to_string(index)), v);
rdb_storage->db->Put(
rocksdb::WriteOptions{},
(is_header ? "h|" : "i|") +
(is_header ? decl->name() : std::to_string(identity)) + "|" +
std::to_string(index), v);
}
template void rocks_db_attribute_storage::set<Blank>(size_t index, const Blank& value);
template void rocks_db_attribute_storage::set<int>(size_t index, const int& value);
template void rocks_db_attribute_storage::set<bool>(size_t index, const bool& value);
template void rocks_db_attribute_storage::set<boost::logic::tribool>(size_t index, const boost::logic::tribool& value);
template void rocks_db_attribute_storage::set<double>(size_t index, const double& value);
template void rocks_db_attribute_storage::set<std::string>(size_t index, const std::string& value);
template void rocks_db_attribute_storage::set<boost::dynamic_bitset<>>(size_t index, const boost::dynamic_bitset<>& value);
template void rocks_db_attribute_storage::set<EnumerationReference>(size_t index, const EnumerationReference& value);
template void rocks_db_attribute_storage::set<IfcUtil::IfcBaseClass*>(size_t index, IfcUtil::IfcBaseClass* const& value);
template void rocks_db_attribute_storage::set<std::vector<int>>(size_t index, const std::vector<int>& value);
template void rocks_db_attribute_storage::set<std::vector<double>>(size_t index, const std::vector<double>& value);
template void rocks_db_attribute_storage::set<std::vector<std::string>>(size_t index, const std::vector<std::string>& value);
template void rocks_db_attribute_storage::set<std::vector<boost::dynamic_bitset<>>>(size_t index, const std::vector<boost::dynamic_bitset<>>& value);
template void rocks_db_attribute_storage::set<aggregate_of_instance::ptr>(size_t index, const aggregate_of_instance::ptr& value);
template void rocks_db_attribute_storage::set<std::vector<std::vector<int>>>(size_t index, const std::vector<std::vector<int>>& value);
template void rocks_db_attribute_storage::set<std::vector<std::vector<double>>>(size_t index, const std::vector<std::vector<double>>& value);
template void rocks_db_attribute_storage::set<aggregate_of_aggregate_of_instance::ptr>(size_t index, const aggregate_of_aggregate_of_instance::ptr& value);
template void rocks_db_attribute_storage::set<Blank>(void* storage, const IfcParse::declaration* decl, std::size_t identity, size_t index, const Blank& value);
template void rocks_db_attribute_storage::set<int>(void* storage, const IfcParse::declaration* decl, std::size_t identity, size_t index, const int& value);
template void rocks_db_attribute_storage::set<bool>(void* storage, const IfcParse::declaration* decl, std::size_t identity, size_t index, const bool& value);
template void rocks_db_attribute_storage::set<boost::logic::tribool>(void* storage, const IfcParse::declaration* decl, std::size_t identity, size_t index, const boost::logic::tribool& value);
template void rocks_db_attribute_storage::set<double>(void* storage, const IfcParse::declaration* decl, std::size_t identity, size_t index, const double& value);
template void rocks_db_attribute_storage::set<std::string>(void* storage, const IfcParse::declaration* decl, std::size_t identity, size_t index, const std::string& value);
template void rocks_db_attribute_storage::set<boost::dynamic_bitset<>>(void* storage, const IfcParse::declaration* decl, std::size_t identity, size_t index, const boost::dynamic_bitset<>& value);
template void rocks_db_attribute_storage::set<EnumerationReference>(void* storage, const IfcParse::declaration* decl, std::size_t identity, size_t index, const EnumerationReference& value);
template void rocks_db_attribute_storage::set<IfcUtil::IfcBaseClass*>(void* storage, const IfcParse::declaration* decl, std::size_t identity, size_t index, IfcUtil::IfcBaseClass* const& value);
template void rocks_db_attribute_storage::set<std::vector<int>>(void* storage, const IfcParse::declaration* decl, std::size_t identity, size_t index, const std::vector<int>& value);
template void rocks_db_attribute_storage::set<std::vector<double>>(void* storage, const IfcParse::declaration* decl, std::size_t identity, size_t index, const std::vector<double>& value);
template void rocks_db_attribute_storage::set<std::vector<std::string>>(void* storage, const IfcParse::declaration* decl, std::size_t identity, size_t index, const std::vector<std::string>& value);
template void rocks_db_attribute_storage::set<std::vector<boost::dynamic_bitset<>>>(void* storage, const IfcParse::declaration* decl, std::size_t identity, size_t index, const std::vector<boost::dynamic_bitset<>>& value);
template void rocks_db_attribute_storage::set<aggregate_of_instance::ptr>(void* storage, const IfcParse::declaration* decl, std::size_t identity, size_t index, const aggregate_of_instance::ptr& value);
template void rocks_db_attribute_storage::set<std::vector<std::vector<int>>>(void* storage, const IfcParse::declaration* decl, std::size_t identity, size_t index, const std::vector<std::vector<int>>& value);
template void rocks_db_attribute_storage::set<std::vector<std::vector<double>>>(void* storage, const IfcParse::declaration* decl, std::size_t identity, size_t index, const std::vector<std::vector<double>>& value);
template void rocks_db_attribute_storage::set<aggregate_of_aggregate_of_instance::ptr>(void* storage, const IfcParse::declaration* decl, std::size_t identity, size_t index, const aggregate_of_aggregate_of_instance::ptr& value);
// @todo why do these need to be included, but are not in BaseEntity::set()?
template void rocks_db_attribute_storage::set<Derived>(size_t index, const Derived& value);
template void rocks_db_attribute_storage::set<empty_aggregate_t>(size_t index, const empty_aggregate_t& value);
template void rocks_db_attribute_storage::set<empty_aggregate_of_aggregate_t>(size_t index, const empty_aggregate_of_aggregate_t& value);
template void rocks_db_attribute_storage::set<Derived>(void* storage, const IfcParse::declaration* decl, std::size_t identity, size_t index, const Derived& value);
template void rocks_db_attribute_storage::set<empty_aggregate_t>(void* storage, const IfcParse::declaration* decl, std::size_t identity, size_t index, const empty_aggregate_t& value);
template void rocks_db_attribute_storage::set<empty_aggregate_of_aggregate_t>(void* storage, const IfcParse::declaration* decl, std::size_t identity, size_t index, const empty_aggregate_of_aggregate_t& value);
+90 -72
View File
@@ -172,11 +172,6 @@ namespace impl {
template <typename CharT, typename Traits, typename Alloc>
struct is_contiguous_container<std::basic_string<CharT, Traits, Alloc>> : std::true_type {};
template <typename T, typename std::enable_if<is_contiguous_container<T>::value && is_contiguous_container<typename T::value_type>::value, int>::type = 0>
bool serialize(std::string& val, const T& t) {
return false;
}
template <typename T, typename std::enable_if<is_contiguous_container<T>::value && !is_contiguous_container<typename T::value_type>::value, int>::type = 0>
bool serialize(std::string& val, const T& t) {
auto s = sizeof(typename T::value_type) * t.size();
@@ -186,6 +181,22 @@ namespace impl {
return true;
}
template <typename T, typename std::enable_if<is_contiguous_container<T>::value&& is_contiguous_container<typename T::value_type>::value, int>::type = 0>
bool serialize(std::string& val, const T& t) {
val = std::string(1, TypeEncoder::encode_type<T>());
for (auto& tt : t) {
std::string v2;
serialize(v2, tt);
std::string len(sizeof(size_t), 0);
size_t s = v2.size() - 1;
memcpy(len.data(), &s, sizeof(size_t));
// @todo horribly inefficient
// @todo strip off type label?
val += len + v2.substr(1);
}
return true;
}
template <typename T, typename std::enable_if<std::is_integral_v<T> || std::is_floating_point_v<T>, int>::type = 0>
bool serialize(std::string& val, const T& t) {
val.resize(sizeof(T) + 1);
@@ -212,20 +223,41 @@ namespace impl {
bool serialize(std::string& val, const aggregate_of_aggregate_of_instance::ptr& t);
template <typename T, typename std::enable_if<is_contiguous_container<T>::value, int>::type = 0>
bool deserialize(std::string& val, T& t) {
// @todo vector of vector
if (val[0] != TypeEncoder::encode_type<T>()) {
template <typename T, typename std::enable_if<is_contiguous_container<T>::value && !is_contiguous_container<typename T::value_type>::value, int>::type = 0>
bool deserialize(IfcParse::impl::rocks_db_file_storage*, const std::string& val, T& t, bool prefixed = true) {
if (prefixed && val[0] != TypeEncoder::encode_type<T>()) {
return false;
}
auto s = (val.size() - 1) / sizeof(typename T::value_type);
auto s = (val.size() - (prefixed ? 1 : 0)) / sizeof(typename T::value_type);
t.resize(s);
memcpy(t.data(), val.data() + 1, s * sizeof(typename T::value_type));
memcpy(t.data(), val.data() + (prefixed ? 1 : 0), s * sizeof(typename T::value_type));
return true;
}
template <typename T, typename std::enable_if<is_contiguous_container<T>::value && is_contiguous_container<typename T::value_type>::value, int>::type = 0>
bool deserialize(IfcParse::impl::rocks_db_file_storage* storage, const std::string& val, T& t) {
// @todo
auto ptr = val.data();
if (*ptr != TypeEncoder::encode_type<T>()) {
return false;
}
ptr++;
t.clear();
while (ptr < val.data() + val.size()) {
size_t s;
memcpy(&s, ptr, sizeof(size_t));
// @todo view
ptr += sizeof(size_t);
std::string part(ptr, s);
t.emplace_back();
deserialize(storage, part, t.back(), false);
ptr += s;
}
return true;
}
template <typename T, typename std::enable_if<std::is_integral_v<T> || std::is_floating_point_v<T>, int>::type = 0>
bool deserialize(std::string & val, T & t) {
bool deserialize(IfcParse::impl::rocks_db_file_storage*, const std::string& val, T & t) {
if (val[0] != TypeEncoder::encode_type<T>()) {
return false;
}
@@ -234,13 +266,13 @@ namespace impl {
return true;
}
bool deserialize(std::string& val, boost::logic::tribool& t);
bool deserialize(IfcParse::impl::rocks_db_file_storage*, const std::string& val, boost::logic::tribool& t);
bool deserialize(std::string& val, boost::dynamic_bitset<>& t);
bool deserialize(IfcParse::impl::rocks_db_file_storage*, const std::string& val, boost::dynamic_bitset<>& t);
bool deserialize(std::string& val, aggregate_of_instance::ptr& t);
bool deserialize(IfcParse::impl::rocks_db_file_storage*, const std::string& val, aggregate_of_instance::ptr& t);
bool deserialize(std::string& val, aggregate_of_aggregate_of_instance::ptr& t);
bool deserialize(IfcParse::impl::rocks_db_file_storage*, const std::string& val, aggregate_of_aggregate_of_instance::ptr& t);
}
@@ -250,7 +282,7 @@ struct AttributeValue {
uint8_t storage_model_ = 0;
size_t instance_name_;
// @todo couple with db_ptr;
IfcParse::schema_definition* schema_;
const IfcParse::schema_definition* schema_;
union pointer_type {
const in_memory_attribute_storage* storage_ptr;
IfcParse::impl::rocks_db_file_storage* db_ptr;
@@ -271,7 +303,7 @@ struct AttributeValue {
, storage_model_(0)
{}
AttributeValue(IfcParse::schema_definition* schema, IfcParse::impl::rocks_db_file_storage* db, size_t instance_name, uint8_t index)
AttributeValue(const IfcParse::schema_definition* schema, IfcParse::impl::rocks_db_file_storage* db, size_t instance_name, uint8_t index)
: index_(index)
, array_(db)
, storage_model_(1)
@@ -307,11 +339,6 @@ struct AttributeValue {
struct rocks_db_attribute_storage {
private:
// @todo not needed as call always passes through EntityInstanceData
IfcParse::impl::rocks_db_file_storage* fs_;
// @todo not needed should be passed from call stack
const char* prefix_;
template<typename Visitor, std::size_t Index>
auto apply_visitor_impl(Visitor&& visitor, std::size_t idx, std::integral_constant<std::size_t, Index>) const {
return apply_visitor_impl(std::forward<Visitor>(visitor), idx, std::integral_constant<std::size_t, Index - 1>{});
@@ -323,59 +350,31 @@ private:
}
public:
rocks_db_attribute_storage(IfcParse::impl::rocks_db_file_storage* fs, const char* const prefix)
: fs_(fs)
, prefix_(prefix)
{}
rocks_db_attribute_storage(rocks_db_attribute_storage& other)
: fs_(other.fs_)
, prefix_(other.prefix_)
{}
rocks_db_attribute_storage(rocks_db_attribute_storage&& other)
: fs_(other.fs_)
, prefix_(other.prefix_)
{}
rocks_db_attribute_storage& operator=(const rocks_db_attribute_storage& other) {
if (this != &other) {
fs_ = other.fs_;
prefix_ = other.prefix_;
}
return *this;
}
rocks_db_attribute_storage& operator=(const rocks_db_attribute_storage&& other) {
if (this != &other) {
fs_ = other.fs_;
prefix_ = other.prefix_;
}
return *this;
}
size_t size() const {
size_t size(void*, const IfcParse::declaration*, std::size_t identity) const {
// @todo is this actually needed?
return 8;
}
// @todo void* is obviously very ugly here
template<typename T>
void set(std::size_t index, const T& value);
void set(void* storage, const IfcParse::declaration*, std::size_t identity, std::size_t index, const T& value);
template<typename T>
bool has(std::size_t index) const {
bool has(void* storage, const IfcParse::declaration*, std::size_t identity, std::size_t index) const {
// @todo
return false;
}
template<typename Visitor>
auto apply_visitor(Visitor&& visitor, std::size_t index) const {
auto apply_visitor(void* storage, const IfcParse::declaration*, std::size_t identity, std::size_t index, Visitor&& visitor) const {
return apply_visitor_impl(std::forward<Visitor>(visitor), index, std::integral_constant<std::size_t, type_variant_parameter_pack::size>{});
}
};
class IFC_PARSE_API IfcEntityInstanceData {
public:
// @todo since rocks_db_attribute_storage has no members anymore, change to in_memory_attribute_storage*?
// 24 -> 8 bytes...
std::variant<in_memory_attribute_storage, rocks_db_attribute_storage> storage_;
IfcEntityInstanceData(in_memory_attribute_storage&& storage)
@@ -390,7 +389,8 @@ class IFC_PARSE_API IfcEntityInstanceData {
: storage_(std::move(other.storage_))
{}
IfcEntityInstanceData(const IfcEntityInstanceData& data);
// No copy-constructor anymore because we need the instance for storage model context
IfcEntityInstanceData(const IfcEntityInstanceData&) = delete;
IfcEntityInstanceData& operator=(IfcEntityInstanceData&& other) {
if (this != &other) {
@@ -399,34 +399,52 @@ class IFC_PARSE_API IfcEntityInstanceData {
return *this;
}
AttributeValue get_attribute_value(size_t index) const;
AttributeValue get_attribute_value(void* storage, const IfcParse::declaration*, std::size_t identity, size_t index) const;
template<typename T>
void set_attribute_value(std::size_t index, T&& value) {
std::visit([&index, &value](auto& x) {
return x.set(index, value);
void set_attribute_value(void* storage, const IfcParse::declaration* decl, std::size_t identity, std::size_t index, T&& value) {
std::visit([&index, &value, storage, decl, identity](auto& x) {
if constexpr (std::is_same_v<std::decay_t<decltype(x)>, in_memory_attribute_storage>) {
return x.set(index, value);
} else {
return x.set(storage, decl, identity, index, value);
}
}, storage_);
}
template<typename T>
bool has_attribute_value(std::size_t index) const {
return std::visit([&index](const auto& x) {
return x.has<T>(index);
bool has_attribute_value(void* storage, const IfcParse::declaration* decl, std::size_t identity, std::size_t index) const {
return std::visit([&index, storage, decl, identity](const auto& x) {
if constexpr (std::is_same_v<std::decay_t<decltype(x)>, in_memory_attribute_storage>) {
return x.has<T>(index);
} else {
return x.has<T>(storage, decl, identity, index);
}
}, storage_);
}
template<typename Visitor>
auto apply_visitor(Visitor&& visitor, std::size_t index) const {
return std::visit([&index, &visitor](const auto& x) {
return x.apply_visitor(std::forward<Visitor>(visitor), index);
auto apply_visitor(void* storage, const IfcParse::declaration* decl, std::size_t identity, Visitor&& visitor, std::size_t index) const {
return std::visit([&index, &visitor, storage, decl, identity](const auto& x) {
if constexpr (std::is_same_v<std::decay_t<decltype(x)>, in_memory_attribute_storage>) {
return x.apply_visitor(std::forward<Visitor>(visitor), index);
} else {
return x.apply_visitor(storage, decl, identity, index, std::forward<Visitor>(visitor));
}
}, storage_);
}
size_t size() const {
return std::visit([](const auto& x) { return x.size(); }, storage_);
size_t size(void* storage, const IfcParse::declaration* decl, std::size_t identity) const {
return std::visit([storage, decl, identity](const auto& x) {
if constexpr (std::is_same_v<std::decay_t<decltype(x)>, in_memory_attribute_storage>) {
return x.size();
} else {
return x.size(storage, decl, identity);
}
}, storage_);
}
void toString(std::ostream&, bool upper = false, const IfcParse::entity* ent = nullptr) const;
void toString(void* storage, const IfcParse::declaration*, std::size_t identity, std::ostream&, bool upper = false) const;
};
#endif
+65 -17
View File
@@ -337,7 +337,7 @@ IfcUtil::IfcBaseClass* IfcParse::impl::rocks_db_file_storage::rocksdb_instance_i
if (jt != storage_->instance_cache_.end()) {
return jt->second;
} else {
return storage_->assert_existance(it->second);
return storage_->assert_existance(it->first, by_name);
}
}
}
@@ -346,46 +346,94 @@ const IfcParse::declaration* IfcParse::impl::rocks_db_file_storage::rocksdb_type
return storage_->file->schema()->declarations()[*read_id_()];
}
IfcUtil::IfcBaseClass* IfcParse::impl::rocks_db_file_storage::assert_existance(size_t instanceId) {
IfcUtil::IfcBaseClass* IfcParse::impl::rocks_db_file_storage::assert_existance(size_t number, instance_ref r) {
size_t name, identity;
std::string v;
rocksdb::Status s = db->Get(rocksdb::ReadOptions{}, "i|" + std::to_string(instanceId) + "|t", &v);
if (r == by_identity) {
name = 0;
identity = number;
} else {
name = number;
auto it = byid_.find(name);
if (it == byid_.end()) {
throw std::runtime_error("Unable to lookup identity of name: #" + std::to_string(number));
}
identity = it->second;
}
decltype(instance_cache_)::const_iterator it = instance_cache_.find(identity);
if (it != instance_cache_.end()) {
return it->second;
}
rocksdb::Status s = db->Get(rocksdb::ReadOptions{}, "i|" + std::to_string(identity) + "|t", &v);
if (s.ok()) {
size_t s;
memcpy(&s, v.data(), sizeof(size_t));
if (s >= file->schema()->declarations().size()) {
throw std::runtime_error("");
}
auto decl = file->schema()->declarations()[s];
IfcEntityInstanceData data(rocks_db_attribute_storage(this, "i|"));
bool is_entity = decl->as_entity() != nullptr;
if (is_entity != (r == by_name)) {
throw std::runtime_error("Incorrect reference");
}
IfcEntityInstanceData data(rocks_db_attribute_storage{});
auto inst = file->schema()->instantiate(decl, std::move(data));
inst->id_ = instanceId;
inst->id_ = name;
inst->file_ = file;
instance_cache_.insert({ inst->identity(), inst });
byid_.insert({ inst->id(), inst->identity() });
if (is_entity) {
byid_.insert({ inst->id(), inst->identity() });
}
return inst;
}
throw std::runtime_error("");
}
namespace {
rocksdb::DB* init_db(const std::string& filepath) {
rocksdb::DB* db;
rocksdb::Options options;
options.create_if_missing = true;
// options.merge_operator.reset(new ConcatenateIdMergeOperator());
rocksdb::Status status = rocksdb::DB::Open(options, filepath, &db);
if (!status.ok()) {
throw std::runtime_error(status.ToString());
}
return db;
}
}
// @todo naming
IfcParse::impl::rocks_db_file_storage::rocks_db_file_storage(const std::string& filepath, IfcParse::IfcFile* ffile)
: file(ffile)
// @todo db is not initialized here yet
, db(init_db(filepath))
, byguid_internal_(db, "g|")
, byguid_(&byguid_internal_, [this](size_t v) { return assert_existance(v); }, [](IfcUtil::IfcBaseClass* v) { return v->identity(); })
, byguid_(&byguid_internal_, [this](size_t v) { return assert_existance(v, by_name); }, [](IfcUtil::IfcBaseClass* v) { return v->identity(); })
, byid_(db, "d|")
, bytype_(db, "t|")
, byidentity_(&byid_, [this](size_t v) { return assert_existance(v); }, [](IfcUtil::IfcBaseClass* v) { return v->identity(); })
// @todo by_identity is probably not correct here, this mapping is Name -> Identity, so Fn should have access to full pair?
, byidentity_(&byid_, [this](size_t v) { return assert_existance(v, by_identity); }, [](IfcUtil::IfcBaseClass* v) { return v->identity(); })
{}
IfcParse::impl::rocks_db_file_storage::~rocks_db_file_storage()
{
rocksdb::Options options;
options.create_if_missing = true;
options.merge_operator.reset(new ConcatenateIdMergeOperator());
rocksdb::Status status = rocksdb::DB::Open(options, filepath, &db);
if (!status.ok()) {
throw std::runtime_error(status.ToString());
}
rocksdb::FlushOptions flush_options;
flush_options.allow_write_stall = true;
flush_options.wait = true; // Wait until flush completes.
rocksdb::Status s = db->Flush(flush_options);
assert(s.ok());
db->Close();
delete db;
}
IfcUtil::IfcBaseClass* IfcParse::impl::rocks_db_file_storage::instance_by_id(int id)
{
// @todo rename assert_existance() -> instance_by_id();
return assert_existance(id);
return assert_existance(id, by_name);
}
void IfcParse::impl::rocks_db_file_storage::process_deletion_inverse(IfcUtil::IfcBaseClass* inst)
+36 -22
View File
@@ -37,17 +37,18 @@
#include <iterator>
#include <map>
#include "rocksdb/merge_operator.h"
// #include "rocksdb/merge_operator.h"
/*
namespace {
// @todo move to a proper place
class ConcatenateIdMergeOperator : public rocksdb::AssociativeMergeOperator {
public:
virtual bool Merge(const rocksdb::Slice& key,
virtual bool Merge(const rocksdb::Slice&,
const rocksdb::Slice* existing_value,
const rocksdb::Slice& value,
std::string* new_value,
rocksdb::Logger* logger) const override {
rocksdb::Logger*) const override
{
if (existing_value) {
new_value->assign(existing_value->data(), existing_value->size());
new_value->append(value.data(), value.size());
@@ -62,6 +63,7 @@ namespace {
}
};
}
*/
namespace IfcParse {
@@ -348,7 +350,11 @@ namespace impl {
IfcUtil::IfcBaseClass* create(const IfcParse::declaration* decl);
};
struct rocks_db_file_storage {
class rocks_db_file_storage {
public:
rocksdb::DB* db;
IfcParse::IfcFile* file;
// to make sure that instance pointer are constant during file lifetime
// 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 IfcFile side?
@@ -375,20 +381,18 @@ namespace impl {
typedef map_transformer<rocksdb_map_adapter<std::string, size_t>, std::function<IfcUtil::IfcBaseClass* (size_t)>, std::function< size_t(IfcUtil::IfcBaseClass*)>> entity_by_guid_t;
entity_by_guid_t byguid_;
rocksdb::DB* db;
IfcParse::IfcFile* file;
// @todo naming
rocks_db_file_storage(const std::string& filepath, IfcParse::IfcFile* ffile);
rocks_db_file_storage(const std::string& filepath, IfcParse::IfcFile* file);
~rocks_db_file_storage();
bool read_schema(const IfcParse::schema_definition*& schema) {
// @todo
schema = nullptr;
return true;
}
bool read_schema(const IfcParse::schema_definition*& schema);
enum instance_ref {
by_name,
by_identity
};
IfcUtil::IfcBaseClass* assert_existance(size_t instanceId);
IfcUtil::IfcBaseClass* assert_existance(size_t instanceId, instance_ref r);
// @todo this could be another map_adapter?
class rocksdb_instance_iterator {
@@ -396,7 +400,7 @@ namespace impl {
rocksdb::Iterator* state_;
rocks_db_file_storage* storage_;
static constexpr char prefix_[] = "a|";
static constexpr char prefix_[] = "i|";
boost::optional<size_t> read_id_() const {
auto sv = state_->key().ToStringView();
@@ -810,29 +814,37 @@ IFC_PARSE_API IfcFile* parse_ifcxml(const std::string& filename);
template <typename T>
T* IfcParse::impl::in_memory_file_storage::create() {
IfcUtil::IfcBaseClass* inst = nullptr;
if constexpr (std::is_same_v<std::decay_t<std::invoke_result_t<T::Class>>, IfcParse::entity>) {
return file->addEntity(new T(in_memory_attribute_storage(T::Class().attribute_count())))->as<T>();
inst = new T(in_memory_attribute_storage(T::Class().attribute_count()));
} else if constexpr (std::is_same_v<std::decay_t<std::invoke_result_t<T::Class>>, IfcParse::type_declaration>) {
return file->addEntity(new T(in_memory_attribute_storage(1)))->as<T>();
inst = new T(in_memory_attribute_storage(1));
} else {
static_assert(false, "Requires and entity or type declaration");
}
inst->file_ = file;
return file->addEntity(inst)->as<T>();
}
IfcUtil::IfcBaseClass* IfcParse::impl::in_memory_file_storage::create(const IfcParse::declaration* decl) {
IfcUtil::IfcBaseClass* inst = nullptr;
if (auto* ent = decl->as_entity()) {
return file->addEntity(file->schema()->instantiate(decl, in_memory_attribute_storage(ent->attribute_count())));
inst = file->schema()->instantiate(decl, in_memory_attribute_storage(ent->attribute_count()));
} else if (auto* typedecl = decl->as_type_declaration()) {
return file->addEntity(file->schema()->instantiate(decl, in_memory_attribute_storage(1)));
inst = file->schema()->instantiate(decl, in_memory_attribute_storage(1));
} else {
throw std::runtime_error("Requires and entity or type declaration");
}
inst->file_ = file;
return file->addEntity(inst);
}
template <typename T>
T* IfcParse::impl::rocks_db_file_storage::create() {
if constexpr (std::is_same_v<std::decay_t<std::invoke_result_t<T::Class>>, IfcParse::entity> || std::is_same_v<std::decay_t<std::invoke_result_t<T::Class>>, IfcParse::type_declaration>) {
return file->addEntity(new T(rocks_db_attribute_storage{}))->as<T>();
auto* inst = new T(rocks_db_attribute_storage{});
inst->file_ = file;
return file->addEntity(inst)->as<T>();
} else {
static_assert(false, "Requires and entity or type declaration");
}
@@ -840,7 +852,9 @@ T* IfcParse::impl::rocks_db_file_storage::create() {
IfcUtil::IfcBaseClass* IfcParse::impl::rocks_db_file_storage::create(const IfcParse::declaration* decl) {
if (decl->as_entity() || decl->as_type_declaration()) {
return file->addEntity(file->schema()->instantiate(decl, rocks_db_attribute_storage(this, "i|")));
auto* inst = file->schema()->instantiate(decl, rocks_db_attribute_storage{});
inst->file_ = file;
return file->addEntity(inst);
} else {
throw std::runtime_error("Requires and entity or type declaration");
}
+5 -8
View File
@@ -434,20 +434,17 @@ class IFC_PARSE_API IfcHierarchyHelper : public IfcParse::IfcFile {
aggregate_of_instance::ptr related_objects(new aggregate_of_instance);
related_objects->push(related_object);
IfcEntityInstanceData data = IfcEntityInstanceData(in_memory_attribute_storage(T::Class().attribute_count()));
data.set_attribute_value(0, (std::string)IfcParse::IfcGlobalId());
data.set_attribute_value(1, owner_hist);
T* t = create(&T::Class())->as<T>();
t->set_attribute_value(0, (std::string)IfcParse::IfcGlobalId());
t->set_attribute_value(1, owner_hist);
int relating_index = 4;
int related_index = 5;
if (T::Class().name() == "IfcRelContainedInSpatialStructure" || std::is_base_of<typename Schema::IfcRelDefines, T>::value) {
// some classes have attributes reversed.
std::swap(relating_index, related_index);
}
data.set_attribute_value(relating_index, relating_object);
data.set_attribute_value(related_index, related_objects);
T* t = (T*)Schema::get_schema().instantiate(&T::Class(), std::move(data));
addEntity(t);
t->set_attribute_value(relating_index, relating_object);
t->set_attribute_value(related_index, related_objects);
}
}
+197 -112
View File
@@ -791,10 +791,21 @@ void IfcParse::impl::rocks_db_file_storage::register_inverse(unsigned id_from, c
size_t v = id_from;
s.resize(sizeof(size_t));
memcpy(s.data(), &v, sizeof(size_t));
/*
// no merges yet, because python client doesn't support them
db->Merge(
rocksdb::WriteOptions{},
"v|" + to_string_fixed_width(inst_id, 10) + "|" + to_string_fixed_width(from_entity->index_in_schema(), 4) + "|" + to_string_fixed_width(attribute_index, 2),
,
s);
*/
{
std::string current;
auto key = "v|" + to_string_fixed_width(inst_id, 10) + "|" + to_string_fixed_width(from_entity->index_in_schema(), 4) + "|" + to_string_fixed_width(attribute_index, 2);
db->Get(rocksdb::ReadOptions{}, key, &current);
auto new_val = current + s;
db->Put(rocksdb::WriteOptions{}, key, new_val);
}
}
void IfcParse::impl::rocks_db_file_storage::unregister_inverse(unsigned id_from, const IfcParse::entity* from_entity, IfcUtil::IfcBaseClass* inst, int attribute_index) {
@@ -813,10 +824,28 @@ void IfcParse::impl::rocks_db_file_storage::unregister_inverse(unsigned id_from,
void IfcParse::impl::rocks_db_file_storage::add_type_ref(IfcUtil::IfcBaseClass* new_entity)
{
size_t v = new_entity->identity();
if (!new_entity->declaration().as_entity()) {
throw std::runtime_error("Type refs are only supposed to be used for entities");
}
size_t v = new_entity->id();
std::string s(sizeof(size_t), ' ');
memcpy(s.data(), &v, sizeof(size_t));
db->Merge(rocksdb::WriteOptions{}, "t|" + std::to_string(new_entity->declaration().index_in_schema()), s);
// no merges yet, because the python client doesn't support them
// db->Merge(rocksdb::WriteOptions{}, "t|" + std::to_string(new_entity->declaration().index_in_schema()), s);
{
std::string current;
auto key = "t|" + std::to_string(new_entity->declaration().index_in_schema());
db->Get(rocksdb::ReadOptions{}, key, &current);
auto new_val = current + s;
db->Put(rocksdb::WriteOptions{}, key, new_val);
}
// not only mapping also register type
v = new_entity->declaration().index_in_schema();
memcpy(s.data(), &v, sizeof(size_t));
db->Put(rocksdb::WriteOptions{}, "i|" + std::to_string(new_entity->identity()) + "|t", s);
}
void IfcParse::impl::rocks_db_file_storage::remove_type_ref(IfcUtil::IfcBaseClass* new_entity)
@@ -826,11 +855,13 @@ void IfcParse::impl::rocks_db_file_storage::remove_type_ref(IfcUtil::IfcBaseClas
if (db->Get(rocksdb::ReadOptions{}, key, &s).ok()) {
std::vector<size_t> vals(s.size() / sizeof(size_t));
memcpy(vals.data(), s.data(), s.size());
vals.erase(std::find(vals.begin(), vals.end(), (size_t)new_entity->identity()));
vals.erase(std::find(vals.begin(), vals.end(), (size_t)new_entity->id()));
s.resize(vals.size() * sizeof(size_t));
memcpy(s.data(), vals.data(), s.size());
db->Put(rocksdb::WriteOptions{}, key, s);
}
db->Delete(rocksdb::WriteOptions{}, "i|" + std::to_string(new_entity->identity()) + "|t");
}
namespace {
@@ -1032,25 +1063,26 @@ namespace {
// Returns a string representation of the entity
// Note that this initializes the entity if it is not initialized
//
void IfcEntityInstanceData::toString(std::ostream& ss, bool upper, const entity* decl) const {
void IfcEntityInstanceData::toString(void* storage, const IfcParse::declaration* decl, std::size_t identity, std::ostream& ss, bool upper) const {
ss.imbue(std::locale::classic());
ss << "(";
StringBuilderVisitor vis(ss, upper);
for (size_t i = 0; i < size(); ++i) {
// @todo perhaps IfcEntityInstanceData::size() can be removed now?
for (size_t i = 0; i < (decl && decl->as_entity() ? decl->as_entity()->attribute_count() : 1); ++i) {
if (i != 0) {
ss << ",";
}
if (has_attribute_value<Blank>(i)) {
if (decl != nullptr && decl->derived()[i]) {
if (has_attribute_value<Blank>(storage, decl, identity, i)) {
if (decl != nullptr && decl->as_entity() && decl->as_entity()->derived()[i]) {
ss << "*";
} else {
ss << "$";
}
} else {
apply_visitor(vis, i);
apply_visitor(storage, decl, identity, vis, i);
}
}
ss << ")";
@@ -1132,9 +1164,11 @@ class add_to_instance_list_visitor {
class apply_individual_instance_visitor {
private:
boost::optional<AttributeValue> attribute_;
IfcEntityInstanceData* data_;
int attribute_index_;
const IfcUtil::IfcBaseClass* inst_;
template <typename T>
void apply_attribute_(T& t, const AttributeValue& attr, int index) const {
if (attr.type() == IfcUtil::Argument_ENTITY_INSTANCE) {
@@ -1161,8 +1195,8 @@ class apply_individual_instance_visitor {
, attribute_index_(idx)
{}
apply_individual_instance_visitor(IfcEntityInstanceData* data)
: data_(data)
apply_individual_instance_visitor(const IfcUtil::IfcBaseClass* data)
: inst_(data)
{}
template <typename T>
@@ -1170,8 +1204,9 @@ class apply_individual_instance_visitor {
if (attribute_) {
apply_attribute_(t, *attribute_, attribute_index_);
} else {
for (size_t i = 0; i < data_->size(); ++i) {
auto attr = data_->get_attribute_value(i);
const auto& decl = inst_->declaration();
for (size_t i = 0; i < (decl.as_entity() ? decl.as_entity()->attribute_count() : 1); ++i) {
auto attr = inst_->get_attribute_value(i);
apply_attribute_(t, attr, (int) i);
}
}
@@ -1180,7 +1215,7 @@ class apply_individual_instance_visitor {
template <typename T>
void IfcUtil::IfcBaseClass::set_attribute_value(size_t i, const T& t) {
auto current_attribute = data_.get_attribute_value(i);
auto current_attribute = get_attribute_value(i);
if (file_ != nullptr) {
// Deregister old attribute guid in file guid map.
@@ -1188,8 +1223,11 @@ void IfcUtil::IfcBaseClass::set_attribute_value(size_t i, const T& t) {
try {
auto guid = (std::string) current_attribute;
auto it = file_->internal_guid_map().find(guid);
if (it != file_->internal_guid_map().end() && it->second == this) {
file_->internal_guid_map().erase(it);
if (it != file_->internal_guid_map().end()) {
const std::pair<const std::string, IfcUtil::IfcBaseClass*>& p = *it;
if (p.second == this) {
file_->internal_guid_map().erase(it);
}
}
} catch (IfcParse::IfcException& e) {
Logger::Error(e);
@@ -1200,22 +1238,25 @@ void IfcUtil::IfcBaseClass::set_attribute_value(size_t i, const T& t) {
unregister_inverse_visitor visitor(*file_, this);
apply_individual_instance_visitor(current_attribute, (int) i).apply(visitor);
}
if constexpr (std::is_pointer_v<T>) {
if (t) {
data_.set_attribute_value(i, t);
{
void* const storage = file_ ? std::visit([](const auto& m) { return (void*)&m; }, file_->storage_) : nullptr;
if constexpr (std::is_pointer_v<T>) {
if (t) {
data_.set_attribute_value(storage, &declaration(), identity(), i, t);
} else {
data_.set_attribute_value(storage, &declaration(), identity(), i, Blank{});
}
} else {
data_.set_attribute_value(i, Blank{});
data_.set_attribute_value(storage, &declaration(), identity(),i, t);
}
} else {
data_.set_attribute_value(i, t);
}
auto new_attribute = data_.get_attribute_value(i);
auto new_attribute = get_attribute_value(i);
if (file_ != nullptr) {
// Register inverse indices in file
register_inverse_visitor visitor(*file_, this);
apply_individual_instance_visitor(new_attribute, (int) i).apply(visitor);
// @todo verify no longer necessary?
// register_inverse_visitor visitor(*file_, this);
// apply_individual_instance_visitor(new_attribute, (int) i).apply(visitor);
// Register new attribute guid in guid map
if (i == 0 && (file_->ifcroot_type() != nullptr) && this->declaration().is(*file_->ifcroot_type())) {
@@ -1225,7 +1266,7 @@ void IfcUtil::IfcBaseClass::set_attribute_value(size_t i, const T& t) {
if (it != file_->internal_guid_map().end()) {
Logger::Warning("Duplicate guid " + guid);
}
file_->internal_guid_map().insert({ guid, file_->instance_by_id(this->id()) });
file_->internal_guid_map().insert({ guid, this });
} catch (IfcParse::IfcException& e) {
Logger::Error(e);
}
@@ -1257,10 +1298,19 @@ IfcFile::IfcFile(const std::string& path, filetype ty) {
// @todo assign in constructor
std::get<impl::in_memory_file_storage>(storage_).file = this;
std::get<impl::in_memory_file_storage>(storage_).read_from_stream(&s, schema_, max_id_);
// @todo unify these names, it's already confusing enough as it stands
byid_ = decltype(byid_)(&std::get<impl::in_memory_file_storage>(storage_).byid_);
idenbyid_ = decltype(idenbyid_)(&std::get<impl::in_memory_file_storage>(storage_).idenbyid_);
byidentity_ = decltype(byidentity_)(&std::get<impl::in_memory_file_storage>(storage_).byidentity_);
} else {
// @todo this can only be used for databases that already exist, because otherwise there is no way to specify the schema
storage_ = impl::rocks_db_file_storage(path, this);
storage_.emplace<2>(path, this);
std::get<impl::rocks_db_file_storage>(storage_).read_schema(schema_);
byid_ = decltype(byid_)(&std::get<impl::rocks_db_file_storage>(storage_).byidentity_);
idenbyid_ = decltype(idenbyid_)(&std::get<impl::rocks_db_file_storage>(storage_).byid_);
byidentity_ = decltype(byidentity_)(&std::get<impl::rocks_db_file_storage>(storage_).instance_cache_);
}
ifcroot_type_ = schema_->declaration_by_name("IfcRoot");
}
@@ -1294,8 +1344,17 @@ IfcFile::IfcFile(const IfcParse::schema_definition* schema, filetype ty, const s
{
if (ty == ifcspf) {
storage_.emplace<1>();
std::get<impl::in_memory_file_storage>(storage_).file = this;
byid_ = decltype(byid_)(&std::get<impl::in_memory_file_storage>(storage_).byid_);
idenbyid_ = decltype(idenbyid_)(&std::get<impl::in_memory_file_storage>(storage_).idenbyid_);
byidentity_ = decltype(byidentity_)(&std::get<impl::in_memory_file_storage>(storage_).byidentity_);
} else {
storage_.emplace<2>(path, this);
byid_ = decltype(byid_)(&std::get<impl::rocks_db_file_storage>(storage_).byidentity_);
idenbyid_ = decltype(idenbyid_)(&std::get<impl::rocks_db_file_storage>(storage_).byid_);
byidentity_ = decltype(byidentity_)(&std::get<impl::rocks_db_file_storage>(storage_).instance_cache_);
}
setDefaultHeaderValues();
}
@@ -1323,7 +1382,7 @@ void IfcParse::impl::in_memory_file_storage::read_from_stream(IfcParse::IfcSpfSt
if (file->header().tryRead()) {
try {
schemas = file->header().file_schema().schema_identifiers();
schemas = file->header().file_schema()->schema_identifiers();
} catch (...) {
// Purposely empty catch block
}
@@ -1402,7 +1461,8 @@ void IfcParse::impl::in_memory_file_storage::read_from_stream(IfcParse::IfcSpfSt
if (instance->declaration().is(*ifcroot_type_)) {
try {
const std::string guid = instance->data().get_attribute_value(0);
// @nb here we know we're using in-memory so 'nullptr, nullptr, 0' is safe
const std::string guid = instance->data().get_attribute_value(nullptr, nullptr, 0, 0);
if (byguid_.find(guid) != byguid_.end()) {
std::stringstream ss;
ss << "Instance encountered with non-unique GlobalId " << guid;
@@ -1488,10 +1548,10 @@ void IfcParse::impl::in_memory_file_storage::read_from_stream(IfcParse::IfcSpfSt
if (it == byid_.end()) {
Logger::Error("Instance reference #" + std::to_string(*name) + " used by instance #" + std::to_string(ref) + " at attribute index " + std::to_string(refattr) + " not found");
} else {
byidentity_[idenbyid_[p.first.name_]]->data().set_attribute_value(p.first.index_, it->second);
byidentity_[idenbyid_[p.first.name_]]->data().set_attribute_value(nullptr, nullptr, 0, p.first.index_, it->second);
}
} else if (auto* inst = boost::get<IfcUtil::IfcBaseClass*>(v)) {
byidentity_[idenbyid_[p.first.name_]]->data().set_attribute_value(p.first.index_, *inst);
byidentity_[idenbyid_[p.first.name_]]->data().set_attribute_value(nullptr, nullptr, 0, p.first.index_, *inst);
}
} else if (auto* v = boost::get<std::vector<reference_or_simple_type>>(&p.second)) {
aggregate_of_instance::ptr instances(new aggregate_of_instance);
@@ -1508,7 +1568,7 @@ void IfcParse::impl::in_memory_file_storage::read_from_stream(IfcParse::IfcSpfSt
instances->push(*inst);
}
}
byidentity_[idenbyid_[p.first.name_]]->data().set_attribute_value(p.first.index_, instances);
byidentity_[idenbyid_[p.first.name_]]->data().set_attribute_value(nullptr, nullptr, 0, p.first.index_, instances);
} else if (auto* v = boost::get<std::vector<std::vector<reference_or_simple_type>>>(&p.second)) {
aggregate_of_aggregate_of_instance::ptr instances(new aggregate_of_aggregate_of_instance);
for (const auto& vi : *v) {
@@ -1527,7 +1587,7 @@ void IfcParse::impl::in_memory_file_storage::read_from_stream(IfcParse::IfcSpfSt
}
instances->push(inner);
}
byidentity_[idenbyid_[p.first.name_]]->data().set_attribute_value(p.first.index_, instances);
byidentity_[idenbyid_[p.first.name_]]->data().set_attribute_value(nullptr, nullptr, 0, p.first.index_, instances);
}
}
@@ -1614,7 +1674,7 @@ void traverse_(IfcUtil::IfcBaseClass* instance, std::set<IfcUtil::IfcBaseClass*>
}
traversal_visitor visit(visited, list, level + 1, max_level);
apply_individual_instance_visitor(&instance->data()).apply(visit);
apply_individual_instance_visitor(instance).apply(visit);
}
void traversal_visitor::operator()(IfcUtil::IfcBaseClass* inst, int /* index */) {
@@ -1712,16 +1772,42 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id)
// container and entity is created. The attribute references
// need to be updated to point to instances in this file.
IfcFile* other_file = entity->file_;
auto* decl = &entity->declaration();
if (storage_.index() == 1) {
if (auto* ent = decl->as_entity()) {
new_entity = schema_->instantiate(decl, in_memory_attribute_storage(ent->attribute_count()));
} else if (auto* typedecl = decl->as_type_declaration()) {
new_entity = schema_->instantiate(decl, in_memory_attribute_storage(1));
}
}
if (storage_.index() == 2) {
new_entity = schema_->instantiate(decl, rocks_db_attribute_storage{});
}
new_entity->file_ = this;
IfcEntityInstanceData we(entity->data());
new_entity = schema()->instantiate(&entity->declaration(), std::move(we));
void* own_storage = std::visit([](const auto& m) { return (void*)&m; }, storage_);
void* other_storage = std::visit([](const auto& m) { return (void*)&m; }, other_file->storage_);
for (size_t i = 0; i < (entity->declaration().as_entity() ? entity->declaration().as_entity()->attribute_count() : 1); ++i) {
entity->data().apply_visitor(other_storage, decl, entity->identity(), [this, i, decl, new_entity, own_storage](const auto& v) {
using U = std::decay_t<decltype(v)>;
// only need to copy non-instance attribute values, others are assigned below after mapping
if constexpr (std::is_same_v<U, IfcUtil::IfcBaseClass*>) {
} else if constexpr (std::is_same_v<U, aggregate_of_instance::ptr>) {
} else if constexpr (std::is_same_v<U, aggregate_of_aggregate_of_instance::ptr>) {
} else {
new_entity->set_attribute_value(i, v);
}
}, i);
}
// In case an entity is added that contains geometry, the unit
// information needs to be accounted for for IfcLengthMeasures.
double conversion_factor = std::numeric_limits<double>::quiet_NaN();
for (size_t i = 0; i < new_entity->data().size(); ++i) {
auto attr = new_entity->data().get_attribute_value(i);
for (size_t i = 0; i < (new_entity->declaration().as_entity() ? new_entity->declaration().as_entity()->attribute_count() : 1); ++i) {
// old attribute value
auto attr = entity->get_attribute_value(i);
IfcUtil::ArgumentType attr_type = attr.type();
IfcParse::declaration* decl = 0;
@@ -1741,8 +1827,8 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id)
if (eit == entity_file_map_.end()) {
throw IfcParse::IfcException("Unable to map instance to file");
}
// We directly use storage set not to trigger inverse recalculation which happens at the end
new_entity->data().set_attribute_value(i, eit->second);
// @todo previously, we directly use storage::set() not to trigger inverse recalculation which happens at the end
new_entity->set_attribute_value(i, eit->second);
} else if (attr_type == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) {
aggregate_of_instance::ptr instances = attr;
aggregate_of_instance::ptr new_instances(new aggregate_of_instance);
@@ -1754,7 +1840,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id)
new_instances->push(eit->second);
}
new_entity->data().set_attribute_value(i, new_instances);
new_entity->set_attribute_value(i, new_instances);
} else if (attr_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE) {
aggregate_of_aggregate_of_instance::ptr instances = attr;
aggregate_of_aggregate_of_instance::ptr new_instances(new aggregate_of_aggregate_of_instance);
@@ -1770,7 +1856,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id)
new_instances->push(list);
}
new_entity->data().set_attribute_value(i, new_instances);
new_entity->set_attribute_value(i, new_instances);
} else if ((decl != nullptr) && decl->is(*schema()->declaration_by_name("IfcLengthMeasure"))) {
if (boost::math::isnan(conversion_factor)) {
std::pair<IfcUtil::IfcBaseClass*, double> this_file_unit = {nullptr, 1.0};
@@ -1789,13 +1875,13 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id)
if (attr_type == IfcUtil::Argument_DOUBLE) {
double v = attr;
v *= conversion_factor;
new_entity->data().set_attribute_value(i, v);
new_entity->set_attribute_value(i, v);
} else if (attr_type == IfcUtil::Argument_AGGREGATE_OF_DOUBLE) {
std::vector<double> v = attr;
for (std::vector<double>::iterator it = v.begin(); it != v.end(); ++it) {
(*it) *= conversion_factor;
}
new_entity->data().set_attribute_value(i, v);
new_entity->set_attribute_value(i, v);
} else if (attr_type == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE) {
std::vector<std::vector<double>> v = attr;
for (std::vector<std::vector<double>>::iterator it = v.begin(); it != v.end(); ++it) {
@@ -1804,14 +1890,13 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id)
(*jt) *= conversion_factor;
}
}
new_entity->data().set_attribute_value(i, v);
new_entity->set_attribute_value(i, v);
}
}
}
// A new entity instance name is generated and
// the instance is pointed to this file.
new_entity->file_ = this;
if (new_entity->declaration().as_entity() != nullptr) {
if (id == -1) {
new_entity->as<IfcUtil::IfcBaseEntity>()->set_id(FreshId());
@@ -1829,7 +1914,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id)
// For subtypes of IfcRoot, the GUID mapping needs to be updated.
if (new_entity->declaration().is(*ifcroot_type_)) {
try {
const std::string guid = new_entity->data().get_attribute_value(0);
const std::string guid = new_entity->get_attribute_value(0);
if (byguid_.find(guid) != byguid_.end()) {
std::stringstream ss;
ss << "Overwriting entity with guid " << guid;
@@ -1884,9 +1969,12 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id)
byidentity_.insert({ new_entity->identity(), new_entity });
}
/*
// @todo not needed anymore, because these are now calculated by using baseclass::set() ?
if ((ty->as_entity() != nullptr)) {
build_inverses_(new_entity);
}
*/
return new_entity;
}
@@ -1930,8 +2018,9 @@ void IfcFile::removeEntity(IfcUtil::IfcBaseClass* entity) {
continue;
}
for (size_t i = 0; i < related_instance->data().size(); ++i) {
auto attr = related_instance->data().get_attribute_value(i);
const auto& decl = related_instance->declaration();
for (size_t i = 0; i < (decl.as_entity() ? decl.as_entity()->attribute_count() : 1); ++i) {
auto attr = related_instance->get_attribute_value(i);
if (attr.isNull()) {
continue;
}
@@ -1978,8 +2067,8 @@ void IfcFile::removeEntity(IfcUtil::IfcBaseClass* entity) {
}
}
if (entity->declaration().is(*ifcroot_type_) && !entity->data().get_attribute_value(0).isNull()) {
const std::string global_id = entity->data().get_attribute_value(0);
if (entity->declaration().is(*ifcroot_type_) && !entity->get_attribute_value(0).isNull()) {
const std::string global_id = entity->get_attribute_value(0);
auto it = byguid_.find(global_id);
if (it != byguid_.end()) {
byguid_.erase(it);
@@ -2088,12 +2177,14 @@ aggregate_of_instance::ptr IfcFile::instances_by_type_excl_subtypes(const IfcPar
} else if constexpr (std::is_same_v<std::decay_t<decltype(x)>, impl::rocks_db_file_storage>) {
aggregate_of_instance::ptr ret(new aggregate_of_instance);
auto it = x.bytype_.find(t->index_in_schema());
const auto& s = it->second;
// @todo generalize this, bytype_ should be a map_adapter
std::vector<size_t> vals(s.size() / sizeof(size_t));
memcpy(vals.data(), s.data(), s.size());
for (auto& v : vals) {
ret->push(x.assert_existance(v));
if (it != x.bytype_.end()) {
const auto& s = it->second;
// @todo generalize this, bytype_ should be a map_adapter
std::vector<size_t> vals(s.size() / sizeof(size_t));
memcpy(vals.data(), s.data(), s.size());
for (auto& v : vals) {
ret->push(x.assert_existance(v, IfcParse::impl::rocks_db_file_storage::by_name));
}
}
return ret;
} else {
@@ -2360,18 +2451,18 @@ void IfcFile::setDefaultHeaderValues() {
schema_identifiers.push_back(schema()->name());
}
header().file_description().description(file_description);
header().file_description().implementation_level("2;1");
header().file_description()->setdescription(file_description);
header().file_description()->setimplementation_level("2;1");
header().file_name().name(empty_string);
header().file_name().time_stamp(createTimestamp());
header().file_name().author(string_vector);
header().file_name().organization(string_vector);
header().file_name().preprocessor_version("IfcOpenShell " IFCOPENSHELL_VERSION);
header().file_name().originating_system("IfcOpenShell " IFCOPENSHELL_VERSION);
header().file_name().authorization(empty_string);
header().file_name()->setname(empty_string);
header().file_name()->settime_stamp(createTimestamp());
header().file_name()->setauthor(string_vector);
header().file_name()->setorganization(string_vector);
header().file_name()->setpreprocessor_version("IfcOpenShell " IFCOPENSHELL_VERSION);
header().file_name()->setoriginating_system("IfcOpenShell " IFCOPENSHELL_VERSION);
header().file_name()->setauthorisation(empty_string);
header().file_schema().schema_identifiers(schema_identifiers);
header().file_schema()->setschema_identifiers(schema_identifiers);
}
std::pair<IfcUtil::IfcBaseClass*, double> IfcFile::getUnit(const std::string& unit_type) {
@@ -2388,16 +2479,16 @@ std::pair<IfcUtil::IfcBaseClass*, double> IfcFile::getUnit(const std::string& un
if (projects && projects->size() == 1) {
IfcUtil::IfcBaseClass* project = *projects->begin();
IfcUtil::IfcBaseClass* unit_assignment = project->data().get_attribute_value(
IfcUtil::IfcBaseClass* unit_assignment = project->get_attribute_value(
project->declaration().as_entity()->attribute_index("UnitsInContext"));
aggregate_of_instance::ptr units = unit_assignment->data().get_attribute_value(
aggregate_of_instance::ptr units = unit_assignment->get_attribute_value(
unit_assignment->declaration().as_entity()->attribute_index("Units"));
for (aggregate_of_instance::it it = units->begin(); it != units->end(); ++it) {
IfcUtil::IfcBaseClass* unit = *it;
if (unit->declaration().is("IfcNamedUnit")) {
const std::string file_unit_type = unit->data().get_attribute_value(
const std::string file_unit_type = unit->get_attribute_value(
unit->declaration().as_entity()->attribute_index("UnitType"));
if (file_unit_type != unit_type) {
@@ -2406,16 +2497,16 @@ std::pair<IfcUtil::IfcBaseClass*, double> IfcFile::getUnit(const std::string& un
IfcUtil::IfcBaseClass* siunit = 0;
if (unit->declaration().is("IfcConversionBasedUnit")) {
IfcUtil::IfcBaseClass* mu = unit->data().get_attribute_value(
IfcUtil::IfcBaseClass* mu = unit->get_attribute_value(
unit->declaration().as_entity()->attribute_index("ConversionFactor"));
IfcUtil::IfcBaseClass* vlc = mu->data().get_attribute_value(
IfcUtil::IfcBaseClass* vlc = mu->get_attribute_value(
mu->declaration().as_entity()->attribute_index("ValueComponent"));
IfcUtil::IfcBaseClass* unc = mu->data().get_attribute_value(
IfcUtil::IfcBaseClass* unc = mu->get_attribute_value(
mu->declaration().as_entity()->attribute_index("UnitComponent"));
return_value.second *= static_cast<double>(vlc->data().get_attribute_value(0));
return_value.second *= static_cast<double>(vlc->get_attribute_value(0));
return_value.first = unit;
if (unc->declaration().is("IfcSIUnit")) {
@@ -2427,7 +2518,7 @@ std::pair<IfcUtil::IfcBaseClass*, double> IfcFile::getUnit(const std::string& un
}
if (siunit != nullptr) {
AttributeValue prefix = siunit->data().get_attribute_value(
AttributeValue prefix = siunit->get_attribute_value(
siunit->declaration().as_entity()->attribute_index("Prefix"));
if (!prefix.isNull()) {
@@ -2458,7 +2549,7 @@ void IfcParse::IfcFile::build_inverses_(IfcUtil::IfcBaseClass* inst) {
}
};
apply_individual_instance_visitor(&inst->data()).apply(fn);
apply_individual_instance_visitor(inst).apply(fn);
}
void IfcParse::IfcFile::build_inverses() {
@@ -2494,11 +2585,13 @@ std::atomic_uint32_t IfcUtil::IfcBaseClass::counter_(0);
// bool IfcParse::IfcFile::guid_map_ = true;
void IfcUtil::IfcBaseClass::unset_attribute_value(size_t index) {
data_.set_attribute_value(index, Blank{});
void* storage = file_ ? std::visit([](const auto& m) { return (void*)&m; }, file_->storage_) : nullptr;
data_.set_attribute_value(storage, &declaration(), identity(), index, Blank{});
}
AttributeValue IfcUtil::IfcBaseClass::get_attribute_value(size_t index) const {
return data_.get_attribute_value(index);
void* storage = file_ ? std::visit([](const auto& m) { return (void*)&m; }, file_->storage_) : nullptr;
return data_.get_attribute_value(storage, &declaration(), identity(), index);
}
void IfcUtil::IfcBaseClass::toString(std::ostream& out, bool upper) const
@@ -2512,57 +2605,48 @@ void IfcUtil::IfcBaseClass::toString(std::ostream& out, bool upper) const
} else {
out << declaration().name();
}
data().toString(out, upper, ent);
void* storage = file_ ? std::visit([](const auto& m) { return (void*)&m; }, file_->storage_) : nullptr;
data().toString(storage, &declaration(), identity(), out, upper);
}
/*
IfcEntityInstanceData::IfcEntityInstanceData(const IfcEntityInstanceData& data)
: storage_(data.size())
{
for (size_t i = 0; i < data.size(); ++i) {
data.apply_visitor([this, i](const auto& v) {
using U = std::decay_t<decltype(v)>;
if constexpr (std::is_same_v<U, aggregate_of_instance::ptr>) {
// @todo why did we ever choose shared_ptrs for these
// aggregates? Now we need to explicit copies.
aggregate_of_instance::ptr v2(new aggregate_of_instance);
if (v) {
v2->reserve(v->size());
for (auto& i : *v) {
v2->push(i);
}
}
set_attribute_value(i, v2);
} else if constexpr (std::is_same_v<U, aggregate_of_aggregate_of_instance::ptr>) {
aggregate_of_aggregate_of_instance::ptr v2(new aggregate_of_aggregate_of_instance);
if (v) {
for (auto& i : *v) {
v2->push(i);
}
}
set_attribute_value(i, v2);
} else {
set_attribute_value(i, v);
}
}, i);
}
}
*/
AttributeValue IfcEntityInstanceData::get_attribute_value(size_t index) const
AttributeValue IfcEntityInstanceData::get_attribute_value(void* storage, const IfcParse::declaration* decl, std::size_t identity, size_t index) const
{
return std::visit([index](const auto& x) {
return std::visit([this, storage, decl, identity, index](const auto& x) {
if constexpr (std::is_same_v<std::decay_t<decltype(x)>, in_memory_attribute_storage>) {
return AttributeValue(&x, (uint8_t)index);
} else if constexpr (std::is_same_v<std::decay_t<decltype(x)>, rocks_db_attribute_storage>) {
// @todo
return AttributeValue{};
return AttributeValue(decl->schema(), (IfcParse::impl::rocks_db_file_storage*) storage, identity, index);
} else {
return AttributeValue{};
}
}, storage_);
}
bool IfcParse::impl::rocks_db_file_storage::read_schema(const IfcParse::schema_definition*& schema) {
std::string value;
auto key = "h|file_schema|0";
db->Get(rocksdb::ReadOptions{}, key, &value);
std::vector<std::string> strings;
if (::impl::deserialize(this, value, strings) && strings.size() == 1) {
schema = schema_by_name(strings[0]);
return true;
}
return false;
}
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<Blank>(size_t index, const Blank& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<Derived>(size_t index, const Derived& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<int>(size_t index, const int& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<bool>(size_t index, const bool& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<boost::logic::tribool>(size_t index, const boost::logic::tribool& value);
@@ -2581,6 +2665,7 @@ template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<std::vect
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<aggregate_of_aggregate_of_instance::ptr>(size_t index, const aggregate_of_aggregate_of_instance::ptr& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<Blank>(const std::string& name, const Blank& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<Derived>(const std::string& name, const Derived& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<int>(const std::string& name, const int& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<bool>(const std::string& name, const bool& value);
template void IFC_PARSE_API IfcUtil::IfcBaseClass::set_attribute_value<boost::logic::tribool>(const std::string& name, const boost::logic::tribool& value);
+2 -1
View File
@@ -120,7 +120,8 @@ double IfcParse::get_SI_equivalent(typename Schema::IfcNamedUnit* named_unit) {
if (component->declaration().is(Schema::IfcSIUnit::Class())) {
si_unit = component->template as<typename Schema::IfcSIUnit>();
typename Schema::IfcValue* value = factor->ValueComponent();
scale = value->data().get_attribute_value(0);
// @todo provide sufficient context
scale = value->data().get_attribute_value(nullptr, nullptr, 0, 0);
}
} else if (named_unit->declaration().is(Schema::IfcSIUnit::Class())) {
si_unit = named_unit->template as<typename Schema::IfcSIUnit>();
+104 -68
View File
@@ -24,15 +24,8 @@
static const char* const ISO_10303_21 = "ISO-10303-21";
static const char* const HEADER = "HEADER";
static const char* const FILE_DESCRIPTION = "FILE_DESCRIPTION";
static const char* const FILE_NAME = "FILE_NAME";
static const char* const FILE_SCHEMA = "FILE_SCHEMA";
static const char* const ENDSEC = "ENDSEC";
static const char* const DATA = "DATA";
// The following header entities are not normally encountered in IFC files and are not parsed.
// static const char * const FILE_POPULATION = "FILE_POPULATION";
// static const char * const SECTION_LANGUAGE = "SECTION_LANGUAGE";
// static const char * const SECTION_CONTEXT = "SECTION_CONTEXT";
using namespace IfcParse;
@@ -52,20 +45,6 @@ namespace {
}
}
HeaderEntity::HeaderEntity(const char* const datatype, size_t size, IfcFile* file)
: datatype_(datatype)
, file_(file)
, data_((file && file->storage_.index() == 1)
? read_from_spf_file(file, size)
: (file && file->storage_.index() == 2)
? IfcEntityInstanceData(rocks_db_attribute_storage(&std::get<IfcParse::impl::rocks_db_file_storage>(file->storage_), "h|"))
: IfcEntityInstanceData(in_memory_attribute_storage(size))
)
{}
HeaderEntity::~HeaderEntity() {
}
void IfcSpfHeader::readSemicolon() {
std::visit([](auto& m) {
if constexpr (std::is_same_v<std::decay_t<decltype(m)>, IfcParse::impl::in_memory_file_storage>) {
@@ -78,18 +57,6 @@ void IfcSpfHeader::readSemicolon() {
}, file_->storage_);
}
void IfcSpfHeader::readParen() {
std::visit([](auto& m) {
if constexpr (std::is_same_v<std::decay_t<decltype(m)>, IfcParse::impl::in_memory_file_storage>) {
if (!TokenFunc::isOperator(m.tokens->Next(), '(')) {
throw IfcException(std::string("Expected ("));
}
} else {
// std::unreachable();
}
}, file_->storage_);
}
void IfcSpfHeader::readTerminal(const std::string& term, Trail trail) {
std::visit([this, term, trail](auto& m) {
if constexpr (std::is_same_v<std::decay_t<decltype(m)>, IfcParse::impl::in_memory_file_storage>) {
@@ -98,8 +65,6 @@ void IfcSpfHeader::readTerminal(const std::string& term, Trail trail) {
}
if (trail == TRAILING_SEMICOLON) {
readSemicolon();
} else if (trail == TRAILING_PAREN) {
readParen();
}
} else {
// std::unreachable();
@@ -107,6 +72,29 @@ void IfcSpfHeader::readTerminal(const std::string& term, Trail trail) {
}, file_->storage_);
}
IfcParse::IfcSpfHeader::IfcSpfHeader(IfcParse::IfcFile* file)
: file_(file),
file_description_(nullptr),
file_name_(nullptr),
file_schema_(nullptr)
{
if (file == nullptr) {
// overwritten later in IfcFile::setDefaultHeaderValues() when we know the schema identifier
file_description_ = new Header_section_schema::file_description({}, "");
file_description_->file_ = file_;
file_name_ = new Header_section_schema::file_name("", "", {}, {}, "", "", "");
file_name_->file_ = file_;
file_schema_ = new Header_section_schema::file_schema({});
file_schema_->file_ = file_;
}
}
IfcParse::IfcSpfHeader::~IfcSpfHeader() {
delete file_schema_;
delete file_name_;
delete file_description_;
}
void IfcSpfHeader::read() {
readTerminal(ISO_10303_21, TRAILING_SEMICOLON);
readTerminal(HEADER, TRAILING_SEMICOLON);
@@ -121,22 +109,22 @@ void IfcSpfHeader::read() {
//
// ISO 10303-21 Second edition 2002-01-15 p. 16
readTerminal(FILE_DESCRIPTION, NONE);
readTerminal(Header_section_schema::file_description::Class().name_uc(), NONE);
delete file_description_;
// readParen();
file_description_ = new FileDescription(file_);
file_description_ = new Header_section_schema::file_description(read_from_spf_file(file_, Header_section_schema::file_description::Class().attribute_count()));
file_description_->file_ = file_;
readSemicolon();
readTerminal(FILE_NAME, NONE);
readTerminal(Header_section_schema::file_name::Class().name_uc(), NONE);
delete file_name_;
// readParen();
file_name_ = new FileName(file_);
file_name_ = new Header_section_schema::file_name(read_from_spf_file(file_, Header_section_schema::file_name::Class().attribute_count()));
file_name_->file_ = file_;
readSemicolon();
readTerminal(FILE_SCHEMA, NONE);
readTerminal(Header_section_schema::file_schema::Class().name_uc(), NONE);
delete file_schema_;
// readParen();
file_schema_ = new FileSchema(file_);
file_schema_ = new Header_section_schema::file_schema(read_from_spf_file(file_, Header_section_schema::file_schema::Class().attribute_count()));
file_schema_->file_ = file_;
readSemicolon();
}
@@ -155,11 +143,14 @@ void IfcSpfHeader::write(std::ostream& out) const {
<< "\n";
out << HEADER << ";"
<< "\n";
out << file_description().toString(true) << ";"
file_description()->toString(out, true);
out << ";"
<< "\n";
out << file_name().toString(true) << ";"
file_name()->toString(out, true);
out << ";"
<< "\n";
out << file_schema().toString(true) << ";"
file_schema()->toString(out, true);
out << ";"
<< "\n";
out << ENDSEC << ";"
<< "\n";
@@ -167,48 +158,93 @@ void IfcSpfHeader::write(std::ostream& out) const {
<< "\n";
}
const FileDescription& IfcSpfHeader::file_description() const {
const Header_section_schema::file_description* IfcParse::IfcSpfHeader::file_description() const {
if (file_description_ == nullptr) {
throw IfcException("File description not set");
std::visit([this](auto& m) {
if constexpr (std::is_same_v<std::decay_t<decltype(m)>, impl::rocks_db_file_storage>) {
file_description_ = new Header_section_schema::file_description(rocks_db_attribute_storage{});
} else if constexpr (std::is_same_v<std::decay_t<decltype(m)>, impl::in_memory_file_storage>) {
file_description_ = new Header_section_schema::file_description(in_memory_attribute_storage(Header_section_schema::file_description::Class().attribute_count()));
}
}, file_->storage_);
file_description_->file_ = file_;
}
return *file_description_;
return file_description_;
}
const FileName& IfcSpfHeader::file_name() const {
const Header_section_schema::file_name* IfcParse::IfcSpfHeader::file_name() const {
if (file_name_ == nullptr) {
throw IfcException("File name not set");
std::visit([this](auto& m) {
if constexpr (std::is_same_v<std::decay_t<decltype(m)>, impl::rocks_db_file_storage>) {
file_name_ = new Header_section_schema::file_name(rocks_db_attribute_storage{});
} else if constexpr (std::is_same_v<std::decay_t<decltype(m)>, impl::in_memory_file_storage>) {
file_name_ = new Header_section_schema::file_name(in_memory_attribute_storage(Header_section_schema::file_name::Class().attribute_count()));
}
}, file_->storage_);
file_name_->file_ = file_;
}
return *file_name_;
return file_name_;
}
const FileSchema& IfcSpfHeader::file_schema() const {
const Header_section_schema::file_schema* IfcParse::IfcSpfHeader::file_schema() const {
if (file_schema_ == nullptr) {
throw IfcException("File schema not set");
std::visit([this](auto& m) {
if constexpr (std::is_same_v<std::decay_t<decltype(m)>, impl::rocks_db_file_storage>) {
file_schema_ = new Header_section_schema::file_schema(rocks_db_attribute_storage{});
} else if constexpr (std::is_same_v<std::decay_t<decltype(m)>, impl::in_memory_file_storage>) {
file_schema_ = new Header_section_schema::file_schema(in_memory_attribute_storage(Header_section_schema::file_schema::Class().attribute_count()));
}
}, file_->storage_);
file_schema_->file_ = file_;
}
return *file_schema_;
return file_schema_;
}
FileDescription& IfcSpfHeader::file_description() {
Header_section_schema::file_description* IfcParse::IfcSpfHeader::file_description() {
if (file_description_ == nullptr) {
file_description_ = new FileDescription(file_);
std::visit([this](auto& m) {
if constexpr (std::is_same_v<std::decay_t<decltype(m)>, impl::rocks_db_file_storage>) {
file_description_ = new Header_section_schema::file_description(rocks_db_attribute_storage{});
} else if constexpr (std::is_same_v<std::decay_t<decltype(m)>, impl::in_memory_file_storage>) {
file_description_ = new Header_section_schema::file_description(in_memory_attribute_storage(Header_section_schema::file_description::Class().attribute_count()));
}
}, file_->storage_);
file_description_->file_ = file_;
}
return *file_description_;
return file_description_;
}
FileName& IfcSpfHeader::file_name() {
Header_section_schema::file_name* IfcParse::IfcSpfHeader::file_name() {
if (file_name_ == nullptr) {
file_name_ = new FileName(file_);
std::visit([this](auto& m) {
if constexpr (std::is_same_v<std::decay_t<decltype(m)>, impl::rocks_db_file_storage>) {
file_name_ = new Header_section_schema::file_name(rocks_db_attribute_storage{});
} else if constexpr (std::is_same_v<std::decay_t<decltype(m)>, impl::in_memory_file_storage>) {
file_name_ = new Header_section_schema::file_name(in_memory_attribute_storage(Header_section_schema::file_name::Class().attribute_count()));
}
}, file_->storage_);
file_name_->file_ = file_;
}
return *file_name_;
return file_name_;
}
FileSchema& IfcSpfHeader::file_schema() {
Header_section_schema::file_schema* IfcParse::IfcSpfHeader::file_schema() {
if (file_schema_ == nullptr) {
file_schema_ = new FileSchema(file_);
std::visit([this](auto& m) {
if constexpr (std::is_same_v<std::decay_t<decltype(m)>, impl::rocks_db_file_storage>) {
file_schema_ = new Header_section_schema::file_schema(rocks_db_attribute_storage{});
} else if constexpr (std::is_same_v<std::decay_t<decltype(m)>, impl::in_memory_file_storage>) {
file_schema_ = new Header_section_schema::file_schema(in_memory_attribute_storage(Header_section_schema::file_schema::Class().attribute_count()));
}
}, file_->storage_);
file_schema_->file_ = file_;
}
return *file_schema_;
return file_schema_;
}
FileDescription::FileDescription(IfcFile* file) : HeaderEntity(FILE_DESCRIPTION, 2, file) {}
FileName::FileName(IfcFile* file) : HeaderEntity(FILE_NAME, 7, file) {}
FileSchema::FileSchema(IfcFile* file) : HeaderEntity(FILE_SCHEMA, 1, file) {}
static auto& _ = Header_section_schema::get_schema();
+13 -99
View File
@@ -22,115 +22,29 @@
#include "ifc_parse_api.h"
#include "IfcEntityInstanceData.h"
#include "Header_section_schema.h"
namespace IfcParse {
class IfcFile;
class IFC_PARSE_API HeaderEntity {
private:
const char* const datatype_;
IfcFile* file_;
HeaderEntity(const HeaderEntity&); //N/A
HeaderEntity& operator=(const HeaderEntity&); //N/A
protected:
IfcEntityInstanceData data_;
HeaderEntity(const char* const datatype, size_t size, IfcParse::IfcFile* file);
virtual ~HeaderEntity();
public:
virtual size_t getArgumentCount() const {
return data_.size();
}
AttributeValue getArgument(size_t index) const {
return data_.get_attribute_value(index);
}
std::string toString(bool upper = false) const {
std::stringstream stream;
stream << datatype_;
data_.toString(stream, upper);
return stream.str();
}
};
class IFC_PARSE_API FileDescription : public HeaderEntity {
public:
explicit FileDescription(IfcFile* = 0);
std::vector<std::string> description() const { return data_.get_attribute_value(0); }
std::string implementation_level() const { return data_.get_attribute_value(1); }
void description(const std::vector<std::string>& value) { data_.set_attribute_value(0, value); }
void implementation_level(const std::string& value) { data_.set_attribute_value(1, value); }
};
class IFC_PARSE_API FileName : public HeaderEntity {
public:
explicit FileName(IfcFile* = 0);
std::string name() const { return data_.get_attribute_value(0); }
std::string time_stamp() const { return data_.get_attribute_value(1); }
std::vector<std::string> author() const { return data_.get_attribute_value(2); }
std::vector<std::string> organization() const { return data_.get_attribute_value(3); }
std::string preprocessor_version() const { return data_.get_attribute_value(4); }
std::string originating_system() const { return data_.get_attribute_value(5); }
std::string authorization() const { return data_.get_attribute_value(6); }
void name(const std::string& value) { data_.set_attribute_value(0, value); }
void time_stamp(const std::string& value) { data_.set_attribute_value(1, value); }
void author(const std::vector<std::string>& value) { data_.set_attribute_value(2, value); }
void organization(const std::vector<std::string>& value) { data_.set_attribute_value(3, value); }
void preprocessor_version(const std::string& value) { data_.set_attribute_value(4, value); }
void originating_system(const std::string& value) { data_.set_attribute_value(5, value); }
void authorization(const std::string& value) { data_.set_attribute_value(6, value); }
};
class IFC_PARSE_API FileSchema : public HeaderEntity {
public:
explicit FileSchema(IfcFile* = 0);
std::vector<std::string> schema_identifiers() const { return data_.get_attribute_value(0); }
void schema_identifiers(const std::vector<std::string>& value) { data_.set_attribute_value(0, value); }
};
class IfcFile;
class IFC_PARSE_API IfcSpfHeader {
private:
IfcFile* file_;
FileDescription* file_description_;
FileName* file_name_;
FileSchema* file_schema_;
void readParen();
mutable Header_section_schema::file_description* file_description_;
mutable Header_section_schema::file_name* file_name_;
mutable Header_section_schema::file_schema* file_schema_;
void readSemicolon();
enum Trail {
TRAILING_SEMICOLON,
TRAILING_PAREN,
NONE
};
void readTerminal(const std::string& term, Trail trail);
public:
explicit IfcSpfHeader(IfcParse::IfcFile* file = nullptr)
: file_(file),
file_description_(0),
file_name_(0),
file_schema_(0)
{
if (file == nullptr) {
file_description_ = new FileDescription(file_);
file_name_ = new FileName(file_);
file_schema_ = new FileSchema(file_);
}
}
explicit IfcSpfHeader(IfcParse::IfcFile* file = nullptr);
~IfcSpfHeader() {
delete file_schema_;
delete file_name_;
delete file_description_;
}
~IfcSpfHeader();
IfcParse::IfcFile* file() { return file_; }
void file(IfcParse::IfcFile* file) { file_ = file; }
@@ -140,13 +54,13 @@ class IFC_PARSE_API IfcSpfHeader {
void write(std::ostream& out) const;
const FileDescription& file_description() const;
const FileName& file_name() const;
const FileSchema& file_schema() const;
const Header_section_schema::file_description* file_description() const;
const Header_section_schema::file_name* file_name() const;
const Header_section_schema::file_schema* file_schema() const;
FileDescription& file_description();
FileName& file_name();
FileSchema& file_schema();
Header_section_schema::file_description* file_description();
Header_section_schema::file_name* file_name();
Header_section_schema::file_schema* file_schema();
};
} // namespace IfcParse
+2 -2
View File
@@ -209,7 +209,7 @@ IfcUtil::IfcBaseEntity::IfcBaseEntity(IfcEntityInstanceData&& data)
void IfcUtil::IfcBaseEntity::populate_derived() {
for (auto it = declaration().as_entity()->derived().begin(); it != declaration().as_entity()->derived().end(); ++it) {
if (*it) {
this->data().set_attribute_value(
set_attribute_value(
std::distance(declaration().as_entity()->derived().begin(), it),
Derived{}
);
@@ -224,7 +224,7 @@ AttributeValue IfcUtil::IfcBaseEntity::get(const std::string& name) const
size_t idx = 0;
for (; iter != attrs.end(); ++iter, ++idx) {
if ((*iter)->name() == name) {
return data().get_attribute_value(idx);
return get_attribute_value(idx);
}
}
throw IfcParse::IfcException(name + " not found on " + declaration().name());
+14 -14
View File
@@ -279,7 +279,7 @@ static void end_element(void* user, const xmlChar* tag) {
}
*/
// @todo
// back.inst()->data().set_attribute_value(back.idx(), elems);
// back.inst()->set_attribute_value(back.idx(), elems);
}
if (state->dialect == ifcxml_dialect_ifc2x3 && state->stack.back().ntype() == stack_node::node_instance) {
@@ -325,28 +325,28 @@ static void process_characters(void* user, const xmlChar* character, int len) {
if (!val.empty()) {
// type declaration always at idx 0
visit_any([&state](auto& v) {
state->stack.back().inst()->data().set_attribute_value(0, v);
state->stack.back().inst()->set_attribute_value(0, v);
}, val);
}
} else if (state_type == stack_node::node_header_entry) {
const std::string tagname = boost::replace_all_copy(state->stack.back().tagname(), "ex:", "");
auto& header = state->file->header();
if (tagname == "name") {
header.file_name().name(txt);
header.file_name()->setname(txt);
} else if (tagname == "time_stamp") {
header.file_name().time_stamp(txt);
header.file_name()->settime_stamp(txt);
} else if (tagname == "author") {
header.file_name().author({txt});
header.file_name()->setauthor({txt});
} else if (tagname == "organization") {
header.file_name().organization({txt});
header.file_name()->setorganization({txt});
} else if (tagname == "preprocessor_version") {
header.file_name().preprocessor_version(txt);
header.file_name()->setpreprocessor_version(txt);
} else if (tagname == "originating_system") {
header.file_name().originating_system(txt);
header.file_name()->setoriginating_system(txt);
} else if (tagname == "authorization") {
header.file_name().authorization(txt);
header.file_name()->setauthorisation(txt);
} else if (tagname == "documentation") {
header.file_description().description({txt});
header.file_description()->setdescription({txt});
} else {
Logger::Error("Unrecognized header entry " + tagname);
}
@@ -531,7 +531,7 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs)
IfcUtil::IfcBaseClass* inst;
auto inst_ = create_instance(decl);
instance_to_attribute(inst_, state->stack.back().idx(), inst);
// state->stack.back().inst()->data().set_attribute_value(state->stack.back().idx(), attr);
// state->stack.back().inst()->set_attribute_value(state->stack.back().idx(), attr);
state->stack.push_back(stack_node::instance(id, inst));
} else if (state_type == stack_node::node_aggregate) {
@@ -592,7 +592,7 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs)
if (inst != nullptr) {
int idx = (*found)->entity_reference()->attribute_index(
(*found)->attribute_reference());
inst->data().set_attribute_value(idx, state->stack.back().inst());
inst->set_attribute_value(idx, state->stack.back().inst());
state->stack.push_back(stack_node::instance(id, inst));
} else {
Logger::Error("Unknown attribute " + tagname);
@@ -663,12 +663,12 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs)
int idx = state->stack.back().inv_attr()->entity_reference()->attribute_index(
state->stack.back().inv_attr()->attribute_reference());
if (inst != nullptr) {
inst->data().set_attribute_value(idx, state->stack.back().inst());
inst->set_attribute_value(idx, state->stack.back().inst());
} else {
Logger::Error("Internal error, inverse attribute not processed");
}
} else if (state_type == stack_node::node_instance_attribute) {
state->stack.back().inst()->data().set_attribute_value(state->stack.back().idx(), inst);
state->stack.back().inst()->set_attribute_value(state->stack.back().idx(), inst);
}
if (entity == nullptr) {
+4 -8
View File
@@ -34,18 +34,14 @@ template <>
struct DefaultCodec<size_t> {
std::string encode(const size_t& v) const {
std::string s(sizeof(v), 0);
size_t temp = v;
for (size_t i = 0; i < sizeof(v); i++) {
s[sizeof(v) - i - 1] = static_cast<char>(temp & 0xFF);
temp >>= 8;
}
memcpy(s.data(), &v, sizeof(v));
return s;
}
size_t decode(const std::string& s) const {
size_t v = 0;
for (size_t i = 0; i < s.size(); i++) {
v = (v << 8) | static_cast<unsigned char>(s[i]);
}
// @todo take min of sizeof(v), len(s)
// @todo unify all serialization primitives
memcpy(&v, s.data(), sizeof(v));
return v;
}
};
+1 -1
View File
@@ -508,7 +508,7 @@ namespace {
continue;
}
IfcUtil::IfcBaseClass* v = ((IfcUtil::IfcBaseEntity*) prop)->get("NominalValue");
auto value = v->data().get_attribute_value(0);
auto value = v->get_attribute_value(0);
if (value.type() == IfcUtil::Argument_STRING) {
std::string v_str = value;
*output_it++ = string_property{ pset_name, name, v_str };
@@ -106,7 +106,7 @@ boost::optional<std::string> format_attribute(ifcopenshell::geometry::abstract_m
IfcUtil::IfcBaseClass* e = argument;
if (!e->declaration().as_entity()) {
IfcUtil::IfcBaseType* f = e->as<IfcUtil::IfcBaseType>();
value = format_attribute(mapping, f->data().get_attribute_value(0), f->data().get_attribute_value(0).type(), argument_name);
value = format_attribute(mapping, f->get_attribute_value(0), f->get_attribute_value(0).type(), argument_name);
} else if (e->declaration().is(IfcSchema::IfcSIUnit::Class()) || e->declaration().is(IfcSchema::IfcConversionBasedUnit::Class())) {
// Some string concatenation to have a unit name as a XML attribute.
@@ -154,12 +154,12 @@ ptree* format_entity_instance(ifcopenshell::geometry::abstract_mapping* mapping,
const unsigned n = instance->declaration().as_entity()->attribute_count();
for (unsigned i = 0; i < n; ++i) {
try {
instance->data().get_attribute_value(i);
instance->get_attribute_value(i);
} catch (const std::exception&) {
Logger::Error("Expected " + boost::lexical_cast<std::string>(n) + " attributes for:", instance);
break;
}
auto argument = instance->data().get_attribute_value(i);
auto argument = instance->get_attribute_value(i);
if (argument.isNull()) continue;
std::string argument_name = instance->declaration().as_entity()->attribute_by_index(i)->name();
@@ -168,7 +168,7 @@ ptree* format_entity_instance(ifcopenshell::geometry::abstract_mapping* mapping,
if (argument_name_it != POSTFIX_SCHEMA(argument_name_map).end()) {
argument_name = argument_name_it->second;
}
const IfcUtil::ArgumentType argument_type = instance->data().get_attribute_value(i).type();
const IfcUtil::ArgumentType argument_type = instance->get_attribute_value(i).type();
const std::string qualified_name = instance->declaration().name() + "." + argument_name;
boost::optional<std::string> value;
@@ -559,20 +559,20 @@ void POSTFIX_SCHEMA(XmlSerializer)::finalize() {
};
// Write the SPF header as XML nodes.
BOOST_FOREACH(const std::string & s, catch_exceptions([this]() { return file->header().file_description().description(); })) {
BOOST_FOREACH(const std::string & s, catch_exceptions([this]() { return file->header().file_description()->description(); })) {
header.add_child("file_description.description", ptree(s));
}
BOOST_FOREACH(const std::string& s, catch_exceptions([this]() { return file->header().file_name().author(); })) {
BOOST_FOREACH(const std::string& s, catch_exceptions([this]() { return file->header().file_name()->author(); })) {
header.add_child("file_name.author", ptree(s));
}
BOOST_FOREACH(const std::string& s, catch_exceptions([this]() { return file->header().file_name().organization(); })) {
BOOST_FOREACH(const std::string& s, catch_exceptions([this]() { return file->header().file_name()->organization(); })) {
header.add_child("file_name.organization", ptree(s));
}
BOOST_FOREACH(const std::string& s, catch_exceptions([this]() { return file->header().file_schema().schema_identifiers(); })) {
BOOST_FOREACH(const std::string& s, catch_exceptions([this]() { return file->header().file_schema()->schema_identifiers(); })) {
header.add_child("file_schema.schema_identifiers", ptree(s));
}
try {
header.put("file_description.implementation_level", file->header().file_description().implementation_level());
header.put("file_description.implementation_level", file->header().file_description()->implementation_level());
}
catch (const IfcParse::IfcException& ex) {
std::stringstream ss;
@@ -580,7 +580,7 @@ void POSTFIX_SCHEMA(XmlSerializer)::finalize() {
Logger::Message(Logger::LOG_ERROR, ss.str());
}
try {
header.put("file_name.name", file->header().file_name().name());
header.put("file_name.name", file->header().file_name()->name());
}
catch (const IfcParse::IfcException& ex) {
std::stringstream ss;
@@ -588,7 +588,7 @@ void POSTFIX_SCHEMA(XmlSerializer)::finalize() {
Logger::Message(Logger::LOG_ERROR, ss.str());
}
try {
header.put("file_name.time_stamp", file->header().file_name().time_stamp());
header.put("file_name.time_stamp", file->header().file_name()->time_stamp());
}
catch (const IfcParse::IfcException& ex) {
std::stringstream ss;
@@ -596,7 +596,7 @@ void POSTFIX_SCHEMA(XmlSerializer)::finalize() {
Logger::Message(Logger::LOG_ERROR, ss.str());
}
try {
header.put("file_name.preprocessor_version", file->header().file_name().preprocessor_version());
header.put("file_name.preprocessor_version", file->header().file_name()->preprocessor_version());
}
catch (const IfcParse::IfcException& ex) {
std::stringstream ss;
@@ -604,7 +604,7 @@ void POSTFIX_SCHEMA(XmlSerializer)::finalize() {
Logger::Message(Logger::LOG_ERROR, ss.str());
}
try {
header.put("file_name.originating_system", file->header().file_name().originating_system());
header.put("file_name.originating_system", file->header().file_name()->originating_system());
}
catch (const IfcParse::IfcException& ex) {
std::stringstream ss;
@@ -612,7 +612,8 @@ void POSTFIX_SCHEMA(XmlSerializer)::finalize() {
Logger::Message(Logger::LOG_ERROR, ss.str());
}
try {
header.put("file_name.authorization", file->header().file_name().authorization());
// @nb inconsistent spelling
header.put("file_name.authorization", file->header().file_name()->authorisation());
}
catch (const IfcParse::IfcException& ex) {
std::stringstream ss;
+3 -2
View File
@@ -565,8 +565,9 @@ call :GitCloneAndCheckoutRevision https://gitlab.com/libeigen/eigen.git "%DEPEND
:rocksdb
set DEPENDENCY_NAME=rocksdb
set DEPENDENCY_DIR=%INSTALL_DIR%\%DEPENDENCY_NAME%
call :GitCloneAndCheckoutRevision https://github.com/facebook/rocksdb "%DEPENDENCY_DIR%" v9.9.3
set DEPENDENCY_DIR=%DEPS_DIR%\%DEPENDENCY_NAME%
:: this is a 3y old version due to conda-forge's python-rocksdb depending on v6
call :GitCloneAndCheckoutRevision https://github.com/facebook/rocksdb "%DEPENDENCY_DIR%" v6.29.5
IF NOT %ERRORLEVEL%==0 GOTO :Error
cd "%DEPENDENCY_DIR%"
call :RunCMake -DCMAKE_INSTALL_PREFIX="%INSTALL_DIR%\rocksdb" ^