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

Generated by: LCOV version 1.14