LCOV - code coverage report
Current view: directory - frmts/hdf5 - hdf5dataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 412 300 72.8 %
Date: 2010-01-09 Functions: 18 18 100.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: hdf5dataset.cpp 18346 2009-12-19 11:05:26Z rouault $
       3                 :  *
       4                 :  * Project:  Hierarchical Data Format Release 5 (HDF5)
       5                 :  * Purpose:  HDF5 Datasets. Open HDF5 file, fetch metadata and list of
       6                 :  *           subdatasets.
       7                 :  *           This driver initially based on code supplied by Markus Neteler
       8                 :  * Author:  Denis Nadeau <denis.nadeau@gmail.com>
       9                 :  *
      10                 :  ******************************************************************************
      11                 :  * Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
      12                 :  *
      13                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      14                 :  * copy of this software and associated documentation files (the "Software"),
      15                 :  * to deal in the Software without restriction, including without limitation
      16                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      17                 :  * and/or sell copies of the Software, and to permit persons to whom the
      18                 :  * Software is furnished to do so, subject to the following conditions:
      19                 :  *
      20                 :  * The above copyright notice and this permission notice shall be included
      21                 :  * in all copies or substantial portions of the Software.
      22                 :  *
      23                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      24                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      25                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      26                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      27                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      28                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      29                 :  * DEALINGS IN THE SOFTWARE.
      30                 :  ****************************************************************************/
      31                 : 
      32                 : #define H5_USE_16_API
      33                 : 
      34                 : #include "hdf5.h"
      35                 : 
      36                 : #include "gdal_priv.h"
      37                 : #include "cpl_string.h"
      38                 : #include "hdf5dataset.h"
      39                 : 
      40                 : CPL_CVSID("$Id: hdf5dataset.cpp 18346 2009-12-19 11:05:26Z rouault $");
      41                 : 
      42                 : CPL_C_START
      43                 : void  GDALRegister_HDF5(void);
      44                 : CPL_C_END
      45                 : 
      46                 : 
      47                 : 
      48                 : /************************************************************************/
      49                 : /* ==================================================================== */
      50                 : /*        HDF5Dataset       */
      51                 : /* ==================================================================== */
      52                 : /************************************************************************/
      53                 : 
      54                 : /************************************************************************/
      55                 : /*                        GDALRegister_HDF5()       */
      56                 : /************************************************************************/
      57             338 : void GDALRegister_HDF5()
      58                 :     
      59                 : {
      60                 :     GDALDriver  *poDriver;
      61             338 :     if( GDALGetDriverByName("HDF5") == NULL )
      62                 :   {
      63             336 :       poDriver = new GDALDriver();
      64             336 :       poDriver->SetDescription("HDF5");
      65                 :       poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, 
      66             336 :               "Hierarchical Data Format Release 5");
      67                 :       poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, 
      68             336 :               "frmt_hdf5.html");
      69             336 :       poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "hdf5");
      70             336 :       poDriver->pfnOpen = HDF5Dataset::Open;
      71             336 :       poDriver->pfnIdentify = HDF5Dataset::Identify;
      72             336 :       GetGDALDriverManager()->RegisterDriver(poDriver);
      73                 :   }
      74             338 : }
      75                 : 
      76                 : /************************************************************************/
      77                 : /*                           HDF5Dataset()                        */
      78                 : /************************************************************************/
      79              10 : HDF5Dataset::HDF5Dataset()
      80                 : {
      81              10 :     papszSubDatasets    = NULL;
      82              10 :     papszMetadata       = NULL;
      83              10 :     poH5RootGroup       = NULL;
      84              10 :     nSubDataCount       = 0;
      85              10 :     hHDF5               = -1;
      86              10 :     hDatasetID          = -1;
      87              10 :     hGroupID            = -1;
      88              10 :     bIsHDFEOS           = FALSE;
      89              10 :     nDatasetType        = -1;
      90              10 : }
      91                 : 
      92                 : /************************************************************************/
      93                 : /*                            ~HDF5Dataset()                            */
      94                 : /************************************************************************/
      95              11 : HDF5Dataset::~HDF5Dataset()
      96                 : {
      97              10 :     CSLDestroy( papszMetadata );
      98              10 :     if( hHDF5 > 0 )
      99              10 :   H5Fclose( hHDF5 );
     100              10 :     if( hGroupID > 0 )
     101              10 :   H5Gclose( hGroupID );
     102              10 :     CSLDestroy( papszSubDatasets );
     103              10 :     if( poH5RootGroup != NULL ){
     104              10 :   DestroyH5Objects( poH5RootGroup );
     105              10 :   CPLFree( poH5RootGroup->pszName );
     106              10 :   CPLFree( poH5RootGroup->pszPath );
     107              10 :   CPLFree( poH5RootGroup->pszUnderscorePath );
     108              10 :   CPLFree( poH5RootGroup->poHchild );
     109              10 :   delete poH5RootGroup;
     110                 :     }
     111              11 : }
     112                 : 
     113                 : /************************************************************************/
     114                 : /*                            GetDataType()                             */
     115                 : /*                                                                      */
     116                 : /*      Transform HDF5 datatype to GDAL datatype                        */
     117                 : /************************************************************************/
     118              11 : GDALDataType HDF5Dataset::GetDataType(hid_t TypeID) 
     119                 : {
     120              11 :     if( H5Tequal( H5T_NATIVE_CHAR,        TypeID ) )
     121               0 :   return GDT_Byte;
     122              11 :     else if( H5Tequal( H5T_NATIVE_UCHAR,  TypeID ) ) 
     123               4 :   return GDT_Byte;
     124               7 :     else if( H5Tequal( H5T_NATIVE_SHORT,  TypeID ) )
     125               1 :   return GDT_Int16;
     126               6 :     else if( H5Tequal( H5T_NATIVE_USHORT, TypeID ) ) 
     127               0 :   return GDT_UInt16;
     128               6 :     else if( H5Tequal( H5T_NATIVE_INT,    TypeID ) ) 
     129               6 :   return GDT_Int32;      
     130               0 :     else if( H5Tequal( H5T_NATIVE_UINT,   TypeID ) ) 
     131               0 :   return GDT_UInt32;
     132               0 :     else if( H5Tequal( H5T_NATIVE_LONG,   TypeID ) ) 
     133                 :     {
     134                 :         if( sizeof(long) == 4 )
     135               0 :             return GDT_Int32;      
     136                 :         else
     137                 :             return GDT_Unknown;
     138                 :     }
     139               0 :     else if( H5Tequal( H5T_NATIVE_ULONG,  TypeID ) ) 
     140                 :     {
     141                 :         if( sizeof(unsigned long) == 4 )
     142               0 :             return GDT_UInt32;      
     143                 :         else
     144                 :             return GDT_Unknown;
     145                 :     }
     146               0 :     else if( H5Tequal( H5T_NATIVE_FLOAT,  TypeID ) ) 
     147               0 :   return GDT_Float32;
     148               0 :     else if( H5Tequal( H5T_NATIVE_DOUBLE, TypeID ) ) 
     149               0 :   return GDT_Float64;
     150               0 :     else if( H5Tequal( H5T_NATIVE_LLONG,  TypeID ) ) 
     151               0 :   return GDT_Unknown;
     152               0 :     else if( H5Tequal( H5T_NATIVE_ULLONG, TypeID ) ) 
     153               0 :   return GDT_Unknown;
     154               0 :     else if( H5Tequal( H5T_NATIVE_DOUBLE, TypeID ) ) 
     155               0 :   return GDT_Unknown;
     156                 : 
     157               0 :     return GDT_Unknown;
     158                 : }
     159                 : 
     160                 : /************************************************************************/
     161                 : /*                          GetDataTypeName()                           */
     162                 : /*                                                                      */
     163                 : /*      Return the human readable name of data type                     */
     164                 : /************************************************************************/
     165               2 : const char *HDF5Dataset::GetDataTypeName(hid_t TypeID)
     166                 : {
     167               2 :     if( H5Tequal( H5T_NATIVE_CHAR,        TypeID ) )
     168               0 :   return "8-bit character";
     169               2 :     else if( H5Tequal( H5T_NATIVE_UCHAR,  TypeID ) ) 
     170               0 :   return "8-bit unsigned character";    
     171               2 :     else if( H5Tequal( H5T_NATIVE_SHORT,  TypeID ) )
     172               0 :   return "16-bit integer";
     173               2 :     else if( H5Tequal( H5T_NATIVE_USHORT, TypeID ) ) 
     174               0 :   return "16-bit unsigned integer";
     175               2 :     else if( H5Tequal( H5T_NATIVE_INT,    TypeID ) ) 
     176               2 :   return "32-bit integer";
     177               0 :     else if( H5Tequal( H5T_NATIVE_UINT,   TypeID ) ) 
     178               0 :   return "32-bit unsigned integer";
     179               0 :     else if( H5Tequal( H5T_NATIVE_LONG,   TypeID ) ) 
     180               0 :   return "32/64-bit integer";
     181               0 :     else if( H5Tequal( H5T_NATIVE_ULONG,  TypeID ) ) 
     182               0 :   return "32/64-bit unsigned integer";
     183               0 :     else if( H5Tequal( H5T_NATIVE_FLOAT,  TypeID ) ) 
     184               0 :   return "32-bit floating-point";
     185               0 :     else if( H5Tequal( H5T_NATIVE_DOUBLE, TypeID ) ) 
     186               0 :   return "64-bit floating-point";
     187               0 :     else if( H5Tequal( H5T_NATIVE_LLONG,  TypeID ) ) 
     188               0 :   return "64-bit integer";
     189               0 :     else if( H5Tequal( H5T_NATIVE_ULLONG, TypeID ) ) 
     190               0 :   return "64-bit unsigned integer";
     191               0 :     else if( H5Tequal( H5T_NATIVE_DOUBLE, TypeID ) ) 
     192               0 :         return "64-bit floating-point";
     193                 :     
     194               0 :     return "Unknown";
     195                 : }
     196                 : 
     197                 : /************************************************************************/
     198                 : /*                              Identify()                              */
     199                 : /************************************************************************/
     200                 : 
     201            8457 : int HDF5Dataset::Identify( GDALOpenInfo * poOpenInfo )
     202                 : 
     203                 : {
     204                 : /* -------------------------------------------------------------------- */
     205                 : /*      Is it an HDF5 file?                                             */
     206                 : /* -------------------------------------------------------------------- */
     207                 :     static const char achSignature[] = "\211HDF\r\n\032\n";
     208                 : 
     209            8457 :     if( poOpenInfo->pabyHeader == NULL
     210                 :         || memcmp(poOpenInfo->pabyHeader,achSignature,8) != 0 )
     211            8456 :         return FALSE;
     212                 : 
     213               1 :     return TRUE;
     214                 : }
     215                 : 
     216                 : /************************************************************************/
     217                 : /*                                Open()                                */
     218                 : /************************************************************************/
     219             730 : GDALDataset *HDF5Dataset::Open( GDALOpenInfo * poOpenInfo )
     220                 : {
     221                 :     HDF5Dataset *poDS;
     222                 :     CPLErr      Err;
     223                 :     
     224             730 :     if( !Identify( poOpenInfo ) )
     225             729 :         return NULL;
     226                 : 
     227                 : /* -------------------------------------------------------------------- */
     228                 : /*      Create datasource.                                              */
     229                 : /* -------------------------------------------------------------------- */
     230               1 :     poDS = new HDF5Dataset();
     231                 : 
     232               1 :     poDS->SetDescription( poOpenInfo->pszFilename );
     233                 : 
     234                 : /* -------------------------------------------------------------------- */
     235                 : /*      Try opening the dataset.                                        */
     236                 : /* -------------------------------------------------------------------- */
     237                 :     poDS->hHDF5 = H5Fopen( poOpenInfo->pszFilename, 
     238                 :          H5F_ACC_RDONLY, 
     239               1 :          H5P_DEFAULT );
     240               1 :     if( poDS->hHDF5 < 0 )  {
     241               0 :         delete poDS;
     242               0 :     return NULL;
     243                 :     }
     244                 :     
     245               1 :     poDS->hGroupID = H5Gopen( poDS->hHDF5, "/" ); 
     246               1 :     if( poDS->hGroupID < 0 ){
     247               0 :   poDS->bIsHDFEOS=false;
     248               0 :         delete poDS;
     249               0 :   return NULL;
     250                 :     }
     251                 :     
     252               1 :     poDS->bIsHDFEOS=true;
     253               1 :     Err = poDS->ReadGlobalAttributes( true );
     254                 : 
     255               1 :     poDS->SetMetadata( poDS->papszMetadata  );
     256                 :     
     257               1 :     if ( CSLCount( poDS->papszSubDatasets ) / 2 >= 1 )
     258               1 :         poDS->SetMetadata( poDS->papszSubDatasets, "SUBDATASETS" );
     259                 : 
     260                 :     // Make sure we don't try to do any pam stuff with this dataset.
     261               1 :     poDS->nPamFlags |= GPF_NOSAVE;
     262                 : 
     263                 : /* -------------------------------------------------------------------- */
     264                 : /*      If we have single subdataset only, open it immediately          */
     265                 : /* -------------------------------------------------------------------- */
     266               1 :     int nSubDatasets = CSLCount( poDS->papszSubDatasets ) / 2;
     267               1 :     if( nSubDatasets == 1 )
     268                 :     {
     269                 :         CPLString osDSName = CSLFetchNameValue( poDS->papszSubDatasets,
     270               0 :                                                 "SUBDATASET_1_NAME" );
     271               0 :         delete poDS;
     272               0 :         return (GDALDataset *) GDALOpen( osDSName, poOpenInfo->eAccess );
     273                 :     }
     274                 :     else
     275                 :     {
     276                 : /* -------------------------------------------------------------------- */
     277                 : /*      Confirm the requested access is supported.                      */
     278                 : /* -------------------------------------------------------------------- */
     279               1 :         if( poOpenInfo->eAccess == GA_Update )
     280                 :         {
     281               0 :             delete poDS;
     282                 :             CPLError( CE_Failure, CPLE_NotSupported, 
     283                 :                       "The HDF5 driver does not support update access to existing"
     284               0 :                       " datasets.\n" );
     285               0 :             return NULL;
     286                 :         }
     287                 :     }
     288               1 :     return( poDS );
     289                 : }
     290                 : 
     291                 : /************************************************************************/
     292                 : /*                          DestroyH5Objects()                          */
     293                 : /*                                                                      */
     294                 : /*      Erase all objects                                               */
     295                 : /************************************************************************/
     296              52 : void HDF5Dataset::DestroyH5Objects( HDF5GroupObjects *poH5Object )
     297                 : {
     298                 :     int i;
     299                 : 
     300                 : 
     301                 : /* -------------------------------------------------------------------- */
     302                 : /*      Visit all objects                                               */
     303                 : /* -------------------------------------------------------------------- */
     304                 : 
     305              94 :     for( i=0; i < poH5Object->nbObjs; i++ )
     306              42 :   if( poH5Object->poHchild+i != NULL )
     307              42 :       DestroyH5Objects( poH5Object->poHchild+i );
     308                 : 
     309              52 :     if( poH5Object->poHparent ==NULL )
     310              10 :   return;
     311                 : 
     312                 : /* -------------------------------------------------------------------- */
     313                 : /*      Erase some data                                                 */
     314                 : /* -------------------------------------------------------------------- */
     315              42 :     if( poH5Object->paDims != NULL ) {
     316              17 :   CPLFree( poH5Object->paDims );
     317                 :     }
     318                 : 
     319              42 :     if( poH5Object->pszPath != NULL ) {
     320              42 :       CPLFree( poH5Object->pszPath );
     321                 :     }
     322                 : 
     323              42 :     if( poH5Object->pszName != NULL ) {
     324              42 :   CPLFree( poH5Object->pszName );
     325                 :     }
     326                 : 
     327              42 :     if( poH5Object->pszUnderscorePath != NULL ) {
     328              42 :   CPLFree( poH5Object->pszUnderscorePath );
     329                 :     }
     330                 : /* -------------------------------------------------------------------- */
     331                 : /*      All Children are visited and can be deleted.                    */
     332                 : /* -------------------------------------------------------------------- */
     333              42 :     if( ( i==poH5Object->nbObjs ) && ( poH5Object->nbObjs!=0 ) ) {
     334              18 :   CPLFree( poH5Object->poHchild );
     335                 :     }
     336                 : 
     337                 : }
     338                 : 
     339                 : /************************************************************************/
     340                 : /*                             CreatePath()                             */
     341                 : /*                                                                      */
     342                 : /*      Find Dataset path for HDopen                                    */
     343                 : /************************************************************************/
     344             125 : char* CreatePath( HDF5GroupObjects *poH5Object )
     345                 : {
     346                 :     char pszPath[8192];
     347                 :     char pszUnderscoreSpaceInName[8192];
     348                 :     char *popszPath;
     349                 :     int  i;
     350                 :     char **papszPath;
     351                 : 
     352                 : /* -------------------------------------------------------------------- */
     353                 : /*      Recurse to the root path                                        */
     354                 : /* -------------------------------------------------------------------- */
     355             125 :     pszPath[0]='\0';
     356             125 :     if( poH5Object->poHparent !=NULL ) {
     357              83 :   popszPath=CreatePath( poH5Object->poHparent );
     358              83 :   strcpy( pszPath,popszPath );
     359                 :     }
     360                 :   
     361                 : /* -------------------------------------------------------------------- */
     362                 : /*      add name to the path                                            */
     363                 : /* -------------------------------------------------------------------- */
     364             125 :     if( !EQUAL( poH5Object->pszName,"/" ) ){
     365              83 :   strcat( pszPath,"/" );
     366              83 :   strcat( pszPath,poH5Object->pszName );
     367                 :     }
     368                 : 
     369                 : /* -------------------------------------------------------------------- */
     370                 : /*      fill up path for each object                                    */
     371                 : /* -------------------------------------------------------------------- */
     372             125 :     if( poH5Object->pszPath == NULL ) {
     373                 : 
     374              52 :   if( strlen( poH5Object->pszName ) == 1 ) {
     375              10 :       strcat(pszPath, poH5Object->pszName );
     376              10 :       strcpy(pszUnderscoreSpaceInName, poH5Object->pszName);
     377                 :   }
     378                 :   else {
     379                 : /* -------------------------------------------------------------------- */
     380                 : /*      Change space for underscore                                     */
     381                 : /* -------------------------------------------------------------------- */
     382                 :       papszPath = CSLTokenizeString2( pszPath,
     383              42 :               " ", CSLT_HONOURSTRINGS );
     384                 :       
     385              42 :       strcpy(pszUnderscoreSpaceInName,papszPath[0]);
     386              50 :       for( i=1; i < CSLCount( papszPath ); i++ ) {
     387               8 :     strcat( pszUnderscoreSpaceInName, "_" );
     388               8 :     strcat( pszUnderscoreSpaceInName, papszPath[ i ] );
     389                 :       }
     390              42 :       CSLDestroy(papszPath);
     391                 : 
     392                 :   }
     393                 :   poH5Object->pszUnderscorePath  = 
     394              52 :       CPLStrdup( pszUnderscoreSpaceInName );
     395              52 :   poH5Object->pszPath  = CPLStrdup( pszPath );
     396                 :     }
     397                 : 
     398             125 :     return( poH5Object->pszPath );
     399                 : }
     400                 : 
     401                 : /************************************************************************/
     402                 : /*                      HDF5GroupCheckDuplicate()                       */
     403                 : /*                                                                      */
     404                 : /*      Returns TRUE if an ancestor has the same objno[] as passed      */
     405                 : /*      in - used to avoid looping in files with "links up" #(3218).    */
     406                 : /************************************************************************/
     407                 : 
     408              24 : static int HDF5GroupCheckDuplicate( HDF5GroupObjects *poHparent,
     409                 :                                     unsigned long *objno )
     410                 : 
     411                 : {
     412              91 :     while( poHparent != NULL )
     413                 :     {
     414              43 :         if( poHparent->objno[0] == objno[0]
     415               0 :             && poHparent->objno[1] == objno[1] )
     416               0 :             return TRUE;
     417                 : 
     418              43 :         poHparent = poHparent->poHparent;
     419                 :     }
     420                 : 
     421              24 :     return FALSE;
     422                 : }
     423                 : 
     424                 : /************************************************************************/
     425                 : /*                      HDF5CreateGroupObjs()                           */
     426                 : /*                                                                      */
     427                 : /*      Create HDF5 hierarchy into a linked list                        */
     428                 : /************************************************************************/
     429              42 : herr_t HDF5CreateGroupObjs(hid_t hHDF5, const char *pszObjName, 
     430                 :          void *poHObjParent)
     431                 : {
     432                 :     herr_t  ret;      /* error return status */
     433                 :     hid_t hGroupID;   /* identifier of group */
     434                 :     hid_t hDatasetID;   /* identifier of dataset */
     435              42 :     hsize_t     nbObjs=0;   /* number of objects in a group */
     436              42 :     int         nbAttrs=0;    /* number of attributes in object */
     437                 :     int   idx;
     438                 :     int         n_dims;
     439                 :     H5G_stat_t  oStatbuf;
     440              42 :     hsize_t     *dims=NULL;
     441              42 :     hsize_t     *maxdims=NULL;
     442                 :     hid_t       datatype;
     443                 :     hid_t       dataspace;
     444                 :     hid_t       native;
     445                 :     herr_t status;
     446                 : 
     447                 :     char *CreatePath( HDF5GroupObjects *poH5Object );
     448                 : 
     449                 :     HDF5GroupObjects *poHchild;
     450                 :     HDF5GroupObjects *poHparent;
     451                 : 
     452              42 :     poHparent = ( HDF5GroupObjects * ) poHObjParent;
     453              42 :     poHchild=poHparent->poHchild;
     454                 : 
     455              42 :     if( H5Gget_objinfo( hHDF5, pszObjName, FALSE, &oStatbuf ) < 0  )
     456               0 :   return -1;
     457                 : 
     458                 :     
     459                 : /* -------------------------------------------------------------------- */
     460                 : /*      Look for next child                                             */
     461                 : /* -------------------------------------------------------------------- */
     462              61 :     for( idx=0; idx < poHparent->nbObjs; idx++ )  {
     463              61 :   if( poHchild->pszName == NULL ) break;
     464              19 :   poHchild++;
     465                 :     }
     466                 : 
     467              42 :     if( idx == poHparent->nbObjs ) 
     468               0 :   return -1;  // all children parsed
     469                 :     
     470                 : /* -------------------------------------------------------------------- */
     471                 : /*      Save child information                                          */
     472                 : /* -------------------------------------------------------------------- */
     473              42 :     poHchild->pszName  = CPLStrdup( pszObjName );
     474                 :     
     475              42 :     poHchild->nType  = oStatbuf.type;
     476              42 :     poHchild->nIndex = idx;
     477              42 :     poHchild->poHparent = poHparent;
     478              42 :     poHchild->nRank     = 0;
     479              42 :     poHchild->paDims    = 0;
     480              42 :     poHchild->HDatatype = 0;
     481              42 :     poHchild->objno[0]  = oStatbuf.objno[0];
     482              42 :     poHchild->objno[1]  = oStatbuf.objno[1];
     483              42 :     if( poHchild->pszPath == NULL ) {
     484              42 :   poHchild->pszPath  = CreatePath( poHchild );
     485                 :     }
     486              42 :     if( poHparent->pszPath == NULL ) {
     487               0 :   poHparent->pszPath = CreatePath( poHparent );
     488                 :     }
     489                 : 
     490                 : 
     491              42 :     switch ( oStatbuf.type ) 
     492                 :   {
     493                 :   case H5G_LINK:
     494               0 :       poHchild->nbAttrs = 0;
     495               0 :       poHchild->nbObjs = 0;
     496               0 :       poHchild->poHchild = NULL;
     497               0 :       poHchild->nRank      = 0;
     498               0 :       poHchild->paDims    = 0;
     499               0 :       poHchild->HDatatype = 0;
     500               0 :       break;
     501                 :       
     502                 :   case H5G_GROUP:
     503              24 :       if( ( hGroupID = H5Gopen( hHDF5, pszObjName ) ) == -1  ) {
     504                 :     printf( "Error: unable to access \"%s\" group.\n", 
     505               0 :       pszObjName );
     506               0 :     return -1;
     507                 :       }
     508              24 :       nbAttrs          = H5Aget_num_attrs( hGroupID );
     509              24 :       ret              = H5Gget_num_objs( hGroupID, &nbObjs );
     510              24 :       poHchild->nbAttrs= nbAttrs;
     511              24 :       poHchild->nbObjs = nbObjs;
     512              24 :       poHchild->nRank      = 0;
     513              24 :       poHchild->paDims    = 0;
     514              24 :       poHchild->HDatatype = 0;
     515                 :       
     516              24 :       if( nbObjs > 0 ) {
     517                 :     poHchild->poHchild =( HDF5GroupObjects * )
     518              18 :         CPLCalloc( nbObjs, sizeof( HDF5GroupObjects ) );
     519                 :     memset( poHchild->poHchild,0,
     520              18 :       sizeof( HDF5GroupObjects ) * nbObjs );
     521                 :       }
     522                 :       else 
     523               6 :     poHchild->poHchild = NULL;
     524                 : 
     525              24 :             if( !HDF5GroupCheckDuplicate( poHparent, oStatbuf.objno ) )
     526                 :                 H5Giterate( hHDF5, pszObjName, NULL, 
     527              24 :                             HDF5CreateGroupObjs,  (void*) poHchild );
     528                 :             else
     529                 :                 CPLDebug( "HDF5", "avoiding link looping on node '%s'.", 
     530               0 :                           pszObjName );
     531              24 :       H5Gclose( hGroupID );
     532              24 :       break;
     533                 :       
     534                 :   case H5G_DATASET:
     535                 :       
     536              18 :       if( ( hDatasetID = H5Dopen( hHDF5, pszObjName ) ) == -1  ) {
     537                 :     printf( "Error: unable to access \"%s\" dataset.\n", 
     538               0 :            pszObjName );
     539               0 :     return -1;
     540                 :       }
     541              18 :       nbAttrs      = H5Aget_num_attrs( hDatasetID );
     542              18 :       datatype     = H5Dget_type( hDatasetID );
     543              18 :       dataspace    = H5Dget_space( hDatasetID );
     544              18 :       n_dims       = H5Sget_simple_extent_ndims( dataspace );
     545              18 :       native       = H5Tget_native_type( datatype, H5T_DIR_ASCEND );
     546                 :       
     547              18 :       if( n_dims > 0 ) {
     548              17 :     dims     = (hsize_t *) CPLCalloc( n_dims,sizeof( hsize_t ) );
     549              17 :     maxdims  = (hsize_t *) CPLCalloc( n_dims,sizeof( hsize_t ) );
     550                 :       }
     551              18 :       status     = H5Sget_simple_extent_dims( dataspace, dims, maxdims );
     552              18 :       if( maxdims != NULL )
     553              17 :     CPLFree( maxdims );
     554                 :       
     555              18 :       if( n_dims > 0 ) {
     556              17 :     poHchild->nRank     = n_dims;   // rank of the array
     557              17 :     poHchild->paDims    = dims;      // dimmension of the array.
     558              17 :     poHchild->HDatatype = datatype;  // HDF5 datatype
     559                 :       }
     560                 :       else  {
     561               1 :     poHchild->nRank     = -1;
     562               1 :     poHchild->paDims    = NULL;
     563               1 :     poHchild->HDatatype = 0;
     564                 :   }
     565              18 :       poHchild->nbAttrs   = nbAttrs;
     566              18 :       poHchild->nbObjs    = 0;
     567              18 :       poHchild->poHchild  = NULL;
     568              18 :       poHchild->native    = native;
     569              18 :       ret                 = H5Dclose( hDatasetID );
     570              18 :       break;
     571                 :       
     572                 :   case H5G_TYPE:
     573               0 :       poHchild->nbAttrs = 0;
     574               0 :       poHchild->nbObjs = 0;
     575               0 :       poHchild->poHchild = NULL;
     576               0 :       poHchild->nRank      = 0;
     577               0 :       poHchild->paDims    = 0;
     578               0 :       poHchild->HDatatype = 0;
     579                 :       break;
     580                 :       
     581                 :   default:
     582                 :       break;
     583                 :   }
     584                 :     
     585              42 :     return 0;
     586                 : }
     587                 : 
     588                 : 
     589                 : /************************************************************************/
     590                 : /*                          HDF5AttrIterate()                           */
     591                 : /************************************************************************/
     592                 : 
     593              17 : herr_t HDF5AttrIterate( hid_t hH5ObjID, 
     594                 :       const char *AttrName, 
     595                 :       void *pDS )
     596                 : {
     597                 :     hid_t           hAttrID;
     598                 :     hid_t           hAttrTypeID;
     599                 :     hid_t           hAttrNativeType;
     600                 :     hid_t           hAttrSpace;
     601                 : 
     602                 :     char            szData[8192];
     603                 :     hsize_t        nSize[64];
     604                 :     unsigned int            nAttrElmts;
     605                 :     hsize_t        nAttrSize;
     606                 :     hsize_t        i;
     607              17 :     void           *buf = NULL;
     608                 :     unsigned int             nAttrDims;
     609                 : 
     610                 : 
     611                 :     HDF5Dataset    *poDS;
     612                 :     char            szTemp[8192];
     613                 :     char            szValue[8192];
     614                 : 
     615              17 :     poDS = (HDF5Dataset *) pDS;
     616                 :     sprintf( szTemp, "%s:%s", poDS->poH5CurrentObject->pszName, 
     617              17 :        AttrName );
     618                 : 
     619              17 :     hAttrID          = H5Aopen_name( hH5ObjID, AttrName );
     620              17 :     hAttrTypeID      = H5Aget_type( hAttrID );
     621              17 :     hAttrNativeType  = H5Tget_native_type( hAttrTypeID, H5T_DIR_DEFAULT );
     622              17 :     hAttrSpace       = H5Aget_space( hAttrID );
     623              17 :     nAttrDims        = H5Sget_simple_extent_dims( hAttrSpace, nSize, NULL );
     624                 : 
     625                 : 
     626              17 :     szValue[0] ='\0';
     627                 : 
     628              17 :     if( H5Tget_class( hAttrNativeType ) == H5T_STRING ) {
     629              13 :   nAttrSize = H5Tget_size( hAttrTypeID );
     630              13 :   H5Aread( hAttrID, hAttrNativeType, szData  );
     631              13 :   szData[nAttrSize]='\0';
     632              13 :   sprintf( szValue, "%s", szData );
     633                 : 
     634                 :     }
     635                 :     else {
     636               4 :   nAttrElmts = 1;
     637               6 :   for( i=0; i < nAttrDims; i++ ) {
     638               2 :       nAttrElmts *= nSize[i];
     639                 :   }
     640               4 :   if( nAttrElmts > 0 ){
     641                 :       buf = (void *) CPLMalloc( nAttrElmts*
     642               4 :               H5Tget_size( hAttrNativeType ));
     643               4 :       H5Aread( hAttrID, hAttrNativeType, buf );
     644                 :   }
     645               4 :   if( H5Tequal( H5T_NATIVE_CHAR, hAttrNativeType ) ){
     646               0 :       for( i=0; i < nAttrElmts; i++ ) {
     647               0 :     sprintf( szData, "%c ", ((char *) buf)[i]);
     648               0 :     strcat(szValue,szData);
     649                 :       }
     650                 :   }
     651               4 :   else if( H5Tequal( H5T_NATIVE_UCHAR,  hAttrNativeType ) ) {
     652               0 :       for( i=0; i < nAttrElmts; i++ ) {
     653               0 :     sprintf( szData, "%c", ((char *) buf)[i] );
     654               0 :     strcat(szValue,szData);
     655                 :       }
     656                 :   }
     657               4 :   else if( H5Tequal( H5T_NATIVE_SHORT,  hAttrNativeType ) ) {
     658               2 :       for( i=0; i < nAttrElmts; i++ ) {
     659               1 :     sprintf( szData, "%d ", ((short *) buf)[i] );
     660               1 :     strcat(szValue,szData);
     661                 :       }
     662                 :   }
     663               3 :   else if( H5Tequal( H5T_NATIVE_USHORT, hAttrNativeType ) ) {
     664               4 :       for( i=0; i < nAttrElmts; i++ ) {
     665               2 :     sprintf( szData, "%ud ", ((unsigned short *) buf)[i] );
     666               2 :     strcat(szValue,szData);
     667                 :       }
     668                 :   }
     669               1 :   else if( H5Tequal( H5T_NATIVE_INT,    hAttrNativeType ) ) {
     670               0 :       for( i=0; i < nAttrElmts; i++ ) {
     671               0 :     sprintf( szData, "%d ", ((int *) buf)[i] );
     672               0 :     strcat(szValue,szData);
     673                 :       }
     674                 :   }
     675               1 :   else if( H5Tequal( H5T_NATIVE_UINT,   hAttrNativeType ) ) {
     676               0 :       for( i=0; i < nAttrElmts; i++ ) {
     677               0 :     sprintf( szData, "%ud ", ((unsigned int *) buf)[i] );
     678               0 :     strcat(szValue,szData);
     679                 :       }
     680                 :   }
     681               1 :   else if( H5Tequal( H5T_NATIVE_LONG,   hAttrNativeType ) ) {
     682               0 :       for( i=0; i < nAttrElmts; i++ ) {
     683               0 :     sprintf( szData, "%ld ", ((long *)buf)[i] );
     684               0 :     strcat(szValue,szData);
     685                 :       }
     686                 :   }
     687               1 :   else if( H5Tequal( H5T_NATIVE_ULONG,  hAttrNativeType ) ) {
     688               0 :       for( i=0; i < nAttrElmts; i++ ) {
     689               0 :     sprintf( szData, "%ld ", ((unsigned long *)buf)[i] );
     690               0 :     strcat(szValue,szData);
     691                 :       }
     692                 :   }
     693               1 :   else if( H5Tequal( H5T_NATIVE_FLOAT,  hAttrNativeType ) ) {
     694               0 :       for( i=0; i < nAttrElmts; i++ ) {
     695               0 :     sprintf( szData, "%f ",  ((float *)buf)[i] );
     696               0 :     strcat(szValue,szData);
     697                 :       }
     698                 :   }
     699               1 :   else if( H5Tequal( H5T_NATIVE_DOUBLE, hAttrNativeType ) ) {
     700               0 :       for( i=0; i < nAttrElmts; i++ ) {
     701               0 :     sprintf( szData, "%g ",  ((double *)buf)[i] );
     702               0 :     strcat(szValue,szData);
     703                 :       }
     704                 :   }
     705               4 :   CPLFree( buf );
     706                 : 
     707                 :     }
     708              17 :     H5Aclose( hAttrID );
     709                 :     //printf( "%s = %s\n",szTemp, szValue );
     710                 :     poDS->papszMetadata =
     711                 :   CSLSetNameValue( poDS->papszMetadata, szTemp,  
     712              17 :        CPLSPrintf( "%s", szValue ) );
     713                 : 
     714              17 :     return 0;
     715                 : }
     716                 : 
     717                 : /************************************************************************/
     718                 : /*                           CreateMetadata()                           */
     719                 : /************************************************************************/
     720              43 : CPLErr HDF5Dataset::CreateMetadata( HDF5GroupObjects *poH5Object, int nType)
     721                 : {
     722                 :     hid_t hGroupID;   /* identifier of group */
     723                 :     hid_t       hDatasetID;
     724                 :     int         nbAttrs;
     725                 :     herr_t      ret;
     726                 : 
     727                 :     HDF5Dataset *poDS;
     728                 : 
     729              43 :     poDS = this;
     730                 : 
     731              43 :     poH5CurrentObject = poH5Object;
     732              43 :     nbAttrs = poH5Object->nbAttrs;
     733                 : 
     734              43 :     if( EQUAL(poH5Object->pszPath, "" ) )
     735               0 :   return CE_None;
     736                 : 
     737              43 :     switch( nType ) {
     738                 : 
     739                 :     case H5G_GROUP:
     740                 : 
     741              34 :   hGroupID = H5Gopen( hHDF5, poH5Object->pszPath );
     742              34 :   if( nbAttrs > 0 ) { 
     743                 :       ret = H5Aiterate( hGroupID, NULL, 
     744               1 :             HDF5AttrIterate, (void *)poDS  );
     745               1 :       ret = H5Gclose( hGroupID );
     746                 :   }
     747                 : 
     748              34 :   break;
     749                 : 
     750                 :     case H5G_DATASET:
     751                 : 
     752               9 :   hDatasetID =  H5Dopen(hHDF5, poH5Object->pszPath );
     753                 : 
     754               9 :   if( nbAttrs > 0 ) { 
     755                 :       ret = H5Aiterate( hDatasetID, NULL, 
     756               3 :             HDF5AttrIterate, (void *)poDS );
     757               3 :       ret = H5Dclose( hDatasetID );
     758                 :   }
     759                 :   break;
     760                 : 
     761                 :     default:
     762                 :   break;
     763                 :     }
     764                 : 
     765              43 :     return CE_None;
     766                 : }
     767                 : 
     768                 : 
     769                 : /************************************************************************/
     770                 : /*                       HDF5FindDatasetObjectsbyPath()                 */
     771                 : /*      Find object by name                                             */
     772                 : /************************************************************************/
     773              43 : HDF5GroupObjects* HDF5Dataset::HDF5FindDatasetObjectsbyPath
     774                 :     ( HDF5GroupObjects *poH5Objects, char* pszDatasetPath )
     775                 : {
     776                 :     int i;
     777                 :     HDF5Dataset *poDS;
     778                 :     HDF5GroupObjects *poObjectsFound;
     779              43 :     poDS=this;
     780                 :     
     781              43 :     if( poH5Objects->nType == H5G_DATASET &&
     782                 :        EQUAL( poH5Objects->pszUnderscorePath,pszDatasetPath ) )  {
     783                 :       /*      printf("found it! %ld\n",(long) poH5Objects);*/
     784               9 :       return( poH5Objects );
     785                 :   }
     786                 :     
     787              34 :     if( poH5Objects->nbObjs >0 )
     788              40 :   for( i=0; i <poH5Objects->nbObjs; i++ )   {
     789                 :       poObjectsFound=
     790                 :     poDS->HDF5FindDatasetObjectsbyPath( poH5Objects->poHchild+i, 
     791              34 :                 pszDatasetPath );
     792                 : /* -------------------------------------------------------------------- */
     793                 : /*      Is this our dataset??                                           */
     794                 : /* -------------------------------------------------------------------- */
     795              34 :       if( poObjectsFound != NULL ) return( poObjectsFound );
     796                 :   }
     797                 : /* -------------------------------------------------------------------- */
     798                 : /*      Dataset has not been found!                                     */
     799                 : /* -------------------------------------------------------------------- */
     800              16 :     return( NULL );
     801                 :     
     802                 : }
     803                 : 
     804                 : 
     805                 : /************************************************************************/
     806                 : /*                       HDF5FindDatasetObjects()                       */
     807                 : /*      Find object by name                                             */
     808                 : /************************************************************************/
     809              46 : HDF5GroupObjects* HDF5Dataset::HDF5FindDatasetObjects
     810                 :     ( HDF5GroupObjects *poH5Objects, char* pszDatasetName )
     811                 : {
     812                 :     int i;
     813                 :     HDF5Dataset *poDS;
     814                 :     HDF5GroupObjects *poObjectsFound;
     815              46 :     poDS=this;
     816                 :     
     817              46 :     if( poH5Objects->nType == H5G_DATASET &&
     818                 :        EQUAL( poH5Objects->pszName,pszDatasetName ) )  {
     819                 :       /*      printf("found it! %ld\n",(long) poH5Objects);*/
     820               0 :       return( poH5Objects );
     821                 :   }
     822                 :     
     823              46 :     if( poH5Objects->nbObjs >0 )
     824              62 :   for( i=0; i <poH5Objects->nbObjs; i++ )   {
     825                 :       poObjectsFound=
     826                 :     poDS->HDF5FindDatasetObjects( poH5Objects->poHchild+i, 
     827              37 :                 pszDatasetName );
     828                 : /* -------------------------------------------------------------------- */
     829                 : /*      Is this our dataset??                                           */
     830                 : /* -------------------------------------------------------------------- */
     831              37 :       if( poObjectsFound != NULL ) return( poObjectsFound );
     832                 :       
     833                 :   }
     834                 : /* -------------------------------------------------------------------- */
     835                 : /*      Dataset has not been found!                                     */
     836                 : /* -------------------------------------------------------------------- */
     837              46 :     return( NULL );
     838                 :     
     839                 : }
     840                 : 
     841                 : 
     842                 : /************************************************************************/
     843                 : /*                        HDF5ListGroupObjects()                        */
     844                 : /*                                                                      */
     845                 : /*      List all objects in HDF5                                        */
     846                 : /************************************************************************/
     847              52 : CPLErr HDF5Dataset::HDF5ListGroupObjects( HDF5GroupObjects *poRootGroup,
     848                 :             int bSUBDATASET )
     849                 : {
     850                 :     int i;
     851                 :     char szTemp[8192];
     852                 :     char szDim[8192];
     853                 :     HDF5Dataset *poDS;
     854              52 :     poDS=this;
     855                 :     
     856              52 :     if( poRootGroup->nbObjs >0 )  
     857              70 :   for( i=0; i < poRootGroup->nbObjs; i++ ) {
     858              42 :       poDS->HDF5ListGroupObjects( poRootGroup->poHchild+i, bSUBDATASET );
     859                 :   }
     860                 :     
     861                 : 
     862              52 :     if( poRootGroup->nType == H5G_GROUP ) {
     863              34 :   CreateMetadata( poRootGroup, H5G_GROUP );
     864                 :     }
     865                 : 
     866                 : /* -------------------------------------------------------------------- */
     867                 : /*      Create Sub dataset list                                         */
     868                 : /* -------------------------------------------------------------------- */
     869              52 :     if( (poRootGroup->nType == H5G_DATASET ) && bSUBDATASET 
     870                 :         && poDS->GetDataType( poRootGroup->native ) == GDT_Unknown )
     871                 :     {
     872                 :         CPLDebug( "HDF5", "Skipping unsupported %s of type %s", 
     873                 :                   poRootGroup->pszUnderscorePath, 
     874               0 :                   poDS->GetDataTypeName( poRootGroup->native ) );
     875                 :     }
     876              52 :     else if( (poRootGroup->nType == H5G_DATASET ) && bSUBDATASET ) 
     877                 :     {
     878               2 :   szDim[0]='\0';
     879               2 :   switch( poRootGroup->nRank ) {
     880                 :   case 3: 
     881                 :       sprintf( szTemp,"%dx%dx%d",
     882               0 :         (int)poRootGroup->paDims[0],
     883               0 :         (int)poRootGroup->paDims[1],
     884               0 :         (int)poRootGroup->paDims[2] );
     885               0 :       break;
     886                 :       
     887                 :     case 2: 
     888                 :       sprintf( szTemp,"%dx%d",
     889               2 :         (int)poRootGroup->paDims[0],
     890               4 :         (int)poRootGroup->paDims[1] );
     891               2 :     break;
     892                 :         default:
     893               0 :       return CE_None;
     894                 :       
     895                 :   }
     896               2 :   strcat( szDim,szTemp );
     897                 :   
     898               2 :   sprintf( szTemp, "SUBDATASET_%d_NAME", ++(poDS->nSubDataCount) );
     899                 : 
     900                 :   poDS->papszSubDatasets =
     901                 :       CSLSetNameValue( poDS->papszSubDatasets, szTemp,
     902                 :           CPLSPrintf( "HDF5:\"%s\":%s",
     903               2 :           poDS->GetDescription(),
     904               4 :           poRootGroup->pszUnderscorePath ) );
     905                 :   
     906               2 :   sprintf(  szTemp, "SUBDATASET_%d_DESC", poDS->nSubDataCount );
     907                 :   
     908                 :   poDS->papszSubDatasets =
     909                 :       CSLSetNameValue( poDS->papszSubDatasets, szTemp,
     910                 :           CPLSPrintf( "[%s] %s (%s)", 
     911                 :           szDim,
     912                 :           poRootGroup->pszUnderscorePath,
     913                 :           poDS->GetDataTypeName
     914               2 :           ( poRootGroup->native ) ) );
     915                 : 
     916                 :     }
     917                 :     
     918              52 :     return CE_None;
     919                 : }
     920                 : 
     921                 : 
     922                 : /************************************************************************/
     923                 : /*                       ReadGlobalAttributes()                         */
     924                 : /************************************************************************/
     925              10 : CPLErr HDF5Dataset::ReadGlobalAttributes(int bSUBDATASET)
     926                 : {
     927                 :     
     928                 :     HDF5GroupObjects *poRootGroup;
     929                 :     
     930              10 :     poRootGroup = new HDF5GroupObjects;
     931                 :     
     932              10 :     poH5RootGroup=poRootGroup;
     933              10 :     poRootGroup->pszName   = CPLStrdup( "/" );
     934              10 :     poRootGroup->nType     = H5G_GROUP;
     935              10 :     poRootGroup->poHparent = NULL;
     936              10 :     poRootGroup->pszPath = NULL;
     937                 : 
     938              10 :     if( hHDF5 < 0 )  {
     939               0 :   printf( "hHDF5 <0!!\n" );
     940               0 :   return CE_None;
     941                 :     }
     942                 :     
     943                 :     H5G_stat_t  oStatbuf;
     944              10 :     if( H5Gget_objinfo( hHDF5, "/", FALSE, &oStatbuf ) < 0  )
     945               0 :   return CE_Failure;
     946              10 :     poRootGroup->objno[0] = oStatbuf.objno[0];
     947              10 :     poRootGroup->objno[1] = oStatbuf.objno[1];
     948                 :     
     949              10 :     hGroupID = H5Gopen( hHDF5, "/" ); 
     950              10 :     if( hGroupID < 0 ){
     951               0 :   printf( "hGroupID <0!!\n" );
     952               0 :   return CE_None;
     953                 :     }
     954                 :     
     955              10 :     poRootGroup->nbAttrs = H5Aget_num_attrs( hGroupID );
     956                 : 
     957              10 :     H5Gget_num_objs( hGroupID, (hsize_t *) &( poRootGroup->nbObjs ) );
     958                 :     
     959              10 :     if( poRootGroup->nbObjs > 0 ) {
     960                 :   poRootGroup->poHchild = ( HDF5GroupObjects * ) 
     961                 :       CPLCalloc( poRootGroup->nbObjs,
     962              10 :     sizeof( HDF5GroupObjects ) );
     963                 :   H5Giterate( hGroupID, "/", NULL, 
     964              10 :        HDF5CreateGroupObjs, (void *)poRootGroup );
     965                 :     }
     966               0 :     else poRootGroup->poHchild = NULL;
     967                 :     
     968              10 :     HDF5ListGroupObjects( poRootGroup, bSUBDATASET );
     969              10 :     return CE_None;
     970                 : }

Generated by: LCOV version 1.7