diff --git a/include/openPMD/backend/Attributable.hpp b/include/openPMD/backend/Attributable.hpp index fc31a49eec..bdbd2dfd05 100644 --- a/include/openPMD/backend/Attributable.hpp +++ b/include/openPMD/backend/Attributable.hpp @@ -127,7 +127,7 @@ class Attributable friend class BaseRecord; template< typename T_elem > friend class BaseRecordInterface; - template< typename > + template< typename, typename > friend class internal::BaseRecordData; template< typename T, diff --git a/include/openPMD/backend/BaseRecord.hpp b/include/openPMD/backend/BaseRecord.hpp index 7f7377c8a9..d467ce59c3 100644 --- a/include/openPMD/backend/BaseRecord.hpp +++ b/include/openPMD/backend/BaseRecord.hpp @@ -142,6 +142,12 @@ class BaseRecord : using iterator = typename T_container::iterator; using const_iterator = typename T_container::const_iterator; + // this avoids object slicing + operator T_RecordComponent() const + { + return { m_baseRecordData }; + } + virtual ~BaseRecord() = default; mapped_type& operator[](key_type const& key) override; @@ -178,6 +184,8 @@ class BaseRecord : protected: void readBase(); + void datasetDefined() override; + private: void flush(std::string const&) final; virtual void flush_impl(std::string const&) = 0; @@ -238,12 +246,11 @@ BaseRecord< T_elem, T_RecordComponent >::operator[]( key_type const & key ) throw std::runtime_error("A scalar component can not be contained at " "the same time as one or more regular components."); - mapped_type& ret = T_container::operator[](key); if( keyScalar ) { - get().m_containsScalar = true; - ret.parent() = this->parent(); + datasetDefined(); } + mapped_type& ret = keyScalar ? *this : T_container::operator[](key); return ret; } } @@ -263,12 +270,12 @@ BaseRecord< T_elem, T_RecordComponent >::operator[](key_type&& key) throw std::runtime_error("A scalar component can not be contained at " "the same time as one or more regular components."); - mapped_type& ret = T_container::operator[](std::move(key)); if( keyScalar ) { - get().m_containsScalar = true; - ret.parent() = this->parent(); + datasetDefined(); } + mapped_type& ret = + keyScalar ? *this : T_container::operator[](std::move(key)); return ret; } } @@ -417,4 +424,18 @@ BaseRecord< T_elem, T_RecordComponent >::dirtyRecursive() const } return false; } + +template< typename T_elem, typename T_RecordComponent > +void BaseRecord< T_elem, T_RecordComponent >::datasetDefined() +{ + // If the RecordComponent API of this object has been used, then the record + // is a scalar one + T_container::emplace( + RecordComponent::SCALAR, + // need to construct it in this line already, construction inside + // emplace is impossible due to private constructors + T_RecordComponent{ m_baseRecordData } ); + get().m_containsScalar = true; + T_RecordComponent::datasetDefined(); +} } // namespace openPMD diff --git a/include/openPMD/backend/BaseRecordComponent.hpp b/include/openPMD/backend/BaseRecordComponent.hpp index b19ac2e75a..09d25dd755 100644 --- a/include/openPMD/backend/BaseRecordComponent.hpp +++ b/include/openPMD/backend/BaseRecordComponent.hpp @@ -133,6 +133,8 @@ class BaseRecordComponent : public Attributable BaseRecordComponent( std::shared_ptr< internal::BaseRecordComponentData > ); + virtual void datasetDefined(); + private: BaseRecordComponent(); }; // BaseRecordComponent diff --git a/include/openPMD/backend/MeshRecordComponent.hpp b/include/openPMD/backend/MeshRecordComponent.hpp index 805f9955fc..796ff7306f 100644 --- a/include/openPMD/backend/MeshRecordComponent.hpp +++ b/include/openPMD/backend/MeshRecordComponent.hpp @@ -86,6 +86,9 @@ class MeshRecordComponent : public RecordComponent */ template< typename T > MeshRecordComponent& makeConstant(T); + +protected: + void datasetDefined() override; }; diff --git a/src/Mesh.cpp b/src/Mesh.cpp index 6b0dc1b2d2..8edb5fd95e 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -237,11 +237,8 @@ Mesh::flush_impl(std::string const& name) if( scalar() ) { MeshRecordComponent& mrc = at(RecordComponent::SCALAR); - mrc.parent() = parent(); mrc.flush(name); IOHandler()->flush(); - writable().abstractFilePosition = mrc.writable().abstractFilePosition; - written() = true; } else { Parameter< Operation::CREATE_PATH > pCreate; @@ -257,8 +254,6 @@ Mesh::flush_impl(std::string const& name) for( auto& comp : *this ) { comp.second.flush(name); - writable().abstractFilePosition = - comp.second.writable().abstractFilePosition; } } else diff --git a/src/RecordComponent.cpp b/src/RecordComponent.cpp index 305a0cab4b..29596ff9b2 100644 --- a/src/RecordComponent.cpp +++ b/src/RecordComponent.cpp @@ -93,6 +93,8 @@ RecordComponent::resetDataset( Dataset d ) throw error::WrongAPIUsage( "[RecordComponent] Must set specific datatype." ); } + + datasetDefined(); // if( d.extent.empty() ) // throw std::runtime_error("Dataset extent must be at least 1D."); if( std::any_of( @@ -186,6 +188,7 @@ RecordComponent::makeEmpty( Dataset d ) if( rc.m_dataset.extent.size() == 0 ) throw std::runtime_error( "Dataset extent must be at least 1D." ); + datasetDefined(); rc.m_isEmpty = true; dirty() = true; if( !written() ) diff --git a/src/backend/BaseRecordComponent.cpp b/src/backend/BaseRecordComponent.cpp index 54503f8313..fce3122d11 100644 --- a/src/backend/BaseRecordComponent.cpp +++ b/src/backend/BaseRecordComponent.cpp @@ -35,6 +35,7 @@ BaseRecordComponent::resetDatatype(Datatype d) if( written() ) throw std::runtime_error("A Records Datatype can not (yet) be changed after it has been written."); + datasetDefined(); get().m_dataset.dtype = d; return *this; } @@ -79,4 +80,7 @@ BaseRecordComponent::BaseRecordComponent() { Attributable::setData( m_baseRecordComponentData ); } + +void BaseRecordComponent::datasetDefined() +{} } // namespace openPMD diff --git a/src/backend/MeshRecordComponent.cpp b/src/backend/MeshRecordComponent.cpp index 8c9634a32c..73a1c24b2a 100644 --- a/src/backend/MeshRecordComponent.cpp +++ b/src/backend/MeshRecordComponent.cpp @@ -25,9 +25,7 @@ namespace openPMD { MeshRecordComponent::MeshRecordComponent() : RecordComponent() -{ - setPosition(std::vector< double >{0}); -} +{} void MeshRecordComponent::read() @@ -62,6 +60,12 @@ MeshRecordComponent::setPosition(std::vector< T > pos) return *this; } +void MeshRecordComponent::datasetDefined() +{ + setPosition(std::vector< double >{0}); + RecordComponent::datasetDefined(); +} + template MeshRecordComponent& MeshRecordComponent::setPosition(std::vector< float > pos); diff --git a/src/backend/PatchRecordComponent.cpp b/src/backend/PatchRecordComponent.cpp index 9331e65b90..bf2d52cc1c 100644 --- a/src/backend/PatchRecordComponent.cpp +++ b/src/backend/PatchRecordComponent.cpp @@ -53,6 +53,7 @@ PatchRecordComponent::resetDataset(Dataset d) [](Extent::value_type const& i) { return i == 0u; }) ) throw std::runtime_error("Dataset extent must not be zero in any dimension."); + datasetDefined(); get().m_dataset = d; dirty() = true; return *this;