mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-30 12:09:51 +00:00
Work towards serialization of data
This commit is contained in:
@@ -328,6 +328,7 @@ if (WITH_ROCKSDB)
|
|||||||
message(FATAL_ERROR "Unable to find rocksdb library in: ${ROCKSDB_LIBRARY_DIR}")
|
message(FATAL_ERROR "Unable to find rocksdb library in: ${ROCKSDB_LIBRARY_DIR}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# @todo IFOPSH_ prefix?
|
||||||
add_definitions(-DWITH_ROCKSDB)
|
add_definitions(-DWITH_ROCKSDB)
|
||||||
set(SWIG_DEFINES ${SWIG_DEFINES} -DWITH_ROCKSDB)
|
set(SWIG_DEFINES ${SWIG_DEFINES} -DWITH_ROCKSDB)
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
#include "../serializers/SvgSerializer.h"
|
#include "../serializers/SvgSerializer.h"
|
||||||
#include "../serializers/USDSerializer.h"
|
#include "../serializers/USDSerializer.h"
|
||||||
#include "../serializers/TtlWktSerializer.h"
|
#include "../serializers/TtlWktSerializer.h"
|
||||||
|
#include "../serializers/RocksDbSerializer.h"
|
||||||
|
|
||||||
#include "../ifcgeom/IfcGeomFilter.h"
|
#include "../ifcgeom/IfcGeomFilter.h"
|
||||||
#include "../ifcgeom/Iterator.h"
|
#include "../ifcgeom/Iterator.h"
|
||||||
@@ -126,7 +127,8 @@ void print_usage(bool suggest_help = true)
|
|||||||
<< " .stp STEP Standard for the Exchange of Product Data\n"
|
<< " .stp STEP Standard for the Exchange of Product Data\n"
|
||||||
<< " .igs IGES Initial Graphics Exchange Specification\n"
|
<< " .igs IGES Initial Graphics Exchange Specification\n"
|
||||||
<< " .xml XML Property definitions and decomposition tree\n"
|
<< " .xml XML Property definitions and decomposition tree\n"
|
||||||
<< " .svg SVG Scalable Vector Graphics (2D floor plan)\n"
|
<< " .rdb RocksDB RocksDB Key-Value store serialization of IFC data\n"
|
||||||
|
<< " .svg SVG Scalable Vector Graphics (2D floor plan)\n"
|
||||||
#ifdef WITH_HDF5
|
#ifdef WITH_HDF5
|
||||||
<< " .h5 HDF Hierarchical Data Format storing positions, normals and indices\n"
|
<< " .h5 HDF Hierarchical Data Format storing positions, normals and indices\n"
|
||||||
#endif
|
#endif
|
||||||
@@ -642,6 +644,8 @@ int main(int argc, char** argv) {
|
|||||||
CACHE = IfcUtil::path::from_utf8(".cache"),
|
CACHE = IfcUtil::path::from_utf8(".cache"),
|
||||||
HDF = IfcUtil::path::from_utf8(".h5"),
|
HDF = IfcUtil::path::from_utf8(".h5"),
|
||||||
XML = IfcUtil::path::from_utf8(".xml"),
|
XML = IfcUtil::path::from_utf8(".xml"),
|
||||||
|
// @todo this is just temporary as it doesn't make sense to require an extension for a DB
|
||||||
|
RDB = IfcUtil::path::from_utf8(".rdb"),
|
||||||
CITY_JSON = IfcUtil::path::from_utf8(".cityjson"),
|
CITY_JSON = IfcUtil::path::from_utf8(".cityjson"),
|
||||||
IFC = IfcUtil::path::from_utf8(".ifc"),
|
IFC = IfcUtil::path::from_utf8(".ifc"),
|
||||||
USD = IfcUtil::path::from_utf8(".usd"),
|
USD = IfcUtil::path::from_utf8(".usd"),
|
||||||
@@ -696,6 +700,27 @@ int main(int argc, char** argv) {
|
|||||||
write_log(!quiet);
|
write_log(!quiet);
|
||||||
return exit_code;
|
return exit_code;
|
||||||
}
|
}
|
||||||
|
#ifdef WITH_ROCKSDB
|
||||||
|
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)) {
|
||||||
|
time_t start, end;
|
||||||
|
time(&start);
|
||||||
|
RocksDbSerializer s(ifc_file, IfcUtil::path::to_utf8(output_filename));
|
||||||
|
Logger::Status("Populating RockDB Key-Value store...");
|
||||||
|
s.finalize();
|
||||||
|
time(&end);
|
||||||
|
Logger::Status("Done! Conversion took " + format_duration(start, end));
|
||||||
|
exit_code = EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
Logger::Error(e);
|
||||||
|
}
|
||||||
|
write_log(!quiet);
|
||||||
|
return exit_code;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#ifdef IFOPSH_WITH_CITYJSON
|
#ifdef IFOPSH_WITH_CITYJSON
|
||||||
else if (output_extension == CITY_JSON || (output_extension == OBJ || output_extension == DAE || output_extension == GLB) && vmap.count("exterior-only") && exterior_only_algo != "none") {
|
else if (output_extension == CITY_JSON || (output_extension == OBJ || output_extension == DAE || output_extension == GLB) && vmap.count("exterior-only") && exterior_only_algo != "none") {
|
||||||
|
|
||||||
|
|||||||
@@ -29,124 +29,6 @@ public:
|
|||||||
int operator()(const aggregate_of_aggregate_of_instance::ptr& i) const { return i->size(); }
|
int operator()(const aggregate_of_aggregate_of_instance::ptr& i) const { return i->size(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
// Trait to detect contiguous containers (vector / string)
|
|
||||||
template <typename T>
|
|
||||||
struct is_contiguous_container : std::false_type {};
|
|
||||||
template <typename T, typename Alloc>
|
|
||||||
struct is_contiguous_container<std::vector<T, Alloc>> : std::true_type {};
|
|
||||||
template <typename CharT, typename Traits, typename Alloc>
|
|
||||||
struct is_contiguous_container<std::basic_string<CharT, Traits, Alloc>> : std::true_type {};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
bool serialize(std::string& val, const T& t) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename std::enable_if<is_contiguous_container<T>::value, int>::type = 0>
|
|
||||||
bool serialize(std::string& val, const T& t) {
|
|
||||||
auto s = sizeof(typename T::value_type) * t.size();
|
|
||||||
val.resize(s);
|
|
||||||
val[0] = TypeEncoder::encode_type<T>();
|
|
||||||
memcpy(val.data() + 1, t.data(), s);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool serialize(std::string& val, const IfcUtil::IfcBaseClass* t) {
|
|
||||||
auto s = sizeof(size_t);
|
|
||||||
val.resize(s + 2);
|
|
||||||
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;
|
|
||||||
size_t iden = t->declaration().as_entity() ? t->id() : t->identity();
|
|
||||||
memcpy(val.data() + 2, &iden, s);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool serialize(std::string& val, const EnumerationReference& v) {
|
|
||||||
auto s = sizeof(size_t);
|
|
||||||
val.resize(s * 2 + 1);
|
|
||||||
val[0] = TypeEncoder::encode_type<EnumerationReference>();
|
|
||||||
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));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool serialize(std::string& val, 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool serialize(std::string& val, aggregate_of_aggregate_of_instance::ptr& t) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
template <typename T>
|
|
||||||
bool deserialize(std::string& val, const T& 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>()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
auto s = (val.size() - 1) / sizeof(typename T::value_type);
|
|
||||||
t.resize(s);
|
|
||||||
memcpy(t.data(), val.data() + 1, s * sizeof(typename T::value_type));
|
|
||||||
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) {
|
|
||||||
if (val[0] != TypeEncoder::encode_type<T>()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
auto s = (val.size() - 1) / sizeof(T);
|
|
||||||
memcpy(&t, val.data() + 1, sizeof(T));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool deserialize(std::string& val, boost::logic::tribool& t) {
|
|
||||||
if (val[0] != TypeEncoder::encode_type<boost::logic::tribool>()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (val[1] == 0) {
|
|
||||||
t = false;
|
|
||||||
} else if (val[1] == 1) {
|
|
||||||
t = true;
|
|
||||||
} else if (val[1] == 2) {
|
|
||||||
t = boost::logic::indeterminate;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool deserialize(std::string& val, boost::dynamic_bitset<>& t) {
|
|
||||||
if (val[0] != TypeEncoder::encode_type<boost::dynamic_bitset<>>()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
t = boost::dynamic_bitset<>(val.substr(1));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool deserialize(std::string& val, aggregate_of_instance::ptr& t) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool deserialize(std::string& val, aggregate_of_aggregate_of_instance::ptr& t) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline T dispatch_get_(AttributeValue::pointer_type array_, uint8_t storage_model_, size_t instance_name_, uint8_t index_)
|
inline T dispatch_get_(AttributeValue::pointer_type array_, uint8_t storage_model_, size_t instance_name_, uint8_t index_)
|
||||||
@@ -162,7 +44,7 @@ namespace {
|
|||||||
{
|
{
|
||||||
std::string str;
|
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{}, "a|" + std::to_string(instance_name_) + "|" + std::to_string(index_), &str);
|
||||||
deserialize(str, val);
|
impl::deserialize(str, val);
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
@@ -326,3 +208,138 @@ IfcUtil::ArgumentType AttributeValue::type() const
|
|||||||
{
|
{
|
||||||
return static_cast<IfcUtil::ArgumentType>(dispatch_index_(array_, storage_model_, instance_name_, index_));
|
return static_cast<IfcUtil::ArgumentType>(dispatch_index_(array_, storage_model_, instance_name_, index_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool impl::serialize(std::string& val, const IfcUtil::IfcBaseClass* t)
|
||||||
|
{
|
||||||
|
auto s = sizeof(size_t);
|
||||||
|
val.resize(s + 2);
|
||||||
|
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;
|
||||||
|
size_t iden = t->declaration().as_entity() ? t->id() : t->identity();
|
||||||
|
memcpy(val.data() + 2, &iden, s);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool impl::serialize(std::string& val, const EnumerationReference& v)
|
||||||
|
{
|
||||||
|
auto s = sizeof(size_t);
|
||||||
|
val.resize(s * 2 + 1);
|
||||||
|
val[0] = TypeEncoder::encode_type<EnumerationReference>();
|
||||||
|
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));
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool impl::serialize(std::string& val, const aggregate_of_aggregate_of_instance::ptr& t)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool impl::serialize(std::string& val, const Blank& t)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool impl::serialize(std::string& val, const Derived& t)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool impl::serialize(std::string& val, const empty_aggregate_t& t)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool impl::serialize(std::string& val, const empty_aggregate_of_aggregate_t& t)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool impl::serialize(std::string& val, const boost::logic::tribool& t)
|
||||||
|
{
|
||||||
|
using T = char;
|
||||||
|
T tt = t == boost::logic::indeterminate ? 2 : t ? 1 : 0;
|
||||||
|
val.resize(sizeof(T) + 1);
|
||||||
|
val[0] = TypeEncoder::encode_type<T>();
|
||||||
|
memcpy(val.data() + 1, &tt, sizeof(T));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool impl::serialize(std::string& val, const boost::dynamic_bitset<>& t)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool impl::deserialize(std::string& val, boost::logic::tribool& t) {
|
||||||
|
if (val[0] != TypeEncoder::encode_type<boost::logic::tribool>()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (val[1] == 0) {
|
||||||
|
t = false;
|
||||||
|
} else if (val[1] == 1) {
|
||||||
|
t = true;
|
||||||
|
} else if (val[1] == 2) {
|
||||||
|
t = boost::logic::indeterminate;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool impl::deserialize(std::string& val, boost::dynamic_bitset<>& t) {
|
||||||
|
if (val[0] != TypeEncoder::encode_type<boost::dynamic_bitset<>>()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
t = boost::dynamic_bitset<>(val.substr(1));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool impl::deserialize(std::string& val, aggregate_of_instance::ptr& t) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool impl::deserialize(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)
|
||||||
|
{
|
||||||
|
std::string v;
|
||||||
|
impl::serialize(v, value);
|
||||||
|
fs_->db->Put(rocksdb::WriteOptions{}, prefix_ + ("|" + 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);
|
||||||
|
|
||||||
|
// @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);
|
||||||
|
|||||||
@@ -161,6 +161,89 @@ namespace IfcParse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace impl {
|
||||||
|
|
||||||
|
// Trait to detect contiguous containers (vector / string)
|
||||||
|
template <typename T>
|
||||||
|
struct is_contiguous_container : std::false_type {};
|
||||||
|
template <typename T, typename Alloc>
|
||||||
|
struct is_contiguous_container<std::vector<T, Alloc>> : std::true_type {};
|
||||||
|
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();
|
||||||
|
val.resize(s + 1);
|
||||||
|
val[0] = TypeEncoder::encode_type<T>();
|
||||||
|
memcpy(val.data() + 1, t.data(), 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 serialize(std::string& val, const T& t) {
|
||||||
|
val.resize(sizeof(T) + 1);
|
||||||
|
val[0] = TypeEncoder::encode_type<T>();
|
||||||
|
memcpy(val.data() + 1, &t, sizeof(T));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool serialize(std::string& val, const Blank& t);
|
||||||
|
|
||||||
|
bool serialize(std::string& val, const Derived& t);
|
||||||
|
bool serialize(std::string& val, const empty_aggregate_t& t);
|
||||||
|
bool serialize(std::string& val, const empty_aggregate_of_aggregate_t& t);
|
||||||
|
|
||||||
|
bool serialize(std::string& val, const boost::logic::tribool& t);
|
||||||
|
|
||||||
|
bool serialize(std::string& val, const boost::dynamic_bitset<>& t);
|
||||||
|
|
||||||
|
bool serialize(std::string& val, const IfcUtil::IfcBaseClass* t);
|
||||||
|
|
||||||
|
bool serialize(std::string& val, const EnumerationReference& v);
|
||||||
|
|
||||||
|
bool serialize(std::string& val, const aggregate_of_instance::ptr& t);
|
||||||
|
|
||||||
|
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>()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto s = (val.size() - 1) / sizeof(typename T::value_type);
|
||||||
|
t.resize(s);
|
||||||
|
memcpy(t.data(), val.data() + 1, s * sizeof(typename T::value_type));
|
||||||
|
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) {
|
||||||
|
if (val[0] != TypeEncoder::encode_type<T>()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto s = (val.size() - 1) / sizeof(T);
|
||||||
|
memcpy(&t, val.data() + 1, sizeof(T));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool deserialize(std::string& val, boost::logic::tribool& t);
|
||||||
|
|
||||||
|
bool deserialize(std::string& val, boost::dynamic_bitset<>& t);
|
||||||
|
|
||||||
|
bool deserialize(std::string& val, aggregate_of_instance::ptr& t);
|
||||||
|
|
||||||
|
bool deserialize(std::string& val, aggregate_of_aggregate_of_instance::ptr& t);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// short lived
|
// short lived
|
||||||
struct AttributeValue {
|
struct AttributeValue {
|
||||||
uint8_t index_;
|
uint8_t index_;
|
||||||
@@ -224,7 +307,10 @@ struct AttributeValue {
|
|||||||
|
|
||||||
struct rocks_db_attribute_storage {
|
struct rocks_db_attribute_storage {
|
||||||
private:
|
private:
|
||||||
IfcParse::impl::rocks_db_file_storage* fs;
|
// @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>
|
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 {
|
auto apply_visitor_impl(Visitor&& visitor, std::size_t idx, std::integral_constant<std::size_t, Index>) const {
|
||||||
@@ -237,15 +323,44 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
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() const {
|
||||||
// @todo
|
// @todo is this actually needed?
|
||||||
return 8;
|
return 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void set(std::size_t index, T&& value) {
|
void set(std::size_t index, const T& value);
|
||||||
// @todo
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool has(std::size_t index) const {
|
bool has(std::size_t index) const {
|
||||||
|
|||||||
@@ -353,7 +353,7 @@ IfcUtil::IfcBaseClass* IfcParse::impl::rocks_db_file_storage::assert_existance(s
|
|||||||
size_t s;
|
size_t s;
|
||||||
memcpy(&s, v.data(), sizeof(size_t));
|
memcpy(&s, v.data(), sizeof(size_t));
|
||||||
auto decl = file->schema()->declarations()[s];
|
auto decl = file->schema()->declarations()[s];
|
||||||
IfcEntityInstanceData data(rocks_db_attribute_storage{});
|
IfcEntityInstanceData data(rocks_db_attribute_storage(this, "i|"));
|
||||||
auto inst = file->schema()->instantiate(decl, std::move(data));
|
auto inst = file->schema()->instantiate(decl, std::move(data));
|
||||||
inst->id_ = instanceId;
|
inst->id_ = instanceId;
|
||||||
instance_cache_.insert({ inst->identity(), inst });
|
instance_cache_.insert({ inst->identity(), inst });
|
||||||
@@ -363,34 +363,6 @@ IfcUtil::IfcBaseClass* IfcParse::impl::rocks_db_file_storage::assert_existance(s
|
|||||||
throw std::runtime_error("");
|
throw std::runtime_error("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#include "rocksdb/merge_operator.h"
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
class ConcatenateIdMergeOperator : public rocksdb::AssociativeMergeOperator {
|
|
||||||
public:
|
|
||||||
virtual bool Merge(const rocksdb::Slice& key,
|
|
||||||
const rocksdb::Slice* existing_value,
|
|
||||||
const rocksdb::Slice& value,
|
|
||||||
std::string* new_value,
|
|
||||||
rocksdb::Logger* logger) const override {
|
|
||||||
if (existing_value) {
|
|
||||||
new_value->assign(existing_value->data(), existing_value->size());
|
|
||||||
new_value->append(value.data(), value.size());
|
|
||||||
} else {
|
|
||||||
new_value->assign(value.data(), value.size());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual const char* Name() const override {
|
|
||||||
return "ConcatenateIdMergeOperator";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// @todo naming
|
// @todo naming
|
||||||
IfcParse::impl::rocks_db_file_storage::rocks_db_file_storage(const std::string& filepath, IfcParse::IfcFile* ffile)
|
IfcParse::impl::rocks_db_file_storage::rocks_db_file_storage(const std::string& filepath, IfcParse::IfcFile* ffile)
|
||||||
: file(ffile)
|
: file(ffile)
|
||||||
@@ -399,11 +371,15 @@ IfcParse::impl::rocks_db_file_storage::rocks_db_file_storage(const std::string&
|
|||||||
, 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); }, [](IfcUtil::IfcBaseClass* v) { return v->identity(); })
|
||||||
, byid_(db, "d|")
|
, byid_(db, "d|")
|
||||||
, bytype_(db, "t|")
|
, bytype_(db, "t|")
|
||||||
|
, byidentity_(&byid_, [this](size_t v) { return assert_existance(v); }, [](IfcUtil::IfcBaseClass* v) { return v->identity(); })
|
||||||
{
|
{
|
||||||
rocksdb::Options options;
|
rocksdb::Options options;
|
||||||
options.create_if_missing = true;
|
options.create_if_missing = true;
|
||||||
options.merge_operator.reset(new ConcatenateIdMergeOperator());
|
options.merge_operator.reset(new ConcatenateIdMergeOperator());
|
||||||
rocksdb::Status status = rocksdb::DB::Open(options, filepath, &db);
|
rocksdb::Status status = rocksdb::DB::Open(options, filepath, &db);
|
||||||
|
if (!status.ok()) {
|
||||||
|
throw std::runtime_error(status.ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IfcUtil::IfcBaseClass* IfcParse::impl::rocks_db_file_storage::instance_by_id(int id)
|
IfcUtil::IfcBaseClass* IfcParse::impl::rocks_db_file_storage::instance_by_id(int id)
|
||||||
|
|||||||
+108
-5
@@ -37,6 +37,32 @@
|
|||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
#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,
|
||||||
|
const rocksdb::Slice* existing_value,
|
||||||
|
const rocksdb::Slice& value,
|
||||||
|
std::string* new_value,
|
||||||
|
rocksdb::Logger* logger) const override {
|
||||||
|
if (existing_value) {
|
||||||
|
new_value->assign(existing_value->data(), existing_value->size());
|
||||||
|
new_value->append(value.data(), value.size());
|
||||||
|
} else {
|
||||||
|
new_value->assign(value.data(), value.size());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const char* Name() const override {
|
||||||
|
return "ConcatenateIdMergeOperator";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
namespace IfcParse {
|
namespace IfcParse {
|
||||||
|
|
||||||
class IFC_PARSE_API file_open_status {
|
class IFC_PARSE_API file_open_status {
|
||||||
@@ -315,6 +341,11 @@ namespace impl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void process_deletion_inverse(IfcUtil::IfcBaseClass* inst);
|
void process_deletion_inverse(IfcUtil::IfcBaseClass* inst);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T* create();
|
||||||
|
|
||||||
|
IfcUtil::IfcBaseClass* create(const IfcParse::declaration* decl);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rocks_db_file_storage {
|
struct rocks_db_file_storage {
|
||||||
@@ -328,9 +359,9 @@ namespace impl {
|
|||||||
typedef rocksdb_map_adapter<size_t, size_t> identity_by_id_t;
|
typedef rocksdb_map_adapter<size_t, size_t> identity_by_id_t;
|
||||||
identity_by_id_t byid_;
|
identity_by_id_t byid_;
|
||||||
|
|
||||||
// typedef map_transformer<rocksdb_map_adapter<size_t, size_t>, std::function<IfcUtil::IfcBaseClass*(size_t)>, std::function<size_t(IfcUtil::IfcBaseClass*)>> entity_by_identity_t;
|
typedef map_transformer<rocksdb_map_adapter<size_t, size_t>, std::function<IfcUtil::IfcBaseClass*(size_t)>, std::function<size_t(IfcUtil::IfcBaseClass*)>> entity_by_id_t;
|
||||||
// storage is now Instance name -> Identity -> Pointer (cached)
|
// storage is now Instance name -> Identity -> Pointer (cached)
|
||||||
// entity_by_identity_t byidentity_;
|
entity_by_id_t byidentity_;
|
||||||
|
|
||||||
// index in schema to binary serialized ids
|
// index in schema to binary serialized ids
|
||||||
typedef rocksdb_map_adapter<size_t, std::string> instance_id_str_by_type_t;
|
typedef rocksdb_map_adapter<size_t, std::string> instance_id_str_by_type_t;
|
||||||
@@ -531,6 +562,11 @@ namespace impl {
|
|||||||
IfcUtil::IfcBaseClass* instance_by_id(int id);
|
IfcUtil::IfcBaseClass* instance_by_id(int id);
|
||||||
|
|
||||||
void process_deletion_inverse(IfcUtil::IfcBaseClass* inst);
|
void process_deletion_inverse(IfcUtil::IfcBaseClass* inst);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T* create();
|
||||||
|
|
||||||
|
IfcUtil::IfcBaseClass* create(const IfcParse::declaration* decl);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -591,7 +627,8 @@ private:
|
|||||||
IfcFile(std::istream& stream, int length);
|
IfcFile(std::istream& stream, int length);
|
||||||
IfcFile(void* data, int length);
|
IfcFile(void* data, int length);
|
||||||
IfcFile(IfcParse::IfcSpfStream* stream);
|
IfcFile(IfcParse::IfcSpfStream* stream);
|
||||||
IfcFile(const IfcParse::schema_definition* schema = IfcParse::schema_by_name("IFC4"));
|
// @nb path is only used in rocksdb mode, for spf file is in-memory only until write() is called
|
||||||
|
IfcFile(const IfcParse::schema_definition* schema = IfcParse::schema_by_name("IFC4"), filetype ty = ifcspf, const std::string& path = "");
|
||||||
|
|
||||||
~IfcFile() {
|
~IfcFile() {
|
||||||
for (const auto& p : byidentity_) {
|
for (const auto& p : byidentity_) {
|
||||||
@@ -722,10 +759,13 @@ private:
|
|||||||
|
|
||||||
typedef VariantMap<impl::in_memory_file_storage::entity_by_guid_t, impl::rocks_db_file_storage::entity_by_guid_t> entity_by_guid_t;
|
typedef VariantMap<impl::in_memory_file_storage::entity_by_guid_t, impl::rocks_db_file_storage::entity_by_guid_t> entity_by_guid_t;
|
||||||
entity_by_guid_t byguid_;
|
entity_by_guid_t byguid_;
|
||||||
typedef VariantMap<impl::in_memory_file_storage::identity_by_id_t, impl::rocks_db_file_storage::identity_by_id_t> identity_by_id_t;
|
typedef VariantMap<impl::in_memory_file_storage::entity_by_id_t, impl::rocks_db_file_storage::entity_by_id_t> entity_by_id_t;
|
||||||
identity_by_id_t byid_;
|
entity_by_id_t byid_;
|
||||||
typedef VariantMap<impl::in_memory_file_storage::entity_by_iden_t, impl::rocks_db_file_storage::entity_by_iden_cache_t> entity_by_iden_t;
|
typedef VariantMap<impl::in_memory_file_storage::entity_by_iden_t, impl::rocks_db_file_storage::entity_by_iden_cache_t> entity_by_iden_t;
|
||||||
entity_by_iden_t byidentity_;
|
entity_by_iden_t byidentity_;
|
||||||
|
typedef VariantMap<impl::in_memory_file_storage::identity_by_id_t, impl::rocks_db_file_storage::identity_by_id_t> identity_by_id_t;
|
||||||
|
identity_by_id_t idenbyid_;
|
||||||
|
|
||||||
|
|
||||||
// @todo
|
// @todo
|
||||||
entity_by_guid_t internal_guid_map() { return byguid_; };
|
entity_by_guid_t internal_guid_map() { return byguid_; };
|
||||||
@@ -735,6 +775,31 @@ private:
|
|||||||
void process_deletion_inverse(IfcUtil::IfcBaseClass* inst);
|
void process_deletion_inverse(IfcUtil::IfcBaseClass* inst);
|
||||||
|
|
||||||
void build_inverses_(IfcUtil::IfcBaseClass*);
|
void build_inverses_(IfcUtil::IfcBaseClass*);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T* create() {
|
||||||
|
return std::visit([](auto& m) -> T* {
|
||||||
|
if constexpr (std::is_same_v<std::decay_t<decltype(m)>, impl::in_memory_file_storage> ||
|
||||||
|
std::is_same_v<std::decay_t<decltype(m)>, impl::rocks_db_file_storage>)
|
||||||
|
{
|
||||||
|
return m.create<T>();
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}, storage_);
|
||||||
|
}
|
||||||
|
|
||||||
|
IfcUtil::IfcBaseClass* create(const IfcParse::declaration* decl) {
|
||||||
|
return std::visit([decl](auto& m) -> IfcUtil::IfcBaseClass* {
|
||||||
|
if constexpr (std::is_same_v<std::decay_t<decltype(m)>, impl::in_memory_file_storage> ||
|
||||||
|
std::is_same_v<std::decay_t<decltype(m)>, impl::rocks_db_file_storage>)
|
||||||
|
{
|
||||||
|
return m.create(decl);
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}, storage_);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef WITH_IFCXML
|
#ifdef WITH_IFCXML
|
||||||
@@ -743,6 +808,44 @@ IFC_PARSE_API IfcFile* parse_ifcxml(const std::string& filename);
|
|||||||
|
|
||||||
} // namespace IfcParse
|
} // namespace IfcParse
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T* IfcParse::impl::in_memory_file_storage::create() {
|
||||||
|
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>();
|
||||||
|
} 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>();
|
||||||
|
} else {
|
||||||
|
static_assert(false, "Requires and entity or type declaration");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IfcUtil::IfcBaseClass* IfcParse::impl::in_memory_file_storage::create(const IfcParse::declaration* decl) {
|
||||||
|
if (auto* ent = decl->as_entity()) {
|
||||||
|
return file->addEntity(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)));
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Requires and entity or type declaration");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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>();
|
||||||
|
} else {
|
||||||
|
static_assert(false, "Requires and entity or type declaration");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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|")));
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Requires and entity or type declaration");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
template <>
|
template <>
|
||||||
struct iterator_traits<IfcParse::IfcFile::type_iterator> {
|
struct iterator_traits<IfcParse::IfcFile::type_iterator> {
|
||||||
|
|||||||
@@ -1258,6 +1258,7 @@ IfcFile::IfcFile(const std::string& path, filetype ty) {
|
|||||||
std::get<impl::in_memory_file_storage>(storage_).file = this;
|
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_);
|
std::get<impl::in_memory_file_storage>(storage_).read_from_stream(&s, schema_, max_id_);
|
||||||
} else {
|
} 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_ = impl::rocks_db_file_storage(path, this);
|
||||||
std::get<impl::rocks_db_file_storage>(storage_).read_schema(schema_);
|
std::get<impl::rocks_db_file_storage>(storage_).read_schema(schema_);
|
||||||
}
|
}
|
||||||
@@ -1285,12 +1286,17 @@ IfcFile::IfcFile(IfcParse::IfcSpfStream* s) {
|
|||||||
ifcroot_type_ = schema_->declaration_by_name("IfcRoot");
|
ifcroot_type_ = schema_->declaration_by_name("IfcRoot");
|
||||||
}
|
}
|
||||||
|
|
||||||
IfcFile::IfcFile(const IfcParse::schema_definition* schema)
|
IfcFile::IfcFile(const IfcParse::schema_definition* schema, filetype ty, const std::string& path)
|
||||||
: schema_(schema)
|
: schema_(schema)
|
||||||
, ifcroot_type_(schema_->declaration_by_name("IfcRoot"))
|
, ifcroot_type_(schema_->declaration_by_name("IfcRoot"))
|
||||||
, max_id_(0)
|
, max_id_(0)
|
||||||
|
, _header(ty == rocksdb ? this : nullptr)
|
||||||
{
|
{
|
||||||
storage_.emplace<1>();
|
if (ty == ifcspf) {
|
||||||
|
storage_.emplace<1>();
|
||||||
|
} else {
|
||||||
|
storage_.emplace<2>(path, this);
|
||||||
|
}
|
||||||
setDefaultHeaderValues();
|
setDefaultHeaderValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1866,7 +1872,7 @@ IfcUtil::IfcBaseClass* IfcFile::addEntity(IfcUtil::IfcBaseClass* entity, int id)
|
|||||||
Logger::Message(Logger::LOG_WARNING, ss.str());
|
Logger::Message(Logger::LOG_WARNING, ss.str());
|
||||||
}
|
}
|
||||||
// The mapping by entity instance name is updated.
|
// The mapping by entity instance name is updated.
|
||||||
byid_.insert({ new_id, new_entity->identity() });
|
idenbyid_.insert({ new_id, new_entity->identity() });
|
||||||
byidentity_.insert({ new_entity->identity(), new_entity });
|
byidentity_.insert({ new_entity->identity(), new_entity });
|
||||||
} else if (new_entity->file_ == nullptr) {
|
} else if (new_entity->file_ == nullptr) {
|
||||||
// For non-entity instances, no mappings are updated, but the file
|
// For non-entity instances, no mappings are updated, but the file
|
||||||
@@ -2210,7 +2216,7 @@ std::ostream& operator<<(std::ostream& out, const IfcParse::IfcFile& file) {
|
|||||||
|
|
||||||
typedef std::vector<IfcUtil::IfcBaseClass*> vector_t;
|
typedef std::vector<IfcUtil::IfcBaseClass*> vector_t;
|
||||||
vector_t sorted;
|
vector_t sorted;
|
||||||
std::transform(file.begin(), file.end(), std::back_inserter(sorted), [&file](const auto& x) { return file.byidentity_.find(x.second)->second; });
|
std::transform(file.begin(), file.end(), std::back_inserter(sorted), [&file](const auto& x) { return x.second; });
|
||||||
std::sort(sorted.begin(), sorted.end(), [](const auto& a, const auto& b) { return a->id() < b->id(); });
|
std::sort(sorted.begin(), sorted.end(), [](const auto& a, const auto& b) { return a->id() < b->id(); });
|
||||||
|
|
||||||
for (auto& e : sorted) {
|
for (auto& e : sorted) {
|
||||||
@@ -2457,7 +2463,7 @@ void IfcParse::IfcFile::build_inverses_(IfcUtil::IfcBaseClass* inst) {
|
|||||||
|
|
||||||
void IfcParse::IfcFile::build_inverses() {
|
void IfcParse::IfcFile::build_inverses() {
|
||||||
for (const auto& pair : *this) {
|
for (const auto& pair : *this) {
|
||||||
build_inverses_(byidentity_.find(pair.second)->second);
|
build_inverses_(pair.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,12 @@ namespace {
|
|||||||
HeaderEntity::HeaderEntity(const char* const datatype, size_t size, IfcFile* file)
|
HeaderEntity::HeaderEntity(const char* const datatype, size_t size, IfcFile* file)
|
||||||
: datatype_(datatype)
|
: datatype_(datatype)
|
||||||
, file_(file)
|
, file_(file)
|
||||||
, data_(file ? read_from_spf_file(file, size) : IfcEntityInstanceData(in_memory_attribute_storage(size)))
|
, 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() {
|
HeaderEntity::~HeaderEntity() {
|
||||||
@@ -185,21 +190,21 @@ const FileSchema& IfcSpfHeader::file_schema() const {
|
|||||||
|
|
||||||
FileDescription& IfcSpfHeader::file_description() {
|
FileDescription& IfcSpfHeader::file_description() {
|
||||||
if (file_description_ == nullptr) {
|
if (file_description_ == nullptr) {
|
||||||
throw IfcException("File description not set");
|
file_description_ = new FileDescription(file_);
|
||||||
}
|
}
|
||||||
return *file_description_;
|
return *file_description_;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileName& IfcSpfHeader::file_name() {
|
FileName& IfcSpfHeader::file_name() {
|
||||||
if (file_name_ == nullptr) {
|
if (file_name_ == nullptr) {
|
||||||
throw IfcException("File name not set");
|
file_name_ = new FileName(file_);
|
||||||
}
|
}
|
||||||
return *file_name_;
|
return *file_name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileSchema& IfcSpfHeader::file_schema() {
|
FileSchema& IfcSpfHeader::file_schema() {
|
||||||
if (file_schema_ == nullptr) {
|
if (file_schema_ == nullptr) {
|
||||||
throw IfcException("File schema not set");
|
file_schema_ = new FileSchema(file_);
|
||||||
}
|
}
|
||||||
return *file_schema_;
|
return *file_schema_;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ public:
|
|||||||
using base_mapped_type = typename BaseMap::mapped_type;
|
using base_mapped_type = typename BaseMap::mapped_type;
|
||||||
using transformed_mapped_type = std::invoke_result_t<Transform, base_mapped_type>;
|
using transformed_mapped_type = std::invoke_result_t<Transform, base_mapped_type>;
|
||||||
using value_type = std::pair<key_type, transformed_mapped_type>;
|
using value_type = std::pair<key_type, transformed_mapped_type>;
|
||||||
|
using mapped_type = transformed_mapped_type;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BaseMap* base_map_;
|
BaseMap* base_map_;
|
||||||
|
|||||||
Reference in New Issue
Block a user