Mesh Oriented datABase  (version 5.4.1)
Array-based unstructured mesh datastructure
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,
00200                                     const char* attrib_name,
00201                                     hid_t type_id,
00202                                     const void* value,
00203                                     hsize_t value_size,
00204                                     mhdf_Status* status )
00205 {
00206     hid_t write_type;
00207     int rval;
00208     if( value_size == 1 )
00209         write_type = type_id;
00210     else if( H5Tget_class( type_id ) == H5T_OPAQUE )
00211     {
00212         write_type = H5Tcreate( H5T_OPAQUE, value_size );
00213     }
00214     else
00215     {
00216 #if defined( H5Tarray_create_vers ) && H5Tarray_create_vers > 1
00217         write_type = H5Tarray_create2( type_id, 1, &value_size );
00218 #else
00219         write_type = H5Tarray_create( type_id, 1, &value_size, 0 );
00220 #endif
00221     }
00222 
00223     if( write_type < 0 )
00224     {
00225         mhdf_setFail( status, "Error constructing type object for tag mesh/default value" );
00226         return -1;
00227     }
00228 
00229     rval = mhdf_create_scalar_attrib( tag_id, attrib_name, write_type, value, status );
00230     if( write_type != type_id ) H5Tclose( write_type );
00231 
00232     return rval;
00233 }
00234 
00235 static hid_t create_tag_common( mhdf_FileHandle file_handle,
00236                                 const char* tag_name,
00237                                 enum mhdf_TagDataType tag_type,
00238                                 int size,
00239                                 int storage,
00240                                 const void* default_value,
00241                                 int default_value_size_in,
00242                                 const void* global_value,
00243                                 int global_value_size_in,
00244                                 hid_t hdf_type,
00245                                 hid_t hdf_base_type,
00246                                 mhdf_Status* status )
00247 {
00248     hid_t temp_id, group_id, tag_id;
00249     char* path;
00250     FileHandle* file_ptr;
00251     herr_t rval;
00252     hsize_t arr_len;
00253     int one = 1, var_len = 0;
00254     hsize_t default_value_size = default_value_size_in;
00255     hsize_t global_value_size  = global_value_size_in;
00256     int close_base_type        = 0;
00257 
00258     /* Force standard data types over user-specified types */
00259 
00260     if( tag_type != mhdf_OPAQUE ) hdf_type = 0;
00261     if( tag_type != mhdf_ENTITY_ID ) hdf_base_type = 0;
00262 
00263     /* Validate input */
00264 
00265     file_ptr = (FileHandle*)file_handle;
00266     if( !mhdf_check_valid_file( file_ptr, status ) ) return -1;
00267 
00268     if( !tag_name || !*tag_name )
00269     {
00270         mhdf_setFail( status, "Invalid tag name" );
00271         return -1;
00272     }
00273 
00274     /* Open the tag group */
00275 
00276 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
00277     group_id = H5Gopen2( file_ptr->hdf_handle, TAG_GROUP, H5P_DEFAULT );
00278 #else
00279     group_id = H5Gopen( file_ptr->hdf_handle, TAG_GROUP );
00280 #endif
00281     if( group_id < 0 )
00282     {
00283         mhdf_setFail( status, "H5Gopen(\"%s\") failed.", TAG_GROUP );
00284         return -1;
00285     }
00286 
00287     /* Create path string for tag object */
00288 
00289     path = mhdf_name_to_path_copy( tag_name, status );
00290     if( !path )
00291     {
00292         H5Gclose( group_id );
00293         return -1;
00294     }
00295 
00296     /* Create group for this tag */
00297 
00298 #if defined( H5Gcreate_vers ) && H5Gcreate_vers > 1
00299     tag_id = H5Gcreate2( group_id, path, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
00300 #else
00301     tag_id   = H5Gcreate( group_id, path, 3 );
00302 #endif
00303     if( tag_id < 0 )
00304     {
00305         mhdf_setFail( status, "H5Gcreate( \"%s\" ) failed.", path );
00306         free( path );
00307         H5Gclose( group_id );
00308         return -1;
00309     }
00310 
00311     /* Store the tag name as the comment on the group entry */
00312 
00313     rval = H5Gset_comment( group_id, path, tag_name );
00314     H5Gclose( group_id );
00315     free( path );
00316     if( rval < 0 )
00317     {
00318         mhdf_setFail( status, "H5Gset_comment failed for tag \"%s\"", tag_name );
00319         H5Gclose( tag_id );
00320         return -1;
00321     }
00322 
00323     /* Store TSTT tag type as attribute */
00324 
00325     rval = mhdf_create_scalar_attrib( tag_id, TAG_TYPE_ATTRIB, H5T_NATIVE_INT, &storage, status );
00326     if( !rval )
00327     {
00328         H5Gclose( tag_id );
00329         return -1;
00330     }
00331 
00332     if( hdf_type )
00333     {
00334         hdf_type = H5Tcopy( hdf_type );
00335         arr_len  = 1;
00336     }
00337     else
00338     {
00339         switch( tag_type )
00340         {
00341             default:
00342             case mhdf_OPAQUE:
00343                 arr_len  = 1;
00344                 hdf_type = H5Tcreate( H5T_OPAQUE, abs( size ) );
00345                 H5Tset_tag( hdf_type, "tag_data" );
00346                 break;
00347 
00348             case mhdf_BITFIELD:
00349                 arr_len = 1;
00350                 if( size <= 0 )
00351                 {
00352                     mhdf_setFail( status, "Invalid size (%d) for bit tag.", (int)size );
00353                     return -1;
00354                 }
00355                 else if( size <= 8 )
00356                     hdf_type = H5Tcopy( H5T_NATIVE_B8 );
00357                 else if( size <= 16 )
00358                     hdf_type = H5Tcopy( H5T_NATIVE_B16 );
00359                 else if( size <= 32 )
00360                     hdf_type = H5Tcopy( H5T_NATIVE_B32 );
00361                 else if( size <= 64 )
00362                     hdf_type = H5Tcopy( H5T_NATIVE_B64 );
00363                 else
00364                 {
00365                     mhdf_setFail( status, "Cannot create a bit tag larger than 64-bits.  %d bits requested.\n",
00366                                   (int)size );
00367                     return -1;
00368                 }
00369 
00370                 if( 0 > H5Tset_precision( hdf_type, size ) )
00371                 {
00372                     mhdf_setFail( status, "H5Tset_precision failed." );
00373                     return -1;
00374                 }
00375                 break;
00376 
00377             case mhdf_ENTITY_ID:
00378                 arr_len  = abs( size );
00379                 hdf_type = H5Tcopy( H5T_NATIVE_ULONG );
00380                 break;
00381 
00382             case mhdf_BOOLEAN:
00383                 arr_len  = abs( size );
00384                 hdf_type = H5Tcopy( H5T_NATIVE_UCHAR );
00385                 break;
00386 
00387             case mhdf_INTEGER:
00388                 arr_len  = abs( size );
00389                 hdf_type = H5Tcopy( H5T_NATIVE_INT );
00390                 break;
00391 
00392             case mhdf_FLOAT:
00393                 arr_len  = abs( size );
00394                 hdf_type = H5Tcopy( H5T_NATIVE_DOUBLE );
00395                 break;
00396         }
00397     }
00398 
00399     if( hdf_type <= 0 )
00400     {
00401         mhdf_setFail( status, "Failed to create tag type object." );
00402         H5Gclose( tag_id );
00403         return -1;
00404     }
00405 
00406     if( hdf_base_type && H5Tget_class( hdf_type ) != H5Tget_class( hdf_base_type ) )
00407     {
00408         mhdf_setFail( status, "Invalid base type for tag default/global data" );
00409         H5Gclose( tag_id );
00410         return -1;
00411     }
00412 
00413     if( size < -1 || !arr_len )
00414     {
00415         mhdf_setFail( status, "Invalid 'size' parameter passed to mhdf_createTag (%d)", (int)size );
00416         H5Gclose( tag_id );
00417         return -1;
00418     }
00419     else if( size == -1 )
00420     {
00421         /* Note: we don't do anything with this here.  We rely on
00422          *       the app to ask us to create the index table later.
00423          */
00424         arr_len = 1;
00425         /* need to know this later, when storing default/global values */
00426         var_len = 1;
00427     }
00428     else if( arr_len > 1 )
00429     {
00430 #if defined( H5Tarray_create_vers ) && H5Tarray_create_vers > 1
00431         temp_id = H5Tarray_create2( hdf_type, 1, &arr_len );
00432 #else
00433         temp_id = H5Tarray_create( hdf_type, 1, &arr_len, NULL );
00434 #endif
00435         H5Tclose( hdf_type );
00436         if( temp_id < 0 )
00437         {
00438             mhdf_setFail( status, "Failed to create tag type object." );
00439             H5Gclose( tag_id );
00440             return -1;
00441         }
00442         hdf_type = temp_id;
00443 
00444         if( hdf_base_type )
00445         {
00446             if( H5Tequal( hdf_base_type, hdf_type ) > 0 )
00447             {
00448                 hdf_base_type = hdf_type;
00449             }
00450             else
00451             {
00452 #if defined( H5Tarray_create_vers ) && H5Tarray_create_vers > 1
00453                 temp_id = H5Tarray_create2( hdf_base_type, 1, &arr_len );
00454 #else
00455                 temp_id = H5Tarray_create( hdf_base_type, 1, &arr_len, NULL );
00456 #endif
00457                 if( temp_id < 0 )
00458                 {
00459                     mhdf_setFail( status, "Failed to create tag type object." );
00460                     H5Gclose( tag_id );
00461                     H5Tclose( hdf_type );
00462                     return -1;
00463                 }
00464                 hdf_base_type   = temp_id;
00465                 close_base_type = 1;
00466             }
00467         }
00468     }
00469 
00470     if( !hdf_base_type ) hdf_base_type = hdf_type;
00471 
00472         /* Create tag type object, or write attribute if opaque */
00473 
00474 #if defined( H5Tcommit_vers ) && H5Tcommit_vers > 1
00475     rval = H5Tcommit2( tag_id, TAG_TYPE_NAME, hdf_type, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
00476 #else
00477     rval     = H5Tcommit( tag_id, TAG_TYPE_NAME, hdf_type );
00478 #endif
00479     if( rval < 0 )
00480     {
00481         mhdf_setFail( status, "H5Tcommit failed for tag \"%s\"", tag_name );
00482         if( close_base_type ) H5Tclose( hdf_base_type );
00483         H5Tclose( hdf_type );
00484         H5Gclose( tag_id );
00485         return -1;
00486     }
00487 
00488     /* If tag is entity handle, make note of it */
00489     if( tag_type == mhdf_ENTITY_ID )
00490     {
00491         rval = mhdf_create_scalar_attrib( tag_id, TAG_HANDLE_TYPE_ATTRIB, H5T_NATIVE_INT, &one, 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 the default value as a attribute of the tag group */
00502 
00503     if( default_value )
00504     {
00505         rval = store_tag_val_in_attrib( tag_id, TAG_DEFAULT_ATTRIB, hdf_base_type, default_value,
00506                                         var_len ? default_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     /* Store global tag value as attribute */
00517 
00518     if( global_value )
00519     {
00520         rval = store_tag_val_in_attrib( tag_id, TAG_GLOBAL_ATTRIB, hdf_base_type, global_value,
00521                                         var_len ? global_value_size : 1, status );
00522         if( !rval )
00523         {
00524             if( close_base_type ) H5Tclose( hdf_base_type );
00525             H5Gclose( tag_id );
00526             H5Tclose( hdf_type );
00527             return -1;
00528         }
00529     }
00530 
00531     if( close_base_type ) H5Tclose( hdf_base_type );
00532     H5Tclose( hdf_type );
00533     mhdf_setOkay( status );
00534     return tag_id;
00535 }
00536 
00537 hid_t mhdf_getTagDataType( mhdf_FileHandle file_handle, const char* tag_name, mhdf_Status* status )
00538 {
00539     FileHandle* file_ptr;
00540     hid_t result;
00541     char* path;
00542     API_BEGIN;
00543 
00544     /* Validate input */
00545 
00546     file_ptr = (FileHandle*)file_handle;
00547     if( !mhdf_check_valid_file( file_ptr, status ) ) return -1;
00548 
00549     if( !tag_name || !*tag_name )
00550     {
00551         mhdf_setFail( status, "Invalid tag name" );
00552         return -1;
00553     }
00554 
00555     /* Create path string for tag object */
00556 
00557     path = mhdf_name_to_path_copy( tag_name, status );
00558     if( !path )
00559     {
00560         return -1;
00561     }
00562 
00563     result = get_tag_type( file_ptr, path, status );
00564 
00565     free( path );
00566     API_END;
00567     return result;
00568 }
00569 
00570 void mhdf_createTag( mhdf_FileHandle file_handle,
00571                      const char* tag_name,
00572                      enum mhdf_TagDataType tag_type,
00573                      int size,
00574                      int storage,
00575                      const void* default_value,
00576                      const void* global_value,
00577                      hid_t hdf_type,
00578                      hid_t hdf_base_type,
00579                      mhdf_Status* status )
00580 {
00581     hid_t tag_id;
00582     API_BEGIN;
00583     tag_id = create_tag_common( file_handle, tag_name, tag_type, size, storage, default_value, 1, global_value, 1,
00584                                 hdf_type, hdf_base_type, status );
00585     if( tag_id >= 0 ) H5Gclose( tag_id );
00586     API_END;
00587 }
00588 
00589 void mhdf_createVarLenTag( mhdf_FileHandle file_handle,
00590                            const char* tag_name,
00591                            enum mhdf_TagDataType tag_type,
00592                            int storage,
00593                            const void* default_value,
00594                            int default_value_length,
00595                            const void* global_value,
00596                            int global_value_length,
00597                            hid_t hdf_type,
00598                            hid_t hdf_base_type,
00599                            mhdf_Status* status )
00600 {
00601     hid_t tag_id;
00602     int one = 1;
00603 
00604     API_BEGIN;
00605     tag_id = create_tag_common( file_handle, tag_name, tag_type, -1, storage, default_value, default_value_length,
00606                                 global_value, global_value_length, hdf_type, hdf_base_type, status );
00607     if( tag_id >= 0 )
00608     {
00609         mhdf_create_scalar_attrib( tag_id, TAG_VARLEN_ATTRIB, H5T_NATIVE_INT, &one, status );
00610         H5Gclose( tag_id );
00611     }
00612     API_END;
00613 }
00614 
00615 int mhdf_getNumberTags( mhdf_FileHandle file_handle, mhdf_Status* status )
00616 {
00617     hid_t group_id;
00618     hsize_t result;
00619     FileHandle* file_ptr;
00620     API_BEGIN;
00621 
00622     /* Validate input */
00623 
00624     file_ptr = (FileHandle*)file_handle;
00625     if( !mhdf_check_valid_file( file_ptr, status ) ) return -1;
00626 
00627         /* Open the tags group */
00628 
00629 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
00630     group_id = H5Gopen2( file_ptr->hdf_handle, TAG_GROUP, H5P_DEFAULT );
00631 #else
00632     group_id = H5Gopen( file_ptr->hdf_handle, TAG_GROUP );
00633 #endif
00634     if( group_id < 0 )
00635     {
00636         mhdf_setFail( status, "H5Gopen(\"%s\") failed", TAG_GROUP );
00637         return -1;
00638     }
00639 
00640     /* Get number of objects in tags group */
00641 
00642     if( H5Gget_num_objs( group_id, &result ) < 0 )
00643     {
00644         mhdf_setFail( status, "Internal failure calling H5Gget_num_objs." );
00645         H5Gclose( group_id );
00646         return -1;
00647     }
00648 
00649     H5Gclose( group_id );
00650     mhdf_setOkay( status );
00651     API_END;
00652     return (int)result;
00653 }
00654 
00655 char** mhdf_getTagNames( mhdf_FileHandle file_handle, int* num_names_out, mhdf_Status* status )
00656 {
00657     hid_t group_id;
00658     FileHandle* file_ptr;
00659     hsize_t count, idx;
00660     char* name;
00661     char** result;
00662     ssize_t size;
00663     API_BEGIN;
00664 
00665     /* Validate input */
00666 
00667     file_ptr = (FileHandle*)file_handle;
00668     if( !mhdf_check_valid_file( file_ptr, status ) ) return NULL;
00669 
00670         /* Open the tags group */
00671 
00672 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
00673     group_id = H5Gopen2( file_ptr->hdf_handle, TAG_GROUP, H5P_DEFAULT );
00674 #else
00675     group_id = H5Gopen( file_ptr->hdf_handle, TAG_GROUP );
00676 #endif
00677     if( group_id < 0 )
00678     {
00679         mhdf_setFail( status, "H5Gopen(\"%s\") failed", TAG_GROUP );
00680         return NULL;
00681     }
00682 
00683     /* Get number of objects in tags group */
00684 
00685     if( H5Gget_num_objs( group_id, &count ) < 0 )
00686     {
00687         mhdf_setFail( status, "Internal failure calling H5Gget_num_objs." );
00688         H5Gclose( group_id );
00689         return NULL;
00690     }
00691 
00692     /* No tags? */
00693 
00694     *num_names_out = (int)count;
00695     if( count == 0 )
00696     {
00697         H5Gclose( group_id );
00698         mhdf_setOkay( status );
00699         return NULL;
00700     }
00701 
00702     /* Allocate string array */
00703 
00704     result = (char**)mhdf_malloc( sizeof( char* ) * count, status );
00705     if( NULL == result )
00706     {
00707         H5Gclose( group_id );
00708         return NULL;
00709     }
00710 
00711     /* Get names */
00712 
00713     for( idx = 0; idx < count; ++idx )
00714     {
00715         size = H5Gget_objname_by_idx( group_id, idx, NULL, 0 );
00716         if( size < 1 || NULL == ( name = (char*)mhdf_malloc( size + 1, status ) ) )
00717         {
00718             while( ( --idx ) > 0 )
00719                 free( result[idx] );
00720             free( result );
00721             H5Gclose( group_id );
00722             mhdf_setFail( status, "Internal failure calling H5Gget_objname_by_idx." );
00723             return NULL;
00724         }
00725 
00726         H5Gget_objname_by_idx( group_id, idx, name, size + 1 );
00727         if( !mhdf_path_to_name( name, name ) )
00728         {
00729             mhdf_setFail( status, "Invalid character string in internal file path: \"%s\"\n", name );
00730             return NULL;
00731         }
00732         result[idx] = name;
00733     }
00734 
00735     H5Gclose( group_id );
00736     mhdf_setOkay( status );
00737     API_END;
00738     return result;
00739 }
00740 
00741 static int get_attrib_array_length_handle( hid_t attrib_id )
00742 {
00743     hid_t type_id;
00744     int rank;
00745     hsize_t dims[H5S_MAX_RANK];
00746     int perm[H5S_MAX_RANK];
00747 
00748     type_id = H5Aget_type( attrib_id );
00749     switch( H5Tget_class( type_id ) )
00750     {
00751         case H5T_NO_CLASS:
00752             dims[0] = -1;
00753             break;
00754         case H5T_OPAQUE:
00755             dims[0] = H5Tget_size( type_id );
00756             break;
00757         case H5T_ARRAY:
00758 #if defined( H5Tget_array_dims_vers ) && H5Tget_array_dims_vers > 1
00759             (void)perm; /* suppress warning */
00760             rank = H5Tget_array_dims2( type_id, dims );
00761 #else
00762             rank = H5Tget_array_dims( type_id, dims, perm );
00763 #endif
00764             if( rank == 1 )
00765                 break;
00766             else
00767                 return -1;
00768         default:
00769             dims[0] = 1;
00770             break;
00771     }
00772 
00773     H5Tclose( type_id );
00774     return dims[0];
00775 }
00776 
00777 /*
00778 static int get_attrib_array_length_index( hid_t object_id, unsigned int index )
00779 {
00780   hid_t attrib_id;
00781   int result;
00782 
00783   attrib_id = H5Aopen_idx( object_id, index );
00784   if (attrib_id < 0)
00785     return -1;
00786 
00787   result = get_attrib_array_length_handle( attrib_id );
00788   H5Aclose( attrib_id );
00789   return result;
00790 }
00791 */
00792 
00793 static int get_attrib_array_length_name( hid_t file, const char* path )
00794 {
00795     hid_t attrib_id;
00796     int result;
00797 
00798     attrib_id = H5Aopen_name( file, path );
00799     if( attrib_id < 0 ) return -1;
00800 
00801     result = get_attrib_array_length_handle( attrib_id );
00802     H5Aclose( attrib_id );
00803     return result;
00804 }
00805 
00806 void mhdf_getTagInfo( mhdf_FileHandle file_handle,
00807                       const char* tag_name,
00808                       enum mhdf_TagDataType* class_out,
00809                       int* size_out,
00810                       int* tstt_storage_out,
00811                       int* have_default_out,
00812                       int* have_global_out,
00813                       int* have_sparse_out,
00814                       mhdf_Status* status )
00815 {
00816     hid_t tag_id, type_id, super_id;
00817     int i, rval, is_handle;
00818     hsize_t size, sup_size;
00819     unsigned int idx;
00820     int rank, var_data;
00821     hsize_t dims[H5S_MAX_RANK];
00822     int perm[H5S_MAX_RANK];
00823     H5T_class_t class_tmp;
00824 
00825     API_BEGIN;
00826 
00827     /* Validate input */
00828     if( NULL == tag_name || NULL == class_out || NULL == size_out || NULL == tstt_storage_out ||
00829         NULL == have_default_out || NULL == have_global_out || NULL == have_sparse_out )
00830     {
00831         mhdf_setFail( status, "Invalid input." );
00832         return;
00833     }
00834 
00835     /* Get group for tag */
00836     tag_id = get_tag( file_handle, tag_name, NULL, status );
00837     if( tag_id < 0 ) return;
00838 
00839     /* Check for sparse data */
00840     rval = mhdf_is_in_group( tag_id, SPARSE_ENTITY_NAME, status );
00841     if( rval < 0 )
00842     {
00843         H5Gclose( tag_id );
00844         return;
00845     }
00846     *have_sparse_out = rval ? 1 : 0;
00847 
00848     /* Check for variable-length tag data */
00849     rval = mhdf_find_attribute( tag_id, TAG_VARLEN_ATTRIB, &idx, status );
00850     if( rval < 0 )
00851     {
00852         H5Gclose( tag_id );
00853         return;
00854     }
00855     var_data = rval ? 1 : 0;
00856 
00857     /* Check if have default value for tag */
00858     rval = mhdf_find_attribute( tag_id, TAG_DEFAULT_ATTRIB, &idx, status );
00859     if( rval < 0 )
00860     {
00861         H5Gclose( tag_id );
00862         return;
00863     }
00864     if( !rval )
00865         *have_default_out = 0;
00866     else if( !var_data )
00867         *have_default_out = 1;
00868     else
00869     {
00870         /* *have_default_out = get_attrib_array_length_index( tag_id, index ); */
00871         *have_default_out = get_attrib_array_length_name( tag_id, TAG_DEFAULT_ATTRIB );
00872         if( *have_default_out < 0 )
00873         {
00874             mhdf_setFail( status, "Error checking length of default value for tag: %s\n", tag_name );
00875             H5Gclose( tag_id );
00876             return;
00877         }
00878     }
00879 
00880     /* Check if have global value for tag */
00881     rval = mhdf_find_attribute( tag_id, TAG_GLOBAL_ATTRIB, &idx, status );
00882     if( rval < 0 )
00883     {
00884         H5Gclose( tag_id );
00885         return;
00886     }
00887     if( !rval )
00888         *have_global_out = 0;
00889     else if( !var_data )
00890         *have_global_out = 1;
00891     else
00892     {
00893         /* *have_global_out = get_attrib_array_length_index( tag_id, index ); */
00894         *have_global_out = get_attrib_array_length_name( tag_id, TAG_GLOBAL_ATTRIB );
00895         if( *have_global_out < 0 )
00896         {
00897             mhdf_setFail( status, "Error checking length of global value for tag: %s\n", tag_name );
00898             H5Gclose( tag_id );
00899             return;
00900         }
00901     }
00902 
00903     /* Get TSTT tag class */
00904     rval = mhdf_read_scalar_attrib( tag_id, TAG_TYPE_ATTRIB, H5T_NATIVE_INT, tstt_storage_out, status );
00905     if( rval < 1 )
00906     {
00907         H5Gclose( tag_id );
00908         return;
00909     }
00910 
00911     /* Check if tag is storing entity handles */
00912     rval = mhdf_find_attribute( tag_id, TAG_HANDLE_TYPE_ATTRIB, &idx, status );
00913     if( rval < 0 )
00914     {
00915         H5Gclose( tag_id );
00916         return;
00917     }
00918     is_handle = rval;
00919 
00920     /* Get tag type */
00921 #if defined( H5Topen_vers ) && H5Topen_vers > 1
00922     type_id = H5Topen2( tag_id, TAG_TYPE_NAME, H5P_DEFAULT );
00923 #else
00924     type_id = H5Topen( tag_id, TAG_TYPE_NAME );
00925 #endif
00926     if( type_id < 0 )
00927     {
00928         H5Gclose( tag_id );
00929         mhdf_setFail( status, "Failed to get type object for tag \"%s\".", tag_name );
00930         return;
00931     }
00932 
00933     class_tmp = H5Tget_class( type_id );
00934     if( class_tmp < 0 )
00935     {
00936         mhdf_setFail( status, "H5Tget_class failed." );
00937         H5Gclose( tag_id );
00938         H5Tclose( type_id );
00939         return;
00940     }
00941 
00942     size = H5Tget_size( type_id );
00943     if( size <= 0 )
00944     {
00945         mhdf_setFail( status, "H5Tget_size failed." );
00946         H5Gclose( tag_id );
00947         H5Tclose( type_id );
00948         return;
00949     }
00950 
00951     switch( class_tmp )
00952     {
00953         case H5T_INTEGER:
00954             *class_out = ( size == 1 ) ? mhdf_BOOLEAN : mhdf_INTEGER;
00955             *size_out  = 1;
00956             break;
00957 
00958         case H5T_FLOAT:
00959             *class_out = mhdf_FLOAT;
00960             *size_out  = 1;
00961             break;
00962 
00963         case H5T_BITFIELD:
00964             *class_out = mhdf_BITFIELD;
00965             *size_out  = H5Tget_precision( type_id );
00966             if( *size_out <= 0 )
00967             {
00968                 mhdf_setFail( status, "H5Tget_precision failed." );
00969                 H5Gclose( tag_id );
00970                 H5Tclose( type_id );
00971                 return;
00972             }
00973             break;
00974 
00975         default:
00976         case H5T_OPAQUE:
00977             *class_out = mhdf_OPAQUE;
00978             *size_out  = size;
00979             break;
00980 
00981         case H5T_ARRAY:
00982 
00983 #if defined( H5Tget_array_dims_vers ) && H5Tget_array_dims_vers > 1
00984             (void)perm; /* suppress warning */
00985             rank = H5Tget_array_dims2( type_id, dims );
00986 #else
00987             rank      = H5Tget_array_dims( type_id, dims, perm );
00988 #endif
00989             if( rank <= 0 )
00990             {
00991                 mhdf_setFail( status, "H5Tget_size failed." );
00992                 H5Gclose( tag_id );
00993                 H5Tclose( type_id );
00994                 return;
00995             }
00996             for( i = 1; i < rank; ++i )
00997                 dims[0] *= dims[i];
00998 
00999             super_id = H5Tget_super( type_id );
01000             if( super_id < 0 )
01001             {
01002                 mhdf_setFail( status, "H5Tget_super failed" );
01003                 H5Gclose( tag_id );
01004                 H5Tclose( type_id );
01005                 return;
01006             }
01007 
01008             class_tmp = H5Tget_class( super_id );
01009             if( class_tmp < 0 )
01010             {
01011                 mhdf_setFail( status, "H5Tget_class failed." );
01012                 H5Gclose( tag_id );
01013                 H5Tclose( type_id );
01014                 H5Tclose( super_id );
01015                 return;
01016             }
01017 
01018             sup_size = H5Tget_size( super_id );
01019             H5Tclose( super_id );
01020             if( sup_size <= 0 )
01021             {
01022                 mhdf_setFail( status, "H5Tget_size failed." );
01023                 H5Gclose( tag_id );
01024                 H5Tclose( type_id );
01025                 return;
01026             }
01027 
01028             switch( class_tmp )
01029             {
01030                 case H5T_INTEGER:
01031                     *class_out = ( sup_size == 1 ) ? mhdf_BOOLEAN : mhdf_INTEGER;
01032                     *size_out  = dims[0];
01033                     break;
01034 
01035                 case H5T_FLOAT:
01036                     *class_out = mhdf_FLOAT;
01037                     *size_out  = dims[0];
01038                     break;
01039 
01040                 default:
01041                     *class_out = mhdf_OPAQUE;
01042                     *size_out  = size;
01043                     break;
01044             }
01045 
01046             break;
01047     }
01048     H5Tclose( type_id );
01049     H5Gclose( tag_id );
01050 
01051     if( is_handle )
01052     {
01053         if( *class_out != mhdf_INTEGER )
01054         {
01055             mhdf_setFail( status, "Non-integer tag marked as handle type." );
01056             return;
01057         }
01058         *class_out = mhdf_ENTITY_ID;
01059     }
01060 
01061     if( var_data )
01062     {
01063         if( *size_out != 1 || *class_out == mhdf_BITFIELD )
01064         {
01065             mhdf_setFail( status, "Invalid or unexpected variable-length tag data" );
01066             return;
01067         }
01068         *size_out = -1;
01069     }
01070 
01071     mhdf_setOkay( status );
01072     API_END;
01073 }
01074 
01075 static int read_tag_attrib_data( hid_t tag_id,
01076                                  const char* attrib_name,
01077                                  hid_t type_id,
01078                                  void* data,
01079                                  int is_var_len,
01080                                  mhdf_Status* status )
01081 {
01082     int rval, ilen;
01083     unsigned idx;
01084     hid_t read_type = type_id;
01085     hsize_t len;
01086 
01087     /* Check if tag has attribute */
01088     rval = mhdf_find_attribute( tag_id, attrib_name, &idx, status );
01089     if( rval < 0 )
01090         return 0;
01091     else if( 0 == rval )
01092         return 1;
01093 
01094     if( NULL == data )
01095     {
01096         mhdf_setFail( status, "Invalid input." );
01097         return 0;
01098     }
01099 
01100     if( is_var_len )
01101     {
01102         /* len = get_attrib_array_length_index(tag_id, index); */
01103         ilen = get_attrib_array_length_name( tag_id, attrib_name );
01104         if( ilen < 0 )
01105         {
01106             mhdf_setFail( status, "Failed to read length of default/mesh value for tag" );
01107             return 0;
01108         }
01109         len = ilen;
01110 
01111         /* caller passes type_id == 0 for OPAQUE */
01112         if( 0 == type_id )
01113             read_type = H5Tcreate( H5T_OPAQUE, len );
01114         else
01115         {
01116 #if defined( H5Tarray_create_vers ) && H5Tarray_create_vers > 1
01117             read_type = H5Tarray_create2( type_id, 1, &len );
01118 #else
01119             read_type = H5Tarray_create( type_id, 1, &len, 0 );
01120 #endif
01121         }
01122         if( read_type < 0 )
01123         {
01124             mhdf_setFail( status, "Failed to read mesh/default value for tag" );
01125             return 0;
01126         }
01127     }
01128 
01129     rval = mhdf_read_scalar_attrib( tag_id, attrib_name, read_type, data, status );
01130     if( is_var_len ) H5Tclose( read_type );
01131 
01132     return rval;
01133 }
01134 
01135 void mhdf_getTagValues( mhdf_FileHandle file_handle,
01136                         const char* tag_name,
01137                         hid_t output_data_type,
01138                         void* default_value,
01139                         void* global_value,
01140                         mhdf_Status* status )
01141 {
01142     hid_t tag_id;
01143     int rval, var_data;
01144     unsigned int idx;
01145     API_BEGIN;
01146 
01147     /* check args */
01148     if( NULL == tag_name || !*tag_name )
01149     {
01150         mhdf_setFail( status, "Invalid input." );
01151         return;
01152     }
01153 
01154     /* Get the tag group */
01155     tag_id = get_tag( file_handle, tag_name, NULL, status );
01156     if( tag_id < 0 ) return;
01157 
01158     /* Check for variable-length tag data */
01159     rval = mhdf_find_attribute( tag_id, TAG_VARLEN_ATTRIB, &idx, status );
01160     if( rval < 0 )
01161     {
01162         H5Gclose( tag_id );
01163         return;
01164     }
01165     var_data = rval ? 1 : 0;
01166 
01167     /* Read default value if present */
01168     rval = read_tag_attrib_data( tag_id, TAG_DEFAULT_ATTRIB, output_data_type, default_value, var_data, status );
01169     if( !rval )
01170     {
01171         H5Gclose( tag_id );
01172         return;
01173     }
01174 
01175     /* Read mesh value if present */
01176     rval = read_tag_attrib_data( tag_id, TAG_GLOBAL_ATTRIB, output_data_type, global_value, var_data, status );
01177     if( !rval )
01178     {
01179         H5Gclose( tag_id );
01180         return;
01181     }
01182 
01183     H5Gclose( tag_id );
01184     mhdf_setOkay( status );
01185     API_END;
01186 }
01187 
01188 int mhdf_haveDenseTag( mhdf_FileHandle file_handle, const char* tag_name, const char* type_handle, mhdf_Status* status )
01189 {
01190     char* path;
01191     hid_t elem_id, group_id;
01192     FileHandle* file_ptr;
01193     int rval = 0;
01194     API_BEGIN;
01195 
01196     file_ptr = (FileHandle*)file_handle;
01197     if( !mhdf_check_valid_file( file_ptr, status ) ) return -1;
01198 
01199     if( type_handle == mhdf_node_type_handle() )
01200     {
01201 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
01202         elem_id = H5Gopen2( file_ptr->hdf_handle, NODE_GROUP, H5P_DEFAULT );
01203 #else
01204         elem_id = H5Gopen( file_ptr->hdf_handle, NODE_GROUP );
01205 #endif
01206         if( elem_id < 0 ) mhdf_setFail( status, "Could not open node group." );
01207     }
01208     else if( type_handle == mhdf_set_type_handle() )
01209     {
01210 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
01211         elem_id = H5Gopen2( file_ptr->hdf_handle, SET_GROUP, H5P_DEFAULT );
01212 #else
01213         elem_id = H5Gopen( file_ptr->hdf_handle, SET_GROUP );
01214 #endif
01215         if( elem_id < 0 ) mhdf_setFail( status, "Could not open set group." );
01216     }
01217     else
01218     {
01219         elem_id = mhdf_elem_group_from_handle( file_ptr, type_handle, status );
01220     }
01221     if( elem_id < 0 ) return -1;
01222 
01223     rval = mhdf_is_in_group( elem_id, TAG_GROUP_NAME, status );
01224     if( rval < 0 )
01225     {
01226         H5Gclose( elem_id );
01227         return -1;
01228     }
01229     else if( rval == 0 )
01230     {
01231         H5Gclose( elem_id );
01232         mhdf_setOkay( status );
01233         return 0;
01234     }
01235 
01236 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
01237     group_id = H5Gopen2( elem_id, DENSE_TAG_SUBGROUP, H5P_DEFAULT );
01238 #else
01239     group_id = H5Gopen( elem_id, DENSE_TAG_SUBGROUP );
01240 #endif
01241     H5Gclose( elem_id );
01242     if( group_id < 0 )
01243     {
01244         mhdf_setFail( status, "Could not open tag subgroup." );
01245         return -1;
01246     }
01247 
01248     path = mhdf_name_to_path_copy( tag_name, status );
01249     if( NULL == path )
01250     {
01251         H5Gclose( group_id );
01252         return -1;
01253     }
01254 
01255     rval = mhdf_is_in_group( group_id, path, status );
01256     H5Gclose( group_id );
01257     free( path );
01258 
01259     if( rval >= 0 )
01260     {
01261         mhdf_setOkay( status );
01262     }
01263 
01264     API_END;
01265     return rval;
01266 }
01267 
01268 hid_t mhdf_createDenseTagData( mhdf_FileHandle file_handle,
01269                                const char* tag_name,
01270                                const char* type_handle,
01271                                long num_values,
01272                                mhdf_Status* status )
01273 {
01274     char* path;
01275     hid_t elem_id, data_id, type_id;
01276     FileHandle* file_ptr;
01277     size_t name_len, path_len, dir_len;
01278     hsize_t size;
01279     API_BEGIN;
01280 
01281     file_ptr = (FileHandle*)file_handle;
01282     if( !mhdf_check_valid_file( file_ptr, status ) ) return -1;
01283 
01284     if( type_handle == mhdf_node_type_handle() )
01285     {
01286 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
01287         elem_id = H5Gopen2( file_ptr->hdf_handle, NODE_GROUP, H5P_DEFAULT );
01288 #else
01289         elem_id = H5Gopen( file_ptr->hdf_handle, NODE_GROUP );
01290 #endif
01291         if( elem_id < 0 ) mhdf_setFail( status, "Could not open node group." );
01292     }
01293     else if( type_handle == mhdf_set_type_handle() )
01294     {
01295 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
01296         elem_id = H5Gopen2( file_ptr->hdf_handle, SET_GROUP, H5P_DEFAULT );
01297 #else
01298         elem_id = H5Gopen( file_ptr->hdf_handle, SET_GROUP );
01299 #endif
01300         if( elem_id < 0 ) mhdf_setFail( status, "Could not open set group." );
01301     }
01302     else
01303     {
01304         elem_id = mhdf_elem_group_from_handle( file_ptr, type_handle, status );
01305     }
01306     if( elem_id < 0 ) return -1;
01307 
01308     dir_len  = strlen( DENSE_TAG_SUBGROUP );
01309     name_len = mhdf_name_to_path( tag_name, NULL, 0 );
01310     path_len = dir_len + name_len + 1;
01311     path     = (char*)mhdf_malloc( path_len, status );
01312     if( NULL == path )
01313     {
01314         H5Gclose( elem_id );
01315         return -1;
01316     }
01317     strcpy( path, DENSE_TAG_SUBGROUP );
01318     mhdf_name_to_path( tag_name, path + dir_len, name_len + 1 );
01319 
01320     type_id = get_tag_type( file_ptr, path + dir_len, status );
01321     if( type_id < 0 )
01322     {
01323         H5Gclose( elem_id );
01324         return -1;
01325     }
01326 
01327     size    = (hsize_t)num_values;
01328     data_id = mhdf_create_table( elem_id, path, type_id, 1, &size, status );
01329     free( path );
01330     H5Gclose( elem_id );
01331     H5Tclose( type_id );
01332 
01333     if( data_id > 0 ) mhdf_setOkay( status );
01334 
01335     API_END_H( 1 );
01336     return data_id;
01337 }
01338 
01339 hid_t mhdf_openDenseTagData( mhdf_FileHandle file_handle,
01340                              const char* tag_name,
01341                              const char* type_handle,
01342                              long* num_values_out,
01343                              mhdf_Status* status )
01344 {
01345     char* path;
01346     hid_t elem_id, data_id;
01347     FileHandle* file_ptr;
01348     size_t name_len, path_len, dir_len;
01349     hsize_t size;
01350     API_BEGIN;
01351 
01352     file_ptr = (FileHandle*)file_handle;
01353     if( !mhdf_check_valid_file( file_ptr, status ) ) return -1;
01354 
01355     if( type_handle == mhdf_node_type_handle() )
01356     {
01357 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
01358         elem_id = H5Gopen2( file_ptr->hdf_handle, NODE_GROUP, H5P_DEFAULT );
01359 #else
01360         elem_id = H5Gopen( file_ptr->hdf_handle, NODE_GROUP );
01361 #endif
01362         if( elem_id < 0 ) mhdf_setFail( status, "Could not open node group." );
01363     }
01364     else if( type_handle == mhdf_set_type_handle() )
01365     {
01366 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
01367         elem_id = H5Gopen2( file_ptr->hdf_handle, SET_GROUP, H5P_DEFAULT );
01368 #else
01369         elem_id = H5Gopen( file_ptr->hdf_handle, SET_GROUP );
01370 #endif
01371         if( elem_id < 0 ) mhdf_setFail( status, "Could not open set group." );
01372     }
01373     else
01374     {
01375         elem_id = mhdf_elem_group_from_handle( file_ptr, type_handle, status );
01376     }
01377     if( elem_id < 0 ) return -1;
01378 
01379     dir_len  = strlen( DENSE_TAG_SUBGROUP );
01380     name_len = mhdf_name_to_path( tag_name, NULL, 0 );
01381     path_len = dir_len + name_len + 1;
01382     path     = (char*)mhdf_malloc( path_len, status );
01383     if( NULL == path )
01384     {
01385         H5Gclose( elem_id );
01386         return -1;
01387     }
01388     strcpy( path, DENSE_TAG_SUBGROUP );
01389     mhdf_name_to_path( tag_name, path + dir_len, name_len + 1 );
01390 
01391     data_id = mhdf_open_table( elem_id, path, 1, &size, status );
01392     free( path );
01393     H5Gclose( elem_id );
01394     *num_values_out = (long)size;
01395 
01396     if( data_id >= 0 ) mhdf_setOkay( status );
01397 
01398     API_END_H( 1 );
01399     return data_id;
01400 }
01401 
01402 void mhdf_createSparseTagData( mhdf_FileHandle file_handle,
01403                                const char* tag_name,
01404                                long num_values,
01405                                hid_t handles_out[2],
01406                                mhdf_Status* status )
01407 {
01408     hid_t tag_id, index_id, data_id, type_id, id_type;
01409     hsize_t count = (hsize_t)num_values;
01410     API_BEGIN;
01411 
01412     tag_id = get_tag( file_handle, tag_name, &id_type, status );
01413     if( tag_id < 0 ) return;
01414 
01415 #if defined( H5Topen_vers ) && H5Topen_vers > 1
01416     type_id = H5Topen2( tag_id, TAG_TYPE_NAME, H5P_DEFAULT );
01417 #else
01418     type_id = H5Topen( tag_id, TAG_TYPE_NAME );
01419 #endif
01420     if( type_id < 0 )
01421     {
01422         H5Gclose( tag_id );
01423         mhdf_setFail( status, "Failed to get type object for tag \"%s\".", tag_name );
01424         return;
01425     }
01426 
01427     index_id = mhdf_create_table( tag_id, SPARSE_ENTITY_NAME, id_type, 1, &count, status );
01428     if( index_id < 0 )
01429     {
01430         H5Gclose( tag_id );
01431         H5Tclose( type_id );
01432         return;
01433     }
01434 
01435     data_id = mhdf_create_table( tag_id, SPARSE_VALUES_NAME, type_id, 1, &count, status );
01436     H5Tclose( type_id );
01437     H5Gclose( tag_id );
01438     if( data_id < 0 )
01439     {
01440         H5Dclose( index_id );
01441         return;
01442     }
01443 
01444     handles_out[0] = index_id;
01445     handles_out[1] = data_id;
01446     mhdf_setOkay( status );
01447     API_END_H( 2 );
01448 }
01449 
01450 void mhdf_createVarLenTagData( mhdf_FileHandle file_handle,
01451                                const char* tag_name,
01452                                long num_entities,
01453                                long num_values,
01454                                hid_t handles_out[3],
01455                                mhdf_Status* status )
01456 {
01457     hid_t tag_id, index_id, data_id, type_id, offset_id, id_type;
01458     hsize_t count = (hsize_t)num_entities;
01459     API_BEGIN;
01460 
01461     tag_id = get_tag( file_handle, tag_name, &id_type, status );
01462     if( tag_id < 0 ) return;
01463 
01464 #if defined( H5Topen_vers ) && H5Topen_vers > 1
01465     type_id = H5Topen2( tag_id, TAG_TYPE_NAME, H5P_DEFAULT );
01466 #else
01467     type_id = H5Topen( tag_id, TAG_TYPE_NAME );
01468 #endif
01469     if( type_id < 0 )
01470     {
01471         H5Gclose( tag_id );
01472         mhdf_setFail( status, "Failed to get type object for tag \"%s\".", tag_name );
01473         return;
01474     }
01475 
01476     index_id = mhdf_create_table( tag_id, SPARSE_ENTITY_NAME, id_type, 1, &count, status );
01477     if( index_id < 0 )
01478     {
01479         H5Gclose( tag_id );
01480         H5Tclose( type_id );
01481         return;
01482     }
01483 
01484     offset_id = mhdf_create_table( tag_id, TAG_VAR_INDICES, MHDF_INDEX_TYPE, 1, &count, status );
01485     if( index_id < 0 )
01486     {
01487         H5Dclose( offset_id );
01488         H5Gclose( tag_id );
01489         H5Tclose( type_id );
01490         return;
01491     }
01492 
01493     count   = (hsize_t)num_values;
01494     data_id = mhdf_create_table( tag_id, SPARSE_VALUES_NAME, type_id, 1, &count, status );
01495     H5Tclose( type_id );
01496     H5Gclose( tag_id );
01497     if( data_id < 0 )
01498     {
01499         H5Dclose( offset_id );
01500         H5Dclose( index_id );
01501         return;
01502     }
01503 
01504     handles_out[0] = index_id;
01505     handles_out[1] = data_id;
01506     handles_out[2] = offset_id;
01507     mhdf_setOkay( status );
01508     API_END_H( 3 );
01509 }
01510 
01511 void mhdf_openSparseTagData( mhdf_FileHandle file_handle,
01512                              const char* tag_name,
01513                              long* num_entity_out,
01514                              long* num_values_out,
01515                              hid_t handles_out[3],
01516                              mhdf_Status* status )
01517 {
01518     hid_t tag_id, index_id, data_id, offset_id = -1;
01519     hsize_t num_ent, data_size, num_data;
01520     int rval;
01521     unsigned idx;
01522     API_BEGIN;
01523 
01524     tag_id = get_tag( file_handle, tag_name, NULL, status );
01525     if( tag_id < 0 ) return;
01526 
01527     index_id = mhdf_open_table( tag_id, SPARSE_ENTITY_NAME, 1, &num_ent, status );
01528     if( index_id < 0 )
01529     {
01530         H5Gclose( tag_id );
01531         return;
01532     }
01533 
01534     data_id = mhdf_open_table( tag_id, SPARSE_VALUES_NAME, 1, &data_size, status );
01535     if( data_id < 0 )
01536     {
01537         H5Gclose( tag_id );
01538         H5Dclose( index_id );
01539         return;
01540     }
01541 
01542     /* check if tag is variable-lentgth */
01543     rval = mhdf_find_attribute( tag_id, TAG_VARLEN_ATTRIB, &idx, status );
01544     if( rval < 0 )
01545     {
01546         H5Gclose( tag_id );
01547         H5Dclose( index_id );
01548         H5Dclose( data_id );
01549         return;
01550     }
01551 
01552     /* If variable length... */
01553     if( rval )
01554     {
01555         offset_id = mhdf_open_table( tag_id, TAG_VAR_INDICES, 1, &num_data, status );
01556         if( offset_id < 0 )
01557         {
01558             H5Gclose( tag_id );
01559             H5Dclose( index_id );
01560             H5Dclose( data_id );
01561             return;
01562         }
01563     }
01564     /* Otherwise the number of values is the same as the size of the data table */
01565     else
01566     {
01567         num_data = data_size;
01568     }
01569 
01570     H5Gclose( tag_id );
01571     if( num_ent != num_data )
01572     {
01573         mhdf_setFail( status, "Data length mismatch for sparse tag data -- invalid file." );
01574         if( offset_id >= 0 ) H5Dclose( offset_id );
01575         H5Dclose( index_id );
01576         H5Dclose( data_id );
01577         return;
01578     }
01579     *num_entity_out = (long)num_ent;
01580     if( num_values_out ) *num_values_out = (long)data_size;
01581 
01582     handles_out[0] = index_id;
01583     handles_out[1] = data_id;
01584     if( offset_id >= 0 ) handles_out[2] = offset_id;
01585     mhdf_setOkay( status );
01586     API_END_H( 2 );
01587 }
01588 
01589 void mhdf_writeSparseTagEntities( hid_t table_id,
01590                                   long offset,
01591                                   long count,
01592                                   hid_t int_type,
01593                                   const void* id_list,
01594                                   mhdf_Status* status )
01595 {
01596     API_BEGIN;
01597     mhdf_write_data( table_id, offset, count, int_type, id_list, H5P_DEFAULT, status );
01598     API_END;
01599 }
01600 void mhdf_writeSparseTagEntitiesWithOpt( hid_t table_id,
01601                                          long offset,
01602                                          long count,
01603                                          hid_t int_type,
01604                                          const void* id_list,
01605                                          hid_t io_prop,
01606                                          mhdf_Status* status )
01607 {
01608     API_BEGIN;
01609     mhdf_write_data( table_id, offset, count, int_type, id_list, io_prop, status );
01610     API_END;
01611 }
01612 
01613 void mhdf_writeTagValues( hid_t table_id,
01614                           long offset,
01615                           long count,
01616                           hid_t tag_type,
01617                           const void* tag_data,
01618                           mhdf_Status* status )
01619 {
01620     mhdf_writeTagValuesWithOpt( table_id, offset, count, tag_type, tag_data, H5P_DEFAULT, status );
01621 }
01622 
01623 void mhdf_writeTagValuesWithOpt( hid_t table_id,
01624                                  long offset,
01625                                  long count,
01626                                  hid_t tag_type,
01627                                  const void* tag_data,
01628                                  hid_t io_prop,
01629                                  mhdf_Status* status )
01630 {
01631     API_BEGIN;
01632     mhdf_write_data( table_id, offset, count, tag_type, tag_data, io_prop, status );
01633     API_END;
01634 }
01635 
01636 void mhdf_writeSparseTagIndices( hid_t table_id,
01637                                  long offset,
01638                                  long count,
01639                                  hid_t int_type,
01640                                  const void* indices,
01641                                  mhdf_Status* status )
01642 {
01643     API_BEGIN;
01644     mhdf_write_data( table_id, offset, count, int_type, indices, H5P_DEFAULT, status );
01645     API_END;
01646 }
01647 void mhdf_writeSparseTagIndicesWithOpt( hid_t table_id,
01648                                         long offset,
01649                                         long count,
01650                                         hid_t int_type,
01651                                         const void* indices,
01652                                         hid_t io_prop,
01653                                         mhdf_Status* status )
01654 {
01655     API_BEGIN;
01656     mhdf_write_data( table_id, offset, count, int_type, indices, io_prop, status );
01657     API_END;
01658 }
01659 
01660 void mhdf_readSparseTagEntities( hid_t table_id,
01661                                  long offset,
01662                                  long count,
01663                                  hid_t int_type,
01664                                  void* id_list,
01665                                  mhdf_Status* status )
01666 {
01667     API_BEGIN;
01668     mhdf_read_data( table_id, offset, count, int_type, id_list, H5P_DEFAULT, status );
01669     API_END;
01670 }
01671 void mhdf_readSparseTagEntitiesWithOpt( hid_t table_id,
01672                                         long offset,
01673                                         long count,
01674                                         hid_t int_type,
01675                                         void* id_list,
01676                                         hid_t io_prop,
01677                                         mhdf_Status* status )
01678 {
01679     API_BEGIN;
01680     mhdf_read_data( table_id, offset, count, int_type, id_list, io_prop, status );
01681     API_END;
01682 }
01683 
01684 void mhdf_readTagValues( hid_t table_id, long offset, long count, hid_t tag_type, void* tag_data, mhdf_Status* status )
01685 {
01686     mhdf_readTagValuesWithOpt( table_id, offset, count, tag_type, tag_data, H5P_DEFAULT, status );
01687 }
01688 void mhdf_readTagValuesWithOpt( hid_t table_id,
01689                                 long offset,
01690                                 long count,
01691                                 hid_t tag_type,
01692                                 void* tag_data,
01693                                 hid_t io_prop,
01694                                 mhdf_Status* status )
01695 {
01696     API_BEGIN;
01697     mhdf_read_data( table_id, offset, count, tag_type, tag_data, io_prop, status );
01698     API_END;
01699 }
01700 
01701 void mhdf_readSparseTagIndices( hid_t table_id,
01702                                 long offset,
01703                                 long count,
01704                                 hid_t int_type,
01705                                 void* indices,
01706                                 mhdf_Status* status )
01707 {
01708     API_BEGIN;
01709     mhdf_read_data( table_id, offset, count, int_type, indices, H5P_DEFAULT, status );
01710     API_END;
01711 }
01712 void mhdf_readSparseTagIndicesWithOpt( hid_t table_id,
01713                                        long offset,
01714                                        long count,
01715                                        hid_t int_type,
01716                                        void* indices,
01717                                        hid_t io_prop,
01718                                        mhdf_Status* status )
01719 {
01720     API_BEGIN;
01721     mhdf_read_data( table_id, offset, count, int_type, indices, io_prop, status );
01722     API_END;
01723 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines