LCOV - code coverage report
Current view: directory - frmts/hdf5 - hdf5dataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 514 400 77.8 %
Date: 2013-03-30 Functions: 21 20 95.2 %

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

Generated by: LCOV version 1.7