1 /****************************************************************************
2 * NCSA HDF *
3 * Scientific Data Technologies *
4 * National Center for Supercomputing Applications *
5 * University of Illinois at Urbana-Champaign *
6 * 605 E. Springfield, Champaign IL 61820 *
7 * *
8 * For conditions of distribution and use, see the accompanying *
9 * hdf/COPYING file. *
10 * *
11 * Modified versions of H5LT for getting and setting attributes for open
12 * groups and leaves.
13 * F. Alted 2005/09/29
14 * *
15 ****************************************************************************/
16
17 #include <string.h>
18 #include <stdlib.h>
19
20 #include "H5ATTR.h"
21
22
23 /*-------------------------------------------------------------------------
24 *
25 * Set & get attribute functions
26 *
27 *-------------------------------------------------------------------------
28 */
29
30 /*-------------------------------------------------------------------------
31 * Function: H5ATTRset_attribute
32 *
33 * Purpose: Create an attribute named attr_name and attach it to the
34 * object specified by the name obj_name. This supports general
35 * n-dimensional types (rank > 0), but if rank == 0, an H5T_SCALAR is
36 * chosen.
37 *
38 * Return: Success: 0, Failure: -1
39 *
40 * Programmer: Francesc Alted
41 *
42 * Date: October 18, 2006
43 *
44 * Comments:
45 *
46 * Modifications:
47 *
48 *-------------------------------------------------------------------------
49 */
50
H5ATTRset_attribute(hid_t obj_id,const char * attr_name,hid_t type_id,size_t rank,hsize_t * dims,const char * attr_data)51 herr_t H5ATTRset_attribute( hid_t obj_id,
52 const char *attr_name,
53 hid_t type_id,
54 size_t rank,
55 hsize_t *dims,
56 const char *attr_data )
57 {
58 hid_t space_id;
59 hid_t attr_id;
60 int has_attr;
61
62 /* Create the data space for the attribute. */
63 if (rank == 0)
64 space_id = H5Screate( H5S_SCALAR );
65 else
66 space_id = H5Screate_simple( rank, dims, NULL );
67
68 /* Verify whether the attribute already exists */
69 has_attr = H5ATTRfind_attribute( obj_id, attr_name );
70
71 /* The attribute already exists, delete it */
72 if ( has_attr == 1 )
73 {
74 if ( H5Adelete( obj_id, attr_name ) < 0 )
75 goto out;
76 }
77
78 /* Create and write the attribute */
79 attr_id = H5Acreate( obj_id, attr_name, type_id, space_id, H5P_DEFAULT,
80 H5P_DEFAULT );
81
82 if ( H5Awrite( attr_id, type_id, attr_data ) < 0 )
83 goto out;
84
85 H5Aclose( attr_id );
86
87 H5Sclose( space_id );
88
89 return 0;
90
91 out:
92 return -1;
93 }
94
95
96 /*-------------------------------------------------------------------------
97 * Function: H5ATTRset_attribute_string
98 *
99 * Purpose: Creates and writes a string attribute named attr_name and attaches
100 * it to the object specified by the name obj_name.
101 *
102 * Return: Success: 0, Failure: -1
103 *
104 * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
105 *
106 * Date: July 23, 2001
107 *
108 * Comments: If the attribute already exists, it is overwritten
109 *
110 * Modifications:
111 *
112 *-------------------------------------------------------------------------
113 */
114
H5ATTRset_attribute_string(hid_t obj_id,const char * attr_name,const char * attr_data,hsize_t attr_size,int cset)115 herr_t H5ATTRset_attribute_string( hid_t obj_id,
116 const char *attr_name,
117 const char *attr_data,
118 hsize_t attr_size,
119 int cset )
120 {
121 hid_t attr_type;
122 /*size_t attr_size;*/
123 hid_t attr_space_id;
124 hid_t attr_id;
125 int has_attr;
126
127 /* Create the attribute */
128 if ( (attr_type = H5Tcopy( H5T_C_S1 )) < 0 )
129 goto out;
130
131 if ( ( ( cset == H5T_CSET_ASCII ) || ( cset == H5T_CSET_UTF8 ) ) &&
132 ( H5Tset_cset( attr_type, cset ) < 0 ) )
133 goto out;
134
135 if ( H5Tset_strpad( attr_type, H5T_STR_NULLTERM ) < 0 )
136 goto out;
137
138 if ( attr_size > 0 )
139 {
140 if (H5Tset_size( attr_type, attr_size) < 0 )
141 goto out;
142 if ( (attr_space_id = H5Screate( H5S_SCALAR )) < 0 )
143 goto out;
144 }
145 else
146 {
147 if ( (attr_space_id = H5Screate( H5S_NULL )) < 0 )
148 goto out;
149 }
150
151 /* Verify if the attribute already exists */
152 has_attr = H5ATTRfind_attribute( obj_id, attr_name );
153
154 /* The attribute already exists, delete it */
155 if ( has_attr == 1 )
156 {
157 if ( H5Adelete( obj_id, attr_name ) < 0 )
158 goto out;
159 }
160
161 /* Create and write the attribute */
162
163 if ( (attr_id = H5Acreate( obj_id, attr_name, attr_type, attr_space_id,
164 H5P_DEFAULT, H5P_DEFAULT )) < 0 )
165 goto out;
166
167 if ( H5Awrite( attr_id, attr_type, attr_data ) < 0 )
168 goto out;
169
170 if ( H5Aclose( attr_id ) < 0 )
171 goto out;
172
173 if ( H5Sclose( attr_space_id ) < 0 )
174 goto out;
175
176 if ( H5Tclose(attr_type) < 0 )
177 goto out;
178
179 return 0;
180
181 out:
182 return -1;
183 }
184
185
186 /*-------------------------------------------------------------------------
187 * Function: H5ATTRget_attribute
188 *
189 * Purpose: Reads an attribute named attr_name with the memory type type_id
190 *
191 * Return: Success: 0, Failure: -1
192 *
193 * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
194 *
195 * Date: September 19, 2002
196 *
197 * Comments:
198 *
199 * Modifications:
200 *
201 *-------------------------------------------------------------------------
202 */
203
H5ATTRget_attribute(hid_t obj_id,const char * attr_name,hid_t type_id,void * data)204 herr_t H5ATTRget_attribute( hid_t obj_id,
205 const char *attr_name,
206 hid_t type_id,
207 void *data )
208 {
209
210 /* identifiers */
211 hid_t attr_id;
212
213 if ( ( attr_id = H5Aopen_by_name(obj_id, ".", attr_name,
214 H5P_DEFAULT, H5P_DEFAULT) ) < 0 )
215 return -1;
216
217 if ( H5Aread( attr_id, type_id, data ) < 0 )
218 goto out;
219
220 if ( H5Aclose( attr_id ) < 0 )
221 return -1;
222
223 return 0;
224
225 out:
226 H5Aclose( attr_id );
227 return -1;
228 }
229
230
231 /*-------------------------------------------------------------------------
232 * Function: H5ATTRget_attribute_string
233 *
234 * Purpose: Reads an string attribute named attr_name.
235 *
236 * Return: Success: 0, Failure: -1
237 *
238 * Programmer: Francesc Alted, faltet@pytables.com
239 *
240 * Date: February 23, 2005
241 *
242 * Comments:
243 *
244 * Modifications:
245 *
246 *-------------------------------------------------------------------------
247 */
248
H5ATTRget_attribute_string(hid_t obj_id,const char * attr_name,char ** data,int * cset)249 hsize_t H5ATTRget_attribute_string( hid_t obj_id,
250 const char *attr_name,
251 char **data,
252 int *cset )
253 {
254 /* identifiers */
255 hid_t attr_id;
256 hid_t attr_type;
257 hid_t space_id;
258 hsize_t type_size = 0;
259 htri_t is_vlstr = 0;
260
261 *data = NULL;
262 if ( ( attr_id = H5Aopen_by_name(obj_id, ".", attr_name,
263 H5P_DEFAULT, H5P_DEFAULT) ) < 0 )
264 return -1;
265
266 if ( (attr_type = H5Aget_type( attr_id )) < 0 )
267 goto out;
268
269 if ( ( cset != NULL ) && ( ( *cset = H5Tget_cset( attr_type ) ) < 0 ) )
270 goto out;
271
272 is_vlstr = H5Tis_variable_str( attr_type );
273 if ( is_vlstr == 0 )
274 {
275 /* Get the size */
276 if ( (type_size = H5Tget_size( attr_type )) < 0 )
277 goto out;
278
279 if ( (space_id = H5Aget_space( attr_id )) < 0 )
280 goto out;
281
282 if ( H5Sget_simple_extent_type( space_id ) == H5S_NULL )
283 type_size = 0;
284
285 H5Sclose( space_id );
286
287 /* Malloc space enough for the string, plus 1 for the trailing '\0' */
288 *data = (char *)malloc(type_size + 1);
289
290 if ( type_size > 0)
291 {
292 if ( H5Aread( attr_id, attr_type, *data ) < 0 )
293 goto out;
294 }
295
296 /* Set the last character to \0 in case we are dealing with space
297 padded strings */
298 (*data)[type_size] = '\0';
299 }
300 else
301 {
302 /* is_vlstr */
303 if ( H5Aread( attr_id, attr_type, data ) < 0 )
304 goto out;
305
306 type_size = strlen( *data );
307 }
308
309 if ( H5Tclose( attr_type ) < 0 )
310 goto out;
311
312 if ( H5Aclose( attr_id ) < 0 )
313 return -1;
314
315 return type_size;
316
317 out:
318 H5Tclose( attr_type );
319 H5Aclose( attr_id );
320 if ( (is_vlstr == 0) && (*data != NULL) )
321 free(*data);
322 *data = NULL;
323 return -1;
324 }
325
326
327 /*-------------------------------------------------------------------------
328 * Function: H5ATTRget_attribute_vlen_string_array
329 *
330 * Purpose: Reads a variable length string attribute named attr_name.
331 *
332 * Return: Success: number of elements of the array, Failure: -1
333 *
334 * Programmer: Antonio Valentino <antonio.valentino@tiscali.it>
335 *
336 * Date: November 27, 2011
337 *
338 * Comments: only rank 1 attributes of 8bit strings are supported
339 *
340 * Modifications:
341 *
342 *-------------------------------------------------------------------------
343 */
344
H5ATTRget_attribute_vlen_string_array(hid_t obj_id,const char * attr_name,char *** data,int * cset)345 hsize_t H5ATTRget_attribute_vlen_string_array( hid_t obj_id,
346 const char *attr_name,
347 char ***data,
348 int *cset )
349 {
350 /* identifiers */
351 hid_t attr_id = -1, attr_type = -1, space_id = -1;
352 hsize_t nelements = 0, *dims = NULL;
353 int ndims = 0, i;
354
355 *data = NULL;
356 if ( ( attr_id = H5Aopen_by_name( obj_id, ".", attr_name,
357 H5P_DEFAULT, H5P_DEFAULT ) ) < 0 )
358 return -1;
359
360 if ( (attr_type = H5Aget_type( attr_id )) < 0 )
361 goto out;
362
363 if ( ( cset != NULL ) && ( ( *cset = H5Tget_cset( attr_type ) ) < 0 ) )
364 goto out;
365
366 if ( (space_id = H5Aget_space( attr_id )) < 0 )
367 goto out;
368
369 if ( (ndims = H5Sget_simple_extent_ndims( space_id )) < 1 )
370 goto out;
371
372 if ( (dims = (hsize_t *)malloc(ndims * sizeof(hsize_t))) == NULL )
373 goto out;
374
375 if ( H5Sget_simple_extent_dims( space_id, dims, NULL ) < 0 )
376 goto out;
377
378 nelements = 1;
379 for ( i = 0; i < ndims; ++i )
380 nelements *= dims[i];
381
382 free( dims );
383 dims = NULL;
384
385 if ((*data = (char **)malloc( nelements * sizeof(char*))) == NULL )
386 goto out;
387
388 if ( H5Aread( attr_id, attr_type, *data ) < 0 )
389 goto out;
390
391 if ( H5Tclose( attr_type ) < 0 )
392 goto out;
393
394 if ( H5Sclose( space_id ) < 0 )
395 goto out;
396
397 if ( H5Aclose( attr_id ) < 0 )
398 return -1;
399
400 return nelements;
401
402 out:
403 if ( *data != NULL )
404 free( *data );
405 *data = NULL;
406 if ( dims != NULL )
407 free( dims );
408 H5Tclose( attr_type );
409 H5Sclose( space_id );
410 H5Aclose( attr_id );
411 return -1;
412 }
413
414
415 /*-------------------------------------------------------------------------
416 *
417 * Helper functions
418 *
419 *-------------------------------------------------------------------------
420 */
421
422 /*-------------------------------------------------------------------------
423 * Function: find_attr
424 *
425 * Purpose: operator function used by H5ATTRfind_attribute
426 *
427 * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
428 *
429 * Date: June 21, 2001
430 *
431 * Comments:
432 *
433 * Modifications:
434 *
435 *-------------------------------------------------------------------------
436 */
437
find_attr(hid_t loc_id,const char * name,const H5A_info_t * ainfo,void * op_data)438 static herr_t find_attr( hid_t loc_id,
439 const char *name,
440 const H5A_info_t *ainfo,
441 void *op_data)
442 {
443
444 /* Define a default zero value for return. This will cause the
445 * iterator to continue if the palette attribute is not found yet.
446 */
447
448 int ret = 0;
449
450 char *attr_name = (char*)op_data;
451
452 /* Shut the compiler up */
453 loc_id=loc_id;
454
455 /* Define a positive value for return value if the attribute was
456 * found. This will cause the iterator to immediately return that
457 * positive value, indicating short-circuit success
458 */
459
460 if( strcmp( name, attr_name ) == 0 )
461 ret = 1;
462
463 return ret;
464 }
465
466
467 /*-------------------------------------------------------------------------
468 * Function: H5ATTRfind_attribute
469 *
470 * Purpose: Inquires if an attribute named attr_name exists attached
471 * to the object loc_id.
472 *
473 * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
474 *
475 * Date: June 21, 2001
476 *
477 * Comments:
478 * The function uses H5Aiterate with the operator function find_attr
479 *
480 * Return:
481 * Success: The return value of the first operator that
482 * returns non-zero, or zero if all members were
483 * processed with no operator returning non-zero.
484 *
485 * Failure: Negative if something goes wrong within the
486 * library, or the negative value returned by one
487 * of the operators.
488 *
489 *-------------------------------------------------------------------------
490 */
491
H5ATTRfind_attribute(hid_t loc_id,const char * attr_name)492 herr_t H5ATTRfind_attribute( hid_t loc_id,
493 const char* attr_name )
494 {
495
496 hsize_t attr_num;
497 herr_t ret;
498
499 attr_num = 0;
500 ret = H5Aiterate( loc_id, H5_INDEX_CRT_ORDER, H5_ITER_NATIVE, &attr_num,
501 find_attr, (void *)attr_name );
502
503 return ret;
504 }
505
506
507
508 /*-------------------------------------------------------------------------
509 * Function: H5ATTRget_attribute_ndims
510 *
511 * Purpose: Gets the dimensionality of an attribute.
512 *
513 * Return: Success: 0, Failure: -1
514 *
515 * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
516 *
517 * Date: September 4, 2001
518 *
519 *-------------------------------------------------------------------------
520 */
521
H5ATTRget_type_ndims(hid_t obj_id,const char * attr_name,hid_t * type_id,H5T_class_t * class_id,size_t * type_size,int * rank)522 herr_t H5ATTRget_type_ndims( hid_t obj_id,
523 const char *attr_name,
524 hid_t *type_id,
525 H5T_class_t *class_id,
526 size_t *type_size,
527 int *rank )
528 {
529 hid_t attr_id;
530 hid_t space_id;
531
532 /* Open the attribute. */
533 if ( ( attr_id = H5Aopen_by_name(obj_id, ".", attr_name,
534 H5P_DEFAULT, H5P_DEFAULT) ) < 0 )
535 {
536 return -1;
537 }
538
539 /* Get an identifier for the datatype. */
540 *type_id = H5Aget_type( attr_id );
541
542 /* Get the class. */
543 *class_id = H5Tget_class( *type_id );
544
545 /* Get the size. */
546 *type_size = H5Tget_size( *type_id );
547
548 /* Get the dataspace handle */
549 if ( (space_id = H5Aget_space( attr_id )) < 0 )
550 goto out;
551
552 /* Get rank */
553 if ( (*rank = H5Sget_simple_extent_ndims( space_id )) < 0 )
554 goto out;
555
556 /* Terminate access to the attribute */
557 if ( H5Sclose( space_id ) < 0 )
558 goto out;
559
560 /* End access to the attribute */
561 if ( H5Aclose( attr_id ) )
562 goto out;;
563
564 return 0;
565
566 out:
567 H5Tclose( *type_id );
568 H5Aclose( attr_id );
569 return -1;
570 }
571
572
573 /*-------------------------------------------------------------------------
574 * Function: H5ATTRget_dims
575 *
576 * Purpose: Gets information about an attribute.
577 *
578 * Return: Success: 0, Failure: -1
579 *
580 * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
581 *
582 * Date: September 4, 2001
583 *
584 *-------------------------------------------------------------------------
585 */
586
H5ATTRget_dims(hid_t obj_id,const char * attr_name,hsize_t * dims)587 herr_t H5ATTRget_dims( hid_t obj_id,
588 const char *attr_name,
589 hsize_t *dims)
590 {
591 hid_t attr_id;
592 hid_t space_id;
593
594 /* Open the attribute. */
595 if ( ( attr_id = H5Aopen_by_name(obj_id, ".", attr_name,
596 H5P_DEFAULT, H5P_DEFAULT) ) < 0 )
597 {
598 return -1;
599 }
600
601 /* Get the dataspace handle */
602 if ( (space_id = H5Aget_space( attr_id )) < 0 )
603 goto out;
604
605 /* Get dimensions */
606 if ( H5Sget_simple_extent_dims( space_id, dims, NULL) < 0 )
607 goto out;
608
609 /* Terminate access to the dataspace */
610 if ( H5Sclose( space_id ) < 0 )
611 goto out;
612
613 /* End access to the attribute */
614 if ( H5Aclose( attr_id ) )
615 goto out;
616
617 return 0;
618
619 out:
620 H5Aclose( attr_id );
621 return -1;
622 }
623