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 <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 }