diff --git a/include/openPMD/backend/Attributable.hpp b/include/openPMD/backend/Attributable.hpp index 58648c8b2a..bba3eb409c 100644 --- a/include/openPMD/backend/Attributable.hpp +++ b/include/openPMD/backend/Attributable.hpp @@ -90,21 +90,37 @@ namespace internal A_MAP m_attributes; }; + enum class SetAttributeMode : char + { + WhileReadingAttributes, + FromPublicAPICall + }; + /** Verify values of attributes in the frontend * * verify string attributes are not empty (backend restriction, e.g., HDF5) */ template - inline void attr_value_check(std::string const /* key */, T /* value */) + inline void attr_value_check( + std::string const /* key */, T /* value */, SetAttributeMode) {} template <> - inline void attr_value_check(std::string const key, std::string const value) + inline void attr_value_check( + std::string const key, std::string const value, SetAttributeMode mode) { - if (value.empty()) - throw std::runtime_error( - "[setAttribute] Value for string attribute '" + key + - "' must not be empty!"); + switch (mode) + { + case SetAttributeMode::FromPublicAPICall: + if (value.empty()) + throw std::runtime_error( + "[setAttribute] Value for string attribute '" + key + + "' must not be empty!"); + break; + case SetAttributeMode::WhileReadingAttributes: + // no checks while reading + break; + } } template @@ -276,6 +292,13 @@ OPENPMD_protected void seriesFlush(internal::FlushParams); void flushAttributes(internal::FlushParams const &); + + template + bool setAttributeImpl( + std::string const &key, T value, internal::SetAttributeMode); + bool setAttributeImpl( + std::string const &key, char const value[], internal::SetAttributeMode); + enum ReadMode { /** @@ -410,11 +433,29 @@ OPENPMD_protected virtual void linkHierarchy(Writable &w); }; // Attributable -// TODO explicitly instantiate Attributable::setAttribute for all T in Datatype template inline bool Attributable::setAttribute(std::string const &key, T value) { - internal::attr_value_check(key, value); + return setAttributeImpl( + key, std::move(value), internal::SetAttributeMode::FromPublicAPICall); +} + +inline bool +Attributable::setAttribute(std::string const &key, char const value[]) +{ + return setAttributeImpl( + key, value, internal::SetAttributeMode::FromPublicAPICall); +} + +// note: we explicitly instantiate Attributable::setAttributeImpl for all T in +// Datatype in Attributable.cpp +template +inline bool Attributable::setAttributeImpl( + std::string const &key, + T value, + internal::SetAttributeMode setAttributeMode) +{ + internal::attr_value_check(key, value, setAttributeMode); auto &attri = get(); if (IOHandler() && Access::READ_ONLY == IOHandler()->m_frontendAccess) @@ -442,10 +483,12 @@ inline bool Attributable::setAttribute(std::string const &key, T value) } } -inline bool -Attributable::setAttribute(std::string const &key, char const value[]) +inline bool Attributable::setAttributeImpl( + std::string const &key, + char const value[], + internal::SetAttributeMode setAttributeMode) { - return this->setAttribute(key, std::string(value)); + return this->setAttributeImpl(key, std::string(value), setAttributeMode); } template diff --git a/src/backend/Attributable.cpp b/src/backend/Attributable.cpp index d037ad68bc..44238b161d 100644 --- a/src/backend/Attributable.cpp +++ b/src/backend/Attributable.cpp @@ -299,96 +299,183 @@ void Attributable::readAttributes(ReadMode mode) } std::array arr; std::copy_n(vector.begin(), 7, arr.begin()); - setAttribute(key, std::move(arr)); + setAttributeImpl( + key, + std::move(arr), + internal::SetAttributeMode::WhileReadingAttributes); } else { - setAttribute(key, std::move(vector)); + setAttributeImpl( + key, + std::move(vector), + internal::SetAttributeMode::WhileReadingAttributes); } }; switch (*aRead.dtype) { case DT::CHAR: - setAttribute(att, a.get()); + setAttributeImpl( + att, + a.get(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::UCHAR: - setAttribute(att, a.get()); + setAttributeImpl( + att, + a.get(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::SHORT: - setAttribute(att, a.get()); + setAttributeImpl( + att, + a.get(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::INT: - setAttribute(att, a.get()); + setAttributeImpl( + att, + a.get(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::LONG: - setAttribute(att, a.get()); + setAttributeImpl( + att, + a.get(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::LONGLONG: - setAttribute(att, a.get()); + setAttributeImpl( + att, + a.get(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::USHORT: - setAttribute(att, a.get()); + setAttributeImpl( + att, + a.get(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::UINT: - setAttribute(att, a.get()); + setAttributeImpl( + att, + a.get(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::ULONG: - setAttribute(att, a.get()); + setAttributeImpl( + att, + a.get(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::ULONGLONG: - setAttribute(att, a.get()); + setAttributeImpl( + att, + a.get(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::FLOAT: - setAttribute(att, a.get()); + setAttributeImpl( + att, + a.get(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::DOUBLE: - setAttribute(att, a.get()); + setAttributeImpl( + att, + a.get(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::LONG_DOUBLE: - setAttribute(att, a.get()); + setAttributeImpl( + att, + a.get(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::CFLOAT: - setAttribute(att, a.get >()); + setAttributeImpl( + att, + a.get >(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::CDOUBLE: - setAttribute(att, a.get >()); + setAttributeImpl( + att, + a.get >(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::CLONG_DOUBLE: - setAttribute(att, a.get >()); + setAttributeImpl( + att, + a.get >(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::STRING: - setAttribute(att, a.get()); + setAttributeImpl( + att, + a.get(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::VEC_CHAR: - setAttribute(att, a.get >()); + setAttributeImpl( + att, + a.get >(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::VEC_SHORT: - setAttribute(att, a.get >()); + setAttributeImpl( + att, + a.get >(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::VEC_INT: - setAttribute(att, a.get >()); + setAttributeImpl( + att, + a.get >(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::VEC_LONG: - setAttribute(att, a.get >()); + setAttributeImpl( + att, + a.get >(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::VEC_LONGLONG: - setAttribute(att, a.get >()); + setAttributeImpl( + att, + a.get >(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::VEC_UCHAR: - setAttribute(att, a.get >()); + setAttributeImpl( + att, + a.get >(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::VEC_USHORT: - setAttribute(att, a.get >()); + setAttributeImpl( + att, + a.get >(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::VEC_UINT: - setAttribute(att, a.get >()); + setAttributeImpl( + att, + a.get >(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::VEC_ULONG: - setAttribute(att, a.get >()); + setAttributeImpl( + att, + a.get >(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::VEC_ULONGLONG: - setAttribute(att, a.get >()); + setAttributeImpl( + att, + a.get >(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::VEC_FLOAT: guardUnitDimension(att, a.get >()); @@ -400,23 +487,40 @@ void Attributable::readAttributes(ReadMode mode) guardUnitDimension(att, a.get >()); break; case DT::VEC_CFLOAT: - setAttribute(att, a.get > >()); + setAttributeImpl( + att, + a.get > >(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::VEC_CDOUBLE: - setAttribute(att, a.get > >()); + setAttributeImpl( + att, + a.get > >(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::VEC_CLONG_DOUBLE: - setAttribute( - att, a.get > >()); + setAttributeImpl( + att, + a.get > >(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::VEC_STRING: - setAttribute(att, a.get >()); + setAttributeImpl( + att, + a.get >(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::ARR_DBL_7: - setAttribute(att, a.get >()); + setAttributeImpl( + att, + a.get >(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::BOOL: - setAttribute(att, a.get()); + setAttributeImpl( + att, + a.get(), + internal::SetAttributeMode::WhileReadingAttributes); break; case DT::UNDEFINED: throw std::runtime_error("Invalid Attribute datatype during read");