30inline bool checkDimensions(
const std::vector<size_t>& dims,
size_t n_dim_requested) {
31 size_t n_dim_actual = dims.size();
34 if (n_dim_requested == 0) {
35 if (n_dim_actual == 0ul) {
39 return size_t(std::count(dims.begin(), dims.end(), 1ul)) == n_dim_actual;
44 if (n_dim_actual < n_dim_requested) {
50 if (n_dim_requested == 1ul) {
51 return n_dim_actual >= 1ul &&
52 size_t(std::count(dims.begin(), dims.end(), 1ul)) >= n_dim_actual - 1ul;
57 size_t n_dim_excess = n_dim_actual - n_dim_requested;
59 bool squeeze_back =
true;
60 for (
size_t i = 1; i <= n_dim_excess; ++i) {
61 if (dims[n_dim_actual - i] != 1) {
71inline std::vector<size_t> squeezeDimensions(
const std::vector<size_t>& dims,
72 size_t n_dim_requested) {
73 auto format_error_message = [&]() -> std::string {
74 return "Can't interpret dims = " + format_vector(dims) +
" as " +
75 std::to_string(n_dim_requested) +
"-dimensional.";
78 if (n_dim_requested == 0) {
79 if (!checkDimensions(dims, n_dim_requested)) {
80 throw std::invalid_argument(
"Failed dimensions check: " + format_error_message());
86 auto n_dim = dims.size();
87 if (n_dim < n_dim_requested) {
88 throw std::invalid_argument(
"Failed 'n_dim < n_dim_requested: " + format_error_message());
91 if (n_dim_requested == 1ul) {
92 size_t non_singleton_dim = size_t(-1);
93 for (
size_t i = 0; i < n_dim; ++i) {
95 if (non_singleton_dim ==
size_t(-1)) {
96 non_singleton_dim = i;
98 throw std::invalid_argument(
"Failed one-dimensional: " +
99 format_error_message());
104 return {dims[std::min(non_singleton_dim, n_dim - 1)]};
107 size_t n_dim_excess = dims.size() - n_dim_requested;
108 for (
size_t i = 1; i <= n_dim_excess; ++i) {
109 if (dims[n_dim - i] != 1) {
110 throw std::invalid_argument(
"Failed stripping from back:" + format_error_message());
114 return std::vector<size_t>(dims.begin(),
115 dims.end() -
static_cast<std::ptrdiff_t
>(n_dim_excess));
162 using type = unqualified_t<T>;
163 using base_type = unqualified_t<T>;
164 using hdf5_type = base_type;
166 static constexpr size_t ndim = 0;
167 static constexpr size_t recursive_ndim = ndim;
168 static constexpr bool is_trivially_copyable = std::is_trivially_copyable<type>::value;
170 static std::vector<size_t> getDimensions(
const type& ) {
174 static size_t getSizeVal(
const type& val) {
178 static size_t getSize(
const std::vector<size_t>& dims) {
182 static void prepare(type& ,
const std::vector<size_t>& ) {}
184 static hdf5_type* data(type& val) {
185 static_assert(is_trivially_copyable,
"The type is not trivially copyable");
189 static const hdf5_type* data(
const type& val) {
190 static_assert(is_trivially_copyable,
"The type is not trivially copyable");
194 static void serialize(
const type& val, hdf5_type* m) {
195 static_assert(is_trivially_copyable,
"The type is not trivially copyable");
199 static void unserialize(
const hdf5_type* vec,
200 const std::vector<size_t>& ,
202 static_assert(is_trivially_copyable,
"The type is not trivially copyable");
208struct inspector: type_helper<T> {};
210enum class Boolean : int8_t {
216struct inspector<bool>: type_helper<bool> {
217 using base_type = Boolean;
218 using hdf5_type = int8_t;
220 static constexpr bool is_trivially_copyable =
false;
222 static hdf5_type* data(type& ) {
223 throw DataSpaceException(
"A boolean cannot be read directly.");
226 static const hdf5_type* data(
const type& ) {
227 throw DataSpaceException(
"A boolean cannot be written directly.");
230 static void unserialize(
const hdf5_type* vec,
231 const std::vector<size_t>& ,
233 val = vec[0] != 0 ? true :
false;
236 static void serialize(
const type& val, hdf5_type* m) {
242struct inspector<std::string>: type_helper<std::string> {
243 using hdf5_type =
const char*;
245 static hdf5_type* data(type& ) {
246 throw DataSpaceException(
"A std::string cannot be read directly.");
249 static const hdf5_type* data(
const type& ) {
250 throw DataSpaceException(
"A std::string cannot be written directly.");
254 static void serialize(
const type& val, It m) {
259 static void unserialize(
const It& vec,
const std::vector<size_t>& , type& val) {
260 const auto& view = *vec;
261 val.assign(view.data(), view.length());
266struct inspector<
Reference>: type_helper<Reference> {
267 using hdf5_type = hobj_ref_t;
269 static constexpr bool is_trivially_copyable =
false;
271 static hdf5_type* data(type& ) {
272 throw DataSpaceException(
"A Reference cannot be read directly.");
275 static const hdf5_type* data(
const type& ) {
276 throw DataSpaceException(
"A Reference cannot be written directly.");
279 static void serialize(
const type& val, hdf5_type* m) {
281 val.create_ref(&ref);
285 static void unserialize(
const hdf5_type* vec,
286 const std::vector<size_t>& ,
293struct inspector<deprecated::FixedLenStringArray<N>> {
294 using type = deprecated::FixedLenStringArray<N>;
295 using value_type =
char*;
296 using base_type = deprecated::FixedLenStringArray<N>;
297 using hdf5_type = char;
299 static constexpr size_t ndim = 1;
300 static constexpr size_t recursive_ndim = ndim;
301 static constexpr bool is_trivially_copyable =
false;
303 static std::vector<size_t> getDimensions(
const type& val) {
304 return std::vector<size_t>{val.size()};
307 static size_t getSizeVal(
const type& val) {
311 static size_t getSize(
const std::vector<size_t>& dims) {
315 static void prepare(type& ,
const std::vector<size_t>& dims) {
317 std::ostringstream os;
318 os <<
"Size of FixedlenStringArray (" << N <<
") is too small for dims (" << dims[0]
320 throw DataSpaceException(os.str());
324 static hdf5_type* data(type& val) {
328 static const hdf5_type* data(
const type& val) {
332 static void serialize(
const type& val, hdf5_type* m) {
333 for (
size_t i = 0; i < val.size(); ++i) {
334 std::memcpy(m + i * N, val[i], N);
338 static void unserialize(
const hdf5_type* vec,
const std::vector<size_t>& dims, type& val) {
339 for (
size_t i = 0; i < dims[0]; ++i) {
340 std::array<char, N> s;
341 std::memcpy(s.data(), vec + (i * N), N);
348struct inspector<std::vector<T>> {
349 using type = std::vector<T>;
350 using value_type = unqualified_t<T>;
351 using base_type =
typename inspector<value_type>::base_type;
352 using hdf5_type =
typename inspector<value_type>::hdf5_type;
354 static constexpr size_t ndim = 1;
355 static constexpr size_t recursive_ndim = ndim + inspector<value_type>::recursive_ndim;
356 static constexpr bool is_trivially_copyable = std::is_trivially_copyable<value_type>::value &&
357 inspector<value_type>::is_trivially_copyable;
359 static std::vector<size_t> getDimensions(
const type& val) {
360 std::vector<size_t> sizes(recursive_ndim, 1ul);
361 sizes[0] = val.size();
363 auto s = inspector<value_type>::getDimensions(val[0]);
364 assert(s.size() + ndim == sizes.size());
365 for (
size_t i = 0; i < s.size(); ++i) {
366 sizes[i + ndim] = s[i];
372 static size_t getSizeVal(
const type& val) {
376 static size_t getSize(
const std::vector<size_t>& dims) {
380 static void prepare(type& val,
const std::vector<size_t>& dims) {
382 std::vector<size_t> next_dims(dims.begin() + 1, dims.end());
383 for (
auto&& e: val) {
384 inspector<value_type>::prepare(e, next_dims);
388 static hdf5_type* data(type& val) {
389 return val.empty() ? nullptr : inspector<value_type>::data(val[0]);
392 static const hdf5_type* data(
const type& val) {
393 return val.empty() ? nullptr : inspector<value_type>::data(val[0]);
397 static void serialize(
const type& val, It m) {
399 size_t subsize = inspector<value_type>::getSizeVal(val[0]);
400 for (
auto&& e: val) {
401 inspector<value_type>::serialize(e, m);
408 static void unserialize(
const It& vec_align,
const std::vector<size_t>& dims, type& val) {
409 std::vector<size_t> next_dims(dims.begin() + 1, dims.end());
411 for (
size_t i = 0; i < dims[0]; ++i) {
412 inspector<value_type>::unserialize(vec_align + i * next_size, next_dims, val[i]);
418struct inspector<std::vector<bool>> {
419 using type = std::vector<bool>;
420 using value_type = bool;
421 using base_type = Boolean;
422 using hdf5_type = uint8_t;
424 static constexpr size_t ndim = 1;
425 static constexpr size_t recursive_ndim = ndim;
426 static constexpr bool is_trivially_copyable =
false;
428 static std::vector<size_t> getDimensions(
const type& val) {
429 std::vector<size_t> sizes{val.size()};
433 static size_t getSizeVal(
const type& val) {
437 static size_t getSize(
const std::vector<size_t>& dims) {
438 if (dims.size() > 1) {
439 throw DataSpaceException(
"std::vector<bool> is only 1 dimension.");
444 static void prepare(type& val,
const std::vector<size_t>& dims) {
445 if (dims.size() > 1) {
446 throw DataSpaceException(
"std::vector<bool> is only 1 dimension.");
451 static hdf5_type* data(type& ) {
452 throw DataSpaceException(
"A std::vector<bool> cannot be read directly.");
455 static const hdf5_type* data(
const type& ) {
456 throw DataSpaceException(
"A std::vector<bool> cannot be written directly.");
459 static void serialize(
const type& val, hdf5_type* m) {
460 for (
size_t i = 0; i < val.size(); ++i) {
461 m[i] = val[i] ? 1 : 0;
465 static void unserialize(
const hdf5_type* vec_align,
466 const std::vector<size_t>& dims,
468 for (
size_t i = 0; i < dims[0]; ++i) {
469 val[i] = vec_align[i] != 0 ? true :
false;
474template <
typename T,
size_t N>
475struct inspector<std::array<T, N>> {
476 using type = std::array<T, N>;
477 using value_type = unqualified_t<T>;
478 using base_type =
typename inspector<value_type>::base_type;
479 using hdf5_type =
typename inspector<value_type>::hdf5_type;
481 static constexpr size_t ndim = 1;
482 static constexpr size_t recursive_ndim = ndim + inspector<value_type>::recursive_ndim;
483 static constexpr bool is_trivially_copyable = std::is_trivially_copyable<value_type>::value &&
484 sizeof(type) == N *
sizeof(T) &&
485 inspector<value_type>::is_trivially_copyable;
487 static std::vector<size_t> getDimensions(
const type& val) {
488 std::vector<size_t> sizes{N};
490 auto s = inspector<value_type>::getDimensions(val[0]);
491 sizes.insert(sizes.end(), s.begin(), s.end());
496 static size_t getSizeVal(
const type& val) {
500 static size_t getSize(
const std::vector<size_t>& dims) {
504 static void prepare(type& val,
const std::vector<size_t>& dims) {
506 std::ostringstream os;
507 os <<
"Size of std::array (" << N <<
") is too small for dims (" << dims[0] <<
").";
508 throw DataSpaceException(os.str());
511 std::vector<size_t> next_dims(dims.begin() + 1, dims.end());
512 for (
auto&& e: val) {
513 inspector<value_type>::prepare(e, next_dims);
517 static hdf5_type* data(type& val) {
518 return inspector<value_type>::data(val[0]);
521 static const hdf5_type* data(
const type& val) {
522 return inspector<value_type>::data(val[0]);
526 static void serialize(
const type& val, It m) {
527 size_t subsize = inspector<value_type>::getSizeVal(val[0]);
529 inspector<value_type>::serialize(e, m);
535 static void unserialize(
const It& vec_align,
const std::vector<size_t>& dims, type& val) {
537 std::ostringstream os;
538 os <<
"Impossible to pair DataSet with " << dims[0] <<
" elements into an array with "
539 << N <<
" elements.";
540 throw DataSpaceException(os.str());
542 std::vector<size_t> next_dims(dims.begin() + 1, dims.end());
544 for (
size_t i = 0; i < dims[0]; ++i) {
545 inspector<value_type>::unserialize(vec_align + i * next_size, next_dims, val[i]);
552struct inspector<T*> {
554 using value_type = unqualified_t<T>;
555 using base_type =
typename inspector<value_type>::base_type;
556 using hdf5_type =
typename inspector<value_type>::hdf5_type;
558 static constexpr size_t ndim = 1;
559 static constexpr size_t recursive_ndim = ndim + inspector<value_type>::recursive_ndim;
560 static constexpr bool is_trivially_copyable = std::is_trivially_copyable<value_type>::value &&
561 inspector<value_type>::is_trivially_copyable;
563 static size_t getSizeVal(
const type& ) {
564 throw DataSpaceException(
"Not possible to have size of a T*");
567 static std::vector<size_t> getDimensions(
const type& ) {
568 throw DataSpaceException(
"Not possible to have size of a T*");
571 static const hdf5_type* data(
const type& val) {
572 return reinterpret_cast<const hdf5_type*
>(val);
577 static void serialize(
const type& , hdf5_type* ) {
578 throw DataSpaceException(
"Not possible to serialize a T*");
583template <
typename T,
size_t N>
584struct inspector<T[N]> {
586 using value_type = unqualified_t<T>;
587 using base_type =
typename inspector<value_type>::base_type;
588 using hdf5_type =
typename inspector<value_type>::hdf5_type;
590 static constexpr size_t ndim = 1;
591 static constexpr size_t recursive_ndim = ndim + inspector<value_type>::recursive_ndim;
592 static constexpr bool is_trivially_copyable = std::is_trivially_copyable<value_type>::value &&
593 inspector<value_type>::is_trivially_copyable;
595 static void prepare(type& val,
const std::vector<size_t>& dims) {
596 if (dims.size() < 1) {
597 throw DataSpaceException(
"Invalid 'dims', must be at least 1 dimensional.");
601 throw DataSpaceException(
"Dimensions mismatch.");
604 std::vector<size_t> next_dims(dims.begin() + 1, dims.end());
605 for (
size_t i = 0; i < dims[0]; ++i) {
606 inspector<value_type>::prepare(val[i], next_dims);
610 static size_t getSizeVal(
const type& val) {
614 static std::vector<size_t> getDimensions(
const type& val) {
615 std::vector<size_t> sizes{N};
617 auto s = inspector<value_type>::getDimensions(val[0]);
618 sizes.insert(sizes.end(), s.begin(), s.end());
623 static const hdf5_type* data(
const type& val) {
624 return inspector<value_type>::data(val[0]);
627 static hdf5_type* data(type& val) {
628 return inspector<value_type>::data(val[0]);
633 static void serialize(
const type& val, hdf5_type* m) {
634 size_t subsize = inspector<value_type>::getSizeVal(val[0]);
635 for (
size_t i = 0; i < N; ++i) {
636 inspector<value_type>::serialize(val[i], m + i * subsize);
size_t getSize(const File &file, const std::string &path)
Get the size of an existing DataSet in an open HDF5 file.
Definition H5Easy_public.hpp:82
Definition H5_definitions.hpp:22
size_t compute_total_size(const std::vector< size_t > &dims)
Definition H5Inspector_decl.hpp:10