LCOV - code coverage report
Current view: top level - frmts/hdf5 - gh5_convenience.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 140 210 66.7 %
Date: 2024-05-03 15:49:35 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  Hierarchical Data Format Release 5 (HDF5)
       4             :  * Purpose:  HDF5 convenience functions.
       5             :  * Author:   Frank Warmerdam <warmerdam@pobox.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2009, Frank Warmerdam <warmerdam@pobox.com>
       9             :  *
      10             :  * Permission is hereby granted, free of charge, to any person obtaining a
      11             :  * copy of this software and associated documentation files (the "Software"),
      12             :  * to deal in the Software without restriction, including without limitation
      13             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14             :  * and/or sell copies of the Software, and to permit persons to whom the
      15             :  * Software is furnished to do so, subject to the following conditions:
      16             :  *
      17             :  * The above copyright notice and this permission notice shall be included
      18             :  * in all copies or substantial portions of the Software.
      19             :  *
      20             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26             :  * DEALINGS IN THE SOFTWARE.
      27             :  ****************************************************************************/
      28             : 
      29             : #include "gh5_convenience.h"
      30             : 
      31             : /************************************************************************/
      32             : /*                    GH5_FetchAttribute(CPLString)                     */
      33             : /************************************************************************/
      34             : 
      35          84 : bool GH5_FetchAttribute(hid_t loc_id, const char *pszAttrName,
      36             :                         CPLString &osResult, bool bReportError)
      37             : 
      38             : {
      39          84 :     if (!bReportError && H5Aexists(loc_id, pszAttrName) <= 0)
      40             :     {
      41           0 :         return false;
      42             :     }
      43             : 
      44          84 :     hid_t hAttr = H5Aopen_name(loc_id, pszAttrName);
      45             : 
      46          84 :     osResult.clear();
      47             : 
      48          84 :     if (hAttr < 0)
      49             :     {
      50           0 :         if (bReportError)
      51           0 :             CPLError(CE_Failure, CPLE_AppDefined,
      52             :                      "Attempt to read attribute %s failed, not found.",
      53             :                      pszAttrName);
      54           0 :         return false;
      55             :     }
      56             : 
      57          84 :     const hid_t hAttrSpace = H5Aget_space(hAttr);
      58          84 :     hsize_t anSize[H5S_MAX_RANK] = {};
      59             :     const unsigned int nAttrDims =
      60          84 :         H5Sget_simple_extent_dims(hAttrSpace, anSize, nullptr);
      61          84 :     if (nAttrDims != 0 && !(nAttrDims == 1 && anSize[0] == 1))
      62             :     {
      63           0 :         H5Sclose(hAttrSpace);
      64           0 :         H5Aclose(hAttr);
      65           0 :         return false;
      66             :     }
      67             : 
      68          84 :     hid_t hAttrTypeID = H5Aget_type(hAttr);
      69          84 :     hid_t hAttrNativeType = H5Tget_native_type(hAttrTypeID, H5T_DIR_DEFAULT);
      70             : 
      71          84 :     bool retVal = false;
      72          84 :     if (H5Tget_class(hAttrNativeType) == H5T_STRING)
      73             :     {
      74          84 :         if (H5Tis_variable_str(hAttrNativeType))
      75             :         {
      76          13 :             char *aszBuffer[1] = {nullptr};
      77          13 :             H5Aread(hAttr, hAttrNativeType, aszBuffer);
      78             : 
      79          13 :             if (aszBuffer[0])
      80          13 :                 osResult = aszBuffer[0];
      81             : 
      82          13 :             H5Dvlen_reclaim(hAttrNativeType, hAttrSpace, H5P_DEFAULT,
      83             :                             aszBuffer);
      84             :         }
      85             :         else
      86             :         {
      87          71 :             const size_t nAttrSize = H5Tget_size(hAttrTypeID);
      88          71 :             char *pachBuffer = static_cast<char *>(CPLCalloc(nAttrSize + 1, 1));
      89          71 :             H5Aread(hAttr, hAttrNativeType, pachBuffer);
      90             : 
      91          71 :             osResult = pachBuffer;
      92          71 :             CPLFree(pachBuffer);
      93             :         }
      94             : 
      95          84 :         retVal = true;
      96             :     }
      97             :     else
      98             :     {
      99           0 :         if (bReportError)
     100           0 :             CPLError(
     101             :                 CE_Failure, CPLE_AppDefined,
     102             :                 "Attribute %s of unsupported type for conversion to string.",
     103             :                 pszAttrName);
     104             : 
     105           0 :         retVal = false;
     106             :     }
     107             : 
     108          84 :     H5Sclose(hAttrSpace);
     109          84 :     H5Tclose(hAttrNativeType);
     110          84 :     H5Tclose(hAttrTypeID);
     111          84 :     H5Aclose(hAttr);
     112          84 :     return retVal;
     113             : }
     114             : 
     115             : /************************************************************************/
     116             : /*                      GH5_FetchAttribute(double)                      */
     117             : /************************************************************************/
     118             : 
     119         955 : bool GH5_FetchAttribute(hid_t loc_id, const char *pszAttrName, double &dfResult,
     120             :                         bool bReportError)
     121             : 
     122             : {
     123         955 :     if (!bReportError && H5Aexists(loc_id, pszAttrName) <= 0)
     124             :     {
     125         375 :         return false;
     126             :     }
     127             : 
     128         580 :     const hid_t hAttr = H5Aopen_name(loc_id, pszAttrName);
     129             : 
     130         580 :     dfResult = 0.0;
     131         580 :     if (hAttr < 0)
     132             :     {
     133           0 :         if (bReportError)
     134           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     135             :                      "Attempt to read attribute %s failed, not found.",
     136             :                      pszAttrName);
     137           0 :         return false;
     138             :     }
     139             : 
     140         580 :     hid_t hAttrTypeID = H5Aget_type(hAttr);
     141         580 :     hid_t hAttrNativeType = H5Tget_native_type(hAttrTypeID, H5T_DIR_DEFAULT);
     142             : 
     143             :     // Confirm that we have a single element value.
     144         580 :     hid_t hAttrSpace = H5Aget_space(hAttr);
     145         580 :     hsize_t anSize[H5S_MAX_RANK] = {};
     146         580 :     int nAttrDims = H5Sget_simple_extent_dims(hAttrSpace, anSize, nullptr);
     147             : 
     148         580 :     int i, nAttrElements = 1;
     149             : 
     150         590 :     for (i = 0; i < nAttrDims; i++)
     151             :     {
     152          10 :         nAttrElements *= (int)anSize[i];
     153             :     }
     154             : 
     155         580 :     if (nAttrElements != 1)
     156             :     {
     157           0 :         if (bReportError)
     158           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     159             :                      "Attempt to read attribute %s failed, count=%d, not 1.",
     160             :                      pszAttrName, nAttrElements);
     161             : 
     162           0 :         H5Sclose(hAttrSpace);
     163           0 :         H5Tclose(hAttrNativeType);
     164           0 :         H5Tclose(hAttrTypeID);
     165           0 :         H5Aclose(hAttr);
     166           0 :         return false;
     167             :     }
     168             : 
     169             :     // Read the value.
     170         580 :     void *buf = CPLMalloc(H5Tget_size(hAttrNativeType));
     171         580 :     H5Aread(hAttr, hAttrNativeType, buf);
     172             : 
     173             :     // Translate to double.
     174         580 :     if (H5Tequal(H5T_NATIVE_CHAR, hAttrNativeType))
     175           0 :         dfResult = *((char *)buf);
     176         580 :     else if (H5Tequal(H5T_NATIVE_SCHAR, hAttrNativeType))
     177           0 :         dfResult = *((signed char *)buf);
     178         580 :     else if (H5Tequal(H5T_NATIVE_UCHAR, hAttrNativeType))
     179           0 :         dfResult = *((unsigned char *)buf);
     180         580 :     else if (H5Tequal(H5T_NATIVE_SHORT, hAttrNativeType))
     181           0 :         dfResult = *((short *)buf);
     182         580 :     else if (H5Tequal(H5T_NATIVE_USHORT, hAttrNativeType))
     183           1 :         dfResult = *((unsigned short *)buf);
     184         579 :     else if (H5Tequal(H5T_NATIVE_INT, hAttrNativeType))
     185           0 :         dfResult = *((int *)buf);
     186         579 :     else if (H5Tequal(H5T_NATIVE_UINT, hAttrNativeType))
     187           1 :         dfResult = *((unsigned int *)buf);
     188         578 :     else if (H5Tequal(H5T_NATIVE_INT64, hAttrNativeType))
     189             :     {
     190           1 :         const auto nVal = *static_cast<int64_t *>(buf);
     191           1 :         dfResult = static_cast<double>(nVal);
     192           1 :         if (nVal != static_cast<int64_t>(dfResult))
     193             :         {
     194           0 :             CPLDebug("HDF5",
     195             :                      "Loss of accuracy when reading attribute %s. "
     196             :                      "Value " CPL_FRMT_GIB " will be read as %.18g",
     197             :                      pszAttrName, static_cast<GIntBig>(nVal), dfResult);
     198             :         }
     199             :     }
     200         577 :     else if (H5Tequal(H5T_NATIVE_UINT64, hAttrNativeType))
     201             :     {
     202           1 :         const auto nVal = *static_cast<uint64_t *>(buf);
     203           1 :         dfResult = static_cast<double>(nVal);
     204           1 :         if (nVal != static_cast<uint64_t>(dfResult))
     205             :         {
     206           0 :             CPLDebug("HDF5",
     207             :                      "Loss of accuracy when reading attribute %s. "
     208             :                      "Value " CPL_FRMT_GUIB " will be read as %.18g",
     209             :                      pszAttrName, static_cast<GUIntBig>(nVal), dfResult);
     210             :         }
     211             :     }
     212         576 :     else if (H5Tequal(H5T_NATIVE_FLOAT, hAttrNativeType))
     213         534 :         dfResult = *((float *)buf);
     214          42 :     else if (H5Tequal(H5T_NATIVE_DOUBLE, hAttrNativeType))
     215          42 :         dfResult = *((double *)buf);
     216             :     else
     217             :     {
     218           0 :         if (bReportError)
     219           0 :             CPLError(
     220             :                 CE_Failure, CPLE_AppDefined,
     221             :                 "Attribute %s of unsupported type for conversion to double.",
     222             :                 pszAttrName);
     223           0 :         CPLFree(buf);
     224             : 
     225           0 :         H5Sclose(hAttrSpace);
     226           0 :         H5Tclose(hAttrNativeType);
     227           0 :         H5Tclose(hAttrTypeID);
     228           0 :         H5Aclose(hAttr);
     229             : 
     230           0 :         return false;
     231             :     }
     232             : 
     233         580 :     CPLFree(buf);
     234             : 
     235         580 :     H5Sclose(hAttrSpace);
     236         580 :     H5Tclose(hAttrNativeType);
     237         580 :     H5Tclose(hAttrTypeID);
     238         580 :     H5Aclose(hAttr);
     239         580 :     return true;
     240             : }
     241             : 
     242             : /************************************************************************/
     243             : /*                          GH5_GetDataType()                           */
     244             : /*                                                                      */
     245             : /*      Transform HDF5 datatype to GDAL datatype                        */
     246             : /************************************************************************/
     247         144 : GDALDataType GH5_GetDataType(hid_t TypeID)
     248             : {
     249         144 :     if (H5Tequal(H5T_NATIVE_CHAR, TypeID))
     250           0 :         return GDT_Byte;
     251         144 :     else if (H5Tequal(H5T_NATIVE_SCHAR, TypeID))
     252           0 :         return GDT_Int8;
     253         144 :     else if (H5Tequal(H5T_NATIVE_UCHAR, TypeID))
     254           0 :         return GDT_Byte;
     255         144 :     else if (H5Tequal(H5T_NATIVE_SHORT, TypeID))
     256           0 :         return GDT_Int16;
     257         144 :     else if (H5Tequal(H5T_NATIVE_USHORT, TypeID))
     258           0 :         return GDT_UInt16;
     259         144 :     else if (H5Tequal(H5T_NATIVE_INT, TypeID))
     260           0 :         return GDT_Int32;
     261         144 :     else if (H5Tequal(H5T_NATIVE_UINT, TypeID))
     262           0 :         return GDT_UInt32;
     263         144 :     else if (H5Tequal(H5T_NATIVE_LONG, TypeID))
     264             :     {
     265             : #if SIZEOF_UNSIGNED_LONG == 4
     266             :         return GDT_Int32;
     267             : #else
     268           0 :         return GDT_Unknown;
     269             : #endif
     270             :     }
     271         144 :     else if (H5Tequal(H5T_NATIVE_ULONG, TypeID))
     272             :     {
     273             : #if SIZEOF_UNSIGNED_LONG == 4
     274             :         return GDT_UInt32;
     275             : #else
     276           0 :         return GDT_Unknown;
     277             : #endif
     278             :     }
     279         144 :     else if (H5Tequal(H5T_NATIVE_FLOAT, TypeID))
     280         144 :         return GDT_Float32;
     281           0 :     else if (H5Tequal(H5T_NATIVE_DOUBLE, TypeID))
     282           0 :         return GDT_Float64;
     283             : #ifdef notdef
     284             :     else if (H5Tequal(H5T_NATIVE_LLONG, TypeID))
     285             :         return GDT_Unknown;
     286             :     else if (H5Tequal(H5T_NATIVE_ULLONG, TypeID))
     287             :         return GDT_Unknown;
     288             : #endif
     289             : 
     290           0 :     return GDT_Unknown;
     291             : }
     292             : 
     293             : /************************************************************************/
     294             : /*                        GH5_CreateAttribute()                         */
     295             : /************************************************************************/
     296             : 
     297         114 : bool GH5_CreateAttribute(hid_t loc_id, const char *pszAttrName, hid_t TypeID,
     298             :                          unsigned nMaxLen)
     299             : {
     300             : #ifdef notdef_write_variable_length_string
     301             :     if (TypeID == H5T_C_S1)
     302             :     {
     303             :         hsize_t dims[1] = {1};
     304             :         hid_t dataspace = H5Screate_simple(1, dims, nullptr);
     305             :         hid_t type = H5Tcopy(TypeID);
     306             :         H5Tset_size(type, H5T_VARIABLE);
     307             :         hid_t att =
     308             :             H5Acreate(loc_id, pszAttrName, type, dataspace, H5P_DEFAULT);
     309             :         H5Tclose(type);
     310             :         H5Aclose(att);
     311             :         H5Sclose(dataspace);
     312             :         return true;
     313             :     }
     314             : #endif
     315             : 
     316         114 :     hid_t hDataSpace = H5Screate(H5S_SCALAR);
     317         114 :     if (hDataSpace < 0)
     318           0 :         return false;
     319             : 
     320         114 :     hid_t hDataType = H5Tcopy(TypeID);
     321         114 :     if (hDataType < 0)
     322             :     {
     323           0 :         H5Sclose(hDataSpace);
     324           0 :         return false;
     325             :     }
     326             : 
     327         114 :     if (TypeID == H5T_C_S1)
     328             :     {
     329          20 :         if (H5Tset_size(hDataType, nMaxLen) < 0)
     330             :         {
     331           0 :             H5Tclose(hDataType);
     332           0 :             H5Sclose(hDataSpace);
     333           0 :             return false;
     334             :         }
     335             :     }
     336             : 
     337             :     hid_t hAttr =
     338         114 :         H5Acreate(loc_id, pszAttrName, hDataType, hDataSpace, H5P_DEFAULT);
     339         114 :     if (hAttr < 0)
     340             :     {
     341           0 :         H5Sclose(hDataSpace);
     342           0 :         H5Tclose(hDataType);
     343           0 :         return false;
     344             :     }
     345             : 
     346         114 :     H5Aclose(hAttr);
     347         114 :     H5Sclose(hDataSpace);
     348         114 :     H5Tclose(hDataType);
     349             : 
     350         114 :     return true;
     351             : }
     352             : 
     353             : /************************************************************************/
     354             : /*                        GH5_WriteAttribute()                          */
     355             : /************************************************************************/
     356             : 
     357          20 : bool GH5_WriteAttribute(hid_t loc_id, const char *pszAttrName,
     358             :                         const char *pszValue)
     359             : {
     360             : 
     361          20 :     hid_t hAttr = H5Aopen_name(loc_id, pszAttrName);
     362          20 :     if (hAttr < 0)
     363           0 :         return false;
     364             : 
     365          20 :     hid_t hDataType = H5Aget_type(hAttr);
     366          20 :     if (hDataType < 0)
     367             :     {
     368           0 :         H5Aclose(hAttr);
     369           0 :         return false;
     370             :     }
     371             : 
     372          20 :     hid_t hAttrNativeType = H5Tget_native_type(hDataType, H5T_DIR_DEFAULT);
     373          20 :     bool bSuccess = false;
     374          20 :     if (H5Tget_class(hAttrNativeType) == H5T_STRING)
     375             :     {
     376             : #ifdef notdef_write_variable_length_string
     377             :         bSuccess = H5Awrite(hAttr, hDataType, &pszValue) >= 0;
     378             : #else
     379          20 :         bSuccess = H5Awrite(hAttr, hDataType, pszValue) >= 0;
     380             : #endif
     381             :     }
     382             :     else
     383             :     {
     384           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     385             :                  "Attribute %s is not of type string", pszAttrName);
     386             :     }
     387             : 
     388          20 :     H5Tclose(hAttrNativeType);
     389          20 :     H5Tclose(hDataType);
     390          20 :     H5Aclose(hAttr);
     391             : 
     392          20 :     return bSuccess;
     393             : }
     394             : 
     395             : /************************************************************************/
     396             : /*                        GH5_WriteAttribute()                          */
     397             : /************************************************************************/
     398             : 
     399          74 : bool GH5_WriteAttribute(hid_t loc_id, const char *pszAttrName, double dfValue)
     400             : {
     401             : 
     402          74 :     hid_t hAttr = H5Aopen_name(loc_id, pszAttrName);
     403          74 :     if (hAttr < 0)
     404           0 :         return false;
     405             : 
     406          74 :     hid_t hDataType = H5Aget_type(hAttr);
     407          74 :     if (hDataType < 0)
     408             :     {
     409           0 :         H5Aclose(hAttr);
     410           0 :         return false;
     411             :     }
     412             : 
     413          74 :     hid_t hAttrNativeType = H5Tget_native_type(hDataType, H5T_DIR_DEFAULT);
     414          74 :     bool bSuccess = false;
     415          74 :     if (H5Tequal(hAttrNativeType, H5T_NATIVE_FLOAT))
     416             :     {
     417          74 :         float fVal = static_cast<float>(dfValue);
     418          74 :         bSuccess = H5Awrite(hAttr, hAttrNativeType, &fVal) >= 0;
     419             :     }
     420           0 :     else if (H5Tequal(hAttrNativeType, H5T_NATIVE_DOUBLE))
     421             :     {
     422           0 :         bSuccess = H5Awrite(hAttr, hAttrNativeType, &dfValue) >= 0;
     423             :     }
     424             :     else
     425             :     {
     426           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     427             :                  "Attribute %s is not of type float or double", pszAttrName);
     428             :     }
     429             : 
     430          74 :     H5Tclose(hAttrNativeType);
     431          74 :     H5Aclose(hAttr);
     432          74 :     H5Tclose(hDataType);
     433             : 
     434          74 :     return bSuccess;
     435             : }
     436             : 
     437             : /************************************************************************/
     438             : /*                        GH5_WriteAttribute()                          */
     439             : /************************************************************************/
     440             : 
     441          20 : bool GH5_WriteAttribute(hid_t loc_id, const char *pszAttrName, unsigned nValue)
     442             : {
     443             : 
     444          20 :     hid_t hAttr = H5Aopen_name(loc_id, pszAttrName);
     445          20 :     if (hAttr < 0)
     446           0 :         return false;
     447             : 
     448          20 :     hid_t hDataType = H5Aget_type(hAttr);
     449          20 :     if (hDataType < 0)
     450             :     {
     451           0 :         H5Aclose(hAttr);
     452           0 :         return false;
     453             :     }
     454             : 
     455          20 :     hid_t hAttrNativeType = H5Tget_native_type(hDataType, H5T_DIR_DEFAULT);
     456          20 :     bool bSuccess = false;
     457          40 :     if (H5Tequal(hAttrNativeType, H5T_NATIVE_INT) ||
     458          20 :         H5Tequal(hAttrNativeType, H5T_NATIVE_UINT))
     459             :     {
     460          20 :         bSuccess = H5Awrite(hAttr, hAttrNativeType, &nValue) >= 0;
     461             :     }
     462             :     else
     463             :     {
     464           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     465             :                  "Attribute %s is not of type int/uint", pszAttrName);
     466             :     }
     467             : 
     468          20 :     H5Tclose(hAttrNativeType);
     469          20 :     H5Aclose(hAttr);
     470          20 :     H5Tclose(hDataType);
     471             : 
     472          20 :     return bSuccess;
     473             : }

Generated by: LCOV version 1.14