1 /**
2 * \file RMF/HDF5/types.h
3 * \brief Handle read/write of Model data from/to files.
4 *
5 * Copyright 2007-2021 IMP Inventors. All rights reserved.
6 *
7 */
8
9 #ifndef RMF_HDF5_TYPES_H
10 #define RMF_HDF5_TYPES_H
11
12 #include "RMF/config.h"
13 #include "handle.h"
14 #include "infrastructure_macros.h"
15 #include "RMF/internal/errors.h"
16 #include "RMF/ID.h"
17 #include "internal/types.h"
18 #include <hdf5.h>
19 #include <algorithm>
20 #include <boost/cstdint.hpp>
21 #include <limits>
22
23 RMF_ENABLE_WARNINGS
24 namespace RMF {
25 namespace HDF5 {
26
27 /** The type used to store integral values.*/
28 typedef int Int;
29 /** The type used to store lists of integral values.*/
30 typedef std::vector<Int> Ints;
31 /** The type used to store lists of floating point values.*/
32 typedef float Float;
33 /** The type used to store lists of floating point values.*/
34 typedef std::vector<Float> Floats;
35 /** The type used to store lists of floating point values.*/
36 typedef std::vector<Floats> FloatsList;
37 /** The type used to store lists of index values.*/
38 typedef int Index;
39 /** The type used to store lists of index values.*/
40 typedef std::vector<Index> Indexes;
41 /** The type used to store lists of indexes.*/
42 typedef std::vector<Indexes> IndexesList;
43 /** The type used to store lists of string values.*/
44 typedef std::string String;
45 /** The type used to store lists of string values.*/
46 typedef std::vector<String> Strings;
47 /** The type used to store lists of strings values.*/
48 typedef std::vector<Strings> StringsList;
49 /** The type used to store lists of lists of integers values.*/
50 typedef std::vector<Ints> IntsList;
51 /** The type used to store char values.*/
52 typedef char Char;
53 /** The type used to store lists of char values.*/
54 typedef std::string Chars;
55
56 struct IntTraitsBase {
57 typedef int Type;
58 typedef std::vector<int> Types;
59 static const bool BatchOperations = true;
get_indexIntTraitsBase60 static int get_index() { return 0; }
get_null_valueIntTraitsBase61 static const Type& get_null_value() {
62 static Type null = std::numeric_limits<int>::max();
63 return null;
64 }
get_is_null_valueIntTraitsBase65 static bool get_is_null_value(Type t) { return t == get_null_value(); }
get_hdf5_fill_typeIntTraitsBase66 static hid_t get_hdf5_fill_type() { return H5T_NATIVE_INT; }
get_hdf5_disk_typeIntTraitsBase67 static hid_t get_hdf5_disk_type() { return H5T_STD_I64LE; }
get_hdf5_memory_typeIntTraitsBase68 static hid_t get_hdf5_memory_type() { return H5T_NATIVE_INT; }
get_fill_valueIntTraitsBase69 static const Type& get_fill_value() { return get_null_value(); }
get_nameIntTraitsBase70 static std::string get_name() { return "int"; }
71 };
72
73 struct FloatTraitsBase {
74 typedef float Type;
75 typedef std::vector<float> Types;
76 static const bool BatchOperations = true;
get_indexFloatTraitsBase77 static int get_index() { return 1; }
get_null_valueFloatTraitsBase78 static const Type& get_null_value() {
79 static Type null = std::numeric_limits<float>::max();
80 return null;
81 }
get_is_null_valueFloatTraitsBase82 static bool get_is_null_value(Type t) { return t == get_null_value(); }
get_hdf5_fill_typeFloatTraitsBase83 static hid_t get_hdf5_fill_type() { return H5T_NATIVE_FLOAT; }
get_hdf5_disk_typeFloatTraitsBase84 static hid_t get_hdf5_disk_type() { return H5T_IEEE_F64LE; }
get_hdf5_memory_typeFloatTraitsBase85 static hid_t get_hdf5_memory_type() { return H5T_NATIVE_FLOAT; }
get_fill_valueFloatTraitsBase86 static const Type& get_fill_value() { return get_null_value(); }
get_nameFloatTraitsBase87 static std::string get_name() { return "float"; }
88 };
89
90 struct IndexTraitsBase : public IntTraitsBase {
get_indexIndexTraitsBase91 static int get_index() { return 2; }
get_null_valueIndexTraitsBase92 static const Type& get_null_value() {
93 static Type null = -1;
94 return null;
95 }
get_is_null_valueIndexTraitsBase96 static bool get_is_null_value(Type t) { return t == get_null_value(); }
get_fill_valueIndexTraitsBase97 static const Type& get_fill_value() { return get_null_value(); }
get_nameIndexTraitsBase98 static std::string get_name() { return "index"; }
99 };
100
101 template <class Base>
102 struct SimpleTraits : public Base {
write_value_datasetSimpleTraits103 static void write_value_dataset(hid_t d, hid_t iss, hid_t s,
104 typename Base::Type v) {
105 RMF_HDF5_CALL(
106 H5Dwrite(d, Base::get_hdf5_memory_type(), iss, s, H5P_DEFAULT, &v));
107 }
read_value_datasetSimpleTraits108 static typename Base::Type read_value_dataset(hid_t d, hid_t iss, hid_t sp) {
109 typename Base::Type ret;
110 RMF_HDF5_CALL(
111 H5Dread(d, Base::get_hdf5_memory_type(), iss, sp, H5P_DEFAULT, &ret));
112 return ret;
113 }
write_values_datasetSimpleTraits114 static void write_values_dataset(hid_t d, hid_t iss, hid_t s,
115 const typename Base::Types& v) {
116 if (v.empty()) return;
117 RMF_HDF5_CALL(H5Dwrite(d, Base::get_hdf5_memory_type(), iss, s, H5P_DEFAULT,
118 const_cast<typename Base::Type*>(&v[0])));
119 }
read_values_datasetSimpleTraits120 static typename Base::Types read_values_dataset(hid_t d, hid_t iss, hid_t sp,
121 unsigned int sz) {
122 typename Base::Types ret(sz, Base::get_null_value());
123 RMF_HDF5_CALL(H5Dread(d, Base::get_hdf5_memory_type(), iss, sp, H5P_DEFAULT,
124 &ret[0]));
125 return ret;
126 }
write_values_attributeSimpleTraits127 static void write_values_attribute(hid_t a, const typename Base::Types& v) {
128 if (v.empty()) return;
129 RMF_HDF5_CALL(H5Awrite(a, Base::get_hdf5_memory_type(), &v[0]));
130 }
read_values_attributeSimpleTraits131 static typename Base::Types read_values_attribute(hid_t a, unsigned int sz) {
132 typename Base::Types ret(sz, Base::get_null_value());
133 RMF_HDF5_CALL(H5Aread(a, Base::get_hdf5_memory_type(), &ret[0]));
134 return ret;
135 }
136 };
137
138 struct CharTraits {
139 typedef char Type;
140 typedef std::string Types;
141 static const bool BatchOperations = false;
get_indexCharTraits142 static int get_index() { return 6; }
get_null_valueCharTraits143 static const Type& get_null_value() {
144 static char null = '\0';
145 return null;
146 }
get_is_null_valueCharTraits147 static bool get_is_null_value(Type t) { return t == '\0'; }
get_hdf5_fill_typeCharTraits148 static hid_t get_hdf5_fill_type() { return H5T_NATIVE_CHAR; }
get_hdf5_disk_typeCharTraits149 static hid_t get_hdf5_disk_type() { return H5T_STD_I8LE; }
get_hdf5_memory_typeCharTraits150 static hid_t get_hdf5_memory_type() { return H5T_NATIVE_CHAR; }
get_fill_valueCharTraits151 static const Type& get_fill_value() { return get_null_value(); }
get_nameCharTraits152 static std::string get_name() { return "char"; }
153
write_value_datasetCharTraits154 static void write_value_dataset(hid_t, hid_t, hid_t, char) {
155 RMF_NOT_IMPLEMENTED;
156 }
read_value_datasetCharTraits157 static char read_value_dataset(hid_t, hid_t, hid_t) {
158 RMF_NOT_IMPLEMENTED;
159 return '\0';
160 }
write_values_datasetCharTraits161 static void write_values_dataset(hid_t, hid_t, hid_t, const Types&) {
162 RMF_NOT_IMPLEMENTED;
163 }
read_values_datasetCharTraits164 static Types read_values_dataset(hid_t, hid_t, hid_t, unsigned int) {
165 RMF_NOT_IMPLEMENTED;
166 }
write_values_attributeCharTraits167 static void write_values_attribute(hid_t a, const Types& v) {
168 RMF_HDF5_CALL(H5Awrite(a, H5T_NATIVE_CHAR, v.c_str()));
169 }
read_values_attributeCharTraits170 static Types read_values_attribute(hid_t a, unsigned int sz) {
171 std::vector<char> v(sz);
172 RMF_HDF5_CALL(H5Aread(a, H5T_NATIVE_CHAR, &v[0]));
173 return std::string(&v[0], v.size());
174 }
175 };
176
177 template <class Traits>
178 struct SimplePluralTraits {
179 typedef typename Traits::Types Type;
180 typedef std::vector<Type> Types;
181 static const bool BatchOperations = false;
get_indexSimplePluralTraits182 static int get_index() { return 7 + Traits::get_index(); }
get_null_valueSimplePluralTraits183 static const Type& get_null_value() {
184 static Type null;
185 return null;
186 }
get_is_null_valueSimplePluralTraits187 static bool get_is_null_value(const Type& t) { return t.empty(); }
get_hdf5_fill_typeSimplePluralTraits188 static hid_t get_hdf5_fill_type() { return get_hdf5_memory_type(); }
get_hdf5_disk_typeSimplePluralTraits189 static hid_t get_hdf5_disk_type() {
190 static RMF_HDF5_HANDLE(
191 ints_type, H5Tvlen_create(Traits::get_hdf5_disk_type()), H5Tclose);
192 return ints_type;
193 }
get_hdf5_memory_typeSimplePluralTraits194 static hid_t get_hdf5_memory_type() {
195 static RMF_HDF5_HANDLE(
196 ints_type, H5Tvlen_create(Traits::get_hdf5_memory_type()), H5Tclose);
197 return ints_type;
198 }
get_fill_valueSimplePluralTraits199 static const Type& get_fill_value() { return get_null_value(); }
get_nameSimplePluralTraits200 static std::string get_name() { return Traits::get_name() + "s"; }
201
write_value_datasetSimplePluralTraits202 static void write_value_dataset(hid_t d, hid_t iss, hid_t s, const Type& v) {
203 hvl_t data;
204 data.len = v.size();
205 if (data.len > 0) {
206 data.p = const_cast<typename Type::pointer>(&v[0]);
207 } else {
208 data.p = NULL;
209 }
210 RMF_HDF5_CALL(
211 H5Dwrite(d, get_hdf5_memory_type(), iss, s, H5P_DEFAULT, &data));
212 }
read_value_datasetSimplePluralTraits213 static Type read_value_dataset(hid_t d, hid_t iss, hid_t sp) {
214 hvl_t data;
215 H5Dread(d, get_hdf5_memory_type(), iss, sp, H5P_DEFAULT, &data);
216 Type ret(data.len);
217 std::copy(static_cast<typename Type::pointer>(data.p),
218 static_cast<typename Type::pointer>(data.p) + data.len,
219 ret.begin());
220 free(data.p);
221 return ret;
222 }
write_values_datasetSimplePluralTraits223 static void write_values_dataset(hid_t, hid_t, hid_t, const Types&) {
224 RMF_NOT_IMPLEMENTED;
225 };
read_values_datasetSimplePluralTraits226 static Types read_values_dataset(hid_t, hid_t, hid_t, unsigned int) {
227 RMF_NOT_IMPLEMENTED;
228 }
read_values_attributeSimplePluralTraits229 static Types read_values_attribute(hid_t, unsigned int) {
230 RMF_NOT_IMPLEMENTED;
231 }
write_values_attributeSimplePluralTraits232 static void write_values_attribute(hid_t, const Types&) {
233 RMF_NOT_IMPLEMENTED;
234 }
235 };
236
237 struct RMFEXPORT StringTraits {
238 typedef std::string Type;
239 typedef std::vector<std::string> Types;
240 static const bool BatchOperations = false;
get_indexStringTraits241 static int get_index() { return 3; }
get_null_valueStringTraits242 static const Type& get_null_value() {
243 static std::string null;
244 return null;
245 }
get_is_null_valueStringTraits246 static bool get_is_null_value(Type t) { return t.empty(); }
get_hdf5_fill_typeStringTraits247 static hid_t get_hdf5_fill_type() { return internal::get_string_type(); }
get_hdf5_disk_typeStringTraits248 static hid_t get_hdf5_disk_type() { return internal::get_string_type(); }
get_hdf5_memory_typeStringTraits249 static hid_t get_hdf5_memory_type() { return internal::get_string_type(); }
get_fill_valueStringTraits250 static const Type& get_fill_value() { return get_null_value(); }
get_nameStringTraits251 static std::string get_name() { return "string"; }
252 static void write_value_dataset(hid_t d, hid_t iss, hid_t s, const Type& v);
253 static Type read_value_dataset(hid_t d, hid_t iss, hid_t sp);
write_values_datasetStringTraits254 static void write_values_dataset(hid_t, hid_t, hid_t, Types) {
255 RMF_NOT_IMPLEMENTED;
256 };
read_values_datasetStringTraits257 static Types read_values_dataset(hid_t, hid_t, hid_t, unsigned int) {
258 RMF_NOT_IMPLEMENTED;
259 }
read_values_attributeStringTraits260 static Types read_values_attribute(hid_t, unsigned int) {
261 RMF_NOT_IMPLEMENTED;
262 }
write_values_attributeStringTraits263 static void write_values_attribute(hid_t, const Types&) {
264 RMF_NOT_IMPLEMENTED;
265 }
266 };
267
268 struct RMFEXPORT StringsTraits {
269 typedef std::vector<std::string> Type;
270 typedef std::vector<Type> Types;
271 static const bool BatchOperations = false;
get_indexStringsTraits272 static int get_index() { return 3 + 7; }
get_null_valueStringsTraits273 static const Type& get_null_value() {
274 static Type null;
275 return null;
276 }
get_is_null_valueStringsTraits277 static bool get_is_null_value(Type t) { return t.empty(); }
278 static hid_t get_hdf5_fill_type();
279 static hid_t get_hdf5_disk_type();
280 static hid_t get_hdf5_memory_type();
281 static const hvl_t& get_fill_value();
get_nameStringsTraits282 static std::string get_name() { return "strings"; }
283 static void write_value_dataset(hid_t d, hid_t iss, hid_t s, const Type& v);
284 static Type read_value_dataset(hid_t d, hid_t iss, hid_t sp);
write_values_datasetStringsTraits285 static void write_values_dataset(hid_t, hid_t, hid_t, const Types&) {
286 RMF_NOT_IMPLEMENTED;
287 };
read_values_datasetStringsTraits288 static Types read_values_dataset(hid_t, hid_t, hid_t, unsigned int) {
289 RMF_NOT_IMPLEMENTED;
290 }
read_values_attributeStringsTraits291 static Types read_values_attribute(hid_t, unsigned int) {
292 RMF_NOT_IMPLEMENTED;
293 }
write_values_attributeStringsTraits294 static void write_values_attribute(hid_t, const Types&) {
295 RMF_NOT_IMPLEMENTED;
296 }
297 };
298
299 #ifndef SWIG
300 struct IntTraits : public SimpleTraits<IntTraitsBase> {};
301 struct IntsTraits : public SimplePluralTraits<IntTraits> {};
302 struct FloatTraits : public SimpleTraits<FloatTraitsBase> {};
303 struct FloatsTraits : public SimplePluralTraits<FloatTraits> {};
304 struct IndexTraits : public SimpleTraits<IndexTraitsBase> {};
305 struct IndexesTraits : public SimplePluralTraits<IndexTraits> {};
306
307 #ifndef IMP_DOXYGEN
308 namespace {
309 template <class OutType, class InType>
get_as_impl(InType in,OutType & out)310 inline void get_as_impl(InType in, OutType& out) {
311 out = OutType(in);
312 }
313 template <class Traits, class InType>
get_as_impl(InType in,ID<Traits> & out)314 inline void get_as_impl(InType in, ID<Traits>& out) {
315 if (in == -1)
316 out = ID<Traits>();
317 else
318 out = ID<Traits>(in);
319 }
320 template <class OutType, class Traits>
get_as_impl(ID<Traits> in,OutType & out)321 inline void get_as_impl(ID<Traits> in, OutType& out) {
322 if (in == ID<Traits>())
323 out = -1;
324 else
325 out = in.get_index();
326 }
327 }
328 #endif
329 #endif
330
331 /** Get one type as another, handling vectors or scalars.*/
332 template <class OutType, class InType>
get_as(InType in)333 inline OutType get_as(InType in) {
334 OutType ret;
335 get_as_impl(in, ret);
336 return ret;
337 }
338
339 /** Get one type as another, handling vectors or scalars.*/
340 template <class OutType, class InType>
get_as(const std::vector<InType> in)341 inline OutType get_as(const std::vector<InType> in) {
342 OutType ret(in.size());
343 for (unsigned int i = 0; i < ret.size(); ++i) {
344 ret[i] = get_as<typename OutType::value_type>(in[i]);
345 }
346 return ret;
347 }
348
349 } /* namespace HDF5 */
350 } /* namespace RMF */
351
352 RMF_DISABLE_WARNINGS
353
354 #endif /* RMF_HDF5_TYPES_H */
355