Skip to content

Commit 03b283b

Browse files
committed
Make the default specification more flexible
prep for reading
1 parent 2115ede commit 03b283b

2 files changed

Lines changed: 142 additions & 31 deletions

File tree

include/openPMD/backend/ScientificDefaults.hpp

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include "openPMD/IO/Access.hpp"
4+
#include <iostream>
45
#include <type_traits>
56

67
namespace openPMD::detail
@@ -27,6 +28,89 @@ using CallResult_t = typename IsCallable<F>::type;
2728

2829
namespace openPMD::internal
2930
{
31+
template <typename, typename, typename>
32+
struct ConfigAttributeWithSetter;
33+
34+
template <typename RecordType, typename GetDefaultValue>
35+
struct ConfigAttribute
36+
{
37+
using DefaultValue = detail::CallResult_t<GetDefaultValue>;
38+
template <typename S>
39+
using SetterType = RecordType &(
40+
RecordType::
41+
*)(std::conditional_t<
42+
std::is_void_v<S>,
43+
std::remove_reference_t<detail::CallResult_t<GetDefaultValue>>,
44+
S>);
45+
46+
RecordType &child;
47+
char const *attrName;
48+
GetDefaultValue &&getDefaultValue;
49+
50+
ConfigAttribute(
51+
RecordType &child_in,
52+
char const *attrName_in,
53+
GetDefaultValue &&getDefaultValue_in)
54+
: child(child_in)
55+
, attrName(attrName_in)
56+
, getDefaultValue(std::forward<GetDefaultValue>(getDefaultValue_in))
57+
{}
58+
59+
ConfigAttribute(ConfigAttribute const &) = delete;
60+
ConfigAttribute(ConfigAttribute &&) = default;
61+
62+
ConfigAttribute &operator=(ConfigAttribute const &) = delete;
63+
ConfigAttribute &operator=(ConfigAttribute &&) = default;
64+
65+
template <typename S = void>
66+
[[nodiscard]] auto
67+
withSetter(SetterType<S>) && -> ConfigAttributeWithSetter<
68+
RecordType,
69+
GetDefaultValue,
70+
SetterType<S>>;
71+
72+
auto get() -> DefaultValue
73+
{
74+
if constexpr (detail::IsCallable_v<GetDefaultValue>)
75+
{
76+
return std::forward<GetDefaultValue>(getDefaultValue)();
77+
}
78+
else
79+
{
80+
return std::forward<GetDefaultValue>(getDefaultValue);
81+
}
82+
}
83+
};
84+
85+
template <
86+
typename RecordType,
87+
typename GetDefaultValue,
88+
typename SetDefaultValue>
89+
struct ConfigAttributeWithSetter : ConfigAttribute<RecordType, GetDefaultValue>
90+
{
91+
using parent_t = ConfigAttribute<RecordType, GetDefaultValue>;
92+
using DefaultValue = typename parent_t::DefaultValue;
93+
94+
ConfigAttributeWithSetter(parent_t &&par, SetDefaultValue setter_in)
95+
: parent_t(std::move(par)), setter(setter_in)
96+
{}
97+
98+
SetDefaultValue setter;
99+
void set(DefaultValue &&val)
100+
{
101+
(this->child.*setter)(std::forward<DefaultValue>(val));
102+
}
103+
104+
void operator()()
105+
{
106+
if (this->child.containsAttribute(this->attrName))
107+
{
108+
return;
109+
}
110+
set(this->get());
111+
}
112+
};
113+
30114
template <typename Child> // CRT
31115
class ScientificDefaults
32116
{
@@ -37,6 +121,17 @@ class ScientificDefaults
37121
template <typename F>
38122
using setter_t = Child &(Child::*)();
39123

124+
template <typename GetDefaultValue>
125+
[[nodiscard]] auto
126+
defaultAttribute(char const *attrName, GetDefaultValue &&getDefaultValue)
127+
-> ConfigAttribute<Child, GetDefaultValue>
128+
{
129+
return ConfigAttribute{
130+
asChild(),
131+
attrName,
132+
std::forward<GetDefaultValue>(getDefaultValue)};
133+
}
134+
40135
template <typename Setter = void, typename V>
41136
void addDefaultFor_worker(char const *key, V &&value, Setter &&setter);
42137

src/backend/ScientificDefaults.cpp

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,18 @@
1818

1919
namespace openPMD::internal
2020
{
21+
template <typename RecordType, typename GetDefaultValue>
22+
template <typename S>
23+
auto ConfigAttribute<RecordType, GetDefaultValue>::withSetter(
24+
SetterType<S> setter)
25+
&& -> ConfigAttributeWithSetter<RecordType, GetDefaultValue, SetterType<S>>
26+
{
27+
return ConfigAttributeWithSetter<
28+
RecordType,
29+
GetDefaultValue,
30+
SetterType<S>>{std::move(*this), setter};
31+
}
32+
2133
template <typename Child>
2234
auto ScientificDefaults<Child>::asChild() -> Child &
2335
{
@@ -189,19 +201,21 @@ void ScientificDefaults<Child>::addDefaults()
189201

190202
if constexpr (std::is_same_v<Child, Iteration>)
191203
{
192-
addDefaultFor("time", 0., &Iteration::setTime);
193-
addDefaultFor("dt", 1., &Iteration::setDt);
194-
addDefaultFor("timeUnitSI", 1.0, &Iteration::setTimeUnitSI);
204+
defaultAttribute("time", 0.).withSetter (&Iteration::setTime)();
205+
defaultAttribute("dt", 1.).withSetter (&Iteration::setDt)();
206+
defaultAttribute("timeUnitSI", 1.0)
207+
.withSetter (&Iteration::setTimeUnitSI)();
195208
}
196209
else if constexpr (std::is_same_v<Child, Mesh>)
197210
{
198211
auto dimensionality = asChild().retrieveDimensionality();
199212

200-
addDefaultFor("timeOffset", 0.f, &Mesh::setTimeOffset);
201-
addDefaultFor(
202-
"geometry", Mesh::Geometry::cartesian, &Mesh::setGeometry);
203-
addDefaultFor("dataOrder", Mesh::DataOrder::C, &Mesh::setDataOrder);
204-
addDefaultFor<std::vector<std::string> const &>(
213+
defaultAttribute("timeOffset", 0.f).withSetter (&Mesh::setTimeOffset)();
214+
defaultAttribute("geometry", Mesh::Geometry::cartesian)
215+
.withSetter (&Mesh::setGeometry)();
216+
defaultAttribute("dataOrder", Mesh::DataOrder::C)
217+
.withSetter (&Mesh::setDataOrder)();
218+
defaultAttribute(
205219
"axisLabels",
206220
[&]() -> std::vector<std::string> {
207221
switch (dimensionality)
@@ -233,9 +247,10 @@ void ScientificDefaults<Child>::addDefaults()
233247
}
234248
}
235249
return std::vector<std::string>{"x", "y", "z"};
236-
},
237-
&Mesh::setAxisLabels);
238-
addDefaultFor<std::vector<double> const &>(
250+
})
251+
.template withSetter<std::vector<std::string> const &> (
252+
&Mesh::setAxisLabels)();
253+
defaultAttribute(
239254
"gridSpacing",
240255
[&]() {
241256
if (dimensionality < 100)
@@ -246,9 +261,10 @@ void ScientificDefaults<Child>::addDefaults()
246261
{
247262
return std::vector<double>{1.0};
248263
}
249-
},
250-
&Mesh::setGridSpacing);
251-
addDefaultFor<std::vector<double> const &>(
264+
})
265+
.template withSetter<std::vector<double> const &> (
266+
&Mesh::setGridSpacing)();
267+
defaultAttribute(
252268
"gridGlobalOffset",
253269
[&]() {
254270
if (dimensionality < 100)
@@ -259,14 +275,16 @@ void ScientificDefaults<Child>::addDefaults()
259275
{
260276
return std::vector<double>{0.0};
261277
}
262-
},
263-
&Mesh::setGridGlobalOffset);
278+
})
279+
.template withSetter<std::vector<double> const &> (
280+
&Mesh::setGridGlobalOffset)();
264281

265282
addParentDefaults<BaseRecord<MeshRecordComponent>>();
266283
}
267284
else if constexpr (std::is_same_v<Child, Record>)
268285
{
269-
addDefaultFor("timeOffset", 0.f, &Record::setTimeOffset);
286+
defaultAttribute("timeOffset", 0.f)
287+
.withSetter (&Record::setTimeOffset)();
270288
auto const &keyInParent = asChild().writable().ownKeyWithinParent;
271289

272290
if (keyInParent == "position" || keyInParent == "positionOffset")
@@ -287,25 +305,23 @@ void ScientificDefaults<Child>::addDefaults()
287305
}
288306
else if constexpr (std::is_same_v<Child, RecordComponent>)
289307
{
290-
addDefaultFor("unitSI", 1.0, &RecordComponent::setUnitSI);
308+
defaultAttribute("unitSI", 1.0)
309+
.withSetter (&RecordComponent::setUnitSI)();
291310
}
292311
else if constexpr (std::is_same_v<Child, MeshRecordComponent>)
293312
{
294313
// position
295314
auto dimensionality = asChild().getDimensionality();
296-
addDefaultFor(
297-
"position",
298-
[&]() {
299-
if (dimensionality < 100)
300-
{
301-
return std::vector<double>(dimensionality, 0.5);
302-
}
303-
else
304-
{
305-
return std::vector<double>{0.0};
306-
}
307-
},
308-
&MeshRecordComponent::setPosition);
315+
defaultAttribute("position", [&]() {
316+
if (dimensionality < 100)
317+
{
318+
return std::vector<double>(dimensionality, 0.5);
319+
}
320+
else
321+
{
322+
return std::vector<double>{0.0};
323+
}
324+
}).withSetter (&MeshRecordComponent::setPosition)();
309325
addParentDefaults<RecordComponent>();
310326
}
311327
else if constexpr (std::is_same_v<Child, PatchRecordComponent>)

0 commit comments

Comments
 (0)