@@ -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 {
@@ -323,6 +341,13 @@ void RecordComponent::flush(
323341 {
324342 if (constant ())
325343 {
344+ if (!constant_component_write_shape ())
345+ {
346+ throw error::WrongAPIUsage (
347+ " Extended constant component from a previous shape to "
348+ " one that cannot be written (empty or with joined "
349+ " dimension)." );
350+ }
326351 bool isVBased = retrieveSeries ().iterationEncoding () ==
327352 IterationEncoding::variableBased;
328353 Parameter<Operation::WRITE_ATT> aWrite;
@@ -387,28 +412,35 @@ namespace
387412 };
388413} // namespace
389414
415+ inline void breakpoint ()
416+ {}
417+
390418void RecordComponent::readBase (bool require_unit_si)
391419{
392420 using DT = Datatype;
393- // auto & rc = get();
394- Parameter<Operation::READ_ATT> aRead;
421+ auto &rc = get ();
395422
396- if (constant () && !empty ())
397- {
398- aRead.name = " value" ;
399- IOHandler ()->enqueue (IOTask (this , aRead));
400- IOHandler ()->flush (internal::defaultFlushParams);
423+ readAttributes (ReadMode::FullyReread);
401424
402- Attribute a (*aRead.resource );
403- DT dtype = *aRead.dtype ;
425+ auto read_constant =
426+ [&]() // comment for forcing clang-format into putting a newline here
427+ {
428+ Attribute a = rc.readAttribute (" value" );
429+ DT dtype = a.dtype ;
404430 setWritten (false , Attributable::EnqueueAsynchronously::No);
405431 switchNonVectorType<MakeConstant>(dtype, *this , a);
406432 setWritten (true , Attributable::EnqueueAsynchronously::No);
407433
408- aRead.name = " shape" ;
409- IOHandler ()->enqueue (IOTask (this , aRead));
410- IOHandler ()->flush (internal::defaultFlushParams);
411- a = Attribute (*aRead.resource );
434+ if (!containsAttribute (" shape" ))
435+ {
436+ setWritten (false , Attributable::EnqueueAsynchronously::No);
437+ resetDataset (Dataset (dtype, {}));
438+ setWritten (true , Attributable::EnqueueAsynchronously::No);
439+
440+ return ;
441+ }
442+
443+ a = rc.attributes ().at (" shape" );
412444 Extent e;
413445
414446 // uint64_t check
@@ -418,7 +450,7 @@ void RecordComponent::readBase(bool require_unit_si)
418450 else
419451 {
420452 std::ostringstream oss;
421- oss << " Unexpected datatype (" << *aRead .dtype
453+ oss << " Unexpected datatype (" << a .dtype
422454 << " ) for attribute 'shape' (" << determineDatatype<uint64_t >()
423455 << " aka uint64_t)" ;
424456 throw error::ReadError (
@@ -431,9 +463,13 @@ void RecordComponent::readBase(bool require_unit_si)
431463 setWritten (false , Attributable::EnqueueAsynchronously::No);
432464 resetDataset (Dataset (dtype, e));
433465 setWritten (true , Attributable::EnqueueAsynchronously::No);
434- }
466+ };
435467
436- readAttributes (ReadMode::FullyReread);
468+ if (constant () && !empty ())
469+ {
470+ breakpoint ();
471+ read_constant ();
472+ }
437473
438474 if (require_unit_si)
439475 {
@@ -447,16 +483,17 @@ void RecordComponent::readBase(bool require_unit_si)
447483 " '" +
448484 myPath ().openPMDPath () + " '." );
449485 }
450- if (!getAttribute (" unitSI" ).getOptional <double >().has_value ())
486+ if (auto attr = getAttribute (" unitSI" );
487+ !attr.getOptional <double >().has_value ())
451488 {
452489 throw error::ReadError (
453490 error::AffectedObject::Attribute,
454491 error::Reason::UnexpectedContent,
455492 {},
456493 " Unexpected Attribute datatype for 'unitSI' (expected double, "
457494 " found " +
458- datatypeToString (Attribute (*aRead. resource ). dtype ) +
459- " ) in ' " + myPath ().openPMDPath () + " '." );
495+ datatypeToString (attr. dtype ) + " ) in ' " +
496+ myPath ().openPMDPath () + " '." );
460497 }
461498 }
462499}
0 commit comments