ritsuko
Helper utilities for ArtifactDB C++ code
Loading...
Searching...
No Matches
validate.hpp
Go to the documentation of this file.
1#ifndef RITSUKO_CVLS_VALIDATE_HPP
2#define RITSUKO_CVLS_VALIDATE_HPP
3
4#include <string>
5#include <vector>
6#include <stdexcept>
7#include <limits>
8#include <cassert>
9
10#include "H5Cpp.h"
11#include "sanisizer/sanisizer.hpp"
12
13#include "../hdf5/get_name.hpp"
16
17#include "Pointer.hpp"
18
24namespace ritsuko {
25
26namespace cvls {
27
40template<typename Offset_, typename Length_>
41inline void validate_scalar_pointer(const H5::DataSet& data, hsize_t heap_length) {
42 validate_pointer_datatype(data, std::numeric_limits<Offset_>::digits, std::numeric_limits<Length_>::digits);
43 assert(data.getSpace().getSimpleExtentNdims() == 0);
44
47 data.read(&val, dtype);
48
49 if (is_Pointer_out_of_range(val, heap_length)) {
50 throw std::runtime_error("compressed VLS array pointer at '" + hdf5::get_name(data) + "' is out of range of the heap");
51 }
52}
53
67template<typename Offset_, typename Length_>
68inline void validate_1d_pointers(const H5::DataSet& data, hsize_t full_length, hsize_t heap_length) {
69 validate_pointer_datatype(data, std::numeric_limits<Offset_>::digits, std::numeric_limits<Length_>::digits);
70 assert(data.getSpace().getSimpleExtentNdims() == 1);
71
72 const auto& plist = data.getCreatePlist();
73 hsize_t block_size = 0;
74 if (plist.getLayout() == H5D_CHUNKED) {
75 plist.getChunk(1, &block_size);
76 } else {
77 // Hard-coding the mock chunk size for non-chunked datasets,
78 // it's not worth requiring an extra function argument to customize this.
79 block_size = sanisizer::min(full_length, 10000);
80 }
81
82 H5::DataSpace mspace(1, &block_size), dspace(1, &full_length);
83 auto buffer = sanisizer::create<std::vector<Pointer<Offset_, Length_> > >(block_size);
85
86 hsize_t i = 0;
87 while (i < full_length) {
88 const auto available = sanisizer::min(full_length - i, block_size);
89 constexpr hsize_t zero = 0;
90 mspace.selectHyperslab(H5S_SELECT_SET, &available, &zero);
91 dspace.selectHyperslab(H5S_SELECT_SET, &available, &i);
92
93 data.read(buffer.data(), dtype, mspace, dspace);
94 for (I<decltype(available)> j = 0; j < available; ++j) {
95 const auto& val = buffer[j];
96 if (is_Pointer_out_of_range(val, heap_length)) {
97 throw std::runtime_error("compressed VLS array pointers at '" + hdf5::get_name(data) + "' are out of range of the heap");
98 }
99 }
100
101 i += available;
102 }
103}
104
119template<typename Offset_, typename Length_>
120void validate_nd_pointers(const H5::DataSet& data, const std::vector<hsize_t>& dimensions, hsize_t heap_length) {
121 validate_pointer_datatype(data, std::numeric_limits<Offset_>::digits, std::numeric_limits<Length_>::digits);
122 assert(data.getSpace().getSimpleExtentNdims() > 0);
123
124 // Cast of 'ndim' to 'int' is implicitly safe if the assertion holds.
125 const auto ndim = dimensions.size();
126 assert(sanisizer::is_equal(ndim, data.getSpace().getSimpleExtentNdims()));
127
128 std::vector<hsize_t> chunk_dims;
129 const auto& plist = data.getCreatePlist();
130 if (plist.getLayout() == H5D_CHUNKED) {
131 chunk_dims.resize(ndim); // No need to check this, dimensions is of the same type as chunk_dims.
132 plist.getChunk(ndim, chunk_dims.data());
133 } else {
134 chunk_dims = hdf5::mock_contiguous_chunks(dimensions, 10000); // Hard-coding the upper bound to save ourselves an argument.
135 }
136
137 hdf5::IterateChunks iter(dimensions, chunk_dims);
138 H5::DataSpace fspace(ndim, dimensions.data());
139 H5::DataSpace mspace(ndim, iter.chunk_dimensions().data());
140 auto buffer = sanisizer::create<std::vector<Pointer<Offset_, Length_> > >(mspace.getSimpleExtentNpoints());
142
143 while (iter.advance()) {
144 const auto& curcount = iter.counts();
145 mspace.setExtentSimple(ndim, curcount.data());
146 fspace.selectHyperslab(H5S_SELECT_SET, curcount.data(), iter.starts().data());
147
148 data.read(buffer.data(), dtype, mspace, fspace);
149 const auto available = mspace.getSimpleExtentNpoints();
150 for (I<decltype(available)> i = 0; i < available; ++i) {
151 const auto& val = buffer[i];
152 if (is_Pointer_out_of_range(val, heap_length)) {
153 throw std::runtime_error("compressed VLS array pointers at '" + hdf5::get_name(data) + "' are out of range of the heap");
154 }
155 }
156 }
157}
158
166inline void validate_heap(const H5::DataSet& data) {
167 if (data.getTypeClass() != H5T_INTEGER) {
168 throw std::runtime_error("expected an integer datatype for the compressed VLS heap at '" + hdf5::get_name(data) + "'");
169 }
170 if (hdf5::exceeds_integer_limit(data.getIntType(), 8, false)) {
171 throw std::runtime_error("expected 8-bit unsigned integers for the compressed VLS heap at '" + hdf5::get_name(data) + "'");
172 }
173 if (data.getSpace().getSimpleExtentNdims() != 1) {
174 throw std::runtime_error("expected a 1-dimensional dataset for the compressed VLS heap at '" + hdf5::get_name(data) + "'");
175 }
176}
177
178}
179
180}
181
182#endif
Iterate through a dataspace by chunk.
Compound datatype of the compresed VLS heap pointer.
Get the name of a HDF5 object.
Mock chunk sizes for a contiguous HDF5 dataset.
void validate_1d_pointers(const H5::DataSet &data, hsize_t full_length, hsize_t heap_length)
Definition validate.hpp:68
void validate_pointer_datatype(const H5::CompType &type, const std::size_t offset_precision, const std::size_t length_precision)
Definition Pointer.hpp:88
void validate_nd_pointers(const H5::DataSet &data, const std::vector< hsize_t > &dimensions, hsize_t heap_length)
Definition validate.hpp:120
void validate_scalar_pointer(const H5::DataSet &data, hsize_t heap_length)
Definition validate.hpp:41
H5::CompType define_pointer_datatype()
Definition Pointer.hpp:69
void validate_heap(const H5::DataSet &data)
Definition validate.hpp:166
bool is_Pointer_out_of_range(const Pointer< Offset_, Length_ > &ptr, const hsize_t heap_length)
Definition Pointer.hpp:148
std::vector< hsize_t > mock_contiguous_chunks(const std::vector< hsize_t > &dimensions, hsize_t chunk_size)
Definition mock_contiguous_chunks.hpp:30
std::string get_name(const Object_ &obj)
Definition get_name.hpp:29
bool exceeds_integer_limit(const H5::IntType &itype, std::size_t precision, bool is_signed)
Definition exceeds_limit.hpp:28
Helper functions for ArtifactDB parsing and validation.
Definition Pointer.hpp:21
Pointer into the compressed VLS heap.
Definition Pointer.hpp:35
Iterate through an high-dimensional dataspace by chunk.
Definition IterateChunks.hpp:28
const std::vector< hsize_t > & chunk_dimensions() const
Definition IterateChunks.hpp:122
bool advance()
Definition IterateChunks.hpp:66
const std::vector< hsize_t > & starts() const
Definition IterateChunks.hpp:95
const std::vector< hsize_t > & counts() const
Definition IterateChunks.hpp:106