TRIQS/h5 1.3.0
C++ interface to HDF5
Loading...
Searching...
No Matches
object.cpp
Go to the documentation of this file.
1// Copyright (c) 2019-2024 Simons Foundation
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0.txt
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// Authors: Thomas Hahn, Olivier Parcollet, Nils Wentzell
16
22#include "./complex.hpp"
23#include "./macros.hpp"
24#include "./object.hpp"
25#include "./utils.hpp"
26
27#include <H5Ipublic.h>
28#include <H5Fpublic.h>
29#include <H5Gpublic.h>
30#include <H5Ppublic.h>
31
32#include <algorithm>
33#include <complex>
34#include <stdexcept>
35#include <string>
36#include <type_traits>
37#include <vector>
38
39// make sure that hid_t and hsize_t have a compatible type in the HDF5 library
40static_assert(std::is_same_v<hid_t, int64_t> or std::is_same_v<hid_t, int>, "h5::hid_t type is not compatible with HDF5");
41static_assert(sizeof(::hsize_t) == sizeof(h5::hsize_t), "h5::hsize_t type is not compatible with HDF5");
42
43namespace h5 {
44
45 // anonymous namespace for internal functions
46 namespace {
47
48 // decrease reference count if HDF5 ID is valid
49 inline void xdecref(hid_t id) {
50 if (H5Iis_valid(id)) H5Idec_ref(id);
51 }
52
53 // increase reference count if HDF5 ID is valid
54 inline void xincref(hid_t id) {
55 if (H5Iis_valid(id)) H5Iinc_ref(id);
56 }
57
58 // stores an HDF5 datatype and its name
59 struct h5_name_t {
61 std::string name;
62 };
63
64 // table of HDF5 datatypes and their names
65 std::vector<h5_name_t> h5_name_table; // NOLINT (global variable is in an unnamed namespace)
66
67 // initialize the table of HDF5 datatypes and their names
68 void init_h5_name_table() {
69 h5_name_table = std::vector<h5_name_t>{
70 {hdf5_type<char>(), H5_AS_STRING(char)},
71 {hdf5_type<signed char>(), H5_AS_STRING(signed char)},
72 {hdf5_type<unsigned char>(), H5_AS_STRING(unsigned char)},
73 {hdf5_type<bool>(), H5_AS_STRING(bool)},
74 {hdf5_type<short>(), H5_AS_STRING(short)},
75 {hdf5_type<unsigned short>(), H5_AS_STRING(unsigned short)},
76 {hdf5_type<int>(), H5_AS_STRING(int)},
77 {hdf5_type<unsigned int>(), H5_AS_STRING(unsigned int)},
78 {hdf5_type<long>(), H5_AS_STRING(long)},
79 {hdf5_type<unsigned long>(), H5_AS_STRING(unsigned long)},
80 {hdf5_type<long long>(), H5_AS_STRING(long long)},
81 {hdf5_type<unsigned long long>(), H5_AS_STRING(unsigned long long)},
82 {hdf5_type<float>(), H5_AS_STRING(float)},
83 {hdf5_type<double>(), H5_AS_STRING(double)},
84 {hdf5_type<long double>(), H5_AS_STRING(long double)},
85 {hdf5_type<std::complex<float>>(), H5_AS_STRING(std::complex<float>)},
86 {hdf5_type<std::complex<double>>(), H5_AS_STRING(std::complex<double>)},
87 {hdf5_type<std::complex<long double>>(), H5_AS_STRING(std::complex<long double>)},
88 {hdf5_type<std::string>(), H5_AS_STRING(std::string)},
89 {hdf5_type<dcplx_t>(), "Complex Compound Datatype"} //
90 };
91 }
92
93 } // namespace
94
96 xincref(id);
97 return {id};
98 }
99
100 object::object(object const &x) : id(x.id) { xincref(id); }
101
102 object &object::operator=(object &&x) noexcept {
103 xdecref(id);
104 id = x.id;
105 x.id = 0;
106 return *this;
107 }
108
110 xdecref(id);
111 id = 0;
112 }
113
114 int object::get_ref_count() const { return H5Iget_ref(id); }
115
116 bool object::is_valid() const { return H5Iis_valid(id) == 1; }
117
118 namespace detail {
119
120 // clang-format off
121 // map basic C++ types to HDF5 datatypes
122 template <> hid_t hid_t_of<char> (){return H5T_NATIVE_CHAR;}
123 template <> hid_t hid_t_of<signed char> (){return H5T_NATIVE_SCHAR;}
124 template <> hid_t hid_t_of<unsigned char> (){return H5T_NATIVE_UCHAR;}
125
126 template <> hid_t hid_t_of<short> (){return H5T_NATIVE_SHORT;}
127 template <> hid_t hid_t_of<int> (){return H5T_NATIVE_INT;}
128 template <> hid_t hid_t_of<long> (){return H5T_NATIVE_LONG;}
129 template <> hid_t hid_t_of<long long> (){return H5T_NATIVE_LLONG;}
130
131 template <> hid_t hid_t_of<unsigned short> (){return H5T_NATIVE_USHORT;}
132 template <> hid_t hid_t_of<unsigned int> (){return H5T_NATIVE_UINT;}
133 template <> hid_t hid_t_of<unsigned long> (){return H5T_NATIVE_ULONG;}
134 template <> hid_t hid_t_of<unsigned long long> (){return H5T_NATIVE_ULLONG;}
135
136 template <> hid_t hid_t_of<float> (){return H5T_NATIVE_FLOAT;}
137 template <> hid_t hid_t_of<double> (){return H5T_NATIVE_DOUBLE;}
138 template <> hid_t hid_t_of<long double> (){return H5T_NATIVE_LDOUBLE;}
139
140 template <> hid_t hid_t_of<std::complex<float>> (){return H5T_NATIVE_FLOAT;}
141 template <> hid_t hid_t_of<std::complex<double>> (){return H5T_NATIVE_DOUBLE;}
142 template <> hid_t hid_t_of<std::complex<long double>> (){return H5T_NATIVE_LDOUBLE;}
143
144 // custom HDF5 datatype for strings
145 hid_t const str_dt = [](){
146 hid_t dt = H5Tcopy(H5T_C_S1);
147 H5Tset_size(dt, H5T_VARIABLE);
148 H5Tset_cset(dt, H5T_CSET_UTF8);
149 H5Tlock(dt);
150 return dt;
151 }();
152
153 // map different string types to the custom HDF5 string datatype from above
154 template <> hid_t hid_t_of<std::string> (){return detail::str_dt;}
155 template <> hid_t hid_t_of<char *> (){return detail::str_dt;}
156 template <> hid_t hid_t_of<const char *> (){return detail::str_dt;}
157
158 // custom HDF5 datatype for a complex number
159 hid_t const cplx_cmpd_dt = [](){
160 hid_t dt = H5Tcreate(H5T_COMPOUND, 16);
161 H5Tinsert(dt, "r", 0, H5T_NATIVE_DOUBLE);
162 H5Tinsert(dt, "i", 8, H5T_NATIVE_DOUBLE);
163 H5Tlock(dt);
164 return dt;
165 }();
166
167 // map the custom complex type to the custom HDF5 datatype from above
168 template <> hid_t hid_t_of<dcplx_t> (){return detail::cplx_cmpd_dt;}
169 // clang-format on
170
171 // custom HDF5 datatype for bool (use a lambda to initialize it?)
172 template <>
173 hid_t hid_t_of<bool>() {
174 hid_t bool_enum_h5type = H5Tenum_create(H5T_NATIVE_CHAR);
175 char val = 0;
176 H5Tenum_insert(bool_enum_h5type, "FALSE", (val = 0, &val));
177 H5Tenum_insert(bool_enum_h5type, "TRUE", (val = 1, &val));
178 return bool_enum_h5type;
179 }
180
181 } // namespace detail
182
184 // initialize name table if it has not been done yet
185 if (h5_name_table.empty()) init_h5_name_table();
186
187 // find name in table
188 auto _end = h5_name_table.end();
189 auto pos = std::find_if(h5_name_table.begin(), _end, [dt](auto const &x) { return hdf5_type_equal(dt, x.hdf5_type); });
190
191 // return name if found, otherwise throw an exception
192 if (pos == _end) throw std::logic_error("Error in h5::get_name_of_h5_type: datatype not supported");
193 return pos->name;
194 }
195
196 datatype get_hdf5_type(dataset ds) { return H5Dget_type(ds); }
197
199 // for strings check only if they are both of the class H5T_STRING
200 if (H5Tget_class(dt1) == H5T_STRING) { return H5Tget_class(dt2) == H5T_STRING; }
201
202 // for other types use H5Tequal
203 auto res = H5Tequal(dt1, dt2);
204 if (res < 0) { throw std::runtime_error("Error in h5::hdf5_type_equal: H5Tequal call failed"); }
205 return res > 0;
206 }
207
208} // namespace h5
A generic handle for HDF5 objects.
Definition object.hpp:49
bool is_valid() const
Ensure that the wrapped HDF5 ID is valid (by calling H5Iis_valid).
Definition object.cpp:116
int get_ref_count() const
Get the current reference count.
Definition object.cpp:114
object & operator=(object const &x)
Copy assignment operator copies the underlying HDF5 ID and increases its reference count.
Definition object.hpp:89
object(hid_t id=0)
Construct a new h5::object for a given HDF5 ID by taking ownership, i.e. without increasing the refer...
Definition object.hpp:71
static object from_borrowed(hid_t id)
Create an h5::object for a given HDF5 ID and increase its reference count.
Definition object.cpp:95
void close()
Release the HDF5 handle by decreasing the reference count and by setting the object's ID to zero.
Definition object.cpp:109
Provides a compound type and type traits for complex numbers.
object datatype
Type alias for an HDF5 datatype.
Definition object.hpp:123
bool hdf5_type_equal(datatype dt1, datatype dt2)
Check if two HDF5 datatypes are equal.
Definition object.cpp:198
datatype hdf5_type()
Map a given C++ type to an HDF5 datatype.
Definition object.hpp:156
datatype get_hdf5_type(dataset ds)
Get the HDF5 type stored in a given h5::dataset.
Definition object.cpp:196
std::string get_name_of_h5_type(datatype dt)
Get the name of an h5::datatype (for error messages).
Definition object.cpp:183
unsigned long long hsize_t
Size type used in HDF5.
Definition utils.hpp:55
int64_t hid_t
ID type used in HDF5.
Definition utils.hpp:45
Macros used in the h5 library.
Provides a generic handle for HDF5 objects.
Provides some utility functions for h5.