![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
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
00017 #include
00018 #include
00019 #include
00020 #include
00021 #include "util.h"
00022 #include "status.h"
00023 #include "names-and-paths.h"
00024
00025 #ifdef VALGRIND
00026 #include
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 }