MOAB: Mesh Oriented datABase  (version 5.4.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 )
00213     {
00214         type_id = type;
00215     }
00216     else
00217     {
00218         type_id = H5Aget_type( attr_id );
00219         if( type_id < 0 )
00220         {
00221             H5Aclose( attr_id );
00222             return 0;
00223         }
00224     }
00225 
00226     rval = H5Aread( attr_id, type_id, value );
00227     H5Aclose( attr_id );
00228     if( type < 1 ) H5Tclose( type_id );
00229     if( rval < 0 )
00230     {
00231         mhdf_setFail( status, "Failed to read \"%s\" attrib.", name );
00232         return 0;
00233     }
00234 
00235     return 1;
00236 }
00237 
00238 #if defined( H5Aiterate_vers ) && H5Aiterate_vers > 1
00239 static herr_t find_attr_by_name( hid_t handle, const char* name, const H5A_info_t* info, void* mydata )
00240 {
00241     /* empty statement to remove compiler warning */
00242     if( info )
00243     {
00244     }
00245 #else
00246 static herr_t find_attr_by_name( hid_t handle, const char* name, void* mydata )
00247 {
00248 #endif
00249     /* empty statement to remove compiler warning */
00250     if( handle )
00251     {
00252     }
00253     return !strcmp( name, (const char*)mydata );
00254 }
00255 
00256 int mhdf_find_attribute( hid_t object, const char* attrib_name, unsigned int* index_out, mhdf_Status* status )
00257 {
00258     herr_t rval;
00259 #if defined( H5Aiterate_vers ) && H5Aiterate_vers > 1
00260     hsize_t idx = 0;
00261     rval = H5Aiterate2( object, H5_INDEX_CRT_ORDER, H5_ITER_NATIVE, &idx, &find_attr_by_name, (void*)attrib_name );
00262     *index_out = (unsigned int)idx;
00263 #else
00264     *index_out = 0;
00265     rval = H5Aiterate( object, index_out, &find_attr_by_name, (void*)attrib_name );
00266 #endif
00267     if( rval < 0 ) mhdf_setFail( status, "Internal error calling H5Aiterate." );
00268     return (int)rval;
00269 }
00270 
00271 static herr_t find_link_by_name( hid_t handle, const char* name, void* mydata )
00272 {
00273     /* empty statement to remove compiler warning */
00274     if( handle )
00275     {
00276     }
00277     return !strcmp( name, (const char*)mydata );
00278 }
00279 
00280 int mhdf_is_in_group( hid_t group, const char* name, mhdf_Status* status )
00281 {
00282     int rval;
00283     rval = H5Giterate( group, ".", NULL, &find_link_by_name, (void*)name );
00284     if( rval < 0 ) mhdf_setFail( status, "Internal error in H5Giterate." );
00285     return rval;
00286 }
00287 
00288 static int mhdf_readwrite( hid_t data_id,
00289                            int read,
00290                            long offset,
00291                            long count,
00292                            hid_t type,
00293                            void* array,
00294                            hid_t io_prop,
00295                            mhdf_Status* status )
00296 {
00297     hid_t slab_id, mem_id;
00298     hsize_t offsets[2], counts[2] = { 1, 1 };
00299     herr_t rval;
00300     int dims;
00301     /*#if (1000 * H5_VERS_MAJOR + H5_VERS_MINOR) < 1008*/
00302     const hsize_t one = 1;
00303     /*#endif*/
00304 
00305     if( offset < 0 || count < 0 )
00306     {
00307         mhdf_setFail( status,
00308                       "Invalid input for %s: "
00309                       "offset = %ld, count = %ld\n",
00310                       read ? "read" : "write", offset, count );
00311         return 0;
00312     }
00313 
00314     slab_id = H5Dget_space( data_id );
00315     if( slab_id < 0 )
00316     {
00317         mhdf_setFail( status, "Internal error calling H5Dget_space." );
00318         return 0;
00319     }
00320 
00321     dims = H5Sget_simple_extent_ndims( slab_id );
00322     if( dims < 1 || dims > 2 )
00323     {
00324         H5Sclose( slab_id );
00325         mhdf_setFail( status, "Internal error: unexpected dataset rank: %d.", dims );
00326         return 0;
00327     }
00328 
00329     dims = H5Sget_simple_extent_dims( slab_id, counts, NULL );
00330     if( dims < 0 )
00331     {
00332         H5Sclose( slab_id );
00333         mhdf_setFail( status, "Internal error calling H5Sget_simple_extend_dims." );
00334         return 0;
00335     }
00336 
00337     if( (unsigned long)( offset + count ) > counts[0] )
00338     {
00339         H5Sclose( slab_id );
00340         mhdf_setFail( status, "Requested %s of rows %ld to %ld of a %ld row table.\n", read ? "read" : "write", offset,
00341                       offset + count - 1, (long)counts[dims - 1] );
00342         return 0;
00343     }
00344 
00345     counts[0]  = (hsize_t)count;
00346     offsets[0] = (hsize_t)offset;
00347     offsets[1] = 0;
00348     if( count )
00349         rval = H5Sselect_hyperslab( slab_id, H5S_SELECT_SET, offsets, NULL, counts, NULL );
00350     else
00351         rval = H5Sselect_none( slab_id );
00352     if( rval < 0 )
00353     {
00354         H5Sclose( slab_id );
00355         mhdf_setFail( status, "Internal error calling H5Sselect_hyperslab." );
00356         return 0;
00357     }
00358 
00359     if( count )
00360         mem_id = H5Screate_simple( dims, counts, NULL );
00361     else
00362     {
00363         /*#if H5_VERS_MAJOR > 1 || H5_VERS_MINOR >= 8
00364             mem_id = H5Screate(H5S_NULL);
00365         #else*/
00366         mem_id = H5Screate_simple( 1, &one, NULL );
00367         if( mem_id && 0 > H5Sselect_none( mem_id ) )
00368         {
00369             H5Sclose( mem_id );
00370             mem_id = -1;
00371         }
00372         /*#endif*/
00373     }
00374 
00375     if( mem_id < 0 )
00376     {
00377         H5Sclose( slab_id );
00378         mhdf_setFail( status, "Internal error calling H5Screate_simple." );
00379         return 0;
00380     }
00381 
00382     if( read )
00383         rval = H5Dread( data_id, type, mem_id, slab_id, io_prop, array );
00384     else
00385     {
00386         VALGRIND_CHECK_MEM_IS_DEFINED( array, counts[0] * counts[1] * H5Tget_size( type ) );
00387         rval = H5Dwrite( data_id, type, mem_id, slab_id, io_prop, array );
00388     }
00389     H5Sclose( slab_id );
00390     H5Sclose( mem_id );
00391     if( rval < 0 )
00392     {
00393         mhdf_setFail( status, "Internal error calling H5D%s.", read ? "read" : "write" );
00394         return 0;
00395     }
00396 
00397     mhdf_setOkay( status );
00398     return 1;
00399 }
00400 
00401 static int mhdf_readwrite_column( hid_t data_id,
00402                                   int read,
00403                                   int column,
00404                                   long offset,
00405                                   long count,
00406                                   hid_t type,
00407                                   void* array,
00408                                   hid_t io_prop,
00409                                   mhdf_Status* status )
00410 {
00411     hid_t slab_id, mem_id;
00412     hsize_t offsets[2], counts[2];
00413     herr_t rval;
00414     int dims;
00415     /*#if (1000 * H5_VERS_MAJOR + H5_VERS_MINOR) < 1008*/
00416     const hsize_t one = 1;
00417     /*#endif*/
00418 
00419     if( column < 0 || offset < 0 || count < 0 )
00420     {
00421         mhdf_setFail( status,
00422                       "Invalid input for %s: "
00423                       "column = %d, offset = %ld, count = %ld\n",
00424                       read ? "read" : "write", column, offset, count );
00425         return 0;
00426     }
00427 
00428     slab_id = H5Dget_space( data_id );
00429     if( slab_id < 0 )
00430     {
00431         mhdf_setFail( status, "Internal error calling H5Dget_space." );
00432         return 0;
00433     }
00434 
00435     dims = H5Sget_simple_extent_ndims( slab_id );
00436     if( dims < 1 || dims > 2 )
00437     {
00438         H5Sclose( slab_id );
00439         mhdf_setFail( status, "Internal error: unexpected dataset rank: %d.", dims );
00440         return 0;
00441     }
00442 
00443     dims = H5Sget_simple_extent_dims( slab_id, counts, NULL );
00444     if( dims < 0 )
00445     {
00446         H5Sclose( slab_id );
00447         mhdf_setFail( status, "Internal error calling H5Sget_simple_extend_dims." );
00448         return 0;
00449     }
00450 
00451     if( (unsigned long)( offset + count ) > counts[0] || (unsigned long)column > counts[1] )
00452     {
00453         H5Sclose( slab_id );
00454         mhdf_setFail( status, "Requested %s of (%ld,%d)->(%ld,%ld) of (%ld, %ld) table.\n", read ? "read" : "write",
00455                       offset, column, offset + count - 1, column, (long)counts[0], (long)counts[1] );
00456         return 0;
00457     }
00458 
00459     counts[0]  = (hsize_t)count;
00460     offsets[0] = (hsize_t)offset;
00461     counts[1]  = 1;
00462     offsets[1] = column;
00463     if( count )
00464         rval = H5Sselect_hyperslab( slab_id, H5S_SELECT_SET, offsets, NULL, counts, NULL );
00465     else
00466         rval = H5Sselect_none( slab_id );
00467     if( rval < 0 )
00468     {
00469         H5Sclose( slab_id );
00470         mhdf_setFail( status, "Internal error calling H5Sselect_hyperslab." );
00471         return 0;
00472     }
00473 
00474     if( count )
00475         mem_id = H5Screate_simple( dims, counts, NULL );
00476     else
00477     {
00478         /*#if H5_VERS_MAJOR > 1 || H5_VERS_MINOR >= 8
00479             mem_id = H5Screate(H5S_NULL);
00480         #else*/
00481         mem_id = H5Screate_simple( 1, &one, NULL );
00482         if( mem_id && 0 > H5Sselect_none( mem_id ) )
00483         {
00484             H5Sclose( mem_id );
00485             mem_id = -1;
00486         }
00487         /*#endif*/
00488     }
00489 
00490     if( mem_id < 0 )
00491     {
00492         H5Sclose( slab_id );
00493         mhdf_setFail( status, "Internal error calling H5Screate_simple." );
00494         return 0;
00495     }
00496 
00497     if( read )
00498         rval = H5Dread( data_id, type, mem_id, slab_id, io_prop, array );
00499     else
00500     {
00501         VALGRIND_CHECK_MEM_IS_DEFINED( array, count * H5Tget_size( type ) );
00502         rval = H5Dwrite( data_id, type, mem_id, slab_id, io_prop, array );
00503         VALGRIND_MAKE_MEM_UNDEFINED( array, count * H5Tget_size( type ) );
00504     }
00505     H5Sclose( slab_id );
00506     H5Sclose( mem_id );
00507     if( rval < 0 )
00508     {
00509         mhdf_setFail( status, "Internal error calling H5D%s.", read ? "read" : "write" );
00510         return 0;
00511     }
00512 
00513     mhdf_setOkay( status );
00514     return 1;
00515 }
00516 
00517 int mhdf_write_data( hid_t data_id,
00518                      long offset,
00519                      long count,
00520                      hid_t type_id,
00521                      const void* array,
00522                      hid_t prop,
00523                      mhdf_Status* status )
00524 {
00525     return mhdf_readwrite( data_id, 0, offset, count, type_id, (void*)array, prop, status );
00526 }
00527 
00528 int mhdf_read_data( hid_t data_id,
00529                     long offset,
00530                     long count,
00531                     hid_t type_id,
00532                     void* array,
00533                     hid_t prop,
00534                     mhdf_Status* status )
00535 {
00536     return mhdf_readwrite( data_id, 1, offset, count, type_id, array, prop, status );
00537 }
00538 
00539 int mhdf_read_column( hid_t data_id,
00540                       int column,
00541                       long offset,
00542                       long count,
00543                       hid_t type,
00544                       void* array,
00545                       hid_t prop,
00546                       mhdf_Status* status )
00547 {
00548     return mhdf_readwrite_column( data_id, 1, column, offset, count, type, array, prop, status );
00549 }
00550 
00551 int mhdf_write_column( hid_t data_id,
00552                        int column,
00553                        long offset,
00554                        long count,
00555                        hid_t type,
00556                        const void* array,
00557                        hid_t prop,
00558                        mhdf_Status* status )
00559 {
00560     return mhdf_readwrite_column( data_id, 0, column, offset, count, type, (void*)array, prop, status );
00561 }
00562 
00563 hid_t mhdf_create_table( hid_t group_id, const char* path, hid_t type, int rank, hsize_t* dims, mhdf_Status* status )
00564 {
00565     return mhdf_create_table_with_prop( group_id, path, type, rank, dims, H5P_DEFAULT, status );
00566 }
00567 
00568 hid_t mhdf_create_table_with_prop( hid_t group_id,
00569                                    const char* path,
00570                                    hid_t type,
00571                                    int rank,
00572                                    hsize_t* dims,
00573                                    hid_t create_prop,
00574                                    mhdf_Status* status )
00575 {
00576     hid_t space_id, table_id;
00577 
00578     space_id = H5Screate_simple( rank, dims, NULL );
00579     if( space_id < 0 )
00580     {
00581         mhdf_setFail( status, "Internal error calling H5Screate_simple." );
00582         return -1;
00583     }
00584 
00585 #if defined( H5Dcreate_vers ) && H5Dcreate_vers > 1
00586     table_id = H5Dcreate2( group_id, path, type, space_id, H5P_DEFAULT, create_prop, H5P_DEFAULT );
00587 #else
00588     table_id = H5Dcreate( group_id, path, type, space_id, create_prop );
00589 #endif
00590     H5Sclose( space_id );
00591     if( table_id < 0 )
00592     {
00593         mhdf_setFail( status, "HDF5 DataSet creation failed." );
00594         return -1;
00595     }
00596 
00597     mhdf_setOkay( status );
00598     return table_id;
00599 }
00600 
00601 hid_t mhdf_open_table( hid_t group_id, const char* path, int columns, hsize_t* rows_out, mhdf_Status* status )
00602 {
00603     hid_t table_id, space_id;
00604     hsize_t dims[2];
00605     int rank;
00606 
00607 #if defined( H5Dopen_vers ) && H5Dopen_vers > 1
00608     table_id = H5Dopen2( group_id, path, H5P_DEFAULT );
00609 #else
00610     table_id = H5Dopen( group_id, path );
00611 #endif
00612     if( table_id < 0 )
00613     {
00614         mhdf_setFail( status, "HDF5 DataSet creation failed." );
00615         return -1;
00616     }
00617 
00618     space_id = H5Dget_space( table_id );
00619     if( space_id < 0 )
00620     {
00621         mhdf_setFail( status, "Internal error in H5Dget_space." );
00622         H5Dclose( table_id );
00623         return -1;
00624     }
00625 
00626     rank = H5Sget_simple_extent_ndims( space_id );
00627     if( rank != ( columns ? 1 : 2 ) )
00628     {
00629         mhdf_setFail( status, "Incorrect DataSpace for DataSet." );
00630         H5Sclose( space_id );
00631         H5Dclose( table_id );
00632         return -1;
00633     }
00634 
00635     rank = H5Sget_simple_extent_dims( space_id, dims, NULL );
00636     H5Sclose( space_id );
00637     if( rank < 0 )
00638     {
00639         mhdf_setFail( status, "Internal error calling H5Sget_simple_extent_dims." );
00640         H5Dclose( table_id );
00641         return -1;
00642     }
00643 
00644     *rows_out = dims[0];
00645     mhdf_setOkay( status );
00646     return table_id;
00647 }
00648 
00649 hid_t mhdf_open_table2( hid_t group_id,
00650                         const char* path,
00651                         int rank,
00652                         hsize_t* dims_out,
00653                         long* start_id_out,
00654                         mhdf_Status* status )
00655 {
00656     hid_t table_id, space_id;
00657 
00658 #if defined( H5Dopen_vers ) && H5Dopen_vers > 1
00659     table_id = H5Dopen2( group_id, path, H5P_DEFAULT );
00660 #else
00661     table_id = H5Dopen( group_id, path );
00662 #endif
00663     if( table_id < 0 )
00664     {
00665         mhdf_setFail( status, "HDF5 DataSet creation failed." );
00666         return -1;
00667     }
00668 
00669     space_id = H5Dget_space( table_id );
00670     if( space_id < 0 )
00671     {
00672         mhdf_setFail( status, "Internal error in H5Dget_space." );
00673         H5Dclose( table_id );
00674         return -1;
00675     }
00676 
00677     if( H5Sget_simple_extent_ndims( space_id ) != rank )
00678     {
00679         mhdf_setFail( status, "Incorrect DataSpace for DataSet." );
00680         H5Sclose( space_id );
00681         H5Dclose( table_id );
00682         return -1;
00683     }
00684 
00685     rank = H5Sget_simple_extent_dims( space_id, dims_out, NULL );
00686     H5Sclose( space_id );
00687     if( rank < 0 )
00688     {
00689         mhdf_setFail( status, "Internal error calling H5Sget_simple_extent_dims." );
00690         H5Dclose( table_id );
00691         return -1;
00692     }
00693 
00694     if( !mhdf_read_scalar_attrib( table_id, START_ID_ATTRIB, H5T_NATIVE_LONG, start_id_out, status ) )
00695     {
00696         mhdf_setFail( status, "File format error.  Failed to retreive ID offset." );
00697         H5Dclose( table_id );
00698         return -1;
00699     }
00700 
00701     mhdf_setOkay( status );
00702     return table_id;
00703 }
00704 
00705 hid_t mhdf_open_table_simple( hid_t group_id, const char* path, mhdf_Status* status )
00706 {
00707     hid_t table_id;
00708 
00709 #if defined( H5Dopen_vers ) && H5Dopen_vers > 1
00710     table_id = H5Dopen2( group_id, path, H5P_DEFAULT );
00711 #else
00712     table_id = H5Dopen( group_id, path );
00713 #endif
00714     if( table_id < 0 )
00715     {
00716         mhdf_setFail( status, "HDF5 DataSet creation failed." );
00717     }
00718     else
00719     {
00720         mhdf_setOkay( status );
00721     }
00722 
00723     return table_id;
00724 }
00725 
00726 static int qs_comp_int( const void* ptr1, const void* ptr2 )
00727 {
00728     const int* left  = (const int*)ptr1;
00729     const int* right = (const int*)ptr2;
00730     return *left < *right ? -1 : *left > *right ? 1 : 0;
00731 }
00732 
00733 int mhdf_compact_to_ranges( int* length, int* ids, int ordered )
00734 {
00735     int new_length = 0;
00736     int *iter, *end;
00737     int prev, count;
00738     int need_copy = 0;
00739     int *copy_ptr = 0, *w_iter;
00740     size_t blen;
00741 
00742     if( !ordered ) qsort( ids, *length, sizeof( int ), &qs_comp_int );
00743 
00744     iter = ids;
00745     end  = ids + *length;
00746     while( iter != end )
00747     {
00748         prev = *( iter++ );
00749         while( iter < end && *( iter++ ) == ++prev )
00750             ;
00751         new_length += 2;
00752         if( new_length > ( iter - ids ) ) need_copy = 1;
00753     }
00754 
00755     if( new_length > *length ) return 0;
00756 
00757     if( need_copy )
00758     {
00759         blen     = sizeof( int ) * *length;
00760         copy_ptr = (int*)malloc( blen );
00761         memcpy( copy_ptr, ids, blen );
00762         iter = copy_ptr;
00763     }
00764     else
00765     {
00766         iter = ids;
00767     }
00768 
00769     end    = iter + *length;
00770     w_iter = ids;
00771     while( iter != end )
00772     {
00773         prev  = *( iter++ );
00774         count = 1;
00775         while( iter < end && *( iter++ ) == ++prev )
00776             ;
00777         *( w_iter++ ) = prev - count;
00778         *( w_iter++ ) = count;
00779     }
00780 
00781     *length = new_length;
00782     if( need_copy ) free( copy_ptr );
00783     return 1;
00784 }
00785 
00786 hid_t get_elem_type_enum( FileHandle* file_ptr, mhdf_Status* status )
00787 {
00788     hid_t result;
00789 #if defined( H5Topen_vers ) && H5Topen_vers > 1
00790     result = H5Topen2( file_ptr->hdf_handle, TYPE_ENUM_PATH, H5P_DEFAULT );
00791 #else
00792     result = H5Topen( file_ptr->hdf_handle, TYPE_ENUM_PATH );
00793 #endif
00794     if( result < 0 ) mhdf_setFail( status, "Element type enum does not exist in file.  Invalid file." );
00795     return result;
00796 }
00797 
00798 int mhdf_write_max_id( FileHandle* file_ptr, mhdf_Status* status )
00799 {
00800     hid_t group_id, attr_id, space_id;
00801     herr_t rval;
00802 
00803 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
00804     group_id = H5Gopen2( file_ptr->hdf_handle, ROOT_GROUP, H5P_DEFAULT );
00805 #else
00806     group_id = H5Gopen( file_ptr->hdf_handle, ROOT_GROUP );
00807 #endif
00808     if( group_id < 0 )
00809     {
00810         mhdf_setFail( status, "Internal error -- file invalid." );
00811         return 0;
00812     }
00813 
00814     attr_id = H5Aopen_name( group_id, MAX_ID_ATTRIB );
00815     if( attr_id < 0 )
00816     {
00817         space_id = H5Screate( H5S_SCALAR );
00818 #if defined( H5Acreate_vers ) && H5Acreate_vers > 1
00819         attr_id = H5Acreate2( group_id, MAX_ID_ATTRIB, H5T_NATIVE_ULONG, space_id, H5P_DEFAULT, H5P_DEFAULT );
00820 #else
00821         attr_id = H5Acreate( group_id, MAX_ID_ATTRIB, H5T_NATIVE_ULONG, space_id, H5P_DEFAULT );
00822 #endif
00823         H5Sclose( space_id );
00824     }
00825     H5Gclose( group_id );
00826     if( attr_id < 0 )
00827     {
00828         mhdf_setFail( status, "Failed to create attribute \"%s\" on \"%s\"", MAX_ID_ATTRIB, ROOT_GROUP );
00829         return 0;
00830     }
00831 
00832     rval = H5Awrite( attr_id, H5T_NATIVE_ULONG, &file_ptr->max_id );
00833     H5Aclose( attr_id );
00834     if( rval < 0 )
00835     {
00836         mhdf_setFail( status, "Failed to write \"%s\" attrib.", MAX_ID_ATTRIB );
00837         return 0;
00838     }
00839 
00840     return 1;
00841 }
00842 
00843 static int mhdf_api_handle_count = 0;
00844 
00845 static int num_open()
00846 {
00847     hid_t list[64];
00848     int nf, rval, i, count = 0;
00849 
00850     nf = H5Fget_obj_ids( H5F_OBJ_ALL, H5F_OBJ_FILE, sizeof( list ) / sizeof( hid_t ), list );
00851     if( nf <= 0 || nf > 64 ) return 0;
00852 
00853     for( i = 0; i < nf; i++ )
00854     {
00855         rval = H5Fget_obj_count( list[i], H5F_OBJ_ALL );
00856         if( rval > 0 ) count += rval;
00857     }
00858 
00859     return count;
00860 }
00861 
00862 void mhdf_api_begin_internal()
00863 {
00864     /* HDF5 docs are incorrect.  Passing H5F_OBJ_ALL as the first
00865        arg to H5Fget_obj_count returns the total number of open
00866        handles, not just those in files (i.e. temporary types and such.)
00867     mhdf_api_handle_count = H5Fget_obj_count( H5F_OBJ_ALL, H5F_OBJ_ALL );
00868        Need to loop to get actual file handles:
00869     */
00870     mhdf_api_handle_count = num_open();
00871 }
00872 
00873 void mhdf_api_end_internal( int expected_diff, const char* filename, int linenumber )
00874 {
00875     if( mhdf_api_handle_count + expected_diff != num_open() )
00876     {
00877         fprintf( stderr, "Unclosed handles at end of mhdf API call.\n" );
00878         fprintf( stderr, "Entered with %d, expected %d change, got %d.\n", mhdf_api_handle_count, expected_diff,
00879                  num_open() );
00880         fprintf( stderr, "%s:%d\n", filename, linenumber );
00881         abort();
00882     }
00883 
00884     mhdf_api_handle_count = 0;
00885 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines