MDAL
mdal_hdf5.hpp
1 /*
2  MDAL - Mesh Data Abstraction Library (MIT License)
3  Copyright (C) 2018 Lutra Consulting Limited
4 */
5 
6 #ifndef MDAL_HDF5_HPP
7 #define MDAL_HDF5_HPP
8 
9 
12 // for compatibility (older hdf5 version in Travis)
13 #define H5Gopen_vers 1
14 
15 #include "mdal_utils.hpp"
16 #include "mdal_logger.hpp"
17 #include "hdf5.h"
18 typedef unsigned char uchar;
19 
20 #include <memory>
21 #include <vector>
22 #include <string>
23 #include <numeric>
24 
25 #include <assert.h>
26 #include "stdlib.h"
27 
28 #define HDF_MAX_NAME 1024
29 struct HdfString
30 {
31  char data [HDF_MAX_NAME];
32 };
33 
34 template <int TYPE> inline void hdfClose( hid_t id ) { MDAL_UNUSED( id ); assert( false ); }
35 template <> inline void hdfClose<H5I_FILE>( hid_t id ) { H5Fclose( id ); }
36 template <> inline void hdfClose<H5I_GROUP>( hid_t id ) { H5Gclose( id ); }
37 template <> inline void hdfClose<H5I_DATASET>( hid_t id ) { H5Dclose( id ); }
38 template <> inline void hdfClose<H5I_ATTR>( hid_t id ) { H5Aclose( id ); }
39 template <> inline void hdfClose<H5I_DATASPACE>( hid_t id ) { H5Sclose( id ); }
40 template <> inline void hdfClose<H5I_DATATYPE>( hid_t id ) { H5Tclose( id ); }
41 
42 template <int TYPE>
43 class HdfH
44 {
45  public:
46  HdfH( hid_t hid ) : id( hid ) {}
47  HdfH( const HdfH &other ) : id( other.id ) { }
48  ~HdfH() { if ( id >= 0 ) hdfClose<TYPE>( id ); }
49 
50  hid_t id;
51 };
52 
53 class HdfGroup;
54 class HdfDataset;
55 class HdfAttribute;
56 class HdfDataspace;
57 class HdfDataType;
58 
59 class HdfFile
60 {
61  public:
62  enum Mode
63  {
64  ReadOnly,
65  ReadWrite,
66  Create
67  };
68  typedef HdfH<H5I_FILE> Handle;
69 
70  HdfFile( const std::string &path, HdfFile::Mode mode );
71  ~HdfFile();
72  bool isValid() const;
73  hid_t id() const;
74 
75  inline std::vector<std::string> groups() const;
76 
77  inline HdfGroup group( const std::string &path ) const;
78  inline HdfDataset dataset( const std::string &path ) const;
79  inline HdfAttribute attribute( const std::string &attr_name ) const;
80  inline bool pathExists( const std::string &path ) const;
81  std::string filePath() const;
82 
83  protected:
84  std::shared_ptr<Handle> d;
85  std::string mPath;
86 };
87 
89 {
90  public:
91  typedef HdfH<H5I_DATATYPE> Handle;
92  HdfDataType();
93  HdfDataType( hid_t type, bool isNativeType = true );
94  ~HdfDataType();
95 
96  // Creates new string type with size, use HDF_MAX_NAME for maximum length
97  static HdfDataType createString( int size = HDF_MAX_NAME );
98  bool isValid() const;
99  hid_t id() const;
100 
101 
102  protected:
103  std::shared_ptr<Handle> d;
104  hid_t mNativeId = -1;
105 };
106 
107 class HdfGroup
108 {
109  public:
110  typedef HdfH<H5I_GROUP> Handle;
111 
112  static HdfGroup create( hid_t file, const std::string &path );
113  HdfGroup( hid_t file, const std::string &path );
114  HdfGroup( std::shared_ptr<Handle> handle );
115 
116  bool isValid() const;
117  hid_t id() const;
118  hid_t file_id() const;
119 
120  std::string name() const;
121 
122  std::vector<std::string> groups() const;
123  std::vector<std::string> datasets() const;
124  std::vector<std::string> objects() const;
125 
126  std::string childPath( const std::string &childName ) const;
127 
128  inline HdfGroup group( const std::string &groupName ) const;
129  inline HdfDataset dataset( const std::string &dsName ) const;
130  inline HdfAttribute attribute( const std::string &attr_name ) const;
131  inline bool pathExists( const std::string &path ) const;
132  protected:
133  std::vector<std::string> objects( H5G_obj_t type ) const;
134 
135  protected:
136  std::shared_ptr<Handle> d;
137 };
138 
140 {
141  public:
142  typedef HdfH<H5I_ATTR> Handle;
143 
145  HdfAttribute( hid_t obj_id, const std::string &attr_name, HdfDataType type );
146 
148  HdfAttribute( hid_t obj_id, const std::string &attr_name );
149  ~HdfAttribute();
150  bool isValid() const;
151  hid_t id() const;
152 
153  std::string readString() const;
154  double readDouble() const;
155 
156  void write( const std::string &value );
157  void write( int value );
158 
159  protected:
160  std::shared_ptr<Handle> d;
161  hid_t m_objId;
162  std::string m_name;
163  HdfDataType mType; // when in write mode
164 };
165 
166 
167 
169 {
170  public:
171  typedef HdfH<H5I_DATASPACE> Handle;
172 
174  HdfDataspace( const std::vector<hsize_t> &dims );
176  HdfDataspace( hid_t dataset = -1 );
177  ~HdfDataspace( );
179  void selectHyperslab( hsize_t start, hsize_t count );
181  void selectHyperslab( const std::vector<hsize_t> offsets,
182  const std::vector<hsize_t> counts );
183 
184  bool isValid() const;
185  hid_t id() const;
186 
187  protected:
188  std::shared_ptr<Handle> d;
189 };
190 
192 {
193  public:
194  typedef HdfH<H5I_DATASET> Handle;
195 
197  HdfDataset() = default;
198 
200  HdfDataset( hid_t file, const std::string &path, HdfDataType dtype, size_t nItems = 1 );
202  HdfDataset( hid_t file, const std::string &path, HdfDataType dtype, HdfDataspace dataspace );
204  HdfDataset( hid_t file, const std::string &path );
205  ~HdfDataset();
206  bool isValid() const;
207  hid_t id() const;
208 
209  std::vector<hsize_t> dims() const;
210 
211  hsize_t elementCount() const;
212 
213  H5T_class_t type() const;
214 
218  std::vector<uchar> readArrayUint8() const;
219  std::vector<float> readArray() const;
220  std::vector<double> readArrayDouble() const;
221  std::vector<int> readArrayInt() const;
222  std::vector<std::string> readArrayString() const;
223 
228  std::vector<uchar> readArrayUint8( const std::vector<hsize_t> offsets, const std::vector<hsize_t> counts ) const;
229  std::vector<float> readArray( const std::vector<hsize_t> offsets, const std::vector<hsize_t> counts ) const;
230  std::vector<double> readArrayDouble( const std::vector<hsize_t> offsets, const std::vector<hsize_t> counts ) const;
231  std::vector<int> readArrayInt( const std::vector<hsize_t> offsets, const std::vector<hsize_t> counts ) const;
232 
233  inline bool hasAttribute( const std::string &attr_name ) const;
234  inline HdfAttribute attribute( const std::string &attr_name ) const;
235 
236  template <typename T> std::vector<T> readArray( hid_t mem_type_id ) const
237  {
238  hsize_t cnt = elementCount();
239  std::vector<T> data( cnt );
240  herr_t status = H5Dread( d->id, mem_type_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, data.data() );
241  if ( status < 0 )
242  {
243  MDAL::Log::debug( "Failed to read data!" );
244  return std::vector<T>();
245  }
246  return data;
247  }
248 
249  template <typename T> std::vector<T> readArray( hid_t mem_type_id,
250  const std::vector<hsize_t> offsets,
251  const std::vector<hsize_t> counts ) const
252  {
253  HdfDataspace dataspace( d->id );
254  dataspace.selectHyperslab( offsets, counts );
255 
256  hsize_t totalItems = 1;
257  for ( auto it = counts.begin(); it != counts.end(); ++it )
258  totalItems *= *it;
259 
260  std::vector<hsize_t> dims = {totalItems};
261  HdfDataspace memspace( dims );
262  memspace.selectHyperslab( 0, totalItems );
263 
264  std::vector<T> data( totalItems );
265  herr_t status = H5Dread( d->id, mem_type_id, memspace.id(), dataspace.id(), H5P_DEFAULT, data.data() );
266  if ( status < 0 )
267  {
268  MDAL::Log::debug( "Failed to read data!" );
269  return std::vector<T>();
270  }
271  return data;
272  }
273 
275  float readFloat() const;
276 
278  std::string readString() const;
279 
281  void write( const std::string &value );
282 
284  void write( std::vector<float> &value );
285  void write( float value );
286 
288  void write( std::vector<double> &value );
289 
290  protected:
291  std::shared_ptr<Handle> d;
292  HdfDataType mType; // when in write mode
293 };
294 
295 inline std::vector<std::string> HdfFile::groups() const { return group( "/" ).groups(); }
296 
297 inline HdfGroup HdfFile::group( const std::string &path ) const { return HdfGroup( d->id, path ); }
298 
299 inline HdfDataset HdfFile::dataset( const std::string &path ) const { return HdfDataset( d->id, path ); }
300 
301 inline HdfGroup HdfGroup::group( const std::string &groupName ) const { return HdfGroup( file_id(), childPath( groupName ) ); }
302 
303 inline HdfDataset HdfGroup::dataset( const std::string &dsName ) const { return HdfDataset( file_id(), childPath( dsName ) ); }
304 
305 inline bool HdfDataset::hasAttribute( const std::string &attr_name ) const
306 {
307  htri_t res = H5Aexists( d->id, attr_name.c_str() );
308  return res > 0 ;
309 }
310 
311 inline HdfAttribute HdfFile::attribute( const std::string &attr_name ) const { return HdfAttribute( d->id, attr_name ); }
312 
313 inline HdfAttribute HdfGroup::attribute( const std::string &attr_name ) const { return HdfAttribute( d->id, attr_name ); }
314 
315 inline HdfAttribute HdfDataset::attribute( const std::string &attr_name ) const { return HdfAttribute( d->id, attr_name ); }
316 
317 inline bool HdfFile::pathExists( const std::string &path ) const { return H5Lexists( d->id, path.c_str(), H5P_DEFAULT ) > 0; }
318 
319 inline bool HdfGroup::pathExists( const std::string &path ) const { return H5Lexists( d->id, path.c_str(), H5P_DEFAULT ) > 0; }
320 
321 #endif // MDAL_HDF5_HPP
Definition: mdal_hdf5.hpp:140
HdfAttribute(hid_t obj_id, const std::string &attr_name, HdfDataType type)
Create new attribute for writing for 1 item.
Definition: mdal_hdf5.cpp:95
Definition: mdal_hdf5.hpp:89
Definition: mdal_hdf5.hpp:192
std::string readString() const
Reads string value.
Definition: mdal_hdf5.cpp:316
void write(const std::string &value)
Writes string dataset with single entry.
Definition: mdal_hdf5.cpp:301
float readFloat() const
Reads float value.
Definition: mdal_hdf5.cpp:253
std::vector< uchar > readArrayUint8() const
Reads full array into vector Array can have any number of dimenstions and it is fully read into 1D ve...
Definition: mdal_hdf5.cpp:229
HdfDataset()=default
creates invalid dataset
Definition: mdal_hdf5.hpp:169
HdfDataspace(const std::vector< hsize_t > &dims)
memory dataspace for simple N-D array
Definition: mdal_hdf5.cpp:335
void selectHyperslab(hsize_t start, hsize_t count)
select from 1D array
Definition: mdal_hdf5.cpp:353
Definition: mdal_hdf5.hpp:60
Definition: mdal_hdf5.hpp:108
Definition: mdal_hdf5.hpp:44
Definition: mdal_hdf5.hpp:30