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