@@ -40,30 +40,8 @@ namespace openPMD::internal
4040namespace
4141{
4242 template <typename T>
43- auto write_val_to_stderr (T const &val) -> std::ostream &
44- {
45- if constexpr (auxiliary::IsVector_v<T> || auxiliary::IsArray_v<T>)
46- {
47- auxiliary::write_vec_to_stream (std::cerr, val);
48- }
49- else if constexpr (std::is_same_v<T, unit_representations::AsMap>)
50- {
51- std::cerr << " Unit_Map" ;
52- }
53- else
54- {
55- std::cerr << val;
56- }
57- return std::cerr;
58- }
59- auto write_to_stderr (Attribute const &a) -> std::ostream &
60- {
61- std::visit (
62- [](auto const &val) { write_val_to_stderr (val); },
63- a.getVariant <attribute_types>());
64- return std::cerr;
65- }
66-
43+ auto write_val_to_stderr (T const &val) -> std::ostream &;
44+ auto write_to_stderr (Attribute const &a) -> std::ostream &;
6745} // namespace
6846
6947namespace attribute_read_result
@@ -81,49 +59,24 @@ using AttributeReadResult = std::variant<
8159 attribute_read_result::TypeUnmatched,
8260 error::ReadError>;
8361
84- struct NewAttributeReader
62+ struct AttributeReader
8563{
86- std::deque<Datatype> eligibleDatatypes;
8764 using process_attribute_type =
8865 std::function<std::optional<error::ReadError>(
8966 Attributable &, char const *, Attribute const &)>;
67+
68+ std::deque<Datatype> eligibleDatatypes;
9069 std::optional<process_attribute_type> processAttribute;
9170
92- NewAttributeReader (
71+ AttributeReader (
9372 std::deque<Datatype> eligibleDatatypes_in,
94- std::optional<process_attribute_type> processAttribute_in)
95- : eligibleDatatypes(std::move(eligibleDatatypes_in))
96- , processAttribute(std::move(processAttribute_in))
97- {}
73+ std::optional<process_attribute_type> processAttribute_in);
9874
9975 auto operator ()(
10076 Attributable &record,
10177 char const *attrName,
10278 Attribute const &a,
103- std::deque<Datatype> unmatched_so_far) -> AttributeReadResult
104- {
105- if (std::find (
106- eligibleDatatypes.begin (), eligibleDatatypes.end (), a.dtype ) ==
107- eligibleDatatypes.end ())
108- {
109- auto res = attribute_read_result::TypeUnmatched{
110- std::move (unmatched_so_far)};
111- for (auto dt : this ->eligibleDatatypes )
112- {
113- res.expectedDatatypes .push_back (dt);
114- }
115- return res;
116- }
117- if (processAttribute.has_value ())
118- {
119- auto maybe_error = (*processAttribute)(record, attrName, a);
120- if (maybe_error.has_value ())
121- {
122- return *maybe_error;
123- }
124- }
125- return attribute_read_result::Success{};
126- }
79+ std::deque<Datatype> unmatched_so_far) -> AttributeReadResult;
12780};
12881
12982enum class WriteOrRead : std::uint8_t
@@ -140,13 +93,13 @@ struct ConfigAttribute
14093{
14194 Attributable &child;
14295 char const *attrName;
143- std::function<void (Attributable &)> initDefaultAttribute;
96+ std::optional<std:: function<void (Attributable &)> > initDefaultAttribute;
14497 // processed "from left to right"
145- std::deque<NewAttributeReader> attributeReaders;
98+ std::deque<AttributeReader> attributeReaders;
99+
100+ using process_attribute_type = AttributeReader::process_attribute_type;
146101
147- ConfigAttribute (Attributable &child_in, char const *attrName_in)
148- : child(child_in), attrName(attrName_in)
149- {}
102+ ConfigAttribute (Attributable &child_in, char const *attrName_in);
150103
151104 ConfigAttribute (ConfigAttribute const &) = delete ;
152105 ConfigAttribute (ConfigAttribute &&) = delete ;
@@ -161,141 +114,37 @@ struct ConfigAttribute
161114 std::conditional_t <
162115 std::is_void_v<S>,
163116 detail::CallResult_t<GetDefaultValue>,
164- S>)) -> ConfigAttribute &
165- {
166- initDefaultAttribute = [getDefaultVal_lambda = std::move (getDefaultVal),
167- setDefaultVal](Attributable &attr) {
168- RecordType *record = dynamic_cast <RecordType *>(&attr);
169- if (!record)
170- {
171- throw error::Internal (" dynamic cast failure" );
172- }
173- if constexpr (detail::IsCallable_v<GetDefaultValue>)
174- {
175- ((*record).*setDefaultVal)(getDefaultVal_lambda ());
176- }
177- else
178- {
179- ((*record).*setDefaultVal)(std::move (getDefaultVal_lambda));
180- }
181- };
182- return *this ;
183- }
117+ S>)) -> ConfigAttribute &;
184118
185119 template <typename DefaultValue>
186120 [[nodiscard]] auto withGenericSetter (DefaultValue &&defaultVal)
187- -> ConfigAttribute &
188- {
189- initDefaultAttribute = [this ,
190- defaultVal_lambda =
191- std::forward<DefaultValue &&>(defaultVal)](
192- Attributable &attr) {
193- attr.setAttribute (this ->attrName , std::move (defaultVal_lambda));
194- };
195- return *this ;
196- }
121+ -> ConfigAttribute &;
197122
198123 [[nodiscard]] auto withReader (
199124 std::deque<Datatype> eligibleDatatypes,
200- std::optional<NewAttributeReader::process_attribute_type>
201- processAttribute = std::nullopt ) -> ConfigAttribute &
202- {
203- this ->attributeReaders .emplace_back (
204- std::move (eligibleDatatypes), std::move (processAttribute));
205- return *this ;
206- }
125+ std::optional<process_attribute_type> processAttribute = std::nullopt )
126+ -> ConfigAttribute &;
207127
208- void write ()
209- {
210- if (this ->child .containsAttribute (this ->attrName ))
211- {
212- return ;
213- }
214- this ->initDefaultAttribute (this ->child );
215- }
216-
217- void read ()
218- {
219- if (attributeReaders.empty ())
220- {
221- // No readers emplaced for this attribute
222- return ;
223- }
224- AttributeReadResult res = attribute_read_result::TypeUnmatched{};
225- Parameter<Operation::READ_ATT> aRead;
226- aRead.name = this ->attrName ;
227- auto IOHandler = this ->child .IOHandler ();
228- IOHandler->enqueue (IOTask (&this ->child , aRead));
229- try
230- {
231- IOHandler->flush (defaultFlushParams);
232- }
233- catch (error::ReadError const &e)
234- {
235- std::cerr << " Could not read expected attribute '" << this ->attrName
236- << " ' in '" << this ->child .myPath ().openPMDPath ()
237- << " . Will initialize it with a default value. "
238- " Original error: "
239- << e.what () << std::endl;
240- this ->initDefaultAttribute (this ->child );
241- return ;
242- }
243-
244- Attribute attribute (Attribute::from_any, std::move (*aRead.m_resource ));
245- for (auto &attributeReader : attributeReaders)
246- {
128+ void write ();
129+ void read ();
130+ void operator ()(WriteOrRead wor);
131+ };
247132
248- if (auto *not_matched =
249- std::get_if<attribute_read_result::TypeUnmatched>(&res))
250- {
251- res = attributeReader (
252- this ->child ,
253- this ->attrName ,
254- attribute,
255- std::move (not_matched->expectedDatatypes ));
256- }
257- else
258- {
259- break ;
260- }
261- }
262- auto dt = attribute.dtype ;
263- std::visit (
264- auxiliary::overloaded{
265- [&](attribute_read_result::TypeUnmatched &&type_unmatched) {
266- std::cerr << " Unexpected type '" << dt
267- << " ' for attribute '" << this ->attrName
268- << " ' in '" << this ->child .myPath ().openPMDPath ()
269- << " ' with value '" ;
270- write_to_stderr (attribute) << " '. Expected one of " ;
271- auxiliary::write_vec_to_stream (
272- std::cerr, type_unmatched.expectedDatatypes )
273- << " or convertible to such a type." << std::endl;
274- },
275- [&](error::ReadError const &err) {
276- std::cerr << " Unexpected error while trying to read "
277- " attribute '"
278- << this ->attrName << " ' in '"
279- << this ->child .myPath ().openPMDPath ()
280- << " '' with value '" ;
281- write_to_stderr (attribute)
282- << " ': " << err.what () << std::endl;
283- },
284- [](attribute_read_result::Success) { /* no-op */ }},
285- std::move (res));
286- }
133+ // below are some helpers that may be used as processing functions for
134+ // attributes in withReader()
135+ namespace
136+ { // try converting to scalar values (e.g. when a vector of length 1 is given)
137+ extern ConfigAttribute::process_attribute_type require_scalar;
138+ // try converting to vectors (e.g. when a scalar or an array is given)
139+ extern ConfigAttribute::process_attribute_type require_vector;
140+ // F: T -> void
141+ template <typename T, typename F>
142+ auto require_type (F &&) -> ConfigAttribute::process_attribute_type;
143+ // common case: directly use setAttribute
144+ template <typename T>
145+ auto require_type () -> ConfigAttribute::process_attribute_type;
287146
288- void operator ()(WriteOrRead wor)
289- {
290- switch (wor)
291- {
292- case WriteOrRead::Write:
293- write ();
294- break ;
295- case WriteOrRead::Read:
296- read ();
297- break ;
298- }
299- }
300- };
147+ auto get_float_types () -> std::deque<Datatype>;
148+ auto get_string_types () -> std::deque<Datatype>;
149+ } // namespace
301150} // namespace openPMD::internal
0 commit comments