34 const std::string type_name =
"dense_array";
36 ritsuko::Version version;
38 const auto& type_meta = extract_json_object(metadata.
other, type_name);
40 const auto& vstring = extract_json_version_string(type_meta);
41 version = ritsuko::parse_version_string(vstring.c_str(), vstring.size(),
true);
42 if (version.major != 1) {
43 throw std::runtime_error(
"unsupported version '" + vstring +
"'");
46 std::throw_with_nested(std::runtime_error(
"failed to validate 'version'"));
49 std::throw_with_nested(std::runtime_error(
"failed to validate '" + type_name +
"' in the object metadata"));
53 H5::H5File handle(path /
"array.h5", H5F_ACC_RDONLY);
54 auto ghandle = handle.openGroup(type_name);
56 if (ghandle.attrExists(
"transposed")) {
57 auto ahandle = ghandle.openAttribute(
"transposed");
58 if (ahandle.getSpace().getSimpleExtentNdims() != 0) {
59 throw std::runtime_error(
"expected 'transposed' attribute to be a scalar");
61 if (ritsuko::hdf5::exceeds_integer_limit(ahandle, 32,
true)) {
62 throw std::runtime_error(
"expected 'transposed' attribute to have a datatype that fits in a 32-bit signed integer");
68 auto thandle = ghandle.openAttribute(
"type");
69 type = open_and_load_scalar_string_attribute(thandle);
71 std::throw_with_nested(std::runtime_error(
"failed to validate the 'type' attribute"));
74 const char* missing_attr_name =
"missing-value-placeholder";
75 std::vector<hsize_t> extents;
78 if (version.lt(1, 1, 0)) {
79 throw std::runtime_error(
"unsupported type '" + type +
"'");
82 enum Failure { HEAP, POINTERS };
83 Failure who_failed = HEAP;
86 auto hhandle = ghandle.openDataSet(
"heap");
87 const auto hlen = ritsuko::cvls::validate_heap(hhandle);
89 who_failed = POINTERS;
90 auto phandle = ghandle.openDataSet(
"pointers");
91 auto pspace = phandle.getSpace();
92 auto ndim = pspace.getSimpleExtentNdims();
94 throw std::runtime_error(
"expected 'pointers' to have at least one dimension");
96 sanisizer::resize(extents, ndim);
97 pspace.getSimpleExtentDims(extents.data());
99 ritsuko::cvls::validate_nd_pointers<std::uint64_t, std::uint64_t>(
104 ritsuko::cvls::ValidateNdPointersOptions opt;
110 validate_string_missing_placeholder(phandle, missing_attr_name);
113 switch (who_failed) {
114 case HEAP: desc =
"heap";
break;
115 case POINTERS: desc =
"pointers";
break;
117 std::throw_with_nested(std::runtime_error(
"failed to validate '" + desc +
"'"));
122 auto dhandle = ghandle.openDataSet(
"data");
123 auto dspace = dhandle.getSpace();
124 auto ndim = dspace.getSimpleExtentNdims();
126 throw std::runtime_error(
"expected dataset to have at least one dimension");
128 sanisizer::resize(extents, ndim);
129 dspace.getSimpleExtentDims(extents.data());
131 if (type ==
"string") {
132 if (!ritsuko::hdf5::is_utf8_string(dhandle)) {
133 throw std::runtime_error(
"expected a datatype that can be represented by a UTF-8 encoded string");
136 ritsuko::hdf5::validate_nd_strings(
140 ritsuko::hdf5::ValidateNdStringsOptions opt;
146 validate_string_missing_placeholder(dhandle, missing_attr_name);
149 if (type ==
"integer") {
150 if (ritsuko::hdf5::exceeds_integer_limit(dhandle, 32,
true)) {
151 throw std::runtime_error(
"expected a datatype that fits into a 32-bit signed integer");
153 }
else if (type ==
"boolean") {
154 if (ritsuko::hdf5::exceeds_integer_limit(dhandle, 32,
true)) {
155 throw std::runtime_error(
"expected a datatype that fits into a 32-bit signed integer");
157 }
else if (type ==
"number") {
158 if (ritsuko::hdf5::exceeds_float_limit(dhandle, 64)) {
159 throw std::runtime_error(
"expected a datatype that fits into a 64-bit float");
162 throw std::runtime_error(
"unknown array type '" + type +
"'");
165 validate_numeric_missing_placeholder(dhandle, missing_attr_name);
168 std::throw_with_nested(std::runtime_error(
"failed to validate 'data'"));
172 validate_array_dimnames(ghandle,
"names", extents, options);
174 std::throw_with_nested(std::runtime_error(
"failed to validate '" + type_name +
"' in 'contents.h5'"));
185 H5::H5File handle(path /
"array.h5", H5F_ACC_RDONLY);
186 auto ghandle = handle.openGroup(
"dense_array");
187 auto type = open_and_load_scalar_string_attribute(ghandle.openAttribute(
"type"));
191 space = ghandle.openDataSet(
"pointers").getSpace();
193 space = ghandle.openDataSet(
"data").getSpace();
195 auto ndims = space.getSimpleExtentNdims();
196 auto extents = sanisizer::create<std::vector<hsize_t> >(ndims);
197 space.getSimpleExtentDims(extents.data());
199 std::int32_t transposed = 0;
200 if (ghandle.attrExists(
"transposed")) {
201 auto ahandle = ghandle.openAttribute(
"transposed");
202 ahandle.read(H5::PredType::NATIVE_INT32, &transposed);
205 return sanisizer::cast<std::size_t>(transposed ? extents.back() : extents.front());
215 H5::H5File handle(path /
"array.h5", H5F_ACC_RDONLY);
216 auto ghandle = handle.openGroup(
"dense_array");
217 auto type = open_and_load_scalar_string_attribute(ghandle.openAttribute(
"type"));
221 space = ghandle.openDataSet(
"pointers").getSpace();
223 space = ghandle.openDataSet(
"data").getSpace();
226 auto ndims = space.getSimpleExtentNdims();
227 auto extents = sanisizer::create<std::vector<hsize_t> >(ndims);
228 space.getSimpleExtentDims(extents.data());
230 std::int32_t transposed = 0;
231 if (ghandle.attrExists(
"transposed")) {
232 auto ahandle = ghandle.openAttribute(
"transposed");
233 ahandle.read(H5::PredType::NATIVE_INT32, &transposed);
235 std::reverse(extents.begin(), extents.end());
239 return cast_array_dimensions<std::size_t>(std::move(extents));