Skip to content

Commit 865e15f

Browse files
committed
scientificdefaults_internal.cpp
1 parent 996051d commit 865e15f

7 files changed

Lines changed: 635 additions & 618 deletions

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,8 @@ set(CORE_SOURCE
427427
src/backend/PatchRecordComponent.cpp
428428
src/backend/Writable.cpp
429429
src/backend/ScientificDefaults.cpp
430+
src/backend/ScientificDefaults_auxiliary.cpp
431+
src/backend/ScientificDefaults_impl.cpp
430432
src/auxiliary/OneDimensionalBlockSlicer.cpp
431433
src/helper/list_series.cpp
432434
src/snapshots/ContainerImpls.cpp
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#pragma once
2+
3+
#include "openPMD/backend/Attribute.hpp"
4+
5+
#include <iostream>
6+
#include <string>
7+
#include <type_traits>
8+
#include <vector>
9+
10+
namespace openPMD::auxiliary
11+
{
12+
template <typename F, typename SFINAE = void>
13+
struct CallResult
14+
{
15+
// If F is not callable, then use its type directly without calling.
16+
using type = F;
17+
};
18+
19+
template <typename F>
20+
struct CallResult<F, std::void_t<decltype(std::declval<F>()())>>
21+
{
22+
// If F is callable (used to avoid complex computations until necessary),
23+
// then use its return type.
24+
using type = decltype(std::declval<F>()());
25+
};
26+
27+
template <typename F>
28+
using CallResult_t = typename CallResult<F>::type;
29+
30+
template <typename T>
31+
auto write_val_to_stderr(T const &val) -> std::ostream &;
32+
auto write_to_stderr(Attribute const &a) -> std::ostream &;
33+
34+
auto createDefaultAxisLabels(uint64_t dimensionality)
35+
-> std::vector<std::string>;
36+
auto createDefaultVector(uint64_t dimensionality, double defaultValue)
37+
-> std::vector<double>;
38+
} // namespace openPMD::auxiliary
39+
40+
namespace openPMD::internal
41+
{
42+
enum class WriteOrRead : std::uint8_t
43+
{
44+
Write,
45+
Read
46+
};
47+
}

include/openPMD/backend/ScientificDefaults_internal.hpp renamed to include/openPMD/backend/ScientificDefaults_impl.hpp

Lines changed: 96 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -4,82 +4,22 @@
44
#include "openPMD/Mesh.hpp"
55
#include "openPMD/backend/Attributable.hpp"
66
#include "openPMD/backend/Attribute.hpp"
7+
#include "openPMD/backend/ScientificDefaults_auxiliary.hpp"
78

89
#include <deque>
9-
#include <iostream>
1010
#include <optional>
1111
#include <string>
1212
#include <type_traits>
1313
#include <variant>
14-
#include <vector>
15-
16-
namespace openPMD::detail
17-
{
18-
template <typename F, typename SFINAE = void>
19-
struct IsCallable
20-
{
21-
static constexpr bool value = false;
22-
using type = F;
23-
};
24-
25-
template <typename F>
26-
struct IsCallable<F, std::void_t<decltype(std::declval<F>()())>>
27-
{
28-
static constexpr bool value = true;
29-
using type = decltype(std::declval<F>()());
30-
};
31-
32-
template <typename F>
33-
constexpr bool IsCallable_v = IsCallable<F>::value;
34-
template <typename F>
35-
using CallResult_t = typename IsCallable<F>::type;
36-
} // namespace openPMD::detail
3714

3815
namespace openPMD::internal
3916
{
40-
namespace
41-
{
42-
template <typename T>
43-
inline auto write_val_to_stderr(T const &val) -> std::ostream &;
44-
inline auto write_to_stderr(Attribute const &a) -> std::ostream &;
45-
46-
// Helper functions used in ScientificDefaults implementations
47-
inline auto setMeshGeometryFromString(Mesh &mesh, std::string val)
48-
-> std::optional<error::ReadError>;
49-
inline auto setMeshDataOrderFromChar(Mesh &mesh, char val)
50-
-> std::optional<error::ReadError>;
51-
inline auto createDefaultAxisLabels(uint64_t dimensionality)
52-
-> std::vector<std::string>;
53-
inline auto
54-
createDefaultVector(uint64_t dimensionality, double defaultValue)
55-
-> std::vector<double>;
56-
} // namespace
57-
58-
namespace attribute_read_result
59-
{
60-
struct TypeUnmatched
61-
{
62-
std::deque<Datatype> expectedDatatypes;
63-
};
64-
struct Success
65-
{};
66-
} // namespace attribute_read_result
6717

6818
/*
6919
* The structs below implement the typical routines for parsing an attribute.
7020
* This implies validation and conversion.
7121
*/
7222

73-
/*
74-
* General interface for attribute processing used in struct AttributeReader.
75-
*/
76-
struct ProcessAttribute
77-
{
78-
virtual auto operator()(Attributable &, char const *, Attribute const &)
79-
-> std::optional<error::ReadError> = 0;
80-
virtual ~ProcessAttribute() = default;
81-
};
82-
8323
/*
8424
* Interface for validating an attribute whose type has already been determined.
8525
*/
@@ -100,18 +40,38 @@ struct PostProcessConvertedAttributeImpl : PostProcessConvertedAttribute<T>
10040
using handler_t = std::optional<error::ReadError> (*)(RecordType &, T);
10141
handler_t reader;
10242

103-
PostProcessConvertedAttributeImpl(
104-
RecordType record_in, handler_t reader_in);
43+
PostProcessConvertedAttributeImpl(RecordType record_in, handler_t reader_in)
44+
: record(std::move(record_in)), reader(reader_in)
45+
{}
10546

106-
auto operator()(T val) -> std::optional<error::ReadError> override;
47+
auto operator()(T val) -> std::optional<error::ReadError> override
48+
{
49+
return (*reader)(record, std::move(val));
50+
}
10751
};
10852

10953
template <typename T, typename RecordType>
11054
auto makePostProcessConvertedAttribute(
11155
RecordType &&record,
11256
std::optional<error::ReadError> (*handler)(
11357
std::remove_reference_t<RecordType> &, T))
114-
-> std::shared_ptr<PostProcessConvertedAttribute<T>>;
58+
-> std::shared_ptr<PostProcessConvertedAttribute<T>>
59+
{
60+
return std::make_shared<PostProcessConvertedAttributeImpl<
61+
T,
62+
std::remove_reference_t<RecordType>>>(
63+
std::forward<RecordType>(record), handler);
64+
}
65+
66+
/*
67+
* General interface for attribute processing used in struct AttributeReader.
68+
*/
69+
struct ProcessAttribute
70+
{
71+
virtual auto operator()(Attributable &, char const *, Attribute const &)
72+
-> std::optional<error::ReadError> = 0;
73+
virtual ~ProcessAttribute() = default;
74+
};
11575

11676
/*
11777
* Validate an attribute by requiring one specific type T, and by optionally
@@ -129,12 +89,49 @@ struct RequireType : ProcessAttribute
12989
RequireType(
13090
RecordType &&record,
13191
std::optional<error::ReadError> (*handler)(
132-
std::remove_reference_t<RecordType> &, T));
92+
std::remove_reference_t<RecordType> &, T))
93+
: postProcess(makePostProcessConvertedAttribute(
94+
std::forward<RecordType>(record), handler))
95+
{}
13396

134-
auto operator()(Attributable &, char const *, Attribute const &)
135-
-> std::optional<error::ReadError> override;
97+
auto operator()(
98+
Attributable &record, char const *attrName, Attribute const &attr)
99+
-> std::optional<error::ReadError> override
100+
{
101+
auto converted_or_error = attr.getOrError<T>();
102+
return std::visit(
103+
auxiliary::overloaded{
104+
[&](T casted_val) -> std::optional<error::ReadError> {
105+
if (this->postProcess.has_value())
106+
{
107+
return (**this->postProcess)(std::move(casted_val));
108+
}
109+
else
110+
{
111+
record.setAttribute<T>(attrName, std::move(casted_val));
112+
return std::nullopt;
113+
}
114+
},
115+
[](std::runtime_error const &err)
116+
-> std::optional<error::ReadError> {
117+
std::string msg = "Expected a scalar type: ";
118+
msg += err.what();
119+
return error::ReadError(
120+
error::AffectedObject::Attribute,
121+
error::Reason::UnexpectedContent,
122+
std::nullopt,
123+
std::move(msg));
124+
}},
125+
converted_or_error);
126+
}
136127
};
137128

129+
// Postprocessing handlers
130+
auto setMeshGeometryFromString(Mesh &mesh, std::string val)
131+
-> std::optional<error::ReadError>;
132+
auto setMeshDataOrderFromChar(Mesh &mesh, char val)
133+
-> std::optional<error::ReadError>;
134+
138135
/*
139136
* Validate an attribute by requiring a vector type, potentially wrapping
140137
* scalar values into a vector.
@@ -159,6 +156,16 @@ struct RequireScalar : ProcessAttribute
159156
-> std::optional<error::ReadError> override;
160157
};
161158

159+
namespace attribute_read_result
160+
{
161+
struct TypeUnmatched
162+
{
163+
std::deque<Datatype> expectedDatatypes;
164+
};
165+
struct Success
166+
{};
167+
} // namespace attribute_read_result
168+
162169
using AttributeReadResult = std::variant<
163170
attribute_read_result::Success,
164171
attribute_read_result::TypeUnmatched,
@@ -184,12 +191,6 @@ struct AttributeReader
184191
std::deque<Datatype> unmatched_so_far) -> AttributeReadResult;
185192
};
186193

187-
enum class WriteOrRead : std::uint8_t
188-
{
189-
Write,
190-
Read
191-
};
192-
193194
/////////////////////
194195
// ConfigAttribute //
195196
// //////////////////
@@ -220,7 +221,7 @@ struct ConfigAttribute
220221
RecordType,
221222
std::conditional_t<
222223
std::is_void_v<S>,
223-
detail::CallResult_t<GetDefaultValue>,
224+
auxiliary::CallResult_t<GetDefaultValue>,
224225
S>> setDefaultVal) -> ConfigAttribute &;
225226

226227
template <typename DefaultValue>
@@ -239,21 +240,24 @@ struct ConfigAttribute
239240

240241
// below are some helpers that may be used as processing functions for
241242
// attributes in withReader()
242-
namespace
243-
{ // try converting to scalar values (e.g. when a vector of length 1 is given)
244-
extern std::shared_ptr<ProcessAttribute> require_scalar;
245-
// try converting to vectors (e.g. when a scalar or an array is given)
246-
extern std::shared_ptr<ProcessAttribute> require_vector;
247-
template <typename T, typename RecordType>
248-
auto require_type(
249-
std::optional<error::ReadError> (*)(
250-
std::remove_reference_t<RecordType> &, T))
251-
-> std::shared_ptr<ProcessAttribute>;
252-
// common case: directly use setAttribute
253-
template <typename T>
254-
auto require_type() -> std::shared_ptr<ProcessAttribute>;
255-
256-
inline auto get_float_types() -> std::deque<Datatype>;
257-
inline auto get_string_types() -> std::deque<Datatype>;
258-
} // namespace
243+
244+
// try converting to scalar values (e.g. when a vector of length 1 is given)
245+
extern std::shared_ptr<ProcessAttribute> require_scalar;
246+
// try converting to vectors (e.g. when a scalar or an array is given)
247+
extern std::shared_ptr<ProcessAttribute> require_vector;
248+
249+
template <typename T, typename RecordType>
250+
auto require_type(
251+
std::optional<error::ReadError> (*)(
252+
std::remove_reference_t<RecordType> &, T))
253+
-> std::shared_ptr<ProcessAttribute>;
254+
// common case: directly use setAttribute
255+
template <typename T>
256+
auto require_type() -> std::shared_ptr<ProcessAttribute>;
257+
258+
auto get_float_types() -> std::deque<Datatype>;
259+
auto get_string_types() -> std::deque<Datatype>;
260+
259261
} // namespace openPMD::internal
262+
263+
#include "openPMD/backend/ScientificDefaults_impl.tpp"

0 commit comments

Comments
 (0)