TRIQS/h5 2.0.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
21
22#include "./complex.hpp"
23#include "./macros.hpp"
24#include "./object.hpp"
25#include "./utils.hpp"
26
27#include <H5Apublic.h>
28#include <H5Ipublic.h>
29#include <H5Fpublic.h>
30#include <H5Gpublic.h>
31#include <H5Ppublic.h>
32
33#include <algorithm>
34#include <complex>
35#include <stdexcept>
36#include <string>
37#include <type_traits>
38#include <vector>
39
40// make sure that hid_t and hsize_t have a compatible type in the HDF5 library
41static_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");
42static_assert(sizeof(::hsize_t) == sizeof(h5::hsize_t), "h5::hsize_t type is not compatible with HDF5");
43
44namespace h5 {
45
46 // anonymous namespace for internal functions
47 namespace {
48
49 // decrease reference count if HDF5 ID is valid
50 inline void xdecref(hid_t id) {
51 if (H5Iis_valid(id)) H5Idec_ref(id);
52 }
53
54 // increase reference count if HDF5 ID is valid
55 inline void xincref(hid_t id) {
56 if (H5Iis_valid(id)) H5Iinc_ref(id);
57 }
58
59 // stores an HDF5 datatype and its name
60 struct h5_name_t {
61 datatype hdf5_type;
62 std::string name;
63 };
64
65 // table of HDF5 datatypes and their names
66 std::vector<h5_name_t> h5_name_table; // NOLINT (global variable is in an unnamed namespace)
67
68 // initialize the table of HDF5 datatypes and their names
69 void init_h5_name_table() {
70 h5_name_table = std::vector<h5_name_t>{
71 {hdf5_type<char>(), H5_AS_STRING(char)},
72 {hdf5_type<signed char>(), H5_AS_STRING(signed char)},
73 {hdf5_type<unsigned char>(), H5_AS_STRING(unsigned char)},
74 {hdf5_type<bool>(), H5_AS_STRING(bool)},
75 {hdf5_type<short>(), H5_AS_STRING(short)},
76 {hdf5_type<unsigned short>(), H5_AS_STRING(unsigned short)},
77 {hdf5_type<int>(), H5_AS_STRING(int)},
78 {hdf5_type<unsigned int>(), H5_AS_STRING(unsigned int)},
79 {hdf5_type<long>(), H5_AS_STRING(long)},
80 {hdf5_type<unsigned long>(), H5_AS_STRING(unsigned long)},
81 {hdf5_type<long long>(), H5_AS_STRING(long long)},
82 {hdf5_type<unsigned long long>(), H5_AS_STRING(unsigned long long)},
83 {hdf5_type<float>(), H5_AS_STRING(float)},
84 {hdf5_type<double>(), H5_AS_STRING(double)},
85 {hdf5_type<long double>(), H5_AS_STRING(long double)},
86 {hdf5_type<std::complex<float>>(), H5_AS_STRING(std::complex<float>)},
87 {hdf5_type<std::complex<double>>(), H5_AS_STRING(std::complex<double>)},
88 {hdf5_type<std::complex<long double>>(), H5_AS_STRING(std::complex<long double>)},
89 {hdf5_type<std::string>(), H5_AS_STRING(std::string)},
90 {hdf5_type<dcplx_t>(), "Complex Compound Datatype"} //
91 };
92 }
93
94 } // namespace
95
97 xincref(id);
98 return {id};
99 }
100
101 object::object(object const &other) : id(other.id) { xincref(id); }
102
103 object &object::operator=(object &&rhs) noexcept {
104 xdecref(id);
105 id = rhs.id;
106 rhs.id = 0;
107 return *this;
108 }
109
111 xdecref(id);
112 id = 0;
113 }
114
115 int object::get_ref_count() const { return H5Iget_ref(id); }
116
117 bool object::is_valid() const { return H5Iis_valid(id) == 1; }
118
119 namespace detail {
120
121 // clang-format off
122 // map basic C++ types to HDF5 datatypes
123 template <> hid_t hid_t_of<char> (){return H5T_NATIVE_CHAR;}
124 template <> hid_t hid_t_of<signed char> (){return H5T_NATIVE_SCHAR;}
125 template <> hid_t hid_t_of<unsigned char> (){return H5T_NATIVE_UCHAR;}
126
127 template <> hid_t hid_t_of<short> (){return H5T_NATIVE_SHORT;}
128 template <> hid_t hid_t_of<int> (){return H5T_NATIVE_INT;}
129 template <> hid_t hid_t_of<long> (){return H5T_NATIVE_LONG;}
130 template <> hid_t hid_t_of<long long> (){return H5T_NATIVE_LLONG;}
131
132 template <> hid_t hid_t_of<unsigned short> (){return H5T_NATIVE_USHORT;}
133 template <> hid_t hid_t_of<unsigned int> (){return H5T_NATIVE_UINT;}
134 template <> hid_t hid_t_of<unsigned long> (){return H5T_NATIVE_ULONG;}
135 template <> hid_t hid_t_of<unsigned long long> (){return H5T_NATIVE_ULLONG;}
136
137 template <> hid_t hid_t_of<float> (){return H5T_NATIVE_FLOAT;}
138 template <> hid_t hid_t_of<double> (){return H5T_NATIVE_DOUBLE;}
139 template <> hid_t hid_t_of<long double> (){return H5T_NATIVE_LDOUBLE;}
140
141 template <> hid_t hid_t_of<std::complex<float>> (){return H5T_NATIVE_FLOAT;}
142 template <> hid_t hid_t_of<std::complex<double>> (){return H5T_NATIVE_DOUBLE;}
143 template <> hid_t hid_t_of<std::complex<long double>> (){return H5T_NATIVE_LDOUBLE;}
144
145 // custom HDF5 datatype for strings
146 hid_t const str_dt = [](){
147 hid_t dt = H5Tcopy(H5T_C_S1);
148 H5Tset_size(dt, H5T_VARIABLE);
149 H5Tset_cset(dt, H5T_CSET_UTF8);
150 H5Tlock(dt);
151 return dt;
152 }();
153
154 // map different string types to the custom HDF5 string datatype from above
155 template <> hid_t hid_t_of<std::string> (){return detail::str_dt;}
156 template <> hid_t hid_t_of<char *> (){return detail::str_dt;}
157 template <> hid_t hid_t_of<const char *> (){return detail::str_dt;}
158
159 // custom HDF5 datatype for a complex number
160 hid_t const cplx_cmpd_dt = [](){
161 hid_t dt = H5Tcreate(H5T_COMPOUND, 16);
162 H5Tinsert(dt, "r", 0, H5T_NATIVE_DOUBLE);
163 H5Tinsert(dt, "i", 8, H5T_NATIVE_DOUBLE);
164 H5Tlock(dt);
165 return dt;
166 }();
167
168 // map the custom complex type to the custom HDF5 datatype from above
169 template <> hid_t hid_t_of<dcplx_t> (){return detail::cplx_cmpd_dt;}
170 // clang-format on
171
172 // custom HDF5 datatype for bool (use a lambda to initialize it?)
173 template <>
174 hid_t hid_t_of<bool>() {
175 hid_t bool_enum_h5type = H5Tenum_create(H5T_NATIVE_CHAR);
176 char val = 0;
177 H5Tenum_insert(bool_enum_h5type, "FALSE", (val = 0, &val));
178 H5Tenum_insert(bool_enum_h5type, "TRUE", (val = 1, &val));
179 return bool_enum_h5type;
180 }
181
182 } // namespace detail
183
185 // initialize name table if it has not been done yet
186 if (h5_name_table.empty()) init_h5_name_table();
187
188 // find name in table
189 auto _end = h5_name_table.end();
190 auto pos = std::find_if(h5_name_table.begin(), _end, [dt](auto const &x) { return hdf5_type_equal(dt, x.hdf5_type); });
191
192 // return name if found, otherwise throw an exception
193 if (pos == _end) throw std::logic_error("Error in h5::get_name_of_h5_type: datatype not supported");
194 return pos->name;
195 }
196
197 datatype get_hdf5_type(dataset ds) { return H5Dget_type(ds); }
198
199 datatype get_hdf5_attribute_type(object obj, std::string const &name) {
200 attribute attr = H5Aopen(obj, name.c_str(), H5P_DEFAULT);
201 return H5Aget_type(attr);
202 }
203
205 // for strings check only if they are both of the class H5T_STRING
206 if (H5Tget_class(dt1) == H5T_STRING) { return H5Tget_class(dt2) == H5T_STRING; }
207
208 // for other types use H5Tequal
209 auto res = H5Tequal(dt1, dt2);
210 if (res < 0) { throw std::runtime_error("Error in h5::hdf5_type_equal: H5Tequal call failed"); }
211 return res > 0;
212 }
213
214} // namespace h5
bool is_valid() const
Ensure that the wrapped HDF5 ID is valid (by calling H5Iis_valid).
Definition object.cpp:117
int get_ref_count() const
Get the current reference count.
Definition object.cpp:115
object & operator=(object const &rhs)
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:96
void close()
Release the HDF5 handle by decreasing the reference count and by setting the object's ID to zero.
Definition object.cpp:110
Provides a compound type and type traits for complex numbers.
object datatype
Type alias for an HDF5 datatype.
Definition object.hpp:123
object attribute
Type alias for an HDF5 attribute.
Definition object.hpp:132
object dataset
Type alias for an HDF5 dataset.
Definition object.hpp:120
bool hdf5_type_equal(datatype dt1, datatype dt2)
Check if two HDF5 datatypes are equal.
Definition object.cpp:204
datatype get_hdf5_attribute_type(object obj, std::string const &name)
Get the HDF5 type of a named attribute attached to a given h5::object.
Definition object.cpp:199
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:197
std::string get_name_of_h5_type()
Get the name of the HDF5 datatype corresponding to a C++ type.
Definition object.hpp:177
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.