Skip to content

Commit f9663b6

Browse files
Enable empty string attributes (#1338)
* Enable empty string attributes * Disable empty strings exclusively for ADIOS1
1 parent e5b1245 commit f9663b6

File tree

7 files changed

+82
-219
lines changed

7 files changed

+82
-219
lines changed

include/openPMD/backend/Attributable.hpp

Lines changed: 4 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -81,39 +81,6 @@ namespace internal
8181
A_MAP m_attributes;
8282
};
8383

84-
enum class SetAttributeMode : char
85-
{
86-
WhileReadingAttributes,
87-
FromPublicAPICall
88-
};
89-
90-
/** Verify values of attributes in the frontend
91-
*
92-
* verify string attributes are not empty (backend restriction, e.g., HDF5)
93-
*/
94-
template <typename T>
95-
inline void attr_value_check(
96-
std::string const /* key */, T /* value */, SetAttributeMode)
97-
{}
98-
99-
template <>
100-
inline void attr_value_check(
101-
std::string const key, std::string const value, SetAttributeMode mode)
102-
{
103-
switch (mode)
104-
{
105-
case SetAttributeMode::FromPublicAPICall:
106-
if (value.empty())
107-
throw std::runtime_error(
108-
"[setAttribute] Value for string attribute '" + key +
109-
"' must not be empty!");
110-
break;
111-
case SetAttributeMode::WhileReadingAttributes:
112-
// no checks while reading
113-
break;
114-
}
115-
}
116-
11784
template <typename>
11885
class BaseRecordData;
11986
} // namespace internal
@@ -289,12 +256,6 @@ OPENPMD_protected
289256

290257
void flushAttributes(internal::FlushParams const &);
291258

292-
template <typename T>
293-
bool setAttributeImpl(
294-
std::string const &key, T value, internal::SetAttributeMode);
295-
bool setAttributeImpl(
296-
std::string const &key, char const value[], internal::SetAttributeMode);
297-
298259
enum ReadMode
299260
{
300261
/**
@@ -435,30 +396,11 @@ OPENPMD_protected
435396
virtual void linkHierarchy(Writable &w);
436397
}; // Attributable
437398

438-
template <typename T>
439-
inline bool Attributable::setAttribute(std::string const &key, T value)
440-
{
441-
return setAttributeImpl(
442-
key, std::move(value), internal::SetAttributeMode::FromPublicAPICall);
443-
}
444-
445-
inline bool
446-
Attributable::setAttribute(std::string const &key, char const value[])
447-
{
448-
return setAttributeImpl(
449-
key, value, internal::SetAttributeMode::FromPublicAPICall);
450-
}
451-
452399
// note: we explicitly instantiate Attributable::setAttributeImpl for all T in
453400
// Datatype in Attributable.cpp
454401
template <typename T>
455-
inline bool Attributable::setAttributeImpl(
456-
std::string const &key,
457-
T value,
458-
internal::SetAttributeMode setAttributeMode)
402+
inline bool Attributable::setAttribute(std::string const &key, T value)
459403
{
460-
internal::attr_value_check(key, value, setAttributeMode);
461-
462404
auto &attri = get();
463405
if (IOHandler() &&
464406
IOHandler()->m_seriesStatus == internal::SeriesStatus::Default &&
@@ -487,12 +429,10 @@ inline bool Attributable::setAttributeImpl(
487429
}
488430
}
489431

490-
inline bool Attributable::setAttributeImpl(
491-
std::string const &key,
492-
char const value[],
493-
internal::SetAttributeMode setAttributeMode)
432+
inline bool
433+
Attributable::setAttribute(std::string const &key, char const value[])
494434
{
495-
return this->setAttributeImpl(key, std::string(value), setAttributeMode);
435+
return this->setAttribute(key, std::string(value));
496436
}
497437

498438
template <typename T>

src/IO/ADIOS/CommonADIOS1IOHandler.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,11 @@ void CommonADIOS1IOHandlerImpl<ChildClass>::flush_attribute(
235235
}
236236
case DT::STRING: {
237237
auto const &v = att.get<std::string>();
238+
if (v.empty())
239+
{
240+
error::throwOperationUnsupportedInBackend(
241+
"ADIOS1", "Empty string attributes not supported.");
242+
}
238243
values = auxiliary::allocatePtr(Datatype::CHAR, v.length() + 1u);
239244
strcpy((char *)values.get(), v.c_str());
240245
break;
@@ -352,6 +357,11 @@ void CommonADIOS1IOHandlerImpl<ChildClass>::flush_attribute(
352357
auto const &vec = att.get<std::vector<std::string> >();
353358
for (size_t i = 0; i < vec.size(); ++i)
354359
{
360+
if (vec[i].empty())
361+
{
362+
error::throwOperationUnsupportedInBackend(
363+
"ADIOS1", "Empty string attributes not supported.");
364+
}
355365
size_t size = vec[i].size() + 1;
356366
ptr[i] = new char[size];
357367
strncpy(ptr[i], vec[i].c_str(), size);

src/IO/HDF5/HDF5Auxiliary.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,7 @@ hid_t openPMD::GetH5DataType::operator()(Attribute const &att)
111111
m_userTypes.at(typeid(std::complex<long double>).name()));
112112
case DT::STRING: {
113113
hid_t string_t_id = H5Tcopy(H5T_C_S1);
114-
size_t const max_len = att.get<std::string>().size();
115-
VERIFY(max_len > 0, "[HDF5] max_len must be >0 for STRING");
114+
size_t const max_len = att.get<std::string>().size() + 1;
116115
herr_t status = H5Tset_size(string_t_id, max_len);
117116
VERIFY(
118117
status >= 0,
@@ -123,7 +122,7 @@ hid_t openPMD::GetH5DataType::operator()(Attribute const &att)
123122
hid_t string_t_id = H5Tcopy(H5T_C_S1);
124123
size_t max_len = 0;
125124
for (std::string const &s : att.get<std::vector<std::string> >())
126-
max_len = std::max(max_len, s.size());
125+
max_len = std::max(max_len, s.size() + 1);
127126
VERIFY(max_len > 0, "[HDF5] max_len must be >0 for VEC_STRING");
128127
herr_t status = H5Tset_size(string_t_id, max_len);
129128
VERIFY(

src/IO/HDF5/HDF5IOHandler.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1621,8 +1621,8 @@ void HDF5IOHandlerImpl::writeAttribute(
16211621
auto vs = att.get<std::vector<std::string> >();
16221622
size_t max_len = 0;
16231623
for (std::string const &s : vs)
1624-
max_len = std::max(max_len, s.size());
1625-
std::unique_ptr<char[]> c_str(new char[max_len * vs.size()]);
1624+
max_len = std::max(max_len, s.size() + 1);
1625+
std::unique_ptr<char[]> c_str(new char[max_len * vs.size()]());
16261626
for (size_t i = 0; i < vs.size(); ++i)
16271627
strncpy(c_str.get() + i * max_len, vs[i].c_str(), max_len);
16281628
status = H5Awrite(attribute_id, dataType, c_str.get());

0 commit comments

Comments
 (0)