File indexing completed on 2025-04-19 08:55:35
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include <algorithm>
0012 #include <cassert>
0013 #include <functional>
0014 #include <numeric>
0015 #include <sstream>
0016 #include <string>
0017
0018 #include "h5d_wrapper.hpp"
0019 #include "h5s_wrapper.hpp"
0020
0021 #include "H5ReadWrite_misc.hpp"
0022 #include "H5Converter_misc.hpp"
0023
0024 namespace HighFive {
0025
0026 namespace details {
0027
0028
0029
0030
0031 inline const DataSet& get_dataset(const Selection& sel) {
0032 return sel.getDataset();
0033 }
0034
0035 inline const DataSet& get_dataset(const DataSet& ds) {
0036 return ds;
0037 }
0038
0039
0040
0041
0042 inline hid_t get_memspace_id(const Selection& ptr) {
0043 return ptr.getMemSpace().getId();
0044 }
0045
0046 inline hid_t get_memspace_id(const DataSet&) {
0047 return H5S_ALL;
0048 }
0049 }
0050
0051 inline ElementSet::ElementSet(std::initializer_list<std::size_t> list)
0052 : _ids(list) {}
0053
0054 inline ElementSet::ElementSet(std::initializer_list<std::vector<std::size_t>> list)
0055 : ElementSet(std::vector<std::vector<std::size_t>>(list)) {}
0056
0057 inline ElementSet::ElementSet(const std::vector<std::size_t>& element_ids)
0058 : _ids(element_ids) {}
0059
0060 inline ElementSet::ElementSet(const std::vector<std::vector<std::size_t>>& element_ids) {
0061 for (const auto& vec: element_ids) {
0062 std::copy(vec.begin(), vec.end(), std::back_inserter(_ids));
0063 }
0064 }
0065
0066 template <typename Derivate>
0067 inline Selection SliceTraits<Derivate>::select(const HyperSlab& hyperslab,
0068 const DataSpace& memspace) const {
0069
0070
0071
0072
0073
0074
0075 const auto& slice = static_cast<const Derivate&>(*this);
0076 auto filespace = hyperslab.apply(slice.getSpace());
0077
0078 return detail::make_selection(memspace, filespace, details::get_dataset(slice));
0079 }
0080
0081 template <typename Derivate>
0082 inline Selection SliceTraits<Derivate>::select(const HyperSlab& hyper_slab) const {
0083 const auto& slice = static_cast<const Derivate&>(*this);
0084 auto filespace = slice.getSpace();
0085 filespace = hyper_slab.apply(filespace);
0086
0087 auto n_elements = detail::h5s_get_select_npoints(filespace.getId());
0088 auto memspace = DataSpace(std::array<size_t, 1>{size_t(n_elements)});
0089
0090 return detail::make_selection(memspace, filespace, details::get_dataset(slice));
0091 }
0092
0093
0094 template <typename Derivate>
0095 inline Selection SliceTraits<Derivate>::select(const std::vector<size_t>& offset,
0096 const std::vector<size_t>& count,
0097 const std::vector<size_t>& stride,
0098 const std::vector<size_t>& block) const {
0099 auto slab = HyperSlab(RegularHyperSlab(offset, count, stride, block));
0100 auto memspace = DataSpace(count);
0101 return select(slab, memspace);
0102 }
0103
0104 template <typename Derivate>
0105 inline Selection SliceTraits<Derivate>::select(const std::vector<size_t>& columns) const {
0106 const auto& slice = static_cast<const Derivate&>(*this);
0107 const DataSpace& space = slice.getSpace();
0108 std::vector<size_t> dims = space.getDimensions();
0109
0110 std::vector<size_t> counts = dims;
0111 counts.back() = 1;
0112
0113 std::vector<size_t> offsets(dims.size(), 0);
0114
0115 HyperSlab slab;
0116 for (const auto& column: columns) {
0117 offsets.back() = column;
0118 slab |= RegularHyperSlab(offsets, counts);
0119 }
0120
0121 std::vector<size_t> memdims = dims;
0122 memdims.back() = columns.size();
0123
0124 return select(slab, DataSpace(memdims));
0125 }
0126
0127 template <typename Derivate>
0128 inline Selection SliceTraits<Derivate>::select(const ElementSet& elements) const {
0129 const auto& slice = static_cast<const Derivate&>(*this);
0130 const hsize_t* data = nullptr;
0131 const DataSpace space = slice.getSpace().clone();
0132 const std::size_t length = elements._ids.size();
0133 if (length % space.getNumberDimensions() != 0) {
0134 throw DataSpaceException(
0135 "Number of coordinates in elements picking "
0136 "should be a multiple of the dimensions.");
0137 }
0138 const std::size_t num_elements = length / space.getNumberDimensions();
0139 std::vector<hsize_t> raw_elements;
0140
0141
0142
0143 if (std::is_same<std::size_t, hsize_t>::value) {
0144
0145 data = reinterpret_cast<const hsize_t*>(&(elements._ids[0]));
0146 } else {
0147 raw_elements.resize(length);
0148 std::copy(elements._ids.begin(), elements._ids.end(), raw_elements.begin());
0149 data = raw_elements.data();
0150 }
0151
0152 detail::h5s_select_elements(space.getId(), H5S_SELECT_SET, num_elements, data);
0153
0154 return detail::make_selection(DataSpace(num_elements), space, details::get_dataset(slice));
0155 }
0156
0157
0158 template <typename Derivate>
0159 template <typename T>
0160 inline T SliceTraits<Derivate>::read(const DataTransferProps& xfer_props) const {
0161 T array;
0162 read(array, xfer_props);
0163 return array;
0164 }
0165
0166
0167 template <typename Derivate>
0168 template <typename T>
0169 inline void SliceTraits<Derivate>::read(T& array, const DataTransferProps& xfer_props) const {
0170 const auto& slice = static_cast<const Derivate&>(*this);
0171 const DataSpace& mem_space = slice.getMemSpace();
0172
0173 auto file_datatype = slice.getDataType();
0174
0175 const details::BufferInfo<T> buffer_info(
0176 file_datatype,
0177 [&slice]() -> std::string { return details::get_dataset(slice).getPath(); },
0178 details::BufferInfo<T>::Operation::read);
0179
0180 if (!details::checkDimensions(mem_space, buffer_info.n_dimensions)) {
0181 std::ostringstream ss;
0182 ss << "Impossible to read DataSet of dimensions " << mem_space.getNumberDimensions()
0183 << " into arrays of dimensions " << buffer_info.n_dimensions;
0184 throw DataSpaceException(ss.str());
0185 }
0186 auto dims = mem_space.getDimensions();
0187
0188 auto r = details::data_converter::get_reader<T>(dims, array, file_datatype);
0189 read_raw(r.getPointer(), buffer_info.data_type, xfer_props);
0190
0191 r.unserialize(array);
0192
0193 auto t = buffer_info.data_type;
0194 auto c = t.getClass();
0195 if (c == DataTypeClass::VarLen || t.isVariableStr()) {
0196 #if H5_VERSION_GE(1, 12, 0)
0197
0198 (void)
0199 detail::h5t_reclaim(t.getId(), mem_space.getId(), xfer_props.getId(), r.getPointer());
0200 #else
0201
0202 (void) detail::h5d_vlen_reclaim(t.getId(),
0203 mem_space.getId(),
0204 xfer_props.getId(),
0205 r.getPointer());
0206 #endif
0207 }
0208 }
0209
0210 template <typename Derivate>
0211 template <typename T>
0212 inline void SliceTraits<Derivate>::read(T* array,
0213 const DataType& mem_datatype,
0214 const DataTransferProps& xfer_props) const {
0215 read_raw(array, mem_datatype, xfer_props);
0216 }
0217
0218 template <typename Derivate>
0219 template <typename T>
0220 inline void SliceTraits<Derivate>::read(T* array, const DataTransferProps& xfer_props) const {
0221 read_raw(array, xfer_props);
0222 }
0223
0224
0225 template <typename Derivate>
0226 template <typename T>
0227 inline void SliceTraits<Derivate>::read_raw(T* array,
0228 const DataType& mem_datatype,
0229 const DataTransferProps& xfer_props) const {
0230 static_assert(!std::is_const<T>::value,
0231 "read() requires a non-const structure to read data into");
0232
0233 const auto& slice = static_cast<const Derivate&>(*this);
0234
0235 detail::h5d_read(details::get_dataset(slice).getId(),
0236 mem_datatype.getId(),
0237 details::get_memspace_id(slice),
0238 slice.getSpace().getId(),
0239 xfer_props.getId(),
0240 static_cast<void*>(array));
0241 }
0242
0243
0244 template <typename Derivate>
0245 template <typename T>
0246 inline void SliceTraits<Derivate>::read_raw(T* array, const DataTransferProps& xfer_props) const {
0247 using element_type = typename details::inspector<T>::base_type;
0248 const DataType& mem_datatype = create_and_check_datatype<element_type>();
0249
0250 read_raw(array, mem_datatype, xfer_props);
0251 }
0252
0253
0254 template <typename Derivate>
0255 template <typename T>
0256 inline void SliceTraits<Derivate>::write(const T& buffer, const DataTransferProps& xfer_props) {
0257 const auto& slice = static_cast<const Derivate&>(*this);
0258 const DataSpace& mem_space = slice.getMemSpace();
0259
0260 auto file_datatype = slice.getDataType();
0261
0262 const details::BufferInfo<T> buffer_info(
0263 file_datatype,
0264 [&slice]() -> std::string { return details::get_dataset(slice).getPath(); },
0265 details::BufferInfo<T>::Operation::write);
0266
0267 if (!details::checkDimensions(mem_space, buffer_info.n_dimensions)) {
0268 std::ostringstream ss;
0269 ss << "Impossible to write buffer of dimensions "
0270 << details::format_vector(mem_space.getDimensions())
0271 << " into dataset with n = " << buffer_info.n_dimensions << " dimensions.";
0272 throw DataSpaceException(ss.str());
0273 }
0274 auto w = details::data_converter::serialize<T>(buffer, file_datatype);
0275 write_raw(w.getPointer(), buffer_info.data_type, xfer_props);
0276 }
0277
0278
0279 template <typename Derivate>
0280 template <typename T>
0281 inline void SliceTraits<Derivate>::write_raw(const T* buffer,
0282 const DataType& mem_datatype,
0283 const DataTransferProps& xfer_props) {
0284 const auto& slice = static_cast<const Derivate&>(*this);
0285
0286 detail::h5d_write(details::get_dataset(slice).getId(),
0287 mem_datatype.getId(),
0288 details::get_memspace_id(slice),
0289 slice.getSpace().getId(),
0290 xfer_props.getId(),
0291 static_cast<const void*>(buffer));
0292 }
0293
0294
0295 template <typename Derivate>
0296 template <typename T>
0297 inline void SliceTraits<Derivate>::write_raw(const T* buffer, const DataTransferProps& xfer_props) {
0298 using element_type = typename details::inspector<T>::base_type;
0299 const auto& mem_datatype = create_and_check_datatype<element_type>();
0300
0301 write_raw(buffer, mem_datatype, xfer_props);
0302 }
0303
0304
0305 }