![]() |
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
00022 #include
00023 #include
00024 #include
00025 #ifdef MOAB_HAVE_HDF5_PARALLEL
00026 #include
00027 #include
00028 #endif
00029 #include "mhdf.h"
00030 #include "status.h"
00031 #include "names-and-paths.h"
00032 #include "util.h"
00033 #include "file-handle.h"
00034
00035 static int make_hdf_group( const char* path, hid_t file, size_t size, mhdf_Status* status );
00036
00037 mhdf_FileHandle mhdf_createFile( const char* filename,
00038 int overwrite,
00039 const char** elem_type_list,
00040 size_t elem_list_len,
00041 hid_t id_type,
00042 mhdf_Status* status )
00043 {
00044 FileHandle* file_ptr;
00045 unsigned int flags;
00046 unsigned char idx;
00047 size_t i;
00048 hid_t enum_id, group_id;
00049 int rval;
00050 API_BEGIN;
00051
00052 if( elem_list_len > 255 )
00053 {
00054 mhdf_setFail( status, "Element type list too long." );
00055 return NULL;
00056 }
00057 mhdf_setOkay( status );
00058
00059 /* Create struct to hold working data */
00060 file_ptr = mhdf_alloc_FileHandle( 0, id_type, status );
00061 if( !file_ptr ) return NULL;
00062
00063 /* Create the file */
00064 flags = overwrite ? H5F_ACC_TRUNC : H5F_ACC_EXCL;
00065 file_ptr->hdf_handle = H5Fcreate( filename, flags, H5P_DEFAULT, H5P_DEFAULT );
00066 if( file_ptr->hdf_handle < 0 )
00067 {
00068 mhdf_setFail( status, "Failed to create file \"%s\"", filename );
00069 free( file_ptr );
00070 return NULL;
00071 }
00072
00073 /* Create file structure */
00074 if( !make_hdf_group( ROOT_GROUP, file_ptr->hdf_handle, 6, status ) ||
00075 !make_hdf_group( TAG_GROUP, file_ptr->hdf_handle, 0, status ) ||
00076 !make_hdf_group( ELEMENT_GROUP, file_ptr->hdf_handle, 8, status ) ||
00077 !make_hdf_group( NODE_GROUP, file_ptr->hdf_handle, 3, status ) ||
00078 !make_hdf_group( SET_GROUP, file_ptr->hdf_handle, 5, status ) ||
00079 !make_hdf_group( NODE_TAG_GROUP, file_ptr->hdf_handle, 0, status ) ||
00080 !make_hdf_group( SET_TAG_GROUP, file_ptr->hdf_handle, 0, status ) )
00081 {
00082 H5Fclose( file_ptr->hdf_handle );
00083 free( file_ptr );
00084 return NULL;
00085 }
00086
00087 /* Store the max ID as an attribite on the /tstt/ group */
00088 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
00089 group_id = H5Gopen2( file_ptr->hdf_handle, ROOT_GROUP, H5P_DEFAULT );
00090 #else
00091 group_id = H5Gopen( file_ptr->hdf_handle, ROOT_GROUP );
00092 #endif
00093 rval = mhdf_create_scalar_attrib( group_id, MAX_ID_ATTRIB, H5T_NATIVE_ULONG, &file_ptr->max_id, status );
00094 H5Gclose( group_id );
00095 if( !rval )
00096 {
00097 H5Fclose( file_ptr->hdf_handle );
00098 free( file_ptr );
00099 return NULL;
00100 }
00101
00102 /* Create the type name list in file */
00103 enum_id = H5Tenum_create( H5T_NATIVE_UCHAR );
00104 if( enum_id < 0 )
00105 {
00106 mhdf_setFail( status, "Failed to store elem type list." );
00107 H5Fclose( file_ptr->hdf_handle );
00108 free( file_ptr );
00109 return NULL;
00110 }
00111 for( i = 0; i < elem_list_len; ++i )
00112 {
00113 if( !elem_type_list[i] || !*elem_type_list[i] ) continue;
00114
00115 idx = (unsigned char)i;
00116 if( H5Tenum_insert( enum_id, elem_type_list[i], &idx ) < 0 )
00117 {
00118 mhdf_setFail( status, "Failed to store elem type list." );
00119 H5Fclose( file_ptr->hdf_handle );
00120 free( file_ptr );
00121 return NULL;
00122 }
00123 }
00124 #if defined( H5Tcommit_vers ) && H5Tcommit_vers > 1
00125 if( H5Tcommit2( file_ptr->hdf_handle, TYPE_ENUM_PATH, enum_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT ) < 0 )
00126 #else
00127 if( H5Tcommit( file_ptr->hdf_handle, TYPE_ENUM_PATH, enum_id ) < 0 )
00128 #endif
00129 {
00130 mhdf_setFail( status, "Failed to store elem type list." );
00131 H5Fclose( file_ptr->hdf_handle );
00132 free( file_ptr );
00133 return NULL;
00134 }
00135 H5Tclose( enum_id );
00136
00137 API_END_H( 1 );
00138 return file_ptr;
00139 }
00140
00141 mhdf_FileHandle mhdf_openFile( const char* filename,
00142 int writeable,
00143 unsigned long* max_id_out,
00144 hid_t id_type,
00145 mhdf_Status* status )
00146 {
00147 return mhdf_openFileWithOpt( filename, writeable, max_id_out, id_type, H5P_DEFAULT, status );
00148 }
00149
00150 int mhdf_countOpenHandles( mhdf_FileHandle file_handle )
00151 {
00152 return H5Fget_obj_count( ( (FileHandle*)file_handle )->hdf_handle, H5F_OBJ_ALL );
00153 }
00154
00155 static herr_t get_max_id( hid_t group_id, const char* subgroup, const char* datatable, unsigned long* data )
00156 {
00157 unsigned long id;
00158 hid_t elem_id, conn_id, attr_id, space_id;
00159 herr_t rval;
00160 int rank;
00161 hsize_t dims[2];
00162
00163 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
00164 elem_id = H5Gopen2( group_id, subgroup, H5P_DEFAULT );
00165 #else
00166 elem_id = H5Gopen( group_id, subgroup );
00167 #endif
00168 if( elem_id < 0 ) return (herr_t)-1;
00169
00170 #if defined( H5Dopen_vers ) && H5Dopen_vers > 1
00171 conn_id = H5Dopen2( elem_id, datatable, H5P_DEFAULT );
00172 #else
00173 conn_id = H5Dopen( elem_id, datatable );
00174 #endif
00175 H5Gclose( elem_id );
00176 if( conn_id < 0 ) return (herr_t)-1;
00177
00178 space_id = H5Dget_space( conn_id );
00179 if( space_id < 0 )
00180 {
00181 H5Dclose( conn_id );
00182 return -1;
00183 }
00184
00185 rank = H5Sget_simple_extent_ndims( space_id );
00186 if( rank <= 0 || rank > 2 )
00187 {
00188 H5Dclose( conn_id );
00189 H5Sclose( space_id );
00190 return -1;
00191 }
00192
00193 rval = H5Sget_simple_extent_dims( space_id, dims, NULL );
00194 H5Sclose( space_id );
00195 if( rval < 0 )
00196 {
00197 H5Dclose( conn_id );
00198 return -1;
00199 }
00200
00201 attr_id = H5Aopen_name( conn_id, START_ID_ATTRIB );
00202 H5Dclose( conn_id );
00203 if( attr_id < 0 ) return (herr_t)-1;
00204
00205 rval = H5Aread( attr_id, H5T_NATIVE_ULONG, &id );
00206 H5Aclose( attr_id );
00207 if( rval < 0 ) return rval;
00208
00209 id += dims[0];
00210 if( id > *data ) *data = id;
00211 return 0;
00212 }
00213
00214 static herr_t max_id_iter( hid_t group_id, const char* name, void* data )
00215 {
00216 return get_max_id( group_id, name, CONNECTIVITY_NAME, (unsigned long*)data );
00217 }
00218
00219 static int scan_for_max_id( FileHandle* file_ptr, mhdf_Status* status )
00220 {
00221 hid_t group_id;
00222 herr_t rval;
00223
00224 /* Check for new format, with max_id as attrib of root group */
00225 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
00226 group_id = H5Gopen2( file_ptr->hdf_handle, ROOT_GROUP, H5P_DEFAULT );
00227 #else
00228 group_id = H5Gopen( file_ptr->hdf_handle, ROOT_GROUP );
00229 #endif
00230 if( group_id < 0 )
00231 {
00232 mhdf_setFail( status, "Internal error - invalid file." );
00233 return 0;
00234 }
00235 if( mhdf_read_scalar_attrib( group_id, MAX_ID_ATTRIB, H5T_NATIVE_ULONG, &file_ptr->max_id, status ) )
00236 {
00237 H5Gclose( group_id );
00238 return 1;
00239 }
00240
00241 /* Didn't find it, scan the elements group */
00242 rval = H5Giterate( group_id, ELEMENT_GROUP_NAME, 0, &max_id_iter, &file_ptr->max_id );
00243 if( rval )
00244 {
00245 H5Gclose( group_id );
00246 mhdf_setFail( status, "Internal error -- invalid file." );
00247 return 0;
00248 }
00249
00250 /* Check node table too */
00251 rval = get_max_id( group_id, NODE_GROUP_NAME, "coordinates", (unsigned long*)( &file_ptr->max_id ) );
00252 if( rval )
00253 {
00254 H5Gclose( group_id );
00255 mhdf_setFail( status, "Internal error -- invalid file." );
00256 return 0;
00257 }
00258
00259 /* Check set table, if it exists */
00260 rval = mhdf_is_in_group( group_id, SET_GROUP_NAME, status );
00261 if( rval < 1 )
00262 {
00263 H5Gclose( group_id );
00264 return !rval;
00265 }
00266 rval = get_max_id( group_id, SET_GROUP_NAME, SET_META_NAME, (unsigned long*)( &file_ptr->max_id ) );
00267 H5Gclose( group_id );
00268 if( rval )
00269 {
00270 mhdf_setFail( status, "Internal error -- invalid file." );
00271 return 0;
00272 }
00273
00274 return 1;
00275 }
00276
00277 mhdf_FileHandle mhdf_openFileWithOpt( const char* filename,
00278 int writable,
00279 unsigned long* max_id_out,
00280 hid_t id_type,
00281 hid_t access_prop,
00282 mhdf_Status* status )
00283 {
00284 FileHandle* file_ptr;
00285 unsigned int flags;
00286 hid_t group_id;
00287 int check_is_hdf5 = 1;
00288 #ifdef MOAB_HAVE_HDF5_PARALLEL
00289 herr_t err;
00290 MPI_Comm comm;
00291 MPI_Info info;
00292 #endif
00293 API_BEGIN;
00294
00295 /* Check if file is HDF5 */
00296 /* Don't do this because it can't handle MPI-IO driver code that
00297 passes options via prefixes on the file name. */
00298 #ifdef MOAB_HAVE_HDF5_PARALLEL
00299 if( access_prop != H5P_DEFAULT )
00300 {
00301 err = H5Pget_fapl_mpio( access_prop, &comm, &info );
00302 if( err >= 0 )
00303 {
00304 check_is_hdf5 = 0;
00305 /* MPI Documentation is inconsistent with regards to whether
00306 or not the above call dup's these, but my testing with 1.8.3
00307 indicates that at least for that version they are not.
00308 MPI_Comm_free(&comm);
00309 MPI_Info_free(&info); */
00310 }
00311 }
00312 #endif
00313 if( check_is_hdf5 && H5Fis_hdf5( filename ) <= 0 )
00314 {
00315 mhdf_setFail( status, "%s: File is not HDF5", filename );
00316 return NULL;
00317 }
00318
00319 /* Create struct to hold working data */
00320 file_ptr = mhdf_alloc_FileHandle( 0, id_type, status );
00321 if( !file_ptr )
00322 {
00323 mhdf_setFail( status, "Memory allocation failed" );
00324 return NULL;
00325 }
00326
00327 /* Create the file */
00328 flags = writable ? H5F_ACC_RDWR : H5F_ACC_RDONLY;
00329 file_ptr->hdf_handle = H5Fopen( filename, flags, access_prop );
00330 if( file_ptr->hdf_handle < 0 )
00331 {
00332 mhdf_setFail( status, "Failed to open file \"%s\"", filename );
00333 free( file_ptr );
00334 return NULL;
00335 }
00336
00337 /* Check for TSTT data in file */
00338 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
00339 group_id = H5Gopen2( file_ptr->hdf_handle, ROOT_GROUP, H5P_DEFAULT );
00340 #else
00341 group_id = H5Gopen( file_ptr->hdf_handle, ROOT_GROUP );
00342 #endif
00343 if( group_id < 0 )
00344 {
00345 mhdf_setFail( status, "Invalid file \"%s\"\n", filename );
00346 H5Fclose( file_ptr->hdf_handle );
00347 free( file_ptr );
00348 return NULL;
00349 }
00350 H5Gclose( group_id );
00351
00352 /* Get max id */
00353 if( !scan_for_max_id( file_ptr, status ) )
00354 {
00355 H5Fclose( file_ptr->hdf_handle );
00356 mhdf_setFail( status, "Internal error reading file" );
00357 free( file_ptr );
00358 return NULL;
00359 }
00360
00361 if( max_id_out ) *max_id_out = file_ptr->max_id;
00362
00363 mhdf_setOkay( status );
00364 API_END_H( 1 );
00365 return file_ptr;
00366 }
00367
00368 void mhdf_getElemName( mhdf_FileHandle file_handle,
00369 unsigned int type_index,
00370 char* buffer,
00371 size_t buf_size,
00372 mhdf_Status* status )
00373 {
00374 FileHandle* file_ptr;
00375 herr_t rval;
00376 hid_t enum_id;
00377 API_BEGIN;
00378
00379 if( type_index > 255 )
00380 {
00381 mhdf_setFail( status, "Type index out of bounds." );
00382 return;
00383 }
00384
00385 file_ptr = (FileHandle*)( file_handle );
00386 if( !mhdf_check_valid_file( file_ptr, status ) ) return;
00387
00388 enum_id = get_elem_type_enum( file_ptr, status );
00389 if( enum_id < 0 ) return;
00390
00391 rval = H5Tconvert( H5T_NATIVE_UINT, H5Tget_super( enum_id ), 1, &type_index, NULL, H5P_DEFAULT );
00392 if( rval < 0 )
00393 {
00394 H5Tclose( enum_id );
00395 mhdf_setFail( status, "Internal error converting to enum type." );
00396 return;
00397 }
00398
00399 rval = H5Tenum_nameof( enum_id, &type_index, buffer, buf_size );
00400 H5Tclose( enum_id );
00401 if( rval < 0 )
00402 mhdf_setFail( status, "H5Tenum_nameof failed. Invalid type index?" );
00403 else
00404 mhdf_setOkay( status );
00405
00406 API_END;
00407 }
00408
00409 int mhdf_checkOpenHandles( mhdf_FileHandle handle, mhdf_Status* status )
00410 {
00411 FileHandle* file_ptr;
00412 int result;
00413 API_BEGIN;
00414
00415 file_ptr = (FileHandle*)( handle );
00416 if( !mhdf_check_valid_file( file_ptr, status ) ) return -1;
00417
00418 /* Check for open handles. HDF5 will not actually close the
00419 file until all handles are closed. */
00420 result = H5Fget_obj_count( file_ptr->hdf_handle, H5F_OBJ_ALL );
00421 if( result != 1 )
00422 {
00423 mhdf_setFail( status,
00424 "Cannot close file with open handles: "
00425 "%d file, %d data, %d group, %d type, %d attr\n",
00426 H5Fget_obj_count( file_ptr->hdf_handle, H5F_OBJ_FILE ) - 1,
00427 H5Fget_obj_count( file_ptr->hdf_handle, H5F_OBJ_DATASET ),
00428 H5Fget_obj_count( file_ptr->hdf_handle, H5F_OBJ_GROUP ),
00429 H5Fget_obj_count( file_ptr->hdf_handle, H5F_OBJ_DATATYPE ),
00430 H5Fget_obj_count( file_ptr->hdf_handle, H5F_OBJ_ATTR ) );
00431 return result - 1;
00432 }
00433
00434 API_END_H( 0 );
00435 return 0;
00436 }
00437
00438 void mhdf_closeFile( mhdf_FileHandle handle, mhdf_Status* status )
00439 {
00440 FileHandle* file_ptr;
00441 API_BEGIN;
00442
00443 file_ptr = (FileHandle*)( handle );
00444 if( !mhdf_check_valid_file( file_ptr, status ) ) return;
00445 /*
00446 if (file_ptr->open_handle_count)
00447 {
00448 mhdf_setError( status, "Cannot close file with %d open data handles.",
00449 file_ptr->open_handle_count );
00450 return;
00451 }
00452 */
00453
00454 /* Check for open handles. HDF5 will not actually close the
00455 file until all handles are closed. */
00456 if( mhdf_checkOpenHandles( handle, status ) ) return;
00457
00458 if( 0 > H5Fclose( file_ptr->hdf_handle ) )
00459 {
00460 mhdf_setFail( status, "H5FClose failed. Invalid handle?" );
00461 return;
00462 }
00463
00464 memset( file_ptr, 0, sizeof( FileHandle ) );
00465 free( file_ptr );
00466 mhdf_setOkay( status );
00467 API_END_H( -1 );
00468 }
00469
00470 void mhdf_closeData( mhdf_FileHandle file, hid_t handle, mhdf_Status* status )
00471 {
00472 FileHandle* file_ptr;
00473 herr_t rval = -1;
00474
00475 file_ptr = (FileHandle*)( file );
00476 if( !mhdf_check_valid_file( file_ptr, status ) ) return;
00477
00478 switch( H5Iget_type( handle ) )
00479 {
00480 case H5I_GROUP:
00481 rval = H5Gclose( handle );
00482 break;
00483 case H5I_DATATYPE:
00484 rval = H5Tclose( handle );
00485 break;
00486 case H5I_DATASPACE:
00487 rval = H5Sclose( handle );
00488 break;
00489 case H5I_DATASET:
00490 rval = H5Dclose( handle );
00491 break;
00492 default:
00493 rval = -1;
00494 }
00495
00496 if( rval < 0 )
00497 {
00498 mhdf_setFail( status, "H5Xclose failed. Invalid handle?\n" );
00499 }
00500 else
00501 {
00502 file_ptr->open_handle_count--;
00503 mhdf_setOkay( status );
00504 }
00505 }
00506
00507 void mhdf_addElement( mhdf_FileHandle file_handle, const char* name, unsigned int elem_type, mhdf_Status* status )
00508 {
00509 FileHandle* file_ptr = (FileHandle*)file_handle;
00510 hid_t group_id, tag_id, enum_id;
00511 char *path, *ptr;
00512 size_t name_len;
00513 herr_t rval;
00514 API_BEGIN;
00515
00516 if( !mhdf_check_valid_file( file_ptr, status ) ) return;
00517
00518 name_len = mhdf_name_to_path( name, NULL, 0 );
00519 name_len += strlen( ELEMENT_GROUP ) + 1;
00520 path = (char*)mhdf_malloc( name_len, status );
00521 if( !path ) return;
00522
00523 strcpy( path, ELEMENT_GROUP );
00524 ptr = path + strlen( ELEMENT_GROUP );
00525 if( !mhdf_path_to_name( name, ptr ) )
00526 {
00527 mhdf_setFail( status, "Invalid character string in internal file path: \"%s\"\n", name );
00528 return;
00529 }
00530
00531 #if defined( H5Gcreate_vers ) && H5Gcreate_vers > 1
00532 group_id = H5Gcreate2( file_ptr->hdf_handle, path, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
00533 #else
00534 group_id = H5Gcreate( file_ptr->hdf_handle, path, 3 );
00535 #endif
00536 if( group_id < 0 )
00537 {
00538 mhdf_setFail( status, "Creation of \"%s\" group failed.\n", path );
00539 free( path );
00540 return;
00541 }
00542 free( path );
00543
00544 #if defined( H5Gcreate_vers ) && H5Gcreate_vers > 1
00545 tag_id = H5Gcreate2( group_id, DENSE_TAG_SUBGROUP, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
00546 #else
00547 tag_id = H5Gcreate( group_id, DENSE_TAG_SUBGROUP, 0 );
00548 #endif
00549 if( tag_id < 0 )
00550 {
00551 H5Gclose( group_id );
00552 mhdf_setFail( status, "Creation of tag subgroup failed.\n" );
00553 return;
00554 }
00555 H5Gclose( tag_id );
00556
00557 enum_id = get_elem_type_enum( file_ptr, status );
00558 if( enum_id < 0 )
00559 {
00560 H5Gclose( group_id );
00561 return;
00562 }
00563
00564 rval = H5Tconvert( H5T_NATIVE_UINT, H5Tget_super( enum_id ), 1, &elem_type, NULL, H5P_DEFAULT );
00565 if( rval < 0 )
00566 {
00567 H5Gclose( group_id );
00568 H5Tclose( enum_id );
00569 mhdf_setFail( status, "Internal error converting to enum type." );
00570 return;
00571 }
00572
00573 rval = mhdf_create_scalar_attrib( group_id, ELEM_TYPE_ATTRIB, enum_id, &elem_type, status );
00574 H5Tclose( enum_id );
00575 if( rval < 0 )
00576 {
00577 H5Gclose( group_id );
00578 return;
00579 }
00580
00581 H5Gclose( group_id );
00582 mhdf_setOkay( status );
00583 API_END;
00584 }
00585
00586 char** mhdf_getElemHandles( mhdf_FileHandle file_handle, unsigned int* count_out, mhdf_Status* status )
00587 {
00588 hsize_t count, length, i;
00589 char** buffer;
00590 char* current;
00591 hid_t group_id;
00592 herr_t rval;
00593 ssize_t rlen = 0;
00594 size_t remaining;
00595 FileHandle* file_ptr = (FileHandle*)file_handle;
00596 if( !mhdf_check_valid_file( file_ptr, status ) ) return NULL;
00597
00598 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
00599 group_id = H5Gopen2( file_ptr->hdf_handle, ELEMENT_GROUP, H5P_DEFAULT );
00600 #else
00601 group_id = H5Gopen( file_ptr->hdf_handle, ELEMENT_GROUP );
00602 #endif
00603 if( group_id < 0 )
00604 {
00605 mhdf_setFail( status, "Invalid file -- element group does not exist." );
00606 return NULL;
00607 }
00608
00609 rval = H5Gget_num_objs( group_id, &count );
00610 if( rval < 0 )
00611 {
00612 H5Gclose( group_id );
00613 mhdf_setFail( status, "Internal error calling H5Gget_num_objs." );
00614 return NULL;
00615 }
00616 *count_out = count;
00617
00618 for( i = 0; i < count; ++i )
00619 {
00620 rlen += H5Gget_objname_by_idx( group_id, i, NULL, 0 ) + 1;
00621 }
00622
00623 length = count * sizeof( char* ) + rlen;
00624 buffer = (char**)mhdf_malloc( length, status );
00625 if( !buffer )
00626 {
00627 H5Gclose( group_id );
00628 return NULL;
00629 }
00630 current = (char*)( buffer + count );
00631 remaining = rlen;
00632
00633 for( i = 0; i < count; ++i )
00634 {
00635 buffer[i] = current;
00636 rlen = H5Gget_objname_by_idx( group_id, i, current, remaining ) + 1;
00637 if( rlen < 0 )
00638 {
00639 H5Gclose( group_id );
00640 free( buffer );
00641 mhdf_setFail( status, "Internal error calling H5Gget_objname_by_idx." );
00642 return NULL;
00643 }
00644
00645 mhdf_path_to_name( current, current );
00646 remaining -= rlen;
00647 current += rlen;
00648 }
00649
00650 H5Gclose( group_id );
00651 mhdf_setOkay( status );
00652 return buffer;
00653 }
00654
00655 void mhdf_getElemTypeName( mhdf_FileHandle file_handle,
00656 const char* elem_handle,
00657 char* buffer,
00658 size_t buf_len,
00659 mhdf_Status* status )
00660 {
00661 FileHandle* file_ptr;
00662 hid_t elem_id, type_id, attr_id;
00663 char bytes[16];
00664 herr_t rval;
00665 API_BEGIN;
00666
00667 if( NULL == buffer || buf_len < 2 )
00668 {
00669 mhdf_setFail( status, "invalid input" );
00670 return;
00671 }
00672 buffer[0] = '\0';
00673
00674 file_ptr = (FileHandle*)( file_handle );
00675 if( !mhdf_check_valid_file( file_ptr, status ) ) return;
00676
00677 elem_id = mhdf_elem_group_from_handle( file_ptr, elem_handle, status );
00678 if( elem_id < 0 ) return;
00679
00680 attr_id = H5Aopen_name( elem_id, ELEM_TYPE_ATTRIB );
00681 H5Gclose( elem_id );
00682 if( attr_id < 0 )
00683 {
00684 mhdf_setFail( status, "Missing element type attribute. Invalid file." );
00685 return;
00686 }
00687
00688 type_id = H5Aget_type( attr_id );
00689 assert( type_id > 0 );
00690
00691 rval = H5Aread( attr_id, type_id, bytes );
00692 H5Aclose( attr_id );
00693 if( rval < 0 )
00694 {
00695 H5Tclose( type_id );
00696 mhdf_setFail( status, "Failed to read element type attribute. Invalid file." );
00697 return;
00698 }
00699
00700 rval = H5Tenum_nameof( type_id, bytes, buffer, buf_len );
00701 H5Tclose( type_id );
00702 if( rval < 0 )
00703 {
00704 mhdf_setFail( status, "Invalid datatype for element type attribute. Invalid file." );
00705 return;
00706 }
00707
00708 mhdf_setOkay( status );
00709 API_END;
00710 return;
00711 }
00712
00713 static int make_hdf_group( const char* path, hid_t file, size_t sz, mhdf_Status* status )
00714 {
00715 #if defined( H5Gcreate_vers ) && H5Gcreate_vers > 1
00716 hid_t handle = H5Gcreate2( file, path, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
00717 /* empty statement to avoid compiler warning */
00718 if( sz )
00719 {
00720 }
00721 #else
00722 hid_t handle = H5Gcreate( file, path, sz );
00723 #endif
00724 if( handle < 0 )
00725 {
00726 mhdf_setFail( status, "Failed to create \"%s\" group.", path );
00727 return 0;
00728 }
00729 else
00730 {
00731 H5Gclose( handle );
00732 return 1;
00733 }
00734 }
00735
00736 const char* mhdf_node_type_handle( void )
00737 {
00738 static const char rval[] = "nodes";
00739 return rval;
00740 }
00741
00742 const char* mhdf_set_type_handle( void )
00743 {
00744 static const char rval[] = "sets";
00745 return rval;
00746 }
00747
00748 int mhdf_isPolyElement( mhdf_FileHandle file_handle, const char* elem_handle, mhdf_Status* status )
00749 {
00750 FileHandle* file_ptr;
00751 hid_t elem_id;
00752 int rval;
00753 API_BEGIN;
00754
00755 file_ptr = (FileHandle*)( file_handle );
00756 if( !mhdf_check_valid_file( file_ptr, status ) ) return -1;
00757
00758 elem_id = mhdf_elem_group_from_handle( file_ptr, elem_handle, status );
00759 if( elem_id < 0 ) return -1;
00760
00761 mhdf_setOkay( status );
00762 rval = mhdf_is_in_group( elem_id, POLY_INDEX_NAME, status );
00763 H5Gclose( elem_id );
00764 API_END;
00765 return rval;
00766 }
00767
00768 void mhdf_writeHistory( mhdf_FileHandle file_handle, const char** strings, int num_strings, mhdf_Status* status )
00769 {
00770 FileHandle* file_ptr;
00771 hid_t data_id, type_id, space_id;
00772 hsize_t dim = (hsize_t)num_strings;
00773 herr_t rval;
00774 API_BEGIN;
00775
00776 file_ptr = (FileHandle*)( file_handle );
00777 if( !mhdf_check_valid_file( file_ptr, status ) ) return;
00778
00779 type_id = H5Tcopy( H5T_C_S1 );
00780 if( type_id < 0 || H5Tset_size( type_id, H5T_VARIABLE ) < 0 )
00781 {
00782 if( type_id >= 0 ) H5Tclose( type_id );
00783 mhdf_setFail( status, "Could not create variable length string type." );
00784 return;
00785 }
00786
00787 space_id = H5Screate_simple( 1, &dim, NULL );
00788 if( space_id < 0 )
00789 {
00790 H5Tclose( type_id );
00791 mhdf_setFail( status, "H5Screate_simple failed." );
00792 return;
00793 }
00794
00795 #if defined( H5Dcreate_vers ) && H5Dcreate_vers > 1
00796 data_id =
00797 H5Dcreate2( file_ptr->hdf_handle, HISTORY_PATH, type_id, space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
00798 #else
00799 data_id = H5Dcreate( file_ptr->hdf_handle, HISTORY_PATH, type_id, space_id, H5P_DEFAULT );
00800 #endif
00801 H5Sclose( space_id );
00802 if( data_id < 0 )
00803 {
00804 H5Tclose( type_id );
00805 mhdf_setFail( status, "Failed to create \"%s\".", HISTORY_PATH );
00806 return;
00807 }
00808
00809 rval = H5Dwrite( data_id, type_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, strings );
00810 H5Dclose( data_id );
00811 H5Tclose( type_id );
00812 if( rval < 0 )
00813 {
00814 H5Gunlink( file_ptr->hdf_handle, HISTORY_PATH );
00815 mhdf_setFail( status, "Failed to write history data." );
00816 return;
00817 }
00818
00819 mhdf_setOkay( status );
00820 API_END;
00821 }
00822
00823 char** mhdf_readHistory( mhdf_FileHandle file_handle, int* num_strings, mhdf_Status* status )
00824 {
00825 FileHandle* file_ptr;
00826 hid_t data_id, type_id, space_id, group_id;
00827 hsize_t dim;
00828 herr_t rval;
00829 char** array;
00830 API_BEGIN;
00831
00832 file_ptr = (FileHandle*)( file_handle );
00833 if( !mhdf_check_valid_file( file_ptr, status ) ) return NULL;
00834
00835 /* check if file contains history data */
00836 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
00837 group_id = H5Gopen2( file_ptr->hdf_handle, ROOT_GROUP, H5P_DEFAULT );
00838 #else
00839 group_id = H5Gopen( file_ptr->hdf_handle, ROOT_GROUP );
00840 #endif
00841 if( group_id < 0 )
00842 {
00843 mhdf_setFail( status, "Could not open root group. Invalid file." );
00844 return NULL;
00845 }
00846
00847 rval = mhdf_is_in_group( group_id, HISTORY_NAME, status );
00848 if( rval < 1 )
00849 {
00850 H5Gclose( group_id );
00851 *num_strings = 0;
00852 if( 0 == rval ) mhdf_setOkay( status );
00853 return NULL;
00854 }
00855
00856 #if defined( H5Dopen_vers ) && H5Dopen_vers > 1
00857 data_id = H5Dopen2( group_id, HISTORY_NAME, H5P_DEFAULT );
00858 #else
00859 data_id = H5Dopen( group_id, HISTORY_NAME );
00860 #endif
00861 H5Gclose( group_id );
00862 if( data_id < 0 )
00863 {
00864 mhdf_setFail( status, "Failed to open \"%s\".", HISTORY_PATH );
00865 return NULL;
00866 }
00867
00868 space_id = H5Dget_space( data_id );
00869 if( space_id < 0 )
00870 {
00871 H5Dclose( data_id );
00872 mhdf_setFail( status, "Internal error calling H5Dget_space." );
00873 return NULL;
00874 }
00875
00876 if( 1 != H5Sget_simple_extent_ndims( space_id ) || 1 != H5Sget_simple_extent_dims( space_id, &dim, NULL ) )
00877 {
00878 H5Dclose( data_id );
00879 mhdf_setFail( status, "Invalid dimension for \"%s\".", HISTORY_PATH );
00880 return NULL;
00881 }
00882 H5Sclose( space_id );
00883
00884 if( 0 == dim )
00885 {
00886 H5Dclose( data_id );
00887 *num_strings = 0;
00888 mhdf_setOkay( status );
00889 return NULL;
00890 }
00891
00892 array = (char**)mhdf_malloc( dim * sizeof( char* ), status );
00893 if( !array )
00894 {
00895 H5Dclose( data_id );
00896 return NULL;
00897 }
00898
00899 type_id = H5Tcopy( H5T_C_S1 );
00900 if( type_id < 0 || H5Tset_size( type_id, H5T_VARIABLE ) < 0 )
00901 {
00902 H5Dclose( data_id );
00903 if( type_id >= 0 ) H5Tclose( type_id );
00904 mhdf_setFail( status, "Could not create variable length string type." );
00905 free( array );
00906 return NULL;
00907 }
00908
00909 rval = H5Dread( data_id, type_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, array );
00910 H5Tclose( type_id );
00911 H5Dclose( data_id );
00912 if( rval < 0 )
00913 {
00914 free( array );
00915 mhdf_setFail( status, "H5Dread failed." );
00916 return NULL;
00917 }
00918
00919 *num_strings = dim;
00920 mhdf_setOkay( status );
00921 API_END;
00922 return array;
00923 }
00924
00925 void mhdf_getNextStartId( mhdf_FileHandle file, mhdf_index_t* start_id_out, mhdf_Status* status )
00926 {
00927 FileHandle* file_ptr = (FileHandle*)file;
00928 API_BEGIN;
00929
00930 mhdf_setOkay( status );
00931 if( mhdf_check_valid_file( file_ptr, status ) ) *start_id_out = file_ptr->max_id + 1;
00932
00933 API_END;
00934 }