File indexing completed on 2026-05-10 08:42:09
0001 #pragma once
0002
0003 #include "bits/H5Inspector_decl.hpp"
0004 #include "H5Exception.hpp"
0005
0006 #include <mdspan>
0007 #include <vector>
0008 #include <array>
0009 #include <sstream>
0010 #include <utility>
0011 #include <type_traits>
0012
0013 namespace HighFive {
0014 namespace details {
0015
0016
0017 template <class ElementType, class Extents, class LayoutPolicy, class AccessorPolicy>
0018 struct inspector<std::mdspan<ElementType, Extents, LayoutPolicy, AccessorPolicy>> {
0019 using type = std::mdspan<ElementType, Extents, LayoutPolicy, AccessorPolicy>;
0020 using value_type = typename type::element_type;
0021 using base_type = typename inspector<value_type>::base_type;
0022 using hdf5_type = base_type;
0023 using extents_type = typename type::extents_type;
0024 using accessor_type = typename type::accessor_type;
0025
0026 static constexpr size_t ndim = type::rank();
0027 static constexpr size_t min_ndim = ndim + inspector<value_type>::min_ndim;
0028 static constexpr size_t max_ndim = ndim + inspector<value_type>::max_ndim;
0029
0030 static constexpr bool is_trivially_copyable =
0031 std::is_trivially_copyable<value_type>::value &&
0032 inspector<value_type>::is_trivially_nestable &&
0033 (std::is_same_v<std::default_accessor<value_type>, accessor_type>
0034 #ifdef __cpp_lib_aligned_accessor
0035 || std::is_same_v<std::aligned_accessor<value_type>, accessor_type>
0036 #endif
0037 ) &&
0038 (std::is_same_v<typename type::layout_type, std::layout_right> ||
0039 (std::is_same_v<typename type::layout_type, std::layout_left> && ndim == 1));
0040 static constexpr bool is_trivially_nestable = false;
0041
0042 private:
0043 using index_type = typename extents_type::index_type;
0044
0045
0046 static auto get_first_element(const type& val) {
0047 std::array<index_type, ndim> indices{};
0048 return val[indices];
0049 }
0050
0051 template <typename T>
0052 static auto data_impl(T& val) -> decltype(inspector<value_type>::data(*val.data_handle())) {
0053 if (!is_trivially_copyable) {
0054 throw DataSetException("Invalid use of `inspector<std::mdspan<...>>::data`.");
0055 }
0056
0057 if (val.empty()) {
0058 return nullptr;
0059 }
0060
0061 return inspector<value_type>::data(*val.data_handle());
0062 }
0063
0064 public:
0065 static size_t getRank(const type& val) {
0066 if (val.empty()) {
0067 return min_ndim;
0068 }
0069 return ndim + inspector<value_type>::getRank(get_first_element(val));
0070 }
0071
0072 static std::vector<size_t> getDimensions(const type& val) {
0073 std::vector<size_t> sizes;
0074 sizes.reserve(ndim);
0075 for (size_t r = 0; r < ndim; ++r) {
0076 sizes.push_back(val.extent(r));
0077 }
0078 if (!val.empty()) {
0079 auto s = inspector<value_type>::getDimensions(get_first_element(val));
0080 sizes.insert(sizes.end(), s.begin(), s.end());
0081 }
0082 return sizes;
0083 }
0084
0085 static void prepare(type& val, const std::vector<size_t>& dims) {
0086 if (dims.size() < ndim) {
0087 std::ostringstream os;
0088 os << "Impossible to pair DataSet with " << dims.size()
0089 << " dimensions into an mdspan with rank " << ndim << ".";
0090 throw DataSpaceException(os.str());
0091 }
0092
0093
0094 for (size_t r = 0; r < ndim; ++r) {
0095 if (dims[r] != val.extent(r)) {
0096 std::ostringstream os;
0097 os << "Mismatching dimensions for mdspan: expected " << val.extent(r)
0098 << " for dimension " << r << ", but got " << dims[r] << ".";
0099 throw DataSpaceException(os.str());
0100 }
0101 }
0102 }
0103
0104 static hdf5_type* data(type& val) {
0105 return data_impl(val);
0106 }
0107
0108 static const hdf5_type* data(const type& val) {
0109 return data_impl(val);
0110 }
0111
0112 static void serialize(const type& val, const std::vector<size_t>& dims, hdf5_type* m) {
0113 auto subdims = std::vector<size_t>(dims.begin() + ndim, dims.end());
0114 auto subsize = compute_total_size(subdims);
0115
0116 std::array<index_type, ndim> indices{};
0117 auto iterate = [&](auto& self, size_t dim) -> void {
0118 if (dim == ndim) {
0119
0120 inspector<value_type>::serialize(val[indices], subdims, m);
0121 m += subsize;
0122 } else {
0123
0124 const auto n = static_cast<index_type>(val.extent(dim));
0125 for (indices[dim] = 0; indices[dim] < n; ++indices[dim]) {
0126 self(self, dim + 1);
0127 }
0128 }
0129 };
0130
0131 iterate(iterate, 0);
0132 }
0133
0134 static void unserialize(const hdf5_type* vec_align,
0135 const std::vector<size_t>& dims,
0136 type& val) {
0137 if (dims.size() < ndim) {
0138 std::ostringstream os;
0139 os << "Impossible to pair DataSet with " << dims.size()
0140 << " dimensions into an mdspan with rank " << ndim << ".";
0141 throw DataSpaceException(os.str());
0142 }
0143
0144 auto subdims = std::vector<size_t>(dims.begin() + ndim, dims.end());
0145 auto subsize = compute_total_size(subdims);
0146
0147 std::array<index_type, ndim> indices{};
0148 auto iterate = [&](auto& self, size_t dim) -> void {
0149 if (dim == ndim) {
0150
0151 inspector<value_type>::unserialize(vec_align, subdims, val[indices]);
0152 vec_align += subsize;
0153 } else {
0154
0155 const auto n = static_cast<index_type>(dims[dim]);
0156 for (indices[dim] = 0; indices[dim] < n; ++indices[dim]) {
0157 self(self, dim + 1);
0158 }
0159 }
0160 };
0161
0162 iterate(iterate, 0);
0163 }
0164 };
0165
0166 }
0167 }