Skip to content

Commit c7662c9

Browse files
committed
Use a std::optional for BaseRecordComponentData::m_dataset
1 parent 599ac5a commit c7662c9

File tree

5 files changed

+94
-24
lines changed

5 files changed

+94
-24
lines changed

include/openPMD/RecordComponent.tpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,13 @@ RecordComponent::storeChunk( Offset o, Extent e, F && createBuffer )
347347
dCreate.name = rc.m_name;
348348
dCreate.extent = getExtent();
349349
dCreate.dtype = getDatatype();
350-
dCreate.options = rc.m_dataset.options;
350+
if (!rc.m_dataset.has_value())
351+
{
352+
throw error::WrongAPIUsage(
353+
"[RecordComponent] Must specify dataset type and extent before "
354+
"using storeChunk() (see RecordComponent::resetDataset()).");
355+
}
356+
dCreate.options = rc.m_dataset.value().options;
351357
IOHandler()->enqueue(IOTask(this, dCreate));
352358
}
353359
Parameter< Operation::GET_BUFFER_VIEW > getBufferView;

include/openPMD/backend/BaseRecordComponent.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
#include "openPMD/Error.hpp"
2525
#include "openPMD/backend/Attributable.hpp"
2626

27+
#include <optional>
28+
2729
// expose private and protected members for invasive testing
2830
#ifndef OPENPMD_protected
2931
#define OPENPMD_protected protected:
@@ -39,7 +41,7 @@ namespace internal
3941
/**
4042
* The type and extent of the dataset defined by this component.
4143
*/
42-
Dataset m_dataset{Datatype::UNDEFINED, {}};
44+
std::optional<Dataset> m_dataset;
4345
/**
4446
* True if this is defined as a constant record component as specified
4547
* in the openPMD standard.

src/RecordComponent.cpp

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ namespace internal
4242
RecordComponent impl{
4343
std::shared_ptr<RecordComponentData>{this, [](auto const *) {}}};
4444
impl.setUnitSI(1);
45-
impl.resetDataset(Dataset(Datatype::CHAR, {1}));
4645
}
4746
} // namespace internal
4847

@@ -71,11 +70,17 @@ RecordComponent &RecordComponent::resetDataset(Dataset d)
7170
auto &rc = get();
7271
if (written())
7372
{
73+
if (!rc.m_dataset.has_value())
74+
{
75+
throw error::Internal(
76+
"Internal control flow error: Written record component must "
77+
"have defined datatype and extent.");
78+
}
7479
if (d.dtype == Datatype::UNDEFINED)
7580
{
76-
d.dtype = rc.m_dataset.dtype;
81+
d.dtype = rc.m_dataset.value().dtype;
7782
}
78-
else if (d.dtype != rc.m_dataset.dtype)
83+
else if (d.dtype != rc.m_dataset.value().dtype)
7984
{
8085
throw std::runtime_error(
8186
"Cannot change the datatype of a dataset.");
@@ -99,7 +104,7 @@ RecordComponent &RecordComponent::resetDataset(Dataset d)
99104
rc.m_isEmpty = false;
100105
if (written())
101106
{
102-
rc.m_dataset.extend(std::move(d.extent));
107+
rc.m_dataset.value().extend(std::move(d.extent));
103108
}
104109
else
105110
{
@@ -112,12 +117,28 @@ RecordComponent &RecordComponent::resetDataset(Dataset d)
112117

113118
uint8_t RecordComponent::getDimensionality() const
114119
{
115-
return get().m_dataset.rank;
120+
auto &rc = get();
121+
if (rc.m_dataset.has_value())
122+
{
123+
return rc.m_dataset.value().rank;
124+
}
125+
else
126+
{
127+
return 1;
128+
}
116129
}
117130

118131
Extent RecordComponent::getExtent() const
119132
{
120-
return get().m_dataset.extent;
133+
auto &rc = get();
134+
if (rc.m_dataset.has_value())
135+
{
136+
return rc.m_dataset.value().extent;
137+
}
138+
else
139+
{
140+
return {1};
141+
}
121142
}
122143

123144
namespace detail
@@ -149,6 +170,12 @@ RecordComponent &RecordComponent::makeEmpty(Dataset d)
149170
auto &rc = get();
150171
if (written())
151172
{
173+
if (!rc.m_dataset.has_value())
174+
{
175+
throw error::Internal(
176+
"Internal control flow error: Written record component must "
177+
"have defined datatype and extent.");
178+
}
152179
if (!constant())
153180
{
154181
throw std::runtime_error(
@@ -158,30 +185,30 @@ RecordComponent &RecordComponent::makeEmpty(Dataset d)
158185
}
159186
if (d.dtype == Datatype::UNDEFINED)
160187
{
161-
d.dtype = rc.m_dataset.dtype;
188+
d.dtype = rc.m_dataset.value().dtype;
162189
}
163-
else if (d.dtype != rc.m_dataset.dtype)
190+
else if (d.dtype != rc.m_dataset.value().dtype)
164191
{
165192
throw std::runtime_error(
166193
"Cannot change the datatype of a dataset.");
167194
}
168-
rc.m_dataset.extend(std::move(d.extent));
195+
rc.m_dataset.value().extend(std::move(d.extent));
169196
rc.m_hasBeenExtended = true;
170197
}
171198
else
172199
{
173200
rc.m_dataset = std::move(d);
174201
}
175202

176-
if (rc.m_dataset.extent.size() == 0)
203+
if (rc.m_dataset.value().extent.size() == 0)
177204
throw std::runtime_error("Dataset extent must be at least 1D.");
178205

179206
rc.m_isEmpty = true;
180207
dirty() = true;
181208
if (!written())
182209
{
183210
switchType<detail::DefaultValue<RecordComponent> >(
184-
rc.m_dataset.dtype, *this);
211+
rc.m_dataset.value().dtype, *this);
185212
}
186213
return *this;
187214
}
@@ -215,11 +242,11 @@ void RecordComponent::flush(
215242
/*
216243
* This catches when a user forgets to use resetDataset.
217244
*/
218-
if (rc.m_dataset.dtype == Datatype::UNDEFINED)
245+
if (!rc.m_dataset.has_value())
219246
{
220247
throw error::WrongAPIUsage(
221-
"[RecordComponent] Must set specific datatype (Use "
222-
"resetDataset call).");
248+
"[RecordComponent] Must specify dataset type and extent before "
249+
"flushing (see RecordComponent::resetDataset()).");
223250
}
224251
if (!written())
225252
{
@@ -245,7 +272,7 @@ void RecordComponent::flush(
245272
dCreate.name = name;
246273
dCreate.extent = getExtent();
247274
dCreate.dtype = getDatatype();
248-
dCreate.options = rc.m_dataset.options;
275+
dCreate.options = rc.m_dataset.value().options;
249276
IOHandler()->enqueue(IOTask(this, dCreate));
250277
}
251278
}
@@ -264,7 +291,7 @@ void RecordComponent::flush(
264291
else
265292
{
266293
Parameter<Operation::EXTEND_DATASET> pExtend;
267-
pExtend.extent = rc.m_dataset.extent;
294+
pExtend.extent = rc.m_dataset.value().extent;
268295
IOHandler()->enqueue(IOTask(this, std::move(pExtend)));
269296
rc.m_hasBeenExtended = false;
270297
}

src/backend/BaseRecordComponent.cpp

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,29 @@ BaseRecordComponent &BaseRecordComponent::resetDatatype(Datatype d)
3535
"A Records Datatype can not (yet) be changed after it has been "
3636
"written.");
3737

38-
get().m_dataset.dtype = d;
38+
auto &rc = get();
39+
if (rc.m_dataset.has_value())
40+
{
41+
rc.m_dataset.value().dtype = d;
42+
}
43+
else
44+
{
45+
rc.m_dataset = Dataset{d, {1}};
46+
}
3947
return *this;
4048
}
4149

4250
Datatype BaseRecordComponent::getDatatype() const
4351
{
44-
return get().m_dataset.dtype;
52+
auto &rc = get();
53+
if (rc.m_dataset.has_value())
54+
{
55+
return rc.m_dataset.value().dtype;
56+
}
57+
else
58+
{
59+
return Datatype::UNDEFINED;
60+
}
4561
}
4662

4763
bool BaseRecordComponent::constant() const
@@ -54,8 +70,12 @@ ChunkTable BaseRecordComponent::availableChunks()
5470
auto &rc = get();
5571
if (rc.m_isConstant)
5672
{
57-
Offset offset(rc.m_dataset.extent.size(), 0);
58-
return ChunkTable{{std::move(offset), rc.m_dataset.extent}};
73+
if (!rc.m_dataset.has_value())
74+
{
75+
return ChunkTable{};
76+
}
77+
Offset offset(rc.m_dataset.value().extent.size(), 0);
78+
return ChunkTable{{std::move(offset), rc.m_dataset.value().extent}};
5979
}
6080
containingIteration().open();
6181
Parameter<Operation::AVAILABLE_CHUNKS> param;

src/backend/PatchRecordComponent.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,15 @@ uint8_t PatchRecordComponent::getDimensionality() const
6767

6868
Extent PatchRecordComponent::getExtent() const
6969
{
70-
return get().m_dataset.extent;
70+
auto &rc = get();
71+
if (rc.m_dataset.has_value())
72+
{
73+
return rc.m_dataset.value().extent;
74+
}
75+
else
76+
{
77+
return {1};
78+
}
7179
}
7280

7381
PatchRecordComponent::PatchRecordComponent() : BaseRecordComponent{nullptr}
@@ -97,13 +105,20 @@ void PatchRecordComponent::flush(
97105
case Access::READ_WRITE:
98106
case Access::CREATE:
99107
case Access::APPEND: {
108+
if (!rc.m_dataset.has_value())
109+
{
110+
throw error::WrongAPIUsage(
111+
"[PatchRecordComponent] Must specify dataset type and extent "
112+
"before "
113+
"flushing (see RecordComponent::resetDataset()).");
114+
}
100115
if (!written())
101116
{
102117
Parameter<Operation::CREATE_DATASET> dCreate;
103118
dCreate.name = name;
104119
dCreate.extent = getExtent();
105120
dCreate.dtype = getDatatype();
106-
dCreate.options = rc.m_dataset.options;
121+
dCreate.options = rc.m_dataset.value().options;
107122
IOHandler()->enqueue(IOTask(this, dCreate));
108123
}
109124

0 commit comments

Comments
 (0)