MOAB: Mesh Oriented datABase  (version 5.2.1)
tags.c
Go to the documentation of this file.
00001 /**
00002  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
00003  * storing and accessing finite element mesh data.
00004  *
00005  * Copyright 2004 Sandia Corporation.  Under the terms of Contract
00006  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
00007  * retains certain rights in this software.
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  */
00015 
00016 #include <stdlib.h>
00017 #include <string.h>
00018 #include <H5Tpublic.h>
00019 #include <H5Gpublic.h>
00020 #include <H5Dpublic.h>
00021 #include <H5Spublic.h> /* for H5S_MAX_RANK */
00022 #include <H5Apublic.h>
00023 #include <H5Ppublic.h>
00024 #include "status.h"
00025 #include "file-handle.h"
00026 #include "mhdf.h"
00027 #include "util.h"
00028 #include "names-and-paths.h"
00029 
00030 hid_t mhdf_getNativeType( hid_t input_type, int size, mhdf_Status* status )
00031 {
00032     H5T_sign_t  sgn;
00033     H5T_class_t cls;
00034     hid_t       tmp_id, type_id;
00035 
00036     mhdf_setOkay( status );
00037 
00038     cls = H5Tget_class( input_type );
00039     switch( cls )
00040     {
00041         case H5T_FLOAT:
00042             switch( size )
00043             {
00044                 case 4:
00045                     return H5T_NATIVE_FLOAT;
00046                 case 8:
00047                     return H5T_NATIVE_DOUBLE;
00048                 case 16:
00049                     return H5T_NATIVE_LDOUBLE;
00050                 default:
00051                     mhdf_setFail( status, "Invalid size for floating point type: %d", size );
00052                     return -1;
00053             }
00054 
00055         case H5T_INTEGER:
00056             sgn = H5Tget_sign( input_type );
00057             if( H5T_SGN_ERROR == sgn )
00058             {
00059                 mhdf_setFail( status, "Internall errror calling H5Tget_sign." );
00060                 return -1;
00061             }
00062             if( sizeof( char ) == size )
00063                 return sgn == H5T_SGN_NONE ? H5T_NATIVE_UCHAR : H5T_NATIVE_SCHAR;
00064             else if( sizeof( short ) == size )
00065                 return sgn == H5T_SGN_NONE ? H5T_NATIVE_USHORT : H5T_NATIVE_SHORT;
00066             else if( sizeof( int ) == size )
00067                 return sgn == H5T_SGN_NONE ? H5T_NATIVE_UINT : H5T_NATIVE_INT;
00068             else if( sizeof( long ) == size )
00069                 return sgn == H5T_SGN_NONE ? H5T_NATIVE_ULONG : H5T_NATIVE_LONG;
00070             else if( (int)H5Tget_size( H5T_NATIVE_LLONG ) == size )
00071                 return sgn == H5T_SGN_NONE ? H5T_NATIVE_ULLONG : H5T_NATIVE_LLONG;
00072 
00073             mhdf_setFail( status, "Invalid size for integer type: %d", size );
00074             return -1;
00075 
00076         case H5T_ENUM:
00077             tmp_id = H5Tget_super( input_type );
00078             if( tmp_id < 0 )
00079             {
00080                 mhdf_setFail( status, "Internal error calling H5Tget_super." );
00081                 return -1;
00082             }
00083             type_id = mhdf_getNativeType( tmp_id, size, status );
00084             H5Tclose( tmp_id );
00085             return type_id;
00086 
00087         case H5T_TIME:
00088         case H5T_OPAQUE:
00089         case H5T_REFERENCE:
00090             mhdf_setFail( status, "Unsupported type class." );
00091             return -1;
00092 
00093         case H5T_COMPOUND:
00094         case H5T_VLEN:
00095         case H5T_ARRAY:
00096         case H5T_STRING:
00097             mhdf_setFail( status, "Only atomic types are supported." );
00098             return -1;
00099 
00100         default:
00101             mhdf_setFail( status, "Internal error calling H5Tget_class.  Bad handle?" );
00102             return -1;
00103     }
00104 }
00105 
00106 static hid_t get_tag( mhdf_FileHandle file_handle, const char* tag_name, hid_t* id_type, mhdf_Status* status )
00107 {
00108     hid_t       group_id, tag_id;
00109     char*       path;
00110     FileHandle* file_ptr;
00111 
00112     file_ptr = (FileHandle*)file_handle;
00113     if( !mhdf_check_valid_file( file_ptr, status ) ) return -1;
00114 
00115     if( NULL != id_type ) *id_type = file_ptr->id_type;
00116 
00117     path = mhdf_name_to_path_copy( tag_name, status );
00118     if( NULL == path ) return -1;
00119 
00120 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
00121     group_id = H5Gopen2( file_ptr->hdf_handle, TAG_GROUP, H5P_DEFAULT );
00122 #else
00123     group_id = H5Gopen( file_ptr->hdf_handle, TAG_GROUP );
00124 #endif
00125     if( group_id < 0 )
00126     {
00127         mhdf_setFail( status, "Failed to open tag group." );
00128         free( path );
00129         return -1;
00130     }
00131 
00132 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
00133     tag_id = H5Gopen2( group_id, path, H5P_DEFAULT );
00134 #else
00135     tag_id = H5Gopen( group_id, path );
00136 #endif
00137     H5Gclose( group_id );
00138     free( path );
00139     if( tag_id < 0 )
00140     {
00141         mhdf_setFail( status, "Failed to open tag data for tag \"%s\".", tag_name );
00142         return -1;
00143     }
00144 
00145     mhdf_setOkay( status );
00146     return tag_id;
00147 }
00148 
00149 static hid_t get_tag_type( FileHandle* file_ptr, const char* tag_path, mhdf_Status* status )
00150 {
00151     hid_t group_id, tag_id, type_id;
00152 
00153 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
00154     group_id = H5Gopen2( file_ptr->hdf_handle, TAG_GROUP, H5P_DEFAULT );
00155 #else
00156     group_id = H5Gopen( file_ptr->hdf_handle, TAG_GROUP );
00157 #endif
00158     if( group_id < 0 )
00159     {
00160         mhdf_setFail( status, "Failed to open tag group." );
00161         return -1;
00162     }
00163 
00164 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
00165     tag_id = H5Gopen2( group_id, tag_path, H5P_DEFAULT );
00166 #else
00167     tag_id = H5Gopen( group_id, tag_path );
00168 #endif
00169     H5Gclose( group_id );
00170     if( tag_id < 0 )
00171     {
00172         mhdf_setFail( status, "Failed to open group for tag \"%s\".", tag_path );
00173         return -1;
00174     }
00175 
00176 #if defined( H5Topen_vers ) && H5Topen_vers > 1
00177     type_id = H5Topen2( tag_id, TAG_TYPE_NAME, H5P_DEFAULT );
00178 #else
00179     type_id = H5Topen( tag_id, TAG_TYPE_NAME );
00180 #endif
00181     H5Gclose( tag_id );
00182     if( type_id < 0 )
00183     {
00184         mhdf_setFail( status, "Failed to open type data for tag \"%s\".", tag_path );
00185         return -1;
00186     }
00187 
00188     return type_id;
00189 }
00190 
00191 /** Helper function to write default and mesh values for tag
00192  *\param tag_id       The file object upon which to attach the attribute
00193  *\param attrib_name  The name of the attribute object
00194  *\param type_id      The data type of the attribute data
00195  *\param value        Pointer to attribute data
00196  *\param value_size   Size of attribute data, as multiple of type indicated
00197  *                    by type_id.  Should be 1 except for variable-length tag data.
00198  */
00199 static int store_tag_val_in_attrib( hid_t tag_id, const char* attrib_name, hid_t type_id, const void* value,
00200                                     hsize_t value_size, mhdf_Status* status )
00201 {
00202     hid_t write_type;
00203     int   rval;
00204     if( value_size == 1 )
00205         write_type = type_id;
00206     else if( H5Tget_class( type_id ) == H5T_OPAQUE )
00207     {
00208         write_type = H5Tcreate( H5T_OPAQUE, value_size );
00209     }
00210     else
00211     {
00212 #if defined( H5Tarray_create_vers ) && H5Tarray_create_vers > 1
00213         write_type = H5Tarray_create2( type_id, 1, &value_size );
00214 #else
00215         write_type = H5Tarray_create( type_id, 1, &value_size, 0 );
00216 #endif
00217     }
00218 
00219     if( write_type < 0 )
00220     {
00221         mhdf_setFail( status, "Error constructing type object for tag mesh/default value" );
00222         return -1;
00223     }
00224 
00225     rval = mhdf_create_scalar_attrib( tag_id, attrib_name, write_type, value, status );
00226     if( write_type != type_id ) H5Tclose( write_type );
00227 
00228     return rval;
00229 }
00230 
00231 static hid_t create_tag_common( mhdf_FileHandle file_handle, const char* tag_name, enum mhdf_TagDataType tag_type,
00232                                 int size, int storage, const void* default_value, int default_value_size_in,
00233                                 const void* global_value, int global_value_size_in, hid_t hdf_type, hid_t hdf_base_type,
00234                                 mhdf_Status* status )
00235 {
00236     hid_t       temp_id, group_id, tag_id;
00237     char*       path;
00238     FileHandle* file_ptr;
00239     herr_t      rval;
00240     hsize_t     arr_len;
00241     int         one = 1, var_len = 0;
00242     hsize_t     default_value_size = default_value_size_in;
00243     hsize_t     global_value_size = global_value_size_in;
00244     int         close_base_type = 0;
00245 
00246     /* Force standard data types over user-specified types */
00247 
00248     if( tag_type != mhdf_OPAQUE ) hdf_type = 0;
00249     if( tag_type != mhdf_ENTITY_ID ) hdf_base_type = 0;
00250 
00251     /* Validate input */
00252 
00253     file_ptr = (FileHandle*)file_handle;
00254     if( !mhdf_check_valid_file( file_ptr, status ) ) return -1;
00255 
00256     if( !tag_name || !*tag_name )
00257     {
00258         mhdf_setFail( status, "Invalid tag name" );
00259         return -1;
00260     }
00261 
00262     /* Open the tag group */
00263 
00264 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
00265     group_id = H5Gopen2( file_ptr->hdf_handle, TAG_GROUP, H5P_DEFAULT );
00266 #else
00267     group_id = H5Gopen( file_ptr->hdf_handle, TAG_GROUP );
00268 #endif
00269     if( group_id < 0 )
00270     {
00271         mhdf_setFail( status, "H5Gopen(\"%s\") failed.", TAG_GROUP );
00272         return -1;
00273     }
00274 
00275     /* Create path string for tag object */
00276 
00277     path = mhdf_name_to_path_copy( tag_name, status );
00278     if( !path )
00279     {
00280         H5Gclose( group_id );
00281         return -1;
00282     }
00283 
00284     /* Create group for this tag */
00285 
00286 #if defined( H5Gcreate_vers ) && H5Gcreate_vers > 1
00287     tag_id = H5Gcreate2( group_id, path, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
00288 #else
00289     tag_id = H5Gcreate( group_id, path, 3 );
00290 #endif
00291     if( tag_id < 0 )
00292     {
00293         mhdf_setFail( status, "H5Gcreate( \"%s\" ) failed.", path );
00294         free( path );
00295         H5Gclose( group_id );
00296         return -1;
00297     }
00298 
00299     /* Store the tag name as the comment on the group entry */
00300 
00301     rval = H5Gset_comment( group_id, path, tag_name );
00302     H5Gclose( group_id );
00303     free( path );
00304     if( rval < 0 )
00305     {
00306         mhdf_setFail( status, "H5Gset_comment failed for tag \"%s\"", tag_name );
00307         H5Gclose( tag_id );
00308         return -1;
00309     }
00310 
00311     /* Store TSTT tag type as attribute */
00312 
00313     rval = mhdf_create_scalar_attrib( tag_id, TAG_TYPE_ATTRIB, H5T_NATIVE_INT, &storage, status );
00314     if( !rval )
00315     {
00316         H5Gclose( tag_id );
00317         return -1;
00318     }
00319 
00320     if( hdf_type )
00321     {
00322         hdf_type = H5Tcopy( hdf_type );
00323         arr_len = 1;
00324     }
00325     else
00326     {
00327         switch( tag_type )
00328         {
00329             default:
00330             case mhdf_OPAQUE:
00331                 arr_len = 1;
00332                 hdf_type = H5Tcreate( H5T_OPAQUE, abs( size ) );
00333                 H5Tset_tag( hdf_type, "tag_data" );
00334                 break;
00335 
00336             case mhdf_BITFIELD:
00337                 arr_len = 1;
00338                 if( size <= 0 )
00339                 {
00340                     mhdf_setFail( status, "Invalid size (%d) for bit tag.", (int)size );
00341                     return -1;
00342                 }
00343                 else if( size <= 8 )
00344                     hdf_type = H5Tcopy( H5T_NATIVE_B8 );
00345                 else if( size <= 16 )
00346                     hdf_type = H5Tcopy( H5T_NATIVE_B16 );
00347                 else if( size <= 32 )
00348                     hdf_type = H5Tcopy( H5T_NATIVE_B32 );
00349                 else if( size <= 64 )
00350                     hdf_type = H5Tcopy( H5T_NATIVE_B64 );
00351                 else
00352                 {
00353                     mhdf_setFail( status, "Cannot create a bit tag larger than 64-bits.  %d bits requested.\n",
00354                                   (int)size );
00355                     return -1;
00356                 }
00357 
00358                 if( 0 > H5Tset_precision( hdf_type, size ) )
00359                 {
00360                     mhdf_setFail( status, "H5Tset_precision failed." );
00361                     return -1;
00362                 }
00363                 break;
00364 
00365             case mhdf_ENTITY_ID:
00366                 arr_len = abs( size );
00367                 hdf_type = H5Tcopy( H5T_NATIVE_ULONG );
00368                 break;
00369 
00370             case mhdf_BOOLEAN:
00371                 arr_len = abs( size );
00372                 hdf_type = H5Tcopy( H5T_NATIVE_UCHAR );
00373                 break;
00374 
00375             case mhdf_INTEGER:
00376                 arr_len = abs( size );
00377                 hdf_type = H5Tcopy( H5T_NATIVE_INT );
00378                 break;
00379 
00380             case mhdf_FLOAT:
00381                 arr_len = abs( size );
00382                 hdf_type = H5Tcopy( H5T_NATIVE_DOUBLE );
00383                 break;
00384         }
00385     }
00386 
00387     if( hdf_type <= 0 )
00388     {
00389         mhdf_setFail( status, "Failed to create tag type object." );
00390         H5Gclose( tag_id );
00391         return -1;
00392     }
00393 
00394     if( hdf_base_type && H5Tget_class( hdf_type ) != H5Tget_class( hdf_base_type ) )
00395     {
00396         mhdf_setFail( status, "Invalid base type for tag default/global data" );
00397         H5Gclose( tag_id );
00398         return -1;
00399     }
00400 
00401     if( size < -1 || !arr_len )
00402     {
00403         mhdf_setFail( status, "Invalid 'size' parameter passed to mhdf_createTag (%d)", (int)size );
00404         H5Gclose( tag_id );
00405         return -1;
00406     }
00407     else if( size == -1 )
00408     {
00409         /* Note: we don't do anything with this here.  We rely on
00410          *       the app to ask us to create the index table later.
00411          */
00412         arr_len = 1;
00413         /* need to know this later, when storing default/global values */
00414         var_len = 1;
00415     }
00416     else if( arr_len > 1 )
00417     {
00418 #if defined( H5Tarray_create_vers ) && H5Tarray_create_vers > 1
00419         temp_id = H5Tarray_create2( hdf_type, 1, &arr_len );
00420 #else
00421         temp_id = H5Tarray_create( hdf_type, 1, &arr_len, NULL );
00422 #endif
00423         H5Tclose( hdf_type );
00424         if( temp_id < 0 )
00425         {
00426             mhdf_setFail( status, "Failed to create tag type object." );
00427             H5Gclose( tag_id );
00428             return -1;
00429         }
00430         hdf_type = temp_id;
00431 
00432         if( hdf_base_type )
00433         {
00434             if( H5Tequal( hdf_base_type, hdf_type ) > 0 ) { hdf_base_type = hdf_type; }
00435             else
00436             {
00437 #if defined( H5Tarray_create_vers ) && H5Tarray_create_vers > 1
00438                 temp_id = H5Tarray_create2( hdf_base_type, 1, &arr_len );
00439 #else
00440                 temp_id = H5Tarray_create( hdf_base_type, 1, &arr_len, NULL );
00441 #endif
00442                 if( temp_id < 0 )
00443                 {
00444                     mhdf_setFail( status, "Failed to create tag type object." );
00445                     H5Gclose( tag_id );
00446                     H5Tclose( hdf_type );
00447                     return -1;
00448                 }
00449                 hdf_base_type = temp_id;
00450                 close_base_type = 1;
00451             }
00452         }
00453     }
00454 
00455     if( !hdf_base_type ) hdf_base_type = hdf_type;
00456 
00457         /* Create tag type object, or write attribute if opaque */
00458 
00459 #if defined( H5Tcommit_vers ) && H5Tcommit_vers > 1
00460     rval = H5Tcommit2( tag_id, TAG_TYPE_NAME, hdf_type, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
00461 #else
00462     rval = H5Tcommit( tag_id, TAG_TYPE_NAME, hdf_type );
00463 #endif
00464     if( rval < 0 )
00465     {
00466         mhdf_setFail( status, "H5Tcommit failed for tag \"%s\"", tag_name );
00467         if( close_base_type ) H5Tclose( hdf_base_type );
00468         H5Tclose( hdf_type );
00469         H5Gclose( tag_id );
00470         return -1;
00471     }
00472 
00473     /* If tag is entity handle, make note of it */
00474     if( tag_type == mhdf_ENTITY_ID )
00475     {
00476         rval = mhdf_create_scalar_attrib( tag_id, TAG_HANDLE_TYPE_ATTRIB, H5T_NATIVE_INT, &one, status );
00477         if( !rval )
00478         {
00479             if( close_base_type ) H5Tclose( hdf_base_type );
00480             H5Gclose( tag_id );
00481             H5Tclose( hdf_type );
00482             return -1;
00483         }
00484     }
00485 
00486     /* Store the default value as a attribute of the tag group */
00487 
00488     if( default_value )
00489     {
00490         rval = store_tag_val_in_attrib( tag_id, TAG_DEFAULT_ATTRIB, hdf_base_type, default_value,
00491                                         var_len ? default_value_size : 1, status );
00492         if( !rval )
00493         {
00494             if( close_base_type ) H5Tclose( hdf_base_type );
00495             H5Gclose( tag_id );
00496             H5Tclose( hdf_type );
00497             return -1;
00498         }
00499     }
00500 
00501     /* Store global tag value as attribute */
00502 
00503     if( global_value )
00504     {
00505         rval = store_tag_val_in_attrib( tag_id, TAG_GLOBAL_ATTRIB, hdf_base_type, global_value,
00506                                         var_len ? global_value_size : 1, status );
00507         if( !rval )
00508         {
00509             if( close_base_type ) H5Tclose( hdf_base_type );
00510             H5Gclose( tag_id );
00511             H5Tclose( hdf_type );
00512             return -1;
00513         }
00514     }
00515 
00516     if( close_base_type ) H5Tclose( hdf_base_type );
00517     H5Tclose( hdf_type );
00518     mhdf_setOkay( status );
00519     return tag_id;
00520 }
00521 
00522 hid_t mhdf_getTagDataType( mhdf_FileHandle file_handle, const char* tag_name, mhdf_Status* status )
00523 {
00524     FileHandle* file_ptr;
00525     hid_t       result;
00526     char*       path;
00527     API_BEGIN;
00528 
00529     /* Validate input */
00530 
00531     file_ptr = (FileHandle*)file_handle;
00532     if( !mhdf_check_valid_file( file_ptr, status ) ) return -1;
00533 
00534     if( !tag_name || !*tag_name )
00535     {
00536         mhdf_setFail( status, "Invalid tag name" );
00537         return -1;
00538     }
00539 
00540     /* Create path string for tag object */
00541 
00542     path = mhdf_name_to_path_copy( tag_name, status );
00543     if( !path ) { return -1; }
00544 
00545     result = get_tag_type( file_ptr, path, status );
00546 
00547     free( path );
00548     API_END;
00549     return result;
00550 }
00551 
00552 void mhdf_createTag( mhdf_FileHandle file_handle, const char* tag_name, enum mhdf_TagDataType tag_type, int size,
00553                      int storage, const void* default_value, const void* global_value, hid_t hdf_type,
00554                      hid_t hdf_base_type, mhdf_Status* status )
00555 {
00556     hid_t tag_id;
00557     API_BEGIN;
00558     tag_id = create_tag_common( file_handle, tag_name, tag_type, size, storage, default_value, 1, global_value, 1,
00559                                 hdf_type, hdf_base_type, status );
00560     if( tag_id >= 0 ) H5Gclose( tag_id );
00561     API_END;
00562 }
00563 
00564 void mhdf_createVarLenTag( mhdf_FileHandle file_handle, const char* tag_name, enum mhdf_TagDataType tag_type,
00565                            int storage, const void* default_value, int default_value_length, const void* global_value,
00566                            int global_value_length, hid_t hdf_type, hid_t hdf_base_type, mhdf_Status* status )
00567 {
00568     hid_t tag_id;
00569     int   one = 1;
00570 
00571     API_BEGIN;
00572     tag_id = create_tag_common( file_handle, tag_name, tag_type, -1, storage, default_value, default_value_length,
00573                                 global_value, global_value_length, hdf_type, hdf_base_type, status );
00574     if( tag_id >= 0 )
00575     {
00576         mhdf_create_scalar_attrib( tag_id, TAG_VARLEN_ATTRIB, H5T_NATIVE_INT, &one, status );
00577         H5Gclose( tag_id );
00578     }
00579     API_END;
00580 }
00581 
00582 int mhdf_getNumberTags( mhdf_FileHandle file_handle, mhdf_Status* status )
00583 {
00584     hid_t       group_id;
00585     hsize_t     result;
00586     FileHandle* file_ptr;
00587     API_BEGIN;
00588 
00589     /* Validate input */
00590 
00591     file_ptr = (FileHandle*)file_handle;
00592     if( !mhdf_check_valid_file( file_ptr, status ) ) return -1;
00593 
00594         /* Open the tags group */
00595 
00596 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
00597     group_id = H5Gopen2( file_ptr->hdf_handle, TAG_GROUP, H5P_DEFAULT );
00598 #else
00599     group_id = H5Gopen( file_ptr->hdf_handle, TAG_GROUP );
00600 #endif
00601     if( group_id < 0 )
00602     {
00603         mhdf_setFail( status, "H5Gopen(\"%s\") failed", TAG_GROUP );
00604         return -1;
00605     }
00606 
00607     /* Get number of objects in tags group */
00608 
00609     if( H5Gget_num_objs( group_id, &result ) < 0 )
00610     {
00611         mhdf_setFail( status, "Internal failure calling H5Gget_num_objs." );
00612         H5Gclose( group_id );
00613         return -1;
00614     }
00615 
00616     H5Gclose( group_id );
00617     mhdf_setOkay( status );
00618     API_END;
00619     return (int)result;
00620 }
00621 
00622 char** mhdf_getTagNames( mhdf_FileHandle file_handle, int* num_names_out, mhdf_Status* status )
00623 {
00624     hid_t       group_id;
00625     FileHandle* file_ptr;
00626     hsize_t     count, idx;
00627     char*       name;
00628     char**      result;
00629     ssize_t     size;
00630     API_BEGIN;
00631 
00632     /* Validate input */
00633 
00634     file_ptr = (FileHandle*)file_handle;
00635     if( !mhdf_check_valid_file( file_ptr, status ) ) return NULL;
00636 
00637         /* Open the tags group */
00638 
00639 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
00640     group_id = H5Gopen2( file_ptr->hdf_handle, TAG_GROUP, H5P_DEFAULT );
00641 #else
00642     group_id = H5Gopen( file_ptr->hdf_handle, TAG_GROUP );
00643 #endif
00644     if( group_id < 0 )
00645     {
00646         mhdf_setFail( status, "H5Gopen(\"%s\") failed", TAG_GROUP );
00647         return NULL;
00648     }
00649 
00650     /* Get number of objects in tags group */
00651 
00652     if( H5Gget_num_objs( group_id, &count ) < 0 )
00653     {
00654         mhdf_setFail( status, "Internal failure calling H5Gget_num_objs." );
00655         H5Gclose( group_id );
00656         return NULL;
00657     }
00658 
00659     /* No tags? */
00660 
00661     *num_names_out = (int)count;
00662     if( count == 0 )
00663     {
00664         H5Gclose( group_id );
00665         mhdf_setOkay( status );
00666         return NULL;
00667     }
00668 
00669     /* Allocate string array */
00670 
00671     result = (char**)mhdf_malloc( sizeof( char* ) * count, status );
00672     if( NULL == result )
00673     {
00674         H5Gclose( group_id );
00675         return NULL;
00676     }
00677 
00678     /* Get names */
00679 
00680     for( idx = 0; idx < count; ++idx )
00681     {
00682         size = H5Gget_objname_by_idx( group_id, idx, NULL, 0 );
00683         if( size < 1 || NULL == ( name = (char*)mhdf_malloc( size + 1, status ) ) )
00684         {
00685             while( ( --idx ) > 0 )
00686                 free( result[ idx ] );
00687             free( result );
00688             H5Gclose( group_id );
00689             mhdf_setFail( status, "Internal failure calling H5Gget_objname_by_idx." );
00690             return NULL;
00691         }
00692 
00693         H5Gget_objname_by_idx( group_id, idx, name, size + 1 );
00694         if( !mhdf_path_to_name( name, name ) )
00695         {
00696             mhdf_setFail( status, "Invalid character string in internal file path: \"%s\"\n", name );
00697             return NULL;
00698         }
00699         result[ idx ] = name;
00700     }
00701 
00702     H5Gclose( group_id );
00703     mhdf_setOkay( status );
00704     API_END;
00705     return result;
00706 }
00707 
00708 static int get_attrib_array_length_handle( hid_t attrib_id )
00709 {
00710     hid_t   type_id;
00711     int     rank;
00712     hsize_t dims[ H5S_MAX_RANK ];
00713     int     perm[ H5S_MAX_RANK ];
00714 
00715     type_id = H5Aget_type( attrib_id );
00716     switch( H5Tget_class( type_id ) )
00717     {
00718         case H5T_NO_CLASS:
00719             dims[ 0 ] = -1;
00720             break;
00721         case H5T_OPAQUE:
00722             dims[ 0 ] = H5Tget_size( type_id );
00723             break;
00724         case H5T_ARRAY:
00725 #if defined( H5Tget_array_dims_vers ) && H5Tget_array_dims_vers > 1
00726             (void)perm; /* suppress warning */
00727             rank = H5Tget_array_dims2( type_id, dims );
00728 #else
00729             rank = H5Tget_array_dims( type_id, dims, perm );
00730 #endif
00731             if( rank == 1 )
00732                 break;
00733             else
00734                 return -1;
00735         default:
00736             dims[ 0 ] = 1;
00737             break;
00738     }
00739 
00740     H5Tclose( type_id );
00741     return dims[ 0 ];
00742 }
00743 
00744 /*
00745 static int get_attrib_array_length_index( hid_t object_id, unsigned int index )
00746 {
00747   hid_t attrib_id;
00748   int result;
00749 
00750   attrib_id = H5Aopen_idx( object_id, index );
00751   if (attrib_id < 0)
00752     return -1;
00753 
00754   result = get_attrib_array_length_handle( attrib_id );
00755   H5Aclose( attrib_id );
00756   return result;
00757 }
00758 */
00759 
00760 static int get_attrib_array_length_name( hid_t file, const char* path )
00761 {
00762     hid_t attrib_id;
00763     int   result;
00764 
00765     attrib_id = H5Aopen_name( file, path );
00766     if( attrib_id < 0 ) return -1;
00767 
00768     result = get_attrib_array_length_handle( attrib_id );
00769     H5Aclose( attrib_id );
00770     return result;
00771 }
00772 
00773 void mhdf_getTagInfo( mhdf_FileHandle file_handle, const char* tag_name, enum mhdf_TagDataType* class_out,
00774                       int* size_out, int* tstt_storage_out, int* have_default_out, int* have_global_out,
00775                       int* have_sparse_out, mhdf_Status* status )
00776 {
00777     hid_t        tag_id, type_id, super_id;
00778     int          i, rval, is_handle;
00779     hsize_t      size, sup_size;
00780     unsigned int idx;
00781     int          rank, var_data;
00782     hsize_t      dims[ H5S_MAX_RANK ];
00783     int          perm[ H5S_MAX_RANK ];
00784     H5T_class_t  class_tmp;
00785 
00786     API_BEGIN;
00787 
00788     /* Validate input */
00789     if( NULL == tag_name || NULL == class_out || NULL == size_out || NULL == tstt_storage_out ||
00790         NULL == have_default_out || NULL == have_global_out || NULL == have_sparse_out )
00791     {
00792         mhdf_setFail( status, "Invalid input." );
00793         return;
00794     }
00795 
00796     /* Get group for tag */
00797     tag_id = get_tag( file_handle, tag_name, NULL, status );
00798     if( tag_id < 0 ) return;
00799 
00800     /* Check for sparse data */
00801     rval = mhdf_is_in_group( tag_id, SPARSE_ENTITY_NAME, status );
00802     if( rval < 0 )
00803     {
00804         H5Gclose( tag_id );
00805         return;
00806     }
00807     *have_sparse_out = rval ? 1 : 0;
00808 
00809     /* Check for variable-length tag data */
00810     rval = mhdf_find_attribute( tag_id, TAG_VARLEN_ATTRIB, &idx, status );
00811     if( rval < 0 )
00812     {
00813         H5Gclose( tag_id );
00814         return;
00815     }
00816     var_data = rval ? 1 : 0;
00817 
00818     /* Check if have default value for tag */
00819     rval = mhdf_find_attribute( tag_id, TAG_DEFAULT_ATTRIB, &idx, status );
00820     if( rval < 0 )
00821     {
00822         H5Gclose( tag_id );
00823         return;
00824     }
00825     if( !rval )
00826         *have_default_out = 0;
00827     else if( !var_data )
00828         *have_default_out = 1;
00829     else
00830     {
00831         /* *have_default_out = get_attrib_array_length_index( tag_id, index ); */
00832         *have_default_out = get_attrib_array_length_name( tag_id, TAG_DEFAULT_ATTRIB );
00833         if( *have_default_out < 0 )
00834         {
00835             mhdf_setFail( status, "Error checking length of default value for tag: %s\n", tag_name );
00836             H5Gclose( tag_id );
00837             return;
00838         }
00839     }
00840 
00841     /* Check if have global value for tag */
00842     rval = mhdf_find_attribute( tag_id, TAG_GLOBAL_ATTRIB, &idx, status );
00843     if( rval < 0 )
00844     {
00845         H5Gclose( tag_id );
00846         return;
00847     }
00848     if( !rval )
00849         *have_global_out = 0;
00850     else if( !var_data )
00851         *have_global_out = 1;
00852     else
00853     {
00854         /* *have_global_out = get_attrib_array_length_index( tag_id, index ); */
00855         *have_global_out = get_attrib_array_length_name( tag_id, TAG_GLOBAL_ATTRIB );
00856         if( *have_global_out < 0 )
00857         {
00858             mhdf_setFail( status, "Error checking length of global value for tag: %s\n", tag_name );
00859             H5Gclose( tag_id );
00860             return;
00861         }
00862     }
00863 
00864     /* Get TSTT tag class */
00865     rval = mhdf_read_scalar_attrib( tag_id, TAG_TYPE_ATTRIB, H5T_NATIVE_INT, tstt_storage_out, status );
00866     if( rval < 1 )
00867     {
00868         H5Gclose( tag_id );
00869         return;
00870     }
00871 
00872     /* Check if tag is storing entity handles */
00873     rval = mhdf_find_attribute( tag_id, TAG_HANDLE_TYPE_ATTRIB, &idx, status );
00874     if( rval < 0 )
00875     {
00876         H5Gclose( tag_id );
00877         return;
00878     }
00879     is_handle = rval;
00880 
00881     /* Get tag type */
00882 #if defined( H5Topen_vers ) && H5Topen_vers > 1
00883     type_id = H5Topen2( tag_id, TAG_TYPE_NAME, H5P_DEFAULT );
00884 #else
00885     type_id = H5Topen( tag_id, TAG_TYPE_NAME );
00886 #endif
00887     if( type_id < 0 )
00888     {
00889         H5Gclose( tag_id );
00890         mhdf_setFail( status, "Failed to get type object for tag \"%s\".", tag_name );
00891         return;
00892     }
00893 
00894     class_tmp = H5Tget_class( type_id );
00895     if( class_tmp < 0 )
00896     {
00897         mhdf_setFail( status, "H5Tget_class failed." );
00898         H5Gclose( tag_id );
00899         H5Tclose( type_id );
00900         return;
00901     }
00902 
00903     size = H5Tget_size( type_id );
00904     if( size <= 0 )
00905     {
00906         mhdf_setFail( status, "H5Tget_size failed." );
00907         H5Gclose( tag_id );
00908         H5Tclose( type_id );
00909         return;
00910     }
00911 
00912     switch( class_tmp )
00913     {
00914         case H5T_INTEGER:
00915             *class_out = ( size == 1 ) ? mhdf_BOOLEAN : mhdf_INTEGER;
00916             *size_out = 1;
00917             break;
00918 
00919         case H5T_FLOAT:
00920             *class_out = mhdf_FLOAT;
00921             *size_out = 1;
00922             break;
00923 
00924         case H5T_BITFIELD:
00925             *class_out = mhdf_BITFIELD;
00926             *size_out = H5Tget_precision( type_id );
00927             if( *size_out <= 0 )
00928             {
00929                 mhdf_setFail( status, "H5Tget_precision failed." );
00930                 H5Gclose( tag_id );
00931                 H5Tclose( type_id );
00932                 return;
00933             }
00934             break;
00935 
00936         default:
00937         case H5T_OPAQUE:
00938             *class_out = mhdf_OPAQUE;
00939             *size_out = size;
00940             break;
00941 
00942         case H5T_ARRAY:
00943 
00944 #if defined( H5Tget_array_dims_vers ) && H5Tget_array_dims_vers > 1
00945             (void)perm; /* suppress warning */
00946             rank = H5Tget_array_dims2( type_id, dims );
00947 #else
00948             rank = H5Tget_array_dims( type_id, dims, perm );
00949 #endif
00950             if( rank <= 0 )
00951             {
00952                 mhdf_setFail( status, "H5Tget_size failed." );
00953                 H5Gclose( tag_id );
00954                 H5Tclose( type_id );
00955                 return;
00956             }
00957             for( i = 1; i < rank; ++i )
00958                 dims[ 0 ] *= dims[ i ];
00959 
00960             super_id = H5Tget_super( type_id );
00961             if( super_id < 0 )
00962             {
00963                 mhdf_setFail( status, "H5Tget_super failed" );
00964                 H5Gclose( tag_id );
00965                 H5Tclose( type_id );
00966                 return;
00967             }
00968 
00969             class_tmp = H5Tget_class( super_id );
00970             if( class_tmp < 0 )
00971             {
00972                 mhdf_setFail( status, "H5Tget_class failed." );
00973                 H5Gclose( tag_id );
00974                 H5Tclose( type_id );
00975                 H5Tclose( super_id );
00976                 return;
00977             }
00978 
00979             sup_size = H5Tget_size( super_id );
00980             H5Tclose( super_id );
00981             if( sup_size <= 0 )
00982             {
00983                 mhdf_setFail( status, "H5Tget_size failed." );
00984                 H5Gclose( tag_id );
00985                 H5Tclose( type_id );
00986                 return;
00987             }
00988 
00989             switch( class_tmp )
00990             {
00991                 case H5T_INTEGER:
00992                     *class_out = ( sup_size == 1 ) ? mhdf_BOOLEAN : mhdf_INTEGER;
00993                     *size_out = dims[ 0 ];
00994                     break;
00995 
00996                 case H5T_FLOAT:
00997                     *class_out = mhdf_FLOAT;
00998                     *size_out = dims[ 0 ];
00999                     break;
01000 
01001                 default:
01002                     *class_out = mhdf_OPAQUE;
01003                     *size_out = size;
01004                     break;
01005             }
01006 
01007             break;
01008     }
01009     H5Tclose( type_id );
01010     H5Gclose( tag_id );
01011 
01012     if( is_handle )
01013     {
01014         if( *class_out != mhdf_INTEGER )
01015         {
01016             mhdf_setFail( status, "Non-integer tag marked as handle type." );
01017             return;
01018         }
01019         *class_out = mhdf_ENTITY_ID;
01020     }
01021 
01022     if( var_data )
01023     {
01024         if( *size_out != 1 || *class_out == mhdf_BITFIELD )
01025         {
01026             mhdf_setFail( status, "Invalid or unexpected variable-length tag data" );
01027             return;
01028         }
01029         *size_out = -1;
01030     }
01031 
01032     mhdf_setOkay( status );
01033     API_END;
01034 }
01035 
01036 static int read_tag_attrib_data( hid_t tag_id, const char* attrib_name, hid_t type_id, void* data, int is_var_len,
01037                                  mhdf_Status* status )
01038 {
01039     int      rval, ilen;
01040     unsigned idx;
01041     hid_t    read_type = type_id;
01042     hsize_t  len;
01043 
01044     /* Check if tag has attribute */
01045     rval = mhdf_find_attribute( tag_id, attrib_name, &idx, status );
01046     if( rval < 0 )
01047         return 0;
01048     else if( 0 == rval )
01049         return 1;
01050 
01051     if( NULL == data )
01052     {
01053         mhdf_setFail( status, "Invalid input." );
01054         return 0;
01055     }
01056 
01057     if( is_var_len )
01058     {
01059         /* len = get_attrib_array_length_index(tag_id, index); */
01060         ilen = get_attrib_array_length_name( tag_id, attrib_name );
01061         if( ilen < 0 )
01062         {
01063             mhdf_setFail( status, "Failed to read length of default/mesh value for tag" );
01064             return 0;
01065         }
01066         len = ilen;
01067 
01068         /* caller passes type_id == 0 for OPAQUE */
01069         if( 0 == type_id )
01070             read_type = H5Tcreate( H5T_OPAQUE, len );
01071         else
01072         {
01073 #if defined( H5Tarray_create_vers ) && H5Tarray_create_vers > 1
01074             read_type = H5Tarray_create2( type_id, 1, &len );
01075 #else
01076             read_type = H5Tarray_create( type_id, 1, &len, 0 );
01077 #endif
01078         }
01079         if( read_type < 0 )
01080         {
01081             mhdf_setFail( status, "Failed to read mesh/default value for tag" );
01082             return 0;
01083         }
01084     }
01085 
01086     rval = mhdf_read_scalar_attrib( tag_id, attrib_name, read_type, data, status );
01087     if( is_var_len ) H5Tclose( read_type );
01088 
01089     return rval;
01090 }
01091 
01092 void mhdf_getTagValues( mhdf_FileHandle file_handle, const char* tag_name, hid_t output_data_type, void* default_value,
01093                         void* global_value, mhdf_Status* status )
01094 {
01095     hid_t        tag_id;
01096     int          rval, var_data;
01097     unsigned int idx;
01098     API_BEGIN;
01099 
01100     /* check args */
01101     if( NULL == tag_name || !*tag_name )
01102     {
01103         mhdf_setFail( status, "Invalid input." );
01104         return;
01105     }
01106 
01107     /* Get the tag group */
01108     tag_id = get_tag( file_handle, tag_name, NULL, status );
01109     if( tag_id < 0 ) return;
01110 
01111     /* Check for variable-length tag data */
01112     rval = mhdf_find_attribute( tag_id, TAG_VARLEN_ATTRIB, &idx, status );
01113     if( rval < 0 )
01114     {
01115         H5Gclose( tag_id );
01116         return;
01117     }
01118     var_data = rval ? 1 : 0;
01119 
01120     /* Read default value if present */
01121     rval = read_tag_attrib_data( tag_id, TAG_DEFAULT_ATTRIB, output_data_type, default_value, var_data, status );
01122     if( !rval )
01123     {
01124         H5Gclose( tag_id );
01125         return;
01126     }
01127 
01128     /* Read mesh value if present */
01129     rval = read_tag_attrib_data( tag_id, TAG_GLOBAL_ATTRIB, output_data_type, global_value, var_data, status );
01130     if( !rval )
01131     {
01132         H5Gclose( tag_id );
01133         return;
01134     }
01135 
01136     H5Gclose( tag_id );
01137     mhdf_setOkay( status );
01138     API_END;
01139 }
01140 
01141 int mhdf_haveDenseTag( mhdf_FileHandle file_handle, const char* tag_name, const char* type_handle, mhdf_Status* status )
01142 {
01143     char*       path;
01144     hid_t       elem_id, group_id;
01145     FileHandle* file_ptr;
01146     int         rval = 0;
01147     API_BEGIN;
01148 
01149     file_ptr = (FileHandle*)file_handle;
01150     if( !mhdf_check_valid_file( file_ptr, status ) ) return -1;
01151 
01152     if( type_handle == mhdf_node_type_handle( ) )
01153     {
01154 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
01155         elem_id = H5Gopen2( file_ptr->hdf_handle, NODE_GROUP, H5P_DEFAULT );
01156 #else
01157         elem_id = H5Gopen( file_ptr->hdf_handle, NODE_GROUP );
01158 #endif
01159         if( elem_id < 0 ) mhdf_setFail( status, "Could not open node group." );
01160     }
01161     else if( type_handle == mhdf_set_type_handle( ) )
01162     {
01163 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
01164         elem_id = H5Gopen2( file_ptr->hdf_handle, SET_GROUP, H5P_DEFAULT );
01165 #else
01166         elem_id = H5Gopen( file_ptr->hdf_handle, SET_GROUP );
01167 #endif
01168         if( elem_id < 0 ) mhdf_setFail( status, "Could not open set group." );
01169     }
01170     else
01171     {
01172         elem_id = mhdf_elem_group_from_handle( file_ptr, type_handle, status );
01173     }
01174     if( elem_id < 0 ) return -1;
01175 
01176     rval = mhdf_is_in_group( elem_id, TAG_GROUP_NAME, status );
01177     if( rval < 0 )
01178     {
01179         H5Gclose( elem_id );
01180         return -1;
01181     }
01182     else if( rval == 0 )
01183     {
01184         H5Gclose( elem_id );
01185         mhdf_setOkay( status );
01186         return 0;
01187     }
01188 
01189 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
01190     group_id = H5Gopen2( elem_id, DENSE_TAG_SUBGROUP, H5P_DEFAULT );
01191 #else
01192     group_id = H5Gopen( elem_id, DENSE_TAG_SUBGROUP );
01193 #endif
01194     H5Gclose( elem_id );
01195     if( group_id < 0 )
01196     {
01197         mhdf_setFail( status, "Could not open tag subgroup." );
01198         return -1;
01199     }
01200 
01201     path = mhdf_name_to_path_copy( tag_name, status );
01202     if( NULL == path )
01203     {
01204         H5Gclose( group_id );
01205         return -1;
01206     }
01207 
01208     rval = mhdf_is_in_group( group_id, path, status );
01209     H5Gclose( group_id );
01210     free( path );
01211 
01212     if( rval >= 0 ) { mhdf_setOkay( status ); }
01213 
01214     API_END;
01215     return rval;
01216 }
01217 
01218 hid_t mhdf_createDenseTagData( mhdf_FileHandle file_handle, const char* tag_name, const char* type_handle,
01219                                long num_values, mhdf_Status* status )
01220 {
01221     char*       path;
01222     hid_t       elem_id, data_id, type_id;
01223     FileHandle* file_ptr;
01224     size_t      name_len, path_len, dir_len;
01225     hsize_t     size;
01226     API_BEGIN;
01227 
01228     file_ptr = (FileHandle*)file_handle;
01229     if( !mhdf_check_valid_file( file_ptr, status ) ) return -1;
01230 
01231     if( type_handle == mhdf_node_type_handle( ) )
01232     {
01233 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
01234         elem_id = H5Gopen2( file_ptr->hdf_handle, NODE_GROUP, H5P_DEFAULT );
01235 #else
01236         elem_id = H5Gopen( file_ptr->hdf_handle, NODE_GROUP );
01237 #endif
01238         if( elem_id < 0 ) mhdf_setFail( status, "Could not open node group." );
01239     }
01240     else if( type_handle == mhdf_set_type_handle( ) )
01241     {
01242 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
01243         elem_id = H5Gopen2( file_ptr->hdf_handle, SET_GROUP, H5P_DEFAULT );
01244 #else
01245         elem_id = H5Gopen( file_ptr->hdf_handle, SET_GROUP );
01246 #endif
01247         if( elem_id < 0 ) mhdf_setFail( status, "Could not open set group." );
01248     }
01249     else
01250     {
01251         elem_id = mhdf_elem_group_from_handle( file_ptr, type_handle, status );
01252     }
01253     if( elem_id < 0 ) return -1;
01254 
01255     dir_len = strlen( DENSE_TAG_SUBGROUP );
01256     name_len = mhdf_name_to_path( tag_name, NULL, 0 );
01257     path_len = dir_len + name_len + 1;
01258     path = (char*)mhdf_malloc( path_len, status );
01259     if( NULL == path )
01260     {
01261         H5Gclose( elem_id );
01262         return -1;
01263     }
01264     strcpy( path, DENSE_TAG_SUBGROUP );
01265     mhdf_name_to_path( tag_name, path + dir_len, name_len + 1 );
01266 
01267     type_id = get_tag_type( file_ptr, path + dir_len, status );
01268     if( type_id < 0 )
01269     {
01270         H5Gclose( elem_id );
01271         return -1;
01272     }
01273 
01274     size = (hsize_t)num_values;
01275     data_id = mhdf_create_table( elem_id, path, type_id, 1, &size, status );
01276     free( path );
01277     H5Gclose( elem_id );
01278     H5Tclose( type_id );
01279 
01280     if( data_id > 0 ) mhdf_setOkay( status );
01281 
01282     API_END_H( 1 );
01283     return data_id;
01284 }
01285 
01286 hid_t mhdf_openDenseTagData( mhdf_FileHandle file_handle, const char* tag_name, const char* type_handle,
01287                              long* num_values_out, mhdf_Status* status )
01288 {
01289     char*       path;
01290     hid_t       elem_id, data_id;
01291     FileHandle* file_ptr;
01292     size_t      name_len, path_len, dir_len;
01293     hsize_t     size;
01294     API_BEGIN;
01295 
01296     file_ptr = (FileHandle*)file_handle;
01297     if( !mhdf_check_valid_file( file_ptr, status ) ) return -1;
01298 
01299     if( type_handle == mhdf_node_type_handle( ) )
01300     {
01301 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
01302         elem_id = H5Gopen2( file_ptr->hdf_handle, NODE_GROUP, H5P_DEFAULT );
01303 #else
01304         elem_id = H5Gopen( file_ptr->hdf_handle, NODE_GROUP );
01305 #endif
01306         if( elem_id < 0 ) mhdf_setFail( status, "Could not open node group." );
01307     }
01308     else if( type_handle == mhdf_set_type_handle( ) )
01309     {
01310 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
01311         elem_id = H5Gopen2( file_ptr->hdf_handle, SET_GROUP, H5P_DEFAULT );
01312 #else
01313         elem_id = H5Gopen( file_ptr->hdf_handle, SET_GROUP );
01314 #endif
01315         if( elem_id < 0 ) mhdf_setFail( status, "Could not open set group." );
01316     }
01317     else
01318     {
01319         elem_id = mhdf_elem_group_from_handle( file_ptr, type_handle, status );
01320     }
01321     if( elem_id < 0 ) return -1;
01322 
01323     dir_len = strlen( DENSE_TAG_SUBGROUP );
01324     name_len = mhdf_name_to_path( tag_name, NULL, 0 );
01325     path_len = dir_len + name_len + 1;
01326     path = (char*)mhdf_malloc( path_len, status );
01327     if( NULL == path )
01328     {
01329         H5Gclose( elem_id );
01330         return -1;
01331     }
01332     strcpy( path, DENSE_TAG_SUBGROUP );
01333     mhdf_name_to_path( tag_name, path + dir_len, name_len + 1 );
01334 
01335     data_id = mhdf_open_table( elem_id, path, 1, &size, status );
01336     free( path );
01337     H5Gclose( elem_id );
01338     *num_values_out = (long)size;
01339 
01340     if( data_id >= 0 ) mhdf_setOkay( status );
01341 
01342     API_END_H( 1 );
01343     return data_id;
01344 }
01345 
01346 void mhdf_createSparseTagData( mhdf_FileHandle file_handle, const char* tag_name, long num_values,
01347                                hid_t handles_out[ 2 ], mhdf_Status* status )
01348 {
01349     hid_t   tag_id, index_id, data_id, type_id, id_type;
01350     hsize_t count = (hsize_t)num_values;
01351     API_BEGIN;
01352 
01353     tag_id = get_tag( file_handle, tag_name, &id_type, status );
01354     if( tag_id < 0 ) return;
01355 
01356 #if defined( H5Topen_vers ) && H5Topen_vers > 1
01357     type_id = H5Topen2( tag_id, TAG_TYPE_NAME, H5P_DEFAULT );
01358 #else
01359     type_id = H5Topen( tag_id, TAG_TYPE_NAME );
01360 #endif
01361     if( type_id < 0 )
01362     {
01363         H5Gclose( tag_id );
01364         mhdf_setFail( status, "Failed to get type object for tag \"%s\".", tag_name );
01365         return;
01366     }
01367 
01368     index_id = mhdf_create_table( tag_id, SPARSE_ENTITY_NAME, id_type, 1, &count, status );
01369     if( index_id < 0 )
01370     {
01371         H5Gclose( tag_id );
01372         H5Tclose( type_id );
01373         return;
01374     }
01375 
01376     data_id = mhdf_create_table( tag_id, SPARSE_VALUES_NAME, type_id, 1, &count, status );
01377     H5Tclose( type_id );
01378     H5Gclose( tag_id );
01379     if( data_id < 0 )
01380     {
01381         H5Dclose( index_id );
01382         return;
01383     }
01384 
01385     handles_out[ 0 ] = index_id;
01386     handles_out[ 1 ] = data_id;
01387     mhdf_setOkay( status );
01388     API_END_H( 2 );
01389 }
01390 
01391 void mhdf_createVarLenTagData( mhdf_FileHandle file_handle, const char* tag_name, long num_entities, long num_values,
01392                                hid_t handles_out[ 3 ], mhdf_Status* status )
01393 {
01394     hid_t   tag_id, index_id, data_id, type_id, offset_id, id_type;
01395     hsize_t count = (hsize_t)num_entities;
01396     API_BEGIN;
01397 
01398     tag_id = get_tag( file_handle, tag_name, &id_type, status );
01399     if( tag_id < 0 ) return;
01400 
01401 #if defined( H5Topen_vers ) && H5Topen_vers > 1
01402     type_id = H5Topen2( tag_id, TAG_TYPE_NAME, H5P_DEFAULT );
01403 #else
01404     type_id = H5Topen( tag_id, TAG_TYPE_NAME );
01405 #endif
01406     if( type_id < 0 )
01407     {
01408         H5Gclose( tag_id );
01409         mhdf_setFail( status, "Failed to get type object for tag \"%s\".", tag_name );
01410         return;
01411     }
01412 
01413     index_id = mhdf_create_table( tag_id, SPARSE_ENTITY_NAME, id_type, 1, &count, status );
01414     if( index_id < 0 )
01415     {
01416         H5Gclose( tag_id );
01417         H5Tclose( type_id );
01418         return;
01419     }
01420 
01421     offset_id = mhdf_create_table( tag_id, TAG_VAR_INDICES, MHDF_INDEX_TYPE, 1, &count, status );
01422     if( index_id < 0 )
01423     {
01424         H5Dclose( offset_id );
01425         H5Gclose( tag_id );
01426         H5Tclose( type_id );
01427         return;
01428     }
01429 
01430     count = (hsize_t)num_values;
01431     data_id = mhdf_create_table( tag_id, SPARSE_VALUES_NAME, type_id, 1, &count, status );
01432     H5Tclose( type_id );
01433     H5Gclose( tag_id );
01434     if( data_id < 0 )
01435     {
01436         H5Dclose( offset_id );
01437         H5Dclose( index_id );
01438         return;
01439     }
01440 
01441     handles_out[ 0 ] = index_id;
01442     handles_out[ 1 ] = data_id;
01443     handles_out[ 2 ] = offset_id;
01444     mhdf_setOkay( status );
01445     API_END_H( 3 );
01446 }
01447 
01448 void mhdf_openSparseTagData( mhdf_FileHandle file_handle, const char* tag_name, long* num_entity_out,
01449                              long* num_values_out, hid_t handles_out[ 3 ], mhdf_Status* status )
01450 {
01451     hid_t    tag_id, index_id, data_id, offset_id = -1;
01452     hsize_t  num_ent, data_size, num_data;
01453     int      rval;
01454     unsigned idx;
01455     API_BEGIN;
01456 
01457     tag_id = get_tag( file_handle, tag_name, NULL, status );
01458     if( tag_id < 0 ) return;
01459 
01460     index_id = mhdf_open_table( tag_id, SPARSE_ENTITY_NAME, 1, &num_ent, status );
01461     if( index_id < 0 )
01462     {
01463         H5Gclose( tag_id );
01464         return;
01465     }
01466 
01467     data_id = mhdf_open_table( tag_id, SPARSE_VALUES_NAME, 1, &data_size, status );
01468     if( data_id < 0 )
01469     {
01470         H5Gclose( tag_id );
01471         H5Dclose( index_id );
01472         return;
01473     }
01474 
01475     /* check if tag is variable-lentgth */
01476     rval = mhdf_find_attribute( tag_id, TAG_VARLEN_ATTRIB, &idx, status );
01477     if( rval < 0 )
01478     {
01479         H5Gclose( tag_id );
01480         H5Dclose( index_id );
01481         H5Dclose( data_id );
01482         return;
01483     }
01484 
01485     /* If variable length... */
01486     if( rval )
01487     {
01488         offset_id = mhdf_open_table( tag_id, TAG_VAR_INDICES, 1, &num_data, status );
01489         if( offset_id < 0 )
01490         {
01491             H5Gclose( tag_id );
01492             H5Dclose( index_id );
01493             H5Dclose( data_id );
01494             return;
01495         }
01496     }
01497     /* Otherwise the number of values is the same as the size of the data table */
01498     else
01499     {
01500         num_data = data_size;
01501     }
01502 
01503     H5Gclose( tag_id );
01504     if( num_ent != num_data )
01505     {
01506         mhdf_setFail( status, "Data length mismatch for sparse tag data -- invalid file." );
01507         if( offset_id >= 0 ) H5Dclose( offset_id );
01508         H5Dclose( index_id );
01509         H5Dclose( data_id );
01510         return;
01511     }
01512     *num_entity_out = (long)num_ent;
01513     if( num_values_out ) *num_values_out = (long)data_size;
01514 
01515     handles_out[ 0 ] = index_id;
01516     handles_out[ 1 ] = data_id;
01517     if( offset_id >= 0 ) handles_out[ 2 ] = offset_id;
01518     mhdf_setOkay( status );
01519     API_END_H( 2 );
01520 }
01521 
01522 void mhdf_writeSparseTagEntities( hid_t table_id, long offset, long count, hid_t int_type, const void* id_list,
01523                                   mhdf_Status* status )
01524 {
01525     API_BEGIN;
01526     mhdf_write_data( table_id, offset, count, int_type, id_list, H5P_DEFAULT, status );
01527     API_END;
01528 }
01529 void mhdf_writeSparseTagEntitiesWithOpt( hid_t table_id, long offset, long count, hid_t int_type, const void* id_list,
01530                                          hid_t io_prop, mhdf_Status* status )
01531 {
01532     API_BEGIN;
01533     mhdf_write_data( table_id, offset, count, int_type, id_list, io_prop, status );
01534     API_END;
01535 }
01536 
01537 void mhdf_writeTagValues( hid_t table_id, long offset, long count, hid_t tag_type, const void* tag_data,
01538                           mhdf_Status* status )
01539 {
01540     mhdf_writeTagValuesWithOpt( table_id, offset, count, tag_type, tag_data, H5P_DEFAULT, status );
01541 }
01542 
01543 void mhdf_writeTagValuesWithOpt( hid_t table_id, long offset, long count, hid_t tag_type, const void* tag_data,
01544                                  hid_t io_prop, mhdf_Status* status )
01545 {
01546     API_BEGIN;
01547     mhdf_write_data( table_id, offset, count, tag_type, tag_data, io_prop, status );
01548     API_END;
01549 }
01550 
01551 void mhdf_writeSparseTagIndices( hid_t table_id, long offset, long count, hid_t int_type, const void* indices,
01552                                  mhdf_Status* status )
01553 {
01554     API_BEGIN;
01555     mhdf_write_data( table_id, offset, count, int_type, indices, H5P_DEFAULT, status );
01556     API_END;
01557 }
01558 void mhdf_writeSparseTagIndicesWithOpt( hid_t table_id, long offset, long count, hid_t int_type, const void* indices,
01559                                         hid_t io_prop, mhdf_Status* status )
01560 {
01561     API_BEGIN;
01562     mhdf_write_data( table_id, offset, count, int_type, indices, io_prop, status );
01563     API_END;
01564 }
01565 
01566 void mhdf_readSparseTagEntities( hid_t table_id, long offset, long count, hid_t int_type, void* id_list,
01567                                  mhdf_Status* status )
01568 {
01569     API_BEGIN;
01570     mhdf_read_data( table_id, offset, count, int_type, id_list, H5P_DEFAULT, status );
01571     API_END;
01572 }
01573 void mhdf_readSparseTagEntitiesWithOpt( hid_t table_id, long offset, long count, hid_t int_type, void* id_list,
01574                                         hid_t io_prop, mhdf_Status* status )
01575 {
01576     API_BEGIN;
01577     mhdf_read_data( table_id, offset, count, int_type, id_list, io_prop, status );
01578     API_END;
01579 }
01580 
01581 void mhdf_readTagValues( hid_t table_id, long offset, long count, hid_t tag_type, void* tag_data, mhdf_Status* status )
01582 {
01583     mhdf_readTagValuesWithOpt( table_id, offset, count, tag_type, tag_data, H5P_DEFAULT, status );
01584 }
01585 void mhdf_readTagValuesWithOpt( hid_t table_id, long offset, long count, hid_t tag_type, void* tag_data, hid_t io_prop,
01586                                 mhdf_Status* status )
01587 {
01588     API_BEGIN;
01589     mhdf_read_data( table_id, offset, count, tag_type, tag_data, io_prop, status );
01590     API_END;
01591 }
01592 
01593 void mhdf_readSparseTagIndices( hid_t table_id, long offset, long count, hid_t int_type, void* indices,
01594                                 mhdf_Status* status )
01595 {
01596     API_BEGIN;
01597     mhdf_read_data( table_id, offset, count, int_type, indices, H5P_DEFAULT, status );
01598     API_END;
01599 }
01600 void mhdf_readSparseTagIndicesWithOpt( hid_t table_id, long offset, long count, hid_t int_type, void* indices,
01601                                        hid_t io_prop, mhdf_Status* status )
01602 {
01603     API_BEGIN;
01604     mhdf_read_data( table_id, offset, count, int_type, indices, io_prop, status );
01605     API_END;
01606 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines