1 /******************************************************************************
2  * $Id: hdf5dataset.h 16c87cd95f27db3344c6c034950fdf285666d924 2020-08-18 15:37:19 +0200 Even Rouault $
3  *
4  * Project:  Hierarchical Data Format Release 5 (HDF5)
5  * Purpose:  Header file for HDF5 datasets reader.
6  * Author:   Denis Nadeau (denis.nadeau@gmail.com)
7  *
8  ******************************************************************************
9  * Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
10  * Copyright (c) 2013, Even Rouault <even dot rouault at spatialys.com>
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a
13  * copy of this software and associated documentation files (the "Software"),
14  * to deal in the Software without restriction, including without limitation
15  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16  * and/or sell copies of the Software, and to permit persons to whom the
17  * Software is furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included
20  * in all copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28  * DEALINGS IN THE SOFTWARE.
29  ****************************************************************************/
30 
31 #ifndef HDF5DATASET_H_INCLUDED_
32 #define HDF5DATASET_H_INCLUDED_
33 
34 #include "hdf5_api.h"
35 
36 #include "cpl_list.h"
37 #include "gdal_pam.h"
38 
39 typedef struct HDF5GroupObjects
40 {
41     char *pszName;
42     char *pszPath;
43     char *pszUnderscorePath;
44     char *pszTemp;
45     int nType;
46     int nIndex;
47     hsize_t nbObjs;
48     int nbAttrs;
49     int nRank;
50     hsize_t *paDims;
51     hid_t native;
52     hid_t HDatatype;
53     unsigned long objno[2];
54     struct HDF5GroupObjects *poHparent;
55     struct HDF5GroupObjects *poHchild;
56 } HDF5GroupObjects;
57 
58 herr_t HDF5CreateGroupObjs(hid_t, const char *, void *);
59 
60 hid_t HDF5GetFileDriver();
61 void HDF5UnloadFileDriver();
62 
63 hid_t GDAL_HDF5Open(const std::string& osFilename );
64 
65 #if defined(H5_VERSION_GE) // added in 1.8.7
66 # if !H5_VERSION_GE(1,8,13)
67 #ifndef _WIN32
68 #  define H5free_memory(x) free(x)
69 #else
70 #  define H5free_memory(x) CPL_IGNORE_RET_VAL(x)
71 #endif
72 # endif
73 #else
74 #ifndef _WIN32
75 #  define H5free_memory(x) free(x)
76 #else
77 #  define H5free_memory(x) CPL_IGNORE_RET_VAL(x)
78 #endif
79 #endif
80 
81 // Release 1.6.3 or 1.6.4 changed the type of count in some API functions.
82 
83 #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR <= 6 \
84        && (H5_VERS_MINOR < 6 || H5_VERS_RELEASE < 3)
85 #  define H5OFFSET_TYPE hssize_t
86 #else
87 #  define H5OFFSET_TYPE  hsize_t
88 #endif
89 
90 class HDF5Dataset;
91 class BAGDataset;
92 
93 namespace GDAL
94 {
95 
96 /************************************************************************/
97 /*                         HDF5SharedResources                          */
98 /************************************************************************/
99 
100 class HDF5SharedResources
101 {
102     friend class ::HDF5Dataset;
103     friend class ::BAGDataset;
104 
105     bool m_bReadOnly = true;
106     hid_t            m_hHDF5 = 0;
107     CPLString        m_osFilename{};
108 public:
109     HDF5SharedResources() = default;
110     ~HDF5SharedResources();
111 
GetHDF5()112     inline hid_t GetHDF5() const { return m_hHDF5; }
IsReadOnly()113     inline bool IsReadOnly() const { return m_bReadOnly; }
114 };
115 
116 } // namespace GDAL
117 
118 /************************************************************************/
119 /* ==================================================================== */
120 /*                              HDF5Dataset                             */
121 /* ==================================================================== */
122 /************************************************************************/
123 class HDF5Dataset CPL_NON_FINAL: public GDALPamDataset
124 {
125 protected:
126     hid_t            hHDF5;
127     hid_t            hGroupID; // H handler interface.
128     char             **papszSubDatasets;
129     int              bIsHDFEOS;
130     int              nDatasetType;
131     int              nSubDataCount;
132 
133     HDF5GroupObjects *poH5RootGroup; /* Contain hdf5 Groups information */
134     std::shared_ptr<GDALGroup> m_poRootGroup{};
135 
136     CPLErr ReadGlobalAttributes(int);
137     CPLErr HDF5ListGroupObjects(HDF5GroupObjects *, int );
138     CPLErr CreateMetadata( HDF5GroupObjects *, int );
139 
140     HDF5GroupObjects *HDF5FindDatasetObjects( HDF5GroupObjects *, const char * );
141     HDF5GroupObjects *HDF5FindDatasetObjectsbyPath( HDF5GroupObjects *, const char * );
142     char *CreatePath(HDF5GroupObjects *);
143     void DestroyH5Objects(HDF5GroupObjects *);
144 
145     static const char *GetDataTypeName(hid_t);
146 
147   /**
148    * Reads an array of double attributes from the HDF5 metadata.
149    * It reads the attributes directly on its binary form directly,
150    * thus avoiding string conversions.
151    *
152    * Important: It allocates the memory for the attributes internally,
153    * so the caller must free the returned array after using it.
154    * @param pszAttrName Name of the attribute to be read.
155    *                    the attribute name must be the form:
156    *                                    root attribute name
157    *                                    SUBDATASET/subdataset attribute name
158    * @param pdfValues pointer which will store the array of doubles read.
159    * @param nLen it stores the length of the array read. If NULL it doesn't inform
160    *        the length of the array.
161    * @return CPLErr CE_None in case of success, CE_Failure in case of failure
162    */
163     CPLErr HDF5ReadDoubleAttr(const char *pszAttrName, double **pdfValues,
164                               int *nLen = nullptr);
165 
166   public:
167 
168     char             **papszMetadata;
169     HDF5GroupObjects *poH5CurrentObject;
170 
171     HDF5Dataset();
172     ~HDF5Dataset();
173 
GetRootGroup()174     std::shared_ptr<GDALGroup> GetRootGroup() const override { return m_poRootGroup; }
175 
176     static GDALDataset *Open(GDALOpenInfo *);
177     static GDALDataset *OpenMultiDim(GDALOpenInfo *);
178     static std::shared_ptr<GDALGroup> OpenGroup(std::shared_ptr<GDAL::HDF5SharedResources> poSharedResources);
179     static int Identify(GDALOpenInfo *);
180 
181     static GDALDataType GetDataType(hid_t);
182 };
183 
184 #endif /* HDF5DATASET_H_INCLUDED_ */
185