@@ -108,7 +108,14 @@ RecordComponent &RecordComponent::resetDataset(Dataset d)
108108 throw std::runtime_error (" Dataset extent must be at least 1D." );
109109 if (d.empty ())
110110 {
111- if (d.dtype != Datatype::UNDEFINED)
111+ if (d.extent .empty ())
112+ {
113+ throw error::Internal (
114+ " A zero-dimensional dataset is not to be considered empty, but "
115+ " undefined. This is an internal safeguard against future "
116+ " changes that might not consider this." );
117+ }
118+ else if (d.dtype != Datatype::UNDEFINED)
112119 {
113120 return makeEmpty (std::move (d));
114121 }
@@ -280,6 +287,13 @@ void RecordComponent::flush(
280287 {
281288 setUnitSI (1 );
282289 }
290+ auto constant_component_write_shape = [&]() {
291+ auto extent = getExtent ();
292+ return !extent.empty () &&
293+ std::none_of (extent.begin (), extent.end (), [](auto val) {
294+ return val == Dataset::JOINED_DIMENSION;
295+ });
296+ };
283297 if (!written ())
284298 {
285299 if (constant ())
@@ -299,16 +313,20 @@ void RecordComponent::flush(
299313 Operation::WRITE_ATT>::ChangesOverSteps::IfPossible;
300314 }
301315 IOHandler ()->enqueue (IOTask (this , aWrite));
302- aWrite.name = " shape" ;
303- Attribute a (getExtent ());
304- aWrite.dtype = a.dtype ;
305- aWrite.resource = a.getResource ();
306- if (isVBased)
316+ if (constant_component_write_shape ())
307317 {
308- aWrite.changesOverSteps = Parameter<
309- Operation::WRITE_ATT>::ChangesOverSteps::IfPossible;
318+
319+ aWrite.name = " shape" ;
320+ Attribute a (getExtent ());
321+ aWrite.dtype = a.dtype ;
322+ aWrite.resource = a.getResource ();
323+ if (isVBased)
324+ {
325+ aWrite.changesOverSteps = Parameter<
326+ Operation::WRITE_ATT>::ChangesOverSteps::IfPossible;
327+ }
328+ IOHandler ()->enqueue (IOTask (this , aWrite));
310329 }
311- IOHandler ()->enqueue (IOTask (this , aWrite));
312330 }
313331 else
314332 {
@@ -326,6 +344,13 @@ void RecordComponent::flush(
326344 {
327345 if (constant ())
328346 {
347+ if (!constant_component_write_shape ())
348+ {
349+ throw error::WrongAPIUsage (
350+ " Extended constant component from a previous shape to "
351+ " one that cannot be written (empty or with joined "
352+ " dimension)." );
353+ }
329354 bool isVBased = retrieveSeries ().iterationEncoding () ==
330355 IterationEncoding::variableBased;
331356 Parameter<Operation::WRITE_ATT> aWrite;
@@ -390,28 +415,35 @@ namespace
390415 };
391416} // namespace
392417
418+ inline void breakpoint ()
419+ {}
420+
393421void RecordComponent::readBase (bool require_unit_si)
394422{
395423 using DT = Datatype;
396- // auto & rc = get();
397- Parameter<Operation::READ_ATT> aRead;
424+ auto &rc = get ();
398425
399- if (constant () && !empty ())
400- {
401- aRead.name = " value" ;
402- IOHandler ()->enqueue (IOTask (this , aRead));
403- IOHandler ()->flush (internal::defaultFlushParams);
426+ readAttributes (ReadMode::FullyReread);
404427
405- Attribute a (*aRead.resource );
406- DT dtype = *aRead.dtype ;
428+ auto read_constant =
429+ [&]() // comment for forcing clang-format into putting a newline here
430+ {
431+ Attribute a = rc.readAttribute (" value" );
432+ DT dtype = a.dtype ;
407433 setWritten (false , Attributable::EnqueueAsynchronously::No);
408434 switchNonVectorType<MakeConstant>(dtype, *this , a);
409435 setWritten (true , Attributable::EnqueueAsynchronously::No);
410436
411- aRead.name = " shape" ;
412- IOHandler ()->enqueue (IOTask (this , aRead));
413- IOHandler ()->flush (internal::defaultFlushParams);
414- a = Attribute (*aRead.resource );
437+ if (!containsAttribute (" shape" ))
438+ {
439+ setWritten (false , Attributable::EnqueueAsynchronously::No);
440+ resetDataset (Dataset (dtype, {}));
441+ setWritten (true , Attributable::EnqueueAsynchronously::No);
442+
443+ return ;
444+ }
445+
446+ a = rc.attributes ().at (" shape" );
415447 Extent e;
416448
417449 // uint64_t check
@@ -421,7 +453,7 @@ void RecordComponent::readBase(bool require_unit_si)
421453 else
422454 {
423455 std::ostringstream oss;
424- oss << " Unexpected datatype (" << *aRead .dtype
456+ oss << " Unexpected datatype (" << a .dtype
425457 << " ) for attribute 'shape' (" << determineDatatype<uint64_t >()
426458 << " aka uint64_t)" ;
427459 throw error::ReadError (
@@ -434,9 +466,13 @@ void RecordComponent::readBase(bool require_unit_si)
434466 setWritten (false , Attributable::EnqueueAsynchronously::No);
435467 resetDataset (Dataset (dtype, e));
436468 setWritten (true , Attributable::EnqueueAsynchronously::No);
437- }
469+ };
438470
439- readAttributes (ReadMode::FullyReread);
471+ if (constant () && !empty ())
472+ {
473+ breakpoint ();
474+ read_constant ();
475+ }
440476
441477 if (require_unit_si)
442478 {
@@ -450,16 +486,17 @@ void RecordComponent::readBase(bool require_unit_si)
450486 " '" +
451487 myPath ().openPMDPath () + " '." );
452488 }
453- if (!getAttribute (" unitSI" ).getOptional <double >().has_value ())
489+ if (auto attr = getAttribute (" unitSI" );
490+ !attr.getOptional <double >().has_value ())
454491 {
455492 throw error::ReadError (
456493 error::AffectedObject::Attribute,
457494 error::Reason::UnexpectedContent,
458495 {},
459496 " Unexpected Attribute datatype for 'unitSI' (expected double, "
460497 " found " +
461- datatypeToString (Attribute (*aRead. resource ). dtype ) +
462- " ) in ' " + myPath ().openPMDPath () + " '." );
498+ datatypeToString (attr. dtype ) + " ) in ' " +
499+ myPath ().openPMDPath () + " '." );
463500 }
464501 }
465502}
0 commit comments