|
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" |
|
29 | 31 | #include "openPMD/auxiliary/UniquePtr.hpp" |
30 | 32 |
|
31 | 33 | #include <memory> |
| 34 | +#include <type_traits> |
32 | 35 |
|
33 | 36 | namespace openPMD |
34 | 37 | { |
@@ -92,12 +95,34 @@ inline std::shared_ptr<T> RecordComponent::loadChunk(Offset o, Extent e) |
92 | 95 | #endif |
93 | 96 | } |
94 | 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 | + |
95 | 120 | template <typename T> |
96 | 121 | inline void |
97 | 122 | RecordComponent::loadChunk(std::shared_ptr<T> data, Offset o, Extent e) |
98 | 123 | { |
99 | 124 | Datatype dtype = determineDatatype(data); |
100 | | - if (dtype != getDatatype()) |
| 125 | + if (dtype != getDatatype() && !constant()) |
101 | 126 | if (!isSameInteger<T>(getDatatype()) && |
102 | 127 | !isSameFloatingPoint<T>(getDatatype()) && |
103 | 128 | !isSameComplexFloatingPoint<T>(getDatatype()) && |
@@ -159,10 +184,25 @@ RecordComponent::loadChunk(std::shared_ptr<T> data, Offset o, Extent e) |
159 | 184 | for (auto const &dimensionSize : extent) |
160 | 185 | numPoints *= dimensionSize; |
161 | 186 |
|
162 | | - T value = rc.m_constantValue.get<T>(); |
| 187 | + std::optional<T> val = |
| 188 | + switchNonVectorType<detail::do_convert</* To = */ T>>( |
| 189 | + /* from = */ getDatatype(), rc.m_constantValue); |
163 | 190 |
|
164 | | - T *raw_ptr = data.get(); |
165 | | - std::fill(raw_ptr, raw_ptr + numPoints, value); |
| 191 | + if (val.has_value()) |
| 192 | + { |
| 193 | + T *raw_ptr = data.get(); |
| 194 | + std::fill(raw_ptr, raw_ptr + numPoints, *val); |
| 195 | + } |
| 196 | + else |
| 197 | + { |
| 198 | + std::string const data_type_str = datatypeToString(getDatatype()); |
| 199 | + std::string const requ_type_str = |
| 200 | + datatypeToString(determineDatatype<T>()); |
| 201 | + std::string err_msg = |
| 202 | + "Type conversion during chunk loading not possible! "; |
| 203 | + err_msg += "Data: " + data_type_str + "; Load as: " + requ_type_str; |
| 204 | + throw error::WrongAPIUsage(err_msg); |
| 205 | + } |
166 | 206 | } |
167 | 207 | else |
168 | 208 | { |
@@ -250,7 +290,7 @@ void RecordComponent::storeChunkRaw(T *ptr, Offset offset, Extent extent) |
250 | 290 |
|
251 | 291 | template <typename T_ContiguousContainer> |
252 | 292 | inline typename std::enable_if_t< |
253 | | - auxiliary::IsContiguousContainer_v<T_ContiguousContainer> > |
| 293 | + auxiliary::IsContiguousContainer_v<T_ContiguousContainer>> |
254 | 294 | RecordComponent::storeChunk(T_ContiguousContainer &data, Offset o, Extent e) |
255 | 295 | { |
256 | 296 | uint8_t dim = getDimensionality(); |
|
0 commit comments