|
21 | 21 |
|
22 | 22 | #pragma once |
23 | 23 |
|
| 24 | +#include "openPMD/Datatype.hpp" |
| 25 | +#include "openPMD/Error.hpp" |
24 | 26 | #include "openPMD/RecordComponent.hpp" |
25 | 27 | #include "openPMD/Span.hpp" |
26 | 28 | #include "openPMD/auxiliary/Memory.hpp" |
@@ -93,12 +95,38 @@ inline std::shared_ptr<T> RecordComponent::loadChunk(Offset o, Extent e) |
93 | 95 | #endif |
94 | 96 | } |
95 | 97 |
|
| 98 | +namespace detail |
| 99 | +{ |
| 100 | + template <typename To> |
| 101 | + struct do_convert |
| 102 | + { |
| 103 | + template <typename From> |
| 104 | + static std::optional<To> call(Attribute &attr) |
| 105 | + { |
| 106 | + if constexpr (std::is_convertible_v<From, To>) |
| 107 | + { |
| 108 | + return std::make_optional<To>(attr.get<From>()); |
| 109 | + } |
| 110 | + else |
| 111 | + { |
| 112 | + return std::nullopt; |
| 113 | + } |
| 114 | + } |
| 115 | + |
| 116 | + static constexpr char const *errorMsg = "is_conversible"; |
| 117 | + }; |
| 118 | +} // namespace detail |
| 119 | + |
96 | 120 | template <typename T> |
97 | 121 | inline void |
98 | 122 | RecordComponent::loadChunk(std::shared_ptr<T> data, Offset o, Extent e) |
99 | 123 | { |
100 | 124 | Datatype dtype = determineDatatype(data); |
101 | | - if (dtype != getDatatype()) |
| 125 | + /* |
| 126 | + * For constant components, we implement type conversion, so there is |
| 127 | + * a separate check further below. |
| 128 | + */ |
| 129 | + if (dtype != getDatatype() && !constant()) |
102 | 130 | if (!isSameInteger<T>(getDatatype()) && |
103 | 131 | !isSameFloatingPoint<T>(getDatatype()) && |
104 | 132 | !isSameComplexFloatingPoint<T>(getDatatype()) && |
@@ -160,10 +188,25 @@ RecordComponent::loadChunk(std::shared_ptr<T> data, Offset o, Extent e) |
160 | 188 | for (auto const &dimensionSize : extent) |
161 | 189 | numPoints *= dimensionSize; |
162 | 190 |
|
163 | | - T value = rc.m_constantValue.get<T>(); |
| 191 | + std::optional<T> val = |
| 192 | + switchNonVectorType<detail::do_convert</* To = */ T>>( |
| 193 | + /* from = */ getDatatype(), rc.m_constantValue); |
164 | 194 |
|
165 | | - T *raw_ptr = data.get(); |
166 | | - std::fill(raw_ptr, raw_ptr + numPoints, value); |
| 195 | + if (val.has_value()) |
| 196 | + { |
| 197 | + T *raw_ptr = data.get(); |
| 198 | + std::fill(raw_ptr, raw_ptr + numPoints, *val); |
| 199 | + } |
| 200 | + else |
| 201 | + { |
| 202 | + std::string const data_type_str = datatypeToString(getDatatype()); |
| 203 | + std::string const requ_type_str = |
| 204 | + datatypeToString(determineDatatype<T>()); |
| 205 | + std::string err_msg = |
| 206 | + "Type conversion during chunk loading not possible! "; |
| 207 | + err_msg += "Data: " + data_type_str + "; Load as: " + requ_type_str; |
| 208 | + throw error::WrongAPIUsage(err_msg); |
| 209 | + } |
167 | 210 | } |
168 | 211 | else |
169 | 212 | { |
|
0 commit comments