Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: Hierarchical Data Format Release 5 (HDF5) 4 : * Purpose: Header file for HDF5 datasets reader. 5 : * Author: Denis Nadeau (denis.nadeau@gmail.com) 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com> 9 : * Copyright (c) 2013, Even Rouault <even dot rouault at spatialys.com> 10 : * 11 : * SPDX-License-Identifier: MIT 12 : ****************************************************************************/ 13 : 14 : #ifndef HDF5DATASET_H_INCLUDED_ 15 : #define HDF5DATASET_H_INCLUDED_ 16 : 17 : #include "hdf5_api.h" 18 : #include "hdf5eosparser.h" 19 : 20 : #include "cpl_list.h" 21 : #include "gdal_pam.h" 22 : 23 : #include <map> 24 : 25 : #ifdef ENABLE_HDF5_GLOBAL_LOCK 26 : #include <mutex> 27 : std::recursive_mutex &GetHDF5GlobalMutex(); 28 : #define HDF5_GLOBAL_LOCK() \ 29 : std::lock_guard<std::recursive_mutex> oLock(GetHDF5GlobalMutex()) 30 : #else 31 : #define HDF5_GLOBAL_LOCK() \ 32 : do \ 33 : { \ 34 : } while (0) 35 : #endif 36 : 37 : typedef struct HDF5GroupObjects 38 : { 39 : char *pszName; 40 : char *pszPath; 41 : char *pszUnderscorePath; 42 : char *pszTemp; 43 : int nType; 44 : int nIndex; 45 : hsize_t nbObjs; 46 : int nbAttrs; 47 : int nRank; 48 : hsize_t *paDims; 49 : hid_t native; 50 : hid_t HDatatype; 51 : unsigned long objno[2]; 52 : struct HDF5GroupObjects *poHparent; 53 : struct HDF5GroupObjects *poHchild; 54 : } HDF5GroupObjects; 55 : 56 : herr_t HDF5CreateGroupObjs(hid_t, const char *, void *); 57 : 58 : hid_t HDF5GetFileDriver(); 59 : void HDF5UnloadFileDriver(); 60 : 61 : hid_t GDAL_HDF5Open(const std::string &osFilename); 62 : 63 : #if defined(H5_VERSION_GE) // added in 1.8.7 64 : #if !H5_VERSION_GE(1, 8, 13) 65 : #ifndef _WIN32 66 : #define H5free_memory(x) free(x) 67 : #else 68 : #define H5free_memory(x) CPL_IGNORE_RET_VAL(x) 69 : #endif 70 : #endif 71 : #else 72 : #ifndef _WIN32 73 : #define H5free_memory(x) free(x) 74 : #else 75 : #define H5free_memory(x) CPL_IGNORE_RET_VAL(x) 76 : #endif 77 : #endif 78 : 79 : // Release 1.6.3 or 1.6.4 changed the type of count in some API functions. 80 : 81 : #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR <= 6 && \ 82 : (H5_VERS_MINOR < 6 || H5_VERS_RELEASE < 3) 83 : #define H5OFFSET_TYPE hssize_t 84 : #else 85 : #define H5OFFSET_TYPE hsize_t 86 : #endif 87 : 88 : class HDF5Dataset; 89 : class HDF5EOSParser; 90 : class BAGDataset; 91 : class S100BaseDataset; 92 : 93 : namespace GDAL 94 : { 95 : class HDF5Group; 96 : 97 : /************************************************************************/ 98 : /* HDF5SharedResources */ 99 : /************************************************************************/ 100 : 101 : class HDF5SharedResources 102 : { 103 : friend class ::HDF5Dataset; 104 : friend class ::BAGDataset; 105 : friend class ::S100BaseDataset; 106 : 107 : std::weak_ptr<HDF5SharedResources> m_poSelf{}; 108 : bool m_bReadOnly = true; 109 : hid_t m_hHDF5 = 0; 110 : CPLString m_osFilename{}; 111 : std::shared_ptr<GDALPamMultiDim> m_poPAM{}; 112 : std::unique_ptr<HDF5EOSParser> m_poHDF5EOSParser{}; 113 : std::map<std::string, std::vector<std::shared_ptr<GDALDimension>>> 114 : m_oMapEOSGridNameToDimensions{}; 115 : std::map<std::string, std::vector<std::shared_ptr<GDALDimension>>> 116 : m_oMapEOSSwathNameToDimensions{}; 117 : std::map<std::string, std::shared_ptr<GDALMDArray>> m_oRefKeeper; 118 : 119 : explicit HDF5SharedResources(const std::string &osFilename); 120 : 121 : public: 122 : static std::shared_ptr<HDF5SharedResources> 123 : Create(const std::string &osFilename); 124 : ~HDF5SharedResources(); 125 : 126 : std::shared_ptr<HDF5Group> GetRootGroup(); 127 : 128 344 : const std::string &GetFilename() const 129 : { 130 344 : return m_osFilename; 131 : } 132 : 133 1033 : inline hid_t GetHDF5() const 134 : { 135 1033 : return m_hHDF5; 136 : } 137 : 138 42 : inline bool IsReadOnly() const 139 : { 140 42 : return m_bReadOnly; 141 : } 142 : 143 : const std::shared_ptr<GDALPamMultiDim> &GetPAM() 144 : { 145 : return m_poPAM; 146 : } 147 : 148 190 : const HDF5EOSParser *GetHDF5EOSParser() const 149 : { 150 190 : return m_poHDF5EOSParser.get(); 151 : } 152 : 153 2 : void RegisterEOSGridDimensions( 154 : const std::string &osGridName, 155 : const std::vector<std::shared_ptr<GDALDimension>> &apoDims) 156 : { 157 2 : m_oMapEOSGridNameToDimensions[osGridName] = apoDims; 158 2 : } 159 : 160 : std::vector<std::shared_ptr<GDALDimension>> 161 2 : GetEOSGridDimensions(const std::string &osGridName) const 162 : { 163 2 : auto oIter = m_oMapEOSGridNameToDimensions.find(osGridName); 164 2 : if (oIter == m_oMapEOSGridNameToDimensions.end()) 165 0 : return {}; 166 2 : return oIter->second; 167 : } 168 : 169 3 : void RegisterEOSSwathDimensions( 170 : const std::string &osSwathName, 171 : const std::vector<std::shared_ptr<GDALDimension>> &apoDims) 172 : { 173 3 : m_oMapEOSSwathNameToDimensions[osSwathName] = apoDims; 174 3 : } 175 : 176 : std::vector<std::shared_ptr<GDALDimension>> 177 3 : GetEOSSwathDimensions(const std::string &osSwathName) const 178 : { 179 3 : auto oIter = m_oMapEOSSwathNameToDimensions.find(osSwathName); 180 3 : if (oIter == m_oMapEOSSwathNameToDimensions.end()) 181 0 : return {}; 182 3 : return oIter->second; 183 : } 184 : 185 56 : void KeepRef(const std::shared_ptr<GDALMDArray> &poArray) 186 : { 187 56 : m_oRefKeeper[poArray->GetFullName()] = poArray; 188 56 : } 189 : }; 190 : 191 : } // namespace GDAL 192 : 193 : /************************************************************************/ 194 : /* ==================================================================== */ 195 : /* HDF5Dataset */ 196 : /* ==================================================================== */ 197 : /************************************************************************/ 198 : class HDF5Dataset CPL_NON_FINAL : public GDALPamDataset 199 : { 200 : protected: 201 : hid_t m_hHDF5 = -1; 202 : hid_t hGroupID; // H handler interface. 203 : char **papszSubDatasets; 204 : int nDatasetType; 205 : int nSubDataCount; 206 : 207 : HDF5GroupObjects *poH5RootGroup; /* Contain hdf5 Groups information */ 208 : std::shared_ptr<GDALGroup> m_poRootGroup{}; 209 : 210 : CPLStringList m_aosMetadata{}; 211 : 212 : HDF5EOSParser m_oHDFEOSParser{}; 213 : 214 : CPLErr ReadGlobalAttributes(int); 215 : CPLErr HDF5ListGroupObjects(HDF5GroupObjects *, int); 216 : static CPLErr CreateMetadata(hid_t hHDF5, HDF5GroupObjects *, int, 217 : bool bPrefixWithDatasetName, 218 : CPLStringList &aosMetadata); 219 : 220 : HDF5GroupObjects *HDF5FindDatasetObjects(HDF5GroupObjects *, const char *); 221 : HDF5GroupObjects *HDF5FindDatasetObjectsbyPath(HDF5GroupObjects *, 222 : const char *); 223 : char *CreatePath(HDF5GroupObjects *); 224 : static void DestroyH5Objects(HDF5GroupObjects *); 225 : 226 : /** 227 : * Reads an array of double attributes from the HDF5 metadata. 228 : * It reads the attributes directly on its binary form directly, 229 : * thus avoiding string conversions. 230 : * 231 : * Important: It allocates the memory for the attributes internally, 232 : * so the caller must free the returned array after using it. 233 : * @param pszAttrName Name of the attribute to be read. 234 : * the attribute name must be the form: 235 : * root attribute name 236 : * SUBDATASET/subdataset attribute name 237 : * @param pdfValues pointer which will store the array of doubles read. 238 : * @param nLen it stores the length of the array read. If NULL it doesn't 239 : * inform the length of the array. 240 : * @return CPLErr CE_None in case of success, CE_Failure in case of failure 241 : */ 242 : CPLErr HDF5ReadDoubleAttr(const char *pszAttrName, double **pdfValues, 243 : int *nLen = nullptr); 244 : 245 : public: 246 : HDF5Dataset(); 247 : ~HDF5Dataset(); 248 : 249 27 : std::shared_ptr<GDALGroup> GetRootGroup() const override 250 : { 251 27 : return m_poRootGroup; 252 : } 253 : 254 : static GDALDataset *Open(GDALOpenInfo *); 255 : static GDALDataset *OpenMultiDim(GDALOpenInfo *); 256 : static std::shared_ptr<GDALGroup> OpenGroup( 257 : const std::shared_ptr<GDAL::HDF5SharedResources> &poSharedResources); 258 : 259 : static bool IsNativeCFloat16(hid_t hDataType); 260 : static const char *GetDataTypeName(hid_t); 261 : static GDALDataType GetDataType(hid_t); 262 : }; 263 : 264 : #endif /* HDF5DATASET_H_INCLUDED_ */