Skip to content

Commit 2eacc9b

Browse files
committed
Use a std::optional for BaseRecordComponentData::m_dataset
1 parent a6f5131 commit 2eacc9b

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
@@ -348,7 +348,13 @@ RecordComponent::storeChunk( Offset o, Extent e, F && createBuffer )
348348
dCreate.name = rc.m_name;
349349
dCreate.extent = getExtent();
350350
dCreate.dtype = getDatatype();
351-
dCreate.options = rc.m_dataset.options;
351+
if (!rc.m_dataset.has_value())
352+
{
353+
throw error::WrongAPIUsage(
354+
"[RecordComponent] Must specify dataset type and extent before "
355+
"using storeChunk() (see RecordComponent::resetDataset()).");
356+
}
357+
dCreate.options = rc.m_dataset.value().options;
352358
IOHandler()->enqueue(IOTask(this, dCreate));
353359
}
354360
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
}
@@ -213,11 +240,11 @@ void RecordComponent::flush(
213240
/*
214241
* This catches when a user forgets to use resetDataset.
215242
*/
216-
if (rc.m_dataset.dtype == Datatype::UNDEFINED)
243+
if (!rc.m_dataset.has_value())
217244
{
218245
throw error::WrongAPIUsage(
219-
"[RecordComponent] Must set specific datatype (Use "
220-
"resetDataset call).");
246+
"[RecordComponent] Must specify dataset type and extent before "
247+
"flushing (see RecordComponent::resetDataset()).");
221248
}
222249
if (!written())
223250
{
@@ -243,7 +270,7 @@ void RecordComponent::flush(
243270
dCreate.name = name;
244271
dCreate.extent = getExtent();
245272
dCreate.dtype = getDatatype();
246-
dCreate.options = rc.m_dataset.options;
273+
dCreate.options = rc.m_dataset.value().options;
247274
IOHandler()->enqueue(IOTask(this, dCreate));
248275
}
249276
}
@@ -262,7 +289,7 @@ void RecordComponent::flush(
262289
else
263290
{
264291
Parameter<Operation::EXTEND_DATASET> pExtend;
265-
pExtend.extent = rc.m_dataset.extent;
292+
pExtend.extent = rc.m_dataset.value().extent;
266293
IOHandler()->enqueue(IOTask(this, std::move(pExtend)));
267294
rc.m_hasBeenExtended = false;
268295
}

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}
@@ -94,13 +102,20 @@ void PatchRecordComponent::flush(
94102
}
95103
else
96104
{
105+
if (!rc.m_dataset.has_value())
106+
{
107+
throw error::WrongAPIUsage(
108+
"[PatchRecordComponent] Must specify dataset type and extent "
109+
"before "
110+
"flushing (see RecordComponent::resetDataset()).");
111+
}
97112
if (!written())
98113
{
99114
Parameter<Operation::CREATE_DATASET> dCreate;
100115
dCreate.name = name;
101116
dCreate.extent = getExtent();
102117
dCreate.dtype = getDatatype();
103-
dCreate.options = rc.m_dataset.options;
118+
dCreate.options = rc.m_dataset.value().options;
104119
IOHandler()->enqueue(IOTask(this, dCreate));
105120
}
106121

0 commit comments

Comments
 (0)