hops
H5DataType_misc.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c), 2017, Adrien Devresse <adrien.devresse@epfl.ch>
3  *
4  * Distributed under the Boost Software License, Version 1.0.
5  * (See accompanying file LICENSE_1_0.txt or copy at
6  * http://www.boost.org/LICENSE_1_0.txt)
7  *
8  */
9 #ifndef H5DATATYPE_MISC_HPP
10 #define H5DATATYPE_MISC_HPP
11 
12 #include <string>
13 #include <complex>
14 #include <cstring>
15 
16 #include <H5Ppublic.h>
17 #include <H5Tpublic.h>
18 
19 
20 namespace HighFive {
21 
22 namespace { // unnamed
23 inline DataTypeClass convert_type_class(const H5T_class_t& tclass);
24 inline std::string type_class_string(DataTypeClass);
25 inline hid_t create_string(std::size_t length);
26 }
27 
28 inline bool DataType::empty() const noexcept {
29  return _hid == H5I_INVALID_HID;
30 }
31 
33  return convert_type_class(H5Tget_class(_hid));
34 }
35 
36 inline size_t DataType::getSize() const {
37  return H5Tget_size(_hid);
38 }
39 
40 inline bool DataType::operator==(const DataType& other) const {
41  return (H5Tequal(_hid, other._hid) > 0);
42 }
43 
44 inline bool DataType::operator!=(const DataType& other) const {
45  return !(*this == other);
46 }
47 
48 inline bool DataType::isVariableStr() const {
49  auto var_value = H5Tis_variable_str(_hid);
50  if (var_value < 0) {
51  HDF5ErrMapper::ToException<DataTypeException>(
52  "Unable to define datatype size to variable");
53  }
54  return static_cast<bool>(var_value);
55 }
56 
57 inline bool DataType::isFixedLenStr() const {
59 }
60 
61 inline bool DataType::isReference() const {
62  return H5Tequal(_hid, H5T_STD_REF_OBJ) > 0;
63 }
64 
65 inline std::string DataType::string() const {
66  return type_class_string(getClass()) + std::to_string(getSize() * 8);
67 }
68 
69 // char mapping
70 template <>
72  _hid = H5Tcopy(H5T_NATIVE_CHAR);
73 }
74 
75 template <>
77  _hid = H5Tcopy(H5T_NATIVE_CHAR);
78 }
79 
80 template <>
82  _hid = H5Tcopy(H5T_NATIVE_UCHAR);
83 }
84 
85 // short mapping
86 template <>
88  _hid = H5Tcopy(H5T_NATIVE_SHORT);
89 }
90 
91 template <>
93  _hid = H5Tcopy(H5T_NATIVE_USHORT);
94 }
95 
96 // integer mapping
97 template <>
99  _hid = H5Tcopy(H5T_NATIVE_INT);
100 }
101 
102 template <>
104  _hid = H5Tcopy(H5T_NATIVE_UINT);
105 }
106 
107 // long mapping
108 template <>
110  _hid = H5Tcopy(H5T_NATIVE_LONG);
111 }
112 
113 template <>
115  _hid = H5Tcopy(H5T_NATIVE_ULONG);
116 }
117 
118 // long long mapping
119 template <>
121  _hid = H5Tcopy(H5T_NATIVE_LLONG);
122 }
123 
124 template <>
126  _hid = H5Tcopy(H5T_NATIVE_ULLONG);
127 }
128 
129 // float and double mapping
130 template <>
132  _hid = H5Tcopy(H5T_NATIVE_FLOAT);
133 }
134 
135 template <>
137  _hid = H5Tcopy(H5T_NATIVE_DOUBLE);
138 }
139 
140 // boolean mapping
141 template <>
143  _hid = H5Tcopy(H5T_NATIVE_HBOOL);
144 }
145 
146 // std string
147 template <>
149  _hid = create_string(H5T_VARIABLE);
150 }
151 
152 // Fixed-Length strings
153 // require class specialization templated for the char length
154 template <size_t StrLen>
155 class AtomicType<char[StrLen]> : public DataType {
156  public:
157  inline AtomicType() : DataType(create_string(StrLen)) {}
158 };
159 
160 template <size_t StrLen>
161 class AtomicType<FixedLenStringArray<StrLen>> : public DataType {
162  public:
163  inline AtomicType() : DataType(create_string(StrLen)) {}
164 };
165 
166 template <>
168  static struct ComplexType : public Object {
169  ComplexType() {
170  _hid = H5Tcreate(H5T_COMPOUND, sizeof(std::complex<double>));
171  // h5py/numpy compatible datatype
172  H5Tinsert(_hid, "r", 0, H5T_NATIVE_DOUBLE);
173  H5Tinsert(_hid, "i", sizeof(double), H5T_NATIVE_DOUBLE);
174  };
175  } complexType;
176  _hid = H5Tcopy(complexType.getId());
177 }
178 
179 // Other cases not supported. Fail early with a user message
180 template <typename T>
182  static_assert(details::array_dims<T>::value == 0,
183  "Atomic types cant be arrays, except for char[] (fixed-len strings)");
184  static_assert(details::array_dims<T>::value > 0, "Type not supported");
185 }
186 
187 
188 // class FixedLenStringArray<N>
189 
190 template <std::size_t N>
192 ::FixedLenStringArray(const char array[][N], std::size_t length) {
193  datavec.resize(length);
194  std::memcpy(datavec[0].data(), array[0].data(), N * length);
195 }
196 
197 template <std::size_t N>
199 ::FixedLenStringArray(const std::string* iter_begin, const std::string* iter_end) {
200  datavec.resize(static_cast<std::size_t>(iter_end - iter_begin));
201  for (auto& dst_array : datavec) {
202  const char* src = (iter_begin++)->c_str();
203  const size_t length = std::min(N - 1 , std::strlen(src));
204  std::memcpy(dst_array.data(), src, length);
205  dst_array[length] = 0;
206  }
207 }
208 
209 template <std::size_t N>
211 ::FixedLenStringArray(const std::vector<std::string> & vec)
212  : FixedLenStringArray(&vec.front(), &vec.back()) {}
213 
214 template <std::size_t N>
216 ::FixedLenStringArray(const std::initializer_list<std::string>& init_list)
217  : FixedLenStringArray(init_list.begin(), init_list.end()) {}
218 
219 template <std::size_t N>
221  datavec.emplace_back();
222  const size_t length = std::min(N - 1 , src.length());
223  std::memcpy(datavec.back().data(), src.c_str(), length);
224  datavec.back()[length] = 0;
225 }
226 
227 template <std::size_t N>
228 inline void FixedLenStringArray<N>::push_back(const std::array<char, N>& src) {
229  datavec.emplace_back();
230  std::copy(src.begin(), src.end(), datavec.back().data());
231 }
232 
233 template <std::size_t N>
234 inline std::string FixedLenStringArray<N>::getString(std::size_t i) const {
235  return std::string(datavec[i].data());
236 }
237 
238 // Internal
239 // Reference mapping
240 template <>
242  _hid = H5Tcopy(H5T_STD_REF_OBJ);
243 }
244 
245 
246 // Calculate the padding required to align an element of a struct
247 #define _H5_STRUCT_PADDING(current_size, member_size) (((member_size) - (current_size)) % (member_size))
248 
249 inline void CompoundType::create(size_t size) {
250  if (size == 0) {
251  size_t current_size = 0, max_type_size = 0;
252 
253  // Do a first pass to find the total size of the compound datatype
254  for (auto& member: members) {
255  size_t member_size = H5Tget_size(member.base_type.getId());
256  if (member_size == 0) {
257  throw DataTypeException("Cannot get size of DataType with hid: " +
258  std::to_string(member.base_type.getId()));
259  }
260 
261  // Set the offset of this member within the struct according to the
262  // standard alignment rules
263  member.offset = current_size + _H5_STRUCT_PADDING(current_size, member_size);
264 
265  // Set the current size to the end of the new member
266  current_size = member.offset + member_size;
267 
268  max_type_size = std::max(max_type_size, member_size);
269  }
270 
271  size = current_size + _H5_STRUCT_PADDING(current_size, max_type_size);
272  }
273 
274  // Create the HDF5 type
275  if((_hid = H5Tcreate(H5T_COMPOUND, size)) < 0) {
276  HDF5ErrMapper::ToException<DataTypeException>(
277  "Could not create new compound datatype");
278  }
279 
280  // Loop over all the members and insert them into the datatype
281  for (const auto& member: members) {
282  if(H5Tinsert(_hid, member.name.c_str(), member.offset, member.base_type.getId()) < 0) {
283  HDF5ErrMapper::ToException<DataTypeException>(
284  "Could not add new member to datatype"
285  );
286  }
287  }
288 }
289 
290 #undef _H5_STRUCT_PADDING
291 
292 inline void CompoundType::commit(const Object& object, const std::string& name) const {
293  H5Tcommit2(object.getId(), name.c_str(), getId(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
294 }
295 
296 template<typename T>
297 inline void EnumType<T>::create() {
298  // Create the HDF5 type
299  if((_hid = H5Tenum_create(AtomicType<typename std::underlying_type<T>::type>{}.getId())) < 0) {
300  HDF5ErrMapper::ToException<DataTypeException>(
301  "Could not create new enum datatype");
302  }
303 
304  // Loop over all the members and insert them into the datatype
305  for (const auto& member: members) {
306  if(H5Tenum_insert(_hid, member.name.c_str(), &(member.value)) < 0) {
307  HDF5ErrMapper::ToException<DataTypeException>(
308  "Could not add new member to this enum datatype"
309  );
310  }
311  }
312 }
313 
314 template<typename T>
315 inline void EnumType<T>::commit(const Object& object, const std::string& name) const {
316  H5Tcommit2(object.getId(), name.c_str(), getId(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
317 }
318 
319 namespace {
320 
321 inline hid_t create_string(size_t length){
322  hid_t _hid = H5Tcopy(H5T_C_S1);
323  if (H5Tset_size(_hid, length) < 0) {
324  HDF5ErrMapper::ToException<DataTypeException>(
325  "Unable to define datatype size to variable");
326  }
327  // define encoding to UTF-8 by default
328  H5Tset_cset(_hid, H5T_CSET_UTF8);
329  return _hid;
330 }
331 
332 
333 inline DataTypeClass convert_type_class(const H5T_class_t& tclass) {
334  switch(tclass) {
335  case H5T_TIME:
336  return DataTypeClass::Time;
337  case H5T_INTEGER:
338  return DataTypeClass::Integer;
339  case H5T_FLOAT:
340  return DataTypeClass::Float;
341  case H5T_STRING:
342  return DataTypeClass::String;
343  case H5T_BITFIELD:
345  case H5T_OPAQUE:
346  return DataTypeClass::Opaque;
347  case H5T_COMPOUND:
349  case H5T_REFERENCE:
351  case H5T_ENUM:
352  return DataTypeClass::Enum;
353  case H5T_VLEN:
354  return DataTypeClass::VarLen;
355  case H5T_ARRAY:
356  return DataTypeClass::Array;
357  case H5T_NO_CLASS:
358  case H5T_NCLASSES:
359  default:
360  return DataTypeClass::Invalid;
361  }
362 }
363 
364 
365 inline std::string type_class_string(DataTypeClass tclass) {
366  switch(tclass) {
367  case DataTypeClass::Time:
368  return "Time";
370  return "Integer";
372  return "Float";
374  return "String";
376  return "BitField";
378  return "Opaque";
380  return "Compound";
382  return "Reference";
383  case DataTypeClass::Enum:
384  return "Enum";
386  return "Varlen";
388  return "Array";
389  default:
390  return "(Invalid)";
391  }
392 }
393 
394 } // unnamed namespace
395 
396 
398 template <typename T>
400  return AtomicType<T>();
401 }
402 
403 
405 template <typename T>
407 
408  DataType t = create_datatype<T>();
409  // Skip check if the base type is a variable length string
410  if (t.isVariableStr()) {
411  return t;
412  }
413  // Check that the size of the template type matches the size that HDF5 is
414  // expecting.
415  if(!t.isReference() && (sizeof(T) != t.getSize())) {
416  std::ostringstream ss;
417  ss << "Size of array type " << sizeof(T)
418  << " != that of memory datatype " << t.getSize()
419  << std::endl;
420  throw DataTypeException(ss.str());
421  }
422 
423  return t;
424 }
425 
426 } // namespace HighFive
427 
428 
429 #endif // H5DATATYPE_MISC_HPP
HighFive::DataTypeClass::String
@ String
HighFive::DataTypeClass::Opaque
@ Opaque
HighFive::DataTypeClass::Time
@ Time
HighFive::EnumType::commit
void commit(const Object &object, const std::string &name) const
Commit datatype into the given Object.
Definition: H5DataType_misc.hpp:315
HighFive::FixedLenStringArray::push_back
void push_back(const std::string &)
Append an std::string to the buffer structure.
Definition: H5DataType_misc.hpp:220
HighFive::DataType::getSize
size_t getSize() const
Returns the length (in bytes) of this type elements.
Definition: H5DataType_misc.hpp:36
HighFive::DataType::isFixedLenStr
bool isFixedLenStr() const
Returns whether the type is a fixed-length string.
Definition: H5DataType_misc.hpp:57
HighFive::DataType
HDF5 Data Type.
Definition: H5DataType.hpp:42
HighFive::details::array_dims
Definition: H5Utils.hpp:44
HighFive::DataType::isVariableStr
bool isVariableStr() const
Returns whether the type is a variable-length string.
Definition: H5DataType_misc.hpp:48
HighFive::DataTypeClass::VarLen
@ VarLen
HighFive::CompoundType::commit
void commit(const Object &object, const std::string &name) const
Commit datatype into the given Object.
Definition: H5DataType_misc.hpp:292
HighFive::Object
Definition: H5Object.hpp:36
HighFive::FixedLenStringArray::getString
std::string getString(std::size_t index) const
Retrieve a string from the structure as std::string.
Definition: H5DataType_misc.hpp:234
HighFive::FixedLenStringArray
A structure representing a set of fixed-length strings.
Definition: H5_definitions.hpp:42
HighFive::FixedLenStringArray::FixedLenStringArray
FixedLenStringArray()=default
HighFive::Object::getId
hid_t getId() const noexcept
getId
Definition: H5Object_misc.hpp:55
HighFive::AtomicType::AtomicType
AtomicType()
Definition: H5DataType_misc.hpp:181
HighFive::DataType::string
std::string string() const
Returns a friendly description of the type (e.g. Float32)
Definition: H5DataType_misc.hpp:65
HighFive::DataTypeClass::Enum
@ Enum
HighFive::DataType::operator==
bool operator==(const DataType &other) const
Definition: H5DataType_misc.hpp:40
HighFive::DataType::empty
bool empty() const noexcept
Check the DataType was default constructed. Such value might represent auto-detection of the datatype...
Definition: H5DataType_misc.hpp:28
HighFive::DataTypeClass
DataTypeClass
Enum of Fundamental data classes.
Definition: H5DataType.hpp:23
HighFive::DataTypeClass::Float
@ Float
HighFive::DataTypeClass::Integer
@ Integer
HighFive::AtomicType
create an HDF5 DataType from a C++ type
Definition: H5_definitions.hpp:36
HighFive::DataType::isReference
bool isReference() const
Returns whether the type is a Reference.
Definition: H5DataType_misc.hpp:61
HighFive::DataTypeClass::Array
@ Array
HighFive::DataType::operator!=
bool operator!=(const DataType &other) const
Definition: H5DataType_misc.hpp:44
copy
free of to any person obtaining a copy of this software and associated documentation to deal in the Software without including without limitation the rights to copy
Definition: LICENSE.txt:6
HighFive::Object::_hid
hid_t _hid
Definition: H5Object.hpp:81
HighFive::create_and_check_datatype
DataType create_and_check_datatype()
Create a DataType instance representing type T and perform a sanity check on its size.
Definition: H5DataType_misc.hpp:406
HighFive::AtomicType< char[StrLen]>::AtomicType
AtomicType()
Definition: H5DataType_misc.hpp:157
HighFive::create_datatype
DataType create_datatype()
Create a DataType instance representing type T.
Definition: H5DataType_misc.hpp:399
string
NAME string(REPLACE ".cpp" "_bin" example_name ${example_filename}) if($
Definition: hops/Third-party/HighFive/src/examples/CMakeLists.txt:6
HighFive::DataType::getClass
DataTypeClass getClass() const
Return the fundamental type.
Definition: H5DataType_misc.hpp:32
HighFive::DataTypeClass::Reference
@ Reference
HighFive::DataTypeClass::Invalid
@ Invalid
_H5_STRUCT_PADDING
#define _H5_STRUCT_PADDING(current_size, member_size)
Definition: H5DataType_misc.hpp:247
HighFive::AtomicType< FixedLenStringArray< StrLen > >::AtomicType
AtomicType()
Definition: H5DataType_misc.hpp:163
HighFive::DataTypeClass::Compound
@ Compound
HighFive::EnumType
Create a enum HDF5 datatype.
Definition: H5DataType.hpp:188
HighFive::DataTypeException
Exception specific to HighFive DataType interface.
Definition: H5Exception.hpp:83
HighFive
Definition: H5_definitions.hpp:15
HighFive::DataTypeClass::BitField
@ BitField