LCOV - code coverage report
Current view: directory - frmts/hdf5 - hdf5dataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 466 357 76.6 %
Date: 2012-04-28 Functions: 20 19 95.0 %

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

Generated by: LCOV version 1.7