Program Listing for File h5ppHyperslab.h

Return to documentation for file (/home/david/GitProjects/h5pp/h5pp/include/h5pp/details/h5ppHyperslab.h)

#pragma once
#include "h5ppDimensionType.h"
#include "h5ppFormat.h"
#include "h5ppOptional.h"
#include "h5ppTypeSfinae.h"
#include <hdf5.h>
#include <type_traits>
#include <utility>
#include <vector>
namespace h5pp {
    class Hyperslab {
        public:
        // Hyperslab properties. Read here https://support.hdfgroup.org/HDF5/doc/RM/RM_H5S.html#Dataspace-SelectHyperslab

        OptDimsType                 offset      = std::nullopt;
        OptDimsType                 extent      = std::nullopt;
        OptDimsType                 stride      = std::nullopt;
        OptDimsType                 blocks      = std::nullopt;
        std::optional<H5S_sel_type> select_type = std::nullopt;
        Hyperslab()                             = default;
        Hyperslab(const DimsType &offset, const DimsType &extent, OptDimsType stride = std::nullopt, OptDimsType blocks = std::nullopt)
            : offset(offset), extent(extent), stride(std::move(stride)), blocks(std::move(blocks)) {}

        explicit Hyperslab(const hid::h5s &space) {
            int rank = H5Sget_simple_extent_ndims(space);
            if(rank < 0) throw std::runtime_error("Could not read ndims on given space");
            if(rank == 0) return;
            select_type = H5Sget_select_type(space);
            if(select_type.value() == H5S_SEL_HYPERSLABS) {
#if H5_VERSION_GE(1, 10, 0)
                htri_t is_regular = H5Sis_regular_hyperslab(space);
                if(is_regular < 0) {
                    H5Eprint(H5E_DEFAULT, stderr);
                    throw std::runtime_error("Failed to query hyperslab type in space");
                }
                if(not is_regular)
                    throw std::runtime_error("The space has irregular (non-rectangular) hyperslab selection.\n"
                                             "This is not yet supported by h5pp");
#endif
                offset = std::vector<hsize_t>(static_cast<size_t>(rank), 0);
                extent = std::vector<hsize_t>(static_cast<size_t>(rank), 0);
                stride = std::vector<hsize_t>(static_cast<size_t>(rank), 0);
                blocks = std::vector<hsize_t>(static_cast<size_t>(rank), 0);
#if H5_VERSION_GE(1, 10, 0)
                H5Sget_regular_hyperslab(space, offset->data(), stride->data(), extent->data(), blocks->data());
#else
                H5Sget_simple_extent_dims(space, extent->data(), nullptr);
#endif
            } else if(select_type.value() == H5S_SEL_ALL) {
                offset = std::vector<hsize_t>(static_cast<size_t>(rank), 0);
                extent = std::vector<hsize_t>(static_cast<size_t>(rank), 0);
                H5Sget_simple_extent_dims(space, extent->data(), nullptr);
            } else if(select_type.value() == H5S_SEL_ERROR)
                throw std::runtime_error("Invalid hyperslab selection");
            else
                throw std::runtime_error("Unsupported selection type. Choose space selection type NONE, ALL or HYPERSLABS");
        }
        [[nodiscard]] bool empty() const { return not offset and not extent and not stride and not blocks; }

        [[nodiscard]] std::string string() const {
            std::string msg;
            if(offset) msg.append(h5pp::format(" | offset {}", offset.value()));
            if(extent) msg.append(h5pp::format(" | extent {}", extent.value()));
            if(stride) msg.append(h5pp::format(" | stride {}", stride.value()));
            if(blocks) msg.append(h5pp::format(" | blocks {}", blocks.value()));
            return msg;
        }
    };

}