Skip to content

Commit 496a188

Browse files
committed
Split files
1 parent dccc12d commit 496a188

20 files changed

Lines changed: 670 additions & 592 deletions

CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,9 @@ set(CORE_SOURCE
428428
src/backend/Writable.cpp
429429
src/backend/scientific_defaults/ScientificDefaults.cpp
430430
src/backend/scientific_defaults/ScientificDefaults_auxiliary.cpp
431-
src/backend/scientific_defaults/ScientificDefaults_impl.cpp
431+
src/backend/scientific_defaults/ProcessParsedAttribute.cpp
432+
src/backend/scientific_defaults/AttributeReader.cpp
433+
src/backend/scientific_defaults/ConfigAttribute.cpp
432434
src/auxiliary/OneDimensionalBlockSlicer.cpp
433435
src/helper/list_series.cpp
434436
src/snapshots/ContainerImpls.cpp
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#pragma once
2+
3+
#include "openPMD/Error.hpp"
4+
#include "openPMD/backend/Attributable.hpp"
5+
#include "openPMD/backend/Attribute.hpp"
6+
#include "openPMD/backend/scientific_defaults/ProcessParsedAttribute.hpp"
7+
8+
#include <deque>
9+
#include <optional>
10+
#include <variant>
11+
12+
namespace openPMD::internal
13+
{
14+
namespace attribute_read_result
15+
{
16+
struct TypeUnmatched
17+
{
18+
std::deque<Datatype> expectedDatatypes;
19+
};
20+
struct Success
21+
{};
22+
} // namespace attribute_read_result
23+
24+
using AttributeReadResult = std::variant<
25+
attribute_read_result::Success,
26+
attribute_read_result::TypeUnmatched,
27+
error::ReadError>;
28+
29+
/*
30+
* Struct that describes parsing logic for a standard-defined attribute.
31+
* Created by ConfigAttribute::withReader().
32+
*/
33+
struct AttributeReader
34+
{
35+
std::deque<Datatype> eligibleDatatypes;
36+
std::optional<std::shared_ptr<ProcessParsedAttribute>> processAttribute;
37+
38+
AttributeReader(
39+
std::deque<Datatype> eligibleDatatypes_in,
40+
std::optional<std::shared_ptr<ProcessParsedAttribute>>
41+
processAttribute_in);
42+
43+
auto operator()(
44+
Attributable &record,
45+
char const *attrName,
46+
Attribute const &a,
47+
std::deque<Datatype> unmatched_so_far) -> AttributeReadResult;
48+
};
49+
} // namespace openPMD::internal
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#pragma once
2+
3+
#include "openPMD/backend/Attributable.hpp"
4+
#include "openPMD/backend/scientific_defaults/AttributeReader.hpp"
5+
#include "openPMD/backend/scientific_defaults/ScientificDefaults_auxiliary.hpp"
6+
7+
#include <deque>
8+
#include <optional>
9+
10+
namespace openPMD::internal
11+
{
12+
struct ConfigAttribute
13+
{
14+
Attributable &attributable;
15+
char const *attrName;
16+
std::optional<std::function<void(Attributable &)>> initDefaultAttribute;
17+
// processed "from left to right"
18+
std::deque<AttributeReader> attributeReaders;
19+
20+
template <typename RecordType, typename ValueType>
21+
using set_default_val_t = RecordType &(RecordType::*)(ValueType);
22+
23+
ConfigAttribute(Attributable &attributable_in, char const *attrName_in);
24+
25+
ConfigAttribute(ConfigAttribute const &) = delete;
26+
ConfigAttribute(ConfigAttribute &&) = delete;
27+
28+
ConfigAttribute &operator=(ConfigAttribute const &) = delete;
29+
ConfigAttribute &operator=(ConfigAttribute &&) = delete;
30+
31+
template <typename RecordType, typename S = void, typename GetDefaultValue>
32+
[[nodiscard]] auto withSetter(
33+
GetDefaultValue &&getDefaultVal,
34+
set_default_val_t<
35+
RecordType,
36+
std::conditional_t<
37+
std::is_void_v<S>,
38+
auxiliary::CallResult_t<GetDefaultValue>,
39+
S>> setDefaultVal) -> ConfigAttribute &;
40+
41+
template <typename DefaultValue>
42+
[[nodiscard]] auto withGenericSetter(DefaultValue &&defaultVal)
43+
-> ConfigAttribute &;
44+
45+
[[nodiscard]] auto withReader(
46+
std::deque<Datatype> eligibleDatatypes,
47+
std::optional<std::shared_ptr<ProcessParsedAttribute>>
48+
processAttribute = std::nullopt) -> ConfigAttribute &;
49+
50+
void write();
51+
void read();
52+
void operator()(WriteOrRead wor);
53+
};
54+
55+
auto get_float_types() -> std::deque<Datatype>;
56+
auto get_string_types() -> std::deque<Datatype>;
57+
} // namespace openPMD::internal
58+
59+
#include "openPMD/backend/scientific_defaults/ConfigAttribute.tpp"

include/openPMD/backend/scientific_defaults/ScientificDefaults_impl.tpp renamed to include/openPMD/backend/scientific_defaults/ConfigAttribute.tpp

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,9 @@
11
#pragma once
22

3-
#include "openPMD/backend/scientific_defaults/ScientificDefaults_impl.hpp"
3+
#include "openPMD/backend/scientific_defaults/ConfigAttribute.hpp"
44

55
namespace openPMD::internal
66
{
7-
template <typename T, typename RecordType>
8-
auto require_type(
9-
RecordType &&record,
10-
std::optional<error::ReadError> (*handler)(
11-
std::remove_reference_t<RecordType> &, T))
12-
-> std::shared_ptr<ProcessAttribute>
13-
{
14-
return std::make_shared<RequireType<T>>(
15-
std::forward<RecordType>(record), handler);
16-
}
17-
18-
template <typename T>
19-
auto require_type() -> std::shared_ptr<ProcessAttribute>
20-
{
21-
return std::make_shared<RequireType<T>>();
22-
}
23-
247
namespace
258
{
269
// Need SFINAE for this since MSVC doesnt understand if constexpr
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
#pragma once
2+
3+
#include "openPMD/Error.hpp"
4+
#include "openPMD/Mesh.hpp"
5+
#include "openPMD/backend/Attributable.hpp"
6+
#include "openPMD/backend/Attribute.hpp"
7+
8+
#include <optional>
9+
#include <string>
10+
#include <type_traits>
11+
12+
namespace openPMD::internal
13+
{
14+
/*
15+
* General interface for attribute processing used in struct AttributeReader.
16+
*/
17+
struct ProcessParsedAttribute
18+
{
19+
virtual auto operator()(Attributable &, char const *, Attribute const &)
20+
-> std::optional<error::ReadError> = 0;
21+
virtual ~ProcessParsedAttribute() = default;
22+
};
23+
24+
//////////////////////////////////////////////////////////
25+
// 1st implementation: RequireType and associated types //
26+
//////////////////////////////////////////////////////////
27+
28+
/*
29+
* Helper interface for validating an attribute whose type has already been
30+
* determined. Poor-man's lambda, in an attempt at reducing use of template
31+
* types. The only implementation at PostProcessConvertedAttributeImpl<T> is
32+
* conceptually equivalent to storing an object of type RecordType in the lambda
33+
* capture.
34+
*/
35+
template <typename T>
36+
struct PostProcessConvertedAttribute
37+
{
38+
virtual auto operator()(T val) -> std::optional<error::ReadError> = 0;
39+
virtual ~PostProcessConvertedAttribute() = default;
40+
};
41+
42+
/*
43+
* Defer validation to a function pointer of type handler_t.
44+
*/
45+
template <typename T, typename RecordType>
46+
struct PostProcessConvertedAttributeImpl : PostProcessConvertedAttribute<T>
47+
{
48+
RecordType record;
49+
using handler_t = std::optional<error::ReadError> (*)(RecordType &, T);
50+
handler_t reader;
51+
52+
// Use makePostProcessConvertedAttribute below for better type inference
53+
PostProcessConvertedAttributeImpl(
54+
RecordType record_in, handler_t reader_in);
55+
auto operator()(T val) -> std::optional<error::ReadError> override;
56+
};
57+
58+
// Postprocessing handlers for `handler_t reader` above.
59+
auto setMeshGeometryFromString(Mesh &mesh, std::string val)
60+
-> std::optional<error::ReadError>;
61+
auto setMeshDataOrderFromChar(Mesh &mesh, char val)
62+
-> std::optional<error::ReadError>;
63+
64+
template <typename T, typename RecordType>
65+
auto makePostProcessConvertedAttribute(
66+
RecordType &&record,
67+
std::optional<error::ReadError> (*handler)(
68+
std::remove_reference_t<RecordType> &, T))
69+
-> std::shared_ptr<PostProcessConvertedAttribute<T>>;
70+
/*
71+
* Validate an attribute by requiring one specific type T, and by optionally
72+
* postprocessing it. Type conversions for the attribute are attempted.
73+
* Note that type checking for attribute is mainly intended to by done by
74+
* specifying eligible data types in struct AttributeReader. This handler's
75+
* purpose is dynamically casting to one specific type not required by the
76+
* standard, but by our further handling (e.g. setMeshGeometryFromString above
77+
* requires a string, but we should also accept single chars, or vectors with a
78+
* single element if we we find such things on disk).
79+
* If a handler is not specified, this just casts the type and then uses
80+
* setAttribute().
81+
*/
82+
template <typename T>
83+
struct RequireType : ProcessParsedAttribute
84+
{
85+
std::optional<std::shared_ptr<PostProcessConvertedAttribute<T>>>
86+
postProcess;
87+
88+
explicit RequireType() = default;
89+
90+
// Use require_type() helpers below for construction.
91+
template <typename RecordType>
92+
RequireType(
93+
RecordType &&record,
94+
std::optional<error::ReadError> (*handler)(
95+
std::remove_reference_t<RecordType> &, T));
96+
97+
auto operator()(
98+
Attributable &record, char const *attrName, Attribute const &attr)
99+
-> std::optional<error::ReadError> override;
100+
};
101+
102+
template <typename T, typename RecordType>
103+
auto require_type(
104+
std::optional<error::ReadError> (*)(
105+
std::remove_reference_t<RecordType> &, T))
106+
-> std::shared_ptr<ProcessParsedAttribute>;
107+
// common case: directly use setAttribute
108+
template <typename T>
109+
auto require_type() -> std::shared_ptr<ProcessParsedAttribute>;
110+
111+
///////////////////////////////////////
112+
// 2nd implementation: RequireVector //
113+
///////////////////////////////////////
114+
115+
/*
116+
* Validate an attribute by requiring a vector type, potentially wrapping
117+
* scalar values into a vector.
118+
* Note that this employs no type checking for the base type, this is done
119+
* by the type list argument of ConfigAttribute::withReader().
120+
*/
121+
struct RequireVector : ProcessParsedAttribute
122+
{
123+
auto operator()(Attributable &, char const *, Attribute const &)
124+
-> std::optional<error::ReadError> override;
125+
};
126+
extern std::shared_ptr<ProcessParsedAttribute> require_vector;
127+
128+
///////////////////////////////////////
129+
// 3rd implementation: RequireScalar //
130+
///////////////////////////////////////
131+
132+
/*
133+
* Validate an attribute by requiring a scalar type, potentially unwrapping
134+
* single values from a vector.
135+
* Note that this employs no type checking for the base type, this is done
136+
* by the type list argument of ConfigAttribute::withReader().
137+
*/
138+
struct RequireScalar : ProcessParsedAttribute
139+
{
140+
auto operator()(Attributable &, char const *, Attribute const &)
141+
-> std::optional<error::ReadError> override;
142+
};
143+
extern std::shared_ptr<ProcessParsedAttribute> require_scalar;
144+
} // namespace openPMD::internal
145+
146+
#include "openPMD/backend/scientific_defaults/ProcessParsedAttribute.tpp"
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#pragma once
2+
3+
#include "openPMD/backend/scientific_defaults/ProcessParsedAttribute.hpp"
4+
5+
#include <variant>
6+
7+
namespace openPMD::internal
8+
{
9+
template <typename T, typename RecordType>
10+
PostProcessConvertedAttributeImpl<T, RecordType>::
11+
PostProcessConvertedAttributeImpl(RecordType record_in, handler_t reader_in)
12+
: record(std::move(record_in)), reader(reader_in)
13+
{}
14+
15+
template <typename T, typename RecordType>
16+
auto PostProcessConvertedAttributeImpl<T, RecordType>::operator()(T val)
17+
-> std::optional<error::ReadError>
18+
{
19+
return (*reader)(record, std::move(val));
20+
}
21+
22+
template <typename T, typename RecordType>
23+
auto require_type(
24+
RecordType &&record,
25+
std::optional<error::ReadError> (*handler)(
26+
std::remove_reference_t<RecordType> &, T))
27+
-> std::shared_ptr<ProcessParsedAttribute>
28+
{
29+
return std::make_shared<RequireType<T>>(
30+
std::forward<RecordType>(record), handler);
31+
}
32+
33+
template <typename T>
34+
auto require_type() -> std::shared_ptr<ProcessParsedAttribute>
35+
{
36+
return std::make_shared<RequireType<T>>();
37+
}
38+
39+
template <typename T, typename RecordType>
40+
auto makePostProcessConvertedAttribute(
41+
RecordType &&record,
42+
std::optional<error::ReadError> (*handler)(
43+
std::remove_reference_t<RecordType> &, T))
44+
-> std::shared_ptr<PostProcessConvertedAttribute<T>>
45+
{
46+
return std::make_shared<PostProcessConvertedAttributeImpl<
47+
T,
48+
std::remove_reference_t<RecordType>>>(
49+
std::forward<RecordType>(record), handler);
50+
}
51+
52+
template <typename T>
53+
template <typename RecordType>
54+
RequireType<T>::RequireType(
55+
RecordType &&record,
56+
std::optional<error::ReadError> (*handler)(
57+
std::remove_reference_t<RecordType> &, T))
58+
: postProcess(makePostProcessConvertedAttribute(
59+
std::forward<RecordType>(record), handler))
60+
{}
61+
62+
template <typename T>
63+
auto RequireType<T>::operator()(
64+
Attributable &record, char const *attrName, Attribute const &attr)
65+
-> std::optional<error::ReadError>
66+
{
67+
auto converted_or_error = attr.getOrError<T>();
68+
return std::visit(
69+
auxiliary::overloaded{
70+
[&](T casted_val) -> std::optional<error::ReadError> {
71+
if (this->postProcess.has_value())
72+
{
73+
return (**this->postProcess)(std::move(casted_val));
74+
}
75+
else
76+
{
77+
record.setAttribute<T>(attrName, std::move(casted_val));
78+
return std::nullopt;
79+
}
80+
},
81+
[](std::runtime_error const &err)
82+
-> std::optional<error::ReadError> {
83+
std::string msg = "Expected a scalar type: ";
84+
msg += err.what();
85+
return error::ReadError(
86+
error::AffectedObject::Attribute,
87+
error::Reason::UnexpectedContent,
88+
std::nullopt,
89+
std::move(msg));
90+
}},
91+
converted_or_error);
92+
}
93+
} // namespace openPMD::internal

include/openPMD/backend/scientific_defaults/ScientificDefaults.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class ScientificDefaults
3131
//
3232
// Used both by writeDefaults() and readDefaults().
3333
//
34-
// Use helpers from ScientificDefaults_impl.hpp for writing implementations.
34+
// Use helpers from ConfigAttribute.hpp for writing implementations.
3535
virtual void defaults_impl(bool write, OpenpmdStandard) = 0;
3636

3737
// Called upon Iteration::close(), will fill in defaults below Iteration

0 commit comments

Comments
 (0)