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#include <algorithm>
10
11#include "H5Cpp.h"
13
16#include "../itoa.hpp"
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 try {
43 validate_pointer_datatype(data, std::numeric_limits<Offset_>::digits, std::numeric_limits<Length_>::digits);
44 } catch (std::exception& e) {
45 throw std::runtime_error("failed to validate the datatype; " + std::string(e.what()));
46 }
47
48 assert(data.getSpace().getSimpleExtentNdims() == 0);
49
52 data.read(&val, dtype);
53
54 if (is_Pointer_out_of_range(val, heap_length)) {
55 throw std::runtime_error("pointer is out of range of the heap");
56 }
57}
58
69
84template<typename Offset_, typename Length_>
85inline void validate_1d_pointers(const H5::DataSet& data, hsize_t full_length, hsize_t heap_length, const Validate1dPointersOptions& options) {
86 try {
87 validate_pointer_datatype(data, std::numeric_limits<Offset_>::digits, std::numeric_limits<Length_>::digits);
88 } catch (std::exception& e) {
89 throw std::runtime_error("failed to validate the datatype; " + std::string(e.what()));
90 }
91 assert(data.getSpace().getSimpleExtentNdims() == 1);
92
93 const auto& plist = data.getCreatePlist();
94 hsize_t block_size = 0;
95 if (plist.getLayout() == H5D_CHUNKED) {
96 plist.getChunk(1, &block_size);
97 } else {
98 block_size = std::min(full_length, options.contiguous_chunk_size);
99 }
100
101 H5::DataSpace mspace(1, &block_size), dspace(1, &full_length);
104
105 hsize_t i = 0;
106 while (i < full_length) {
107 const auto available = sanisizer::min(full_length - i, block_size);
108 constexpr hsize_t zero = 0;
109 mspace.selectHyperslab(H5S_SELECT_SET, &available, &zero);
110 dspace.selectHyperslab(H5S_SELECT_SET, &available, &i);
111
112 data.read(buffer.data(), dtype, mspace, dspace);
113 for (I<decltype(available)> j = 0; j < available; ++j) {
114 const auto& val = buffer[j];
115 if (is_Pointer_out_of_range(val, heap_length)) {
116 throw std::runtime_error("pointer at position " + itoa(i + j) + " is out of range of the heap");
117 }
118 }
119
120 i += available;
121 }
122}
123
134
150template<typename Offset_, typename Length_>
151void validate_nd_pointers(const H5::DataSet& data, const std::vector<hsize_t>& dimensions, hsize_t heap_length, const ValidateNdPointersOptions& options) {
152 try {
153 validate_pointer_datatype(data, std::numeric_limits<Offset_>::digits, std::numeric_limits<Length_>::digits);
154 } catch (std::exception& e) {
155 throw std::runtime_error("failed to validate the datatype; " + std::string(e.what()));
156 }
157 assert(data.getSpace().getSimpleExtentNdims() > 0);
158
159 // Cast of 'ndim' to 'int' is implicitly safe if the assertion holds.
160 const auto ndim = dimensions.size();
161 assert(sanisizer::is_equal(ndim, data.getSpace().getSimpleExtentNdims()));
162
163 std::vector<hsize_t> chunk_dims;
164 const auto& plist = data.getCreatePlist();
165 if (plist.getLayout() == H5D_CHUNKED) {
166 chunk_dims.resize(ndim); // No need to check this, dimensions is of the same type as chunk_dims.
167 plist.getChunk(ndim, chunk_dims.data());
168 } else {
169 chunk_dims = hdf5::mock_contiguous_chunks(dimensions, options.contiguous_chunk_size);
170 }
171
172 hdf5::IterateChunks iter(dimensions, chunk_dims);
173 H5::DataSpace fspace(ndim, dimensions.data());
174 H5::DataSpace mspace(ndim, iter.chunk_dimensions().data());
175 auto buffer = sanisizer::create<std::vector<Pointer<Offset_, Length_> > >(mspace.getSimpleExtentNpoints());
177
178 while (iter.advance()) {
179 const auto& curcount = iter.counts();
180 const auto& curstart = iter.starts();
181 mspace.setExtentSimple(ndim, curcount.data());
182 fspace.selectHyperslab(H5S_SELECT_SET, curcount.data(), curstart.data());
183
184 data.read(buffer.data(), dtype, mspace, fspace);
185 const auto available = mspace.getSimpleExtentNpoints();
186 for (I<decltype(available)> i = 0; i < available; ++i) {
187 const auto& val = buffer[i];
188 if (is_Pointer_out_of_range(val, heap_length)) {
189 auto posstr = hdf5::emit_coordinates_as_string(i, available, curstart, curcount);
190 throw std::runtime_error("pointer at position " + posstr + " is out of range of the heap");
191 }
192 }
193 }
194}
195
205inline hsize_t validate_heap(const H5::DataSet& data) {
206 if (data.getTypeClass() != H5T_INTEGER) {
207 throw std::runtime_error("expected an integer datatype");
208 }
209 if (hdf5::exceeds_integer_limit(data.getIntType(), 8, false)) {
210 throw std::runtime_error("expected 8-bit unsigned integers");
211 }
212 auto dspace = data.getSpace();
213 if (dspace.getSimpleExtentNdims() != 1) {
214 throw std::runtime_error("expected a 1-dimensional dataset");
215 }
216 hsize_t len;
217 dspace.getSimpleExtentDims(&len);
218 return len;
219}
220
221}
222
223}
224
225#endif
Iterate through a dataspace by chunk.
Compound datatype of the compresed VLS heap pointer.
Convert an integer to a string.
Mock chunk sizes for a contiguous HDF5 dataset.
void validate_nd_pointers(const H5::DataSet &data, const std::vector< hsize_t > &dimensions, hsize_t heap_length, const ValidateNdPointersOptions &options)
Definition validate.hpp:151
void validate_pointer_datatype(const H5::CompType &type, const std::size_t offset_precision, const std::size_t length_precision)
Definition Pointer.hpp:89
void validate_scalar_pointer(const H5::DataSet &data, hsize_t heap_length)
Definition validate.hpp:41
void validate_1d_pointers(const H5::DataSet &data, hsize_t full_length, hsize_t heap_length, const Validate1dPointersOptions &options)
Definition validate.hpp:85
H5::CompType define_pointer_datatype()
Definition Pointer.hpp:70
bool is_Pointer_out_of_range(const Pointer< Offset_, Length_ > &ptr, const hsize_t heap_length)
Definition Pointer.hpp:142
hsize_t validate_heap(const H5::DataSet &data)
Definition validate.hpp:205
std::vector< hsize_t > mock_contiguous_chunks(const std::vector< hsize_t > &dimensions, hsize_t chunk_size)
Definition mock_contiguous_chunks.hpp:30
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:22
void itoa(Integer_ x, std::string &output)
Definition itoa.hpp:26
Container_ create(Value_ x, Args_ &&... args)
constexpr bool is_equal(Left_ left, Right_ right)
constexpr auto min(First_ first, Second_ second)
constexpr Dest_ cap(Value_ x)
Pointer into the compressed VLS heap.
Definition Pointer.hpp:36
Options for validate_1d_pointers().
Definition validate.hpp:62
hsize_t contiguous_chunk_size
Definition validate.hpp:67
Options for validate_nd_pointers().
Definition validate.hpp:127
hsize_t contiguous_chunk_size
Definition validate.hpp:132
Iterate through an high-dimensional dataspace by chunk.
Definition IterateChunks.hpp:29
const std::vector< hsize_t > & chunk_dimensions() const
Definition IterateChunks.hpp:123
bool advance()
Definition IterateChunks.hpp:67
const std::vector< hsize_t > & starts() const
Definition IterateChunks.hpp:96
const std::vector< hsize_t > & counts() const
Definition IterateChunks.hpp:107