Tatooine
hdf5.h
Go to the documentation of this file.
1#if TATOOINE_HDF5_AVAILABLE
2#ifndef TATOOINE_HDF5_H
3#define TATOOINE_HDF5_H
4//==============================================================================
6#include <tatooine/concepts.h>
8#include <tatooine/hdf5/type.h>
9#include <tatooine/hdf5_include.h>
11#include <tatooine/multidim.h>
13
14#include <boost/range/algorithm/reverse.hpp>
15#include <boost/range/numeric.hpp>
16#include <cassert>
17#include <memory>
18#include <numeric>
19#include <vector>
20//==============================================================================
21namespace tatooine::hdf5 {
22//==============================================================================
23static constexpr auto unlimited = H5S_UNLIMITED;
24//==============================================================================
25struct api {
26 private:
27 H5E_auto_t m_old_func = nullptr;
28 void* m_old_client_data = nullptr;
29 //----------------------------------------------------------------------------
30 api() { H5Eget_auto(H5E_DEFAULT, &m_old_func, &m_old_client_data); }
31
32 public:
33 //----------------------------------------------------------------------------
34 static auto get() -> auto& {
35 static auto obj = api{};
36 return obj;
37 }
38 //----------------------------------------------------------------------------
39 public:
40 static auto disable_error_printing() -> void {
41 get()._disable_error_printing();
42 }
43 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
44 private:
45 auto _disable_error_printing() -> void {
46 H5Eset_auto(H5E_DEFAULT, nullptr, nullptr);
47 }
48 //----------------------------------------------------------------------------
49 public:
50 static auto enable_error_printing() -> void {
51 get()._enable_error_printing();
52 }
53 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
54 private:
55 auto _enable_error_printing() -> void {
56 H5Eset_auto(H5E_DEFAULT, m_old_func, m_old_client_data);
57 }
58 //----------------------------------------------------------------------------
59 static auto error_handler(void* /*error_data*/) -> herr_t {
60 std::cerr << "An HDF5 error was detected. Bye.\n";
61 exit(1);
62 }
63};
64//==============================================================================
65struct id_holder {
66 //============================================================================
67 private:
68 hid_t m_id = hid_t{};
69
70 public:
71 explicit id_holder(hid_t const id) : m_id{id} {}
72 auto id() const { return m_id; }
73 auto set_id(hid_t const id) { m_id = id; }
74};
75//==============================================================================
77 //============================================================================
78 // FACTORIES
79 //============================================================================
80 static auto dataset_creation() { return property_list{H5P_DATASET_CREATE}; }
81
82 //============================================================================
83 // CTORS
84 //============================================================================
85 public:
86 explicit property_list(hid_t cls_id = H5P_DEFAULT)
87 : id_holder{cls_id == H5P_DEFAULT ? H5P_DEFAULT : H5Pcreate(cls_id)} {}
88 property_list(property_list const& other) : id_holder{H5Pcopy(other.id())} {}
89 auto operator=(property_list const& other) -> property_list& {
90 close();
91 set_id(H5Pcopy(other.id()));
92 return *this;
93 }
95
96 //============================================================================
97 // GETTERS
98 //============================================================================
99 [[nodiscard]] auto is_default() const { return id() == H5P_DEFAULT; }
100
101 //============================================================================
102 // METHODS
103 //============================================================================
104 auto close() -> void {
105 if (!is_default()) {
106 H5Pclose(id());
107 }
108 }
109 //----------------------------------------------------------------------------
110 auto set_chunk(integral auto const... size) {
111 auto dim = std::array{static_cast<hsize_t>(size)...};
112 H5Pset_chunk(id(), sizeof...(size), dim.data());
113 }
114};
115//==============================================================================
117 //============================================================================
118 // CTORS
119 //============================================================================
120 public:
121 dataspace(dataspace const& other) : id_holder{H5Scopy(other.id())} {}
122 //----------------------------------------------------------------------------
123 explicit dataspace(hid_t const id) : id_holder{id} {}
124 //----------------------------------------------------------------------------
125 explicit dataspace(integral auto const... size)
126 : dataspace{std::array{static_cast<hsize_t>(size)...}} {}
127 //----------------------------------------------------------------------------
128 explicit dataspace(std::vector<hsize_t> cur_resolution)
129 : id_holder{H5Screate_simple(static_cast<int>(cur_resolution.size()),
130 boost::reverse(cur_resolution).data(),
131 nullptr)} {}
132 //----------------------------------------------------------------------------
133 dataspace(std::vector<hsize_t> cur_resolution,
134 std::vector<hsize_t> max_resolution)
135 : id_holder{H5Screate_simple(static_cast<int>(cur_resolution.size()),
136 boost::reverse(cur_resolution).data(),
137 boost::reverse(max_resolution).data())} {}
138 //----------------------------------------------------------------------------
139 template <std::size_t N>
140 explicit dataspace(std::array<hsize_t, N> cur_resolution)
141 : id_holder{H5Screate_simple(N, boost::reverse(cur_resolution).data(),
142 nullptr)} {}
143 //----------------------------------------------------------------------------
144 template <std::size_t N>
145 dataspace(std::array<hsize_t, N> cur_resolution,
146 std::array<hsize_t, N> maxdims)
147 : id_holder{H5Screate_simple(N, boost::reverse(cur_resolution).data(),
148 boost::reverse(maxdims).data())} {}
149 //----------------------------------------------------------------------------
150 ~dataspace() { H5Sclose(id()); }
151
152 //============================================================================
153 // METHODS
154 //============================================================================
155 auto rank() const { return H5Sget_simple_extent_ndims(id()); }
156 //------------------------------------------------------------------------------
157 auto current_resolution() const {
158 using res_container = std::vector<hsize_t>;
159 using size_type = typename res_container::size_type;
160 auto cur_res = res_container(static_cast<size_type>(rank()));
161 H5Sget_simple_extent_dims(id(), cur_res.data(), nullptr);
162 return boost::reverse(cur_res);
163 }
164 //------------------------------------------------------------------------------
165 auto max_resolution() const {
166 using res_container = std::vector<hsize_t>;
167 using size_type = typename res_container::size_type;
168 auto max_res = res_container(static_cast<size_type>(rank()));
169 H5Sget_simple_extent_dims(id(), nullptr, max_res.data());
170 return boost::reverse(max_res);
171 }
172 //------------------------------------------------------------------------------
174 using hsize_t_container = std::vector<hsize_t>;
175 using size_type = typename hsize_t_container::size_type;
176 auto ret = std::tuple{hsize_t_container(static_cast<size_type>(rank())),
177 hsize_t_container(static_cast<size_type>(rank()))};
178 H5Sget_simple_extent_dims(id(), std::get<0>(ret).data(),
179 std::get<1>(ret).data());
180 boost::reverse(std::get<0>(ret));
181 boost::reverse(std::get<1>(ret));
182 return ret;
183 }
184 //------------------------------------------------------------------------------
185 auto num_elements() const { return H5Sget_simple_extent_npoints(id()); }
186 auto selected_num_elements() const { return H5Sget_select_npoints(id()); }
187 auto num_hyperslab_blocks() const {
188 return H5Sget_select_hyper_nblocks(id());
189 }
191 return H5Sget_select_elem_npoints(id());
192 }
193 //------------------------------------------------------------------------------
194 auto select_hyperslab(hsize_t const* start, hsize_t const* stride,
195 hsize_t const* count, hsize_t const* block = nullptr) {
196 H5Sselect_hyperslab(id(), H5S_SELECT_SET, start, stride, count, block);
197 }
198 //------------------------------------------------------------------------------
199 auto select_hyperslab(H5S_seloper_t op, hsize_t const* start,
200 hsize_t const* stride, hsize_t const* count,
201 hsize_t const* block = nullptr) {
202 H5Sselect_hyperslab(id(), op, start, stride, count, block);
203 }
204 //------------------------------------------------------------------------------
205 auto select_hyperslab(std::vector<hsize_t> offset,
206 std::vector<hsize_t> stride,
207 std::vector<hsize_t> count) {
208 boost::reverse(offset);
209 boost::reverse(stride);
210 boost::reverse(count);
211 select_hyperslab(offset.data(), stride.data(), count.data());
212 }
213 //------------------------------------------------------------------------------
214 auto select_hyperslab(std::vector<hsize_t> offset,
215 std::vector<hsize_t> count) {
216 boost::reverse(offset);
217 boost::reverse(count);
218 select_hyperslab(offset.data(), nullptr, count.data());
219 }
220 //------------------------------------------------------------------------------
221 auto select_hyperslab(hsize_t const offset, hsize_t const count) {
222 select_hyperslab(&offset, nullptr, &count);
223 }
224 //------------------------------------------------------------------------------
225 auto is_unlimited() const {
226 bool has_unlimited_dimension = false;
227 auto max = max_resolution();
228 for (auto dim : max) {
229 if (dim == unlimited) {
230 has_unlimited_dimension = true;
231 break;
232 }
233 }
234 return has_unlimited_dimension;
235 }
236 //----------------------------------------------------------------------------
237 auto name() const {
238 auto n = std::string(
239 static_cast<std::string::size_type>(H5Aget_name(id(), 0, nullptr)),
240 ' ');
241 H5Aget_name(id(), n.size(), n.data());
242 return n;
243 }
244 //----------------------------------------------------------------------------
245 auto info() const {
246 auto i = H5A_info_t{};
247 H5Aget_info(id(), &i);
248 return i;
249 }
250};
251//==============================================================================
252struct attribute {
253 public:
255
256 private:
258 std::string m_name;
259
260 public:
261 attribute(hid_t const parent_id, std::string name)
262 : m_parent_id{parent_id}, m_name{std::move(name)} {
263 H5Iinc_ref(m_parent_id);
264 }
265 //----------------------------------------------------------------------------
266 attribute(attribute&&) noexcept = default;
267 auto operator=(attribute&&) noexcept -> attribute& = default;
268 //----------------------------------------------------------------------------
269 ~attribute() { H5Idec_ref(m_parent_id); }
270 //----------------------------------------------------------------------------
271 template <typename T>
272 auto read_as() const {
273 T attr;
274 auto attr_id = H5Aopen(m_parent_id, m_name.c_str(), H5P_DEFAULT);
275 if (attr_id < 0) {
276 throw std::runtime_error{"Attribute not found."};
277 }
278 auto t = H5Aget_type(attr_id);
279 if constexpr (is_same<T, std::string>) {
280 attr = T(H5Tget_size(t) - 1, ' ');
281 H5Aread(attr_id, t, attr.data());
282 } else {
283 H5Aread(attr_id, t, &attr);
284 }
285 H5Tclose(t);
286 H5Aclose(attr_id);
287 return attr;
288 }
289 //----------------------------------------------------------------------------
290 auto read_as_string() const { return read_as<std::string>(); }
291 //----------------------------------------------------------------------------
292 auto read_int() const { return read_as<int>(); }
293 //----------------------------------------------------------------------------
294 auto read_float() const { return read_as<float>(); }
295 //----------------------------------------------------------------------------
296 auto read_double() const { return read_as<double>(); }
297 //----------------------------------------------------------------------------
298 auto read_int8() const { return read_as<std::int8_t>(); }
299 //----------------------------------------------------------------------------
300 auto read_uint8() const { return read_as<std::uint8_t>(); }
301 //----------------------------------------------------------------------------
302 auto read_int16() const { return read_as<std::int16_t>(); }
303 //----------------------------------------------------------------------------
304 auto read_uint16() const { return read_as<std::uint16_t>(); }
305 //----------------------------------------------------------------------------
306 auto read_int32() const { return read_as<std::int32_t>(); }
307 //----------------------------------------------------------------------------
308 auto read_uint32() const { return read_as<std::uint32_t>(); }
309 //----------------------------------------------------------------------------
310 template <typename T>
311 auto write(T const& val) {
312 if (H5Aexists(m_parent_id, m_name.c_str()) > 0) {
313 H5Adelete(m_parent_id, m_name.c_str());
314 }
315
316 auto ds = hdf5::dataspace{H5Screate(H5S_SCALAR)};
317 auto type = hdf5::type<T>{};
318 if constexpr (is_same<T, std::string>) {
319 type.set_size(val.size() + 1);
320 } else if constexpr (is_same<T, char const*>) {
321 type.set_size(std::strlen(val));
322 }
324 auto attr_id = H5Acreate(m_parent_id, m_name.c_str(), type.id(), ds.id(),
325 H5P_DEFAULT, H5P_DEFAULT);
327 if (attr_id >= 0) {
328 if constexpr (is_same<T, std::string>) {
329 H5Awrite(attr_id, type.id(), val.data());
330 } else if constexpr (is_same<T, char const*>) {
331 H5Awrite(attr_id, type.id(), val);
332 } else {
333 H5Awrite(attr_id, type.id(), &val);
334 }
335 H5Aclose(attr_id);
336 }
337 }
338 //----------------------------------------------------------------------------
339 template <typename T>
340 auto operator=(T const& val) -> attribute& {
341 write(val);
342 return *this;
343 }
344};
345//==============================================================================
346template <typename IDHolder>
348 auto as_id_holder() -> auto& { return *static_cast<IDHolder*>(this); }
349 auto as_id_holder() const -> auto const& {
350 return *static_cast<IDHolder const*>(this);
351 }
352 //----------------------------------------------------------------------------
353 [[nodiscard]] auto attribute(char const* name) const {
354 return hdf5::attribute{as_id_holder().id(), name};
355 }
356 //----------------------------------------------------------------------------
357 [[nodiscard]] auto attribute(std::string const& name) const {
358 return attribute(name.c_str());
359 }
360};
361//==============================================================================
362template <typename T>
363struct dataset : id_holder, attribute_creator<dataset<T>> {
364 public:
366 using value_type = T;
367
368 private:
370 std::string m_name;
371 //============================================================================
372 public:
373 template <typename... Size>
374 dataset(hid_t const parent_id, std::string const& name, Size const... size)
375 : id_holder{-1}, m_parent_id{parent_id}, m_name{name} {
376 if constexpr (sizeof...(Size) > 0) {
377 auto dims = std::array{static_cast<hsize_t>(size)...};
378 bool has_unlimited_dimension = false;
379 for (auto dim : dims) {
380 if (dim == unlimited) {
381 has_unlimited_dimension = true;
382 break;
383 }
384 }
385 auto plist = property_list{};
386 auto maxdims = dims;
387 if (has_unlimited_dimension) {
388 for (auto& dim : dims) {
389 if (dim == unlimited) {
390 dim = 0;
391 }
392 }
394 plist.set_chunk(
395 (static_cast<hsize_t>(size) == unlimited ? 100 : size)...);
396 }
397 auto ds = hdf5::dataspace{dims, maxdims};
398 set_id(H5Dcreate(parent_id, name.data(), type_id<T>(), ds.id(),
399 H5P_DEFAULT, plist.id(), H5P_DEFAULT));
400 if (id() < 0) {
401 set_id(H5Dopen(m_parent_id, name.c_str(), H5P_DEFAULT));
402 resize(size...);
403 }
404 } else {
405 set_id(H5Dopen(m_parent_id, name.c_str(), H5P_DEFAULT));
406 }
407 }
408 //----------------------------------------------------------------------------
409 dataset(dataset const& other)
410 : id_holder{other.id()},
412 m_name{other.m_name} {}
413 //----------------------------------------------------------------------------
414 dataset(dataset&&) noexcept = default;
415 //----------------------------------------------------------------------------
416 auto operator=(dataset const& other) -> dataset& {
417 // if (m_parent_id != nullptr) {
418 // H5Fclose(m_parent_id);
419 //}
420 H5Dclose(id());
421 set_id(other.id());
422 m_parent_id = other.m_parent_id;
423 m_name = other.m_name;
424 return *this;
425 }
426 //----------------------------------------------------------------------------
427 auto operator=(dataset&&) noexcept -> dataset& = default;
428 //----------------------------------------------------------------------------
430 // if (m_parent_id != nullptr) {
431 // H5Fclose(m_parent_id);
432 //}
433 H5Dclose(id());
434 }
435 //============================================================================
436 auto resize(hsize_t const extent) { H5Dset_extent(id(), &extent); }
437 //----------------------------------------------------------------------------
438 auto resize(std::vector<hsize_t> const& extent) {
439 H5Dset_extent(id(), extent.data());
440 }
441 //----------------------------------------------------------------------------
442 template <std::size_t N>
443 auto resize(std::array<hsize_t, N> const& extent) {
444 H5Dset_extent(id(), extent.data());
445 }
446 //----------------------------------------------------------------------------
447 template <integral Integral>
448 auto resize(std::vector<Integral> const& extent) {
449 resize(std::vector<hsize_t>(begin(extent), end(extent)));
450 }
451 //----------------------------------------------------------------------------
452 template <integral Integral, std::size_t N>
453 auto resize(std::array<Integral, N> const& extent) {
454 resize(std::array<hsize_t, N>(begin(extent), end(extent)));
455 }
456 //----------------------------------------------------------------------------
457 template <typename... Size>
458 auto resize(Size const... size) {
459 resize(std::array{static_cast<hsize_t>(size)...});
460 }
461 //----------------------------------------------------------------------------
462 auto resize_if_necessary(hsize_t const requested_size) {
463 auto ds = dataspace();
464 auto const [cur_res, max_res] = ds.current_and_max_resolution();
465 assert(cur_res.size() == 1);
466 if (requested_size > cur_res[0] && max_res[0] == unlimited) {
467 resize(requested_size);
468 }
469 }
470 //----------------------------------------------------------------------------
471 auto resize_if_necessary(std::vector<hsize_t> const& requested_size) {
472 auto ds = dataspace();
473 auto const [cur_res, max_res] = ds.current_and_max_resolution();
474 assert(cur_res.size() == requested_size.size());
475 bool must_resize = true;
476 for (std::size_t i = 0; i < cur_res.size(); ++i) {
477 if (requested_size[i] > cur_res[i] && max_res[i] == unlimited) {
478 must_resize = true;
479 break;
480 }
481 }
482 if (must_resize) {
483 resize(requested_size);
484 }
485 }
486 //============================================================================
487 auto clear() {
488 auto s = std::vector<hsize_t>(dataspace().rank(), 0);
489 resize(s);
490 }
491 //============================================================================
492 auto write(hid_t mem_space_id, hid_t file_space_id, hid_t xfer_plist_id,
493 const void* buf) const -> void {
494 H5Dwrite(id(), type_id<T>(), mem_space_id, file_space_id, xfer_plist_id,
495 buf);
496 }
497 //----------------------------------------------------------------------------
498 auto write(T const* data) -> void {
499 write(H5S_ALL, H5S_ALL, H5P_DEFAULT, data);
500 }
501 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
502 auto write(std::vector<T> const& data) -> void {
503 resize_if_necessary(data.size());
504 write(H5S_ALL, H5S_ALL, H5P_DEFAULT, data.data());
505 }
506 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
507 auto write(std::vector<T> const& data, hsize_t const offset) -> void {
508 resize_if_necessary(data.size() + offset);
509 write(data.data(), std::vector{offset},
510 std::vector{static_cast<hsize_t>(data.size())});
511 }
512 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
513 auto push_back(std::vector<T> const& data) -> void {
514 auto cur_res = dataspace().current_resolution();
515 write(data, cur_res[0]);
516 }
517 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
518 auto push_back(T const& data) -> void {
519 auto cur_res = dataspace().current_resolution();
520 resize_if_necessary(cur_res[0] + 1);
521 write(&data, std::vector{cur_res[0]}, std::vector{hsize_t(1)});
522 }
523 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
524 template <std::size_t N>
525 auto write(std::array<T, N> const& data) -> void {
526 resize_if_necessary(data.size());
527 write(H5S_ALL, H5S_ALL, H5P_DEFAULT, data.data());
528 }
529 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
530 // template <range Range>
531 // auto write(Range&& r) -> void {
532 // write(std::vector(begin(r), end(r)));
533 // }
534 //----------------------------------------------------------------------------
535 template <typename IndexOrder>
537 write(data.data());
538 }
539 //----------------------------------------------------------------------------
540 template <typename IndexOrder>
542 std::vector<std::size_t> const& offset) -> void {
543 assert(data.num_dimensions() == offset.size());
544 auto const size = data.size();
545 auto total_size = size;
546 for (std::size_t i = 0; i < size.size(); ++i) {
547 total_size[i] += offset[i];
548 }
549 resize_if_necessary(total_size);
550 write(data.data(), std::vector<hsize_t>(begin(offset), end(offset)),
551 std::vector<hsize_t>(begin(size), end(size)));
552 }
553 // //----------------------------------------------------------------------------
554 // template <typename IndexOrder, integral... Is>
555 // auto write(dynamic_multidim_array<T, IndexOrder> const& data, Is const...
556 // is)
557 // -> void {
558 // auto const s = data.size();
559 // write<IndexOrder>(data.data(),
560 // std::vector<hsize_t>{static_cast<hsize_t>(is)...},
561 // std::vector<hsize_t>(begin(s), end(s)));
562 // }
563 //----------------------------------------------------------------------------
564 template <typename IndexOrder = x_fastest, integral... Is>
565 auto write(T const& data, Is const... is) -> void {
566 write<IndexOrder>(&data, std::vector<hsize_t>{static_cast<hsize_t>(is)...},
567 std::vector<hsize_t>(sizeof...(Is), 1));
568 }
569 //----------------------------------------------------------------------------
570 auto write(T const& data, std::vector<std::size_t> const& offset) -> void {
571 write(&data, std::vector<hsize_t>(begin(offset), end(offset)),
572 std::vector<hsize_t>(size(offset), 1));
573 }
574 //----------------------------------------------------------------------------
575 auto write(T const& data, std::vector<hsize_t> offset) -> void {
576 write(&data, std::move(offset), std::vector<hsize_t>(size(offset), 1));
577 }
578 //----------------------------------------------------------------------------
579 auto write(std::vector<T> const& data, std::vector<std::size_t> const& offset,
580 std::vector<std::size_t> const& count) -> void {
581 write(data.data(), std::vector<hsize_t>(begin(offset), end(offset)),
582 std::vector<hsize_t>(begin(count), end(count)));
583 }
584 //----------------------------------------------------------------------------
585 auto write(T const* data, std::vector<std::size_t> const& offset,
586 std::vector<std::size_t> const& count) -> void {
587 write(data, std::vector<hsize_t>(begin(offset), end(offset)),
588 std::vector<hsize_t>(begin(count), end(count)));
589 }
590 //----------------------------------------------------------------------------
591 auto write(std::vector<T> const& data, std::vector<hsize_t> offset,
592 std::vector<hsize_t> count) -> void {
593 write(data.data(), std::move(offset), std::move(count));
594 }
595 //----------------------------------------------------------------------------
596 template <typename IndexOrder = x_fastest>
597 auto write(T const* data, std::vector<hsize_t> offset,
598 std::vector<hsize_t> count) -> void {
599 assert(offset.size() == count.size());
600
601 auto dataset_space = dataspace();
602 dataset_space.select_hyperslab(offset, count);
603 auto memory_space = hdf5::dataspace{count};
604 write(memory_space.id(), dataset_space.id(), H5P_DEFAULT, data);
605 }
606 //============================================================================
607 auto read(hid_t mem_space_id, hid_t file_space_id, hid_t xfer_plist_id,
608 T* buf) const -> void {
609 H5Dread(id(), type_id<T>(), mem_space_id, file_space_id, xfer_plist_id,
610 buf);
611 }
612 //----------------------------------------------------------------------------
613 template <typename IndexOrder = x_fastest>
614 auto read() const {
616 read(arr);
617 return arr;
618 }
619 //----------------------------------------------------------------------------
620 template <typename IndexOrder>
622 auto dataset_space = dataspace();
623 auto const rank = dataset_space.rank();
624 auto size = dataset_space.current_resolution();
625 bool must_resize = (unsigned int)rank != arr.num_dimensions();
626 if (!must_resize) {
627 for (int i = 0; i < rank; ++i) {
628 if (arr.size(i) != size[i]) {
629 must_resize = true;
630 break;
631 }
632 }
633 }
634 if (must_resize) {
635 arr.resize(std::vector<std::size_t>(begin(size), end(size)));
636 }
637 read(H5S_ALL, H5S_ALL, H5P_DEFAULT, arr.data());
638 }
639 //----------------------------------------------------------------------------
640 auto read_as_vector() const {
641 std::vector<T> data;
642 read(data);
643 return data;
644 }
645 //----------------------------------------------------------------------------
646 auto read(std::vector<hsize_t> const& offset,
647 std::vector<hsize_t> const& count, std::vector<T>& data) const {
648 assert(offset.size() == count.size());
649
650 auto dataset_space = dataspace();
651 dataset_space.select_hyperslab(offset, count);
652
653 auto memory_space = hdf5::dataspace{count};
654 read(memory_space.id(), dataset_space.id(), H5P_DEFAULT, data.data());
655 }
656 //----------------------------------------------------------------------------
657 auto read(hsize_t const offset, hsize_t const count,
658 std::vector<T>& data) const {
659 assert(count == data.size());
660 auto dataset_space = dataspace();
661 dataset_space.select_hyperslab(offset, count);
662
663 auto memory_space = hdf5::dataspace{count};
664 read(memory_space.id(), dataset_space.id(), H5P_DEFAULT, data.data());
665 }
666 //----------------------------------------------------------------------------
667 template <integral Int0, integral Int1>
668 auto read_as_vector(std::vector<Int0> const& offset,
669 std::vector<Int1> const& count) const {
670 return read_as_vector(std::vector<hsize_t>(begin(offset), end(offset)),
671 std::vector<hsize_t>(begin(count), end(count)));
672 }
673 //----------------------------------------------------------------------------
674 template <typename IndexOrder = x_fastest>
675 auto read(std::vector<T>& data) const {
676 std::size_t num_entries =
677 boost::accumulate(dataspace().current_resolution(), std::size_t(1),
678 std::multiplies<std::size_t>{});
679 if (data.size() != num_entries) {
680 data.resize(num_entries);
681 }
682
683 read(H5S_ALL, H5S_ALL, H5P_DEFAULT, data.data());
684 }
685 //----------------------------------------------------------------------------
686 template <typename IndexOrder>
687 auto read(std::vector<std::size_t> const& offset,
688 std::vector<std::size_t> const& count,
690 read(std::vector<hsize_t>(begin(offset), end(offset)),
691 std::vector<hsize_t>(begin(count), end(count)), arr);
692 return arr;
693 }
694 //----------------------------------------------------------------------------
695 template <typename IndexOrder = x_fastest>
696 auto read(std::vector<std::size_t> const& offset,
697 std::vector<std::size_t> const& count) const
698 requires(!is_same<hsize_t, std::size_t>)
699 {
700 return read<IndexOrder>(std::vector<hsize_t>(begin(offset), end(offset)),
701 std::vector<hsize_t>(begin(count), end(count)));
702 }
703 //----------------------------------------------------------------------------
704 template <typename IndexOrder = x_fastest>
705 auto read(std::vector<hsize_t> const& offset,
706 std::vector<hsize_t> const& count) const {
708 read(offset, count, arr);
709 return arr;
710 }
711 //----------------------------------------------------------------------------
712 template <typename IndexOrder>
713 auto read(std::vector<hsize_t> offset, std::vector<hsize_t> count,
714 dynamic_multidim_array<T, IndexOrder>& arr) const -> auto& {
715 assert(offset.size() == count.size());
716
717 std::vector<hsize_t> count_without_ones;
718
719 auto ds = dataspace();
720 std::size_t rank = 0;
721 for (std::size_t i = 0; i < count.size(); ++i) {
722 if (count[i] > 1) {
723 ++rank;
724 count_without_ones.push_back(count[i]);
725 }
726 }
727 std::size_t num_dimensions = 0;
728 for (std::size_t i = 0; i < arr.num_dimensions(); ++i) {
729 if (arr.size(i) > 1) {
731 }
732 }
733
734 if (rank != num_dimensions) {
735 arr.resize(count);
736 } else {
737 for (std::size_t i = 0; i < rank; ++i) {
738 if (arr.size(i) != count_without_ones[i]) {
739 arr.resize(count_without_ones);
740 break;
741 }
742 }
743 }
744 ds.select_hyperslab(offset, count);
745 auto memory_space = hdf5::dataspace{count};
746 read(memory_space.id(), ds.id(), H5P_DEFAULT, arr.data());
747 return arr;
748 }
749 //----------------------------------------------------------------------------
750 auto read(integral auto const... is) const {
751 auto offset = std::vector<hsize_t>{static_cast<hsize_t>(is)...};
752 auto count = std::vector<hsize_t>(sizeof...(is), 1);
753
754 auto ds = dataspace();
755 ds.select_hyperslab(offset, count);
756 auto ms = hdf5::dataspace{count};
757 T data;
758 read(ms.id(), ds.id(), H5P_DEFAULT, &data);
759 return data;
760 }
761 //----------------------------------------------------------------------------
762 auto operator[](hsize_t const i) const { return read(i); }
763 //----------------------------------------------------------------------------
764 auto num_dimensions() const -> std::size_t {
765 auto dataset_space = H5Dget_space(id());
766 auto ndims = H5Sget_simple_extent_ndims(dataset_space);
767 H5Sclose(dataset_space);
768 return ndims;
769 }
770 //----------------------------------------------------------------------------
771 auto read_lazy(std::vector<std::size_t> const& chunk_size) {
772 return lazy_reader<this_type>{*this, chunk_size};
773 }
774 //----------------------------------------------------------------------------
775 auto name() const -> auto const& { return m_name; }
776 //----------------------------------------------------------------------------
777 auto dataspace() const { return hdf5::dataspace{H5Dget_space(id())}; }
778 auto flush() { H5Dflush(id()); }
779 //----------------------------------------------------------------------------
780 auto size() const { return dataspace().current_resolution(); }
781};
782//==============================================================================
783template <typename IDHolder>
785 auto as_id_holder() -> auto& { return *static_cast<IDHolder*>(this); }
786 auto as_id_holder() const -> auto const& {
787 return *static_cast<IDHolder const*>(this);
788 }
789 template <typename T, typename IndexOrder = x_fastest>
790 auto create_dataset(std::string const& name, integral auto const... size) {
791 return hdf5::dataset<T>{as_id_holder().id(), name, size...};
792 }
793 //----------------------------------------------------------------------------
794 template <typename T>
795 [[nodiscard]] auto dataset(char const* name) const {
796 return hdf5::dataset<T>{as_id_holder().id(), name};
797 }
798 //----------------------------------------------------------------------------
799 template <typename T>
800 [[nodiscard]] auto dataset(std::string const& name) const {
801 return dataset<T>(name.c_str());
802 }
803};
804//==============================================================================
805struct group;
806//==============================================================================
807template <typename IDHolder>
809 auto as_id_holder() -> auto& { return *static_cast<IDHolder*>(this); }
810 auto as_id_holder() const -> auto const& {
811 return *static_cast<IDHolder const*>(this);
812 }
813 //============================================================================
814 auto group(char const* name) {
815 return hdf5::group{as_id_holder().id(), name};
816 }
817 //----------------------------------------------------------------------------
818 auto group(std::string const& name) { return group(name.data()); }
819};
820//==============================================================================
821template <typename IDHolder>
823 dataset_creator<IDHolder>,
824 attribute_creator<IDHolder>,
825 group_creator<IDHolder> {
826 node(hid_t const id) : id_holder{id} {}
827};
828//==============================================================================
829struct group : node<group> {
830 public:
832
833 private:
834 std::string m_name;
835 //============================================================================
836 public:
837 group(hid_t const parent_id, char const* name)
838 : node{H5Gopen(parent_id, name, H5P_DEFAULT)}, m_name{name} {
839 if (id() < 0) {
840 set_id(H5Gcreate(parent_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT));
841 }
842 }
843 //----------------------------------------------------------------------------
844 group(hid_t const parent_id, std::string const& name)
845 : group{parent_id, name.c_str()} {}
846 //----------------------------------------------------------------------------
847 group(group&&) noexcept = default;
848 //----------------------------------------------------------------------------
849 auto operator=(group const& other) -> group& {
850 H5Gclose(id());
851 set_id(other.id());
852 m_name = other.m_name;
853 return *this;
854 }
855 //----------------------------------------------------------------------------
856 auto operator=(group&&) noexcept -> group& = default;
857 //----------------------------------------------------------------------------
858 ~group() { H5Gclose(id()); }
859 //============================================================================
860 auto sub_group(char const* name) { return node<group>::group(name); }
861 auto sub_group(std::string const& name) { return node<group>::group(name); }
862};
863//==============================================================================
864struct file : node<file> {
865 public:
866 explicit file(filesystem::path const& path) : node{-1} {
868
869#if defined(_WIN32) || defined(WIN32)
870 char* path_c_str;
871 std::wcstombs(path_c_str, path.c_str(), path.string().size() + 1);
872 open(path_c_str);
873#else
874 open(path.c_str());
875#endif
876 }
877 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
878 explicit file(std::string const& path) : file{path.data()} {}
879 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
880 explicit file(char const* path) : node{-1} {
882 open(path);
883 }
884 //----------------------------------------------------------------------------
885 file(file const& other) : node{other.id()} {}
886 //----------------------------------------------------------------------------
887 file(file&&) noexcept = default;
888 //----------------------------------------------------------------------------
889 auto operator=(file const& other) -> file& {
890 H5Fclose(id());
891 set_id(other.id());
892 return *this;
893 }
894 //----------------------------------------------------------------------------
895 auto operator=(file&&) noexcept -> file& = default;
896 //----------------------------------------------------------------------------
897 ~file() { H5Fclose(id()); }
898
899 private:
900 auto open(char const* path) -> void {
901 if (filesystem::exists(filesystem::path{path})) {
902 set_id(H5Fopen(path, H5F_ACC_RDWR, H5P_DEFAULT));
903 } else {
904 set_id(H5Fcreate(path, H5F_ACC_EXCL, H5P_DEFAULT, H5P_DEFAULT));
905 }
906 }
907
908 public:
909 //----------------------------------------------------------------------------
910 auto node_exists(char const* name,
911 hid_t link_access_property_list_id = H5P_DEFAULT) const {
912 return H5Lexists(id(), name, link_access_property_list_id);
913 }
914 //----------------------------------------------------------------------------
915 auto node_exists(std::string const& name,
916 hid_t link_access_property_list_id = H5P_DEFAULT) const {
917 return node_exists(name.c_str(), link_access_property_list_id);
918 }
919};
920//==============================================================================
921} // namespace tatooine::hdf5
922//==============================================================================
923#endif
924#else
925#pragma message("including <tatooine/hdf5.h> without HDF5 support.")
926#endif
Definition: dynamic_multidim_array.h:18
constexpr auto data(std::size_t const i) -> auto &
Definition: dynamic_multidim_array.h:311
auto size() const -> auto const &
Definition: dynamic_multidim_size.h:107
auto resize(integral auto const ... size) -> void
Definition: dynamic_multidim_array.h:273
auto num_dimensions() const
Definition: dynamic_multidim_size.h:105
Definition: concepts.h:21
Definition: solver.h:9
Definition: hdf5.h:21
static constexpr auto unlimited
Definition: hdf5.h:23
auto begin(Range &&range)
Definition: iterator_facade.h:318
auto end(Range &&range)
Definition: iterator_facade.h:322
constexpr auto max(A &&a, B &&b)
Definition: math.h:20
auto size(vec< ValueType, N > const &v)
Definition: vec.h:148
constexpr auto rank()
Definition: rank.h:10
Definition: hdf5.h:25
void * m_old_client_data
Definition: hdf5.h:28
auto _enable_error_printing() -> void
Definition: hdf5.h:55
api()
Definition: hdf5.h:30
static auto error_handler(void *) -> herr_t
Definition: hdf5.h:59
static auto disable_error_printing() -> void
Definition: hdf5.h:40
auto _disable_error_printing() -> void
Definition: hdf5.h:45
static auto get() -> auto &
Definition: hdf5.h:34
static auto enable_error_printing() -> void
Definition: hdf5.h:50
H5E_auto_t m_old_func
Definition: hdf5.h:27
Definition: hdf5.h:347
auto attribute(char const *name) const
Definition: hdf5.h:353
auto as_id_holder() const -> auto const &
Definition: hdf5.h:349
auto as_id_holder() -> auto &
Definition: hdf5.h:348
auto attribute(std::string const &name) const
Definition: hdf5.h:357
Definition: hdf5.h:252
auto read_int16() const
Definition: hdf5.h:302
attribute(hid_t const parent_id, std::string name)
Definition: hdf5.h:261
auto read_int8() const
Definition: hdf5.h:298
std::string m_name
Definition: hdf5.h:258
auto read_as_string() const
Definition: hdf5.h:290
hid_t m_parent_id
Definition: hdf5.h:257
auto read_int() const
Definition: hdf5.h:292
auto read_as() const
Definition: hdf5.h:272
auto read_uint16() const
Definition: hdf5.h:304
auto write(T const &val)
Definition: hdf5.h:311
auto operator=(T const &val) -> attribute &
Definition: hdf5.h:340
attribute(attribute &&) noexcept=default
auto read_float() const
Definition: hdf5.h:294
auto read_uint8() const
Definition: hdf5.h:300
auto read_int32() const
Definition: hdf5.h:306
auto read_double() const
Definition: hdf5.h:296
auto read_uint32() const
Definition: hdf5.h:308
Definition: hdf5.h:784
auto dataset(std::string const &name) const
Definition: hdf5.h:800
auto as_id_holder() const -> auto const &
Definition: hdf5.h:786
auto as_id_holder() -> auto &
Definition: hdf5.h:785
auto create_dataset(std::string const &name, integral auto const ... size)
Definition: hdf5.h:790
auto dataset(char const *name) const
Definition: hdf5.h:795
Definition: hdf5.h:363
auto write(std::array< T, N > const &data) -> void
Definition: hdf5.h:525
auto read(std::vector< T > &data) const
Definition: hdf5.h:675
auto read(hsize_t const offset, hsize_t const count, std::vector< T > &data) const
Definition: hdf5.h:657
auto write(hid_t mem_space_id, hid_t file_space_id, hid_t xfer_plist_id, const void *buf) const -> void
Definition: hdf5.h:492
auto resize(std::array< Integral, N > const &extent)
Definition: hdf5.h:453
auto read() const
Definition: hdf5.h:614
auto push_back(T const &data) -> void
Definition: hdf5.h:518
auto flush()
Definition: hdf5.h:778
auto write(T const *data, std::vector< hsize_t > offset, std::vector< hsize_t > count) -> void
Definition: hdf5.h:597
dataset(dataset const &other)
Definition: hdf5.h:409
auto read(hid_t mem_space_id, hid_t file_space_id, hid_t xfer_plist_id, T *buf) const -> void
Definition: hdf5.h:607
auto num_dimensions() const -> std::size_t
Definition: hdf5.h:764
auto write(T const &data, Is const ... is) -> void
Definition: hdf5.h:565
auto name() const -> auto const &
Definition: hdf5.h:775
auto read(std::vector< std::size_t > const &offset, std::vector< std::size_t > const &count) const
Definition: hdf5.h:696
auto read_as_vector(std::vector< Int0 > const &offset, std::vector< Int1 > const &count) const
Definition: hdf5.h:668
auto resize_if_necessary(std::vector< hsize_t > const &requested_size)
Definition: hdf5.h:471
dataset(dataset &&) noexcept=default
auto write(std::vector< T > const &data) -> void
Definition: hdf5.h:502
auto size() const
Definition: hdf5.h:780
auto resize(std::array< hsize_t, N > const &extent)
Definition: hdf5.h:443
auto write(std::vector< T > const &data, hsize_t const offset) -> void
Definition: hdf5.h:507
auto resize(hsize_t const extent)
Definition: hdf5.h:436
auto resize(std::vector< hsize_t > const &extent)
Definition: hdf5.h:438
auto read_lazy(std::vector< std::size_t > const &chunk_size)
Definition: hdf5.h:771
dataset(hid_t const parent_id, std::string const &name, Size const ... size)
Definition: hdf5.h:374
auto read(std::vector< hsize_t > offset, std::vector< hsize_t > count, dynamic_multidim_array< T, IndexOrder > &arr) const -> auto &
Definition: hdf5.h:713
auto write(dynamic_multidim_array< T, IndexOrder > const &data, std::vector< std::size_t > const &offset) -> void
Definition: hdf5.h:541
T value_type
Definition: hdf5.h:366
auto resize_if_necessary(hsize_t const requested_size)
Definition: hdf5.h:462
auto clear()
Definition: hdf5.h:487
auto read_as_vector() const
Definition: hdf5.h:640
auto resize(Size const ... size)
Definition: hdf5.h:458
auto write(T const &data, std::vector< std::size_t > const &offset) -> void
Definition: hdf5.h:570
std::string m_name
Definition: hdf5.h:370
auto read(std::vector< std::size_t > const &offset, std::vector< std::size_t > const &count, dynamic_multidim_array< T, IndexOrder > &arr) const
Definition: hdf5.h:687
auto write(std::vector< T > const &data, std::vector< std::size_t > const &offset, std::vector< std::size_t > const &count) -> void
Definition: hdf5.h:579
auto read(std::vector< hsize_t > const &offset, std::vector< hsize_t > const &count) const
Definition: hdf5.h:705
auto write(T const *data, std::vector< std::size_t > const &offset, std::vector< std::size_t > const &count) -> void
Definition: hdf5.h:585
auto read(integral auto const ... is) const
Definition: hdf5.h:750
auto read(dynamic_multidim_array< T, IndexOrder > &arr) const
Definition: hdf5.h:621
auto push_back(std::vector< T > const &data) -> void
Definition: hdf5.h:513
auto resize(std::vector< Integral > const &extent)
Definition: hdf5.h:448
auto write(dynamic_multidim_array< T, IndexOrder > const &data) -> void
Definition: hdf5.h:536
auto dataspace() const
Definition: hdf5.h:777
auto write(std::vector< T > const &data, std::vector< hsize_t > offset, std::vector< hsize_t > count) -> void
Definition: hdf5.h:591
auto operator[](hsize_t const i) const
Definition: hdf5.h:762
auto operator=(dataset &&) noexcept -> dataset &=default
hid_t m_parent_id
Definition: hdf5.h:369
auto write(T const *data) -> void
Definition: hdf5.h:498
auto read(std::vector< hsize_t > const &offset, std::vector< hsize_t > const &count, std::vector< T > &data) const
Definition: hdf5.h:646
auto write(T const &data, std::vector< hsize_t > offset) -> void
Definition: hdf5.h:575
Definition: hdf5.h:116
auto rank() const
Definition: hdf5.h:155
dataspace(std::array< hsize_t, N > cur_resolution)
Definition: hdf5.h:140
dataspace(dataspace const &other)
Definition: hdf5.h:121
~dataspace()
Definition: hdf5.h:150
auto name() const
Definition: hdf5.h:237
dataspace(integral auto const ... size)
Definition: hdf5.h:125
dataspace(hid_t const id)
Definition: hdf5.h:123
auto select_hyperslab(std::vector< hsize_t > offset, std::vector< hsize_t > count)
Definition: hdf5.h:214
auto select_hyperslab(std::vector< hsize_t > offset, std::vector< hsize_t > stride, std::vector< hsize_t > count)
Definition: hdf5.h:205
auto select_hyperslab(H5S_seloper_t op, hsize_t const *start, hsize_t const *stride, hsize_t const *count, hsize_t const *block=nullptr)
Definition: hdf5.h:199
auto selected_num_hyperslab_blocks() const
Definition: hdf5.h:190
auto num_hyperslab_blocks() const
Definition: hdf5.h:187
auto select_hyperslab(hsize_t const offset, hsize_t const count)
Definition: hdf5.h:221
auto current_and_max_resolution() const
Definition: hdf5.h:173
auto num_elements() const
Definition: hdf5.h:185
dataspace(std::vector< hsize_t > cur_resolution)
Definition: hdf5.h:128
auto is_unlimited() const
Definition: hdf5.h:225
auto max_resolution() const
Definition: hdf5.h:165
auto current_resolution() const
Definition: hdf5.h:157
dataspace(std::vector< hsize_t > cur_resolution, std::vector< hsize_t > max_resolution)
Definition: hdf5.h:133
dataspace(std::array< hsize_t, N > cur_resolution, std::array< hsize_t, N > maxdims)
Definition: hdf5.h:145
auto select_hyperslab(hsize_t const *start, hsize_t const *stride, hsize_t const *count, hsize_t const *block=nullptr)
Definition: hdf5.h:194
auto info() const
Definition: hdf5.h:245
auto selected_num_elements() const
Definition: hdf5.h:186
Definition: hdf5.h:864
file(file const &other)
Definition: hdf5.h:885
file(file &&) noexcept=default
auto open(char const *path) -> void
Definition: hdf5.h:900
auto node_exists(char const *name, hid_t link_access_property_list_id=H5P_DEFAULT) const
Definition: hdf5.h:910
file(std::string const &path)
Definition: hdf5.h:878
auto node_exists(std::string const &name, hid_t link_access_property_list_id=H5P_DEFAULT) const
Definition: hdf5.h:915
file(char const *path)
Definition: hdf5.h:880
file(filesystem::path const &path)
Definition: hdf5.h:866
auto operator=(file &&) noexcept -> file &=default
Definition: hdf5.h:808
auto as_id_holder() -> auto &
Definition: hdf5.h:809
auto group(std::string const &name)
Definition: hdf5.h:818
auto as_id_holder() const -> auto const &
Definition: hdf5.h:810
auto group(char const *name)
Definition: hdf5.h:814
Definition: hdf5.h:829
group(group &&) noexcept=default
auto sub_group(char const *name)
Definition: hdf5.h:860
group(hid_t const parent_id, char const *name)
Definition: hdf5.h:837
group(hid_t const parent_id, std::string const &name)
Definition: hdf5.h:844
auto operator=(group &&) noexcept -> group &=default
std::string m_name
Definition: hdf5.h:834
auto sub_group(std::string const &name)
Definition: hdf5.h:861
Definition: hdf5.h:65
auto id() const
Definition: hdf5.h:72
hid_t m_id
Definition: hdf5.h:68
auto set_id(hid_t const id)
Definition: hdf5.h:73
id_holder(hid_t const id)
Definition: hdf5.h:71
Definition: hdf5.h:825
node(hid_t const id)
Definition: hdf5.h:826
Definition: hdf5.h:76
property_list(hid_t cls_id=H5P_DEFAULT)
Definition: hdf5.h:86
~property_list()
Definition: hdf5.h:94
auto set_chunk(integral auto const ... size)
Definition: hdf5.h:110
auto is_default() const
Definition: hdf5.h:99
property_list(property_list const &other)
Definition: hdf5.h:88
auto close() -> void
Definition: hdf5.h:104
auto operator=(property_list const &other) -> property_list &
Definition: hdf5.h:89
static auto dataset_creation()
Definition: hdf5.h:80
Definition: lazy_reader.h:14
Definition: index_order.h:17