Mesh Oriented datABase  (version 5.5.1)
An array-based unstructured mesh library
tags.c
Go to the documentation of this file.
1 /**
2  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
3  * storing and accessing finite element mesh data.
4  *
5  * Copyright 2004 Sandia Corporation. Under the terms of Contract
6  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
7  * retains certain rights in this software.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  */
15 
16 #include <stdlib.h>
17 #include <string.h>
18 #include <H5Tpublic.h>
19 #include <H5Gpublic.h>
20 #include <H5Dpublic.h>
21 #include <H5Spublic.h> /* for H5S_MAX_RANK */
22 #include <H5Apublic.h>
23 #include <H5Ppublic.h>
24 #include "status.h"
25 #include "file-handle.h"
26 #include "mhdf.h"
27 #include "util.h"
28 #include "names-and-paths.h"
29 
30 hid_t mhdf_getNativeType( hid_t input_type, int size, mhdf_Status* status )
31 {
32  H5T_sign_t sgn;
33  H5T_class_t cls;
34  hid_t tmp_id, type_id;
35 
36  mhdf_setOkay( status );
37 
38  cls = H5Tget_class( input_type );
39  switch( cls )
40  {
41  case H5T_FLOAT:
42  switch( size )
43  {
44  case 4:
45  return H5T_NATIVE_FLOAT;
46  case 8:
47  return H5T_NATIVE_DOUBLE;
48  case 16:
49  return H5T_NATIVE_LDOUBLE;
50  default:
51  mhdf_setFail( status, "Invalid size for floating point type: %d", size );
52  return -1;
53  }
54 
55  case H5T_INTEGER:
56  sgn = H5Tget_sign( input_type );
57  if( H5T_SGN_ERROR == sgn )
58  {
59  mhdf_setFail( status, "Internall errror calling H5Tget_sign." );
60  return -1;
61  }
62  if( sizeof( char ) == size )
63  return sgn == H5T_SGN_NONE ? H5T_NATIVE_UCHAR : H5T_NATIVE_SCHAR;
64  else if( sizeof( short ) == size )
65  return sgn == H5T_SGN_NONE ? H5T_NATIVE_USHORT : H5T_NATIVE_SHORT;
66  else if( sizeof( int ) == size )
67  return sgn == H5T_SGN_NONE ? H5T_NATIVE_UINT : H5T_NATIVE_INT;
68  else if( sizeof( long ) == size )
69  return sgn == H5T_SGN_NONE ? H5T_NATIVE_ULONG : H5T_NATIVE_LONG;
70  else if( (int)H5Tget_size( H5T_NATIVE_LLONG ) == size )
71  return sgn == H5T_SGN_NONE ? H5T_NATIVE_ULLONG : H5T_NATIVE_LLONG;
72 
73  mhdf_setFail( status, "Invalid size for integer type: %d", size );
74  return -1;
75 
76  case H5T_ENUM:
77  tmp_id = H5Tget_super( input_type );
78  if( tmp_id < 0 )
79  {
80  mhdf_setFail( status, "Internal error calling H5Tget_super." );
81  return -1;
82  }
83  type_id = mhdf_getNativeType( tmp_id, size, status );
84  H5Tclose( tmp_id );
85  return type_id;
86 
87  case H5T_TIME:
88  case H5T_OPAQUE:
89  case H5T_REFERENCE:
90  mhdf_setFail( status, "Unsupported type class." );
91  return -1;
92 
93  case H5T_COMPOUND:
94  case H5T_VLEN:
95  case H5T_ARRAY:
96  case H5T_STRING:
97  mhdf_setFail( status, "Only atomic types are supported." );
98  return -1;
99 
100  default:
101  mhdf_setFail( status, "Internal error calling H5Tget_class. Bad handle?" );
102  return -1;
103  }
104 }
105 
106 static hid_t get_tag( mhdf_FileHandle file_handle, const char* tag_name, hid_t* id_type, mhdf_Status* status )
107 {
108  hid_t group_id, tag_id;
109  char* path;
110  FileHandle* file_ptr;
111 
112  file_ptr = (FileHandle*)file_handle;
113  if( !mhdf_check_valid_file( file_ptr, status ) ) return -1;
114 
115  if( NULL != id_type ) *id_type = file_ptr->id_type;
116 
117  path = mhdf_name_to_path_copy( tag_name, status );
118  if( NULL == path ) return -1;
119 
120 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
121  group_id = H5Gopen2( file_ptr->hdf_handle, TAG_GROUP, H5P_DEFAULT );
122 #else
123  group_id = H5Gopen( file_ptr->hdf_handle, TAG_GROUP );
124 #endif
125  if( group_id < 0 )
126  {
127  mhdf_setFail( status, "Failed to open tag group." );
128  free( path );
129  return -1;
130  }
131 
132 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
133  tag_id = H5Gopen2( group_id, path, H5P_DEFAULT );
134 #else
135  tag_id = H5Gopen( group_id, path );
136 #endif
137  H5Gclose( group_id );
138  free( path );
139  if( tag_id < 0 )
140  {
141  mhdf_setFail( status, "Failed to open tag data for tag \"%s\".", tag_name );
142  return -1;
143  }
144 
145  mhdf_setOkay( status );
146  return tag_id;
147 }
148 
149 static hid_t get_tag_type( FileHandle* file_ptr, const char* tag_path, mhdf_Status* status )
150 {
151  hid_t group_id, tag_id, type_id;
152 
153 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
154  group_id = H5Gopen2( file_ptr->hdf_handle, TAG_GROUP, H5P_DEFAULT );
155 #else
156  group_id = H5Gopen( file_ptr->hdf_handle, TAG_GROUP );
157 #endif
158  if( group_id < 0 )
159  {
160  mhdf_setFail( status, "Failed to open tag group." );
161  return -1;
162  }
163 
164 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
165  tag_id = H5Gopen2( group_id, tag_path, H5P_DEFAULT );
166 #else
167  tag_id = H5Gopen( group_id, tag_path );
168 #endif
169  H5Gclose( group_id );
170  if( tag_id < 0 )
171  {
172  mhdf_setFail( status, "Failed to open group for tag \"%s\".", tag_path );
173  return -1;
174  }
175 
176 #if defined( H5Topen_vers ) && H5Topen_vers > 1
177  type_id = H5Topen2( tag_id, TAG_TYPE_NAME, H5P_DEFAULT );
178 #else
179  type_id = H5Topen( tag_id, TAG_TYPE_NAME );
180 #endif
181  H5Gclose( tag_id );
182  if( type_id < 0 )
183  {
184  mhdf_setFail( status, "Failed to open type data for tag \"%s\".", tag_path );
185  return -1;
186  }
187 
188  return type_id;
189 }
190 
191 /** Helper function to write default and mesh values for tag
192  *\param tag_id The file object upon which to attach the attribute
193  *\param attrib_name The name of the attribute object
194  *\param type_id The data type of the attribute data
195  *\param value Pointer to attribute data
196  *\param value_size Size of attribute data, as multiple of type indicated
197  * by type_id. Should be 1 except for variable-length tag data.
198  */
199 static int store_tag_val_in_attrib( hid_t tag_id,
200  const char* attrib_name,
201  hid_t type_id,
202  const void* value,
203  hsize_t value_size,
204  mhdf_Status* status )
205 {
206  hid_t write_type;
207  int rval;
208  if( value_size == 1 )
209  write_type = type_id;
210  else if( H5Tget_class( type_id ) == H5T_OPAQUE )
211  {
212  write_type = H5Tcreate( H5T_OPAQUE, value_size );
213  }
214  else
215  {
216 #if defined( H5Tarray_create_vers ) && H5Tarray_create_vers > 1
217  write_type = H5Tarray_create2( type_id, 1, &value_size );
218 #else
219  write_type = H5Tarray_create( type_id, 1, &value_size, 0 );
220 #endif
221  }
222 
223  if( write_type < 0 )
224  {
225  mhdf_setFail( status, "Error constructing type object for tag mesh/default value" );
226  return -1;
227  }
228 
229  rval = mhdf_create_scalar_attrib( tag_id, attrib_name, write_type, value, status );
230  if( write_type != type_id ) H5Tclose( write_type );
231 
232  return rval;
233 }
234 
235 static hid_t create_tag_common( mhdf_FileHandle file_handle,
236  const char* tag_name,
237  enum mhdf_TagDataType tag_type,
238  int size,
239  int storage,
240  const void* default_value,
241  int default_value_size_in,
242  const void* global_value,
243  int global_value_size_in,
244  hid_t hdf_type,
245  hid_t hdf_base_type,
246  mhdf_Status* status )
247 {
248  hid_t temp_id, group_id, tag_id;
249  char* path;
250  FileHandle* file_ptr;
251  herr_t rval;
252  hsize_t arr_len;
253  int one = 1, var_len = 0;
254  hsize_t default_value_size = default_value_size_in;
255  hsize_t global_value_size = global_value_size_in;
256  int close_base_type = 0;
257 
258  /* Force standard data types over user-specified types */
259 
260  if( tag_type != mhdf_OPAQUE ) hdf_type = 0;
261  if( tag_type != mhdf_ENTITY_ID ) hdf_base_type = 0;
262 
263  /* Validate input */
264 
265  file_ptr = (FileHandle*)file_handle;
266  if( !mhdf_check_valid_file( file_ptr, status ) ) return -1;
267 
268  if( !tag_name || !*tag_name )
269  {
270  mhdf_setFail( status, "Invalid tag name" );
271  return -1;
272  }
273 
274  /* Open the tag group */
275 
276 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
277  group_id = H5Gopen2( file_ptr->hdf_handle, TAG_GROUP, H5P_DEFAULT );
278 #else
279  group_id = H5Gopen( file_ptr->hdf_handle, TAG_GROUP );
280 #endif
281  if( group_id < 0 )
282  {
283  mhdf_setFail( status, "H5Gopen(\"%s\") failed.", TAG_GROUP );
284  return -1;
285  }
286 
287  /* Create path string for tag object */
288 
289  path = mhdf_name_to_path_copy( tag_name, status );
290  if( !path )
291  {
292  H5Gclose( group_id );
293  return -1;
294  }
295 
296  /* Create group for this tag */
297 
298 #if defined( H5Gcreate_vers ) && H5Gcreate_vers > 1
299  tag_id = H5Gcreate2( group_id, path, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
300 #else
301  tag_id = H5Gcreate( group_id, path, 3 );
302 #endif
303  if( tag_id < 0 )
304  {
305  mhdf_setFail( status, "H5Gcreate( \"%s\" ) failed.", path );
306  free( path );
307  H5Gclose( group_id );
308  return -1;
309  }
310 
311  /* Store the tag name as the comment on the group entry */
312 
313  rval = H5Gset_comment( group_id, path, tag_name );
314  H5Gclose( group_id );
315  free( path );
316  if( rval < 0 )
317  {
318  mhdf_setFail( status, "H5Gset_comment failed for tag \"%s\"", tag_name );
319  H5Gclose( tag_id );
320  return -1;
321  }
322 
323  /* Store TSTT tag type as attribute */
324 
325  rval = mhdf_create_scalar_attrib( tag_id, TAG_TYPE_ATTRIB, H5T_NATIVE_INT, &storage, status );
326  if( !rval )
327  {
328  H5Gclose( tag_id );
329  return -1;
330  }
331 
332  if( hdf_type )
333  {
334  hdf_type = H5Tcopy( hdf_type );
335  arr_len = 1;
336  }
337  else
338  {
339  switch( tag_type )
340  {
341  default:
342  case mhdf_OPAQUE:
343  arr_len = 1;
344  hdf_type = H5Tcreate( H5T_OPAQUE, abs( size ) );
345  H5Tset_tag( hdf_type, "tag_data" );
346  break;
347 
348  case mhdf_BITFIELD:
349  arr_len = 1;
350  if( size <= 0 )
351  {
352  mhdf_setFail( status, "Invalid size (%d) for bit tag.", (int)size );
353  return -1;
354  }
355  else if( size <= 8 )
356  hdf_type = H5Tcopy( H5T_NATIVE_B8 );
357  else if( size <= 16 )
358  hdf_type = H5Tcopy( H5T_NATIVE_B16 );
359  else if( size <= 32 )
360  hdf_type = H5Tcopy( H5T_NATIVE_B32 );
361  else if( size <= 64 )
362  hdf_type = H5Tcopy( H5T_NATIVE_B64 );
363  else
364  {
365  mhdf_setFail( status, "Cannot create a bit tag larger than 64-bits. %d bits requested.\n",
366  (int)size );
367  return -1;
368  }
369 
370  if( 0 > H5Tset_precision( hdf_type, size ) )
371  {
372  mhdf_setFail( status, "H5Tset_precision failed." );
373  return -1;
374  }
375  break;
376 
377  case mhdf_ENTITY_ID:
378  arr_len = abs( size );
379  hdf_type = H5Tcopy( H5T_NATIVE_ULONG );
380  break;
381 
382  case mhdf_BOOLEAN:
383  arr_len = abs( size );
384  hdf_type = H5Tcopy( H5T_NATIVE_UCHAR );
385  break;
386 
387  case mhdf_INTEGER:
388  arr_len = abs( size );
389  hdf_type = H5Tcopy( H5T_NATIVE_INT );
390  break;
391 
392  case mhdf_FLOAT:
393  arr_len = abs( size );
394  hdf_type = H5Tcopy( H5T_NATIVE_DOUBLE );
395  break;
396  }
397  }
398 
399  if( hdf_type <= 0 )
400  {
401  mhdf_setFail( status, "Failed to create tag type object." );
402  H5Gclose( tag_id );
403  return -1;
404  }
405 
406  if( hdf_base_type && H5Tget_class( hdf_type ) != H5Tget_class( hdf_base_type ) )
407  {
408  mhdf_setFail( status, "Invalid base type for tag default/global data" );
409  H5Gclose( tag_id );
410  return -1;
411  }
412 
413  if( size < -1 || !arr_len )
414  {
415  mhdf_setFail( status, "Invalid 'size' parameter passed to mhdf_createTag (%d)", (int)size );
416  H5Gclose( tag_id );
417  return -1;
418  }
419  else if( size == -1 )
420  {
421  /* Note: we don't do anything with this here. We rely on
422  * the app to ask us to create the index table later.
423  */
424  arr_len = 1;
425  /* need to know this later, when storing default/global values */
426  var_len = 1;
427  }
428  else if( arr_len > 1 )
429  {
430 #if defined( H5Tarray_create_vers ) && H5Tarray_create_vers > 1
431  temp_id = H5Tarray_create2( hdf_type, 1, &arr_len );
432 #else
433  temp_id = H5Tarray_create( hdf_type, 1, &arr_len, NULL );
434 #endif
435  H5Tclose( hdf_type );
436  if( temp_id < 0 )
437  {
438  mhdf_setFail( status, "Failed to create tag type object." );
439  H5Gclose( tag_id );
440  return -1;
441  }
442  hdf_type = temp_id;
443 
444  if( hdf_base_type )
445  {
446  if( H5Tequal( hdf_base_type, hdf_type ) > 0 )
447  {
448  hdf_base_type = hdf_type;
449  }
450  else
451  {
452 #if defined( H5Tarray_create_vers ) && H5Tarray_create_vers > 1
453  temp_id = H5Tarray_create2( hdf_base_type, 1, &arr_len );
454 #else
455  temp_id = H5Tarray_create( hdf_base_type, 1, &arr_len, NULL );
456 #endif
457  if( temp_id < 0 )
458  {
459  mhdf_setFail( status, "Failed to create tag type object." );
460  H5Gclose( tag_id );
461  H5Tclose( hdf_type );
462  return -1;
463  }
464  hdf_base_type = temp_id;
465  close_base_type = 1;
466  }
467  }
468  }
469 
470  if( !hdf_base_type ) hdf_base_type = hdf_type;
471 
472  /* Create tag type object, or write attribute if opaque */
473 
474 #if defined( H5Tcommit_vers ) && H5Tcommit_vers > 1
475  rval = H5Tcommit2( tag_id, TAG_TYPE_NAME, hdf_type, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
476 #else
477  rval = H5Tcommit( tag_id, TAG_TYPE_NAME, hdf_type );
478 #endif
479  if( rval < 0 )
480  {
481  mhdf_setFail( status, "H5Tcommit failed for tag \"%s\"", tag_name );
482  if( close_base_type ) H5Tclose( hdf_base_type );
483  H5Tclose( hdf_type );
484  H5Gclose( tag_id );
485  return -1;
486  }
487 
488  /* If tag is entity handle, make note of it */
489  if( tag_type == mhdf_ENTITY_ID )
490  {
491  rval = mhdf_create_scalar_attrib( tag_id, TAG_HANDLE_TYPE_ATTRIB, H5T_NATIVE_INT, &one, status );
492  if( !rval )
493  {
494  if( close_base_type ) H5Tclose( hdf_base_type );
495  H5Gclose( tag_id );
496  H5Tclose( hdf_type );
497  return -1;
498  }
499  }
500 
501  /* Store the default value as a attribute of the tag group */
502 
503  if( default_value )
504  {
505  rval = store_tag_val_in_attrib( tag_id, TAG_DEFAULT_ATTRIB, hdf_base_type, default_value,
506  var_len ? default_value_size : 1, status );
507  if( !rval )
508  {
509  if( close_base_type ) H5Tclose( hdf_base_type );
510  H5Gclose( tag_id );
511  H5Tclose( hdf_type );
512  return -1;
513  }
514  }
515 
516  /* Store global tag value as attribute */
517 
518  if( global_value )
519  {
520  rval = store_tag_val_in_attrib( tag_id, TAG_GLOBAL_ATTRIB, hdf_base_type, global_value,
521  var_len ? global_value_size : 1, status );
522  if( !rval )
523  {
524  if( close_base_type ) H5Tclose( hdf_base_type );
525  H5Gclose( tag_id );
526  H5Tclose( hdf_type );
527  return -1;
528  }
529  }
530 
531  if( close_base_type ) H5Tclose( hdf_base_type );
532  H5Tclose( hdf_type );
533  mhdf_setOkay( status );
534  return tag_id;
535 }
536 
537 hid_t mhdf_getTagDataType( mhdf_FileHandle file_handle, const char* tag_name, mhdf_Status* status )
538 {
539  FileHandle* file_ptr;
540  hid_t result;
541  char* path;
542  API_BEGIN;
543 
544  /* Validate input */
545 
546  file_ptr = (FileHandle*)file_handle;
547  if( !mhdf_check_valid_file( file_ptr, status ) ) return -1;
548 
549  if( !tag_name || !*tag_name )
550  {
551  mhdf_setFail( status, "Invalid tag name" );
552  return -1;
553  }
554 
555  /* Create path string for tag object */
556 
557  path = mhdf_name_to_path_copy( tag_name, status );
558  if( !path )
559  {
560  return -1;
561  }
562 
563  result = get_tag_type( file_ptr, path, status );
564 
565  free( path );
566  API_END;
567  return result;
568 }
569 
570 void mhdf_createTag( mhdf_FileHandle file_handle,
571  const char* tag_name,
572  enum mhdf_TagDataType tag_type,
573  int size,
574  int storage,
575  const void* default_value,
576  const void* global_value,
577  hid_t hdf_type,
578  hid_t hdf_base_type,
579  mhdf_Status* status )
580 {
581  hid_t tag_id;
582  API_BEGIN;
583  tag_id = create_tag_common( file_handle, tag_name, tag_type, size, storage, default_value, 1, global_value, 1,
584  hdf_type, hdf_base_type, status );
585  if( tag_id >= 0 ) H5Gclose( tag_id );
586  API_END;
587 }
588 
590  const char* tag_name,
591  enum mhdf_TagDataType tag_type,
592  int storage,
593  const void* default_value,
594  int default_value_length,
595  const void* global_value,
596  int global_value_length,
597  hid_t hdf_type,
598  hid_t hdf_base_type,
599  mhdf_Status* status )
600 {
601  hid_t tag_id;
602  int one = 1;
603 
604  API_BEGIN;
605  tag_id = create_tag_common( file_handle, tag_name, tag_type, -1, storage, default_value, default_value_length,
606  global_value, global_value_length, hdf_type, hdf_base_type, status );
607  if( tag_id >= 0 )
608  {
609  mhdf_create_scalar_attrib( tag_id, TAG_VARLEN_ATTRIB, H5T_NATIVE_INT, &one, status );
610  H5Gclose( tag_id );
611  }
612  API_END;
613 }
614 
615 int mhdf_getNumberTags( mhdf_FileHandle file_handle, mhdf_Status* status )
616 {
617  hid_t group_id;
618  hsize_t result;
619  FileHandle* file_ptr;
620  API_BEGIN;
621 
622  /* Validate input */
623 
624  file_ptr = (FileHandle*)file_handle;
625  if( !mhdf_check_valid_file( file_ptr, status ) ) return -1;
626 
627  /* Open the tags group */
628 
629 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
630  group_id = H5Gopen2( file_ptr->hdf_handle, TAG_GROUP, H5P_DEFAULT );
631 #else
632  group_id = H5Gopen( file_ptr->hdf_handle, TAG_GROUP );
633 #endif
634  if( group_id < 0 )
635  {
636  mhdf_setFail( status, "H5Gopen(\"%s\") failed", TAG_GROUP );
637  return -1;
638  }
639 
640  /* Get number of objects in tags group */
641 
642  if( H5Gget_num_objs( group_id, &result ) < 0 )
643  {
644  mhdf_setFail( status, "Internal failure calling H5Gget_num_objs." );
645  H5Gclose( group_id );
646  return -1;
647  }
648 
649  H5Gclose( group_id );
650  mhdf_setOkay( status );
651  API_END;
652  return (int)result;
653 }
654 
655 char** mhdf_getTagNames( mhdf_FileHandle file_handle, int* num_names_out, mhdf_Status* status )
656 {
657  hid_t group_id;
658  FileHandle* file_ptr;
659  hsize_t count, idx;
660  char* name;
661  char** result;
662  ssize_t size;
663  API_BEGIN;
664 
665  /* Validate input */
666 
667  file_ptr = (FileHandle*)file_handle;
668  if( !mhdf_check_valid_file( file_ptr, status ) ) return NULL;
669 
670  /* Open the tags group */
671 
672 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
673  group_id = H5Gopen2( file_ptr->hdf_handle, TAG_GROUP, H5P_DEFAULT );
674 #else
675  group_id = H5Gopen( file_ptr->hdf_handle, TAG_GROUP );
676 #endif
677  if( group_id < 0 )
678  {
679  mhdf_setFail( status, "H5Gopen(\"%s\") failed", TAG_GROUP );
680  return NULL;
681  }
682 
683  /* Get number of objects in tags group */
684 
685  if( H5Gget_num_objs( group_id, &count ) < 0 )
686  {
687  mhdf_setFail( status, "Internal failure calling H5Gget_num_objs." );
688  H5Gclose( group_id );
689  return NULL;
690  }
691 
692  /* No tags? */
693 
694  *num_names_out = (int)count;
695  if( count == 0 )
696  {
697  H5Gclose( group_id );
698  mhdf_setOkay( status );
699  return NULL;
700  }
701 
702  /* Allocate string array */
703 
704  result = (char**)mhdf_malloc( sizeof( char* ) * count, status );
705  if( NULL == result )
706  {
707  H5Gclose( group_id );
708  return NULL;
709  }
710 
711  /* Get names */
712 
713  for( idx = 0; idx < count; ++idx )
714  {
715  size = H5Gget_objname_by_idx( group_id, idx, NULL, 0 );
716  if( size < 1 || NULL == ( name = (char*)mhdf_malloc( size + 1, status ) ) )
717  {
718  while( ( --idx ) > 0 )
719  free( result[idx] );
720  free( result );
721  H5Gclose( group_id );
722  mhdf_setFail( status, "Internal failure calling H5Gget_objname_by_idx." );
723  return NULL;
724  }
725 
726  H5Gget_objname_by_idx( group_id, idx, name, size + 1 );
727  if( !mhdf_path_to_name( name, name ) )
728  {
729  mhdf_setFail( status, "Invalid character string in internal file path: \"%s\"\n", name );
730  return NULL;
731  }
732  result[idx] = name;
733  }
734 
735  H5Gclose( group_id );
736  mhdf_setOkay( status );
737  API_END;
738  return result;
739 }
740 
741 static int get_attrib_array_length_handle( hid_t attrib_id )
742 {
743  hid_t type_id;
744  int rank;
745  hsize_t dims[H5S_MAX_RANK];
746  int perm[H5S_MAX_RANK];
747 
748  type_id = H5Aget_type( attrib_id );
749  switch( H5Tget_class( type_id ) )
750  {
751  case H5T_NO_CLASS:
752  dims[0] = -1;
753  break;
754  case H5T_OPAQUE:
755  dims[0] = H5Tget_size( type_id );
756  break;
757  case H5T_ARRAY:
758 #if defined( H5Tget_array_dims_vers ) && H5Tget_array_dims_vers > 1
759  (void)perm; /* suppress warning */
760  rank = H5Tget_array_dims2( type_id, dims );
761 #else
762  rank = H5Tget_array_dims( type_id, dims, perm );
763 #endif
764  if( rank == 1 )
765  break;
766  else
767  return -1;
768  default:
769  dims[0] = 1;
770  break;
771  }
772 
773  H5Tclose( type_id );
774  return dims[0];
775 }
776 
777 /*
778 static int get_attrib_array_length_index( hid_t object_id, unsigned int index )
779 {
780  hid_t attrib_id;
781  int result;
782 
783  attrib_id = H5Aopen_idx( object_id, index );
784  if (attrib_id < 0)
785  return -1;
786 
787  result = get_attrib_array_length_handle( attrib_id );
788  H5Aclose( attrib_id );
789  return result;
790 }
791 */
792 
793 static int get_attrib_array_length_name( hid_t file, const char* path )
794 {
795  hid_t attrib_id;
796  int result;
797 
798  attrib_id = H5Aopen_name( file, path );
799  if( attrib_id < 0 ) return -1;
800 
801  result = get_attrib_array_length_handle( attrib_id );
802  H5Aclose( attrib_id );
803  return result;
804 }
805 
807  const char* tag_name,
808  enum mhdf_TagDataType* class_out,
809  int* size_out,
810  int* tstt_storage_out,
811  int* have_default_out,
812  int* have_global_out,
813  int* have_sparse_out,
814  mhdf_Status* status )
815 {
816  hid_t tag_id, type_id, super_id;
817  int i, rval, is_handle;
818  hsize_t size, sup_size;
819  unsigned int idx;
820  int rank, var_data;
821  hsize_t dims[H5S_MAX_RANK];
822  int perm[H5S_MAX_RANK];
823  H5T_class_t class_tmp;
824 
825  API_BEGIN;
826 
827  /* Validate input */
828  if( NULL == tag_name || NULL == class_out || NULL == size_out || NULL == tstt_storage_out ||
829  NULL == have_default_out || NULL == have_global_out || NULL == have_sparse_out )
830  {
831  mhdf_setFail( status, "Invalid input." );
832  return;
833  }
834 
835  /* Get group for tag */
836  tag_id = get_tag( file_handle, tag_name, NULL, status );
837  if( tag_id < 0 ) return;
838 
839  /* Check for sparse data */
840  rval = mhdf_is_in_group( tag_id, SPARSE_ENTITY_NAME, status );
841  if( rval < 0 )
842  {
843  H5Gclose( tag_id );
844  return;
845  }
846  *have_sparse_out = rval ? 1 : 0;
847 
848  /* Check for variable-length tag data */
849  rval = mhdf_find_attribute( tag_id, TAG_VARLEN_ATTRIB, &idx, status );
850  if( rval < 0 )
851  {
852  H5Gclose( tag_id );
853  return;
854  }
855  var_data = rval ? 1 : 0;
856 
857  /* Check if have default value for tag */
858  rval = mhdf_find_attribute( tag_id, TAG_DEFAULT_ATTRIB, &idx, status );
859  if( rval < 0 )
860  {
861  H5Gclose( tag_id );
862  return;
863  }
864  if( !rval )
865  *have_default_out = 0;
866  else if( !var_data )
867  *have_default_out = 1;
868  else
869  {
870  /* *have_default_out = get_attrib_array_length_index( tag_id, index ); */
871  *have_default_out = get_attrib_array_length_name( tag_id, TAG_DEFAULT_ATTRIB );
872  if( *have_default_out < 0 )
873  {
874  mhdf_setFail( status, "Error checking length of default value for tag: %s\n", tag_name );
875  H5Gclose( tag_id );
876  return;
877  }
878  }
879 
880  /* Check if have global value for tag */
881  rval = mhdf_find_attribute( tag_id, TAG_GLOBAL_ATTRIB, &idx, status );
882  if( rval < 0 )
883  {
884  H5Gclose( tag_id );
885  return;
886  }
887  if( !rval )
888  *have_global_out = 0;
889  else if( !var_data )
890  *have_global_out = 1;
891  else
892  {
893  /* *have_global_out = get_attrib_array_length_index( tag_id, index ); */
894  *have_global_out = get_attrib_array_length_name( tag_id, TAG_GLOBAL_ATTRIB );
895  if( *have_global_out < 0 )
896  {
897  mhdf_setFail( status, "Error checking length of global value for tag: %s\n", tag_name );
898  H5Gclose( tag_id );
899  return;
900  }
901  }
902 
903  /* Get TSTT tag class */
904  rval = mhdf_read_scalar_attrib( tag_id, TAG_TYPE_ATTRIB, H5T_NATIVE_INT, tstt_storage_out, status );
905  if( rval < 1 )
906  {
907  H5Gclose( tag_id );
908  return;
909  }
910 
911  /* Check if tag is storing entity handles */
912  rval = mhdf_find_attribute( tag_id, TAG_HANDLE_TYPE_ATTRIB, &idx, status );
913  if( rval < 0 )
914  {
915  H5Gclose( tag_id );
916  return;
917  }
918  is_handle = rval;
919 
920  /* Get tag type */
921 #if defined( H5Topen_vers ) && H5Topen_vers > 1
922  type_id = H5Topen2( tag_id, TAG_TYPE_NAME, H5P_DEFAULT );
923 #else
924  type_id = H5Topen( tag_id, TAG_TYPE_NAME );
925 #endif
926  if( type_id < 0 )
927  {
928  H5Gclose( tag_id );
929  mhdf_setFail( status, "Failed to get type object for tag \"%s\".", tag_name );
930  return;
931  }
932 
933  class_tmp = H5Tget_class( type_id );
934  if( class_tmp < 0 )
935  {
936  mhdf_setFail( status, "H5Tget_class failed." );
937  H5Gclose( tag_id );
938  H5Tclose( type_id );
939  return;
940  }
941 
942  size = H5Tget_size( type_id );
943  if( size <= 0 )
944  {
945  mhdf_setFail( status, "H5Tget_size failed." );
946  H5Gclose( tag_id );
947  H5Tclose( type_id );
948  return;
949  }
950 
951  switch( class_tmp )
952  {
953  case H5T_INTEGER:
954  *class_out = ( size == 1 ) ? mhdf_BOOLEAN : mhdf_INTEGER;
955  *size_out = 1;
956  break;
957 
958  case H5T_FLOAT:
959  *class_out = mhdf_FLOAT;
960  *size_out = 1;
961  break;
962 
963  case H5T_BITFIELD:
964  *class_out = mhdf_BITFIELD;
965  *size_out = H5Tget_precision( type_id );
966  if( *size_out <= 0 )
967  {
968  mhdf_setFail( status, "H5Tget_precision failed." );
969  H5Gclose( tag_id );
970  H5Tclose( type_id );
971  return;
972  }
973  break;
974 
975  default:
976  case H5T_OPAQUE:
977  *class_out = mhdf_OPAQUE;
978  *size_out = size;
979  break;
980 
981  case H5T_ARRAY:
982 
983 #if defined( H5Tget_array_dims_vers ) && H5Tget_array_dims_vers > 1
984  (void)perm; /* suppress warning */
985  rank = H5Tget_array_dims2( type_id, dims );
986 #else
987  rank = H5Tget_array_dims( type_id, dims, perm );
988 #endif
989  if( rank <= 0 )
990  {
991  mhdf_setFail( status, "H5Tget_size failed." );
992  H5Gclose( tag_id );
993  H5Tclose( type_id );
994  return;
995  }
996  for( i = 1; i < rank; ++i )
997  dims[0] *= dims[i];
998 
999  super_id = H5Tget_super( type_id );
1000  if( super_id < 0 )
1001  {
1002  mhdf_setFail( status, "H5Tget_super failed" );
1003  H5Gclose( tag_id );
1004  H5Tclose( type_id );
1005  return;
1006  }
1007 
1008  class_tmp = H5Tget_class( super_id );
1009  if( class_tmp < 0 )
1010  {
1011  mhdf_setFail( status, "H5Tget_class failed." );
1012  H5Gclose( tag_id );
1013  H5Tclose( type_id );
1014  H5Tclose( super_id );
1015  return;
1016  }
1017 
1018  sup_size = H5Tget_size( super_id );
1019  H5Tclose( super_id );
1020  if( sup_size <= 0 )
1021  {
1022  mhdf_setFail( status, "H5Tget_size failed." );
1023  H5Gclose( tag_id );
1024  H5Tclose( type_id );
1025  return;
1026  }
1027 
1028  switch( class_tmp )
1029  {
1030  case H5T_INTEGER:
1031  *class_out = ( sup_size == 1 ) ? mhdf_BOOLEAN : mhdf_INTEGER;
1032  *size_out = dims[0];
1033  break;
1034 
1035  case H5T_FLOAT:
1036  *class_out = mhdf_FLOAT;
1037  *size_out = dims[0];
1038  break;
1039 
1040  default:
1041  *class_out = mhdf_OPAQUE;
1042  *size_out = size;
1043  break;
1044  }
1045 
1046  break;
1047  }
1048  H5Tclose( type_id );
1049  H5Gclose( tag_id );
1050 
1051  if( is_handle )
1052  {
1053  if( *class_out != mhdf_INTEGER )
1054  {
1055  mhdf_setFail( status, "Non-integer tag marked as handle type." );
1056  return;
1057  }
1058  *class_out = mhdf_ENTITY_ID;
1059  }
1060 
1061  if( var_data )
1062  {
1063  if( *size_out != 1 || *class_out == mhdf_BITFIELD )
1064  {
1065  mhdf_setFail( status, "Invalid or unexpected variable-length tag data" );
1066  return;
1067  }
1068  *size_out = -1;
1069  }
1070 
1071  mhdf_setOkay( status );
1072  API_END;
1073 }
1074 
1075 static int read_tag_attrib_data( hid_t tag_id,
1076  const char* attrib_name,
1077  hid_t type_id,
1078  void* data,
1079  int is_var_len,
1080  mhdf_Status* status )
1081 {
1082  int rval, ilen;
1083  unsigned idx;
1084  hid_t read_type = type_id;
1085  hsize_t len;
1086 
1087  /* Check if tag has attribute */
1088  rval = mhdf_find_attribute( tag_id, attrib_name, &idx, status );
1089  if( rval < 0 )
1090  return 0;
1091  else if( 0 == rval )
1092  return 1;
1093 
1094  if( NULL == data )
1095  {
1096  mhdf_setFail( status, "Invalid input." );
1097  return 0;
1098  }
1099 
1100  if( is_var_len )
1101  {
1102  /* len = get_attrib_array_length_index(tag_id, index); */
1103  ilen = get_attrib_array_length_name( tag_id, attrib_name );
1104  if( ilen < 0 )
1105  {
1106  mhdf_setFail( status, "Failed to read length of default/mesh value for tag" );
1107  return 0;
1108  }
1109  len = ilen;
1110 
1111  /* caller passes type_id == 0 for OPAQUE */
1112  if( 0 == type_id )
1113  read_type = H5Tcreate( H5T_OPAQUE, len );
1114  else
1115  {
1116 #if defined( H5Tarray_create_vers ) && H5Tarray_create_vers > 1
1117  read_type = H5Tarray_create2( type_id, 1, &len );
1118 #else
1119  read_type = H5Tarray_create( type_id, 1, &len, 0 );
1120 #endif
1121  }
1122  if( read_type < 0 )
1123  {
1124  mhdf_setFail( status, "Failed to read mesh/default value for tag" );
1125  return 0;
1126  }
1127  }
1128 
1129  rval = mhdf_read_scalar_attrib( tag_id, attrib_name, read_type, data, status );
1130  if( is_var_len ) H5Tclose( read_type );
1131 
1132  return rval;
1133 }
1134 
1136  const char* tag_name,
1137  hid_t output_data_type,
1138  void* default_value,
1139  void* global_value,
1140  mhdf_Status* status )
1141 {
1142  hid_t tag_id;
1143  int rval, var_data;
1144  unsigned int idx;
1145  API_BEGIN;
1146 
1147  /* check args */
1148  if( NULL == tag_name || !*tag_name )
1149  {
1150  mhdf_setFail( status, "Invalid input." );
1151  return;
1152  }
1153 
1154  /* Get the tag group */
1155  tag_id = get_tag( file_handle, tag_name, NULL, status );
1156  if( tag_id < 0 ) return;
1157 
1158  /* Check for variable-length tag data */
1159  rval = mhdf_find_attribute( tag_id, TAG_VARLEN_ATTRIB, &idx, status );
1160  if( rval < 0 )
1161  {
1162  H5Gclose( tag_id );
1163  return;
1164  }
1165  var_data = rval ? 1 : 0;
1166 
1167  /* Read default value if present */
1168  rval = read_tag_attrib_data( tag_id, TAG_DEFAULT_ATTRIB, output_data_type, default_value, var_data, status );
1169  if( !rval )
1170  {
1171  H5Gclose( tag_id );
1172  return;
1173  }
1174 
1175  /* Read mesh value if present */
1176  rval = read_tag_attrib_data( tag_id, TAG_GLOBAL_ATTRIB, output_data_type, global_value, var_data, status );
1177  if( !rval )
1178  {
1179  H5Gclose( tag_id );
1180  return;
1181  }
1182 
1183  H5Gclose( tag_id );
1184  mhdf_setOkay( status );
1185  API_END;
1186 }
1187 
1188 int mhdf_haveDenseTag( mhdf_FileHandle file_handle, const char* tag_name, const char* type_handle, mhdf_Status* status )
1189 {
1190  char* path;
1191  hid_t elem_id, group_id;
1192  FileHandle* file_ptr;
1193  int rval = 0;
1194  API_BEGIN;
1195 
1196  file_ptr = (FileHandle*)file_handle;
1197  if( !mhdf_check_valid_file( file_ptr, status ) ) return -1;
1198 
1199  if( type_handle == mhdf_node_type_handle() )
1200  {
1201 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
1202  elem_id = H5Gopen2( file_ptr->hdf_handle, NODE_GROUP, H5P_DEFAULT );
1203 #else
1204  elem_id = H5Gopen( file_ptr->hdf_handle, NODE_GROUP );
1205 #endif
1206  if( elem_id < 0 ) mhdf_setFail( status, "Could not open node group." );
1207  }
1208  else if( type_handle == mhdf_set_type_handle() )
1209  {
1210 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
1211  elem_id = H5Gopen2( file_ptr->hdf_handle, SET_GROUP, H5P_DEFAULT );
1212 #else
1213  elem_id = H5Gopen( file_ptr->hdf_handle, SET_GROUP );
1214 #endif
1215  if( elem_id < 0 ) mhdf_setFail( status, "Could not open set group." );
1216  }
1217  else
1218  {
1219  elem_id = mhdf_elem_group_from_handle( file_ptr, type_handle, status );
1220  }
1221  if( elem_id < 0 ) return -1;
1222 
1223  rval = mhdf_is_in_group( elem_id, TAG_GROUP_NAME, status );
1224  if( rval < 0 )
1225  {
1226  H5Gclose( elem_id );
1227  return -1;
1228  }
1229  else if( rval == 0 )
1230  {
1231  H5Gclose( elem_id );
1232  mhdf_setOkay( status );
1233  return 0;
1234  }
1235 
1236 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
1237  group_id = H5Gopen2( elem_id, DENSE_TAG_SUBGROUP, H5P_DEFAULT );
1238 #else
1239  group_id = H5Gopen( elem_id, DENSE_TAG_SUBGROUP );
1240 #endif
1241  H5Gclose( elem_id );
1242  if( group_id < 0 )
1243  {
1244  mhdf_setFail( status, "Could not open tag subgroup." );
1245  return -1;
1246  }
1247 
1248  path = mhdf_name_to_path_copy( tag_name, status );
1249  if( NULL == path )
1250  {
1251  H5Gclose( group_id );
1252  return -1;
1253  }
1254 
1255  rval = mhdf_is_in_group( group_id, path, status );
1256  H5Gclose( group_id );
1257  free( path );
1258 
1259  if( rval >= 0 )
1260  {
1261  mhdf_setOkay( status );
1262  }
1263 
1264  API_END;
1265  return rval;
1266 }
1267 
1269  const char* tag_name,
1270  const char* type_handle,
1271  long num_values,
1272  mhdf_Status* status )
1273 {
1274  char* path;
1275  hid_t elem_id, data_id, type_id;
1276  FileHandle* file_ptr;
1277  size_t name_len, path_len, dir_len;
1278  hsize_t size;
1279  API_BEGIN;
1280 
1281  file_ptr = (FileHandle*)file_handle;
1282  if( !mhdf_check_valid_file( file_ptr, status ) ) return -1;
1283 
1284  if( type_handle == mhdf_node_type_handle() )
1285  {
1286 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
1287  elem_id = H5Gopen2( file_ptr->hdf_handle, NODE_GROUP, H5P_DEFAULT );
1288 #else
1289  elem_id = H5Gopen( file_ptr->hdf_handle, NODE_GROUP );
1290 #endif
1291  if( elem_id < 0 ) mhdf_setFail( status, "Could not open node group." );
1292  }
1293  else if( type_handle == mhdf_set_type_handle() )
1294  {
1295 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
1296  elem_id = H5Gopen2( file_ptr->hdf_handle, SET_GROUP, H5P_DEFAULT );
1297 #else
1298  elem_id = H5Gopen( file_ptr->hdf_handle, SET_GROUP );
1299 #endif
1300  if( elem_id < 0 ) mhdf_setFail( status, "Could not open set group." );
1301  }
1302  else
1303  {
1304  elem_id = mhdf_elem_group_from_handle( file_ptr, type_handle, status );
1305  }
1306  if( elem_id < 0 ) return -1;
1307 
1308  dir_len = strlen( DENSE_TAG_SUBGROUP );
1309  name_len = mhdf_name_to_path( tag_name, NULL, 0 );
1310  path_len = dir_len + name_len + 1;
1311  path = (char*)mhdf_malloc( path_len, status );
1312  if( NULL == path )
1313  {
1314  H5Gclose( elem_id );
1315  return -1;
1316  }
1317  strcpy( path, DENSE_TAG_SUBGROUP );
1318  mhdf_name_to_path( tag_name, path + dir_len, name_len + 1 );
1319 
1320  type_id = get_tag_type( file_ptr, path + dir_len, status );
1321  if( type_id < 0 )
1322  {
1323  H5Gclose( elem_id );
1324  return -1;
1325  }
1326 
1327  size = (hsize_t)num_values;
1328  data_id = mhdf_create_table( elem_id, path, type_id, 1, &size, status );
1329  free( path );
1330  H5Gclose( elem_id );
1331  H5Tclose( type_id );
1332 
1333  if( data_id > 0 ) mhdf_setOkay( status );
1334 
1335  API_END_H( 1 );
1336  return data_id;
1337 }
1338 
1340  const char* tag_name,
1341  const char* type_handle,
1342  long* num_values_out,
1343  mhdf_Status* status )
1344 {
1345  char* path;
1346  hid_t elem_id, data_id;
1347  FileHandle* file_ptr;
1348  size_t name_len, path_len, dir_len;
1349  hsize_t size;
1350  API_BEGIN;
1351 
1352  file_ptr = (FileHandle*)file_handle;
1353  if( !mhdf_check_valid_file( file_ptr, status ) ) return -1;
1354 
1355  if( type_handle == mhdf_node_type_handle() )
1356  {
1357 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
1358  elem_id = H5Gopen2( file_ptr->hdf_handle, NODE_GROUP, H5P_DEFAULT );
1359 #else
1360  elem_id = H5Gopen( file_ptr->hdf_handle, NODE_GROUP );
1361 #endif
1362  if( elem_id < 0 ) mhdf_setFail( status, "Could not open node group." );
1363  }
1364  else if( type_handle == mhdf_set_type_handle() )
1365  {
1366 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
1367  elem_id = H5Gopen2( file_ptr->hdf_handle, SET_GROUP, H5P_DEFAULT );
1368 #else
1369  elem_id = H5Gopen( file_ptr->hdf_handle, SET_GROUP );
1370 #endif
1371  if( elem_id < 0 ) mhdf_setFail( status, "Could not open set group." );
1372  }
1373  else
1374  {
1375  elem_id = mhdf_elem_group_from_handle( file_ptr, type_handle, status );
1376  }
1377  if( elem_id < 0 ) return -1;
1378 
1379  dir_len = strlen( DENSE_TAG_SUBGROUP );
1380  name_len = mhdf_name_to_path( tag_name, NULL, 0 );
1381  path_len = dir_len + name_len + 1;
1382  path = (char*)mhdf_malloc( path_len, status );
1383  if( NULL == path )
1384  {
1385  H5Gclose( elem_id );
1386  return -1;
1387  }
1388  strcpy( path, DENSE_TAG_SUBGROUP );
1389  mhdf_name_to_path( tag_name, path + dir_len, name_len + 1 );
1390 
1391  data_id = mhdf_open_table( elem_id, path, 1, &size, status );
1392  free( path );
1393  H5Gclose( elem_id );
1394  *num_values_out = (long)size;
1395 
1396  if( data_id >= 0 ) mhdf_setOkay( status );
1397 
1398  API_END_H( 1 );
1399  return data_id;
1400 }
1401 
1403  const char* tag_name,
1404  long num_values,
1405  hid_t handles_out[2],
1406  mhdf_Status* status )
1407 {
1408  hid_t tag_id, index_id, data_id, type_id, id_type;
1409  hsize_t count = (hsize_t)num_values;
1410  API_BEGIN;
1411 
1412  tag_id = get_tag( file_handle, tag_name, &id_type, status );
1413  if( tag_id < 0 ) return;
1414 
1415 #if defined( H5Topen_vers ) && H5Topen_vers > 1
1416  type_id = H5Topen2( tag_id, TAG_TYPE_NAME, H5P_DEFAULT );
1417 #else
1418  type_id = H5Topen( tag_id, TAG_TYPE_NAME );
1419 #endif
1420  if( type_id < 0 )
1421  {
1422  H5Gclose( tag_id );
1423  mhdf_setFail( status, "Failed to get type object for tag \"%s\".", tag_name );
1424  return;
1425  }
1426 
1427  index_id = mhdf_create_table( tag_id, SPARSE_ENTITY_NAME, id_type, 1, &count, status );
1428  if( index_id < 0 )
1429  {
1430  H5Gclose( tag_id );
1431  H5Tclose( type_id );
1432  return;
1433  }
1434 
1435  data_id = mhdf_create_table( tag_id, SPARSE_VALUES_NAME, type_id, 1, &count, status );
1436  H5Tclose( type_id );
1437  H5Gclose( tag_id );
1438  if( data_id < 0 )
1439  {
1440  H5Dclose( index_id );
1441  return;
1442  }
1443 
1444  handles_out[0] = index_id;
1445  handles_out[1] = data_id;
1446  mhdf_setOkay( status );
1447  API_END_H( 2 );
1448 }
1449 
1451  const char* tag_name,
1452  long num_entities,
1453  long num_values,
1454  hid_t handles_out[3],
1455  mhdf_Status* status )
1456 {
1457  hid_t tag_id, index_id, data_id, type_id, offset_id, id_type;
1458  hsize_t count = (hsize_t)num_entities;
1459  API_BEGIN;
1460 
1461  tag_id = get_tag( file_handle, tag_name, &id_type, status );
1462  if( tag_id < 0 ) return;
1463 
1464 #if defined( H5Topen_vers ) && H5Topen_vers > 1
1465  type_id = H5Topen2( tag_id, TAG_TYPE_NAME, H5P_DEFAULT );
1466 #else
1467  type_id = H5Topen( tag_id, TAG_TYPE_NAME );
1468 #endif
1469  if( type_id < 0 )
1470  {
1471  H5Gclose( tag_id );
1472  mhdf_setFail( status, "Failed to get type object for tag \"%s\".", tag_name );
1473  return;
1474  }
1475 
1476  index_id = mhdf_create_table( tag_id, SPARSE_ENTITY_NAME, id_type, 1, &count, status );
1477  if( index_id < 0 )
1478  {
1479  H5Gclose( tag_id );
1480  H5Tclose( type_id );
1481  return;
1482  }
1483 
1484  offset_id = mhdf_create_table( tag_id, TAG_VAR_INDICES, MHDF_INDEX_TYPE, 1, &count, status );
1485  if( index_id < 0 )
1486  {
1487  H5Dclose( offset_id );
1488  H5Gclose( tag_id );
1489  H5Tclose( type_id );
1490  return;
1491  }
1492 
1493  count = (hsize_t)num_values;
1494  data_id = mhdf_create_table( tag_id, SPARSE_VALUES_NAME, type_id, 1, &count, status );
1495  H5Tclose( type_id );
1496  H5Gclose( tag_id );
1497  if( data_id < 0 )
1498  {
1499  H5Dclose( offset_id );
1500  H5Dclose( index_id );
1501  return;
1502  }
1503 
1504  handles_out[0] = index_id;
1505  handles_out[1] = data_id;
1506  handles_out[2] = offset_id;
1507  mhdf_setOkay( status );
1508  API_END_H( 3 );
1509 }
1510 
1512  const char* tag_name,
1513  long* num_entity_out,
1514  long* num_values_out,
1515  hid_t handles_out[3],
1516  mhdf_Status* status )
1517 {
1518  hid_t tag_id, index_id, data_id, offset_id = -1;
1519  hsize_t num_ent, data_size, num_data;
1520  int rval;
1521  unsigned idx;
1522  API_BEGIN;
1523 
1524  tag_id = get_tag( file_handle, tag_name, NULL, status );
1525  if( tag_id < 0 ) return;
1526 
1527  index_id = mhdf_open_table( tag_id, SPARSE_ENTITY_NAME, 1, &num_ent, status );
1528  if( index_id < 0 )
1529  {
1530  H5Gclose( tag_id );
1531  return;
1532  }
1533 
1534  data_id = mhdf_open_table( tag_id, SPARSE_VALUES_NAME, 1, &data_size, status );
1535  if( data_id < 0 )
1536  {
1537  H5Gclose( tag_id );
1538  H5Dclose( index_id );
1539  return;
1540  }
1541 
1542  /* check if tag is variable-lentgth */
1543  rval = mhdf_find_attribute( tag_id, TAG_VARLEN_ATTRIB, &idx, status );
1544  if( rval < 0 )
1545  {
1546  H5Gclose( tag_id );
1547  H5Dclose( index_id );
1548  H5Dclose( data_id );
1549  return;
1550  }
1551 
1552  /* If variable length... */
1553  if( rval )
1554  {
1555  offset_id = mhdf_open_table( tag_id, TAG_VAR_INDICES, 1, &num_data, status );
1556  if( offset_id < 0 )
1557  {
1558  H5Gclose( tag_id );
1559  H5Dclose( index_id );
1560  H5Dclose( data_id );
1561  return;
1562  }
1563  }
1564  /* Otherwise the number of values is the same as the size of the data table */
1565  else
1566  {
1567  num_data = data_size;
1568  }
1569 
1570  H5Gclose( tag_id );
1571  if( num_ent != num_data )
1572  {
1573  mhdf_setFail( status, "Data length mismatch for sparse tag data -- invalid file." );
1574  if( offset_id >= 0 ) H5Dclose( offset_id );
1575  H5Dclose( index_id );
1576  H5Dclose( data_id );
1577  return;
1578  }
1579  *num_entity_out = (long)num_ent;
1580  if( num_values_out ) *num_values_out = (long)data_size;
1581 
1582  handles_out[0] = index_id;
1583  handles_out[1] = data_id;
1584  if( offset_id >= 0 ) handles_out[2] = offset_id;
1585  mhdf_setOkay( status );
1586  API_END_H( 2 );
1587 }
1588 
1589 void mhdf_writeSparseTagEntities( hid_t table_id,
1590  long offset,
1591  long count,
1592  hid_t int_type,
1593  const void* id_list,
1594  mhdf_Status* status )
1595 {
1596  API_BEGIN;
1597  mhdf_write_data( table_id, offset, count, int_type, id_list, H5P_DEFAULT, status );
1598  API_END;
1599 }
1601  long offset,
1602  long count,
1603  hid_t int_type,
1604  const void* id_list,
1605  hid_t io_prop,
1606  mhdf_Status* status )
1607 {
1608  API_BEGIN;
1609  mhdf_write_data( table_id, offset, count, int_type, id_list, io_prop, status );
1610  API_END;
1611 }
1612 
1613 void mhdf_writeTagValues( hid_t table_id,
1614  long offset,
1615  long count,
1616  hid_t tag_type,
1617  const void* tag_data,
1618  mhdf_Status* status )
1619 {
1620  mhdf_writeTagValuesWithOpt( table_id, offset, count, tag_type, tag_data, H5P_DEFAULT, status );
1621 }
1622 
1623 void mhdf_writeTagValuesWithOpt( hid_t table_id,
1624  long offset,
1625  long count,
1626  hid_t tag_type,
1627  const void* tag_data,
1628  hid_t io_prop,
1629  mhdf_Status* status )
1630 {
1631  API_BEGIN;
1632  mhdf_write_data( table_id, offset, count, tag_type, tag_data, io_prop, status );
1633  API_END;
1634 }
1635 
1636 void mhdf_writeSparseTagIndices( hid_t table_id,
1637  long offset,
1638  long count,
1639  hid_t int_type,
1640  const void* indices,
1641  mhdf_Status* status )
1642 {
1643  API_BEGIN;
1644  mhdf_write_data( table_id, offset, count, int_type, indices, H5P_DEFAULT, status );
1645  API_END;
1646 }
1648  long offset,
1649  long count,
1650  hid_t int_type,
1651  const void* indices,
1652  hid_t io_prop,
1653  mhdf_Status* status )
1654 {
1655  API_BEGIN;
1656  mhdf_write_data( table_id, offset, count, int_type, indices, io_prop, status );
1657  API_END;
1658 }
1659 
1660 void mhdf_readSparseTagEntities( hid_t table_id,
1661  long offset,
1662  long count,
1663  hid_t int_type,
1664  void* id_list,
1665  mhdf_Status* status )
1666 {
1667  API_BEGIN;
1668  mhdf_read_data( table_id, offset, count, int_type, id_list, H5P_DEFAULT, status );
1669  API_END;
1670 }
1672  long offset,
1673  long count,
1674  hid_t int_type,
1675  void* id_list,
1676  hid_t io_prop,
1677  mhdf_Status* status )
1678 {
1679  API_BEGIN;
1680  mhdf_read_data( table_id, offset, count, int_type, id_list, io_prop, status );
1681  API_END;
1682 }
1683 
1684 void mhdf_readTagValues( hid_t table_id, long offset, long count, hid_t tag_type, void* tag_data, mhdf_Status* status )
1685 {
1686  mhdf_readTagValuesWithOpt( table_id, offset, count, tag_type, tag_data, H5P_DEFAULT, status );
1687 }
1688 void mhdf_readTagValuesWithOpt( hid_t table_id,
1689  long offset,
1690  long count,
1691  hid_t tag_type,
1692  void* tag_data,
1693  hid_t io_prop,
1694  mhdf_Status* status )
1695 {
1696  API_BEGIN;
1697  mhdf_read_data( table_id, offset, count, tag_type, tag_data, io_prop, status );
1698  API_END;
1699 }
1700 
1701 void mhdf_readSparseTagIndices( hid_t table_id,
1702  long offset,
1703  long count,
1704  hid_t int_type,
1705  void* indices,
1706  mhdf_Status* status )
1707 {
1708  API_BEGIN;
1709  mhdf_read_data( table_id, offset, count, int_type, indices, H5P_DEFAULT, status );
1710  API_END;
1711 }
1713  long offset,
1714  long count,
1715  hid_t int_type,
1716  void* indices,
1717  hid_t io_prop,
1718  mhdf_Status* status )
1719 {
1720  API_BEGIN;
1721  mhdf_read_data( table_id, offset, count, int_type, indices, io_prop, status );
1722  API_END;
1723 }