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 : }
|