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