MOAB: Mesh Oriented datABase  (version 5.2.1)
util.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 <assert.h>
00019 #include <ctype.h>
00020 #include <hdf5.h>
00021 #include "util.h"
00022 #include "status.h"
00023 #include "names-and-paths.h"
00024 
00025 #ifdef VALGRIND
00026 #include <valgrind/memcheck.h>
00027 #else
00028 #define VALGRIND_CHECK_MEM_IS_DEFINED( A, B )
00029 #define VALGRIND_MAKE_MEM_UNDEFINED( A, B )
00030 #endif
00031 
00032 void* mhdf_malloc( size_t size, mhdf_Status* status )
00033 {
00034     void* result;
00035     result = malloc( size );
00036     if( !result ) mhdf_setFail( status, "Allocation of %d bytes failed.\n", (int)size );
00037     return result;
00038 }
00039 
00040 void* mhdf_realloc( void* ptr, size_t size, mhdf_Status* status )
00041 {
00042     void* result;
00043     result = realloc( ptr, size );
00044     if( !result ) mhdf_setFail( status, "Allocation of %d bytes failed.\n", (int)size );
00045     return result;
00046 }
00047 
00048 size_t mhdf_name_to_path( const char* name, char* path, size_t path_len )
00049 {
00050     size_t         length = 1;
00051     unsigned char* iter;
00052 
00053     if( 0 == strcmp( name, "." ) )
00054     {
00055         if( path_len >= 4 ) sprintf( path, "\\%02X", (int)*name );
00056         return 4;
00057     }
00058 
00059     for( iter = (unsigned char*)name; *iter; ++iter )
00060     {
00061         if( iscntrl( *iter ) || *iter == '/' || *iter == '\\' || *iter > 127 )
00062             length += 3;
00063         else
00064             length += 1;
00065     }
00066     if( path_len < length ) return length;
00067 
00068     for( iter = (unsigned char*)name; *iter; ++iter )
00069     {
00070         if( iscntrl( *iter ) || *iter == '/' || *iter == '\\' || *iter > 127 )
00071         {
00072             sprintf( path, "\\%02X", (int)( *iter ) );
00073             path += 3;
00074         }
00075         else
00076         {
00077             *( path++ ) = *iter;
00078         }
00079     }
00080 
00081     *path = '\0';
00082     return length;
00083 }
00084 
00085 static int mhdf_hex_char( int c )
00086 {
00087     if( isdigit( c ) )
00088         return c - '0';
00089     else
00090         return toupper( c ) - ( 'A' - 10 );
00091 }
00092 
00093 int mhdf_path_to_name( const char* path, char* name )
00094 {
00095     const char* iter;
00096     char        c1, c2;
00097 
00098     for( iter = path; *iter; ++iter, ++name )
00099     {
00100         if( *iter == '\\' )
00101         {
00102             c1 = *++iter;
00103             c2 = *++iter;
00104             if( !isxdigit( c1 ) || !isxdigit( c2 ) ) return 0;
00105 
00106             *name = (char)( 16 * mhdf_hex_char( c1 ) + mhdf_hex_char( c2 ) );
00107         }
00108         else
00109         {
00110             *name = *iter;
00111         }
00112     }
00113 
00114     *name = '\0';
00115     return 1;
00116 }
00117 
00118 char* mhdf_name_to_path_copy( const char* name, mhdf_Status* status )
00119 {
00120     size_t size;
00121     char*  buffer;
00122 
00123     size = mhdf_name_to_path( name, NULL, 0 );
00124     buffer = (char*)mhdf_malloc( size, status );
00125     if( !buffer ) return NULL;
00126 
00127     mhdf_name_to_path( name, buffer, size );
00128     return buffer;
00129 }
00130 
00131 char* mhdf_name_to_path_cat( const char* prefix, const char* name, mhdf_Status* status )
00132 {
00133     size_t size, plen;
00134     char*  buffer;
00135 
00136     plen = strlen( prefix );
00137     size = mhdf_name_to_path( name, NULL, 0 ) + 1;
00138     buffer = (char*)mhdf_malloc( size + plen, status );
00139     if( !buffer ) return NULL;
00140 
00141     memcpy( buffer, prefix, plen );
00142     mhdf_name_to_path( name, buffer + plen, size );
00143     return buffer;
00144 }
00145 
00146 hid_t mhdf_elem_group_from_handle( FileHandle* file_ptr, const char* elem_handle, mhdf_Status* status )
00147 {
00148     char* path;
00149     hid_t result;
00150 
00151     path = mhdf_name_to_path_cat( ELEMENT_GROUP, elem_handle, status );
00152     if( NULL == path ) return -1;
00153 
00154 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
00155     result = H5Gopen2( file_ptr->hdf_handle, path, H5P_DEFAULT );
00156 #else
00157     result = H5Gopen( file_ptr->hdf_handle, path );
00158 #endif
00159     free( path );
00160     if( result < 0 ) mhdf_setFail( status, "Failed to open element group: \"%s\"", elem_handle );
00161     return result;
00162 }
00163 
00164 int mhdf_create_scalar_attrib( hid_t object, const char* name, hid_t type, const void* value, mhdf_Status* status )
00165 {
00166     hid_t  dspace_id, attr_id;
00167     herr_t rval;
00168 
00169     dspace_id = H5Screate( H5S_SCALAR );
00170     if( dspace_id < 0 )
00171     {
00172         mhdf_setFail( status, "Internal error calling H5Screate_simple." );
00173         return 0;
00174     }
00175 
00176 #if defined( H5Acreate_vers ) && H5Acreate_vers > 1
00177     attr_id = H5Acreate2( object, name, type, dspace_id, H5P_DEFAULT, H5P_DEFAULT );
00178 #else
00179     attr_id = H5Acreate( object, name, type, dspace_id, H5P_DEFAULT );
00180 #endif
00181     H5Sclose( dspace_id );
00182     if( attr_id < 0 )
00183     {
00184         mhdf_setFail( status, "Failed to create \"%s\" attrib.", name );
00185         return 0;
00186     }
00187 
00188     VALGRIND_CHECK_MEM_IS_DEFINED( value, H5Tget_size( type ) );
00189     rval = H5Awrite( attr_id, type, value );
00190     H5Aclose( attr_id );
00191     if( rval < 0 )
00192     {
00193         mhdf_setFail( status, "Failed to write \"%s\" attrib.", name );
00194         return 0;
00195     }
00196 
00197     return 1;
00198 }
00199 
00200 int mhdf_read_scalar_attrib( hid_t object, const char* name, hid_t type, void* value, mhdf_Status* status )
00201 {
00202     hid_t  attr_id, type_id;
00203     herr_t rval;
00204 
00205     attr_id = H5Aopen_name( object, name );
00206     if( attr_id < 0 )
00207     {
00208         mhdf_setFail( status, "Failed to create \"%s\" attrib.", name );
00209         return 0;
00210     }
00211 
00212     if( type > 0 ) { type_id = type; }
00213     else
00214     {
00215         type_id = H5Aget_type( attr_id );
00216         if( type_id < 0 )
00217         {
00218             H5Aclose( attr_id );
00219             return 0;
00220         }
00221     }
00222 
00223     rval = H5Aread( attr_id, type_id, value );
00224     H5Aclose( attr_id );
00225     if( type < 1 ) H5Tclose( type_id );
00226     if( rval < 0 )
00227     {
00228         mhdf_setFail( status, "Failed to read \"%s\" attrib.", name );
00229         return 0;
00230     }
00231 
00232     return 1;
00233 }
00234 
00235 #if defined( H5Aiterate_vers ) && H5Aiterate_vers > 1
00236 static herr_t find_attr_by_name( hid_t handle, const char* name, const H5A_info_t* info, void* mydata )
00237 {
00238     /* empty statement to remove compiler warning */
00239     if( info ) {}
00240 #else
00241 static herr_t find_attr_by_name( hid_t handle, const char* name, void* mydata )
00242 {
00243 #endif
00244     /* empty statement to remove compiler warning */
00245     if( handle ) {}
00246     return !strcmp( name, (const char*)mydata );
00247 }
00248 
00249 int mhdf_find_attribute( hid_t object, const char* attrib_name, unsigned int* index_out, mhdf_Status* status )
00250 {
00251     herr_t rval;
00252 #if defined( H5Aiterate_vers ) && H5Aiterate_vers > 1
00253     hsize_t idx = 0;
00254     rval = H5Aiterate2( object, H5_INDEX_CRT_ORDER, H5_ITER_NATIVE, &idx, &find_attr_by_name, (void*)attrib_name );
00255     *index_out = (unsigned int)idx;
00256 #else
00257     *index_out = 0;
00258     rval = H5Aiterate( object, index_out, &find_attr_by_name, (void*)attrib_name );
00259 #endif
00260     if( rval < 0 ) mhdf_setFail( status, "Internal error calling H5Aiterate." );
00261     return (int)rval;
00262 }
00263 
00264 static herr_t find_link_by_name( hid_t handle, const char* name, void* mydata )
00265 {
00266     /* empty statement to remove compiler warning */
00267     if( handle ) {}
00268     return !strcmp( name, (const char*)mydata );
00269 }
00270 
00271 int mhdf_is_in_group( hid_t group, const char* name, mhdf_Status* status )
00272 {
00273     int rval;
00274     rval = H5Giterate( group, ".", NULL, &find_link_by_name, (void*)name );
00275     if( rval < 0 ) mhdf_setFail( status, "Internal error in H5Giterate." );
00276     return rval;
00277 }
00278 
00279 static int mhdf_readwrite( hid_t data_id, int read, long offset, long count, hid_t type, void* array, hid_t io_prop,
00280                            mhdf_Status* status )
00281 {
00282     hid_t   slab_id, mem_id;
00283     hsize_t offsets[ 2 ], counts[ 2 ] = { 1, 1 };
00284     herr_t  rval;
00285     int     dims;
00286     /*#if (1000 * H5_VERS_MAJOR + H5_VERS_MINOR) < 1008*/
00287     const hsize_t one = 1;
00288     /*#endif*/
00289 
00290     if( offset < 0 || count < 0 )
00291     {
00292         mhdf_setFail( status,
00293                       "Invalid input for %s: "
00294                       "offset = %ld, count = %ld\n",
00295                       read ? "read" : "write", offset, count );
00296         return 0;
00297     }
00298 
00299     slab_id = H5Dget_space( data_id );
00300     if( slab_id < 0 )
00301     {
00302         mhdf_setFail( status, "Internal error calling H5Dget_space." );
00303         return 0;
00304     }
00305 
00306     dims = H5Sget_simple_extent_ndims( slab_id );
00307     if( dims < 1 || dims > 2 )
00308     {
00309         H5Sclose( slab_id );
00310         mhdf_setFail( status, "Internal error: unexpected dataset rank: %d.", dims );
00311         return 0;
00312     }
00313 
00314     dims = H5Sget_simple_extent_dims( slab_id, counts, NULL );
00315     if( dims < 0 )
00316     {
00317         H5Sclose( slab_id );
00318         mhdf_setFail( status, "Internal error calling H5Sget_simple_extend_dims." );
00319         return 0;
00320     }
00321 
00322     if( (unsigned long)( offset + count ) > counts[ 0 ] )
00323     {
00324         H5Sclose( slab_id );
00325         mhdf_setFail( status, "Requested %s of rows %ld to %ld of a %ld row table.\n", read ? "read" : "write", offset,
00326                       offset + count - 1, (long)counts[ dims - 1 ] );
00327         return 0;
00328     }
00329 
00330     counts[ 0 ] = (hsize_t)count;
00331     offsets[ 0 ] = (hsize_t)offset;
00332     offsets[ 1 ] = 0;
00333     if( count )
00334         rval = H5Sselect_hyperslab( slab_id, H5S_SELECT_SET, offsets, NULL, counts, NULL );
00335     else
00336         rval = H5Sselect_none( slab_id );
00337     if( rval < 0 )
00338     {
00339         H5Sclose( slab_id );
00340         mhdf_setFail( status, "Internal error calling H5Sselect_hyperslab." );
00341         return 0;
00342     }
00343 
00344     if( count )
00345         mem_id = H5Screate_simple( dims, counts, NULL );
00346     else
00347     {
00348         /*#if H5_VERS_MAJOR > 1 || H5_VERS_MINOR >= 8
00349             mem_id = H5Screate(H5S_NULL);
00350         #else*/
00351         mem_id = H5Screate_simple( 1, &one, NULL );
00352         if( mem_id && 0 > H5Sselect_none( mem_id ) )
00353         {
00354             H5Sclose( mem_id );
00355             mem_id = -1;
00356         }
00357         /*#endif*/
00358     }
00359 
00360     if( mem_id < 0 )
00361     {
00362         H5Sclose( slab_id );
00363         mhdf_setFail( status, "Internal error calling H5Screate_simple." );
00364         return 0;
00365     }
00366 
00367     if( read )
00368         rval = H5Dread( data_id, type, mem_id, slab_id, io_prop, array );
00369     else
00370     {
00371         VALGRIND_CHECK_MEM_IS_DEFINED( array, counts[ 0 ] * counts[ 1 ] * H5Tget_size( type ) );
00372         rval = H5Dwrite( data_id, type, mem_id, slab_id, io_prop, array );
00373     }
00374     H5Sclose( slab_id );
00375     H5Sclose( mem_id );
00376     if( rval < 0 )
00377     {
00378         mhdf_setFail( status, "Internal error calling H5D%s.", read ? "read" : "write" );
00379         return 0;
00380     }
00381 
00382     mhdf_setOkay( status );
00383     return 1;
00384 }
00385 
00386 static int mhdf_readwrite_column( hid_t data_id, int read, int column, long offset, long count, hid_t type, void* array,
00387                                   hid_t io_prop, mhdf_Status* status )
00388 {
00389     hid_t   slab_id, mem_id;
00390     hsize_t offsets[ 2 ], counts[ 2 ];
00391     herr_t  rval;
00392     int     dims;
00393     /*#if (1000 * H5_VERS_MAJOR + H5_VERS_MINOR) < 1008*/
00394     const hsize_t one = 1;
00395     /*#endif*/
00396 
00397     if( column < 0 || offset < 0 || count < 0 )
00398     {
00399         mhdf_setFail( status,
00400                       "Invalid input for %s: "
00401                       "column = %d, offset = %ld, count = %ld\n",
00402                       read ? "read" : "write", column, offset, count );
00403         return 0;
00404     }
00405 
00406     slab_id = H5Dget_space( data_id );
00407     if( slab_id < 0 )
00408     {
00409         mhdf_setFail( status, "Internal error calling H5Dget_space." );
00410         return 0;
00411     }
00412 
00413     dims = H5Sget_simple_extent_ndims( slab_id );
00414     if( dims < 1 || dims > 2 )
00415     {
00416         H5Sclose( slab_id );
00417         mhdf_setFail( status, "Internal error: unexpected dataset rank: %d.", dims );
00418         return 0;
00419     }
00420 
00421     dims = H5Sget_simple_extent_dims( slab_id, counts, NULL );
00422     if( dims < 0 )
00423     {
00424         H5Sclose( slab_id );
00425         mhdf_setFail( status, "Internal error calling H5Sget_simple_extend_dims." );
00426         return 0;
00427     }
00428 
00429     if( (unsigned long)( offset + count ) > counts[ 0 ] || (unsigned long)column > counts[ 1 ] )
00430     {
00431         H5Sclose( slab_id );
00432         mhdf_setFail( status, "Requested %s of (%ld,%d)->(%ld,%ld) of (%ld, %ld) table.\n", read ? "read" : "write",
00433                       offset, column, offset + count - 1, column, (long)counts[ 0 ], (long)counts[ 1 ] );
00434         return 0;
00435     }
00436 
00437     counts[ 0 ] = (hsize_t)count;
00438     offsets[ 0 ] = (hsize_t)offset;
00439     counts[ 1 ] = 1;
00440     offsets[ 1 ] = column;
00441     if( count )
00442         rval = H5Sselect_hyperslab( slab_id, H5S_SELECT_SET, offsets, NULL, counts, NULL );
00443     else
00444         rval = H5Sselect_none( slab_id );
00445     if( rval < 0 )
00446     {
00447         H5Sclose( slab_id );
00448         mhdf_setFail( status, "Internal error calling H5Sselect_hyperslab." );
00449         return 0;
00450     }
00451 
00452     if( count )
00453         mem_id = H5Screate_simple( dims, counts, NULL );
00454     else
00455     {
00456         /*#if H5_VERS_MAJOR > 1 || H5_VERS_MINOR >= 8
00457             mem_id = H5Screate(H5S_NULL);
00458         #else*/
00459         mem_id = H5Screate_simple( 1, &one, NULL );
00460         if( mem_id && 0 > H5Sselect_none( mem_id ) )
00461         {
00462             H5Sclose( mem_id );
00463             mem_id = -1;
00464         }
00465         /*#endif*/
00466     }
00467 
00468     if( mem_id < 0 )
00469     {
00470         H5Sclose( slab_id );
00471         mhdf_setFail( status, "Internal error calling H5Screate_simple." );
00472         return 0;
00473     }
00474 
00475     if( read )
00476         rval = H5Dread( data_id, type, mem_id, slab_id, io_prop, array );
00477     else
00478     {
00479         VALGRIND_CHECK_MEM_IS_DEFINED( array, count * H5Tget_size( type ) );
00480         rval = H5Dwrite( data_id, type, mem_id, slab_id, io_prop, array );
00481         VALGRIND_MAKE_MEM_UNDEFINED( array, count * H5Tget_size( type ) );
00482     }
00483     H5Sclose( slab_id );
00484     H5Sclose( mem_id );
00485     if( rval < 0 )
00486     {
00487         mhdf_setFail( status, "Internal error calling H5D%s.", read ? "read" : "write" );
00488         return 0;
00489     }
00490 
00491     mhdf_setOkay( status );
00492     return 1;
00493 }
00494 
00495 int mhdf_write_data( hid_t data_id, long offset, long count, hid_t type_id, const void* array, hid_t prop,
00496                      mhdf_Status* status )
00497 {
00498     return mhdf_readwrite( data_id, 0, offset, count, type_id, (void*)array, prop, status );
00499 }
00500 
00501 int mhdf_read_data( hid_t data_id, long offset, long count, hid_t type_id, void* array, hid_t prop,
00502                     mhdf_Status* status )
00503 {
00504     return mhdf_readwrite( data_id, 1, offset, count, type_id, array, prop, status );
00505 }
00506 
00507 int mhdf_read_column( hid_t data_id, int column, long offset, long count, hid_t type, void* array, hid_t prop,
00508                       mhdf_Status* status )
00509 {
00510     return mhdf_readwrite_column( data_id, 1, column, offset, count, type, array, prop, status );
00511 }
00512 
00513 int mhdf_write_column( hid_t data_id, int column, long offset, long count, hid_t type, const void* array, hid_t prop,
00514                        mhdf_Status* status )
00515 {
00516     return mhdf_readwrite_column( data_id, 0, column, offset, count, type, (void*)array, prop, status );
00517 }
00518 
00519 hid_t mhdf_create_table( hid_t group_id, const char* path, hid_t type, int rank, hsize_t* dims, mhdf_Status* status )
00520 {
00521     return mhdf_create_table_with_prop( group_id, path, type, rank, dims, H5P_DEFAULT, status );
00522 }
00523 
00524 hid_t mhdf_create_table_with_prop( hid_t group_id, const char* path, hid_t type, int rank, hsize_t* dims,
00525                                    hid_t create_prop, mhdf_Status* status )
00526 {
00527     hid_t space_id, table_id;
00528 
00529     space_id = H5Screate_simple( rank, dims, NULL );
00530     if( space_id < 0 )
00531     {
00532         mhdf_setFail( status, "Internal error calling H5Screate_simple." );
00533         return -1;
00534     }
00535 
00536 #if defined( H5Dcreate_vers ) && H5Dcreate_vers > 1
00537     table_id = H5Dcreate2( group_id, path, type, space_id, H5P_DEFAULT, create_prop, H5P_DEFAULT );
00538 #else
00539     table_id = H5Dcreate( group_id, path, type, space_id, create_prop );
00540 #endif
00541     H5Sclose( space_id );
00542     if( table_id < 0 )
00543     {
00544         mhdf_setFail( status, "HDF5 DataSet creation failed." );
00545         return -1;
00546     }
00547 
00548     mhdf_setOkay( status );
00549     return table_id;
00550 }
00551 
00552 hid_t mhdf_open_table( hid_t group_id, const char* path, int columns, hsize_t* rows_out, mhdf_Status* status )
00553 {
00554     hid_t   table_id, space_id;
00555     hsize_t dims[ 2 ];
00556     int     rank;
00557 
00558 #if defined( H5Dopen_vers ) && H5Dopen_vers > 1
00559     table_id = H5Dopen2( group_id, path, H5P_DEFAULT );
00560 #else
00561     table_id = H5Dopen( group_id, path );
00562 #endif
00563     if( table_id < 0 )
00564     {
00565         mhdf_setFail( status, "HDF5 DataSet creation failed." );
00566         return -1;
00567     }
00568 
00569     space_id = H5Dget_space( table_id );
00570     if( space_id < 0 )
00571     {
00572         mhdf_setFail( status, "Internal error in H5Dget_space." );
00573         H5Dclose( table_id );
00574         return -1;
00575     }
00576 
00577     rank = H5Sget_simple_extent_ndims( space_id );
00578     if( rank != ( columns ? 1 : 2 ) )
00579     {
00580         mhdf_setFail( status, "Incorrect DataSpace for DataSet." );
00581         H5Sclose( space_id );
00582         H5Dclose( table_id );
00583         return -1;
00584     }
00585 
00586     rank = H5Sget_simple_extent_dims( space_id, dims, NULL );
00587     H5Sclose( space_id );
00588     if( rank < 0 )
00589     {
00590         mhdf_setFail( status, "Internal error calling H5Sget_simple_extent_dims." );
00591         H5Dclose( table_id );
00592         return -1;
00593     }
00594 
00595     *rows_out = dims[ 0 ];
00596     mhdf_setOkay( status );
00597     return table_id;
00598 }
00599 
00600 hid_t mhdf_open_table2( hid_t group_id, const char* path, int rank, hsize_t* dims_out, long* start_id_out,
00601                         mhdf_Status* status )
00602 {
00603     hid_t table_id, space_id;
00604 
00605 #if defined( H5Dopen_vers ) && H5Dopen_vers > 1
00606     table_id = H5Dopen2( group_id, path, H5P_DEFAULT );
00607 #else
00608     table_id = H5Dopen( group_id, path );
00609 #endif
00610     if( table_id < 0 )
00611     {
00612         mhdf_setFail( status, "HDF5 DataSet creation failed." );
00613         return -1;
00614     }
00615 
00616     space_id = H5Dget_space( table_id );
00617     if( space_id < 0 )
00618     {
00619         mhdf_setFail( status, "Internal error in H5Dget_space." );
00620         H5Dclose( table_id );
00621         return -1;
00622     }
00623 
00624     if( H5Sget_simple_extent_ndims( space_id ) != rank )
00625     {
00626         mhdf_setFail( status, "Incorrect DataSpace for DataSet." );
00627         H5Sclose( space_id );
00628         H5Dclose( table_id );
00629         return -1;
00630     }
00631 
00632     rank = H5Sget_simple_extent_dims( space_id, dims_out, NULL );
00633     H5Sclose( space_id );
00634     if( rank < 0 )
00635     {
00636         mhdf_setFail( status, "Internal error calling H5Sget_simple_extent_dims." );
00637         H5Dclose( table_id );
00638         return -1;
00639     }
00640 
00641     if( !mhdf_read_scalar_attrib( table_id, START_ID_ATTRIB, H5T_NATIVE_LONG, start_id_out, status ) )
00642     {
00643         mhdf_setFail( status, "File format error.  Failed to retreive ID offset." );
00644         H5Dclose( table_id );
00645         return -1;
00646     }
00647 
00648     mhdf_setOkay( status );
00649     return table_id;
00650 }
00651 
00652 hid_t mhdf_open_table_simple( hid_t group_id, const char* path, mhdf_Status* status )
00653 {
00654     hid_t table_id;
00655 
00656 #if defined( H5Dopen_vers ) && H5Dopen_vers > 1
00657     table_id = H5Dopen2( group_id, path, H5P_DEFAULT );
00658 #else
00659     table_id = H5Dopen( group_id, path );
00660 #endif
00661     if( table_id < 0 ) { mhdf_setFail( status, "HDF5 DataSet creation failed." ); }
00662     else
00663     {
00664         mhdf_setOkay( status );
00665     }
00666 
00667     return table_id;
00668 }
00669 
00670 static int qs_comp_int( const void* ptr1, const void* ptr2 )
00671 {
00672     const int* left = (const int*)ptr1;
00673     const int* right = (const int*)ptr2;
00674     return *left < *right ? -1 : *left > *right ? 1 : 0;
00675 }
00676 
00677 int mhdf_compact_to_ranges( int* length, int* ids, int ordered )
00678 {
00679     int    new_length = 0;
00680     int *  iter, *end;
00681     int    prev, count;
00682     int    need_copy = 0;
00683     int *  copy_ptr = 0, *w_iter;
00684     size_t blen;
00685 
00686     if( !ordered ) qsort( ids, *length, sizeof( int ), &qs_comp_int );
00687 
00688     iter = ids;
00689     end = ids + *length;
00690     while( iter != end )
00691     {
00692         prev = *( iter++ );
00693         while( iter < end && *( iter++ ) == ++prev )
00694             ;
00695         new_length += 2;
00696         if( new_length > ( iter - ids ) ) need_copy = 1;
00697     }
00698 
00699     if( new_length > *length ) return 0;
00700 
00701     if( need_copy )
00702     {
00703         blen = sizeof( int ) * *length;
00704         copy_ptr = (int*)malloc( blen );
00705         memcpy( copy_ptr, ids, blen );
00706         iter = copy_ptr;
00707     }
00708     else
00709     {
00710         iter = ids;
00711     }
00712 
00713     end = iter + *length;
00714     w_iter = ids;
00715     while( iter != end )
00716     {
00717         prev = *( iter++ );
00718         count = 1;
00719         while( iter < end && *( iter++ ) == ++prev )
00720             ;
00721         *( w_iter++ ) = prev - count;
00722         *( w_iter++ ) = count;
00723     }
00724 
00725     *length = new_length;
00726     if( need_copy ) free( copy_ptr );
00727     return 1;
00728 }
00729 
00730 hid_t get_elem_type_enum( FileHandle* file_ptr, mhdf_Status* status )
00731 {
00732     hid_t result;
00733 #if defined( H5Topen_vers ) && H5Topen_vers > 1
00734     result = H5Topen2( file_ptr->hdf_handle, TYPE_ENUM_PATH, H5P_DEFAULT );
00735 #else
00736     result = H5Topen( file_ptr->hdf_handle, TYPE_ENUM_PATH );
00737 #endif
00738     if( result < 0 ) mhdf_setFail( status, "Element type enum does not exist in file.  Invalid file." );
00739     return result;
00740 }
00741 
00742 int mhdf_write_max_id( FileHandle* file_ptr, mhdf_Status* status )
00743 {
00744     hid_t  group_id, attr_id, space_id;
00745     herr_t rval;
00746 
00747 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
00748     group_id = H5Gopen2( file_ptr->hdf_handle, ROOT_GROUP, H5P_DEFAULT );
00749 #else
00750     group_id = H5Gopen( file_ptr->hdf_handle, ROOT_GROUP );
00751 #endif
00752     if( group_id < 0 )
00753     {
00754         mhdf_setFail( status, "Internal error -- file invalid." );
00755         return 0;
00756     }
00757 
00758     attr_id = H5Aopen_name( group_id, MAX_ID_ATTRIB );
00759     if( attr_id < 0 )
00760     {
00761         space_id = H5Screate( H5S_SCALAR );
00762 #if defined( H5Acreate_vers ) && H5Acreate_vers > 1
00763         attr_id = H5Acreate2( group_id, MAX_ID_ATTRIB, H5T_NATIVE_ULONG, space_id, H5P_DEFAULT, H5P_DEFAULT );
00764 #else
00765         attr_id = H5Acreate( group_id, MAX_ID_ATTRIB, H5T_NATIVE_ULONG, space_id, H5P_DEFAULT );
00766 #endif
00767         H5Sclose( space_id );
00768     }
00769     H5Gclose( group_id );
00770     if( attr_id < 0 )
00771     {
00772         mhdf_setFail( status, "Failed to create attribute \"%s\" on \"%s\"", MAX_ID_ATTRIB, ROOT_GROUP );
00773         return 0;
00774     }
00775 
00776     rval = H5Awrite( attr_id, H5T_NATIVE_ULONG, &file_ptr->max_id );
00777     H5Aclose( attr_id );
00778     if( rval < 0 )
00779     {
00780         mhdf_setFail( status, "Failed to write \"%s\" attrib.", MAX_ID_ATTRIB );
00781         return 0;
00782     }
00783 
00784     return 1;
00785 }
00786 
00787 static int mhdf_api_handle_count = 0;
00788 
00789 static int num_open( )
00790 {
00791     hid_t list[ 64 ];
00792     int   nf, rval, i, count = 0;
00793 
00794     nf = H5Fget_obj_ids( H5F_OBJ_ALL, H5F_OBJ_FILE, sizeof( list ) / sizeof( hid_t ), list );
00795     if( nf <= 0 || nf > 64 ) return 0;
00796 
00797     for( i = 0; i < nf; i++ )
00798     {
00799         rval = H5Fget_obj_count( list[ i ], H5F_OBJ_ALL );
00800         if( rval > 0 ) count += rval;
00801     }
00802 
00803     return count;
00804 }
00805 
00806 void mhdf_api_begin_internal( )
00807 {
00808     /* HDF5 docs are incorrect.  Passing H5F_OBJ_ALL as the first
00809        arg to H5Fget_obj_count returns the total number of open
00810        handles, not just those in files (i.e. temporary types and such.)
00811     mhdf_api_handle_count = H5Fget_obj_count( H5F_OBJ_ALL, H5F_OBJ_ALL );
00812        Need to loop to get actual file handles:
00813     */
00814     mhdf_api_handle_count = num_open( );
00815 }
00816 
00817 void mhdf_api_end_internal( int expected_diff, const char* filename, int linenumber )
00818 {
00819     if( mhdf_api_handle_count + expected_diff != num_open( ) )
00820     {
00821         fprintf( stderr, "Unclosed handles at end of mhdf API call.\n" );
00822         fprintf( stderr, "Entered with %d, expected %d change, got %d.\n", mhdf_api_handle_count, expected_diff,
00823                  num_open( ) );
00824         fprintf( stderr, "%s:%d\n", filename, linenumber );
00825         abort( );
00826     }
00827 
00828     mhdf_api_handle_count = 0;
00829 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines