MOAB: Mesh Oriented datABase
(version 5.4.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, 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 }