2017-06-05 17:26:58 +02:00
/********************************************************************************
* *
* This file is part of IfcOpenShell. *
* *
* IfcOpenShell is free software: you can redistribute it and/or modify *
* it under the terms of the Lesser GNU General Public License as published by *
* the Free Software Foundation, either version 3.0 of the License, or *
* (at your option) any later version. *
* *
* IfcOpenShell is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* Lesser GNU General Public License for more details. *
* *
* You should have received a copy of the Lesser GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
2026-01-04 10:40:02 +01:00
# ifndef InstanceData_H
# define InstanceData_H
2017-06-05 17:26:58 +02:00
2026-01-04 10:40:02 +01:00
# include "express.h"
2026-03-31 15:32:36 +02:00
# include "argument_type.h"
# include "variant_array.h"
# include "schema.h"
2026-01-04 10:40:02 +01:00
# include "storage.h"
2017-06-05 17:26:58 +02:00
2025-09-03 11:11:55 +02:00
# ifdef IFOPSH_WITH_ROCKSDB
2025-08-26 13:56:03 +02:00
2025-02-21 16:12:16 +01:00
# pragma push_macro("Handle")
# undef Handle
# include <rocksdb/db.h>
# pragma pop_macro("Handle")
2025-08-26 13:56:03 +02:00
# endif
2024-08-23 20:29:07 +02:00
# include <boost/logic/tribool.hpp>
# include <boost/dynamic_bitset.hpp>
2026-03-31 15:32:36 +02:00
class IFC_PARSE_API enumeration_reference {
2024-08-23 20:29:07 +02:00
private :
2026-03-31 15:32:36 +02:00
const ifcopenshell : : enumeration_type * enumeration_ ;
2024-08-23 20:29:07 +02:00
size_t index_ ;
public :
2026-03-31 15:32:36 +02:00
enumeration_reference ( const ifcopenshell : : enumeration_type * enumeration = nullptr , size_t index = 0 )
2024-08-23 20:29:07 +02:00
: enumeration_ ( enumeration )
, index_ ( index )
{ }
const char * value ( ) const {
return enumeration_ - > lookup_enum_value ( index_ ) ;
}
2017-06-05 17:26:58 +02:00
2024-08-23 20:29:07 +02:00
size_t index ( ) const {
return index_ ;
}
2026-03-31 15:32:36 +02:00
const ifcopenshell : : enumeration_type * enumeration ( ) const {
2024-08-23 20:29:07 +02:00
return enumeration_ ;
}
} ;
2026-03-31 15:32:36 +02:00
class IFC_PARSE_API blank { } ;
class IFC_PARSE_API derived { } ;
2025-09-26 14:24:49 +02:00
class IFC_PARSE_API empty_aggregate_t { } ;
class IFC_PARSE_API empty_aggregate_of_aggregate_t { } ;
2024-08-23 20:29:07 +02:00
2025-02-21 16:12:16 +01:00
template < typename . . . Args >
struct parameter_pack {
static constexpr size_t size = sizeof . . . ( Args ) ;
} ;
typedef parameter_pack <
2024-08-23 20:29:07 +02:00
// A null argument, it will always serialize to $
2026-03-31 15:32:36 +02:00
blank ,
// @todo derived is not really necessary anymore, just serialize correctly based on schema
2024-08-23 20:29:07 +02:00
// A derived argument, it will always serialize to *
2026-03-31 15:32:36 +02:00
derived ,
2024-08-23 20:29:07 +02:00
// An integer argument, e.g. 123
// SCALARS:
int ,
// A boolean argument, it will serialize to either .T. or .F.
bool ,
// A logical argument, it will serialize to either .T. or .F. or .U.
boost : : logic : : tribool ,
// A floating point argument, e.g. 12.3
double ,
// A character string argument, e.g. 'IfcOpenShell'
std : : string ,
// A binary argument, e.g. "092A" -> 100100101010
boost : : dynamic_bitset < > ,
// An enumeration argument, e.g. .USERDEFINED.
// To initialize the argument a string representation
// has to be explicitly passed of the enumeration value
// which is stored internally as an integer. The argument
// itself does not keep track of what schema enumeration
// type is represented.
2026-03-31 15:32:36 +02:00
enumeration_reference ,
2024-08-23 20:29:07 +02:00
// An entity instance argument. It will either serialize to
// e.g. #123 or datatype identifier for simple types, e.g.
// IFCREAL(12.3)
2026-01-04 10:40:02 +01:00
express : : Base ,
2024-08-23 20:29:07 +02:00
// AGGREGATES:
empty_aggregate_t ,
// An aggregate of integers, e.g. (1,2,3)
std : : vector < int > ,
// An aggregate of floats, e.g. (12.3,4.)
std : : vector < double > ,
// An aggregate of strings, e.g. ('Ifc','Open','Shell')
std : : vector < std : : string > ,
// An aggregate of binaries, e.g. ("23B", "092A") -> (111011, 100100101010)
std : : vector < boost : : dynamic_bitset < > > ,
// An aggregate of entity instances. It will either serialize to
// e.g. (#1,#2,#3) or datatype identifier for simple types,
// e.g. (IFCREAL(1.2),IFCINTEGER(3.))
2026-01-04 10:40:02 +01:00
std : : vector < express : : Base > ,
2024-08-23 20:29:07 +02:00
// AGGREGATES OF AGGREGATES:
empty_aggregate_of_aggregate_t ,
// An aggregate of an aggregate of ints. E.g. ((1, 2), (3))
std : : vector < std : : vector < int > > ,
// An aggregate of an aggregate of floats. E.g. ((1., 2.3), (4.))
std : : vector < std : : vector < double > > ,
// An aggregate of an aggregate of entities. E.g. ((#1, #2), (#3))
2026-01-04 10:40:02 +01:00
std : : vector < std : : vector < express : : Base > > >
type_variant_parameter_pack ;
2025-02-21 16:12:16 +01:00
template < typename Pack >
struct pack_to_variant_array ;
template < typename . . . Args >
struct pack_to_variant_array < parameter_pack < Args . . . > > {
2026-03-31 15:32:36 +02:00
using type = variant_array < Args . . . > ;
2025-02-21 16:12:16 +01:00
} ;
using in_memory_attribute_storage = pack_to_variant_array < type_variant_parameter_pack > : : type ;
template < typename Pack >
struct TypeEncoder_t ;
template < typename . . . Types >
struct TypeEncoder_t < parameter_pack < Types . . . > > {
template < typename U >
static char encode_type ( ) {
return ' A ' + : : impl : : TypeIndex_v < U , Types . . . > ;
}
} ;
using TypeEncoder = TypeEncoder_t < type_variant_parameter_pack > ;
2024-08-23 20:29:07 +02:00
2026-03-31 15:32:36 +02:00
class IFC_PARSE_API mutable_attribute_value {
2026-01-04 10:40:02 +01:00
public :
2025-10-13 20:47:43 +02:00
uint32_t name_ ;
2024-08-23 20:29:07 +02:00
uint8_t index_ ;
} ;
2026-03-31 15:32:36 +02:00
namespace ifcopenshell {
2025-02-21 16:12:16 +01:00
namespace impl {
2025-09-26 14:24:49 +02:00
class IFC_PARSE_API rocks_db_file_storage ;
2025-02-21 16:12:16 +01:00
}
}
2025-10-19 13:20:58 +02:00
# ifdef IFOPSH_WITH_ROCKSDB
2025-02-25 21:29:54 +01:00
namespace impl {
// Trait to detect contiguous containers (vector / string)
template < typename T >
struct is_contiguous_container : std : : false_type { } ;
template < typename T , typename Alloc >
struct is_contiguous_container < std : : vector < T , Alloc > > : std : : true_type { } ;
template < typename CharT , typename Traits , typename Alloc >
struct is_contiguous_container < std : : basic_string < CharT , Traits , Alloc > > : std : : true_type { } ;
template < typename T , typename std : : enable_if < is_contiguous_container < T > : : value & & ! is_contiguous_container < typename T : : value_type > : : value , int > : : type = 0 >
2026-03-31 18:23:13 +02:00
bool serialize ( std : : string & buffer , const T & value ) {
auto byte_count = sizeof ( typename T : : value_type ) * value . size ( ) ;
buffer . resize ( byte_count + 1 ) ;
buffer [ 0 ] = TypeEncoder : : encode_type < T > ( ) ;
memcpy ( buffer . data ( ) + 1 , value . data ( ) , byte_count ) ;
2025-02-25 21:29:54 +01:00
return true ;
}
2025-02-27 22:07:31 +01:00
template < typename T , typename std : : enable_if < is_contiguous_container < T > : : value & & is_contiguous_container < typename T : : value_type > : : value , int > : : type = 0 >
2026-03-31 18:23:13 +02:00
bool serialize ( std : : string & buffer , const T & value ) {
buffer = std : : string ( 1 , TypeEncoder : : encode_type < T > ( ) ) ;
for ( auto & nested_value : value ) {
std : : string nested_buffer ;
serialize ( nested_buffer , nested_value ) ;
std : : string encoded_length ( sizeof ( size_t ) , 0 ) ;
size_t payload_size = nested_buffer . size ( ) - 1 ;
memcpy ( encoded_length . data ( ) , & payload_size , sizeof ( size_t ) ) ;
2025-02-27 22:07:31 +01:00
// @todo horribly inefficient
// @todo strip off type label?
2026-03-31 18:23:13 +02:00
buffer + = encoded_length + nested_buffer . substr ( 1 ) ;
2025-02-27 22:07:31 +01:00
}
return true ;
}
2025-02-25 21:29:54 +01:00
template < typename T , typename std : : enable_if < std : : is_integral_v < T > | | std : : is_floating_point_v < T > , int > : : type = 0 >
2026-03-31 18:23:13 +02:00
bool serialize ( std : : string & buffer , const T & value ) {
buffer . resize ( sizeof ( T ) + 1 ) ;
buffer [ 0 ] = TypeEncoder : : encode_type < T > ( ) ;
memcpy ( buffer . data ( ) + 1 , & value , sizeof ( T ) ) ;
2025-02-25 21:29:54 +01:00
return true ;
}
2026-03-31 18:23:13 +02:00
bool serialize ( std : : string & buffer , const blank & value ) ;
2025-02-25 21:29:54 +01:00
2026-03-31 18:23:13 +02:00
bool serialize ( std : : string & buffer , const derived & value ) ;
bool serialize ( std : : string & buffer , const empty_aggregate_t & value ) ;
bool serialize ( std : : string & buffer , const empty_aggregate_of_aggregate_t & value ) ;
2025-02-25 21:29:54 +01:00
2026-03-31 18:23:13 +02:00
bool serialize ( std : : string & buffer , const boost : : logic : : tribool & value ) ;
2025-02-25 21:29:54 +01:00
2026-03-31 18:23:13 +02:00
bool serialize ( std : : string & buffer , const boost : : dynamic_bitset < > & value ) ;
2025-02-25 21:29:54 +01:00
2026-03-31 18:23:13 +02:00
bool serialize ( std : : string & buffer , const express : : Base & value ) ;
2025-02-25 21:29:54 +01:00
2026-03-31 18:23:13 +02:00
bool serialize ( std : : string & buffer , const enumeration_reference & value ) ;
2025-02-25 21:29:54 +01:00
2026-03-31 18:23:13 +02:00
bool serialize ( std : : string & buffer , const std : : vector < express : : Base > & value ) ;
2025-02-25 21:29:54 +01:00
2026-03-31 18:23:13 +02:00
bool serialize ( std : : string & buffer , const std : : vector < std : : vector < express : : Base > > & value ) ;
2025-02-25 21:29:54 +01:00
2025-02-27 22:07:31 +01:00
template < typename T , typename std : : enable_if < is_contiguous_container < T > : : value & & ! is_contiguous_container < typename T : : value_type > : : value , int > : : type = 0 >
2026-03-31 18:23:13 +02:00
bool deserialize ( ifcopenshell : : impl : : rocks_db_file_storage * storage , const std : : string & buffer , T & value , bool has_type_prefix = true ) {
static_cast < void > ( storage ) ;
if ( has_type_prefix & & buffer [ 0 ] ! = TypeEncoder : : encode_type < T > ( ) ) {
2025-02-25 21:29:54 +01:00
return false ;
}
2026-03-31 18:23:13 +02:00
auto element_count = ( buffer . size ( ) - ( has_type_prefix ? 1 : 0 ) ) / sizeof ( typename T : : value_type ) ;
value . resize ( element_count ) ;
memcpy ( value . data ( ) , buffer . data ( ) + ( has_type_prefix ? 1 : 0 ) , element_count * sizeof ( typename T : : value_type ) ) ;
2025-02-27 22:07:31 +01:00
return true ;
}
template < typename T , typename std : : enable_if < is_contiguous_container < T > : : value & & is_contiguous_container < typename T : : value_type > : : value , int > : : type = 0 >
2026-03-31 18:23:13 +02:00
bool deserialize ( ifcopenshell : : impl : : rocks_db_file_storage * storage , const std : : string & buffer , T & value ) {
2025-02-27 22:07:31 +01:00
// @todo
2026-03-31 18:23:13 +02:00
auto ptr = buffer . data ( ) ;
2025-02-27 22:07:31 +01:00
if ( * ptr ! = TypeEncoder : : encode_type < T > ( ) ) {
return false ;
}
ptr + + ;
2026-03-31 18:23:13 +02:00
value . clear ( ) ;
while ( ptr < buffer . data ( ) + buffer . size ( ) ) {
size_t payload_size ;
memcpy ( & payload_size , ptr , sizeof ( size_t ) ) ;
2025-02-27 22:07:31 +01:00
// @todo view
ptr + = sizeof ( size_t ) ;
2026-03-31 18:23:13 +02:00
std : : string part ( ptr , payload_size ) ;
value . emplace_back ( ) ;
deserialize ( storage , part , value . back ( ) , false ) ;
ptr + = payload_size ;
2025-02-27 22:07:31 +01:00
}
2025-02-25 21:29:54 +01:00
return true ;
}
template < typename T , typename std : : enable_if < std : : is_integral_v < T > | | std : : is_floating_point_v < T > , int > : : type = 0 >
2026-03-31 18:23:13 +02:00
bool deserialize ( ifcopenshell : : impl : : rocks_db_file_storage * storage , const std : : string & buffer , T & value ) {
static_cast < void > ( storage ) ;
if ( buffer [ 0 ] ! = TypeEncoder : : encode_type < T > ( ) ) {
2025-02-25 21:29:54 +01:00
return false ;
}
2026-03-31 18:23:13 +02:00
memcpy ( & value , buffer . data ( ) + 1 , sizeof ( T ) ) ;
2025-02-25 21:29:54 +01:00
return true ;
}
2026-03-31 18:23:13 +02:00
bool deserialize ( ifcopenshell : : impl : : rocks_db_file_storage * storage , const std : : string & buffer , boost : : logic : : tribool & value ) ;
2025-02-25 21:29:54 +01:00
2026-03-31 18:23:13 +02:00
bool deserialize ( ifcopenshell : : impl : : rocks_db_file_storage * storage , const std : : string & buffer , boost : : dynamic_bitset < > & value ) ;
2025-02-25 21:29:54 +01:00
2026-03-31 18:23:13 +02:00
bool deserialize ( ifcopenshell : : impl : : rocks_db_file_storage * storage , const std : : string & buffer , std : : vector < express : : Base > & value ) ;
2025-02-25 21:29:54 +01:00
2026-03-31 18:23:13 +02:00
bool deserialize ( ifcopenshell : : impl : : rocks_db_file_storage * storage , const std : : string & buffer , std : : vector < std : : vector < express : : Base > > & value ) ;
2026-01-04 10:40:02 +01:00
}
2025-02-25 21:29:54 +01:00
2025-08-26 13:56:03 +02:00
# endif
2025-02-25 21:29:54 +01:00
2024-08-23 20:29:07 +02:00
// short lived
2026-03-31 15:32:36 +02:00
class IFC_PARSE_API attribute_value {
2024-08-23 20:29:07 +02:00
uint8_t index_ ;
2025-02-21 16:12:16 +01:00
uint8_t storage_model_ = 0 ;
2026-03-31 15:32:36 +02:00
const ifcopenshell : : declaration * entity_or_type_ = 0 ;
2025-02-21 16:12:16 +01:00
size_t instance_name_ ;
2026-01-04 10:40:02 +01:00
public :
2025-02-21 16:12:16 +01:00
union pointer_type {
const in_memory_attribute_storage * storage_ptr ;
2026-03-31 15:32:36 +02:00
ifcopenshell : : impl : : rocks_db_file_storage * db_ptr ;
2026-03-31 18:23:13 +02:00
pointer_type ( ifcopenshell : : impl : : rocks_db_file_storage * storage ) : db_ptr ( storage ) { }
pointer_type ( const in_memory_attribute_storage * storage ) : storage_ptr ( storage ) { }
2025-02-21 16:12:16 +01:00
} ;
2026-01-04 10:40:02 +01:00
private :
2025-02-21 16:12:16 +01:00
pointer_type array_ ;
2026-01-04 10:40:02 +01:00
public :
2026-03-31 15:32:36 +02:00
attribute_value ( )
2025-02-21 16:12:16 +01:00
: index_ ( 0 )
, storage_model_ ( 0 )
2025-08-27 11:03:16 +02:00
, array_ ( ( const in_memory_attribute_storage * ) nullptr )
2024-08-23 20:29:07 +02:00
{ }
2026-03-31 18:23:13 +02:00
attribute_value ( const in_memory_attribute_storage * storage , uint8_t index )
2025-02-21 16:12:16 +01:00
: index_ ( index )
, storage_model_ ( 0 )
2026-03-31 18:23:13 +02:00
, array_ ( storage )
2025-02-21 16:12:16 +01:00
{ }
2026-03-31 18:23:13 +02:00
attribute_value ( ifcopenshell : : impl : : rocks_db_file_storage * storage , size_t instance_name , const ifcopenshell : : declaration * entity_or_type , uint8_t index )
2025-02-21 16:12:16 +01:00
: index_ ( index )
, storage_model_ ( 1 )
2025-03-09 21:20:16 +01:00
, entity_or_type_ ( entity_or_type )
2025-08-27 11:03:16 +02:00
, instance_name_ ( instance_name )
2026-03-31 18:23:13 +02:00
, array_ ( storage )
2024-08-23 20:29:07 +02:00
{ }
operator int ( ) const ;
operator bool ( ) const ;
operator boost : : logic : : tribool ( ) const ;
operator double ( ) const ;
operator std : : string ( ) const ;
operator boost : : dynamic_bitset < > ( ) const ;
2026-01-04 10:40:02 +01:00
operator express : : Base ( ) const ;
2024-08-23 20:29:07 +02:00
operator std : : vector < int > ( ) const ;
operator std : : vector < double > ( ) const ;
operator std : : vector < std : : string > ( ) const ;
operator std : : vector < boost : : dynamic_bitset < > > ( ) const ;
2026-01-04 10:40:02 +01:00
operator std : : vector < express : : Base > ( ) const ;
2024-08-23 20:29:07 +02:00
operator std : : vector < std : : vector < int > > ( ) const ;
operator std : : vector < std : : vector < double > > ( ) const ;
2026-01-04 10:40:02 +01:00
operator std : : vector < std : : vector < express : : Base > > ( ) const ;
2024-08-23 20:29:07 +02:00
2026-03-31 15:32:36 +02:00
operator enumeration_reference ( ) const ;
2025-02-21 16:12:16 +01:00
2024-08-23 20:29:07 +02:00
bool isNull ( ) const ;
unsigned int size ( ) const ;
2026-03-31 15:32:36 +02:00
ifcopenshell : : argument_type type ( ) const ;
2025-03-14 10:20:22 +01:00
template < typename Visitor >
auto apply_visitor ( Visitor & & visitor ) const {
switch ( type ( ) ) {
2026-03-31 15:32:36 +02:00
case ifcopenshell : : Argument_DERIVED :
return visitor ( derived { } ) ;
case ifcopenshell : : Argument_INT :
2025-03-14 10:20:22 +01:00
return visitor ( ( int ) * this ) ;
2026-03-31 15:32:36 +02:00
case ifcopenshell : : Argument_BOOL :
2025-03-14 10:20:22 +01:00
return visitor ( ( bool ) * this ) ;
2026-03-31 15:32:36 +02:00
case ifcopenshell : : Argument_LOGICAL : {
2025-03-14 10:20:22 +01:00
boost : : logic : : tribool tb = * this ;
return visitor ( tb ) ;
}
2026-03-31 15:32:36 +02:00
case ifcopenshell : : Argument_DOUBLE :
2025-03-14 10:20:22 +01:00
return visitor ( ( double ) * this ) ;
2026-03-31 15:32:36 +02:00
case ifcopenshell : : Argument_STRING :
2025-03-14 10:20:22 +01:00
return visitor ( ( std : : string ) * this ) ;
2026-03-31 15:32:36 +02:00
case ifcopenshell : : Argument_BINARY :
2025-03-14 10:20:22 +01:00
return visitor ( ( boost : : dynamic_bitset < > ) * this ) ;
2026-03-31 15:32:36 +02:00
case ifcopenshell : : Argument_ENUMERATION :
return visitor ( ( enumeration_reference ) * this ) ;
case ifcopenshell : : Argument_ENTITY_INSTANCE :
2026-01-04 10:40:02 +01:00
return visitor ( ( express : : Base ) * this ) ;
2026-03-31 15:32:36 +02:00
case ifcopenshell : : Argument_AGGREGATE_OF_INT :
2025-03-14 10:20:22 +01:00
return visitor ( ( std : : vector < int > ) * this ) ;
2026-03-31 15:32:36 +02:00
case ifcopenshell : : Argument_AGGREGATE_OF_DOUBLE :
2025-03-14 10:20:22 +01:00
return visitor ( ( std : : vector < double > ) * this ) ;
2026-03-31 15:32:36 +02:00
case ifcopenshell : : Argument_AGGREGATE_OF_STRING :
2025-03-14 10:20:22 +01:00
return visitor ( ( std : : vector < std : : string > ) * this ) ;
2026-03-31 15:32:36 +02:00
case ifcopenshell : : Argument_AGGREGATE_OF_BINARY :
2025-03-14 10:20:22 +01:00
return visitor ( ( std : : vector < boost : : dynamic_bitset < > > ) * this ) ;
2026-03-31 15:32:36 +02:00
case ifcopenshell : : Argument_AGGREGATE_OF_ENTITY_INSTANCE :
2026-01-04 10:40:02 +01:00
return visitor ( ( std : : vector < express : : Base > ) * this ) ;
2026-03-31 15:32:36 +02:00
case ifcopenshell : : Argument_AGGREGATE_OF_AGGREGATE_OF_INT :
2025-03-14 10:20:22 +01:00
return visitor ( ( std : : vector < std : : vector < int > > ) * this ) ;
2026-03-31 15:32:36 +02:00
case ifcopenshell : : Argument_AGGREGATE_OF_AGGREGATE_OF_DOUBLE :
2025-03-14 10:20:22 +01:00
return visitor ( ( std : : vector < std : : vector < double > > ) * this ) ;
2026-03-31 15:32:36 +02:00
case ifcopenshell : : Argument_AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE :
2026-01-04 10:40:02 +01:00
return visitor ( ( std : : vector < std : : vector < express : : Base > > ) * this ) ;
2026-03-31 15:32:36 +02:00
case ifcopenshell : : Argument_EMPTY_AGGREGATE :
2025-03-14 10:20:22 +01:00
return visitor ( empty_aggregate_t { } ) ;
2026-03-31 15:32:36 +02:00
case ifcopenshell : : Argument_AGGREGATE_OF_EMPTY_AGGREGATE :
2025-03-14 10:20:22 +01:00
return visitor ( empty_aggregate_of_aggregate_t { } ) ;
default :
2026-03-31 15:32:36 +02:00
return visitor ( blank { } ) ;
2025-03-14 10:20:22 +01:00
}
}
2024-08-23 20:29:07 +02:00
} ;
2017-06-05 17:26:58 +02:00
2025-08-26 13:56:03 +02:00
2025-09-26 14:24:49 +02:00
struct IFC_PARSE_API rocks_db_attribute_storage {
2025-02-21 16:12:16 +01:00
public :
2025-09-03 11:11:55 +02:00
# ifdef IFOPSH_WITH_ROCKSDB
2025-02-27 22:07:31 +01:00
// @todo void* is obviously very ugly here
2025-02-21 16:12:16 +01:00
template < typename T >
2026-03-31 18:23:13 +02:00
IFC_PARSE_API void set ( void * storage , const ifcopenshell : : declaration * declaration , std : : size_t identity , std : : size_t index , const T & value ) ;
2025-02-21 16:12:16 +01:00
template < typename T >
2026-03-31 15:32:36 +02:00
IFC_PARSE_API bool has ( void * storage , const ifcopenshell : : declaration * decl , std : : size_t identity , std : : size_t index ) const ;
2025-08-26 13:56:03 +02:00
# endif
2025-02-21 16:12:16 +01:00
} ;
2026-03-31 15:32:36 +02:00
class IFC_PARSE_API instance_data {
2026-01-04 10:40:02 +01:00
protected :
static std : : atomic_uint32_t counter_ ;
2026-03-31 15:32:36 +02:00
ifcopenshell : : file * file_ ;
2026-01-04 10:40:02 +01:00
// @todo this could also be a 2-byte index, because we can get the schema from the file. But it wouldn't save space due to alignment
2026-03-31 15:32:36 +02:00
const ifcopenshell : : declaration * declaration_ ;
2026-01-04 10:40:02 +01:00
uint32_t identity_ ;
uint32_t id_ ;
template < typename T >
2026-01-06 09:41:20 +01:00
T * get_storage_of_type ( ) const ;
2026-01-04 10:40:02 +01:00
2026-01-15 19:24:55 +01:00
void populate_derived_ ( ) ;
2023-09-17 12:30:17 +02:00
public :
2025-03-18 10:41:03 +01:00
// Since rocks_db_attribute_storage has no members this is not a variant<in_memory, rocks> but in_memory*, where nullptr means a rocks_db_attribute_storage is constructed on the fly given the context from instance data.
in_memory_attribute_storage * storage_ ;
2023-09-17 12:30:17 +02:00
2026-03-31 15:32:36 +02:00
const ifcopenshell : : declaration * declaration ( ) const {
2026-01-04 10:40:02 +01:00
return declaration_ ;
}
2026-03-31 15:32:36 +02:00
ifcopenshell : : file * file ( ) const {
2026-01-04 10:40:02 +01:00
return file_ ;
}
uint32_t identity ( ) const {
return identity_ ;
}
uint32_t id ( ) const {
return id_ ;
}
2026-03-31 15:32:36 +02:00
instance_data ( ifcopenshell : : file * file , const ifcopenshell : : declaration * declaration , uint32_t id , in_memory_attribute_storage & & storage )
2026-01-04 10:40:02 +01:00
: file_ ( file ) , declaration_ ( declaration ) , identity_ ( counter_ + + ) , id_ ( id ) , storage_ ( new in_memory_attribute_storage ( std : : move ( storage ) ) )
2026-01-15 19:24:55 +01:00
{
populate_derived_ ( ) ;
}
2025-02-21 16:12:16 +01:00
2026-03-31 18:23:13 +02:00
instance_data ( ifcopenshell : : file * file , const ifcopenshell : : declaration * declaration , uint32_t id , rocks_db_attribute_storage & & storage )
2026-01-04 10:40:02 +01:00
: file_ ( file ) , declaration_ ( declaration ) , identity_ ( counter_ + + ) , id_ ( id ) , storage_ ( nullptr )
2026-01-15 19:24:55 +01:00
{
2026-03-31 18:23:13 +02:00
static_cast < void > ( storage ) ;
2026-01-15 19:24:55 +01:00
populate_derived_ ( ) ;
}
2017-06-05 17:26:58 +02:00
2026-01-04 10:40:02 +01:00
/*
// now that there are referenced as shared_ptr there is no move constructor anymore
2026-03-31 15:32:36 +02:00
instance_data(instance_data&& other) noexcept
2026-01-04 10:40:02 +01:00
: file_(other.file_), id_(other.id_), declaration_(other.declaration_), storage_(std::exchange(other.storage_, nullptr))
2024-08-23 20:29:07 +02:00
{}
2026-01-04 10:40:02 +01:00
*/
2017-06-05 17:26:58 +02:00
2025-08-25 12:45:10 +02:00
// No copy-constructor/-assignment anymore because we need the instance for storage model context
2026-03-31 18:23:13 +02:00
instance_data ( const instance_data & other ) = delete ;
instance_data & operator = ( const instance_data & other ) = delete ;
instance_data & operator = ( instance_data & & other ) = delete ;
2026-03-31 15:32:36 +02:00
instance_data ( instance_data & & other ) noexcept = delete ;
2026-01-04 10:40:02 +01:00
/*
// same
2026-03-31 15:32:36 +02:00
instance_data& operator=(instance_data&& other) noexcept {
2024-08-23 20:29:07 +02:00
if (this != &other) {
2025-08-25 12:45:10 +02:00
delete storage_;
storage_ = std::exchange(other.storage_, nullptr);
2024-08-23 20:29:07 +02:00
}
return *this;
}
2026-01-04 10:40:02 +01:00
*/
2024-08-23 20:29:07 +02:00
2026-03-31 15:32:36 +02:00
~ instance_data ( ) {
2025-08-25 12:45:10 +02:00
delete storage_ ;
}
2026-03-31 18:23:13 +02:00
attribute_value get_attribute_value ( size_t attribute_index ) const ;
2017-06-05 17:26:58 +02:00
2025-02-21 16:12:16 +01:00
template < typename T >
2026-03-31 18:23:13 +02:00
void set_attribute_value ( std : : size_t attribute_index , T & & value ) {
2025-03-18 10:41:03 +01:00
if ( storage_ ) {
2026-03-31 18:23:13 +02:00
storage_ - > set ( attribute_index , value ) ;
2025-08-26 13:56:03 +02:00
}
2025-09-03 11:11:55 +02:00
# ifdef IFOPSH_WITH_ROCKSDB
2025-08-26 13:56:03 +02:00
else {
2026-04-22 12:04:24 +02:00
rocks_db_attribute_storage { } . set ( get_storage_of_type < ifcopenshell : : impl : : rocks_db_file_storage > ( ) , declaration_ , declaration_ - > as_entity ( ) ? id_ : identity_ , attribute_index , value ) ;
2025-03-18 10:41:03 +01:00
}
2025-08-26 13:56:03 +02:00
# endif
2025-02-21 16:12:16 +01:00
}
2017-06-05 17:26:58 +02:00
2025-02-21 16:12:16 +01:00
template < typename T >
2026-03-31 18:23:13 +02:00
bool has_attribute_value ( std : : size_t attribute_index ) const {
2025-03-18 10:41:03 +01:00
if ( storage_ ) {
2026-03-31 18:23:13 +02:00
return storage_ - > has < T > ( attribute_index ) ;
2025-08-26 13:56:03 +02:00
}
2025-09-03 11:11:55 +02:00
# ifdef IFOPSH_WITH_ROCKSDB
2025-08-26 13:56:03 +02:00
else {
2026-04-22 12:04:24 +02:00
return rocks_db_attribute_storage { } . has < T > ( get_storage_of_type < ifcopenshell : : impl : : rocks_db_file_storage > ( ) , declaration_ , declaration_ - > as_entity ( ) ? id_ : identity_ , attribute_index ) ;
2025-03-18 10:41:03 +01:00
}
2025-08-26 13:56:03 +02:00
# endif
2025-02-21 16:12:16 +01:00
}
2026-03-31 18:23:13 +02:00
void to_string ( std : : ostream & stream , bool uppercase = false ) const ;
2017-06-05 17:26:58 +02:00
} ;
# endif