2017-08-18 15:29:05 +02:00
|
|
|
#include "../ifcparse/IfcHdf5File.h"
|
2016-02-24 11:26:47 +01:00
|
|
|
|
2017-08-18 15:29:05 +02:00
|
|
|
#include <limits>
|
|
|
|
|
#include <H5pubconf.h>
|
2016-02-24 11:26:47 +01:00
|
|
|
#include <boost/lexical_cast.hpp>
|
|
|
|
|
|
2015-11-10 11:16:00 +01:00
|
|
|
#ifndef H5_HAVE_FILTER_DEFLATE
|
|
|
|
|
#pragma message("warning: HDF5 compression support is recommended")
|
|
|
|
|
#endif
|
|
|
|
|
|
2017-10-09 13:58:29 +02:00
|
|
|
static boost::optional< std::vector<Argument*> > no_instances = boost::none;
|
|
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
class type_mapper {
|
|
|
|
|
public:
|
2017-09-24 13:48:16 +02:00
|
|
|
type_mapper(IfcParse::IfcFile& ifc_file, H5::H5File* hdf5_file, const IfcParse::Hdf5Settings& settings);
|
2015-11-10 11:16:00 +01:00
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
H5::DataType* commit(H5::DataType* dt, const std::string& name);
|
2017-09-24 13:48:16 +02:00
|
|
|
|
2017-10-09 13:58:29 +02:00
|
|
|
H5::DataType* operator()(const IfcParse::parameter_type* pt, const boost::optional< std::vector<Argument*> >& instances = no_instances, int dims = 0, const hsize_t* max_length = nullptr);
|
|
|
|
|
H5::DataType* operator()(const IfcParse::select_type* pt, const boost::optional< std::vector<Argument*> >& instances = no_instances, int dims = 0, const hsize_t* max_length = nullptr);
|
|
|
|
|
H5::CompType* operator()(const IfcParse::entity* e, const boost::optional< std::vector<Argument*> >& instances = no_instances, int dims = 0, const hsize_t* max_length = nullptr);
|
|
|
|
|
H5::EnumType* operator()(const IfcParse::enumeration_type* en, const boost::optional< std::vector<Argument*> >& instances = no_instances, int dims = 0, const hsize_t* max_length = nullptr);
|
2017-09-01 12:50:42 +02:00
|
|
|
|
|
|
|
|
void operator()();
|
|
|
|
|
|
2017-10-09 13:58:29 +02:00
|
|
|
std::pair<std::string, const H5::DataType*> make_select_leaf(const IfcParse::declaration* decl, const boost::optional< std::vector<Argument*> >& instances);
|
2017-09-01 12:50:42 +02:00
|
|
|
|
|
|
|
|
private:
|
2017-09-24 13:48:16 +02:00
|
|
|
IfcParse::Hdf5Settings settings_;
|
2017-09-01 12:50:42 +02:00
|
|
|
bool padded_;
|
|
|
|
|
bool referenced_;
|
2017-09-24 13:48:16 +02:00
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
IfcParse::IfcFile& ifc_file_;
|
|
|
|
|
H5::H5File* hdf5_file_;
|
|
|
|
|
H5::Group schema_group_;
|
2017-10-09 13:58:29 +02:00
|
|
|
H5::DataType* instance_reference_;
|
2017-09-01 12:50:42 +02:00
|
|
|
std::vector<const H5::DataType*> default_types_;
|
|
|
|
|
std::vector<std::string> default_type_names_;
|
|
|
|
|
std::vector<std::string> default_cpp_type_names_;
|
|
|
|
|
std::vector<H5::DataType*> declared_types_;
|
|
|
|
|
|
|
|
|
|
std::string flatten_aggregate_name(const IfcParse::parameter_type* at) const;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class enumeration_reference {
|
|
|
|
|
private:
|
|
|
|
|
size_t index_;
|
|
|
|
|
public:
|
|
|
|
|
explicit enumeration_reference(size_t index)
|
|
|
|
|
: index_(index)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
operator size_t() const {
|
|
|
|
|
return index_;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class select_item {
|
|
|
|
|
private:
|
|
|
|
|
IfcUtil::IfcBaseClass* data_;
|
|
|
|
|
public:
|
|
|
|
|
explicit select_item(IfcUtil::IfcBaseClass* data)
|
|
|
|
|
: data_(data)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
operator IfcUtil::IfcBaseClass*() const {
|
|
|
|
|
return data_;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <typename T> struct is_hdf5_integral { static const bool value = false; };
|
|
|
|
|
template <> struct is_hdf5_integral <int> { static const bool value = true; };
|
|
|
|
|
template <> struct is_hdf5_integral <bool> { static const bool value = true; };
|
|
|
|
|
template <> struct is_hdf5_integral <float> { static const bool value = true; };
|
|
|
|
|
template <> struct is_hdf5_integral <double> { static const bool value = true; };
|
|
|
|
|
template <> struct is_hdf5_integral <enumeration_reference> { static const bool value = true; };
|
|
|
|
|
|
|
|
|
|
template <typename T> struct hdf5_datatype_for{};
|
|
|
|
|
template <> struct hdf5_datatype_for <int> { static const H5T_class_t value = H5T_INTEGER; };
|
|
|
|
|
// Booleans are enumerations in HDF5 as well!
|
|
|
|
|
template <> struct hdf5_datatype_for <bool> { static const H5T_class_t value = H5T_ENUM; };
|
|
|
|
|
template <> struct hdf5_datatype_for <float> { static const H5T_class_t value = H5T_FLOAT; };
|
|
|
|
|
template <> struct hdf5_datatype_for <double> { static const H5T_class_t value = H5T_FLOAT; };
|
|
|
|
|
template <> struct hdf5_datatype_for <enumeration_reference> { static const H5T_class_t value = H5T_ENUM; };
|
|
|
|
|
|
|
|
|
|
template <unsigned int T> struct uint_of_size {};
|
|
|
|
|
template <> struct uint_of_size <1> { typedef uint8_t type; };
|
|
|
|
|
template <> struct uint_of_size <2> { typedef uint16_t type; };
|
|
|
|
|
template <> struct uint_of_size <4> { typedef uint32_t type; };
|
|
|
|
|
template <> struct uint_of_size <8> { typedef uint64_t type; };
|
|
|
|
|
|
|
|
|
|
template <unsigned int T> struct int_of_size {};
|
|
|
|
|
template <> struct int_of_size <1> { typedef int8_t type; };
|
|
|
|
|
template <> struct int_of_size <2> { typedef int16_t type; };
|
|
|
|
|
template <> struct int_of_size <4> { typedef int32_t type; };
|
|
|
|
|
template <> struct int_of_size <8> { typedef int64_t type; };
|
|
|
|
|
|
|
|
|
|
template <unsigned int T> struct float_of_size {};
|
|
|
|
|
template <> struct float_of_size <4> { typedef float type; };
|
|
|
|
|
template <> struct float_of_size <8> { typedef double type; };
|
|
|
|
|
|
|
|
|
|
template <typename T, unsigned int N> struct number_of_size {};
|
|
|
|
|
template <unsigned int N> struct number_of_size <int, N> { typedef typename int_of_size<N>::type type; };
|
|
|
|
|
template <unsigned int N> struct number_of_size <float, N> { typedef typename float_of_size<N>::type type; };
|
|
|
|
|
template <unsigned int N> struct number_of_size <double, N> { typedef typename float_of_size<N>::type type; };
|
|
|
|
|
|
|
|
|
|
std::pair<H5T_class_t, H5T_class_t> compound_member_types_as_pair(H5::DataType& datatype) {
|
|
|
|
|
if (datatype.getClass() != H5T_COMPOUND) {
|
|
|
|
|
throw std::runtime_error("Expected a compound");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
H5::CompType* compound = (H5::CompType*) &datatype;
|
|
|
|
|
|
|
|
|
|
if (compound->getNmembers() != 2) {
|
|
|
|
|
throw std::runtime_error("Expected a compound with two members");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return std::make_pair(
|
|
|
|
|
compound->getMemberDataType(0).getClass(),
|
|
|
|
|
compound->getMemberDataType(1).getClass());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool is_select(H5::DataType& datatype) {
|
|
|
|
|
if (datatype.getClass() != H5T_COMPOUND) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
H5::CompType* compound = (H5::CompType*) &datatype;
|
|
|
|
|
|
|
|
|
|
if (compound->getNmembers() < 1) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return compound->getMemberName(0) == "type_code";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void advance(void*& ptr, size_t n) {
|
|
|
|
|
ptr = (uint8_t*)ptr + n;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
void write(void*& ptr, const T& t) {
|
|
|
|
|
*((T*)ptr) = t;
|
|
|
|
|
advance(ptr, sizeof(T));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
void write(void*& ptr, const std::string& s) {
|
|
|
|
|
// TFK: So we assume this is freed by h5 vlen reclaim?
|
|
|
|
|
char* c = new char[s.size() + 1];
|
|
|
|
|
strcpy(c, s.c_str());
|
|
|
|
|
write(ptr, c);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
void write_number_of_size(void*& ptr, size_t n, T i) {
|
|
|
|
|
void* old_ptr = ptr;
|
|
|
|
|
if (std::is_floating_point<T>::value) {
|
|
|
|
|
if (n == 4) {
|
|
|
|
|
write(ptr, static_cast< float_of_size<4>::type > (i));
|
|
|
|
|
} else if (n == 8) {
|
|
|
|
|
write(ptr, static_cast< float_of_size<8>::type > (i));
|
2015-11-30 22:34:48 +01:00
|
|
|
}
|
2017-09-01 12:50:42 +02:00
|
|
|
} else if (std::numeric_limits<T>::is_signed) {
|
|
|
|
|
if (n == 1) {
|
|
|
|
|
write(ptr, static_cast< int_of_size<1>::type > (i));
|
|
|
|
|
} else if (n == 2) {
|
|
|
|
|
write(ptr, static_cast< int_of_size<2>::type > (i));
|
|
|
|
|
} else if (n == 4) {
|
|
|
|
|
write(ptr, static_cast< int_of_size<4>::type > (i));
|
|
|
|
|
} else if (n == 8) {
|
|
|
|
|
write(ptr, static_cast< int_of_size<8>::type > (i));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// NB: enumeration_reference also ends up here
|
|
|
|
|
if (n == 1) {
|
|
|
|
|
write(ptr, static_cast< uint_of_size<1>::type > (i));
|
|
|
|
|
} else if (n == 2) {
|
|
|
|
|
write(ptr, static_cast< uint_of_size<2>::type > (i));
|
|
|
|
|
} else if (n == 4) {
|
|
|
|
|
write(ptr, static_cast< uint_of_size<4>::type > (i));
|
|
|
|
|
} else if (n == 8) {
|
|
|
|
|
write(ptr, static_cast< uint_of_size<8>::type > (i));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (old_ptr == ptr) {
|
|
|
|
|
throw std::runtime_error("No value written");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void write_string_of_size(void*& ptr, size_t n, const std::string& s) {
|
|
|
|
|
memset(ptr, 0, n);
|
|
|
|
|
memcpy(ptr, s.c_str(), s.size());
|
|
|
|
|
advance(ptr, n);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void write_vlen_t(void*& ptr, size_t n_elements, void* vlen_data) {
|
|
|
|
|
advance(ptr, HOFFSET(hvl_t, len));
|
|
|
|
|
void* temp_ptr;
|
|
|
|
|
write_number_of_size(temp_ptr = ptr, sizeof(size_t), n_elements);
|
|
|
|
|
advance(ptr, HOFFSET(hvl_t, p));
|
|
|
|
|
write(ptr, vlen_data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define CAST_AND_CALL(attr, type, fn) {IfcUtil::attr_type_to_cpp_type<type>::cpp_type v = *attr; fn(v);}
|
|
|
|
|
#define CHECK_CAST_AND_CALL(ty) else if (attr_->type() == ty) CAST_AND_CALL(attr_, ty, t)
|
|
|
|
|
|
|
|
|
|
class apply_attribute_visitor {
|
|
|
|
|
private:
|
|
|
|
|
Argument* attr_;
|
|
|
|
|
const IfcParse::entity::attribute* schema_attr_;
|
|
|
|
|
public:
|
|
|
|
|
apply_attribute_visitor(Argument* attr, const IfcParse::entity::attribute* schema_attr)
|
|
|
|
|
: attr_(attr)
|
|
|
|
|
, schema_attr_(schema_attr)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
typename T::return_type apply(T& t) const {
|
|
|
|
|
if (attr_->type() == IfcUtil::Argument_NULL) {
|
|
|
|
|
t(boost::none);
|
|
|
|
|
} else if (attr_->type() == IfcUtil::Argument_DERIVED) {
|
|
|
|
|
throw std::runtime_error("Derived attributes should not be written to the file");
|
|
|
|
|
// IfcWrite::IfcWriteArgument::Derived d;
|
|
|
|
|
// t(d);
|
|
|
|
|
}
|
|
|
|
|
CHECK_CAST_AND_CALL(IfcUtil::Argument_INT)
|
|
|
|
|
CHECK_CAST_AND_CALL(IfcUtil::Argument_BOOL)
|
|
|
|
|
CHECK_CAST_AND_CALL(IfcUtil::Argument_DOUBLE)
|
|
|
|
|
CHECK_CAST_AND_CALL(IfcUtil::Argument_STRING)
|
|
|
|
|
else if (attr_->type() == IfcUtil::Argument_BINARY) {
|
|
|
|
|
throw std::runtime_error("Binary not supported at the moment");
|
|
|
|
|
}
|
|
|
|
|
else if (attr_->type() == IfcUtil::Argument_ENUMERATION) {
|
|
|
|
|
std::string v = *attr_;
|
|
|
|
|
const std::vector<std::string>& enum_values = schema_attr_->type_of_attribute()->as_named_type()->declared_type()->as_enumeration_type()->enumeration_items();
|
|
|
|
|
size_t d = std::distance(enum_values.begin(), std::find(enum_values.begin(), enum_values.end(), v));
|
|
|
|
|
enumeration_reference enum_ref(d);
|
|
|
|
|
t(enum_ref);
|
|
|
|
|
}
|
|
|
|
|
CHECK_CAST_AND_CALL(IfcUtil::Argument_ENTITY_INSTANCE)
|
|
|
|
|
|
|
|
|
|
CHECK_CAST_AND_CALL(IfcUtil::Argument_AGGREGATE_OF_INT)
|
|
|
|
|
CHECK_CAST_AND_CALL(IfcUtil::Argument_AGGREGATE_OF_BOOL)
|
|
|
|
|
CHECK_CAST_AND_CALL(IfcUtil::Argument_AGGREGATE_OF_DOUBLE)
|
|
|
|
|
CHECK_CAST_AND_CALL(IfcUtil::Argument_AGGREGATE_OF_STRING)
|
|
|
|
|
else if (attr_->type() == IfcUtil::Argument_AGGREGATE_OF_BINARY) {
|
|
|
|
|
throw std::runtime_error("Not supported currently");
|
|
|
|
|
}
|
|
|
|
|
else if (attr_->type() == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) {
|
|
|
|
|
IfcUtil::attr_type_to_cpp_type<IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE>::cpp_type v = *attr_;
|
|
|
|
|
std::vector<IfcUtil::IfcBaseClass*> vec(v->begin(), v->end());
|
|
|
|
|
t(vec);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CHECK_CAST_AND_CALL(IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT)
|
|
|
|
|
CHECK_CAST_AND_CALL(IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_BOOL)
|
|
|
|
|
CHECK_CAST_AND_CALL(IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE)
|
|
|
|
|
else if (attr_->type() == IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE) {
|
|
|
|
|
IfcUtil::attr_type_to_cpp_type<IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE>::cpp_type v = *attr_;
|
|
|
|
|
std::vector< std::vector<IfcUtil::IfcBaseClass*> > vec(v->begin(), v->end());
|
|
|
|
|
t(vec);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else if (attr_->type() == IfcUtil::Argument_UNKNOWN) {
|
|
|
|
|
auto aggregation = schema_attr_->type_of_attribute()->as_aggregation_type();
|
|
|
|
|
if (aggregation == nullptr) {
|
|
|
|
|
throw std::exception("Attribute of unknown type encountered, expected empty aggregate");
|
|
|
|
|
}
|
|
|
|
|
auto elem_type = aggregation->type_of_element();
|
|
|
|
|
if (elem_type->as_named_type()) {
|
|
|
|
|
auto entity = elem_type->as_named_type()->declared_type()->as_entity();
|
|
|
|
|
if (entity == nullptr) {
|
|
|
|
|
throw std::exception("Not implemented");
|
|
|
|
|
}
|
|
|
|
|
std::vector<IfcUtil::IfcBaseClass*> empty;
|
|
|
|
|
t(empty);
|
|
|
|
|
} else if (elem_type->as_simple_type()) {
|
|
|
|
|
auto dt = elem_type->as_simple_type()->declared_type();
|
|
|
|
|
if (dt == IfcParse::simple_type::integer_type) {
|
|
|
|
|
std::vector<int> empty;
|
|
|
|
|
t(empty);
|
|
|
|
|
} else {
|
|
|
|
|
throw std::exception("Not implemented");
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
throw std::exception("Not implemented");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class sorted_instance_locator {
|
|
|
|
|
private:
|
2017-10-09 13:58:29 +02:00
|
|
|
H5::H5File& hdf5_file_;
|
2017-09-01 12:50:42 +02:00
|
|
|
IfcParse::IfcFile& file_;
|
|
|
|
|
std::vector< IfcSchema::Type::Enum > dataset_names_;
|
|
|
|
|
std::vector< std::vector<IfcUtil::IfcBaseEntity*>* > cache_;
|
2017-10-09 13:58:29 +02:00
|
|
|
bool referenced_;
|
2017-09-01 12:50:42 +02:00
|
|
|
|
2017-10-09 13:58:29 +02:00
|
|
|
public:
|
|
|
|
|
sorted_instance_locator(H5::H5File& hdf5_file, IfcParse::IfcFile& file, bool referenced)
|
|
|
|
|
: hdf5_file_(hdf5_file)
|
|
|
|
|
, file_(file)
|
|
|
|
|
, referenced_(referenced)
|
2017-09-01 12:50:42 +02:00
|
|
|
{
|
|
|
|
|
std::set<IfcSchema::Type::Enum> dataset_names_temp;
|
|
|
|
|
for (auto it = file_.begin(); it != file_.end(); ++it) {
|
|
|
|
|
dataset_names_temp.insert(it->second->declaration().type());
|
|
|
|
|
}
|
|
|
|
|
dataset_names_.assign(dataset_names_temp.begin(), dataset_names_temp.end());
|
|
|
|
|
std::sort(dataset_names_.begin(), dataset_names_.end());
|
|
|
|
|
|
|
|
|
|
cache_.resize(IfcSchema::Type::UNDEFINED);
|
|
|
|
|
|
2017-10-09 13:58:29 +02:00
|
|
|
if (referenced_) {
|
|
|
|
|
// Why not always populate?
|
|
|
|
|
const IfcSchema::Type::Enum begin = IfcSchema::Type::Ifc2DCompositeCurve;
|
|
|
|
|
const IfcSchema::Type::Enum end = IfcSchema::Type::UNDEFINED;
|
|
|
|
|
for (int i = begin; i != end; i++) {
|
|
|
|
|
instances((IfcSchema::Type::Enum)i);
|
|
|
|
|
}
|
2017-09-01 12:50:42 +02:00
|
|
|
}
|
2017-10-09 13:58:29 +02:00
|
|
|
}
|
2017-09-01 12:50:42 +02:00
|
|
|
|
2017-10-09 13:58:29 +02:00
|
|
|
typedef std::vector< IfcSchema::Type::Enum >::const_iterator const_iterator;
|
|
|
|
|
const_iterator begin() const { return dataset_names_.begin(); }
|
|
|
|
|
const_iterator end() const { return dataset_names_.end(); }
|
2017-09-01 12:50:42 +02:00
|
|
|
|
2017-10-09 13:58:29 +02:00
|
|
|
const std::vector<IfcUtil::IfcBaseEntity*>& instances(IfcSchema::Type::Enum t) {
|
2017-09-01 12:50:42 +02:00
|
|
|
if (cache_[t] == nullptr) {
|
|
|
|
|
auto li = file_.entitiesByType(t);
|
|
|
|
|
std::vector<IfcUtil::IfcBaseEntity*>* vs = cache_[t] = new std::vector<IfcUtil::IfcBaseEntity*>();
|
2017-10-09 13:58:29 +02:00
|
|
|
if (li) {
|
|
|
|
|
vs->reserve(li->size());
|
2017-09-01 12:50:42 +02:00
|
|
|
|
2017-10-09 13:58:29 +02:00
|
|
|
for (auto jt = li->begin(); jt != li->end(); ++jt) {
|
|
|
|
|
if ((*jt)->declaration().type() == t) {
|
|
|
|
|
vs->push_back(static_cast<IfcUtil::IfcBaseEntity*>(*jt));
|
|
|
|
|
}
|
2017-09-01 12:50:42 +02:00
|
|
|
}
|
2017-10-09 13:58:29 +02:00
|
|
|
|
|
|
|
|
std::sort(vs->begin(), vs->end(), [](IfcUtil::IfcBaseEntity* i1, IfcUtil::IfcBaseEntity* i2) {
|
|
|
|
|
return i1->data().id() < i2->data().id();
|
|
|
|
|
});
|
2017-09-01 12:50:42 +02:00
|
|
|
}
|
2017-10-09 13:58:29 +02:00
|
|
|
}
|
|
|
|
|
return *cache_[t];
|
|
|
|
|
}
|
2017-09-01 12:50:42 +02:00
|
|
|
|
2017-10-09 13:58:29 +02:00
|
|
|
std::string path(int dsidx) const {
|
|
|
|
|
return IfcSchema::Type::ToString(dataset_names_[dsidx]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::pair<int, int> operator()(IfcUtil::IfcBaseClass* v) {
|
|
|
|
|
if (IfcSchema::Type::IsSimple(v->declaration().type())) {
|
|
|
|
|
throw std::exception("Simple type not expected here");
|
2017-09-01 12:50:42 +02:00
|
|
|
}
|
|
|
|
|
|
2017-10-09 13:58:29 +02:00
|
|
|
IfcSchema::Type::Enum t = v->declaration().type();
|
|
|
|
|
auto tt = std::lower_bound(dataset_names_.begin(), dataset_names_.end(), t);
|
|
|
|
|
int a = std::distance(dataset_names_.begin(), tt);
|
|
|
|
|
int b;
|
|
|
|
|
|
|
|
|
|
const std::vector<IfcUtil::IfcBaseEntity*>& insts = instances(t);
|
|
|
|
|
|
|
|
|
|
auto it = std::lower_bound(insts.begin(), insts.end(), v);
|
|
|
|
|
b = std::distance(insts.begin(), it);
|
2017-09-01 12:50:42 +02:00
|
|
|
|
|
|
|
|
return std::make_pair(a, b);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class pointer_increment_assert {
|
|
|
|
|
void*& ptr_reference_;
|
|
|
|
|
uint8_t* ptr_initial_;
|
|
|
|
|
size_t datatype_size_;
|
|
|
|
|
public:
|
|
|
|
|
pointer_increment_assert(void*& ptr_reference, size_t datatype_size)
|
|
|
|
|
: ptr_reference_(ptr_reference)
|
|
|
|
|
, ptr_initial_(static_cast<uint8_t*>(ptr_reference))
|
|
|
|
|
, datatype_size_(datatype_size)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
~pointer_increment_assert() noexcept(false) {
|
|
|
|
|
if (ptr_initial_ + datatype_size_ != ptr_reference_) {
|
|
|
|
|
throw std::runtime_error("Incorrect amount of bytes written");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2017-09-24 13:48:16 +02:00
|
|
|
class default_value_visitor {
|
|
|
|
|
private:
|
|
|
|
|
H5::DataType& datatype_;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
default_value_visitor(H5::DataType& datatype)
|
|
|
|
|
: datatype_(datatype)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
void operator()(void*& ptr) {
|
|
|
|
|
switch (datatype_.getClass()) {
|
|
|
|
|
case H5T_INTEGER:
|
|
|
|
|
write_number_of_size(ptr, datatype_.getSize(), 0);
|
|
|
|
|
break;
|
|
|
|
|
case H5T_FLOAT:
|
|
|
|
|
write_number_of_size(ptr, datatype_.getSize(), 0.);
|
|
|
|
|
break;
|
|
|
|
|
case H5T_STRING:
|
|
|
|
|
if (datatype_ == H5::StrType(H5::PredType::C_S1, H5T_VARIABLE)) {
|
|
|
|
|
write(ptr, new char(0));
|
|
|
|
|
} else {
|
|
|
|
|
write_string_of_size(ptr, datatype_.getSize(), "");
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case H5T_COMPOUND:
|
|
|
|
|
{
|
|
|
|
|
H5::CompType* compound = (H5::CompType*) &datatype_;
|
|
|
|
|
for (int i = 0; i < compound->getNmembers(); ++i) {
|
|
|
|
|
H5::DataType attr_type = compound->getMemberDataType(i);
|
|
|
|
|
default_value_visitor visitor(attr_type);
|
|
|
|
|
visitor(ptr);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case H5T_REFERENCE:
|
2017-10-09 13:58:29 +02:00
|
|
|
// A bit hard to figure out, but apparently a null-reference is simply zeros
|
|
|
|
|
// https://github.com/h5py/h5py/blob/e611b7ca47e49d83e908d0368d2d9ced224a9de0/h5py/h5r.pyx#L167
|
|
|
|
|
if (datatype_.getSize() != sizeof(hdset_reg_ref_t)) {
|
2017-10-09 14:57:14 +02:00
|
|
|
throw std::runtime_error("Unexpected datatype size for reference");
|
2017-10-09 13:58:29 +02:00
|
|
|
}
|
|
|
|
|
memset(ptr, 0, sizeof(hdset_reg_ref_t));
|
|
|
|
|
advance(ptr, sizeof(hdset_reg_ref_t));
|
2017-09-24 13:48:16 +02:00
|
|
|
break;
|
|
|
|
|
case H5T_ENUM:
|
|
|
|
|
write_number_of_size(ptr, datatype_.getSize(), 0);
|
|
|
|
|
break;
|
|
|
|
|
case H5T_VLEN:
|
|
|
|
|
{
|
|
|
|
|
// H5::VarLenType* vlen = (H5::VarLenType*) &datatype_;
|
|
|
|
|
// Does this work?
|
|
|
|
|
write_vlen_t(ptr, 0, nullptr);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case H5T_ARRAY:
|
|
|
|
|
{
|
|
|
|
|
H5::ArrayType* arr = (H5::ArrayType*) &datatype_;
|
|
|
|
|
size_t ndims = arr->getArrayNDims();
|
|
|
|
|
hsize_t* array_dims = new hsize_t[ndims];
|
|
|
|
|
arr->getArrayDims(array_dims);
|
|
|
|
|
if (ndims != 1) {
|
|
|
|
|
throw std::runtime_error("Not implemented");
|
|
|
|
|
}
|
|
|
|
|
H5::DataType super = arr->getSuper();
|
|
|
|
|
default_value_visitor visitor(super);
|
|
|
|
|
for (hsize_t i = 0; i < array_dims[0]; ++i) {
|
|
|
|
|
visitor(ptr);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
throw std::runtime_error("Unexpected type encountered");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
// template <typename LocatorT>
|
|
|
|
|
class write_visit {
|
|
|
|
|
private:
|
2017-10-09 13:58:29 +02:00
|
|
|
H5::H5File& file_;
|
2017-09-01 12:50:42 +02:00
|
|
|
bool padded_;
|
|
|
|
|
bool referenced_;
|
|
|
|
|
type_mapper& type_mapper_;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
typedef sorted_instance_locator locator_type;
|
|
|
|
|
|
|
|
|
|
locator_type& instance_locator_;
|
|
|
|
|
|
2017-10-09 13:58:29 +02:00
|
|
|
write_visit(H5::H5File& file, bool padded, bool referenced, locator_type& instance_locator, type_mapper& type_mapper)
|
|
|
|
|
: file_(file)
|
|
|
|
|
, padded_(padded)
|
2017-09-01 12:50:42 +02:00
|
|
|
, referenced_(referenced)
|
|
|
|
|
, instance_locator_(instance_locator)
|
|
|
|
|
, type_mapper_(type_mapper)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
template <typename T, typename std::enable_if<is_hdf5_integral<T>::value, T>::type* = nullptr>
|
|
|
|
|
void visit(void*& ptr, H5::DataType& datatype, T& v) {
|
|
|
|
|
if (datatype.getClass() != hdf5_datatype_for<T>::value) {
|
|
|
|
|
throw std::runtime_error("Datatype and value do not match");
|
|
|
|
|
}
|
|
|
|
|
write_number_of_size(ptr, datatype.getSize(), v);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void visit(void*& ptr, H5::DataType& datatype, const boost::none_t&) {
|
|
|
|
|
// TODO: Do we need to do sth based on datatype here, eg. allocate vlen/char* if necessary?
|
|
|
|
|
memset(ptr, 0, datatype.getSize());
|
|
|
|
|
advance(ptr, datatype.getSize());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// template <>
|
|
|
|
|
void visit(void*& ptr, H5::DataType& datatype, std::string& v) {
|
|
|
|
|
pointer_increment_assert _(ptr, datatype.getSize());
|
|
|
|
|
if (padded_) {
|
|
|
|
|
if (compound_member_types_as_pair(datatype) != std::make_pair(H5T_INTEGER, H5T_STRING)) {
|
|
|
|
|
throw std::runtime_error("Datatype and value do not match");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
H5::CompType* compound = (H5::CompType*) &datatype;
|
|
|
|
|
H5::IntType int_type = compound->getMemberIntType(0);
|
|
|
|
|
H5::StrType string_type = compound->getMemberStrType(1);
|
|
|
|
|
|
|
|
|
|
if (string_type.getSize() < v.size()) {
|
|
|
|
|
throw std::runtime_error("Not enough space reserved for string");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
write_number_of_size(ptr, int_type.getSize(), v.size());
|
|
|
|
|
write_string_of_size(ptr, string_type.getSize(), v);
|
|
|
|
|
} else {
|
|
|
|
|
if (datatype.getClass() != H5T_STRING) {
|
|
|
|
|
throw std::runtime_error("Datatype and value do not match");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
H5::StrType* string_type = (H5::StrType*) &datatype;
|
|
|
|
|
|
|
|
|
|
// TFK: Check whether this does not leak resources
|
|
|
|
|
if (*string_type == H5::StrType(H5::PredType::C_S1, H5T_VARIABLE)) {
|
|
|
|
|
write(ptr, v);
|
|
|
|
|
} else {
|
|
|
|
|
if (string_type->getSize() < v.size()) {
|
|
|
|
|
throw std::runtime_error("Not enough space reserved for string");
|
|
|
|
|
}
|
|
|
|
|
write_string_of_size(ptr, string_type->getSize(), v);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void visit(void*& ptr, H5::DataType& datatype, select_item& v);
|
|
|
|
|
|
|
|
|
|
void visit(void*& ptr, H5::DataType& datatype, IfcUtil::IfcBaseClass*& v) {
|
|
|
|
|
|
|
|
|
|
// This does not seem to help
|
|
|
|
|
// if (datatype.committed()) {
|
|
|
|
|
// std::cout << datatype.getObjName();
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
if (is_select(datatype)) {
|
|
|
|
|
select_item si(v);
|
|
|
|
|
return visit(ptr, datatype, si);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pointer_increment_assert _(ptr, datatype.getSize());
|
|
|
|
|
|
2017-10-09 13:58:29 +02:00
|
|
|
std::pair<int, int> ref = instance_locator_(v);
|
|
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
if (referenced_) {
|
|
|
|
|
if (datatype.getClass() != H5T_REFERENCE) {
|
|
|
|
|
throw std::runtime_error("Datatype and value do not match");
|
|
|
|
|
}
|
2017-10-09 13:58:29 +02:00
|
|
|
hsize_t dims = instance_locator_.instances(v->declaration().type()).size();
|
|
|
|
|
H5::DataSpace space(1, &dims);
|
|
|
|
|
hsize_t coord = ref.second;
|
|
|
|
|
space.selectElements(H5S_SELECT_SET, 1, &coord);
|
|
|
|
|
// TODO: Make path configurable
|
|
|
|
|
file_.reference(ptr, "population/" + instance_locator_.path(ref.first) + "_instances", space);
|
|
|
|
|
advance(ptr, sizeof(hdset_reg_ref_t));
|
2017-09-01 12:50:42 +02:00
|
|
|
} else {
|
|
|
|
|
if (datatype.getClass() != H5T_COMPOUND) {
|
|
|
|
|
throw std::runtime_error("Datatype and value do not match");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (compound_member_types_as_pair(datatype) != std::make_pair(H5T_INTEGER, H5T_INTEGER)) {
|
|
|
|
|
throw std::runtime_error("Datatype and value do not match");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
H5::CompType* compound = (H5::CompType*) &datatype;
|
|
|
|
|
H5::IntType ds_idx = compound->getMemberIntType(0);
|
|
|
|
|
H5::IntType ds_row = compound->getMemberIntType(1);
|
|
|
|
|
|
|
|
|
|
write_number_of_size(ptr, ds_idx.getSize(), ref.first);
|
|
|
|
|
write_number_of_size(ptr, ds_row.getSize(), ref.second);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
void visit(void*& ptr, H5::DataType& datatype, std::vector<T>& v) {
|
|
|
|
|
pointer_increment_assert _(ptr, datatype.getSize());
|
|
|
|
|
if (padded_) {
|
|
|
|
|
if (datatype.getClass() != H5T_COMPOUND) {
|
|
|
|
|
throw std::runtime_error("Datatype and value do not match");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (compound_member_types_as_pair(datatype) != std::make_pair(H5T_INTEGER, H5T_ARRAY)) {
|
|
|
|
|
throw std::runtime_error("Datatype and value do not match");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
H5::CompType* compound = (H5::CompType*) &datatype;
|
|
|
|
|
H5::IntType size_dt = compound->getMemberIntType(0);
|
|
|
|
|
H5::ArrayType array_dt = compound->getMemberArrayType(1);
|
|
|
|
|
|
|
|
|
|
write_number_of_size(ptr, size_dt.getSize(), v.size());
|
|
|
|
|
|
|
|
|
|
// TFK: Enable multi-dimensional arrays for LISTS of LISTS as well.
|
|
|
|
|
if (array_dt.getArrayNDims() != 1) {
|
|
|
|
|
throw std::runtime_error("Unexpected array dimensions");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hsize_t n;
|
|
|
|
|
array_dt.getArrayDims(&n);
|
|
|
|
|
H5::DataType elem_dt = array_dt.getSuper();
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < n; ++i) {
|
|
|
|
|
if (i < v.size()) {
|
|
|
|
|
// I only get this to work if I make a copy.
|
|
|
|
|
// cannot convert from 'std::_Vb_reference<std::_Wrap_alloc<std::allocator<_Other>>>' to 'const boost::none_t' :(
|
|
|
|
|
T t = v[i];
|
|
|
|
|
visit(ptr, elem_dt, t);
|
|
|
|
|
} else {
|
2017-09-24 13:48:16 +02:00
|
|
|
default_value_visitor visitor(elem_dt);
|
|
|
|
|
visitor(ptr);
|
2017-09-01 12:50:42 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (datatype.getClass() != H5T_VLEN) {
|
|
|
|
|
throw std::runtime_error("Datatype and value do not match");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
H5::VarLenType* vlen = (H5::VarLenType*) &datatype;
|
|
|
|
|
H5::DataType elem_dt = vlen->getSuper();
|
|
|
|
|
|
|
|
|
|
void* vlen_data = new uint8_t[elem_dt.getSize() * v.size()];
|
|
|
|
|
void* temp = vlen_data;
|
|
|
|
|
for (size_t i = 0; i < v.size(); ++i) {
|
|
|
|
|
T t = v[i];
|
|
|
|
|
visit(temp, elem_dt, t);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
write_vlen_t(ptr, v.size(), vlen_data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// template <typename LocatorT>
|
|
|
|
|
class write_visit_instance_attribute {
|
|
|
|
|
private:
|
|
|
|
|
void*& ptr_;
|
|
|
|
|
write_visit& fn_;
|
|
|
|
|
H5::DataType& dt_;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
typedef void return_type;
|
|
|
|
|
|
|
|
|
|
write_visit_instance_attribute(void*& ptr, write_visit& fn, H5::DataType& dt)
|
|
|
|
|
: ptr_(ptr)
|
|
|
|
|
, fn_(fn)
|
|
|
|
|
, dt_(dt)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
void operator()(T& t) {
|
|
|
|
|
fn_.visit(ptr_, dt_, t);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const std::string Entity_Instance_Identifier = "Entity-Instance-Identifier";
|
|
|
|
|
static const std::string set_unset_bitmap = "set_unset_bitmap";
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
void IfcParse::IfcHdf5File::write_instance(void*& ptr, T& visitor, H5::DataType& datatype, IfcUtil::IfcBaseEntity* v) {
|
|
|
|
|
pointer_increment_assert _(ptr, datatype.getSize());
|
|
|
|
|
|
|
|
|
|
if (datatype.getClass() != H5T_COMPOUND) {
|
|
|
|
|
throw std::runtime_error("Datatype and value do not match");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
H5::CompType* compound = (H5::CompType*) &datatype;
|
|
|
|
|
|
|
|
|
|
auto attributes = v->declaration().all_attributes();
|
|
|
|
|
// TFK: Creating copies
|
|
|
|
|
// TFK: Do this once for every entity
|
|
|
|
|
std::vector<std::string> attribute_names;
|
|
|
|
|
attribute_names.reserve(attributes.size());
|
|
|
|
|
|
|
|
|
|
std::transform(attributes.begin(), attributes.end(),
|
|
|
|
|
std::back_inserter(attribute_names),
|
|
|
|
|
[](const IfcParse::entity::attribute* attr) {
|
|
|
|
|
return attr->name();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
void* set_unset_bitmap_location = 0;
|
|
|
|
|
uint32_t set_unset_bitmap_value = 0;
|
|
|
|
|
size_t set_unset_bitmap_size = 0;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < compound->getNmembers(); ++i) {
|
|
|
|
|
const std::string name = compound->getMemberName(i);
|
|
|
|
|
H5::DataType attr_type = compound->getMemberDataType(i);
|
|
|
|
|
|
|
|
|
|
if (name == Entity_Instance_Identifier) {
|
|
|
|
|
write_number_of_size(ptr, attr_type.getSize(), v->data().id());
|
|
|
|
|
continue;
|
|
|
|
|
} else if (name == set_unset_bitmap) {
|
|
|
|
|
set_unset_bitmap_location = ptr;
|
|
|
|
|
set_unset_bitmap_size = attr_type.getSize();
|
|
|
|
|
advance(ptr, set_unset_bitmap_size);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto it = std::find(attribute_names.begin(), attribute_names.end(), name);
|
|
|
|
|
if (it == attribute_names.end()) {
|
|
|
|
|
throw std::runtime_error("Unexpected compound member");
|
|
|
|
|
}
|
|
|
|
|
int idx = std::distance(attribute_names.begin(), it);
|
|
|
|
|
|
|
|
|
|
Argument* attr = v->data().getArgument(idx);
|
|
|
|
|
if (!attr->isNull()) {
|
|
|
|
|
// TODO: This is now index in IFC-attributes list, specify
|
|
|
|
|
set_unset_bitmap_value |= (1 << idx);
|
|
|
|
|
}
|
|
|
|
|
write_visit_instance_attribute/*<typename T::locator_type>*/ attribute_visitor(ptr, visitor, attr_type);
|
|
|
|
|
apply_attribute_visitor(attr, attributes[idx]).apply(attribute_visitor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (set_unset_bitmap_size && set_unset_bitmap_location) {
|
|
|
|
|
write_number_of_size(set_unset_bitmap_location, set_unset_bitmap_size, set_unset_bitmap_value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void write_visit::visit(void*& ptr, H5::DataType& datatype, select_item& v) {
|
|
|
|
|
pointer_increment_assert _(ptr, datatype.getSize());
|
|
|
|
|
|
|
|
|
|
IfcUtil::IfcBaseClass* data = v;
|
|
|
|
|
|
|
|
|
|
H5::CompType* compound = (H5::CompType*) &datatype;
|
|
|
|
|
const bool data_is_entity = !!data->declaration().as_entity();
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < compound->getNmembers(); ++i) {
|
|
|
|
|
const std::string name = compound->getMemberName(i);
|
|
|
|
|
H5::DataType attr_type = compound->getMemberDataType(i);
|
|
|
|
|
|
|
|
|
|
if (name == "type_code") {
|
|
|
|
|
write_number_of_size(ptr, attr_type.getSize(), data->declaration().type());
|
|
|
|
|
} else if (data_is_entity && name == "instance-value") {
|
|
|
|
|
visit(ptr, attr_type, data);
|
2017-10-09 13:58:29 +02:00
|
|
|
} else if (type_mapper_.make_select_leaf(&data->declaration(), no_instances).first == name) {
|
2017-09-01 12:50:42 +02:00
|
|
|
write_visit_instance_attribute/*<typename T::locator_type>*/ attribute_visitor(ptr, *this, attr_type);
|
|
|
|
|
apply_attribute_visitor(data->data().getArgument(0), 0).apply(attribute_visitor);
|
|
|
|
|
} else {
|
|
|
|
|
default_value_visitor visitor(attr_type);
|
|
|
|
|
visitor(ptr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
H5::CompType* create_compound(const std::vector< IfcParse::IfcHdf5File::compound_member >& members) {
|
|
|
|
|
size_t s = 0, o = 0;
|
|
|
|
|
for (auto it = members.begin(); it != members.end(); ++it) {
|
|
|
|
|
s += it->second->getSize();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
H5::CompType* h5_dt = new H5::CompType(s);
|
|
|
|
|
for (auto it = members.begin(); it != members.end(); ++it) {
|
|
|
|
|
h5_dt->insertMember(it->first, o, *it->second);
|
|
|
|
|
o += it->second->getSize();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return h5_dt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
H5::EnumType* create_enumeration(const std::vector<std::string>& items, int offset = 0) {
|
|
|
|
|
size_t numbytes = 0;
|
|
|
|
|
size_t size = items.size();
|
|
|
|
|
while (size != 0) {
|
|
|
|
|
size >>= 8;
|
|
|
|
|
numbytes++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int i = offset;
|
|
|
|
|
H5::EnumType* h5_enum = new H5::EnumType(numbytes);
|
|
|
|
|
for (auto it = items.begin(); it != items.end(); ++it, ++i) {
|
|
|
|
|
h5_enum->insert(it->c_str(), &i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return h5_enum;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void visit_select(const IfcParse::select_type* pt, std::set<const IfcParse::declaration*>& leafs) {
|
|
|
|
|
for (auto it = pt->select_list().begin(); it != pt->select_list().end(); ++it) {
|
|
|
|
|
if ((*it)->as_select_type()) {
|
|
|
|
|
visit_select((*it)->as_select_type(), leafs);
|
|
|
|
|
} else {
|
|
|
|
|
leafs.insert(*it);
|
2015-11-30 22:34:48 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
class UnmetDependencyException : public std::exception {};
|
|
|
|
|
|
|
|
|
|
std::string type_mapper::flatten_aggregate_name(const IfcParse::parameter_type* at) const {
|
|
|
|
|
if (at->as_aggregation_type()) {
|
|
|
|
|
return std::string("aggregate-of-") + flatten_aggregate_name(at->as_aggregation_type()->type_of_element());
|
|
|
|
|
} else if (at->as_simple_type()) {
|
|
|
|
|
return default_type_names_[at->as_simple_type()->declared_type()];
|
|
|
|
|
} else if (at->as_named_type()) {
|
|
|
|
|
// TODO: Unwind type name
|
|
|
|
|
return at->as_named_type()->declared_type()->name();
|
|
|
|
|
} else {
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-24 13:48:16 +02:00
|
|
|
type_mapper::type_mapper(IfcParse::IfcFile& ifc_file, H5::H5File* hdf5_file, const IfcParse::Hdf5Settings& settings)
|
2017-09-01 12:50:42 +02:00
|
|
|
: ifc_file_(ifc_file)
|
|
|
|
|
, hdf5_file_(hdf5_file)
|
2017-09-24 13:48:16 +02:00
|
|
|
, settings_(settings)
|
|
|
|
|
, padded_(settings_.profile() == IfcParse::Hdf5Settings::padded || settings_.profile() == IfcParse::Hdf5Settings::padded_referenced)
|
|
|
|
|
, referenced_(settings_.profile() == IfcParse::Hdf5Settings::standard_referenced || settings_.profile() == IfcParse::Hdf5Settings::padded_referenced)
|
2017-09-01 12:50:42 +02:00
|
|
|
{
|
|
|
|
|
schema_group_ = hdf5_file_->openGroup(ifc_file_.schema()->name() + "_encoding");
|
|
|
|
|
|
|
|
|
|
default_types_.resize(IfcParse::simple_type::datatype_COUNT);
|
|
|
|
|
default_type_names_.resize(IfcParse::simple_type::datatype_COUNT);
|
|
|
|
|
default_cpp_type_names_.resize(IfcUtil::Argument_UNKNOWN);
|
|
|
|
|
declared_types_.resize(IfcSchema::Type::UNDEFINED);
|
|
|
|
|
|
2017-10-09 13:58:29 +02:00
|
|
|
|
|
|
|
|
if (referenced_) {
|
|
|
|
|
instance_reference_ = commit(new H5::PredType(H5::PredType::STD_REF_DSETREG), "_HDF_INSTANCE_REFERENCE_HANDLE_");
|
|
|
|
|
} else {
|
2017-09-01 12:50:42 +02:00
|
|
|
std::vector< IfcParse::IfcHdf5File::compound_member > members;
|
|
|
|
|
members.push_back(std::make_pair(std::string("_HDF5_dataset_index_"), new H5::PredType(H5::PredType::NATIVE_INT16)));
|
|
|
|
|
members.push_back(std::make_pair(std::string("_HDF5_instance_index_"), new H5::PredType(H5::PredType::NATIVE_INT32)));
|
2017-10-09 13:58:29 +02:00
|
|
|
instance_reference_ = commit(create_compound(members), "_HDF_INSTANCE_REFERENCE_HANDLE_");
|
2017-09-01 12:50:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
std::vector<std::string> names;
|
|
|
|
|
names.push_back("BOOLEAN-FALSE");
|
|
|
|
|
names.push_back("BOOLEAN-TRUE");
|
|
|
|
|
default_types_[IfcParse::simple_type::boolean_type] = create_enumeration(names);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
std::vector<std::string> names;
|
|
|
|
|
names.push_back("LOGICAL-UNKNOWN");
|
|
|
|
|
names.push_back("LOGICAL-FALSE");
|
|
|
|
|
names.push_back("LOGICAL-TRUE");
|
|
|
|
|
default_types_[IfcParse::simple_type::logical_type] = create_enumeration(names, -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
default_types_[IfcParse::simple_type::binary_type] = &H5::PredType::NATIVE_OPAQUE; // vlen?
|
|
|
|
|
default_types_[IfcParse::simple_type::real_type] = &H5::PredType::NATIVE_DOUBLE;
|
|
|
|
|
default_types_[IfcParse::simple_type::number_type] = &H5::PredType::NATIVE_DOUBLE;
|
|
|
|
|
default_types_[IfcParse::simple_type::string_type] = new H5::StrType(H5::PredType::C_S1, H5T_VARIABLE);
|
|
|
|
|
default_types_[IfcParse::simple_type::integer_type] = &H5::PredType::NATIVE_INT;
|
|
|
|
|
|
|
|
|
|
default_type_names_[IfcParse::simple_type::logical_type] = "logical";
|
|
|
|
|
default_type_names_[IfcParse::simple_type::boolean_type] = "boolean";
|
|
|
|
|
default_type_names_[IfcParse::simple_type::binary_type] = "binary";
|
|
|
|
|
default_type_names_[IfcParse::simple_type::real_type] = "real";
|
|
|
|
|
default_type_names_[IfcParse::simple_type::number_type] = "number";
|
|
|
|
|
default_type_names_[IfcParse::simple_type::string_type] = "string";
|
|
|
|
|
default_type_names_[IfcParse::simple_type::integer_type] = "integer";
|
|
|
|
|
|
|
|
|
|
default_cpp_type_names_[IfcUtil::Argument_BOOL] = "boolean";
|
|
|
|
|
default_cpp_type_names_[IfcUtil::Argument_DOUBLE] = "real";
|
|
|
|
|
default_cpp_type_names_[IfcUtil::Argument_STRING] = "string";
|
|
|
|
|
default_cpp_type_names_[IfcUtil::Argument_INT] = "integer";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
H5::DataType* type_mapper::commit(H5::DataType* dt, const std::string& name) {
|
|
|
|
|
dt->commit(schema_group_, name);
|
|
|
|
|
return dt;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-09 13:58:29 +02:00
|
|
|
H5::DataType* type_mapper::operator()(const IfcParse::parameter_type* pt, const boost::optional< std::vector<Argument*> >& instances, int dims, const hsize_t* max_length) {
|
2017-09-24 13:48:16 +02:00
|
|
|
H5::DataType* h5_dt = nullptr;
|
2015-11-10 11:16:00 +01:00
|
|
|
if (pt->as_aggregation_type()) {
|
2017-09-24 13:48:16 +02:00
|
|
|
if (padded_ && dims && max_length) {
|
2017-09-01 12:50:42 +02:00
|
|
|
// TODO: Check whether these pointers can safely be dereferenced
|
2017-09-24 13:48:16 +02:00
|
|
|
|
|
|
|
|
// Zero dim arrays are not supported
|
|
|
|
|
hsize_t* max_length_copy = new hsize_t[dims];
|
|
|
|
|
memcpy(max_length_copy, max_length, sizeof(hsize_t) * dims);
|
|
|
|
|
if (max_length_copy[0] == 0) max_length_copy[0] = 1;
|
|
|
|
|
|
2017-10-09 13:58:29 +02:00
|
|
|
// Assume attribute lists are homogeneous and can be directly passed to supertypes
|
|
|
|
|
H5::DataType* element_dt = (*this)(pt->as_aggregation_type()->type_of_element(), instances, dims - 1, max_length + 1);
|
|
|
|
|
|
|
|
|
|
if (element_dt == nullptr) {
|
|
|
|
|
// in case of select with all instance refs
|
|
|
|
|
element_dt = instance_reference_;
|
|
|
|
|
}
|
2017-09-24 13:48:16 +02:00
|
|
|
|
|
|
|
|
std::vector< IfcParse::IfcHdf5File::compound_member > members;
|
|
|
|
|
members.push_back(std::make_pair(std::string("length"), new H5::PredType(H5::PredType::NATIVE_UINT32)));
|
|
|
|
|
members.push_back(std::make_pair(std::string("data"), new H5::ArrayType(*element_dt, 1, max_length_copy)));
|
|
|
|
|
h5_dt = create_compound(members);
|
|
|
|
|
|
|
|
|
|
delete[] max_length_copy;
|
2017-09-01 12:50:42 +02:00
|
|
|
} else {
|
|
|
|
|
h5_dt = new H5::VarLenType((*this)(pt->as_aggregation_type()->type_of_element()));
|
|
|
|
|
}
|
2015-11-10 11:16:00 +01:00
|
|
|
} else if (pt->as_named_type()) {
|
|
|
|
|
if (pt->as_named_type()->declared_type()->as_entity()) {
|
2017-09-01 12:50:42 +02:00
|
|
|
return instance_reference_;
|
|
|
|
|
// TFK: Do not copy, we want to retain path to simplify datatype identify checks later on
|
|
|
|
|
// h5_dt = new H5::DataType();
|
|
|
|
|
// h5_dt->copy(*instance_reference_);
|
2015-11-10 11:16:00 +01:00
|
|
|
} else {
|
2017-09-24 13:48:16 +02:00
|
|
|
|
|
|
|
|
if (padded_ && dims && max_length) {
|
|
|
|
|
auto decl = pt->as_named_type()->declared_type();
|
|
|
|
|
while (decl->as_type_declaration()) {
|
|
|
|
|
const IfcParse::parameter_type* leaf_pt = decl->as_type_declaration()->declared_type();
|
|
|
|
|
const IfcParse::named_type* nt = leaf_pt->as_named_type();
|
|
|
|
|
if (nt) {
|
|
|
|
|
decl = nt->declared_type();
|
|
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (
|
|
|
|
|
decl->as_type_declaration() &&
|
|
|
|
|
decl->as_type_declaration()->declared_type()->as_simple_type() &&
|
|
|
|
|
decl->as_type_declaration()->declared_type()->as_simple_type()->declared_type() == IfcParse::simple_type::string_type)
|
|
|
|
|
{
|
|
|
|
|
std::vector< IfcParse::IfcHdf5File::compound_member > members;
|
|
|
|
|
members.push_back(std::make_pair(std::string("length"), new H5::PredType(H5::PredType::NATIVE_UINT32)));
|
|
|
|
|
members.push_back(std::make_pair(std::string("data"), new H5::StrType(H5::PredType::C_S1, (size_t) max_length[0] + 1)));
|
|
|
|
|
h5_dt = create_compound(members);
|
2017-10-09 13:58:29 +02:00
|
|
|
} else if (decl->as_type_declaration() && decl->as_type_declaration()->declared_type()->as_aggregation_type()) {
|
|
|
|
|
H5::DataType* element_dt = (*this)(decl->as_type_declaration()->declared_type()->as_aggregation_type()->type_of_element(), instances, dims - 1, max_length + 1);
|
|
|
|
|
|
|
|
|
|
if (element_dt == nullptr) {
|
|
|
|
|
// in case of select with all instance refs
|
|
|
|
|
element_dt = instance_reference_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector< IfcParse::IfcHdf5File::compound_member > members;
|
|
|
|
|
members.push_back(std::make_pair(std::string("length"), new H5::PredType(H5::PredType::NATIVE_UINT32)));
|
|
|
|
|
members.push_back(std::make_pair(std::string("data"), new H5::ArrayType(*element_dt, 1, max_length)));
|
|
|
|
|
h5_dt = create_compound(members);
|
2017-09-24 13:48:16 +02:00
|
|
|
}
|
2017-10-09 13:58:29 +02:00
|
|
|
|
2017-09-24 13:48:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!h5_dt) {
|
|
|
|
|
IfcSchema::Type::Enum ty = pt->as_named_type()->declared_type()->type();
|
|
|
|
|
if (!declared_types_[ty]) {
|
|
|
|
|
if (padded_) {
|
|
|
|
|
if (pt->as_named_type()->declared_type()->as_select_type()) {
|
|
|
|
|
// For padded ifc-hdf the select type is based on model population
|
|
|
|
|
return (*this)(pt->as_named_type()->declared_type()->as_select_type(), instances);
|
|
|
|
|
} else if (pt->as_named_type()->declared_type()->as_type_declaration()) {
|
|
|
|
|
return (*this)(pt->as_named_type()->declared_type()->as_type_declaration()->declared_type(), instances);
|
|
|
|
|
} else {
|
|
|
|
|
throw UnmetDependencyException();
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
throw UnmetDependencyException();
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// TFK: Copy, as well be committed under different name?
|
|
|
|
|
h5_dt = new H5::DataType();
|
|
|
|
|
h5_dt->copy(*declared_types_[ty]);
|
|
|
|
|
}
|
2015-11-10 11:16:00 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (pt->as_simple_type()) {
|
2017-09-24 13:48:16 +02:00
|
|
|
// TODO: This branch has redundancies with pt->as_named_type
|
|
|
|
|
if (padded_ && dims && max_length && pt->as_simple_type()->declared_type() == IfcParse::simple_type::string_type) {
|
|
|
|
|
std::vector< IfcParse::IfcHdf5File::compound_member > members;
|
|
|
|
|
members.push_back(std::make_pair(std::string("length"), new H5::PredType(H5::PredType::NATIVE_UINT32)));
|
|
|
|
|
members.push_back(std::make_pair(std::string("data"), new H5::StrType(H5::PredType::C_S1, (size_t) max_length[0] + 1)));
|
|
|
|
|
h5_dt = create_compound(members);
|
|
|
|
|
} else {
|
|
|
|
|
// TFK: Copy, as well be committed under different name?
|
|
|
|
|
const H5::DataType* orig = default_types_[pt->as_simple_type()->declared_type()];
|
|
|
|
|
h5_dt = new H5::DataType();
|
|
|
|
|
h5_dt->copy(*orig);
|
|
|
|
|
}
|
2015-11-10 11:16:00 +01:00
|
|
|
} else {
|
|
|
|
|
throw UnmetDependencyException();
|
|
|
|
|
}
|
2017-09-01 12:50:42 +02:00
|
|
|
|
2015-11-10 11:16:00 +01:00
|
|
|
return h5_dt;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-09 13:58:29 +02:00
|
|
|
class max_length_visitor {
|
|
|
|
|
private:
|
|
|
|
|
std::vector<hsize_t> max_length_;
|
|
|
|
|
void contain(size_t dim, size_t count) {
|
|
|
|
|
if (dim == max_length_.size()) {
|
|
|
|
|
max_length_.push_back(count);
|
|
|
|
|
} else if (count > max_length_[dim]) {
|
|
|
|
|
max_length_[dim] = count;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
typedef void return_type;
|
|
|
|
|
|
|
|
|
|
void operator()(const IfcEntityList::ptr& aggregate) {
|
|
|
|
|
contain(0, aggregate->size());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void operator()(const IfcEntityListList::ptr& aggregate) {
|
|
|
|
|
contain(0, aggregate->size());
|
|
|
|
|
for (auto it = aggregate->begin(); it != aggregate->end(); ++it) {
|
|
|
|
|
contain(1, it->size());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void operator()(const std::string& str) {
|
|
|
|
|
contain(0, str.size());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void operator()(const std::vector<std::string>& aggregate) {
|
|
|
|
|
contain(0, aggregate.size());
|
|
|
|
|
for (auto it = aggregate.begin(); it != aggregate.end(); ++it) {
|
|
|
|
|
contain(1, it->size());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
void operator()(const std::vector< std::vector<T> >& aggregate) {
|
|
|
|
|
contain(0, aggregate.size());
|
|
|
|
|
for (auto it = aggregate.begin(); it != aggregate.end(); ++it) {
|
|
|
|
|
contain(1, it->size());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
void operator()(const std::vector<T>& aggregate) {
|
|
|
|
|
contain(0, aggregate.size());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
void operator()(const T&) {
|
|
|
|
|
// Empty on purpose
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
operator bool() const {
|
|
|
|
|
return !max_length_.empty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int dims() const {
|
|
|
|
|
return (int)max_length_.size();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const hsize_t* max_length() const {
|
|
|
|
|
return max_length_.data();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
std::pair<std::string, const H5::DataType*> type_mapper::make_select_leaf(const IfcParse::declaration* decl, const boost::optional< std::vector<Argument*> >& instances) {
|
2017-09-01 12:50:42 +02:00
|
|
|
std::string name;
|
|
|
|
|
const H5::DataType* dt = 0;
|
|
|
|
|
|
|
|
|
|
if (decl) {
|
|
|
|
|
while (decl->as_type_declaration()) {
|
|
|
|
|
const IfcParse::parameter_type* leaf_pt = decl->as_type_declaration()->declared_type();
|
|
|
|
|
const IfcParse::named_type* nt = leaf_pt->as_named_type();
|
|
|
|
|
const IfcParse::simple_type* st = leaf_pt->as_simple_type();
|
|
|
|
|
const IfcParse::aggregation_type* at = leaf_pt->as_aggregation_type();
|
|
|
|
|
if (nt) {
|
|
|
|
|
decl = nt->declared_type();
|
|
|
|
|
} else if (st) {
|
|
|
|
|
name = default_type_names_[st->declared_type()];
|
2017-10-09 13:58:29 +02:00
|
|
|
if (padded_ && instances && st->declared_type() == IfcParse::simple_type::string_type) {
|
|
|
|
|
max_length_visitor visitor;
|
|
|
|
|
std::for_each(instances->begin(), instances->end(), [&visitor](Argument* attr) {
|
|
|
|
|
if (attr->type() != IfcUtil::Argument_ENTITY_INSTANCE) {
|
|
|
|
|
throw std::runtime_error("Expected an entity instance or simple type");
|
|
|
|
|
}
|
|
|
|
|
IfcUtil::IfcBaseClass* inst = *attr;
|
|
|
|
|
if (!inst->declaration().as_entity()) {
|
|
|
|
|
Argument* simple_type = inst->data().getArgument(0);
|
|
|
|
|
if (simple_type->type() == IfcUtil::Argument_STRING) {
|
|
|
|
|
// Reference to schema_attr is to resolve enumeration and unknown, it's not necessary here as we explicitely filter on strings.
|
|
|
|
|
apply_attribute_visitor(simple_type, nullptr).apply(visitor);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!visitor) {
|
|
|
|
|
throw std::runtime_error("Unable to determine string width within select type");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector< IfcParse::IfcHdf5File::compound_member > members;
|
|
|
|
|
members.push_back(std::make_pair(std::string("length"), new H5::PredType(H5::PredType::NATIVE_UINT32)));
|
|
|
|
|
members.push_back(std::make_pair(std::string("data"), new H5::StrType(H5::PredType::C_S1, (size_t)visitor.max_length()[0] + 1)));
|
|
|
|
|
dt = create_compound(members);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
dt = default_types_[st->declared_type()];
|
|
|
|
|
}
|
2017-09-01 12:50:42 +02:00
|
|
|
break;
|
|
|
|
|
} else if (at) {
|
|
|
|
|
name = flatten_aggregate_name(at);
|
|
|
|
|
dt = (*this)(at);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-11-10 11:16:00 +01:00
|
|
|
}
|
|
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
if (!dt) {
|
|
|
|
|
if (decl->as_entity()) {
|
|
|
|
|
name = "instance";
|
|
|
|
|
dt = instance_reference_;
|
|
|
|
|
} else if (decl->as_enumeration_type()) {
|
|
|
|
|
name = decl->name();
|
|
|
|
|
dt = declared_types_[decl->type()];
|
|
|
|
|
} else {
|
|
|
|
|
throw;
|
|
|
|
|
}
|
2015-11-10 11:16:00 +01:00
|
|
|
}
|
|
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
name += "-value";
|
|
|
|
|
|
|
|
|
|
return std::make_pair(name, dt);
|
2015-11-10 11:16:00 +01:00
|
|
|
}
|
|
|
|
|
|
2017-10-09 13:58:29 +02:00
|
|
|
H5::DataType* type_mapper::operator()(const IfcParse::select_type* pt, const boost::optional< std::vector<Argument*> >& instances, int, const hsize_t*) {
|
2017-09-24 13:48:16 +02:00
|
|
|
std::set<const IfcParse::declaration*> leafs_schema;
|
|
|
|
|
visit_select(pt, leafs_schema);
|
|
|
|
|
|
|
|
|
|
std::set<const IfcParse::declaration*> leafs_model;
|
|
|
|
|
std::set<const IfcParse::declaration*>* leafs = &leafs_schema;
|
|
|
|
|
|
2017-10-09 13:58:29 +02:00
|
|
|
if (padded_ && instances) {
|
2017-09-24 13:48:16 +02:00
|
|
|
std::set<const IfcParse::declaration*> instantiated;
|
2017-10-09 13:58:29 +02:00
|
|
|
std::for_each(instances->begin(), instances->end(), [&instantiated](Argument* attr) {
|
|
|
|
|
auto add_to_instantiation = [&instantiated](IfcUtil::IfcBaseClass* inst){
|
|
|
|
|
instantiated.insert(&inst->declaration());
|
|
|
|
|
if (inst->declaration().as_entity()) {
|
|
|
|
|
auto entity = inst->declaration().as_entity();
|
|
|
|
|
while (entity->supertype()) {
|
|
|
|
|
entity = entity->supertype();
|
|
|
|
|
instantiated.insert(entity);
|
|
|
|
|
}
|
2017-09-24 13:48:16 +02:00
|
|
|
}
|
2017-10-09 13:58:29 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
switch (attr->type()) {
|
|
|
|
|
// Should check for null?
|
|
|
|
|
case IfcUtil::Argument_ENTITY_INSTANCE: {
|
|
|
|
|
IfcUtil::IfcBaseClass* inst = *attr;
|
|
|
|
|
add_to_instantiation(inst);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE: {
|
|
|
|
|
IfcEntityList::ptr insts = *attr;
|
|
|
|
|
std::for_each(insts->begin(), insts->end(), add_to_instantiation);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
throw std::exception("Unexpected attribute types for datatype width reference");
|
2017-09-24 13:48:16 +02:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
std::set_intersection(leafs_schema.begin(), leafs_schema.end(), instantiated.begin(), instantiated.end(), std::inserter(leafs_model, leafs_model.end()));
|
|
|
|
|
leafs = &leafs_model;
|
|
|
|
|
}
|
2015-11-10 11:16:00 +01:00
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
bool all_entity_instance_refs = true;
|
2017-09-24 13:48:16 +02:00
|
|
|
for (auto it = leafs->begin(); it != leafs->end(); ++it) {
|
2017-09-01 12:50:42 +02:00
|
|
|
if (!(*it)->as_entity()) {
|
|
|
|
|
all_entity_instance_refs = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2015-11-10 11:16:00 +01:00
|
|
|
}
|
|
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
if (all_entity_instance_refs) {
|
|
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
|
std::set<std::string> member_names;
|
|
|
|
|
std::vector<IfcParse::IfcHdf5File::compound_member> h5_attributes;
|
2015-11-10 11:16:00 +01:00
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
h5_attributes.push_back(std::make_pair(std::string("type_code"), &H5::PredType::NATIVE_INT16));
|
2015-11-10 11:16:00 +01:00
|
|
|
|
2017-09-24 13:48:16 +02:00
|
|
|
for (auto it = leafs->begin(); it != leafs->end(); ++it) {
|
2017-09-01 12:50:42 +02:00
|
|
|
const IfcParse::declaration* decl = (*it);
|
2017-10-09 13:58:29 +02:00
|
|
|
auto leaf_type = make_select_leaf(decl, instances);
|
2017-09-01 12:50:42 +02:00
|
|
|
|
|
|
|
|
if (member_names.find(leaf_type.first) != member_names.end()) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
member_names.insert(leaf_type.first);
|
|
|
|
|
|
|
|
|
|
h5_attributes.push_back(leaf_type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return create_compound(h5_attributes);
|
|
|
|
|
}
|
2015-11-10 11:16:00 +01:00
|
|
|
}
|
|
|
|
|
|
2017-09-24 13:48:16 +02:00
|
|
|
class apply_attribute_visitor_instance_list {
|
|
|
|
|
private:
|
|
|
|
|
const IfcEntityList::ptr& instances_;
|
|
|
|
|
int attribute_idx_;
|
|
|
|
|
public:
|
|
|
|
|
apply_attribute_visitor_instance_list(const IfcEntityList::ptr& instances, int attribute_idx)
|
|
|
|
|
: instances_(instances)
|
|
|
|
|
, attribute_idx_(attribute_idx)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
typename T::return_type apply(T& t) const {
|
|
|
|
|
for (auto it = instances_->begin(); it != instances_->end(); ++it) {
|
|
|
|
|
apply_attribute_visitor((**it).data().getArgument(attribute_idx_), (**it).declaration().as_entity()->all_attributes()[attribute_idx_]).apply(t);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class all_null_visitor {
|
|
|
|
|
private:
|
|
|
|
|
bool all_null_;
|
|
|
|
|
public:
|
|
|
|
|
typedef void return_type;
|
|
|
|
|
|
|
|
|
|
all_null_visitor()
|
|
|
|
|
: all_null_(true)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
void operator()(const boost::none_t&) {
|
|
|
|
|
// Empty on purpose
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
void operator()(const T&) {
|
|
|
|
|
all_null_ = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool all_null() const {
|
|
|
|
|
return all_null_;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2017-10-09 13:58:29 +02:00
|
|
|
H5::CompType* type_mapper::operator()(const IfcParse::entity* e, const boost::optional< std::vector<Argument*> >&, int, const hsize_t*) {
|
2017-09-01 12:50:42 +02:00
|
|
|
|
|
|
|
|
// List of entity instances of this type, no subtypes
|
|
|
|
|
IfcEntityList::ptr incl_subtypes = ifc_file_.entitiesByType(e->name());
|
|
|
|
|
IfcEntityList::ptr instances(new IfcEntityList);
|
|
|
|
|
if (incl_subtypes) {
|
|
|
|
|
for (auto it = incl_subtypes->begin(); it != incl_subtypes->end(); ++it) {
|
|
|
|
|
if ((**it).declaration().type() == e->type()) {
|
|
|
|
|
instances->push(*it);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (instances->size() == 0) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-10 11:16:00 +01:00
|
|
|
std::vector<const IfcParse::entity::attribute*> attributes = e->all_attributes();
|
2015-11-30 22:34:48 +01:00
|
|
|
std::vector<const IfcParse::entity::inverse_attribute*> inverse_attributes;
|
|
|
|
|
if (settings_.instantiate_inverse()) {
|
|
|
|
|
inverse_attributes = e->all_inverse_attributes();
|
|
|
|
|
}
|
2015-11-10 11:16:00 +01:00
|
|
|
|
|
|
|
|
const std::vector<bool>& attributes_derived_in_subtype = e->derived();
|
2017-09-01 12:50:42 +02:00
|
|
|
|
|
|
|
|
bool has_optional_attributes = false;
|
|
|
|
|
const size_t num_extra = has_optional_attributes ? 2 : 1;
|
2017-09-24 13:48:16 +02:00
|
|
|
size_t num_all_null = 0;
|
2017-09-01 12:50:42 +02:00
|
|
|
std::vector<bool> attributes_all_null(attributes.size(), false);
|
|
|
|
|
|
2015-11-10 11:16:00 +01:00
|
|
|
auto jt = attributes_derived_in_subtype.begin();
|
2017-09-01 12:50:42 +02:00
|
|
|
for (auto it = attributes.begin(); it != attributes.end(); ++it, ++jt) {
|
|
|
|
|
if (*jt) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if ((**it).optional()) {
|
|
|
|
|
const int idx = std::distance(attributes.begin(), it);
|
|
|
|
|
|
|
|
|
|
has_optional_attributes = true;
|
|
|
|
|
|
|
|
|
|
apply_attribute_visitor_instance_list dispatch(instances, idx);
|
|
|
|
|
all_null_visitor visitor;
|
|
|
|
|
dispatch.apply(visitor);
|
|
|
|
|
if (visitor.all_null()) {
|
|
|
|
|
num_all_null += 1;
|
|
|
|
|
attributes_all_null[idx] = true;
|
2017-09-24 13:48:16 +02:00
|
|
|
// attributes_omitted.insert(std::make_pair(e->name(), idx));
|
2017-09-01 12:50:42 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-11-10 11:16:00 +01:00
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
/*
|
|
|
|
|
if (has_optional_attributes) {
|
|
|
|
|
entities_with_optional_attrs.insert(e->name());
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
std::vector< IfcParse::IfcHdf5File::compound_member > h5_attributes;
|
|
|
|
|
h5_attributes.reserve(attributes.size() + inverse_attributes.size() + num_extra);
|
|
|
|
|
|
|
|
|
|
if (has_optional_attributes) {
|
|
|
|
|
h5_attributes.push_back(std::make_pair(std::string("set_unset_bitmap"), &H5::PredType::NATIVE_INT16));
|
|
|
|
|
}
|
|
|
|
|
h5_attributes.push_back(std::make_pair(std::string("Entity-Instance-Identifier"), &H5::PredType::NATIVE_INT32));
|
|
|
|
|
|
|
|
|
|
jt = attributes_derived_in_subtype.begin();
|
2015-11-10 11:16:00 +01:00
|
|
|
for (auto it = attributes.begin(); it != attributes.end(); ++it, ++jt) {
|
|
|
|
|
if (*jt) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2017-09-01 12:50:42 +02:00
|
|
|
|
|
|
|
|
const int idx = std::distance(attributes.begin(), it);
|
|
|
|
|
|
2017-09-24 13:48:16 +02:00
|
|
|
if (padded_ && attributes_all_null[idx]) {
|
2017-09-01 12:50:42 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-24 13:48:16 +02:00
|
|
|
// TFK: Note the scope of max_length_visitor
|
|
|
|
|
max_length_visitor visitor;
|
|
|
|
|
const hsize_t* max_length = nullptr;
|
|
|
|
|
int dims = 0;
|
|
|
|
|
|
|
|
|
|
if (padded_) {
|
|
|
|
|
apply_attribute_visitor_instance_list dispatch(instances, idx);
|
|
|
|
|
dispatch.apply(visitor);
|
|
|
|
|
if (visitor) {
|
|
|
|
|
max_length = visitor.max_length();
|
|
|
|
|
dims = visitor.dims();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-09 13:58:29 +02:00
|
|
|
boost::optional< std::vector<Argument*> > attribute_select_instances;
|
|
|
|
|
|
|
|
|
|
const bool is_select = (*it)->type_of_attribute()->as_named_type() && (*it)->type_of_attribute()->as_named_type()->declared_type()->as_select_type();
|
|
|
|
|
const bool is_select_aggregate = (*it)->type_of_attribute()->as_aggregation_type() &&
|
|
|
|
|
(*it)->type_of_attribute()->as_aggregation_type()->type_of_element()->as_named_type() &&
|
|
|
|
|
(*it)->type_of_attribute()->as_aggregation_type()->type_of_element()->as_named_type()->declared_type()->as_select_type();
|
|
|
|
|
|
|
|
|
|
if (padded_ && (is_select || is_select_aggregate)) {
|
|
|
|
|
attribute_select_instances.emplace();
|
|
|
|
|
std::for_each(instances->begin(), instances->end(), [idx, &attribute_select_instances](IfcUtil::IfcBaseClass* inst) {
|
|
|
|
|
Argument* attribute_value = inst->data().getArgument(idx);
|
|
|
|
|
attribute_select_instances->push_back(attribute_value);
|
2017-09-24 13:48:16 +02:00
|
|
|
});
|
2017-09-01 12:50:42 +02:00
|
|
|
}
|
2017-09-24 13:48:16 +02:00
|
|
|
|
|
|
|
|
const std::string& name = (*it)->name();
|
2017-10-09 13:58:29 +02:00
|
|
|
if (name == "FillStyles") {
|
|
|
|
|
std::cerr << 1;
|
|
|
|
|
}
|
2015-11-10 11:16:00 +01:00
|
|
|
const bool is_optional = (*it)->optional();
|
2015-11-16 10:37:02 +01:00
|
|
|
const H5::DataType* type;
|
2016-02-24 11:26:47 +01:00
|
|
|
const std::string qualified_attr_name = e->name() + "." + name;
|
|
|
|
|
if (std::binary_search(settings_.ref_attributes().begin(), settings_.ref_attributes().end(), qualified_attr_name)) {
|
|
|
|
|
type = new H5::PredType(H5::PredType::STD_REF_OBJ);
|
2017-09-01 12:50:42 +02:00
|
|
|
// } else if (overridden_types.find(qualified_attr_name) != overridden_types.end()) {
|
|
|
|
|
// type = overridden_types.find(qualified_attr_name)->second;
|
|
|
|
|
// } else if (overridden_types.find("*." + name) != overridden_types.end()) {
|
|
|
|
|
// type = overridden_types.find("*." + name)->second;
|
2015-11-16 10:37:02 +01:00
|
|
|
} else {
|
2017-09-24 13:48:16 +02:00
|
|
|
type = (*this)((*it)->type_of_attribute(), attribute_select_instances, dims, max_length);
|
|
|
|
|
if (type == nullptr) {
|
|
|
|
|
// This is for select types. Should this be handled elsewhere?
|
|
|
|
|
type = instance_reference_;
|
|
|
|
|
}
|
2017-09-01 12:50:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: Re-evaluate
|
|
|
|
|
// if (false && visitor && visitor.max_length()[0] == 0) {
|
|
|
|
|
// attributes_omitted.insert(std::make_pair(e->name(), idx));
|
|
|
|
|
// } else {
|
|
|
|
|
h5_attributes.push_back(std::make_pair(name, type));
|
|
|
|
|
// }
|
2015-11-10 11:16:00 +01:00
|
|
|
}
|
|
|
|
|
|
2015-11-30 22:34:48 +01:00
|
|
|
if (settings_.instantiate_inverse()) {
|
|
|
|
|
for (auto it = inverse_attributes.begin(); it != inverse_attributes.end(); ++it) {
|
|
|
|
|
const std::string& name = (*it)->name();
|
2017-09-01 12:50:42 +02:00
|
|
|
// H5::DataType* ir_copy = new H5::DataType();
|
|
|
|
|
// ir_copy->copy(*instance_reference_);
|
|
|
|
|
const H5::DataType* type = new H5::VarLenType(instance_reference_);
|
2015-11-30 22:34:48 +01:00
|
|
|
h5_attributes.push_back(std::make_pair(name, type));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-10 11:16:00 +01:00
|
|
|
return create_compound(h5_attributes);
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-09 13:58:29 +02:00
|
|
|
H5::EnumType* type_mapper::operator()(const IfcParse::enumeration_type* en, const boost::optional< std::vector<Argument*> >&, int, const hsize_t*) {
|
2017-09-01 12:50:42 +02:00
|
|
|
return create_enumeration(en->enumeration_items());
|
|
|
|
|
}
|
2015-11-10 11:16:00 +01:00
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
void type_mapper::operator()() {
|
|
|
|
|
const IfcParse::schema_definition& schema = *ifc_file_.schema();
|
2015-11-10 11:16:00 +01:00
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
for (auto it = schema.enumeration_types().begin(); it != schema.enumeration_types().end(); ++it) {
|
|
|
|
|
declared_types_[(*it)->type()] = commit((*this)(*it), (*it)->name());
|
2015-11-10 11:16:00 +01:00
|
|
|
}
|
|
|
|
|
|
2017-09-24 13:48:16 +02:00
|
|
|
if (!padded_) {
|
|
|
|
|
// For padded ifc-hdf files the width for declared types will depend on the data in the model.
|
|
|
|
|
// Therefore there is no point in having e.g. an IfcLabel type as part of the serialization.
|
|
|
|
|
|
|
|
|
|
const std::vector<const IfcParse::type_declaration*>& ts = schema.type_declarations();
|
|
|
|
|
std::set<const IfcParse::type_declaration*> processed;
|
|
|
|
|
while (processed.size() < ts.size()) {
|
|
|
|
|
for (auto it = ts.begin(); it != ts.end(); ++it) {
|
|
|
|
|
auto pt = (*it)->declared_type();
|
|
|
|
|
const std::string& name = (*it)->name();
|
|
|
|
|
if (processed.find(*it) != processed.end()) continue;
|
|
|
|
|
try {
|
|
|
|
|
declared_types_[(*it)->type()] = commit((*this)(pt), name);
|
|
|
|
|
processed.insert(*it);
|
|
|
|
|
} catch (const UnmetDependencyException&) {}
|
|
|
|
|
}
|
2017-09-01 12:50:42 +02:00
|
|
|
}
|
2015-11-10 11:16:00 +01:00
|
|
|
|
2017-09-24 13:48:16 +02:00
|
|
|
for (auto it = schema.select_types().begin(); it != schema.select_types().end(); ++it) {
|
2017-10-09 13:58:29 +02:00
|
|
|
H5::DataType* dt = (*this)(*it);
|
2017-09-24 13:48:16 +02:00
|
|
|
if (dt) {
|
|
|
|
|
declared_types_[(*it)->type()] = commit(dt, (*it)->name());
|
|
|
|
|
} else {
|
|
|
|
|
declared_types_[(*it)->type()] = instance_reference_;
|
|
|
|
|
}
|
2017-09-01 12:50:42 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto it = schema.entities().begin(); it != schema.entities().end(); ++it) {
|
|
|
|
|
auto dt = (*this)(*it);
|
|
|
|
|
if (dt) {
|
|
|
|
|
declared_types_[(*it)->type()] = commit(dt, (*it)->name());
|
|
|
|
|
}
|
2015-11-16 10:37:02 +01:00
|
|
|
}
|
2017-09-01 12:50:42 +02:00
|
|
|
|
|
|
|
|
H5::StrType schema_name_t;
|
|
|
|
|
schema_name_t.copy(H5::PredType::C_S1);
|
|
|
|
|
schema_name_t.setSize(schema.name().size());
|
|
|
|
|
|
|
|
|
|
hsize_t schema_name_length = 1;
|
|
|
|
|
H5::DataSpace schema_name_s(1, &schema_name_length);
|
|
|
|
|
|
|
|
|
|
H5::Attribute attr = schema_group_.createAttribute("iso_10303_26_data", schema_name_t, schema_name_s);
|
|
|
|
|
attr.write(schema_name_t, schema.name());
|
|
|
|
|
attr.close();
|
2015-11-10 11:16:00 +01:00
|
|
|
}
|
|
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
void visit(void* buffer, H5::DataType* dt) {
|
|
|
|
|
if (dt->getClass() == H5T_COMPOUND) {
|
|
|
|
|
H5::CompType* ct = (H5::CompType*) dt;
|
|
|
|
|
for (int i = 0; i < ct->getNmembers(); ++i) {
|
|
|
|
|
std::cerr << ct->getMemberName(i) << " ";
|
|
|
|
|
size_t offs = ct->getMemberOffset(i);
|
|
|
|
|
H5::DataType dt2 = ct->getMemberDataType(i);
|
|
|
|
|
visit((uint8_t*)buffer + offs, &dt2);
|
|
|
|
|
dt2.close();
|
|
|
|
|
}
|
|
|
|
|
} else if (dt->getClass() == H5T_VLEN) {
|
|
|
|
|
hvl_t* ht = (hvl_t*)buffer;
|
|
|
|
|
H5::VarLenType* vt = (H5::VarLenType*) dt;
|
|
|
|
|
H5::DataType dt2 = vt->getSuper();
|
|
|
|
|
for (size_t i = 0; i < ht->len; ++i) {
|
|
|
|
|
std::cerr << i << " ";
|
|
|
|
|
visit((uint8_t*)ht->p + i * vt->getSize(), &dt2);
|
2015-11-10 11:16:00 +01:00
|
|
|
}
|
2017-09-01 12:50:42 +02:00
|
|
|
dt2.close();
|
|
|
|
|
} else if (dt->getClass() == H5T_STRING) {
|
|
|
|
|
char* c = *(char**)buffer;
|
|
|
|
|
std::cerr << "'" << c << "'" << " ";
|
2015-11-10 11:16:00 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
/*
|
|
|
|
|
const H5::DataType* IfcParse::IfcHdf5File::specify_length(const H5::DataType* dt, const size_t * n) {
|
|
|
|
|
const hsize_t N = *n;
|
|
|
|
|
|
|
|
|
|
H5::DataType* dt3 = 0;
|
|
|
|
|
if (dt->getClass() == H5T_VLEN) {
|
|
|
|
|
H5::VarLenType* vt = (H5::VarLenType*) dt;
|
|
|
|
|
H5::DataType dt2 = vt->getSuper();
|
|
|
|
|
if (dt2.getClass() == H5T_VLEN) {
|
|
|
|
|
throw IfcParse::IfcException("Not supported");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dt2.getClass() == H5T_STRING) {
|
|
|
|
|
dt2.close();
|
|
|
|
|
dt2 = H5::StrType(H5::PredType::C_S1, n[1] + 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dt3 = new H5::ArrayType(dt2, 1, &N);
|
|
|
|
|
|
|
|
|
|
if (dt2.getClass() != H5T_STRING) {
|
|
|
|
|
dt2.close();
|
|
|
|
|
}
|
|
|
|
|
} else if (dt->getClass() == H5T_STRING) {
|
|
|
|
|
// + 1? 0-sized strings not allowed.
|
|
|
|
|
dt3 = new H5::StrType(H5::PredType::C_S1, *n + 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dt3) {
|
|
|
|
|
if (dt->committed()) {
|
|
|
|
|
std::string nm = dt->getObjName() + "_" + boost::lexical_cast<std::string>(*n);
|
|
|
|
|
dt3->commit(schema_group, nm);
|
|
|
|
|
}
|
|
|
|
|
return dt3;
|
2015-11-10 11:16:00 +01:00
|
|
|
} else {
|
2017-09-01 12:50:42 +02:00
|
|
|
return dt;
|
2015-11-10 11:16:00 +01:00
|
|
|
}
|
|
|
|
|
}
|
2017-09-01 12:50:42 +02:00
|
|
|
*/
|
2015-11-10 11:16:00 +01:00
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
size_t get_alignment() {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2015-11-30 22:34:48 +01:00
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
H5::EnumType* map_enumeration(const IfcParse::enumeration_type* en) {
|
|
|
|
|
return create_enumeration(en->enumeration_items());
|
|
|
|
|
}
|
2015-11-10 11:16:00 +01:00
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
H5::DataType* IfcParse::IfcHdf5File::commit(H5::DataType* dt, const std::string& name) {
|
|
|
|
|
dt->commit(schema_group, name);
|
|
|
|
|
return dt;
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-24 13:48:16 +02:00
|
|
|
// std::set< std::pair<std::string, int> > attributes_omitted;
|
|
|
|
|
// std::set< std::string > entities_with_optional_attrs;
|
2017-09-01 12:50:42 +02:00
|
|
|
|
|
|
|
|
/*
|
2015-11-10 11:16:00 +01:00
|
|
|
template <>
|
|
|
|
|
void IfcParse::IfcHdf5File::write(void*& ptr, const std::string& s) const {
|
|
|
|
|
char* c = new(allocator.allocate(s.size()+1)) char [s.size()+1];
|
|
|
|
|
strcpy(c, s.c_str());
|
|
|
|
|
write(ptr, c);
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
void IfcParse::IfcHdf5File::write_string_of_size(void*& ptr, const std::string& s, size_t n) const {
|
|
|
|
|
memset(ptr, 0, n);
|
|
|
|
|
memcpy(ptr, s.c_str(), s.size());
|
|
|
|
|
advance(ptr, n);
|
2015-11-10 11:16:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IfcParse::IfcHdf5File::write_vlen_t(void*& ptr, size_t n_elements, void* vlen_data) const {
|
|
|
|
|
advance(ptr, HOFFSET(hvl_t, len));
|
|
|
|
|
void* temp_ptr;
|
|
|
|
|
write_number_of_size(temp_ptr = ptr, sizeof(size_t), n_elements);
|
|
|
|
|
advance(ptr, HOFFSET(hvl_t, p));
|
|
|
|
|
write(ptr, vlen_data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
void IfcParse::IfcHdf5File::write_aggregate(void*& ptr, const T& ts) const {
|
|
|
|
|
size_t elem_size = get_datatype<typename T::value_type>()->getSize();
|
|
|
|
|
size_t n_elements = ts.size();
|
|
|
|
|
size_t size_in_bytes = elem_size * n_elements;
|
|
|
|
|
void* aggr_data = allocator.allocate(size_in_bytes);
|
|
|
|
|
void* aggr_ptr = aggr_data;
|
|
|
|
|
for (T::const_iterator it = ts.begin(); it != ts.end(); ++it) {
|
|
|
|
|
write_number_of_size(aggr_ptr, elem_size, *it);
|
|
|
|
|
}
|
|
|
|
|
write_vlen_t(ptr, n_elements, aggr_data);
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
template <typename T>
|
|
|
|
|
void IfcParse::IfcHdf5File::write_consecutive(void*& ptr, const std::vector<T>& ts, hsize_t* num, size_t* elem_size) const {
|
|
|
|
|
size_t sz = get_datatype<T>()->getSize();
|
|
|
|
|
hsize_t n = 0;
|
|
|
|
|
for (typename std::vector<T>::const_iterator it = ts.begin(); it != ts.end(); ++it, ++n) {
|
|
|
|
|
write_number_of_size(ptr, sz, *it);
|
|
|
|
|
}
|
|
|
|
|
while (n++ < num[0]) {
|
|
|
|
|
write_number_of_size(ptr, sz, T());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
void IfcParse::IfcHdf5File::write_consecutive(void*& ptr, const std::vector<IfcUtil::IfcBaseClass*>& ts, hsize_t* num, size_t*) const {
|
|
|
|
|
hsize_t n = 0;
|
|
|
|
|
for (std::vector<IfcUtil::IfcBaseClass*>::const_iterator it = ts.begin(); it != ts.end(); ++it, ++n) {
|
|
|
|
|
auto ref = make_instance_reference(*it);
|
|
|
|
|
write_number_of_size(ptr, 2, ref.first);
|
|
|
|
|
write_number_of_size(ptr, 4, ref.second);
|
|
|
|
|
}
|
|
|
|
|
while (n++ < num[0]) {
|
|
|
|
|
write_number_of_size(ptr, 2, 0);
|
|
|
|
|
write_number_of_size(ptr, 4, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
void IfcParse::IfcHdf5File::write_consecutive(void*& ptr, const std::vector<std::string>& ts, hsize_t* num, size_t* elem_size) const {
|
|
|
|
|
hsize_t n = 0;
|
|
|
|
|
for (std::vector<std::string>::const_iterator it = ts.begin(); it != ts.end(); ++it, ++n) {
|
|
|
|
|
write_string_of_size(ptr, *it, elem_size[0]);
|
|
|
|
|
}
|
|
|
|
|
while (n++ < num[0]) {
|
|
|
|
|
write_string_of_size(ptr, "", elem_size[0]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-10 11:16:00 +01:00
|
|
|
template <>
|
|
|
|
|
void IfcParse::IfcHdf5File::write_aggregate(void*& ptr, const std::vector<std::string>& ts) const {
|
|
|
|
|
size_t elem_size = sizeof(char*);
|
|
|
|
|
size_t n_elements = ts.size();
|
|
|
|
|
size_t size_in_bytes = elem_size * n_elements;
|
|
|
|
|
void* aggr_data = allocator.allocate(size_in_bytes);
|
|
|
|
|
void* aggr_ptr = aggr_data;
|
|
|
|
|
for (std::vector<std::string>::const_iterator it = ts.begin(); it != ts.end(); ++it) {
|
|
|
|
|
write(aggr_ptr, *it);
|
|
|
|
|
}
|
|
|
|
|
write_vlen_t(ptr, n_elements, aggr_data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
void IfcParse::IfcHdf5File::write_aggregate(void*& ptr, const IfcEntityList::ptr& ts) const {
|
|
|
|
|
size_t elem_size = instance_reference->getSize();
|
|
|
|
|
size_t n_elements = ts->size();
|
|
|
|
|
size_t size_in_bytes = elem_size * n_elements;
|
|
|
|
|
void* aggr_data = allocator.allocate(size_in_bytes);
|
|
|
|
|
void* aggr_ptr = aggr_data;
|
|
|
|
|
for (IfcEntityList::it it = ts->begin(); it != ts->end(); ++it) {
|
|
|
|
|
auto ref = make_instance_reference(*it);
|
2015-11-30 22:34:48 +01:00
|
|
|
// write_number_of_size(aggr_ptr, instance_reference->getMemberDataType(0).getSize(), ref.first);
|
|
|
|
|
// write_number_of_size(aggr_ptr, instance_reference->getMemberDataType(1).getSize(), ref.second);
|
|
|
|
|
// Hard-coded for efficiency
|
|
|
|
|
write_number_of_size(aggr_ptr, 2, ref.first);
|
|
|
|
|
write_number_of_size(aggr_ptr, 4, ref.second);
|
2015-11-10 11:16:00 +01:00
|
|
|
}
|
|
|
|
|
write_vlen_t(ptr, n_elements, aggr_data);
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-24 11:26:47 +01:00
|
|
|
template <typename T>
|
|
|
|
|
void IfcParse::IfcHdf5File::write_aggregate2(void*& ptr, const std::vector< std::vector<T> >& ts) const {
|
|
|
|
|
size_t elem_size = sizeof(hvl_t);
|
|
|
|
|
size_t n_elements = ts.size();
|
|
|
|
|
size_t size_in_bytes = elem_size * n_elements;
|
|
|
|
|
void* aggr_data = allocator.allocate(size_in_bytes);
|
|
|
|
|
void* aggr_ptr = aggr_data;
|
|
|
|
|
for (std::vector< std::vector<T> >::const_iterator it = ts.begin(); it != ts.end(); ++it) {
|
|
|
|
|
write_aggregate(aggr_ptr, *it);
|
|
|
|
|
}
|
|
|
|
|
write_vlen_t(ptr, n_elements, aggr_data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
void IfcParse::IfcHdf5File::write_reference_attribute(void*& ptr, const std::string& dsn, const std::vector<T>& vs) {
|
|
|
|
|
const std::string dsn_path = "/population/" + dsn;
|
|
|
|
|
const hsize_t s = vs.size();
|
|
|
|
|
const H5::DataType& dt = *get_datatype<T>();
|
|
|
|
|
const size_t size_in_bytes = dt.getSize() * vs.size();
|
|
|
|
|
|
|
|
|
|
H5::DataSpace space(1, &s);
|
|
|
|
|
|
|
|
|
|
void* buffer = allocator.allocate(size_in_bytes);
|
|
|
|
|
void* ds_ptr = buffer;
|
|
|
|
|
for (auto it = vs.begin(); it != vs.end(); ++it) {
|
|
|
|
|
write_number_of_size(ds_ptr, dt.getSize(), *it);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: Refactor
|
|
|
|
|
hsize_t chunk;
|
|
|
|
|
if (settings_.chunk_size() > 0 && settings_.chunk_size() < s) {
|
|
|
|
|
chunk = static_cast<hsize_t>(settings_.chunk_size());
|
|
|
|
|
} else {
|
|
|
|
|
chunk = s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const H5::DSetCreatPropList* plist;
|
|
|
|
|
// H5O_MESG_MAX_SIZE = 65536
|
|
|
|
|
const bool compact = size_in_bytes < (1 << 15);
|
|
|
|
|
if (settings_.compress() && !compact) {
|
|
|
|
|
H5::DSetCreatPropList* plist_ = new H5::DSetCreatPropList;
|
|
|
|
|
plist_->setChunk(1, &chunk);
|
|
|
|
|
// D'oh. Order is significant, according to h5ex_d_shuffle.c
|
|
|
|
|
plist_->setShuffle();
|
|
|
|
|
plist_->setDeflate(9);
|
|
|
|
|
plist = plist_;
|
|
|
|
|
} else if (compact) {
|
|
|
|
|
H5::DSetCreatPropList* plist_ = new H5::DSetCreatPropList;
|
|
|
|
|
// Set compact according to h5ex_d_compact.c
|
|
|
|
|
plist_->setLayout(H5D_COMPACT);
|
|
|
|
|
plist = plist_;
|
|
|
|
|
} else if (chunk != s){
|
|
|
|
|
H5::DSetCreatPropList* plist_ = new H5::DSetCreatPropList;
|
|
|
|
|
plist_->setChunk(1, &chunk);
|
|
|
|
|
plist = plist_;
|
|
|
|
|
} else {
|
|
|
|
|
plist = &H5::DSetCreatPropList::DEFAULT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
H5::DataSet ds = population_group.createDataSet(dsn, dt, space, *plist);
|
|
|
|
|
ds.write(buffer, dt);
|
|
|
|
|
space.close();
|
|
|
|
|
|
|
|
|
|
ds.reference(ptr, dsn_path.c_str());
|
|
|
|
|
advance(ptr, sizeof(hobj_ref_t));
|
|
|
|
|
|
|
|
|
|
if (plist != &H5::DSetCreatPropList::DEFAULT) {
|
|
|
|
|
// ->close() doesn't work due to const, hack hack hack
|
|
|
|
|
H5Pclose(plist->getId());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delete[] buffer;
|
|
|
|
|
ds.close();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
void IfcParse::IfcHdf5File::write_reference_attribute2(void*& ptr, const std::string& dsn, const std::vector< std::vector<T> >& vs) {
|
|
|
|
|
|
|
|
|
|
// See if the attribute is a 'jagged' array in which case a single row of
|
|
|
|
|
// vlens is written. Otherwise a two dimensional dataset is created.
|
|
|
|
|
bool is_rectangular = true;
|
|
|
|
|
size_t w = 0;
|
|
|
|
|
for (auto it = vs.begin(); it != vs.end(); ++it) {
|
|
|
|
|
if (it == vs.begin()) {
|
|
|
|
|
w = it->size();
|
|
|
|
|
} else {
|
|
|
|
|
if (w != it->size()) {
|
|
|
|
|
is_rectangular = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: Please use smart pointers next time
|
|
|
|
|
hsize_t* s;
|
|
|
|
|
hsize_t* chunk;
|
|
|
|
|
const H5::DataType* dt;
|
|
|
|
|
H5::DataType* dt2;
|
|
|
|
|
bool scaled_type = false;
|
|
|
|
|
|
|
|
|
|
if (is_rectangular) {
|
|
|
|
|
s = new hsize_t[2];
|
|
|
|
|
s[0] = vs.size();
|
|
|
|
|
s[1] = w;
|
|
|
|
|
|
|
|
|
|
// Try to find the narrowest integer that can represent values in the dataset
|
|
|
|
|
dt = dt2 = 0;
|
|
|
|
|
if (std::numeric_limits<T>::is_integer) {
|
|
|
|
|
T min_value = std::numeric_limits<T>::max();
|
|
|
|
|
T max_value = std::numeric_limits<T>::min();
|
|
|
|
|
for (auto it = vs.begin(); it != vs.end(); ++it) {
|
|
|
|
|
for (auto jt = it->begin(); jt != it->end(); ++jt) {
|
|
|
|
|
if ((*jt) > max_value) {
|
|
|
|
|
max_value = *jt;
|
|
|
|
|
}
|
|
|
|
|
if ((*jt) < min_value) {
|
|
|
|
|
min_value = *jt;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
scaled_type = true;
|
|
|
|
|
if (min_value >= std::numeric_limits<uint8_t>::min() && max_value <= std::numeric_limits<uint8_t>::max()) {
|
|
|
|
|
dt = dt2 = new H5::PredType(H5::PredType::NATIVE_UINT8);
|
|
|
|
|
} else if (min_value >= std::numeric_limits<int8_t>::min() && max_value <= std::numeric_limits<int8_t>::max()) {
|
|
|
|
|
dt = dt2 = new H5::PredType(H5::PredType::NATIVE_INT8);
|
|
|
|
|
} else if (min_value >= std::numeric_limits<uint16_t>::min() && max_value <= std::numeric_limits<uint16_t>::max()) {
|
|
|
|
|
dt = dt2 = new H5::PredType(H5::PredType::NATIVE_UINT16);
|
|
|
|
|
} else if (min_value >= std::numeric_limits<int16_t>::min() && max_value <= std::numeric_limits<int16_t>::max()) {
|
|
|
|
|
dt = dt2 = new H5::PredType(H5::PredType::NATIVE_INT16);
|
|
|
|
|
} else if (min_value >= std::numeric_limits<uint32_t>::min() && max_value <= std::numeric_limits<uint32_t>::max()) {
|
|
|
|
|
dt = dt2 = new H5::PredType(H5::PredType::NATIVE_UINT32);
|
|
|
|
|
} else if (min_value >= std::numeric_limits<int32_t>::min() && max_value <= std::numeric_limits<int32_t>::max()) {
|
|
|
|
|
dt = dt2 = new H5::PredType(H5::PredType::NATIVE_INT32);
|
|
|
|
|
} else {
|
|
|
|
|
scaled_type = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dt == 0) {
|
|
|
|
|
dt = get_datatype<T>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
s = new hsize_t(vs.size());
|
|
|
|
|
dt = dt2 = new H5::VarLenType(get_datatype<T>());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::string dsn_path = "/population/" + dsn;
|
|
|
|
|
const size_t size_in_bytes = is_rectangular
|
|
|
|
|
? sizeof(T) * vs.size() * w
|
|
|
|
|
: sizeof(hvl_t) * vs.size();
|
|
|
|
|
|
|
|
|
|
// TODO: Refactor
|
|
|
|
|
const bool is_chunked = settings_.chunk_size() > 0 && settings_.chunk_size() < s[0];
|
|
|
|
|
if (is_chunked) {
|
|
|
|
|
if (is_rectangular) {
|
|
|
|
|
chunk = new hsize_t[2];
|
|
|
|
|
chunk[0] = settings_.chunk_size();
|
|
|
|
|
chunk[1] = s[1];
|
|
|
|
|
} else {
|
|
|
|
|
chunk = new hsize_t(vs.size());
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
chunk = s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const H5::DSetCreatPropList* plist;
|
|
|
|
|
// H5O_MESG_MAX_SIZE = 65536
|
|
|
|
|
const bool compact = size_in_bytes < (1 << 15);
|
|
|
|
|
if (settings_.compress() && !compact) {
|
|
|
|
|
H5::DSetCreatPropList* plist_ = new H5::DSetCreatPropList;
|
|
|
|
|
plist_->setChunk(is_rectangular ? 2 : 1, chunk);
|
|
|
|
|
// D'oh. Order is significant, according to h5ex_d_shuffle.c
|
|
|
|
|
plist_->setShuffle();
|
|
|
|
|
plist_->setDeflate(9);
|
|
|
|
|
plist = plist_;
|
|
|
|
|
} else if (compact) {
|
|
|
|
|
H5::DSetCreatPropList* plist_ = new H5::DSetCreatPropList;
|
|
|
|
|
// Set compact according to h5ex_d_compact.c
|
|
|
|
|
plist_->setLayout(H5D_COMPACT);
|
|
|
|
|
plist = plist_;
|
|
|
|
|
} else if (chunk != s){
|
|
|
|
|
H5::DSetCreatPropList* plist_ = new H5::DSetCreatPropList;
|
|
|
|
|
plist_->setChunk(is_rectangular ? 2 : 1, chunk);
|
|
|
|
|
plist = plist_;
|
|
|
|
|
} else {
|
|
|
|
|
plist = &H5::DSetCreatPropList::DEFAULT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
H5::DataSpace space(is_rectangular ? 2 : 1, s);
|
|
|
|
|
H5::DataSet ds = population_group.createDataSet(dsn, *dt, space, *plist);
|
|
|
|
|
|
|
|
|
|
void* buffer = allocator.allocate(size_in_bytes);
|
|
|
|
|
void* ds_ptr = buffer;
|
|
|
|
|
for (auto it = vs.begin(); it != vs.end(); ++it) {
|
|
|
|
|
if (is_rectangular) {
|
|
|
|
|
for (auto jt = it->begin(); jt != it->end(); ++jt) {
|
|
|
|
|
write_number_of_size(ds_ptr, dt->getSize(), *jt);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
write_aggregate(ds_ptr, *it);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ds.write(buffer, *dt);
|
|
|
|
|
space.close();
|
|
|
|
|
|
|
|
|
|
ds.reference(ptr, dsn_path.c_str());
|
|
|
|
|
advance(ptr, sizeof(hobj_ref_t));
|
|
|
|
|
|
|
|
|
|
delete[] buffer;
|
|
|
|
|
ds.close();
|
|
|
|
|
|
|
|
|
|
if (plist != &H5::DSetCreatPropList::DEFAULT) {
|
|
|
|
|
// ->close() doesn't work due to const, hack hack hack
|
|
|
|
|
H5Pclose(plist->getId());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (is_rectangular) {
|
|
|
|
|
delete[] s;
|
|
|
|
|
if (is_chunked) {
|
|
|
|
|
delete[] chunk;
|
|
|
|
|
}
|
|
|
|
|
if (scaled_type) {
|
|
|
|
|
dt2->close();
|
|
|
|
|
delete dt;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
dt2->close();
|
|
|
|
|
delete dt;
|
|
|
|
|
delete s;
|
|
|
|
|
if (is_chunked) {
|
|
|
|
|
delete chunk;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-09-01 12:50:42 +02:00
|
|
|
*/
|
2016-02-24 11:26:47 +01:00
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
void IfcParse::IfcHdf5File::write_schema(const IfcParse::schema_definition& schema, IfcParse::IfcFile& ifc_file) {
|
2015-11-10 11:16:00 +01:00
|
|
|
|
|
|
|
|
// From h5ex_g_compact.c
|
|
|
|
|
// Compact groups?
|
|
|
|
|
H5::FileAccPropList* plist = new H5::FileAccPropList();
|
|
|
|
|
plist->setLibverBounds(H5F_LIBVER_LATEST, H5F_LIBVER_LATEST);
|
|
|
|
|
|
|
|
|
|
// H5::FileCreatPropList* plist2 = new H5::FileCreatPropList();
|
|
|
|
|
// H5Pset_file_space(plist2->getId(), H5F_FILE_SPACE_VFD, (hsize_t)0);
|
|
|
|
|
|
|
|
|
|
file = new H5::H5File(name_, H5F_ACC_TRUNC, H5::FileCreatPropList::DEFAULT, *plist);
|
|
|
|
|
|
|
|
|
|
schema_group = file->createGroup(schema.name() + "_encoding");
|
|
|
|
|
population_group = file->createGroup("population");
|
|
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
// init_default_types();
|
2016-01-08 06:35:53 +01:00
|
|
|
|
2017-09-24 13:48:16 +02:00
|
|
|
mapper_ = new type_mapper(ifc_file, file, settings_);
|
2017-09-01 12:50:42 +02:00
|
|
|
(*(type_mapper*)mapper_)();
|
2015-11-10 11:16:00 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
std::pair<size_t, size_t> IfcParse::IfcHdf5File::make_instance_reference(const IfcUtil::IfcBaseClass* instance) const {
|
2016-01-08 06:35:53 +01:00
|
|
|
#ifdef SORT_ON_NAME
|
|
|
|
|
const std::vector<uint32_t>& es = sorted_entities.find(instance->declaration().type())->second;
|
|
|
|
|
#else
|
2015-11-10 11:16:00 +01:00
|
|
|
const std::vector<IfcUtil::IfcBaseClass*>& es = sorted_entities.find(instance->declaration().type())->second;
|
2016-01-08 06:35:53 +01:00
|
|
|
#endif
|
2015-11-10 11:16:00 +01:00
|
|
|
|
|
|
|
|
auto dataset_id = std::lower_bound(dataset_names.begin(), dataset_names.end(), instance->declaration().type());
|
2016-01-08 06:35:53 +01:00
|
|
|
#ifdef SORT_ON_NAME
|
|
|
|
|
auto instance_id = std::lower_bound(es.begin(), es.end(), instance->data().id());
|
|
|
|
|
#else
|
|
|
|
|
auto instance_id = std::lower_bound(es.begin(), es.end(), instance);
|
|
|
|
|
#endif
|
2015-11-10 11:16:00 +01:00
|
|
|
|
|
|
|
|
size_t dataset_offset = std::distance(dataset_names.begin(), dataset_id);
|
|
|
|
|
size_t instance_offset = std::distance(es.begin(), instance_id);
|
|
|
|
|
|
|
|
|
|
return std::make_pair(dataset_offset, instance_offset);
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
/*
|
2015-11-10 11:16:00 +01:00
|
|
|
void IfcParse::IfcHdf5File::write_select(void*& ptr, IfcUtil::IfcBaseClass* instance, const H5::CompType* datatype) const {
|
|
|
|
|
int member_index = -1;
|
|
|
|
|
|
|
|
|
|
if (instance->declaration().as_entity()) {
|
|
|
|
|
member_index = datatype->getMemberIndex("instance-value");
|
|
|
|
|
size_t offset = datatype->getMemberOffset(member_index);
|
|
|
|
|
auto ref = make_instance_reference(instance);
|
|
|
|
|
void* ptr_member = (uint8_t*) ptr + offset;
|
2015-11-30 22:34:48 +01:00
|
|
|
// write_number_of_size(ptr_member, instance_reference->getMemberDataType(0).getSize(), ref.first);
|
|
|
|
|
// write_number_of_size(ptr_member, instance_reference->getMemberDataType(1).getSize(), ref.second);
|
|
|
|
|
write_number_of_size(ptr_member, 2, ref.first);
|
|
|
|
|
write_number_of_size(ptr_member, 4, ref.second);
|
2015-11-10 11:16:00 +01:00
|
|
|
} else {
|
|
|
|
|
Argument& wrapped_data = *instance->data().getArgument(0);
|
|
|
|
|
IfcUtil::ArgumentType ty = wrapped_data.type();
|
|
|
|
|
if (default_cpp_type_names.find(ty) == default_cpp_type_names.end()) {
|
|
|
|
|
Logger::Message(Logger::LOG_ERROR, "Unsupported select valuation encountered", instance);
|
|
|
|
|
} else {
|
|
|
|
|
std::string member_name = default_cpp_type_names.find(ty)->second + "-value";
|
|
|
|
|
member_index = datatype->getMemberIndex(member_name);
|
|
|
|
|
size_t offset = datatype->getMemberOffset(member_index);
|
2015-11-30 22:34:48 +01:00
|
|
|
H5::DataType memberdt = datatype->getMemberDataType(member_index);
|
|
|
|
|
size_t member_size = memberdt.getSize();
|
|
|
|
|
memberdt.close();
|
2015-11-10 11:16:00 +01:00
|
|
|
void* ptr_member = (uint8_t*) ptr + offset;
|
|
|
|
|
switch(wrapped_data.type()) {
|
|
|
|
|
case IfcUtil::Argument_BOOL: {
|
2017-09-01 12:50:42 +02:00
|
|
|
bool v = wrapped_data;
|
|
|
|
|
write_number_of_size(ptr_member, member_size, static_cast<uint8_t>(v ? 1 : 0));
|
2015-11-10 11:16:00 +01:00
|
|
|
break; }
|
|
|
|
|
case IfcUtil::Argument_DOUBLE: {
|
|
|
|
|
double d = wrapped_data;
|
|
|
|
|
write_number_of_size(ptr_member, member_size, d);
|
|
|
|
|
break; }
|
|
|
|
|
case IfcUtil::Argument_STRING: {
|
|
|
|
|
std::string s = wrapped_data;
|
|
|
|
|
write(ptr_member, s);
|
|
|
|
|
break; }
|
|
|
|
|
case IfcUtil::Argument_INT: {
|
|
|
|
|
int i = wrapped_data;
|
|
|
|
|
write_number_of_size(ptr_member, member_size, i);
|
|
|
|
|
break; }
|
|
|
|
|
default:
|
|
|
|
|
Logger::Message(Logger::LOG_ERROR, "Unsupported select valuation encountered", instance);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (member_index == -1) {
|
|
|
|
|
member_index = 0;
|
|
|
|
|
} else {
|
|
|
|
|
member_index -= 2; // select_bitmap, type_path
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void* temp_ptr = ptr;
|
|
|
|
|
write_number_of_size(temp_ptr, H5::PredType::NATIVE_INT8.getSize(), member_index);
|
|
|
|
|
write(temp_ptr, instance->declaration().name());
|
|
|
|
|
|
|
|
|
|
// TODO: Should string be set to "", or keep as null?
|
|
|
|
|
// std::cout << datatype->getMemberIndex("string-value") << std::endl;
|
|
|
|
|
|
|
|
|
|
advance(ptr, datatype->getSize());
|
|
|
|
|
}
|
2017-09-01 12:50:42 +02:00
|
|
|
*/
|
2015-11-10 11:16:00 +01:00
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
H5::DataSet IfcParse::IfcHdf5File::create_dataset(const std::string& path, H5::DataType datatype, int rank, hsize_t* dimensions) {
|
|
|
|
|
if (rank != 1) {
|
|
|
|
|
throw std::runtime_error("Expected rank 1");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const size_t datatype_size = datatype.getSize();
|
|
|
|
|
|
|
|
|
|
hsize_t chunk;
|
|
|
|
|
if (settings_.chunk_size() > 0 && settings_.chunk_size() < dimensions[0]) {
|
|
|
|
|
chunk = static_cast<hsize_t>(settings_.chunk_size());
|
|
|
|
|
} else {
|
|
|
|
|
chunk = dimensions[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const H5::DSetCreatPropList* plist;
|
|
|
|
|
// H5O_MESG_MAX_SIZE = 65536
|
|
|
|
|
const bool compact = dimensions[0] * datatype_size < (1 << 15);
|
|
|
|
|
if (settings_.compress() && !compact) {
|
|
|
|
|
H5::DSetCreatPropList* plist_ = new H5::DSetCreatPropList;
|
|
|
|
|
plist_->setChunk(1, &chunk);
|
|
|
|
|
// D'oh. Order is significant, according to h5ex_d_shuffle.c
|
|
|
|
|
plist_->setShuffle();
|
|
|
|
|
plist_->setDeflate(9);
|
|
|
|
|
plist = plist_;
|
|
|
|
|
} else if (compact) {
|
|
|
|
|
H5::DSetCreatPropList* plist_ = new H5::DSetCreatPropList;
|
|
|
|
|
// Set compact according to h5ex_d_compact.c
|
|
|
|
|
plist_->setLayout(H5D_COMPACT);
|
|
|
|
|
plist = plist_;
|
|
|
|
|
} else if (chunk != dimensions[0]) {
|
|
|
|
|
H5::DSetCreatPropList* plist_ = new H5::DSetCreatPropList;
|
|
|
|
|
plist_->setChunk(1, &chunk);
|
|
|
|
|
plist = plist_;
|
|
|
|
|
} else {
|
|
|
|
|
plist = &H5::DSetCreatPropList::DEFAULT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
H5::DataSpace space(1, dimensions);
|
|
|
|
|
H5::DataSet ds = population_group.createDataSet(path, datatype, space, *plist);
|
|
|
|
|
|
|
|
|
|
if (plist != &H5::DSetCreatPropList::DEFAULT) {
|
|
|
|
|
// ->close() doesn't work due to const, hack hack hack
|
|
|
|
|
H5Pclose(plist->getId());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ds;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-09 13:58:29 +02:00
|
|
|
void IfcParse::IfcHdf5File::write_population(IfcFile&) {
|
|
|
|
|
const bool padded = settings_.profile() == IfcParse::Hdf5Settings::padded || settings_.profile() == IfcParse::Hdf5Settings::padded_referenced;
|
|
|
|
|
const bool referenced = settings_.profile() == IfcParse::Hdf5Settings::standard_referenced || settings_.profile() == IfcParse::Hdf5Settings::padded_referenced;
|
|
|
|
|
|
|
|
|
|
sorted_instance_locator locator(*file, this->ifcfile_, referenced);
|
2017-09-01 12:50:42 +02:00
|
|
|
|
2017-10-09 13:58:29 +02:00
|
|
|
dataset_names.assign(locator.begin(), locator.end());
|
2017-09-01 12:50:42 +02:00
|
|
|
|
|
|
|
|
{
|
|
|
|
|
hsize_t dataset_names_length = dataset_names.size();
|
|
|
|
|
H5::DataSpace dataset_names_s(1, &dataset_names_length);
|
|
|
|
|
|
2017-10-09 14:57:14 +02:00
|
|
|
H5::StrType varlen_string_type(H5::PredType::C_S1, H5T_VARIABLE);
|
|
|
|
|
H5::Attribute attr = schema_group.createAttribute("iso_10303_26_data_set_names", varlen_string_type, dataset_names_s);
|
2017-09-01 12:50:42 +02:00
|
|
|
char** attr_data = (char**)allocator.allocate(static_cast<size_t>(sizeof(char*) * dataset_names_length));
|
|
|
|
|
size_t i = 0;
|
|
|
|
|
for (auto it = dataset_names.begin(); it != dataset_names.end(); ++it, ++i) {
|
|
|
|
|
std::string nm = IfcSchema::Type::ToString(*it);
|
|
|
|
|
attr_data[i] = (char*)allocator.allocate(nm.size() + 1);
|
|
|
|
|
strcpy(attr_data[i], nm.c_str());
|
|
|
|
|
}
|
2017-10-09 14:57:14 +02:00
|
|
|
attr.write(varlen_string_type, attr_data);
|
2017-09-01 12:50:42 +02:00
|
|
|
attr.close();
|
2017-10-09 14:57:14 +02:00
|
|
|
varlen_string_type.close();
|
2017-09-01 12:50:42 +02:00
|
|
|
}
|
|
|
|
|
|
2017-10-09 13:58:29 +02:00
|
|
|
write_visit/*<sorted_instance_locator>*/ visitor(*this->file, padded, referenced, locator, *((type_mapper*)mapper_));
|
2017-09-01 12:50:42 +02:00
|
|
|
|
2017-10-09 13:58:29 +02:00
|
|
|
if (referenced) {
|
|
|
|
|
for (auto dsn_it = dataset_names.begin(); dsn_it != dataset_names.end(); ++dsn_it) {
|
|
|
|
|
const std::string current_entity_name = IfcSchema::Type::ToString(*dsn_it);
|
|
|
|
|
const std::string dataset_path = current_entity_name + "_instances";
|
|
|
|
|
|
|
|
|
|
hsize_t num_instances = locator.instances(*dsn_it).size();
|
|
|
|
|
H5::DataType entity_datatype = schema_group.openDataType(current_entity_name);
|
|
|
|
|
|
|
|
|
|
create_dataset(dataset_path, entity_datatype, 1, &num_instances).close();
|
|
|
|
|
entity_datatype.close();
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-09-01 12:50:42 +02:00
|
|
|
|
|
|
|
|
for (auto dsn_it = dataset_names.begin(); dsn_it != dataset_names.end(); ++dsn_it) {
|
|
|
|
|
|
|
|
|
|
const std::string current_entity_name = IfcSchema::Type::ToString(*dsn_it);
|
2017-10-09 13:58:29 +02:00
|
|
|
const std::string dataset_path = current_entity_name + "_instances";
|
|
|
|
|
const std::vector<IfcUtil::IfcBaseEntity*>& instances = locator.instances(*dsn_it);
|
|
|
|
|
hsize_t num_instances = instances.size();
|
|
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
std::cerr << current_entity_name << std::endl;
|
|
|
|
|
|
|
|
|
|
H5::DataType entity_datatype = schema_group.openDataType(current_entity_name);
|
2017-10-09 13:58:29 +02:00
|
|
|
H5::DataSet dataset;
|
2017-09-01 12:50:42 +02:00
|
|
|
|
2017-10-09 13:58:29 +02:00
|
|
|
if (referenced) {
|
|
|
|
|
dataset = population_group.openDataSet(dataset_path);
|
|
|
|
|
} else {
|
|
|
|
|
dataset = create_dataset(dataset_path, entity_datatype, 1, &num_instances);
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
size_t dataset_size = entity_datatype.getSize() * static_cast<size_t>(num_instances);
|
|
|
|
|
void* data = allocator.allocate(dataset_size);
|
|
|
|
|
void* ptr = data;
|
|
|
|
|
std::cerr << dataset_size << std::endl;
|
|
|
|
|
|
|
|
|
|
for (auto inst_it = instances.begin(); inst_it != instances.end(); ++inst_it) {
|
|
|
|
|
write_instance(ptr, visitor, entity_datatype, (IfcUtil::IfcBaseEntity*)*inst_it);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dataset.write(data, entity_datatype);
|
|
|
|
|
H5::DataSpace space(1, &num_instances);
|
|
|
|
|
H5Dvlen_reclaim(entity_datatype.getId(), space.getId(), H5P_DEFAULT, data);
|
|
|
|
|
|
|
|
|
|
dataset.close();
|
|
|
|
|
space.close();
|
|
|
|
|
|
|
|
|
|
// allocator.free();
|
|
|
|
|
delete[] data;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2015-11-30 22:34:48 +01:00
|
|
|
void IfcParse::IfcHdf5File::write_population(IfcFile& f) {
|
2015-11-10 11:16:00 +01:00
|
|
|
std::set<IfcSchema::Type::Enum> tys;
|
2015-11-16 10:37:02 +01:00
|
|
|
|
2015-11-30 22:34:48 +01:00
|
|
|
// Wth was this?
|
|
|
|
|
// this->file->close();
|
2015-11-10 11:16:00 +01:00
|
|
|
|
2015-11-30 22:34:48 +01:00
|
|
|
std::set<IfcSchema::Type::Enum> types_with_instiated_selected;
|
|
|
|
|
|
2015-11-10 11:16:00 +01:00
|
|
|
for (auto it = f.begin(); it != f.end(); ++it) {
|
|
|
|
|
IfcSchema::Type::Enum ty = it->second->declaration().type();
|
|
|
|
|
tys.insert(ty);
|
|
|
|
|
// This already is sorted on entity instance name
|
2016-01-08 06:35:53 +01:00
|
|
|
#ifdef SORT_ON_NAME
|
|
|
|
|
sorted_entities[ty].push_back(static_cast<uint32_t>(it->first));
|
|
|
|
|
#else
|
2015-11-10 11:16:00 +01:00
|
|
|
sorted_entities[ty].push_back(it->second);
|
2016-01-08 06:35:53 +01:00
|
|
|
#endif
|
2015-11-30 22:34:48 +01:00
|
|
|
|
2016-01-08 06:35:53 +01:00
|
|
|
#ifndef SORT_ON_NAME
|
2015-11-30 22:34:48 +01:00
|
|
|
if (settings_.instantiate_select()) {
|
|
|
|
|
bool has=false;
|
|
|
|
|
for (unsigned i = 0; i < it->second->data().getArgumentCount(); ++i) {
|
|
|
|
|
Argument* attr = it->second->data().getArgument(i);
|
|
|
|
|
if (attr->type() == IfcUtil::Argument_ENTITY_INSTANCE) {
|
|
|
|
|
IfcUtil::IfcBaseClass* inst = *attr;
|
|
|
|
|
if (!inst->declaration().as_entity()) {
|
|
|
|
|
IfcSchema::Type::Enum ty2 = inst->declaration().type();
|
|
|
|
|
tys.insert(ty2);
|
|
|
|
|
sorted_entities[ty2].push_back(inst);
|
|
|
|
|
has = true;
|
|
|
|
|
}
|
|
|
|
|
} else if (attr->type() == IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE) {
|
|
|
|
|
IfcEntityList::ptr insts = *attr;
|
|
|
|
|
for (auto it = insts->begin(); it != insts->end(); ++it) {
|
|
|
|
|
if (!(*it)->declaration().as_entity()) {
|
|
|
|
|
IfcSchema::Type::Enum ty2 = (*it)->declaration().type();
|
|
|
|
|
tys.insert(ty2);
|
|
|
|
|
sorted_entities[ty2].push_back(*it);
|
|
|
|
|
has = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (has) {
|
|
|
|
|
types_with_instiated_selected.insert(ty);
|
|
|
|
|
} else {
|
|
|
|
|
static_cast<IfcParse::Entity*>(&it->second->data())->Unload();
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-01-08 06:35:53 +01:00
|
|
|
#endif
|
2015-11-10 11:16:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dataset_names.assign(tys.begin(), tys.end());
|
|
|
|
|
std::sort(dataset_names.begin(), dataset_names.end());
|
2017-09-01 12:50:42 +02:00
|
|
|
|
|
|
|
|
// dataset_names.push_back(IfcSchema::Type::IfcPostalAddress);
|
2016-01-08 06:35:53 +01:00
|
|
|
|
|
|
|
|
{
|
|
|
|
|
hsize_t dataset_names_length = dataset_names.size();
|
|
|
|
|
H5::DataSpace dataset_names_s(1, &dataset_names_length);
|
|
|
|
|
|
|
|
|
|
H5::Attribute attr = schema_group.createAttribute("iso_10303_26_data_set_names", *default_types[simple_type::string_type], dataset_names_s);
|
2017-09-01 12:50:42 +02:00
|
|
|
char** attr_data = (char**) allocator.allocate(static_cast<size_t>(sizeof(char*) * dataset_names_length));
|
2016-01-08 06:35:53 +01:00
|
|
|
size_t i = 0;
|
|
|
|
|
for (auto it = dataset_names.begin(); it != dataset_names.end(); ++it, ++i) {
|
|
|
|
|
std::string nm = IfcSchema::Type::ToString(*it);
|
|
|
|
|
attr_data[i] = (char*) allocator.allocate(nm.size() + 1);
|
|
|
|
|
strcpy(attr_data[i], nm.c_str());
|
|
|
|
|
}
|
|
|
|
|
attr.write(*default_types[simple_type::string_type], attr_data);
|
|
|
|
|
attr.close();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef SORT_ON_NAME
|
|
|
|
|
for (auto it = sorted_entities.begin(); it != sorted_entities.end(); ++it) {
|
|
|
|
|
std::sort(it->second.begin(), it->second.end());
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2015-11-10 11:16:00 +01:00
|
|
|
|
|
|
|
|
for (auto it = dataset_names.begin(); it != dataset_names.end(); ++it) {
|
2015-11-16 10:37:02 +01:00
|
|
|
|
2015-11-30 22:34:48 +01:00
|
|
|
// std::cout << "begin inner loop" << std::endl;
|
|
|
|
|
// std::cin.get();
|
|
|
|
|
|
|
|
|
|
// if (*it != IfcSchema::Type::IfcUnitAssignment) continue;
|
|
|
|
|
|
2016-02-24 11:26:47 +01:00
|
|
|
const std::string current_entity_name = IfcSchema::Type::ToString(*it);
|
|
|
|
|
std::cerr << current_entity_name << std::endl;
|
2015-11-30 22:34:48 +01:00
|
|
|
|
2016-01-08 06:35:53 +01:00
|
|
|
#ifdef SORT_ON_NAME
|
|
|
|
|
std::vector<IfcUtil::IfcBaseClass*> es;
|
|
|
|
|
es.reserve(sorted_entities.find(*it)->second.size());
|
|
|
|
|
for (auto jt = sorted_entities.find(*it)->second.begin(); jt != sorted_entities.find(*it)->second.end(); ++jt) {
|
|
|
|
|
es.push_back(f.entityById(*jt));
|
|
|
|
|
}
|
|
|
|
|
#else
|
2015-11-10 11:16:00 +01:00
|
|
|
const std::vector<IfcUtil::IfcBaseClass*>& es = sorted_entities.find(*it)->second;
|
2016-01-08 06:35:53 +01:00
|
|
|
#endif
|
2015-11-30 22:34:48 +01:00
|
|
|
size_t datatype_size = declared_types[*it]->getSize();
|
2015-11-10 11:16:00 +01:00
|
|
|
hsize_t dims = es.size();
|
2016-01-08 06:35:53 +01:00
|
|
|
|
|
|
|
|
hsize_t chunk;
|
|
|
|
|
if (settings_.chunk_size() > 0 && settings_.chunk_size() < dims) {
|
|
|
|
|
chunk = static_cast<hsize_t>(settings_.chunk_size());
|
|
|
|
|
} else {
|
|
|
|
|
chunk = dims;
|
|
|
|
|
}
|
2015-11-10 11:16:00 +01:00
|
|
|
|
|
|
|
|
const H5::DSetCreatPropList* plist;
|
|
|
|
|
// H5O_MESG_MAX_SIZE = 65536
|
2015-11-30 22:34:48 +01:00
|
|
|
const bool compact = es.size() * datatype_size < (1 << 15);
|
|
|
|
|
if (settings_.compress() && !compact) {
|
2015-11-10 11:16:00 +01:00
|
|
|
H5::DSetCreatPropList* plist_ = new H5::DSetCreatPropList;
|
|
|
|
|
plist_->setChunk(1, &chunk);
|
|
|
|
|
// D'oh. Order is significant, according to h5ex_d_shuffle.c
|
|
|
|
|
plist_->setShuffle();
|
|
|
|
|
plist_->setDeflate(9);
|
|
|
|
|
plist = plist_;
|
|
|
|
|
} else if (compact) {
|
|
|
|
|
H5::DSetCreatPropList* plist_ = new H5::DSetCreatPropList;
|
|
|
|
|
// Set compact according to h5ex_d_compact.c
|
|
|
|
|
plist_->setLayout(H5D_COMPACT);
|
|
|
|
|
plist = plist_;
|
2016-01-08 06:35:53 +01:00
|
|
|
} else if (chunk != dims){
|
|
|
|
|
H5::DSetCreatPropList* plist_ = new H5::DSetCreatPropList;
|
|
|
|
|
plist_->setChunk(1, &chunk);
|
|
|
|
|
plist = plist_;
|
2015-11-10 11:16:00 +01:00
|
|
|
} else {
|
|
|
|
|
plist = &H5::DSetCreatPropList::DEFAULT;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-30 22:34:48 +01:00
|
|
|
H5::DataSpace space(1, &dims);
|
|
|
|
|
H5::DataSet ds = population_group.createDataSet(IfcSchema::Type::ToString(*it) + "_instances", *declared_types[*it], space, *plist);
|
2015-11-10 11:16:00 +01:00
|
|
|
|
2015-11-30 22:34:48 +01:00
|
|
|
size_t dataset_size = declared_types[*it]->getSize() * static_cast<size_t>(dims);
|
|
|
|
|
void* data = allocator.allocate(dataset_size);
|
|
|
|
|
|
|
|
|
|
std::cerr << dataset_size << std::endl;
|
2015-11-10 11:16:00 +01:00
|
|
|
|
|
|
|
|
void* ptr = data;
|
|
|
|
|
const H5::CompType* dt = (H5::CompType*) declared_types[*it];
|
|
|
|
|
int ind = 0;
|
|
|
|
|
|
|
|
|
|
for (auto jt = es.begin(); jt != es.end(); ++jt, ++ind) {
|
2015-11-30 22:34:48 +01:00
|
|
|
void* start = ptr;
|
|
|
|
|
|
2015-11-10 11:16:00 +01:00
|
|
|
int member_idx = 0;
|
|
|
|
|
|
|
|
|
|
H5::DataType member_type;
|
|
|
|
|
|
|
|
|
|
IfcAbstractEntity& dat = (*jt)->data();
|
|
|
|
|
const declaration& decl = (*jt)->declaration();
|
2015-11-30 22:34:48 +01:00
|
|
|
|
|
|
|
|
if (!decl.as_entity()) {
|
|
|
|
|
if (!settings_.instantiate_select()) throw;
|
|
|
|
|
// This is a type
|
2017-09-01 12:50:42 +02:00
|
|
|
// auto q = dt->getClass();
|
|
|
|
|
auto size = dt->getSize();
|
2015-11-30 22:34:48 +01:00
|
|
|
const Argument& attr_value = *dat.getArgument(0);
|
|
|
|
|
if (*dt == *default_types[simple_type::real_type]) {
|
|
|
|
|
double d = attr_value;
|
2017-09-01 12:50:42 +02:00
|
|
|
write_number_of_size(ptr, size, d);
|
2015-11-30 22:34:48 +01:00
|
|
|
} else if (*dt == *default_types[simple_type::string_type]) {
|
|
|
|
|
std::string s = attr_value;
|
|
|
|
|
write(ptr, s);
|
|
|
|
|
} else if (*dt == *default_types[simple_type::integer_type]) {
|
|
|
|
|
int i = attr_value;
|
2017-09-01 12:50:42 +02:00
|
|
|
write_number_of_size(ptr, size, i);
|
2015-11-30 22:34:48 +01:00
|
|
|
} else if (*dt == *default_types[simple_type::boolean_type] ||
|
|
|
|
|
*dt == *default_types[simple_type::logical_type])
|
|
|
|
|
{
|
|
|
|
|
bool b = attr_value;
|
2017-09-01 12:50:42 +02:00
|
|
|
write_number_of_size(ptr, size, static_cast<uint8_t>(b ? 1 : 0));
|
2015-11-30 22:34:48 +01:00
|
|
|
} else {
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-10 11:16:00 +01:00
|
|
|
std::vector<const IfcParse::entity::attribute*> attributes = decl.as_entity()->all_attributes();
|
2015-11-30 22:34:48 +01:00
|
|
|
std::vector<const IfcParse::entity::inverse_attribute*> inverse_attributes;
|
|
|
|
|
if (settings_.instantiate_inverse()) {
|
|
|
|
|
inverse_attributes = decl.as_entity()->all_inverse_attributes();
|
|
|
|
|
}
|
2015-11-10 11:16:00 +01:00
|
|
|
const std::vector<bool>& attributes_derived_in_subtype = decl.as_entity()->derived();
|
|
|
|
|
std::vector<bool>::const_iterator is_derived = attributes_derived_in_subtype.begin();
|
|
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
//for (auto qt = attributes_derived_in_subtype.begin(); qt != attributes_derived_in_subtype.end(); ++qt) {
|
|
|
|
|
// std::cout << int(*qt);
|
|
|
|
|
//}
|
|
|
|
|
//std::cout << std::endl;
|
|
|
|
|
|
|
|
|
|
const bool has_optional = entities_with_optional_attrs.find(current_entity_name) != entities_with_optional_attrs.end();
|
|
|
|
|
|
|
|
|
|
uint32_t set_unset_mask;
|
|
|
|
|
size_t set_unset_size;
|
|
|
|
|
void* set_unset_ptr;
|
|
|
|
|
|
|
|
|
|
if (has_optional) {
|
|
|
|
|
member_type = dt->getMemberDataType(member_idx++);
|
|
|
|
|
set_unset_mask = 0;
|
|
|
|
|
set_unset_ptr = ptr;
|
|
|
|
|
set_unset_size = member_type.getSize();
|
|
|
|
|
// skip for now write later
|
|
|
|
|
advance(ptr, set_unset_size);
|
|
|
|
|
member_type.close();
|
|
|
|
|
}
|
2015-11-30 22:34:48 +01:00
|
|
|
|
2015-11-10 11:16:00 +01:00
|
|
|
member_type = dt->getMemberDataType(member_idx++);
|
2016-01-08 06:35:53 +01:00
|
|
|
const unsigned int inst_name = static_cast<unsigned int>(dat.id());
|
|
|
|
|
write_number_of_size(ptr, member_type.getSize(), inst_name);
|
2015-11-30 22:34:48 +01:00
|
|
|
member_type.close();
|
|
|
|
|
|
|
|
|
|
// ----v----- In some IFC files there are extra superfluous attributes in the instantiation. For example FJK haus.
|
|
|
|
|
const size_t attr_count = (std::min)(attributes.size(), (size_t) dat.getArgumentCount());
|
|
|
|
|
for (unsigned i = 0; i < attr_count; ++i, ++is_derived) {
|
2017-09-01 12:50:42 +02:00
|
|
|
|
|
|
|
|
//std::cout << i << std::endl;
|
|
|
|
|
|
2015-11-10 11:16:00 +01:00
|
|
|
if (*is_derived) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
if (attributes_omitted.find(std::make_pair(current_entity_name, i)) != attributes_omitted.end()) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-10 11:16:00 +01:00
|
|
|
const IfcParse::entity::attribute* schema_attr = attributes[i];
|
2015-11-16 10:37:02 +01:00
|
|
|
const std::string& attribute_name = schema_attr->name();
|
2017-09-01 12:50:42 +02:00
|
|
|
//std::cout << "ifc " << attribute_name << std::endl;
|
2015-11-10 11:16:00 +01:00
|
|
|
Argument& attr_value = *dat.getArgument(i);
|
2015-11-30 22:34:48 +01:00
|
|
|
|
2015-11-10 11:16:00 +01:00
|
|
|
member_type = dt->getMemberDataType(member_idx++);
|
|
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
//std::cout << "hdf5 " << dt->getMemberName(member_idx - 1) << ": " << member_type.getClass() << std::endl;
|
|
|
|
|
|
2015-11-10 11:16:00 +01:00
|
|
|
if (attr_value.isNull()) {
|
|
|
|
|
if (member_type == *default_types[simple_type::string_type]) {
|
|
|
|
|
// HDF5 otherwise crashes on derefencing a zero pointer for the string type
|
|
|
|
|
write(ptr, new(allocator.allocate(1)) char(0));
|
|
|
|
|
} else {
|
|
|
|
|
memset(ptr, 0, member_type.getSize());
|
|
|
|
|
advance(ptr, member_type.getSize());
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
set_unset_mask |= 1 << i;
|
2016-02-24 11:26:47 +01:00
|
|
|
if (member_type.getClass() == H5T_REFERENCE) {
|
|
|
|
|
// Something that comes from the ref_attributes settings
|
|
|
|
|
const std::string dsn = current_entity_name + "." + attribute_name + "_" + boost::lexical_cast<std::string>(dat.id());
|
|
|
|
|
switch(attr_value.type()) {
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_INT: {
|
|
|
|
|
std::vector<int> vs = attr_value;
|
|
|
|
|
write_reference_attribute(ptr, dsn, vs);
|
|
|
|
|
break; }
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_BOOL: {
|
|
|
|
|
std::vector<bool> vs = attr_value;
|
|
|
|
|
write_reference_attribute(ptr, dsn, vs);
|
|
|
|
|
break; }
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_DOUBLE: {
|
|
|
|
|
std::vector<double> vs = attr_value;
|
|
|
|
|
write_reference_attribute(ptr, dsn, vs);
|
|
|
|
|
break; }
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT: {
|
|
|
|
|
std::vector< std::vector<int> > vs = attr_value;
|
|
|
|
|
write_reference_attribute2(ptr, dsn, vs);
|
|
|
|
|
break; }
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_BOOL: {
|
|
|
|
|
std::vector< std::vector<int> > vs = attr_value;
|
|
|
|
|
write_reference_attribute2(ptr, dsn, vs);
|
|
|
|
|
break; }
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE: {
|
|
|
|
|
std::vector< std::vector<double> > vs = attr_value;
|
|
|
|
|
write_reference_attribute2(ptr, dsn, vs);
|
|
|
|
|
break; }
|
|
|
|
|
default:
|
|
|
|
|
throw IfcException(dsn + " is not a supported aggregate");
|
|
|
|
|
}
|
|
|
|
|
} if (settings_.fix_global_id() && attribute_name == "GlobalId") {
|
2015-11-16 10:37:02 +01:00
|
|
|
std::string s = attr_value;
|
|
|
|
|
memcpy(static_cast<char*>(ptr), s.c_str(), s.size());
|
|
|
|
|
advance(ptr, s.length());
|
2016-02-24 11:26:47 +01:00
|
|
|
} else if (settings_.fix_cartesian_point() && ((attribute_name == "Coordinates" && current_entity_name == "IfcCartesianPoint") || (attribute_name == "DirectionRatios" && current_entity_name == "IfcDirection"))) {
|
2017-09-01 12:50:42 +02:00
|
|
|
std::vector<double> vs = attr_value;
|
|
|
|
|
for (auto vs_it = vs.begin(); vs_it != vs.end(); ++vs_it) {
|
|
|
|
|
write_number_of_size(ptr, default_types[simple_type::real_type]->getSize(), *vs_it);
|
2015-11-16 10:37:02 +01:00
|
|
|
}
|
2017-09-01 12:50:42 +02:00
|
|
|
if (vs.size() == 2) {
|
2015-11-16 10:37:02 +01:00
|
|
|
write_number_of_size(ptr, default_types[simple_type::real_type]->getSize(), std::numeric_limits<double>::quiet_NaN());
|
|
|
|
|
}
|
|
|
|
|
} else if (member_type == *instance_reference) {
|
2015-11-10 11:16:00 +01:00
|
|
|
IfcUtil::IfcBaseClass* v = attr_value;
|
|
|
|
|
auto ref = make_instance_reference(v);
|
2015-11-30 22:34:48 +01:00
|
|
|
// write_number_of_size(ptr, instance_reference->getMemberDataType(0).getSize(), ref.first);
|
|
|
|
|
// write_number_of_size(ptr, instance_reference->getMemberDataType(1).getSize(), ref.second);
|
|
|
|
|
write_number_of_size(ptr, 2, ref.first);
|
|
|
|
|
write_number_of_size(ptr, 4, ref.second);
|
2015-11-10 11:16:00 +01:00
|
|
|
} else if (member_type == *default_types[simple_type::real_type]) {
|
|
|
|
|
double d = attr_value;
|
|
|
|
|
write_number_of_size(ptr, member_type.getSize(), d);
|
2017-09-01 12:50:42 +02:00
|
|
|
} else if (member_type == *default_types[simple_type::string_type] || member_type.getClass() == H5T_STRING) {
|
2015-11-10 11:16:00 +01:00
|
|
|
std::string s = attr_value;
|
2017-09-01 12:50:42 +02:00
|
|
|
if (member_type == *default_types[simple_type::string_type]) {
|
|
|
|
|
write(ptr, s);
|
|
|
|
|
} else {
|
|
|
|
|
write_string_of_size(ptr, s, member_type.getSize());
|
|
|
|
|
}
|
2015-11-10 11:16:00 +01:00
|
|
|
} else if (member_type == *default_types[simple_type::integer_type]) {
|
2017-09-01 12:50:42 +02:00
|
|
|
int v = attr_value;
|
|
|
|
|
write_number_of_size(ptr, member_type.getSize(), v);
|
2015-11-10 11:16:00 +01:00
|
|
|
} else if (member_type == *default_types[simple_type::boolean_type] ||
|
|
|
|
|
member_type == *default_types[simple_type::logical_type])
|
|
|
|
|
{
|
|
|
|
|
bool b = attr_value;
|
|
|
|
|
write_number_of_size(ptr, member_type.getSize(), static_cast<uint8_t>(b ? 1 : 0));
|
|
|
|
|
} else if (member_type.getClass() == H5T_ENUM) {
|
|
|
|
|
// NB: Note that boolean and logical are also enums
|
|
|
|
|
// NB2: In IfcOpenShell an enum value can be read as a string
|
|
|
|
|
std::string s = attr_value;
|
|
|
|
|
const std::vector<std::string>& enum_values = schema_attr->type_of_attribute()->as_named_type()->declared_type()->as_enumeration_type()->enumeration_items();
|
|
|
|
|
size_t d = std::distance(enum_values.begin(), std::find(enum_values.begin(), enum_values.end(), s));
|
|
|
|
|
write_number_of_size(ptr, member_type.getSize(), d);
|
2017-09-01 12:50:42 +02:00
|
|
|
} else if (member_type.getClass() == H5T_VLEN || member_type.getClass() == H5T_ARRAY) {
|
2015-11-10 11:16:00 +01:00
|
|
|
const parameter_type* pt = schema_attr->type_of_attribute();
|
|
|
|
|
while (pt->as_named_type()) {
|
|
|
|
|
pt = pt->as_named_type()->declared_type()->as_type_declaration()->declared_type();
|
|
|
|
|
}
|
|
|
|
|
const named_type* nt = pt->as_aggregation_type()->type_of_element()->as_named_type();
|
|
|
|
|
if (nt && nt->declared_type()->as_select_type()) {
|
|
|
|
|
const H5::DataType* datatype = declared_types[nt->declared_type()->type()];
|
2017-09-01 12:50:42 +02:00
|
|
|
IfcEntityList::ptr vs = attr_value;
|
2015-11-10 11:16:00 +01:00
|
|
|
if (datatype == instance_reference) {
|
|
|
|
|
// For a SELECTs with only ENTITY leaves, a blind instance reference type is used
|
2017-09-01 12:50:42 +02:00
|
|
|
// TK: Is this actually correct?
|
|
|
|
|
if (member_type.getClass() == H5T_VLEN) {
|
|
|
|
|
write_aggregate(ptr, vs);
|
|
|
|
|
} else {
|
|
|
|
|
H5::ArrayType* adt = (H5::ArrayType*) &member_type;
|
|
|
|
|
size_t ndims = adt->getArrayNDims();
|
|
|
|
|
size_t element_size = adt->getSuper().getSize();
|
|
|
|
|
hsize_t* array_dims = new hsize_t[ndims];
|
|
|
|
|
adt->getArrayDims(array_dims);
|
|
|
|
|
|
|
|
|
|
std::vector<IfcUtil::IfcBaseClass*> es2(vs->begin(), vs->end());
|
|
|
|
|
write_consecutive(ptr, es2, array_dims, &element_size);
|
|
|
|
|
}
|
2015-11-10 11:16:00 +01:00
|
|
|
} else {
|
2017-09-01 12:50:42 +02:00
|
|
|
if (member_type.getClass() == H5T_VLEN) {
|
|
|
|
|
size_t size_in_bytes = datatype->getSize();
|
|
|
|
|
size_t num_elements = vs->size();
|
|
|
|
|
void* buffer_ptr;
|
|
|
|
|
// void* buffer = buffer_ptr = new uint8_t[size_in_bytes * num_elements];
|
|
|
|
|
void* buffer = buffer_ptr = allocator.allocate(size_in_bytes * num_elements);
|
|
|
|
|
memset(buffer, 0, size_in_bytes * num_elements);
|
|
|
|
|
for (auto vs_it = vs->begin(); vs_it != vs->end(); ++vs_it) {
|
|
|
|
|
write_select(buffer_ptr, *vs_it, static_cast<const H5::CompType*>(datatype));
|
|
|
|
|
}
|
|
|
|
|
write_vlen_t(ptr, num_elements, buffer);
|
|
|
|
|
} else {
|
|
|
|
|
// Set to zero in case of different size
|
|
|
|
|
memset(ptr, 0, member_type.getSize());
|
|
|
|
|
void* ptr_ = ptr;
|
|
|
|
|
for (auto vs_it = vs->begin(); vs_it != vs->end(); ++vs_it) {
|
|
|
|
|
write_select(ptr_, *vs_it, static_cast<const H5::CompType*>(datatype));
|
|
|
|
|
}
|
|
|
|
|
// This is cheating, let's hope the sizes align.
|
|
|
|
|
advance(ptr, member_type.getSize());
|
2015-11-10 11:16:00 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2017-09-01 12:50:42 +02:00
|
|
|
if (member_type.getClass() == H5T_VLEN) {
|
|
|
|
|
switch (attr_value.type()) {
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_INT: {
|
|
|
|
|
std::vector<int> vs = attr_value;
|
|
|
|
|
write_aggregate(ptr, vs);
|
|
|
|
|
break; }
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_BOOL: {
|
|
|
|
|
std::vector<bool> vs = attr_value;
|
|
|
|
|
write_aggregate(ptr, vs);
|
|
|
|
|
break; }
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_DOUBLE: {
|
|
|
|
|
std::vector<double> vs = attr_value;
|
|
|
|
|
write_aggregate(ptr, vs);
|
|
|
|
|
break; }
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE: {
|
|
|
|
|
IfcEntityList::ptr vs = attr_value;
|
|
|
|
|
write_aggregate(ptr, vs);
|
|
|
|
|
break; }
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_STRING: {
|
|
|
|
|
std::vector<std::string> ss = attr_value;
|
|
|
|
|
write_aggregate(ptr, ss);
|
|
|
|
|
break; }
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT: {
|
|
|
|
|
std::vector< std::vector<int> > vs = attr_value;
|
|
|
|
|
write_aggregate2(ptr, vs);
|
|
|
|
|
break; }
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_BOOL: {
|
|
|
|
|
std::vector< std::vector<bool> > vs = attr_value;
|
|
|
|
|
write_aggregate2(ptr, vs);
|
|
|
|
|
break; }
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE: {
|
|
|
|
|
std::vector< std::vector<double> > vs = attr_value;
|
|
|
|
|
write_aggregate2(ptr, vs);
|
|
|
|
|
break; }
|
|
|
|
|
default:
|
|
|
|
|
// Can be an empty list in which case parser does not know type
|
|
|
|
|
if (attr_value.size() > 0) {
|
|
|
|
|
Logger::Message(Logger::LOG_ERROR, "Unsupported aggregate encountered", *jt);
|
|
|
|
|
}
|
|
|
|
|
memset(ptr, 0, member_type.getSize());
|
|
|
|
|
ptr = (uint8_t*)ptr + member_type.getSize();
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (member_type.getClass() != H5T_ARRAY) throw;
|
|
|
|
|
H5::ArrayType* adt = (H5::ArrayType*) &member_type;
|
|
|
|
|
size_t ndims = adt->getArrayNDims();
|
|
|
|
|
size_t element_size = adt->getSuper().getSize();
|
|
|
|
|
hsize_t* array_dims = new hsize_t[ndims];
|
|
|
|
|
adt->getArrayDims(array_dims);
|
|
|
|
|
|
|
|
|
|
size_t ifcdims = 0;
|
|
|
|
|
|
|
|
|
|
switch (attr_value.type()) {
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_INT:
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_BOOL:
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_DOUBLE:
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE:
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_STRING:
|
|
|
|
|
ifcdims = 1;
|
|
|
|
|
break;
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT:
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_BOOL:
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE:
|
|
|
|
|
ifcdims = 2;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Caught in default block below and memset() to zero.
|
|
|
|
|
// if (false && ifcdims != ndims) {
|
|
|
|
|
// std::cerr << "Expected dim " << ndims << " got " << ifcdims << std::endl;
|
|
|
|
|
// std::cin.get();
|
|
|
|
|
// abort();
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
switch (attr_value.type()) {
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_INT: {
|
|
|
|
|
std::vector<int> vs = attr_value;
|
|
|
|
|
write_consecutive(ptr, vs, array_dims, &element_size);
|
|
|
|
|
break; }
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_BOOL: {
|
|
|
|
|
std::vector<bool> vs = attr_value;
|
|
|
|
|
write_consecutive(ptr, vs, array_dims, &element_size);
|
|
|
|
|
break; }
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_DOUBLE: {
|
|
|
|
|
std::vector<double> vs = attr_value;
|
|
|
|
|
write_consecutive(ptr, vs, array_dims, &element_size);
|
|
|
|
|
break; }
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_ENTITY_INSTANCE: {
|
|
|
|
|
IfcEntityList::ptr vs = attr_value;
|
|
|
|
|
std::vector<IfcUtil::IfcBaseClass*> vs2(vs->begin(), vs->end());
|
|
|
|
|
write_consecutive(ptr, vs2, array_dims, &element_size);
|
|
|
|
|
break; }
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_STRING: {
|
|
|
|
|
std::vector<std::string> vs = attr_value;
|
|
|
|
|
write_consecutive(ptr, vs, array_dims, &element_size);
|
|
|
|
|
break; }
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_INT: {
|
|
|
|
|
// std::vector< std::vector<int> > ds = attr_value;
|
|
|
|
|
// write_consecutive2(ptr, ds);
|
|
|
|
|
break; }
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_BOOL: {
|
|
|
|
|
// std::vector< std::vector<bool> > ds = attr_value;
|
|
|
|
|
// write_consecutive2(ptr, ds);
|
|
|
|
|
break; }
|
|
|
|
|
case IfcUtil::Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE: {
|
|
|
|
|
// std::vector< std::vector<double> > ds = attr_value;
|
|
|
|
|
// write_consecutive2(ptr, ds);
|
|
|
|
|
break; }
|
|
|
|
|
default:
|
|
|
|
|
// Can be an empty list in which case parser does not know type
|
|
|
|
|
if (attr_value.size() > 0) {
|
|
|
|
|
Logger::Message(Logger::LOG_ERROR, "Unsupported aggregate encountered", *jt);
|
|
|
|
|
}
|
|
|
|
|
memset(ptr, 0, member_type.getSize());
|
|
|
|
|
advance(ptr, member_type.getSize());
|
2015-11-10 11:16:00 +01:00
|
|
|
}
|
2017-09-01 12:50:42 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
delete[] array_dims;
|
2015-11-10 11:16:00 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (member_type.getClass() == H5T_COMPOUND) {
|
|
|
|
|
memset(ptr, 0, member_type.getSize());
|
|
|
|
|
|
|
|
|
|
IfcUtil::ArgumentType ty = attr_value.type();
|
|
|
|
|
if (ty != IfcUtil::Argument_ENTITY_INSTANCE) throw;
|
2017-09-01 12:50:42 +02:00
|
|
|
// v impl. cast
|
2015-11-10 11:16:00 +01:00
|
|
|
write_select(ptr, attr_value, static_cast<H5::CompType*>(&member_type));
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-11-30 22:34:48 +01:00
|
|
|
|
|
|
|
|
member_type.close();
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
for (auto inv_it = inverse_attributes.begin(); inv_it != inverse_attributes.end(); ++inv_it) {
|
2015-11-30 22:34:48 +01:00
|
|
|
member_type = dt->getMemberDataType(member_idx++);
|
|
|
|
|
|
|
|
|
|
if (member_type.getClass() != H5T_VLEN) {
|
|
|
|
|
std::cerr << dt->getMemberName(member_idx - 1) << " ";
|
|
|
|
|
std::cerr << "Inverse attribute must be vlen" << std::endl;
|
|
|
|
|
}
|
2017-09-01 12:50:42 +02:00
|
|
|
const IfcParse::entity* entity_ref = (*inv_it)->entity_reference();
|
|
|
|
|
const IfcParse::entity::attribute* attribute_ref = (*inv_it)->attribute_reference();
|
2015-11-30 22:34:48 +01:00
|
|
|
IfcEntityList::ptr instances = f.getInverse(dat.id(), entity_ref->type(), entity_ref->attribute_index(attribute_ref));
|
|
|
|
|
if (instances->size() == 0) {
|
|
|
|
|
memset(ptr, 0, member_type.getSize());
|
|
|
|
|
advance(ptr, member_type.getSize());
|
|
|
|
|
} else {
|
|
|
|
|
write_aggregate(ptr, instances);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
member_type.close();
|
2015-11-10 11:16:00 +01:00
|
|
|
}
|
|
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
if (has_optional) {
|
|
|
|
|
write_number_of_size(set_unset_ptr, set_unset_size, set_unset_mask);
|
|
|
|
|
}
|
2015-11-30 22:34:48 +01:00
|
|
|
const size_t written_length = (uint8_t*) ptr - (uint8_t*) start;
|
|
|
|
|
|
|
|
|
|
if (written_length != datatype_size) {
|
|
|
|
|
std::cerr << "Written " << written_length << " bytes, but expected " << datatype_size << std::endl;
|
2017-09-01 12:50:42 +02:00
|
|
|
std::cin.get();
|
|
|
|
|
abort();
|
2015-11-30 22:34:48 +01:00
|
|
|
}
|
2015-11-10 11:16:00 +01:00
|
|
|
}
|
|
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
// for (size_t i = 0; i < dataset_size; ++i) {
|
|
|
|
|
// std::cout << std::hex << (int)((uint8_t*)data)[i] << " ";
|
|
|
|
|
// }
|
2015-11-30 22:34:48 +01:00
|
|
|
|
|
|
|
|
// visit(data, declared_types[*it]);
|
2015-11-10 11:16:00 +01:00
|
|
|
ds.write(data, *declared_types[*it]);
|
2015-11-30 22:34:48 +01:00
|
|
|
H5Dvlen_reclaim(declared_types[*it]->getId(), space.getId(), H5P_DEFAULT, data);
|
|
|
|
|
|
2015-11-10 11:16:00 +01:00
|
|
|
ds.close();
|
2015-11-30 22:34:48 +01:00
|
|
|
space.close();
|
2015-11-10 11:16:00 +01:00
|
|
|
|
2015-11-30 22:34:48 +01:00
|
|
|
if (plist != &H5::DSetCreatPropList::DEFAULT) {
|
|
|
|
|
// ->close() doesn't work due to const, hack hack hack
|
|
|
|
|
H5Pclose(plist->getId());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// allocator.free();
|
|
|
|
|
delete[] data;
|
2015-11-10 11:16:00 +01:00
|
|
|
|
2017-09-01 12:50:42 +02:00
|
|
|
for (auto es_it = es.begin(); es_it != es.end(); ++es_it) {
|
|
|
|
|
if (types_with_instiated_selected.find((**es_it).declaration().type()) == types_with_instiated_selected.end()) {
|
2015-11-30 22:34:48 +01:00
|
|
|
// Instances possibly refering to embedded simple type instantiations are not freed
|
2017-09-01 12:50:42 +02:00
|
|
|
static_cast<IfcParse::Entity*>(&(**es_it).data())->Unload();
|
2015-11-30 22:34:48 +01:00
|
|
|
}
|
2015-11-10 11:16:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
2017-09-01 12:50:42 +02:00
|
|
|
}
|
|
|
|
|
*/
|