102 std::vector<std::size_t> dims;
106 auto shandle = group.openDataSet(
"shape");
107 auto sspace = shandle.getSpace();
108 if (sspace.getSimpleExtentNdims() != 1) {
109 throw std::runtime_error(
"expected a 1-dimensional dataset");
112 sspace.getSimpleExtentDims(&len);
114 throw std::runtime_error(
"dataset should have length 2");
117 if (version.lt(1, 1, 0)) {
118 dims = load_non_negative_integer_vector_0_99<std::size_t>(shandle, 2);
120 if (ritsuko::hdf5::exceeds_integer_limit(shandle, 64,
false)) {
121 throw std::runtime_error(
"expected a datatype that can fit into a 64-bit unsigned integer");
123 dims = load_dimensions_from_uint64_contents<std::size_t>(shandle, 2);
126 std::throw_with_nested(std::runtime_error(
"failed to validate 'shape'"));
131 auto dhandle = group.openDataSet(
"data");
132 auto dspace = dhandle.getSpace();
133 if (dspace.getSimpleExtentNdims() != 1) {
134 throw std::runtime_error(
"expected a 1-dimensional dataset");
136 dspace.getSimpleExtentDims(&nnz);
138 if (version.lt(1, 1, 0)) {
139 array_type = translate_type_0_99(dhandle.getTypeClass());
140 if (is_boolean_0_99(dhandle)) {
141 array_type = BOOLEAN;
145 auto thandle = dhandle.openAttribute(
"type");
146 auto type = read_scalar_string_attribute(thandle);
147 array_type = translate_type_1_1(type);
149 check_type_1_1(dhandle, array_type);
152 std::throw_with_nested(std::runtime_error(
"failed to validate the 'type' attribute"));
157 if (array_type != INTEGER && array_type != BOOLEAN && array_type != FLOAT) {
158 throw std::runtime_error(
"dataset should be integer, float or boolean");
160 validate_missing_placeholder(dhandle, version);
163 std::throw_with_nested(std::runtime_error(
"failed to validate 'data'"));
168 if (version.ge(1, 1, 0)) {
170 auto bhandle = group.openDataSet(
"by_column");
171 if (bhandle.getSpace().getSimpleExtentNdims() != 0) {
172 throw std::runtime_error(
"expected a scalar dataset");
174 if (ritsuko::hdf5::exceeds_integer_limit(bhandle, 8,
true)) {
175 throw std::runtime_error(
"expected a datatype that can fit into an 8-bit signed integer");
178 bhandle.read(&val, H5::PredType::NATIVE_INT8);
181 std::throw_with_nested(std::runtime_error(
"failed to validate 'by_column'"));
185 const auto primary = (csc ? dims[1] : dims[0]);
186 const auto secondary = (csc ? dims[0] : dims[1]);
188 std::vector<std::uint64_t> indptrs;
190 auto iphandle = group.openDataSet(
"indptr");
191 auto ipspace = iphandle.getSpace();
192 if (ipspace.getSimpleExtentNdims() != 1) {
193 throw std::runtime_error(
"expected a 1-dimensional dataset");
196 ipspace.getSimpleExtentDims(&iplen);
199 throw std::runtime_error(
"dataset length should be equal to the number of " + (csc ? std::string(
"columns") : std::string(
"rows")) +
" plus 1");
202 if (version.lt(1, 1, 0)) {
203 if (iphandle.getTypeClass() != H5T_INTEGER) {
204 throw std::runtime_error(
"expected an integer dataset");
206 indptrs = load_non_negative_integer_vector_0_99<std::uint64_t>(iphandle, iplen);
208 if (ritsuko::hdf5::exceeds_integer_limit(iphandle, 64,
false)) {
209 throw std::runtime_error(
"expected a datatype that can fit into a 64-bit unsigned integer");
212 iphandle.read(indptrs.data(), H5::PredType::NATIVE_UINT64);
215 iphandle.read(indptrs.data(), H5::PredType::NATIVE_UINT64);
216 if (indptrs[0] != 0) {
217 throw std::runtime_error(
"first entry should be 0");
220 throw std::runtime_error(
"last entry should be equal to the length of 'data'");
223 for (std::size_t p = 0; p < primary; ++p) {
224 const auto start = indptrs[p];
225 const auto end = indptrs[p + 1];
227 throw std::runtime_error(
"entries must be sorted in increasing order");
231 std::throw_with_nested(std::runtime_error(
"failed to validate 'indptr'"));
235 auto ihandle = group.openDataSet(
"indices");
236 auto ispace = ihandle.getSpace();
237 if (ispace.getSimpleExtentNdims() != 1) {
238 throw std::runtime_error(
"expected a 1-dimensional dataset");
241 ispace.getSimpleExtentDims(&inum);
243 throw std::runtime_error(
"dataset length should be the same as 'data'");
246 if (version.lt(1, 1, 0)) {
247 if (!ritsuko::hdf5::exceeds_integer_limit(ihandle, 64,
true)) {
248 validate_sparse_indices<std::int64_t>(ihandle, indptrs, primary, secondary, csc, options.
contiguous_chunk_size);
249 }
else if (!ritsuko::hdf5::exceeds_integer_limit(ihandle, 64,
false)) {
250 validate_sparse_indices<std::uint64_t>(ihandle, indptrs, primary, secondary, csc, options.
contiguous_chunk_size);
252 throw std::runtime_error(
"expected an integer dataset");
256 if (ritsuko::hdf5::exceeds_integer_limit(ihandle, 64,
false)) {
257 throw std::runtime_error(
"expected a datatype that can fit into a 64-bit unsigned integer");
259 validate_sparse_indices<std::uint64_t>(ihandle, indptrs, primary, secondary, csc, options.
contiguous_chunk_size);
262 std::throw_with_nested(std::runtime_error(
"failed to validate 'indices'"));
265 if (group.exists(
"dimnames")) {
267 auto dnhandle = group.openGroup(
"dimnames");
270 std::throw_with_nested(std::runtime_error(
"failed to validate 'dimnames'"));