diff options
author | Pedro Vicente Nunes <pvn@hdfgroup.org> | 2005-01-28 18:55:20 (GMT) |
---|---|---|
committer | Pedro Vicente Nunes <pvn@hdfgroup.org> | 2005-01-28 18:55:20 (GMT) |
commit | 1df1c1ba6d162772f421b5e6dd5c2e64031684db (patch) | |
tree | a3004c4d1b5913af83ac9f77bcb0558157a2d042 /hl/src/H5TB.c | |
parent | 792e19e6b81522dde7e94d015783d37b86afc2bd (diff) | |
download | hdf5-1df1c1ba6d162772f421b5e6dd5c2e64031684db.zip hdf5-1df1c1ba6d162772f421b5e6dd5c2e64031684db.tar.gz hdf5-1df1c1ba6d162772f421b5e6dd5c2e64031684db.tar.bz2 |
[svn-r9881] Purpose:
changed the name of the hl table files back to H5TB.c and H5TB.h
this can be done now because the H5TB.c (threaded binary trees) file was removed from the hdf5 library
Description:
Solution:
Platforms tested:
linux
Misc. update:
Diffstat (limited to 'hl/src/H5TB.c')
-rw-r--r-- | hl/src/H5TB.c | 3682 |
1 files changed, 3682 insertions, 0 deletions
diff --git a/hl/src/H5TB.c b/hl/src/H5TB.c new file mode 100644 index 0000000..6b58c0f --- /dev/null +++ b/hl/src/H5TB.c @@ -0,0 +1,3682 @@ +/**************************************************************************** + * NCSA HDF * + * Scientific Data Technologies * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +#include "H5TB.h" +#include <stdlib.h> +#include <string.h> + +#if 0 +#define SHRINK +#endif + + +/*------------------------------------------------------------------------- + * + * Private functions + * + *------------------------------------------------------------------------- + */ + +int H5TB_find_field(const char *field, + const char *field_list); + +herr_t H5TB_attach_attributes(const char *table_title, + hid_t loc_id, + const char *dset_name, + hsize_t nfields, + hid_t tid ); + +hid_t H5TB_create_type(hid_t loc_id, + const char *dset_name, + size_t dst_size, + const size_t *dst_offset, + const size_t *dst_sizes, + hid_t ftype_id); + +/*------------------------------------------------------------------------- + * + * Create functions + * + *------------------------------------------------------------------------- + */ + +/*------------------------------------------------------------------------- + * Function: H5TBmake_table + * + * Purpose: Make a table + * + * Return: Success: 0, Failure: -1 + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * Quincey Koziol + * + * Date: January 17, 2001 + * + * Comments: The data is packed + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + + +herr_t H5TBmake_table( const char *table_title, + hid_t loc_id, + const char *dset_name, + hsize_t nfields, + hsize_t nrecords, + size_t type_size, + const char *field_names[], + const size_t *field_offset, + const hid_t *field_types, + hsize_t chunk_size, + void *fill_data, + int compress, + const void *data ) +{ + + hid_t did; + hid_t sid; + hid_t mem_type_id; + hid_t plist_id; + hsize_t dims[1]; + hsize_t dims_chunk[1]; + hsize_t maxdims[1] = { H5S_UNLIMITED }; + char attr_name[255]; + char *member_name; + hid_t attr_id; + char aux[255]; + hsize_t i; + unsigned char *tmp_buf; + + dims[0] = nrecords; + dims_chunk[0] = chunk_size; + + /* Create the memory data type. */ + if ((mem_type_id = H5Tcreate (H5T_COMPOUND, type_size )) < 0 ) + return -1; + + /* Insert fields. */ + for ( i = 0; i < nfields; i++) + { + if ( H5Tinsert(mem_type_id, field_names[i], field_offset[i], field_types[i] ) < 0 ) + return -1; + } + + /* Create a simple data space with unlimited size */ + if ( (sid = H5Screate_simple( 1, dims, maxdims )) < 0 ) + return -1; + + /* Modify dataset creation properties, i.e. enable chunking */ + plist_id = H5Pcreate (H5P_DATASET_CREATE); + if ( H5Pset_chunk ( plist_id, 1, dims_chunk ) < 0 ) + return -1; + + /* Set the fill value using a struct as the data type. */ + if ( fill_data ) + { + if ( H5Pset_fill_value( plist_id, mem_type_id, fill_data ) < 0 ) + return -1; + } + + /* + Dataset creation property list is modified to use + GZIP compression with the compression effort set to 6. + Note that compression can be used only when dataset is chunked. + */ + if ( compress ) + { + if ( H5Pset_deflate( plist_id, 6) < 0 ) + return -1; + } + + /* Create the dataset. */ + if ( (did = H5Dcreate( loc_id, dset_name, mem_type_id, sid, plist_id )) < 0 ) + goto out; + + /* Only write if there is something to write */ + if ( data ) + { + /* Write data to the dataset. */ + if ( H5Dwrite( did, mem_type_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, data ) < 0 ) + goto out; + } + + /* Terminate access to the data space. */ + if ( H5Sclose( sid ) < 0 ) + goto out; + + /* End access to the dataset */ + if ( H5Dclose( did ) < 0 ) + goto out; + + /* End access to the property list */ + if ( H5Pclose( plist_id ) < 0 ) + goto out; + +/*------------------------------------------------------------------------- + * Set the conforming table attributes + *------------------------------------------------------------------------- + */ + + /* Attach the CLASS attribute */ + if ( H5LTset_attribute_string( loc_id, dset_name, "CLASS", "TABLE" ) < 0 ) + goto out; + + /* Attach the VERSION attribute */ + if ( H5LTset_attribute_string( loc_id, dset_name, "VERSION", "2.0" ) < 0 ) + goto out; + + /* Attach the TITLE attribute */ + if ( H5LTset_attribute_string( loc_id, dset_name, "TITLE", table_title ) < 0 ) + goto out; + + /* Attach the FIELD_ name attribute */ + for ( i = 0; i < nfields; i++) + { + + /* Get the member name */ + member_name = H5Tget_member_name( mem_type_id,(unsigned) i ); + + strcpy( attr_name, "FIELD_" ); + sprintf( aux, "%d", (int)i ); + strcat( attr_name, aux ); + sprintf( aux, "%s", "_NAME" ); + strcat( attr_name, aux ); + + /* Attach the attribute */ + if ( H5LTset_attribute_string( loc_id, dset_name, attr_name, member_name ) < 0 ) + goto out; + + free( member_name ); + + } + + /* Attach the FIELD_ fill value attribute */ + if ( fill_data ) + { + + tmp_buf = fill_data; + + /* Open the dataset. */ + if ( (did = H5Dopen( loc_id, dset_name )) < 0 ) + return -1; + + if (( sid = H5Screate(H5S_SCALAR)) < 0 ) + goto out; + + for ( i = 0; i < nfields; i++) + { + + /* Get the member name */ + member_name = H5Tget_member_name( mem_type_id, (unsigned) i ); + + strcpy( attr_name, "FIELD_" ); + sprintf( aux, "%d", (int)i ); + strcat( attr_name, aux ); + sprintf( aux, "%s", "_FILL" ); + strcat( attr_name, aux ); + + if ( (attr_id = H5Acreate( did, attr_name, field_types[i], sid, H5P_DEFAULT )) < 0 ) + goto out; + + if ( H5Awrite( attr_id, field_types[i], tmp_buf+field_offset[i] ) < 0 ) + goto out; + + if ( H5Aclose( attr_id ) < 0 ) + goto out; + + free( member_name ); + } + + /* Close the dataset. */ + H5Dclose( did ); + + /* Close data space. */ + H5Sclose( sid ); + } + + /* Release the datatype. */ + if ( H5Tclose( mem_type_id ) < 0 ) + return -1; + + +return 0; + +/* error zone, gracefully close */ +out: + H5E_BEGIN_TRY { + H5Dclose(did); + H5Sclose(sid); + H5Pclose(plist_id); + H5Tclose(mem_type_id); + } H5E_END_TRY; + return -1; + +} + +/*------------------------------------------------------------------------- + * + * Write functions + * + *------------------------------------------------------------------------- + */ + +/*------------------------------------------------------------------------- + * Function: H5TBappend_records + * + * Purpose: Appends records to a table + * + * Return: Success: 0, Failure: -1 + * + * Programmers: + * Pedro Vicente, pvn@ncsa.uiuc.edu + * Quincey Koziol + * + * Date: November 19, 2001 + * + * Comments: Uses memory offsets + * + * Modifications: April 1, 2004 + * the DST_SIZES parameter is used to define the memory type ID + * returned by H5TB_create_type + * + *------------------------------------------------------------------------- + */ + +herr_t H5TBappend_records( hid_t loc_id, + const char *dset_name, + hsize_t nrecords, + size_t dst_size, + const size_t *dst_offset, + const size_t *dst_sizes, + const void *data ) +{ + hid_t did; + hid_t tid=-1; + hid_t mem_type_id=-1; + hsize_t count[1]; + hsize_t offset[1]; + hid_t sid=-1; + hid_t mem_space_id=-1; + hsize_t dims[1]; + hsize_t mem_dims[1]; + hsize_t nrecords_orig; + hsize_t nfields; + + /* Get the original number of records and fields */ + if ( H5TBget_table_info ( loc_id, dset_name, &nfields, &nrecords_orig ) < 0 ) + return -1; + + /* Open the dataset. */ + if ( (did = H5Dopen( loc_id, dset_name )) < 0 ) + goto out; + + /* Get the datatypes */ + if ( (tid = H5Dget_type( did )) < 0 ) + goto out; + + if ((mem_type_id=H5TB_create_type(loc_id,dset_name,dst_size,dst_offset,dst_sizes,tid))<0) + goto out; + + /* Extend the dataset */ + dims[0] = nrecords_orig; + dims[0] += nrecords; + + if ( H5Dextend ( did, dims ) < 0 ) + goto out; + + /* Create a simple memory data space */ + mem_dims[0]=nrecords; + if ( (mem_space_id = H5Screate_simple( 1, mem_dims, NULL )) < 0 ) + return -1; + + /* Get the file data space */ + if ( (sid = H5Dget_space( did )) < 0 ) + return -1; + + /* Get the dimensions */ + if ( H5Sget_simple_extent_dims( sid, dims, NULL ) != 1 ) + goto out; + + /* Define a hyperslab in the dataset */ + offset[0] = nrecords_orig; + count[0] = nrecords; + if ( H5Sselect_hyperslab( sid, H5S_SELECT_SET, offset, NULL, count, NULL) < 0 ) + goto out; + + if ( H5Dwrite( did, mem_type_id, mem_space_id, sid, H5P_DEFAULT, data ) < 0 ) + goto out; + + /* Terminate access to the dataspace */ + if ( H5Sclose( mem_space_id ) < 0 ) + goto out; + + if ( H5Sclose( sid ) < 0 ) + goto out; + + /* Release the datatype. */ + if ( H5Tclose( tid ) < 0 ) + return -1; + + /* Release the datatype. */ + if ( H5Tclose( mem_type_id ) < 0 ) + goto out; + + /* End access to the dataset */ + if ( H5Dclose( did ) < 0 ) + goto out; + + +return 0; + +/* error zone, gracefully close */ +out: + H5E_BEGIN_TRY { + H5Dclose(did); + H5Tclose(mem_type_id); + H5Tclose(tid); + H5Sclose(mem_space_id); + H5Sclose(sid); + } H5E_END_TRY; + return -1; +} + +/*------------------------------------------------------------------------- + * Function: H5TBwrite_records + * + * Purpose: Writes records + * + * Return: Success: 0, Failure: -1 + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: November 19, 2001 + * + * Comments: Uses memory offsets + * + * Modifications: April 1, 2004 + * the DST_SIZES parameter is used to define the memory type ID + * returned by H5TB_create_type + * + *------------------------------------------------------------------------- + */ + + +herr_t H5TBwrite_records( hid_t loc_id, + const char *dset_name, + hsize_t start, + hsize_t nrecords, + size_t dst_size, + const size_t *dst_offset, + const size_t *dst_sizes, + const void *data ) +{ + + hid_t did; + hid_t tid; + hsize_t count[1]; + hsize_t offset[1]; + hid_t sid=-1; + hid_t mem_space_id=-1; + hsize_t mem_size[1]; + hsize_t dims[1]; + hid_t mem_type_id=-1; + + /* Open the dataset. */ + if ( (did = H5Dopen( loc_id, dset_name )) < 0 ) + return -1; + + /* Get the datatype */ + if ( (tid = H5Dget_type( did )) < 0 ) + goto out; + + if ((mem_type_id=H5TB_create_type(loc_id,dset_name,dst_size,dst_offset,dst_sizes,tid))<0) + goto out; + + /* Get the dataspace handle */ + if ( (sid = H5Dget_space( did )) < 0 ) + goto out; + + /* Get records */ + if ( H5Sget_simple_extent_dims( sid, dims, NULL) < 0 ) + goto out; + + if ( start + nrecords > dims[0] ) + goto out; + + /* Define a hyperslab in the dataset of the size of the records */ + offset[0] = start; + count[0] = nrecords; + if ( H5Sselect_hyperslab( sid, H5S_SELECT_SET, offset, NULL, count, NULL) < 0 ) + goto out; + + /* Create a memory dataspace handle */ + mem_size[0] = count[0]; + if ( (mem_space_id = H5Screate_simple( 1, mem_size, NULL )) < 0 ) + goto out; + + if ( H5Dwrite( did, mem_type_id, mem_space_id, sid, H5P_DEFAULT, data ) < 0 ) + goto out; + + /* Terminate access to the memory dataspace */ + if ( H5Sclose( mem_space_id ) < 0 ) + goto out; + + /* Terminate access to the dataspace */ + if ( H5Sclose( sid ) < 0 ) + goto out; + + /* Release the datatype. */ + if ( H5Tclose( tid ) < 0 ) + goto out; + + /* Release the datatype. */ + if ( H5Tclose( mem_type_id ) < 0 ) + return -1; + + /* End access to the dataset */ + if ( H5Dclose( did ) < 0 ) + return -1; + + +return 0; + +/* error zone, gracefully close */ +out: + H5E_BEGIN_TRY { + H5Dclose(did); + H5Tclose(mem_type_id); + H5Tclose(tid); + H5Sclose(mem_space_id); + H5Sclose(sid); + } H5E_END_TRY; + return -1; +} + +/*------------------------------------------------------------------------- + * Function: H5TBwrite_fields_name + * + * Purpose: Writes fields + * + * Return: Success: 0, Failure: -1 + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: November 21, 2001 + * + * Comments: + * + * Modifications: April 1, 2004 + * the DST_SIZES parameter is used to define the memory type ID + * returned by H5TB_create_type + * + *------------------------------------------------------------------------- + */ +herr_t H5TBwrite_fields_name( hid_t loc_id, + const char *dset_name, + const char *field_names, + hsize_t start, + hsize_t nrecords, + size_t type_size, + const size_t *field_offset, + const size_t *dst_sizes, + const void *data ) +{ + + hid_t did; + hid_t tid=-1; + hid_t write_type_id=-1; + hid_t member_type_id; + hid_t nmtype_id; + hsize_t count[1]; + hsize_t offset[1]; + hid_t sid=-1; + char *member_name; + hssize_t nfields; + hssize_t i, j; + hid_t PRESERVE; + size_t size_native; + + /* Create xfer properties to preserve initialized data */ + if ((PRESERVE = H5Pcreate (H5P_DATASET_XFER))<0) + return -1; + if (H5Pset_preserve (PRESERVE, 1)<0) + return -1; + + /* Open the dataset. */ + if ( (did = H5Dopen( loc_id, dset_name )) < 0 ) + goto out; + + /* Get the datatype */ + if ( (tid = H5Dget_type( did )) < 0 ) + goto out; + + /* Get the number of fields */ + if ( ( nfields = H5Tget_nmembers( tid )) < 0 ) + goto out; + + /* Create a write id */ + if ( ( write_type_id = H5Tcreate( H5T_COMPOUND, type_size )) < 0 ) + goto out; + + j = 0; + + /* Iterate tru the members */ + for ( i = 0; i < nfields; i++) + { + /* Get the member name */ + member_name = H5Tget_member_name( tid, (unsigned)i ); + + if ( H5TB_find_field( member_name, field_names ) > 0 ) + { + + /* Get the member type */ + if ( ( member_type_id = H5Tget_member_type( tid,(unsigned) i )) < 0 ) + goto out; + + /* Convert to native type */ + if ((nmtype_id=H5Tget_native_type(member_type_id,H5T_DIR_DEFAULT))<0) + goto out; + + size_native=H5Tget_size(nmtype_id); + + /* Adjust, if necessary */ + if (dst_sizes[j]!=size_native) + { + if (H5Tset_size(nmtype_id, dst_sizes[j])<0) + goto out; + } + + /* The field in the file is found by its name */ + if ( field_offset ) + { + if ( H5Tinsert( write_type_id, member_name, field_offset[j], nmtype_id ) < 0 ) + goto out; + } + /* Only one field */ + else + { + if ( H5Tinsert( write_type_id, member_name, 0, nmtype_id ) < 0 ) + goto out; + } + + j++; + + /* Close */ + if ( H5Tclose( member_type_id ) < 0 ) + goto out; + if ( H5Tclose( nmtype_id ) < 0 ) + goto out; + } + + free( member_name ); + + } + + /* Get the dataspace handle */ + if ( (sid = H5Dget_space( did )) < 0 ) + goto out; + + /* Define a hyperslab in the dataset */ + offset[0] = start; + count[0] = nrecords; + if ( H5Sselect_hyperslab( sid, H5S_SELECT_SET, offset, NULL, count, NULL) < 0 ) + goto out; + + /* Write */ + if ( H5Dwrite( did, write_type_id, H5S_ALL, sid, PRESERVE, data ) < 0 ) + goto out; + + /* End access to the write id */ + if ( H5Tclose( write_type_id ) ) + goto out; + + /* Release the datatype. */ + if ( H5Tclose( tid ) < 0 ) + return -1; + + /* End access to the dataset */ + if ( H5Dclose( did ) < 0 ) + return -1; + + /* End access to the property list */ + if ( H5Pclose( PRESERVE ) < 0 ) + return -1; + +return 0; + + /* error zone, gracefully close */ +out: + H5E_BEGIN_TRY { + H5Pclose(PRESERVE); + H5Dclose(did); + H5Sclose(sid); + H5Tclose(write_type_id); + H5Tclose(tid); + } H5E_END_TRY; + return -1; + +} + + + +/*------------------------------------------------------------------------- + * Function: H5TBwrite_fields_index + * + * Purpose: Writes fields + * + * Return: Success: 0, Failure: -1 + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: November 21, 2001 + * + * Comments: Uses memory offsets + * + * Modifications: April 1, 2004 + * the DST_SIZES parameter is used to define the memory type ID + * returned by H5TB_create_type + * + *------------------------------------------------------------------------- + */ + + +herr_t H5TBwrite_fields_index( hid_t loc_id, + const char *dset_name, + hsize_t nfields, + const int *field_index, + hsize_t start, + hsize_t nrecords, + size_t type_size, + const size_t *field_offset, + const size_t *dst_sizes, + const void *data ) +{ + + hid_t did; + hid_t tid=-1; + hid_t write_type_id=-1; + hid_t member_type_id; + hid_t nmtype_id; + hsize_t count[1]; + hsize_t offset[1]; + hid_t sid=-1; + char *member_name; + hsize_t i, j; + hid_t PRESERVE; + size_t size_native; + + /* Create xfer properties to preserve initialized data */ + if ((PRESERVE = H5Pcreate (H5P_DATASET_XFER))<0) + return -1; + if (H5Pset_preserve (PRESERVE, 1)<0) + return -1; + + /* Open the dataset. */ + if ( (did = H5Dopen( loc_id, dset_name )) < 0 ) + goto out; + + /* Get the datatype */ + if ( (tid = H5Dget_type( did )) < 0 ) + goto out; + + /* Get the number of fields */ + if ( H5Tget_nmembers( tid ) < 0 ) + goto out; + + /* Create a write id */ + if ( ( write_type_id = H5Tcreate( H5T_COMPOUND, type_size )) < 0 ) + goto out; + + + /* Iterate tru the members */ + for ( i = 0; i < nfields; i++) + { + + j = field_index[i]; + + /* Get the member name */ + member_name = H5Tget_member_name( tid, (unsigned) j ); + + /* Get the member type */ + if ( ( member_type_id = H5Tget_member_type( tid, (unsigned) j )) < 0 ) + goto out; + + /* Convert to native type */ + if ((nmtype_id=H5Tget_native_type(member_type_id,H5T_DIR_DEFAULT))<0) + goto out; + + size_native=H5Tget_size(nmtype_id); + + if (dst_sizes[i]!=size_native) + { + if (H5Tset_size(nmtype_id, dst_sizes[i])<0) + goto out; + } + + /* The field in the file is found by its name */ + if ( field_offset ) + { + if ( H5Tinsert( write_type_id, member_name, field_offset[ i ], nmtype_id ) < 0 ) + goto out; + } + /* Only one field */ + else + { + if ( H5Tinsert( write_type_id, member_name, 0, nmtype_id ) < 0 ) + goto out; + } + /* Close */ + if ( H5Tclose( member_type_id ) < 0 ) + goto out; + if ( H5Tclose( nmtype_id ) < 0 ) + goto out; + + free( member_name ); + + } + + /* Get the dataspace handle */ + if ( (sid = H5Dget_space( did )) < 0 ) + goto out; + + /* Define a hyperslab in the dataset */ + offset[0] = start; + count[0] = nrecords; + if ( H5Sselect_hyperslab( sid, H5S_SELECT_SET, offset, NULL, count, NULL) < 0 ) + goto out; + + /* Write */ + if ( H5Dwrite( did, write_type_id, H5S_ALL, sid, PRESERVE, data ) < 0 ) + goto out; + + /* End access to the write id */ + if ( H5Tclose( write_type_id ) ) + goto out; + + /* Release the datatype. */ + if ( H5Tclose( tid ) < 0 ) + return -1; + + /* End access to the dataset */ + if ( H5Dclose( did ) < 0 ) + return -1; + + /* End access to the property list */ + if ( H5Pclose( PRESERVE ) < 0 ) + return -1; + +return 0; + + /* error zone, gracefully close */ +out: + H5E_BEGIN_TRY { + H5Pclose(PRESERVE); + H5Dclose(did); + H5Sclose(sid); + H5Tclose(write_type_id); + H5Tclose(tid); + } H5E_END_TRY; + return -1; +} + + +/*------------------------------------------------------------------------- + * + * Read functions + * + *------------------------------------------------------------------------- + */ + + +/*------------------------------------------------------------------------- + * Function: H5TBread_table + * + * Purpose: Reads a table + * + * Return: Success: 0, Failure: -1 + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: November 20, 2001 + * + * Comments: + * + * Modifications: April 1, 2004 + * used a memory type ID returned by H5TB_create_type + * + *------------------------------------------------------------------------- + */ + +herr_t H5TBread_table( hid_t loc_id, + const char *dset_name, + size_t dst_size, + const size_t *dst_offset, + const size_t *dst_sizes, + void *dst_buf ) +{ + hid_t did; + hid_t ftype_id=-1; + hid_t mem_type_id=-1; + hid_t sid; + hsize_t dims[1]; + + /* open the dataset. */ + if ((did=H5Dopen(loc_id,dset_name))<0) + return -1; + + /* get the dataspace handle */ + if ( (sid = H5Dget_space( did )) < 0 ) + goto out; + + /* get dimensions */ + if ( H5Sget_simple_extent_dims( sid, dims, NULL) < 0 ) + goto out; + + /* get the datatypes */ + if ((ftype_id=H5Dget_type (did))<0) + goto out; + + if ((mem_type_id=H5TB_create_type(loc_id,dset_name,dst_size,dst_offset,dst_sizes,ftype_id))<0) + goto out; + + /* read */ + if ( H5Dread( did, mem_type_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, dst_buf) < 0 ) + goto out; + + /* close */ + if ( H5Tclose( ftype_id ) < 0 ) + goto out; + if ( H5Tclose( mem_type_id ) < 0 ) + goto out; + if ( H5Sclose( sid ) < 0 ) + goto out; + if ( H5Dclose( did ) < 0 ) + return -1; + + return 0; + + /* error zone, gracefully close */ +out: + H5E_BEGIN_TRY { + H5Dclose(did); + H5Tclose(mem_type_id); + H5Tclose(ftype_id); + H5Sclose(sid); + } H5E_END_TRY; + return -1; +} + +/*------------------------------------------------------------------------- + * Function: H5TBread_records + * + * Purpose: Reads records + * + * Return: Success: 0, Failure: -1 + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: November 19, 2001 + * + * Comments: + * + * Modifications: April 1, 2004 + * the DST_SIZES parameter is used to define the memory type ID + * returned by H5TB_create_type + * + *------------------------------------------------------------------------- + */ + + +herr_t H5TBread_records( hid_t loc_id, + const char *dset_name, + hsize_t start, + hsize_t nrecords, + size_t dst_size, + const size_t *dst_offset, + const size_t *dst_sizes, + void *data ) +{ + + hid_t did; + hid_t ftype_id; + hid_t mem_type_id=-1; + hsize_t count[1]; + hsize_t offset[1]; + hid_t sid=-1; + hsize_t dims[1]; + hid_t mem_space_id=-1; + hsize_t mem_size[1]; + hsize_t nrecords_orig; + hsize_t nfields; + + /* get the number of records and fields */ + if ( H5TBget_table_info ( loc_id, dset_name, &nfields, &nrecords_orig ) < 0 ) + return -1; + + /* open the dataset */ + if ( (did = H5Dopen( loc_id, dset_name )) < 0 ) + return -1; + + /* get the datatypes */ + if ( (ftype_id = H5Dget_type( did )) < 0 ) + goto out; + + if ((mem_type_id=H5TB_create_type(loc_id,dset_name,dst_size,dst_offset,dst_sizes,ftype_id))<0) + goto out; + + /* get the dataspace handle */ + if ( (sid = H5Dget_space( did )) < 0 ) + goto out; + + /* get records */ + if ( H5Sget_simple_extent_dims( sid, dims, NULL) < 0 ) + goto out; + + if ( start + nrecords > dims[0] ) + goto out; + + /* define a hyperslab in the dataset of the size of the records */ + offset[0] = start; + count[0] = nrecords; + if ( H5Sselect_hyperslab( sid, H5S_SELECT_SET, offset, NULL, count, NULL) < 0 ) + goto out; + + /* create a memory dataspace handle */ + mem_size[0] = count[0]; + if ( (mem_space_id = H5Screate_simple( 1, mem_size, NULL )) < 0 ) + goto out; + + /* read */ + if ( H5Dread( did, mem_type_id, mem_space_id, sid, H5P_DEFAULT, data ) < 0 ) + goto out; + + /* close */ + if ( H5Sclose( mem_space_id ) < 0 ) + goto out; + if ( H5Sclose( sid ) < 0 ) + goto out; + if ( H5Tclose( ftype_id ) < 0 ) + return -1; + if ( H5Tclose( mem_type_id ) < 0 ) + return -1; + if ( H5Dclose( did ) < 0 ) + return -1; + + return 0; + + /* error zone, gracefully close */ +out: + H5E_BEGIN_TRY { + H5Dclose(did); + H5Tclose(mem_type_id); + H5Tclose(ftype_id); + H5Sclose(mem_space_id); + H5Sclose(sid); + } H5E_END_TRY; + return -1; + +} + + +/*------------------------------------------------------------------------- + * Function: H5TBread_fields_name + * + * Purpose: Reads fields + * + * Return: Success: 0, Failure: -1 + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: November 19, 2001 + * + * Comments: + * + * Modifications: April 1, 2004 + * the DST_SIZES parameter is used to define the memory type ID + * returned by H5TB_create_type + * + *------------------------------------------------------------------------- + */ + + +herr_t H5TBread_fields_name( hid_t loc_id, + const char *dset_name, + const char *field_names, + hsize_t start, + hsize_t nrecords, + size_t type_size, + const size_t *field_offset, + const size_t *dst_sizes, + void *data ) +{ + + hid_t did; + hid_t ftype_id=-1; + hid_t mem_type_id=-1; + hid_t mtype_id; + hid_t nmtype_id; + char *member_name; + hssize_t nfields; + hsize_t count[1]; + hsize_t offset[1]; + hid_t sid=-1; + hid_t mem_space_id=-1; + hsize_t mem_size[1]; + size_t size_native; + hssize_t i, j; + + /* open the dataset */ + if ( (did = H5Dopen( loc_id, dset_name )) < 0 ) + goto out; + + /* get the datatype */ + if ( (ftype_id = H5Dget_type( did )) < 0 ) + goto out; + + /* get the number of fields */ + if ( ( nfields = H5Tget_nmembers( ftype_id )) < 0 ) + goto out; + + /* create a memory read id */ + if ( ( mem_type_id = H5Tcreate( H5T_COMPOUND, type_size )) < 0 ) + goto out; + + /* iterate tru the members */ + for ( i=0,j=0; i<nfields; i++) + { + /* get the member name */ + member_name = H5Tget_member_name( ftype_id, (unsigned)i ); + + if ( H5TB_find_field( member_name, field_names ) > 0 ) + { + /* get the member type */ + if ( ( mtype_id = H5Tget_member_type( ftype_id, (unsigned) i )) < 0 ) + goto out; + + /* convert to native type */ + if ((nmtype_id=H5Tget_native_type(mtype_id,H5T_DIR_DEFAULT))<0) + goto out; + + size_native=H5Tget_size(nmtype_id); + + if (dst_sizes[j]!=size_native) + { + if (H5Tset_size(nmtype_id, dst_sizes[j])<0) + goto out; + } + /* the field in the file is found by its name */ + if ( field_offset ) + { + if ( H5Tinsert( mem_type_id, member_name, field_offset[j], nmtype_id ) < 0 ) + goto out; + } + else + { + if ( H5Tinsert( mem_type_id, member_name, 0, nmtype_id ) < 0 ) + goto out; + } + + /* close */ + if ( H5Tclose( mtype_id ) < 0 ) + goto out; + if ( H5Tclose( nmtype_id ) < 0 ) + goto out; + j++; + } + free( member_name ); + } + + /* get the dataspace handle */ + if ( (sid = H5Dget_space( did )) < 0 ) + goto out; + + /* define a hyperslab in the dataset */ + offset[0] = start; + count[0] = nrecords; + if ( H5Sselect_hyperslab( sid, H5S_SELECT_SET, offset, NULL, count, NULL) < 0 ) + goto out; + + /* create a memory dataspace handle */ + mem_size[0] = count[0]; + if ( (mem_space_id = H5Screate_simple( 1, mem_size, NULL )) < 0 ) + goto out; + + /* read */ + if ( H5Dread( did, mem_type_id, mem_space_id, sid, H5P_DEFAULT, data ) < 0 ) + goto out; + + /* close */ + if ( H5Tclose( mem_type_id ) ) + goto out; + if ( H5Tclose( ftype_id ) < 0 ) + return -1; + if ( H5Sclose( sid ) < 0 ) + goto out; + if ( H5Sclose( mem_space_id ) < 0 ) + goto out; + if ( H5Dclose( did ) < 0 ) + return -1; + + return 0; + +/* error zone, gracefully close */ +out: + H5E_BEGIN_TRY { + H5Dclose(did); + H5Tclose(mem_type_id); + H5Tclose(ftype_id); + H5Sclose(mem_space_id); + H5Sclose(sid); + } H5E_END_TRY; + return -1; + +} + + +/*------------------------------------------------------------------------- + * Function: H5TBread_fields_index + * + * Purpose: Reads fields + * + * Return: Success: 0, Failure: -1 + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: November 19, 2001 + * + * Comments: + * + * Modifications: April 1, 2004 + * the DST_SIZES parameter is used to define the memory type ID + * returned by H5TB_create_type + * + *------------------------------------------------------------------------- + */ + + +herr_t H5TBread_fields_index( hid_t loc_id, + const char *dset_name, + hsize_t nfields, + const int *field_index, + hsize_t start, + hsize_t nrecords, + size_t type_size, + const size_t *field_offset, + const size_t *dst_sizes, + void *data ) +{ + + hid_t did; + hid_t tid=-1; + hid_t read_type_id=-1; + hid_t member_type_id; + hid_t nmtype_id; + char *member_name; + hsize_t count[1]; + hsize_t offset[1]; + hid_t sid=-1; + hid_t mem_space_id=-1; + hsize_t mem_size[1]; + size_t size_native; + hsize_t i, j; + + /* Open the dataset. */ + if ( (did = H5Dopen( loc_id, dset_name )) < 0 ) + goto out; + + /* Get the datatype */ + if ( (tid = H5Dget_type( did )) < 0 ) + goto out; + + /* Create a read id */ + if ( ( read_type_id = H5Tcreate( H5T_COMPOUND, type_size )) < 0 ) + goto out; + + /* Iterate tru the members */ + for ( i = 0; i < nfields; i++) + { + j = field_index[i]; + + /* Get the member name */ + member_name = H5Tget_member_name( tid, (unsigned) j ); + + /* Get the member type */ + if ( ( member_type_id = H5Tget_member_type( tid, (unsigned) j )) < 0 ) + goto out; + + /* Get the member size */ + if ( H5Tget_size( member_type_id ) == 0 ) + goto out; + + /* Convert to native type */ + if ((nmtype_id=H5Tget_native_type(member_type_id,H5T_DIR_DEFAULT))<0) + goto out; + + size_native=H5Tget_size(nmtype_id); + + if (dst_sizes[i]!=size_native) + { + if (H5Tset_size(nmtype_id, dst_sizes[i])<0) + goto out; + } + + /* The field in the file is found by its name */ + if ( field_offset ) + { + if ( H5Tinsert( read_type_id, member_name, field_offset[i], nmtype_id ) < 0 ) + goto out; + } + else + { + if ( H5Tinsert( read_type_id, member_name, 0, nmtype_id ) < 0 ) + goto out; + } + + /* Close the member type */ + if ( H5Tclose( member_type_id ) < 0 ) + goto out; + if ( H5Tclose( nmtype_id ) < 0 ) + goto out; + + free( member_name ); + } + + /* Get the dataspace handle */ + if ( (sid = H5Dget_space( did )) < 0 ) + goto out; + + /* Define a hyperslab in the dataset */ + offset[0] = start; + count[0] = nrecords; + if ( H5Sselect_hyperslab( sid, H5S_SELECT_SET, offset, NULL, count, NULL) < 0 ) + goto out; + + /* Create a memory dataspace handle */ + mem_size[0] = count[0]; + if ( (mem_space_id = H5Screate_simple( 1, mem_size, NULL )) < 0 ) + goto out; + + /* Read */ + if ( H5Dread( did, read_type_id, mem_space_id, sid, H5P_DEFAULT, data ) < 0 ) + goto out; + + /* Terminate access to the dataspace */ + if ( H5Sclose( sid ) < 0 ) + goto out; + + /* Terminate access to the memory dataspace */ + if ( H5Sclose( mem_space_id ) < 0 ) + goto out; + + /* End access to the read id */ + if ( H5Tclose( read_type_id ) ) + goto out; + + /* Release the datatype. */ + if ( H5Tclose( tid ) < 0 ) + return -1; + + /* End access to the dataset */ + if ( H5Dclose( did ) < 0 ) + return -1; + +return 0; + +/* error zone, gracefully close */ +out: + H5E_BEGIN_TRY { + H5Dclose(did); + H5Tclose(read_type_id); + H5Tclose(tid); + H5Sclose(mem_space_id); + H5Sclose(sid); + } H5E_END_TRY; + return -1; + +} + + +/*------------------------------------------------------------------------- + * + * Manipulation functions + * + *------------------------------------------------------------------------- + */ + +/*------------------------------------------------------------------------- + * Function: H5TBdelete_record + * + * Purpose: Delete records from middle of table ("pulling up" all the records after it) + * + * Return: Success: 0, Failure: -1 + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: November 26, 2001 + * + * Modifications: April 29, 2003 + * + * + *------------------------------------------------------------------------- + */ + +herr_t H5TBdelete_record( hid_t loc_id, + const char *dset_name, + hsize_t start, + hsize_t nrecords ) +{ + + hsize_t nfields; + hsize_t ntotal_records; + hsize_t read_start; + hsize_t read_nrecords; + hid_t did; + hid_t tid; + hsize_t count[1]; + hsize_t offset[1]; + hid_t sid; + hid_t mem_space_id; + hsize_t mem_size[1]; + unsigned char *tmp_buf; + size_t src_size; + size_t *src_offset; + size_t *src_sizes; + hsize_t nrows; +#if defined (SHRINK) + hsize_t dims[1]; +#endif + + +/*------------------------------------------------------------------------- + * First we get information about type size and offsets on disk + *------------------------------------------------------------------------- + */ + + /* Get the number of records and fields */ + if ( H5TBget_table_info ( loc_id, dset_name, &nfields, &ntotal_records ) < 0 ) + return -1; + + src_offset = (size_t *)malloc((size_t)nfields * sizeof(size_t)); + src_sizes = (size_t *)malloc((size_t)nfields * sizeof(size_t)); + + if ( src_offset == NULL ) + return -1; + + /* Get field info */ + if ( H5TBget_field_info( loc_id, dset_name, NULL, src_sizes, src_offset, &src_size ) < 0 ) + return -1; + +/*------------------------------------------------------------------------- + * Read the records after the deleted one(s) + *------------------------------------------------------------------------- + */ + + read_start = start + nrecords; + read_nrecords = ntotal_records - read_start; + tmp_buf = (unsigned char *)calloc((size_t) read_nrecords, src_size ); + + if ( tmp_buf == NULL ) + return -1; + + /* Read the records after the deleted one(s) */ + if ( H5TBread_records( loc_id, dset_name, read_start, read_nrecords, src_size, + src_offset, src_sizes, tmp_buf ) < 0 ) + return -1; + + +/*------------------------------------------------------------------------- + * Write the records in another position + *------------------------------------------------------------------------- + */ + + /* Open the dataset. */ + if ( (did = H5Dopen( loc_id, dset_name )) < 0 ) + return -1; + + /* Get the datatype */ + if ( (tid = H5Dget_type( did )) < 0 ) + goto out; + + /* Get the dataspace handle */ + if ( (sid = H5Dget_space( did )) < 0 ) + goto out; + + /* Define a hyperslab in the dataset of the size of the records */ + offset[0] = start; + count[0] = read_nrecords; + if ( H5Sselect_hyperslab( sid, H5S_SELECT_SET, offset, NULL, count, NULL) < 0 ) + goto out; + + /* Create a memory dataspace handle */ + mem_size[0] = count[0]; + if ( (mem_space_id = H5Screate_simple( 1, mem_size, NULL )) < 0 ) + goto out; + + if ( H5Dwrite( did, tid, mem_space_id, sid, H5P_DEFAULT, tmp_buf ) < 0 ) + goto out; + + /* Terminate access to the memory dataspace */ + if ( H5Sclose( mem_space_id ) < 0 ) + goto out; + + /* Terminate access to the dataspace */ + if ( H5Sclose( sid ) < 0 ) + goto out; + + /* Release the datatype. */ + if ( H5Tclose( tid ) < 0 ) + goto out; + + +/*------------------------------------------------------------------------- + * Change the table dimension + *------------------------------------------------------------------------- + */ +#if defined (SHRINK) + dims[0] = ntotal_records - nrecords; + if ( H5Dset_extent( did, dims ) < 0 ) + goto out; +#endif + + /* End access to the dataset */ + if ( H5Dclose( did ) < 0 ) + return -1; + + free( tmp_buf ); + free( src_offset ); + free( src_sizes ); + + +/*------------------------------------------------------------------------- + * Store the new dimension as an attribute + *------------------------------------------------------------------------- + */ + + nrows = ntotal_records - nrecords; + /* Set the attribute */ + if (H5LT_set_attribute_numerical(loc_id,dset_name,"NROWS",1, + H5T_NATIVE_LLONG,&nrows)<0) + return -1; + + + return 0; + +out: + H5Dclose( did ); + return -1; +} + +/*------------------------------------------------------------------------- + * Function: H5TBinsert_record + * + * Purpose: Inserts records into middle of table ("pushing down" all the records after it) + * + * Return: Success: 0, Failure: -1 + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: November 26, 2001 + * + * Comments: Uses memory offsets + * + * Modifications: April 1, 2004 + * the DST_SIZES parameter is used to define the memory type ID + * returned by H5TB_create_type + * + *------------------------------------------------------------------------- + */ + + +herr_t H5TBinsert_record( hid_t loc_id, + const char *dset_name, + hsize_t start, + hsize_t nrecords, + size_t dst_size, + const size_t *dst_offset, + const size_t *dst_sizes, + void *data ) +{ + + hsize_t nfields; + hsize_t ntotal_records; + hsize_t read_nrecords; + hid_t did; + hid_t tid=-1; + hid_t mem_type_id=-1; + hsize_t count[1]; + hsize_t offset[1]; + hid_t sid=-1; + hid_t mem_space_id=-1; + hsize_t dims[1]; + hsize_t mem_dims[1]; + unsigned char *tmp_buf; + +/*------------------------------------------------------------------------- + * Read the records after the inserted one(s) + *------------------------------------------------------------------------- + */ + + /* Get the dimensions */ + if ( H5TBget_table_info ( loc_id, dset_name, &nfields, &ntotal_records ) < 0 ) + return -1; + + /* Open the dataset. */ + if ( (did = H5Dopen( loc_id, dset_name )) < 0 ) + goto out; + + /* Get the datatype */ + if ( (tid = H5Dget_type( did )) < 0 ) + goto out; + + /* Create the memory data type. */ + if ((mem_type_id=H5TB_create_type(loc_id,dset_name,dst_size,dst_offset,dst_sizes,tid))<0) + goto out; + + read_nrecords = ntotal_records - start; + tmp_buf = (unsigned char *)calloc((size_t) read_nrecords, dst_size ); + + /* Read the records after the inserted one(s) */ + if ( H5TBread_records( loc_id, dset_name, start, read_nrecords, dst_size, dst_offset, + dst_sizes, tmp_buf ) < 0 ) + return -1; + + /* Extend the dataset */ + dims[0] = ntotal_records + nrecords; + + if ( H5Dextend ( did, dims ) < 0 ) + goto out; + +/*------------------------------------------------------------------------- + * Write the inserted records + *------------------------------------------------------------------------- + */ + + /* Create a simple memory data space */ + mem_dims[0]=nrecords; + if ( (mem_space_id = H5Screate_simple( 1, mem_dims, NULL )) < 0 ) + return -1; + + /* Get the file data space */ + if ( (sid = H5Dget_space( did )) < 0 ) + return -1; + + /* Define a hyperslab in the dataset to write the new data */ + offset[0] = start; + count[0] = nrecords; + if ( H5Sselect_hyperslab( sid, H5S_SELECT_SET, offset, NULL, count, NULL) < 0 ) + goto out; + + if ( H5Dwrite( did, mem_type_id, mem_space_id, sid, H5P_DEFAULT, data ) < 0 ) + goto out; + + /* Terminate access to the dataspace */ + if ( H5Sclose( mem_space_id ) < 0 ) + goto out; + if ( H5Sclose( sid ) < 0 ) + goto out; + +/*------------------------------------------------------------------------- + * Write the "pushed down" records + *------------------------------------------------------------------------- + */ + + /* Create a simple memory data space */ + mem_dims[0]=read_nrecords; + if ( (mem_space_id = H5Screate_simple( 1, mem_dims, NULL )) < 0 ) + return -1; + + /* Get the file data space */ + if ( (sid = H5Dget_space( did )) < 0 ) + return -1; + + /* Define a hyperslab in the dataset to write the new data */ + offset[0] = start + nrecords; + count[0] = read_nrecords; + if ( H5Sselect_hyperslab( sid, H5S_SELECT_SET, offset, NULL, count, NULL) < 0 ) + goto out; + + if ( H5Dwrite( did, mem_type_id, mem_space_id, sid, H5P_DEFAULT, tmp_buf ) < 0 ) + goto out; + + /* Terminate access to the dataspace */ + if ( H5Sclose( mem_space_id ) < 0 ) + goto out; + + if ( H5Sclose( sid ) < 0 ) + goto out; + + /* Release the datatype. */ + if ( H5Tclose( tid ) < 0 ) + return -1; + + /* Release the datatype. */ + if ( H5Tclose( mem_type_id ) < 0 ) + return -1; + + /* End access to the dataset */ + if ( H5Dclose( did ) < 0 ) + return -1; + + free( tmp_buf ); + + return 0; + + /* error zone, gracefully close */ +out: + H5E_BEGIN_TRY { + H5Dclose(did); + H5Sclose(sid); + H5Sclose(mem_space_id); + H5Tclose(mem_type_id); + H5Tclose(tid); + } H5E_END_TRY; + return -1; +} + +/*------------------------------------------------------------------------- + * Function: H5TBadd_records_from + * + * Purpose: Add records from first table to second table + * + * Return: Success: 0, Failure: -1 + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: December 5, 2001 + * + * Comments: + * + * Modifications: + * + * + *------------------------------------------------------------------------- + */ + +herr_t H5TBadd_records_from( hid_t loc_id, + const char *dset_name1, + hsize_t start1, + hsize_t nrecords, + const char *dset_name2, + hsize_t start2 ) +{ + + /* Identifiers for the 1st dataset. */ + hid_t dataset_id1; + hid_t type_id1; + hid_t space_id1=-1; + hid_t mem_space_id1=-1; + size_t type_size1; + + hsize_t count[1]; + hsize_t offset[1]; + hsize_t mem_size[1]; + hsize_t nfields; + hsize_t ntotal_records; + unsigned char *tmp_buf; + size_t src_size; + size_t *src_offset; + size_t *src_sizes; + +/*------------------------------------------------------------------------- + * First we get information about type size and offsets on disk + *------------------------------------------------------------------------- + */ + + /* Get the number of records and fields */ + if ( H5TBget_table_info ( loc_id, dset_name1, &nfields, &ntotal_records ) < 0 ) + return -1; + + src_offset = (size_t *)malloc((size_t)nfields * sizeof(size_t)); + src_sizes = (size_t *)malloc((size_t)nfields * sizeof(size_t)); + + if ( src_offset == NULL ) + return -1; + + /* Get field info */ + if ( H5TBget_field_info( loc_id, dset_name1, NULL, src_sizes, src_offset, &src_size ) < 0 ) + return -1; + +/*------------------------------------------------------------------------- + * Get information about the first table and read it + *------------------------------------------------------------------------- + */ + + /* Open the 1st dataset. */ + if ( (dataset_id1 = H5Dopen( loc_id, dset_name1 )) < 0 ) + return -1; + + /* Get the datatype */ + if ( (type_id1 = H5Dget_type( dataset_id1 )) < 0 ) + goto out; + + /* Get the dataspace handle */ + if ( (space_id1 = H5Dget_space( dataset_id1 )) < 0 ) + goto out; + + /* Get the size of the datatype */ + if ( ( type_size1 = H5Tget_size( type_id1 )) == 0 ) + goto out; + + tmp_buf = (unsigned char *)calloc((size_t)nrecords, type_size1 ); + + /* Define a hyperslab in the dataset of the size of the records */ + offset[0] = start1; + count[0] = nrecords; + if ( H5Sselect_hyperslab( space_id1, H5S_SELECT_SET, offset, NULL, count, NULL) < 0 ) + goto out; + + /* Create a memory dataspace handle */ + mem_size[0] = count[0]; + if ( (mem_space_id1 = H5Screate_simple( 1, mem_size, NULL )) < 0 ) + goto out; + + if ( H5Dread( dataset_id1, type_id1, mem_space_id1, space_id1, H5P_DEFAULT, tmp_buf ) < 0 ) + goto out; + +/*------------------------------------------------------------------------- + * Add to the second table + *------------------------------------------------------------------------- + */ + if ( H5TBinsert_record(loc_id,dset_name2,start2,nrecords,src_size,src_offset,src_sizes,tmp_buf ) < 0 ) + goto out; + +/*------------------------------------------------------------------------- + * Close resources for table 1 + *------------------------------------------------------------------------- + */ + + /* Terminate access to the memory dataspace */ + if ( H5Sclose( mem_space_id1 ) < 0 ) + goto out; + + /* Terminate access to the dataspace */ + if ( H5Sclose( space_id1 ) < 0 ) + goto out; + + /* Release the datatype. */ + if ( H5Tclose( type_id1 ) < 0 ) + return -1; + + /* End access to the dataset */ + if ( H5Dclose( dataset_id1 ) < 0 ) + return -1; + + free( tmp_buf ); + free( src_offset ); + free( src_sizes ); + +return 0; + + /* error zone, gracefully close */ +out: + H5E_BEGIN_TRY { + H5Dclose(dataset_id1); + H5Sclose(space_id1); + H5Sclose(mem_space_id1); + H5Tclose(type_id1); + } H5E_END_TRY; + return -1; + +} + +/*------------------------------------------------------------------------- + * Function: H5TBcombine_tables + * + * Purpose: Combine records from two tables into a third + * + * Return: Success: 0, Failure: -1 + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: December 10, 2001 + * + * Comments: + * + * Modifications: + * + * + *------------------------------------------------------------------------- + */ +herr_t H5TBcombine_tables( hid_t loc_id1, + const char *dset_name1, + hid_t loc_id2, + const char *dset_name2, + const char *dset_name3 ) +{ + + /* Identifiers for the 1st dataset. */ + hid_t dataset_id1; + hid_t type_id1; + hid_t space_id1; + hid_t plist_id1; + + /* Identifiers for the 2nd dataset. */ + hid_t dataset_id2; + hid_t type_id2; + hid_t space_id2; + hid_t plist_id2; + + /* Identifiers for the 3rd dataset. */ + hid_t dataset_id3; + hid_t type_id3; + hid_t space_id3; + hid_t plist_id3; + + hsize_t count[1]; + hsize_t offset[1]; + hid_t mem_space_id; + hsize_t mem_size[1]; + hsize_t nfields; + hsize_t nrecords; + hsize_t dims[1]; + hsize_t maxdims[1] = { H5S_UNLIMITED }; + + + size_t type_size; + hid_t sid; + hid_t member_type_id; + size_t member_offset; + char attr_name[255]; + hid_t attr_id; + char aux[255]; + unsigned char *tmp_buf; + unsigned char *tmp_fill_buf; + hsize_t i; + size_t src_size; + size_t *src_offset; + size_t *src_sizes; + int has_fill=0; + +/*------------------------------------------------------------------------- + * First we get information about type size and offsets on disk + *------------------------------------------------------------------------- + */ + + /* Get the number of records and fields */ + if ( H5TBget_table_info ( loc_id1, dset_name1, &nfields, &nrecords ) < 0 ) + return -1; + + src_offset = (size_t *)malloc((size_t)nfields * sizeof(size_t)); + src_sizes = (size_t *)malloc((size_t)nfields * sizeof(size_t)); + + + if ( src_offset == NULL ) + return -1; + + /* Get field info */ + if ( H5TBget_field_info( loc_id1, dset_name1, NULL, src_sizes, src_offset, &src_size ) < 0 ) + return -1; + +/*------------------------------------------------------------------------- + * Get information about the first table + *------------------------------------------------------------------------- + */ + + /* Open the 1st dataset. */ + if ( (dataset_id1 = H5Dopen( loc_id1, dset_name1 )) < 0 ) + goto out; + + /* Get the datatype */ + if ( (type_id1 = H5Dget_type( dataset_id1 )) < 0 ) + goto out; + + /* Get the dataspace handle */ + if ( (space_id1 = H5Dget_space( dataset_id1 )) < 0 ) + goto out; + + /* Get creation properties list */ + if ( (plist_id1 = H5Dget_create_plist( dataset_id1 )) < 0 ) + goto out; + + /* Get the dimensions */ + if ( H5TBget_table_info ( loc_id1, dset_name1, &nfields, &nrecords ) < 0 ) + return -1; + +/*------------------------------------------------------------------------- + * Make the merged table with no data originally + *------------------------------------------------------------------------- + */ + + /* Clone the property list */ + if ( ( plist_id3 = H5Pcopy( plist_id1 )) < 0 ) + goto out; + + /* Clone the type id */ + if ( ( type_id3 = H5Tcopy( type_id1 )) < 0 ) + goto out; + +/*------------------------------------------------------------------------- + * Here we do not clone the file space from the 1st dataset, because we want to create + * an empty table. Instead we create a new dataspace with zero records and expandable. + *------------------------------------------------------------------------- + */ + dims[0] = 0; + +/* Create a simple data space with unlimited size */ + if ( (space_id3 = H5Screate_simple( 1, dims, maxdims )) < 0 ) + return -1; + + /* Create the dataset */ + if ( (dataset_id3 = H5Dcreate( loc_id1, dset_name3, type_id3, space_id3, plist_id3 )) < 0 ) + goto out; + +/*------------------------------------------------------------------------- + * Attach the conforming table attributes + *------------------------------------------------------------------------- + */ + if ( H5TB_attach_attributes( "Merge table", loc_id1, dset_name3, nfields, type_id3 ) < 0 ) + goto out; + +/*------------------------------------------------------------------------- + * Get attributes + *------------------------------------------------------------------------- + */ + + type_size = H5Tget_size( type_id3 ); + + /* alloc fill value attribute buffer */ + tmp_fill_buf = (unsigned char *)malloc((size_t) type_size ); + + /* Get the fill value attributes */ + has_fill=H5TBAget_fill( loc_id1, dset_name1, dataset_id1, tmp_fill_buf ); + +/*------------------------------------------------------------------------- + * Attach the fill attributes from previous table + *------------------------------------------------------------------------- + */ + if ( has_fill == 1 ) + { + + if (( sid = H5Screate(H5S_SCALAR)) < 0 ) + goto out; + + for ( i = 0; i < nfields; i++) + { + + /* Get the member type */ + if ( ( member_type_id = H5Tget_member_type( type_id3, (unsigned) i )) < 0 ) + goto out; + + /* Get the member offset */ + member_offset = H5Tget_member_offset( type_id3, (unsigned) i ); + + strcpy( attr_name, "FIELD_" ); + sprintf( aux, "%d", (int) i ); + strcat( attr_name, aux ); + sprintf( aux, "%s", "_FILL" ); + strcat( attr_name, aux ); + + if ( (attr_id = H5Acreate( dataset_id3, attr_name, member_type_id, sid, H5P_DEFAULT )) < 0 ) + goto out; + + if ( H5Awrite( attr_id, member_type_id, tmp_fill_buf+member_offset ) < 0 ) + goto out; + + if ( H5Aclose( attr_id ) < 0 ) + goto out; + + if ( H5Tclose( member_type_id ) < 0 ) + goto out; + } + + /* Close data space. */ + if ( H5Sclose( sid ) < 0 ) + goto out; + } + +/*------------------------------------------------------------------------- + * Read data from 1st table + *------------------------------------------------------------------------- + */ + + tmp_buf = (unsigned char *)calloc((size_t) nrecords, type_size ); + + /* Define a hyperslab in the dataset of the size of the records */ + offset[0] = 0; + count[0] = nrecords; + if ( H5Sselect_hyperslab( space_id1, H5S_SELECT_SET, offset, NULL, count, NULL) < 0 ) + goto out; + + /* Create a memory dataspace handle */ + mem_size[0] = count[0]; + if ( (mem_space_id = H5Screate_simple( 1, mem_size, NULL )) < 0 ) + goto out; + + if ( H5Dread( dataset_id1, type_id1, mem_space_id, space_id1, H5P_DEFAULT, tmp_buf ) < 0 ) + goto out; + +/*------------------------------------------------------------------------- + * Save data from 1st table into new table + *------------------------------------------------------------------------- + */ + + /* Append the records to the new table */ + if ( H5TBappend_records( loc_id1, dset_name3, nrecords, src_size, src_offset, src_sizes, tmp_buf ) < 0 ) + goto out; + +/*------------------------------------------------------------------------- + * Release resources from 1st table + *------------------------------------------------------------------------- + */ + + /* Terminate access to the memory dataspace */ + if ( H5Sclose( mem_space_id ) < 0 ) + goto out; + + /* Terminate access to the dataspace */ + if ( H5Sclose( space_id1 ) < 0 ) + goto out; + + /* Release the datatype. */ + if ( H5Tclose( type_id1 ) < 0 ) + goto out; + + /* Terminate access to a property list */ + if ( H5Pclose( plist_id1 ) < 0 ) + goto out; + + /* End access to the dataset */ + if ( H5Dclose( dataset_id1 ) < 0 ) + goto out; + + /* Release resources. */ + free( tmp_buf ); + +/*------------------------------------------------------------------------- + * Get information about the 2nd table + *------------------------------------------------------------------------- + */ + + /* Open the dataset. */ + if ( (dataset_id2 = H5Dopen( loc_id2, dset_name2 )) < 0 ) + goto out; + + /* Get the datatype */ + if ( (type_id2 = H5Dget_type( dataset_id2 )) < 0 ) + goto out; + + /* Get the dataspace handle */ + if ( (space_id2 = H5Dget_space( dataset_id2 )) < 0 ) + goto out; + + /* Get the property list handle */ + if ( (plist_id2 = H5Dget_create_plist( dataset_id2 )) < 0 ) + goto out; + + /* Get the dimensions */ + if ( H5TBget_table_info ( loc_id2, dset_name2, &nfields, &nrecords ) < 0 ) + return -1; + +/*------------------------------------------------------------------------- + * Read data from 2nd table + *------------------------------------------------------------------------- + */ + + tmp_buf = (unsigned char *)calloc((size_t) nrecords, type_size ); + + /* Define a hyperslab in the dataset of the size of the records */ + offset[0] = 0; + count[0] = nrecords; + if ( H5Sselect_hyperslab( space_id2, H5S_SELECT_SET, offset, NULL, count, NULL) < 0 ) + goto out; + + /* Create a memory dataspace handle */ + mem_size[0] = count[0]; + if ( (mem_space_id = H5Screate_simple( 1, mem_size, NULL )) < 0 ) + goto out; + + if ( H5Dread( dataset_id2, type_id2, mem_space_id, space_id2, H5P_DEFAULT, tmp_buf ) < 0 ) + goto out; + + +/*------------------------------------------------------------------------- + * Save data from 2nd table into new table + *------------------------------------------------------------------------- + */ + + /* append the records to the new table */ + if ( H5TBappend_records( loc_id1, dset_name3, nrecords, src_size, src_offset, src_sizes, tmp_buf ) < 0 ) + goto out; + +/*------------------------------------------------------------------------- + * Release resources from 2nd table + *------------------------------------------------------------------------- + */ + + /* Terminate access to the memory dataspace */ + if ( H5Sclose( mem_space_id ) < 0 ) + goto out; + + /* Terminate access to the dataspace */ + if ( H5Sclose( space_id2 ) < 0 ) + goto out; + + /* Release the datatype. */ + if ( H5Tclose( type_id2 ) < 0 ) + return -1; + + /* Terminate access to a property list */ + if ( H5Pclose( plist_id2 ) < 0 ) + goto out; + + /* End access to the dataset */ + if ( H5Dclose( dataset_id2 ) < 0 ) + return -1; + +/*------------------------------------------------------------------------- + * Release resources from 3rd table + *------------------------------------------------------------------------- + */ + + /* Terminate access to the dataspace */ + if ( H5Sclose( space_id3 ) < 0 ) + return -1; + + /* Release the datatype. */ + if ( H5Tclose( type_id3 ) < 0 ) + return -1; + + /* Terminate access to a property list */ + if ( H5Pclose( plist_id3 ) < 0 ) + return -1; + + /* End access to the dataset */ + if ( H5Dclose( dataset_id3 ) < 0 ) + return -1; + + /* Release resources. */ + free( tmp_buf ); + free( tmp_fill_buf ); + free( src_offset ); + free( src_sizes ); + +return 0; + +out: + H5Dclose( dataset_id1 ); + return -1; + +} + + + +/*------------------------------------------------------------------------- + * Function: H5TBinsert_field + * + * Purpose: Inserts a field + * + * Return: Success: 0, Failure: -1 + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: January 30, 2002 + * + * Comments: + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +herr_t H5TBinsert_field( hid_t loc_id, + const char *dset_name, + const char *field_name, + hid_t field_type, + hsize_t position, + const void *fill_data, + const void *data ) +{ + + /* Identifiers for the 1st, original dataset */ + hid_t dataset_id1; + hid_t type_id1; + hid_t space_id1; + hid_t plist_id1; + hid_t mem_space_id1; + + /* Identifiers for the 2nd, new dataset */ + hid_t dataset_id2; + hid_t type_id2; + hid_t space_id2; + hid_t plist_id2; + hid_t mem_space_id2; + + hid_t member_type_id; + size_t member_size; + size_t new_member_size = 0; + char *member_name; + size_t total_size; + hsize_t nfields; + hsize_t nrecords; + hsize_t dims_chunk[1]; + hsize_t dims[1]; + hsize_t maxdims[1] = { H5S_UNLIMITED }; + hsize_t count[1]; + hsize_t offset[1]; + hsize_t mem_size[1]; + hid_t write_type_id; + hid_t PRESERVE; + size_t curr_offset; + int inserted; + hsize_t idx; + char table_title[255]; + size_t member_offset; + char attr_name[255]; + hid_t attr_id; + char aux[255]; + unsigned char *tmp_buf; + unsigned char *tmp_fill_buf; + hsize_t i; + + /* Get the number of records and fields */ + if ( H5TBget_table_info ( loc_id, dset_name, &nfields, &nrecords ) < 0 ) + return -1; + +/*------------------------------------------------------------------------- + * Get information about the old data type + *------------------------------------------------------------------------- + */ + + /* Open the dataset. */ + if ( (dataset_id1 = H5Dopen( loc_id, dset_name )) < 0 ) + return -1; + + /* Get creation properties list */ + if ( (plist_id1 = H5Dget_create_plist( dataset_id1 )) < 0 ) + goto out; + + /* Get the datatype */ + if ( (type_id1 = H5Dget_type( dataset_id1 )) < 0 ) + goto out; + + /* Get the size of the datatype */ + if ( ( total_size = H5Tget_size( type_id1 )) == 0 ) + goto out; + + /* Get the dataspace handle */ + if ( (space_id1 = H5Dget_space( dataset_id1 )) < 0 ) + goto out; + + /* Get dimension */ + if ( H5Sget_simple_extent_dims( space_id1, dims, NULL) < 0 ) + goto out; + +/*------------------------------------------------------------------------- + * Get attributes + *------------------------------------------------------------------------- + */ + + /* Get the table title */ + if ( (H5TBAget_title( dataset_id1, table_title )) < 0 ) + goto out; + + /* alloc fill value attribute buffer */ + tmp_fill_buf = (unsigned char *)malloc(total_size ); + + /* Get the fill value attributes */ + if ( (H5TBAget_fill( loc_id, dset_name, dataset_id1, tmp_fill_buf )) < 0 ) + goto out; + +/*------------------------------------------------------------------------- + * Create a new data type + *------------------------------------------------------------------------- + */ + + /* Get the new member size */ + member_size = H5Tget_size( field_type ); + + /* Create the data type. */ + if (( type_id2 = H5Tcreate (H5T_COMPOUND,(size_t)(total_size + member_size) )) < 0 ) + goto out; + + curr_offset = 0; + inserted = 0; + + /* Insert the old fields, counting with the new one */ + for ( i = 0; i < nfields + 1; i++) + { + + idx = i; + if ( inserted ) + idx = i - 1; + + if ( i == position ) + { + + /* Get the new member size */ + new_member_size = H5Tget_size( field_type ); + + /* Insert the new field type */ + if ( H5Tinsert( type_id2, field_name, curr_offset, field_type ) < 0 ) + goto out; + + curr_offset += new_member_size; + + inserted = 1; + + continue; + + } + + /* Get the member name */ + member_name = H5Tget_member_name( type_id1, (unsigned)idx ); + + /* Get the member type */ + if ( ( member_type_id = H5Tget_member_type( type_id1,(unsigned)idx )) < 0 ) + goto out; + + /* Get the member size */ + member_size = H5Tget_size( member_type_id ); + + /* Insert it into the new type */ + if ( H5Tinsert( type_id2, member_name, curr_offset, member_type_id ) < 0 ) + goto out; + + curr_offset += member_size; + + free( member_name ); + + /* Close the member type */ + if ( H5Tclose( member_type_id ) < 0 ) + goto out; + + + } /* i */ + +/*------------------------------------------------------------------------- + * Create a new temporary dataset + *------------------------------------------------------------------------- + */ + + /* Retrieve the size of chunk */ + if ( H5Pget_chunk( plist_id1, 1, dims_chunk ) < 0 ) + goto out; + + /* Create a new simple data space with unlimited size, using the dimension */ + if ( ( space_id2 = H5Screate_simple( 1, dims, maxdims )) < 0 ) + return -1; + + /* Modify dataset creation properties, i.e. enable chunking */ + plist_id2 = H5Pcreate (H5P_DATASET_CREATE); + if ( H5Pset_chunk ( plist_id2, 1, dims_chunk ) < 0 ) + return -1; + + /* Create the dataset. */ + if ( ( dataset_id2 = H5Dcreate( loc_id, "new", type_id2, space_id2, plist_id2 )) < 0 ) + goto out; + + +/*------------------------------------------------------------------------- + * Read data from 1st table + *------------------------------------------------------------------------- + */ + + tmp_buf = (unsigned char *)calloc((size_t) nrecords, (size_t)total_size ); + + /* Define a hyperslab in the dataset of the size of the records */ + offset[0] = 0; + count[0] = nrecords; + if ( H5Sselect_hyperslab( space_id1, H5S_SELECT_SET, offset, NULL, count, NULL) < 0 ) + goto out; + + /* Create a memory dataspace handle */ + mem_size[0] = count[0]; + if ( (mem_space_id1 = H5Screate_simple( 1, mem_size, NULL )) < 0 ) + goto out; + + if ( H5Dread( dataset_id1, type_id1, mem_space_id1, H5S_ALL, H5P_DEFAULT, tmp_buf ) < 0 ) + goto out; + + +/*------------------------------------------------------------------------- + * Save data from 1st table into new table, using the 1st type id + *------------------------------------------------------------------------- + */ + + /* Write */ + if ( H5Dwrite( dataset_id2, type_id1, mem_space_id1, H5S_ALL, H5P_DEFAULT, tmp_buf ) < 0 ) + goto out; + + +/*------------------------------------------------------------------------- + * Save the function supplied data of the new field + *------------------------------------------------------------------------- + */ + + + /* Create a write id */ + if ( ( write_type_id = H5Tcreate( H5T_COMPOUND, (size_t)new_member_size )) < 0 ) + goto out; + + /* The field in the file is found by its name */ + if ( H5Tinsert( write_type_id, field_name, 0, field_type ) < 0 ) + goto out; + + /* Create xfer properties to preserve initialized data */ + if ((PRESERVE = H5Pcreate (H5P_DATASET_XFER))<0) + goto out; + if (H5Pset_preserve (PRESERVE, 1)<0) + goto out; + + /* Only write if there is something to write */ + if ( data ) + { + + /* Create a memory dataspace handle */ + if ( (mem_space_id2 = H5Screate_simple( 1, mem_size, NULL )) < 0 ) + goto out; + + /* Write */ + if ( H5Dwrite( dataset_id2, write_type_id, mem_space_id2, space_id2, PRESERVE, data ) < 0 ) + goto out; + + /* Terminate access to the memory dataspace */ + if ( H5Sclose( mem_space_id2 ) < 0 ) + goto out; + } + + /* End access to the property list */ + if ( H5Pclose( PRESERVE ) < 0 ) + goto out; + + + +/*------------------------------------------------------------------------- + * Release resources from 1st table + *------------------------------------------------------------------------- + */ + + /* Terminate access to the memory dataspace */ + if ( H5Sclose( mem_space_id1 ) < 0 ) + goto out; + + /* Release the datatype. */ + if ( H5Tclose( type_id1 ) < 0 ) + goto out; + + /* Terminate access to a property list */ + if ( H5Pclose( plist_id1 ) < 0 ) + goto out; + + /* Terminate access to the data space */ + if ( H5Sclose( space_id1 ) < 0 ) + goto out; + + /* End access to the dataset */ + if ( H5Dclose( dataset_id1 ) < 0 ) + goto out; + + +/*------------------------------------------------------------------------- + * Release resources from 2nd table + *------------------------------------------------------------------------- + */ + + /* Terminate access to the dataspace */ + if ( H5Sclose( space_id2 ) < 0 ) + goto out; + + /* Release the datatype. */ + if ( H5Tclose( type_id2 ) < 0 ) + return -1; + + /* Terminate access to a property list */ + if ( H5Pclose( plist_id2 ) < 0 ) + goto out; + + /* End access to the dataset */ + if ( H5Dclose( dataset_id2 ) < 0 ) + return -1; +/*------------------------------------------------------------------------- + * Delete 1st table + *------------------------------------------------------------------------- + */ + if ( H5Gunlink( loc_id, dset_name ) < 0 ) + return -1; + +/*------------------------------------------------------------------------- + * Rename 2nd table + *------------------------------------------------------------------------- + */ + + if ( H5Gmove( loc_id, "new", dset_name ) < 0 ) + return -1; + +/*------------------------------------------------------------------------- + * Attach the conforming table attributes + *------------------------------------------------------------------------- + */ + + /* Get the number of records and fields */ + if ( H5TBget_table_info ( loc_id, dset_name, &nfields, &nrecords ) < 0 ) + return -1; + + /* Open the dataset. */ + if ( (dataset_id1 = H5Dopen( loc_id, dset_name )) < 0 ) + return -1; + + /* Get the datatype */ + if ( (type_id1 = H5Dget_type( dataset_id1 )) < 0 ) + goto out; + + /* Set the attributes */ + if ( H5TB_attach_attributes( table_title, loc_id, dset_name,(hsize_t) nfields, type_id1 ) < 0 ) + return -1; +/*------------------------------------------------------------------------- + * Attach the fill attributes from previous table + *------------------------------------------------------------------------- + */ + + if (( space_id1 = H5Screate(H5S_SCALAR)) < 0 ) + goto out; + + for ( i = 0; i < nfields-1; i++) + { + /* Get the member type */ + if ( ( member_type_id = H5Tget_member_type( type_id1, (unsigned) i )) < 0 ) + goto out; + + /* Get the member offset */ + member_offset = H5Tget_member_offset( type_id1, (unsigned) i ); + + strcpy( attr_name, "FIELD_" ); + sprintf( aux, "%d", (int)i ); + strcat( attr_name, aux ); + sprintf( aux, "%s", "_FILL" ); + strcat( attr_name, aux ); + + if ( (attr_id = H5Acreate( dataset_id1, attr_name, member_type_id, space_id1, H5P_DEFAULT )) < 0 ) + goto out; + + if ( H5Awrite( attr_id, member_type_id, tmp_fill_buf+member_offset ) < 0 ) + goto out; + + if ( H5Aclose( attr_id ) < 0 ) + goto out; + + /* Close the member type */ + if ( H5Tclose( member_type_id ) < 0 ) + goto out; + } + +/*------------------------------------------------------------------------- + * Attach the fill attribute from the new field, if present + *------------------------------------------------------------------------- + */ + if ( fill_data ) + { + + strcpy( attr_name, "FIELD_" ); + sprintf( aux, "%d",(int)( nfields-1) ); + strcat( attr_name, aux ); + sprintf( aux, "%s", "_FILL" ); + strcat( attr_name, aux ); + + /* Get the member type */ + if ( ( member_type_id = H5Tget_member_type( type_id1, (unsigned)nfields-1 )) < 0 ) + goto out; + + if ( (attr_id = H5Acreate( dataset_id1, attr_name, member_type_id, space_id1, H5P_DEFAULT )) < 0 ) + goto out; + + if ( H5Awrite( attr_id, member_type_id, fill_data ) < 0 ) + goto out; + + if ( H5Aclose( attr_id ) < 0 ) + goto out; + + if ( H5Tclose( member_type_id ) < 0 ) + goto out; + + } + + /* Close data space. */ + if ( H5Sclose( space_id1 ) < 0 ) + goto out; + + /* Release the datatype. */ + if ( H5Tclose( type_id1 ) < 0 ) + goto out; + + /* End access to the dataset */ + if ( H5Dclose( dataset_id1 ) < 0 ) + goto out; + + /* Release resources. */ + free ( tmp_buf ); + free ( tmp_fill_buf ); + + +return 0; + +out: + H5Dclose( dataset_id1 ); + return -1; +} + +/*------------------------------------------------------------------------- + * Function: H5TBdelete_field + * + * Purpose: Deletes a field + * + * Return: Success: 0, Failure: -1 + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: January 30, 2002 + * + * Comments: + * + * Modifications: + * + * + *------------------------------------------------------------------------- + */ + +herr_t H5TBdelete_field( hid_t loc_id, + const char *dset_name, + const char *field_name ) +{ + + /* Identifiers for the 1st original dataset */ + hid_t dataset_id1; + hid_t type_id1; + hid_t space_id1; + hid_t plist_id1; + + /* Identifiers for the 2nd new dataset */ + hid_t dataset_id2; + hid_t type_id2; + hid_t space_id2; + hid_t plist_id2; + + hid_t member_type_id; + size_t member_size; + char *member_name; + size_t type_size1; + size_t type_size2; + hsize_t nfields; + hsize_t nrecords; + hsize_t dims_chunk[1]; + hsize_t dims[1]; + hsize_t maxdims[1] = { H5S_UNLIMITED }; + hid_t PRESERVE; + size_t curr_offset; + size_t delete_member_size = 0; + hid_t read_type_id; + hid_t write_type_id; + unsigned char *tmp_buf; + unsigned char *tmp_fill_buf; + char attr_name[255]; + char aux[255]; + char table_title[255]; + size_t member_offset; + hid_t attr_id; + hsize_t i; + int has_fill=0; + + /* Get the number of records and fields */ + if ( H5TBget_table_info ( loc_id, dset_name, &nfields, &nrecords ) < 0 ) + return -1; + +/*------------------------------------------------------------------------- + * Get information about the old data type + *------------------------------------------------------------------------- + */ + + /* Open the dataset. */ + if ( (dataset_id1 = H5Dopen( loc_id, dset_name )) < 0 ) + return -1; + + /* Get creation properties list */ + if ( (plist_id1 = H5Dget_create_plist( dataset_id1 )) < 0 ) + goto out; + + /* Get the datatype */ + if ( (type_id1 = H5Dget_type( dataset_id1 )) < 0 ) + goto out; + + /* Get the size of the datatype */ + type_size1 = H5Tget_size( type_id1 ); + + /* Get the dataspace handle */ + if ( (space_id1 = H5Dget_space( dataset_id1 )) < 0 ) + goto out; + + /* Get dimension */ + if ( H5Sget_simple_extent_dims( space_id1, dims, NULL) < 0 ) + goto out; + +/*------------------------------------------------------------------------- + * Create a new data type; first we find the size of the datatype to delete + *------------------------------------------------------------------------- + */ + + /* Check out the field */ + for ( i = 0; i < nfields; i++) + { + + /* Get the member name */ + member_name = H5Tget_member_name( type_id1,(unsigned) i ); + + /* We want to find the field to delete */ + if ( H5TB_find_field( member_name, field_name ) > 0 ) + { + /* Get the member type */ + if ( ( member_type_id = H5Tget_member_type( type_id1,(unsigned) i )) < 0 ) + goto out; + + /* Get the member size */ + delete_member_size = H5Tget_size( member_type_id ); + + /* Close the member type */ + if ( H5Tclose( member_type_id ) < 0 ) + goto out; + + free( member_name ); + + break; + + } + + free( member_name ); + + } /* i */ + + /* No field to delete was found */ + if ( delete_member_size == 0 ) + goto out; + +/*------------------------------------------------------------------------- + * Create a new data type; we now insert all the fields into the new type + *------------------------------------------------------------------------- + */ + + type_size2 = type_size1 - delete_member_size; + + /* Create the data type. */ + if (( type_id2 = H5Tcreate (H5T_COMPOUND, type_size2 )) < 0 ) + goto out; + + curr_offset = 0; + + /* alloc fill value attribute buffer */ + tmp_fill_buf = (unsigned char *)malloc((size_t) type_size2 ); + +/*------------------------------------------------------------------------- + * Get attributes from previous table in the process + *------------------------------------------------------------------------- + */ + + /* Get the table title */ + if ( (H5TBAget_title( dataset_id1, table_title )) < 0 ) + goto out; + + /* Insert the old fields except the one to delete */ + for ( i = 0; i < nfields; i++) + { + + /* Get the member name */ + member_name = H5Tget_member_name( type_id1, (unsigned) i ); + + /* We want to skip the field to delete */ + if ( H5TB_find_field( member_name, field_name ) > 0 ) + { + free( member_name ); + continue; + } + + /* Get the member type */ + if ( ( member_type_id = H5Tget_member_type( type_id1, (unsigned)i )) < 0 ) + goto out; + + /* Get the member size */ + member_size = H5Tget_size( member_type_id ); + + /* Insert it into the new type */ + if ( H5Tinsert( type_id2, member_name, curr_offset, member_type_id ) < 0 ) + goto out; + + /*------------------------------------------------------------------------- + * Get the fill value information + *------------------------------------------------------------------------- + */ + + strcpy( attr_name, "FIELD_" ); + sprintf( aux, "%d", (int)i ); + strcat( attr_name, aux ); + sprintf( aux, "%s", "_FILL" ); + strcat( attr_name, aux ); + + /* Check if we have the _FILL attribute */ + has_fill = H5LT_find_attribute( dataset_id1, attr_name ); + + /* Get it */ + if ( has_fill == 1 ) + { + if ( H5LT_get_attribute_disk( dataset_id1, attr_name, tmp_fill_buf+curr_offset ) < 0 ) + goto out; + } + + curr_offset += member_size; + + free( member_name ); + + /* Close the member type */ + if ( H5Tclose( member_type_id ) < 0 ) + goto out; + + } /* i */ + +/*------------------------------------------------------------------------- + * Create a new temporary dataset + *------------------------------------------------------------------------- + */ + + /* Retrieve the size of chunk */ + if ( H5Pget_chunk( plist_id1, 1, dims_chunk ) < 0 ) + goto out; + + /* Create a new simple data space with unlimited size, using the dimension */ + if ( ( space_id2 = H5Screate_simple( 1, dims, maxdims )) < 0 ) + return -1; + + /* Modify dataset creation properties, i.e. enable chunking */ + plist_id2 = H5Pcreate (H5P_DATASET_CREATE); + if ( H5Pset_chunk ( plist_id2, 1, dims_chunk ) < 0 ) + return -1; + + /* Create the dataset. */ + if ( ( dataset_id2 = H5Dcreate( loc_id, "new", type_id2, space_id2, plist_id2 )) < 0 ) + goto out; + +/*------------------------------------------------------------------------- + * We have to read field by field of the old dataset and save it into the new one + *------------------------------------------------------------------------- + */ + for ( i = 0; i < nfields; i++) + { + + /* Get the member name */ + member_name = H5Tget_member_name( type_id1,(unsigned) i ); + + /* Skip the field to delete */ + if ( H5TB_find_field( member_name, field_name ) > 0 ) + { + free( member_name ); + continue; + } + + /* Get the member type */ + if ( ( member_type_id = H5Tget_member_type( type_id1, (unsigned)i )) < 0 ) + goto out; + + /* Get the member size */ + member_size = H5Tget_size( member_type_id ); + + /* Create a read id */ + if ( ( read_type_id = H5Tcreate( H5T_COMPOUND, member_size )) < 0 ) + goto out; + + /* Insert it into the new type */ + if ( H5Tinsert( read_type_id, member_name, 0, member_type_id ) < 0 ) + goto out; + + tmp_buf = (unsigned char *)calloc((size_t) nrecords, member_size ); + + /* Read */ + if ( H5Dread( dataset_id1, read_type_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, tmp_buf ) < 0 ) + goto out; + + /* Create a write id */ + if ( ( write_type_id = H5Tcreate( H5T_COMPOUND, member_size )) < 0 ) + goto out; + + /* The field in the file is found by its name */ + if ( H5Tinsert( write_type_id, member_name, 0, member_type_id ) < 0 ) + goto out; + + /* Create xfer properties to preserve initialized data */ + if ((PRESERVE = H5Pcreate (H5P_DATASET_XFER))<0) + goto out; + if (H5Pset_preserve (PRESERVE, 1)<0) + goto out; + + /* Write */ + if ( H5Dwrite( dataset_id2, write_type_id, H5S_ALL, H5S_ALL, PRESERVE, tmp_buf ) < 0 ) + goto out; + + /* End access to the property list */ + if ( H5Pclose( PRESERVE ) < 0 ) + goto out; + + /* Close the member type */ + if ( H5Tclose( member_type_id ) < 0 ) + goto out; + + /* Close the read type */ + if ( H5Tclose( read_type_id ) < 0 ) + goto out; + + /* Close the write type */ + if ( H5Tclose( write_type_id ) < 0 ) + goto out; + + /* Release resources. */ + free( member_name ); + free ( tmp_buf ); + + } /* i */ + +/*------------------------------------------------------------------------- + * Release resources from 1st table + *------------------------------------------------------------------------- + */ + + /* Release the datatype. */ + if ( H5Tclose( type_id1 ) < 0 ) + goto out; + + /* Terminate access to a property list */ + if ( H5Pclose( plist_id1 ) < 0 ) + goto out; + + /* Terminate access to the data space */ + if ( H5Sclose( space_id1 ) < 0 ) + goto out; + + /* End access to the dataset */ + if ( H5Dclose( dataset_id1 ) < 0 ) + goto out; + + +/*------------------------------------------------------------------------- + * Release resources from 2nd table + *------------------------------------------------------------------------- + */ + + /* Terminate access to the dataspace */ + if ( H5Sclose( space_id2 ) < 0 ) + goto out; + + /* Release the datatype. */ + if ( H5Tclose( type_id2 ) < 0 ) + return -1; + + /* Terminate access to a property list */ + if ( H5Pclose( plist_id2 ) < 0 ) + goto out; + + /* End access to the dataset */ + if ( H5Dclose( dataset_id2 ) < 0 ) + return -1; + +/*------------------------------------------------------------------------- + * Delete 1st table + *------------------------------------------------------------------------- + */ + + if ( H5Gunlink( loc_id, dset_name ) < 0 ) + return -1; + +/*------------------------------------------------------------------------- + * Rename 2nd table + *------------------------------------------------------------------------- + */ + + if ( H5Gmove( loc_id, "new", dset_name ) < 0 ) + return -1; + +/*------------------------------------------------------------------------- + * Attach the conforming table attributes + *------------------------------------------------------------------------- + */ + + /* Get the number of records and fields */ + if ( H5TBget_table_info ( loc_id, dset_name, &nfields, &nrecords ) < 0 ) + return -1; + + /* Open the dataset. */ + if ( (dataset_id1 = H5Dopen( loc_id, dset_name )) < 0 ) + return -1; + + /* Get the datatype */ + if ( (type_id1 = H5Dget_type( dataset_id1 )) < 0 ) + goto out; + + /* Set the attributes */ + if ( H5TB_attach_attributes( table_title, loc_id, dset_name, nfields, type_id1 ) < 0 ) + return -1; + +/*------------------------------------------------------------------------- + * Attach the fill attributes from previous table + *------------------------------------------------------------------------- + */ + + if ( has_fill == 1 ) + { + + if (( space_id1 = H5Screate(H5S_SCALAR)) < 0 ) + goto out; + + for ( i = 0; i < nfields; i++) + { + + /* Get the member type */ + if ( ( member_type_id = H5Tget_member_type( type_id1, (unsigned)i )) < 0 ) + goto out; + + /* Get the member offset */ + member_offset = H5Tget_member_offset( type_id1, (unsigned)i ); + + strcpy( attr_name, "FIELD_" ); + sprintf( aux, "%d", (int)i ); + strcat( attr_name, aux ); + sprintf( aux, "%s", "_FILL" ); + strcat( attr_name, aux ); + + if ( (attr_id = H5Acreate( dataset_id1, attr_name, member_type_id, space_id1, H5P_DEFAULT )) < 0 ) + goto out; + + if ( H5Awrite( attr_id, member_type_id, tmp_fill_buf+member_offset ) < 0 ) + goto out; + + if ( H5Aclose( attr_id ) < 0 ) + goto out; + + /* Close the member type */ + if ( H5Tclose( member_type_id ) < 0 ) + goto out; + + } + + /* Close data space. */ + if ( H5Sclose( space_id1 ) < 0 ) + goto out; + + } /*has_fill*/ + + /* Release the datatype. */ + if ( H5Tclose( type_id1 ) < 0 ) + goto out; + + /* End access to the dataset */ + if ( H5Dclose( dataset_id1 ) < 0 ) + goto out; + + /* Release resources. */ + free ( tmp_fill_buf ); + +return 0; + +out: + H5Dclose( dataset_id1 ); + return -1; +} + +/*------------------------------------------------------------------------- + * + * Table attribute functions + * + *------------------------------------------------------------------------- + */ + +/*------------------------------------------------------------------------- + * Function: H5TBAget_title + * + * Purpose: Read the table title + * + * Return: Success: 0, Failure: -1 + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: January 30, 2001 + * + * Comments: + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +herr_t H5TBAget_title( hid_t loc_id, + char *table_title ) +{ + + /* Get the TITLE attribute */ + if ( H5LT_get_attribute_disk( loc_id, "TITLE", table_title ) < 0 ) + return -1; + + + return 0; + +} + +/*------------------------------------------------------------------------- + * Function: H5TBAget_fill + * + * Purpose: Read the table attribute fill values + * + * Return: Success: 0, Failure: -1 + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: January 30, 2002 + * + * Comments: + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + + +herr_t H5TBAget_fill( hid_t loc_id, + const char *dset_name, + hid_t dset_id, + unsigned char *dst_buf ) +{ + + hsize_t nfields; + hsize_t nrecords; + char attr_name[255]; + char aux[255]; + hsize_t i; + size_t *src_offset; + int has_fill=0; + + /* Get the number of records and fields */ + if ( H5TBget_table_info ( loc_id, dset_name, &nfields, &nrecords ) < 0 ) + return -1; + + src_offset = (size_t *)malloc((size_t)nfields * sizeof(size_t)); + + if (src_offset == NULL ) + return -1; + + /* Get field info */ + if ( H5TBget_field_info( loc_id, dset_name, NULL, NULL, src_offset, NULL ) < 0 ) + goto out; + + for ( i = 0; i < nfields; i++) + { + strcpy( attr_name, "FIELD_" ); + sprintf( aux, "%d", (int)i ); + strcat( attr_name, aux ); + sprintf( aux, "%s", "_FILL" ); + strcat( attr_name, aux ); + + /* Check if we have the _FILL attribute */ + has_fill = H5LT_find_attribute( dset_id, attr_name ); + + /* Get it */ + if ( has_fill == 1 ) + { + if ( H5LT_get_attribute_disk( dset_id, attr_name, dst_buf+src_offset[i] ) < 0 ) + goto out; + } + + } + + free( src_offset ); + + return has_fill; + +out: + free( src_offset ); + return -1; + +} + + +/*------------------------------------------------------------------------- + * + * Inquiry functions + * + *------------------------------------------------------------------------- + */ + +/*------------------------------------------------------------------------- + * Function: H5TBget_table_info + * + * Purpose: Gets the number of records and fields of a table + * + * Return: Success: 0, Failure: -1 + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: November 19, 2001 + * + * Comments: + * + * Modifications: May 08, 2003 + * In version 2.0 of Table, the number of records is stored as an + * attribute "NROWS" + * + * + *------------------------------------------------------------------------- + */ + +herr_t H5TBget_table_info ( hid_t loc_id, + const char *dset_name, + hsize_t *nfields, + hsize_t *nrecords ) +{ + hid_t tid; + hid_t sid=-1; + hid_t did; + int num_members; + hsize_t dims[1]; + int has_attr; + hsize_t n[1]; + + /* Open the dataset. */ + if ( (did = H5Dopen( loc_id, dset_name )) < 0 ) + return -1; + + /* Get the datatype */ + if ( (tid = H5Dget_type( did )) < 0 ) + goto out; + + /* Get the number of members */ + if ( (num_members = H5Tget_nmembers( tid )) < 0 ) + goto out; + + if (nfields) + *nfields = num_members; + + +/*------------------------------------------------------------------------- + * Get number of records + *------------------------------------------------------------------------- + */ + + if (nrecords) + { + /* Try to find the attribute "NROWS" */ + has_attr = H5LT_find_attribute( did, "NROWS" ); + + /* It exists, get it */ + if ( has_attr == 1 ) + { + /* Get the attribute */ + if ( H5LTget_attribute(loc_id,dset_name,"NROWS",H5T_NATIVE_LLONG,n)<0) + return -1; + + *nrecords = *n; + } + else + { + /* Get the dataspace handle */ + if ( (sid = H5Dget_space( did )) < 0 ) + goto out; + + /* Get records */ + if ( H5Sget_simple_extent_dims( sid, dims, NULL) < 0 ) + goto out; + + /* Terminate access to the dataspace */ + if ( H5Sclose( sid ) < 0 ) + goto out; + + *nrecords = dims[0]; + } + }/*nrecords*/ + + /* close */ + if ( H5Tclose( tid ) < 0 ) + goto out; + if ( H5Dclose( did ) < 0 ) + return -1; + +return 0; + +/* error zone, gracefully close */ +out: + H5E_BEGIN_TRY { + H5Dclose(did); + H5Sclose(sid); + H5Tclose(tid); + } H5E_END_TRY; + return -1; + +} + +/*------------------------------------------------------------------------- + * Function: H5TBget_field_info + * + * Purpose: Get information about fields + * + * Return: Success: 0, Failure: -1 + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: November 19, 2001 + * + * Comments: + * + * Modifications: + * + * + *------------------------------------------------------------------------- + */ +herr_t H5TBget_field_info( hid_t loc_id, + const char *dset_name, + char *field_names[], + size_t *field_sizes, + size_t *field_offsets, + size_t *type_size ) +{ + hid_t did; + hid_t ftype_id; + hid_t native_type_id; + hssize_t nfields; + char *member_name; + hid_t member_type_id; + hid_t nativem_type_id; + size_t member_size; + size_t member_offset; + size_t size; + hssize_t i; + + /* Open the dataset. */ + if ( ( did = H5Dopen( loc_id, dset_name )) < 0 ) + goto out; + + /* Get the datatype */ + if ( ( ftype_id = H5Dget_type( did )) < 0 ) + goto out; + + if ((native_type_id = H5Tget_native_type(ftype_id,H5T_DIR_DEFAULT))<0) + goto out; + + /* Get the type size */ + size = H5Tget_size( native_type_id ); + + if ( type_size ) + *type_size = size; + + /* Get the number of members */ + if ( ( nfields = H5Tget_nmembers( ftype_id )) < 0 ) + goto out; + + /* Iterate tru the members */ + for ( i = 0; i < nfields; i++) + { + /* Get the member name */ + member_name = H5Tget_member_name( ftype_id, (unsigned)i ); + + if ( field_names ) + strcpy( field_names[i], member_name ); + + /* Get the member type */ + if ( ( member_type_id = H5Tget_member_type( ftype_id,(unsigned) i )) < 0 ) + goto out; + if ((nativem_type_id = H5Tget_native_type(member_type_id,H5T_DIR_DEFAULT))<0) + goto out; + + /* Get the member size */ + member_size = H5Tget_size( nativem_type_id ); + + if ( field_sizes ) + field_sizes[i] = member_size; + + /* Get the member offset */ + member_offset = H5Tget_member_offset( native_type_id,(unsigned) i ); + + if ( field_offsets ) + field_offsets[i] = member_offset; + + /* Close the member type */ + if ( H5Tclose( member_type_id ) < 0 ) + goto out; + if ( H5Tclose( nativem_type_id ) < 0 ) + goto out; + + free( member_name ); + + } /* i */ + + /* Release the datatype. */ + if ( H5Tclose( ftype_id ) < 0 ) + return -1; + if ( H5Tclose( native_type_id ) < 0 ) + return -1; + + /* End access to the dataset */ + if ( H5Dclose( did ) < 0 ) + return -1; + +return 0; + +out: + H5Dclose( did ); + return -1; + +} + +/*------------------------------------------------------------------------- + * + * Private functions + * + *------------------------------------------------------------------------- + */ + +/*------------------------------------------------------------------------- + * Function: H5TB_find_field + * + * Purpose: Find a string field + * + * Return: Success: 0, Failure: -1 + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: November 19, 2001 + * + *------------------------------------------------------------------------- + */ + + +int H5TB_find_field( const char *field, const char *field_list ) +{ + const char *start = field_list; + const char *end; + + while ( (end = strstr( start, "," )) != 0 ) { + if ( strncmp(start,field,(size_t)(end-start)) == 0 ) return 1; + start = end + 1; + } + + if ( strcmp( start, field ) == 0 ) return 1; + + return -1; + +} + + +/*------------------------------------------------------------------------- + * Function: H5TB_attach_attributes + * + * Purpose: Private function that creates the conforming table attributes; + * Used by H5TBcombine_tables; not used by H5TBmake_table, which does not read + * the fill value attributes from an existing table + * + * Return: Success: 0, Failure: -1 + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: December 6, 2001 + * + * Comments: + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + + +herr_t H5TB_attach_attributes( const char *table_title, + hid_t loc_id, + const char *dset_name, + hsize_t nfields, + hid_t tid ) +{ + + char attr_name[255]; + char *member_name; + char aux[255]; + hsize_t i; + + /* Attach the CLASS attribute */ + if ( H5LTset_attribute_string( loc_id, dset_name, "CLASS", "TABLE" ) < 0 ) + goto out; + + /* Attach the VERSION attribute */ + if ( H5LTset_attribute_string( loc_id, dset_name, "VERSION", "2.0" ) < 0 ) + goto out; + + /* Attach the TITLE attribute */ + if ( H5LTset_attribute_string( loc_id, dset_name, "TITLE", table_title ) < 0 ) + goto out; + + /* Attach the FIELD_ name attribute */ + for ( i = 0; i < nfields; i++) + { + + /* Get the member name */ + member_name = H5Tget_member_name( tid, (unsigned)i ); + + strcpy( attr_name, "FIELD_" ); + sprintf( aux, "%d", (int)i ); + strcat( attr_name, aux ); + sprintf( aux, "%s", "_NAME" ); + strcat( attr_name, aux ); + + /* Attach the attribute */ + if ( H5LTset_attribute_string( loc_id, dset_name, attr_name, member_name ) < 0 ) + goto out; + + free( member_name ); + + } + + return 0; + +out: + return -1; + +} + +/*------------------------------------------------------------------------- + * Function: H5TB_create_type + * + * Purpose: Private function that creates a memory type ID + * + * Return: Success: the memory type ID, Failure: -1 + * + * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu + * + * Date: March 31, 2004 + * + * Comments: + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +hid_t H5TB_create_type(hid_t loc_id, + const char *dset_name, + size_t dst_size, + const size_t *dst_offset, + const size_t *dst_sizes, + hid_t ftype_id) +{ + hid_t mem_type_id; + hid_t mtype_id=-1; + hid_t nmtype_id=-1; + size_t size_native; + hsize_t nfields; + char **fnames; + unsigned i; + + /* get the number of fields */ + if (H5TBget_table_info(loc_id,dset_name,&nfields,NULL)<0) + return -1; + + if ((fnames=malloc(sizeof(char*)*(size_t)nfields))==NULL) + return -1; + + for ( i=0; i<nfields; i++) + { + if ((fnames[i]=malloc(sizeof(char)*HLTB_MAX_FIELD_LEN))==NULL) { + free(fnames); + return -1; + } + } + + /* get field info */ + if ( H5TBget_field_info(loc_id,dset_name,fnames,NULL,NULL,NULL)<0) + goto out; + + /* create the memory data type */ + if ((mem_type_id=H5Tcreate(H5T_COMPOUND,dst_size))<0) + goto out; + + /* get each field ID and adjust its size, if necessary */ + for ( i=0; i<nfields; i++) + { + if ((mtype_id=H5Tget_member_type(ftype_id,i))<0) + goto out; + if ((nmtype_id=H5Tget_native_type(mtype_id,H5T_DIR_DEFAULT))<0) + goto out; + size_native=H5Tget_size(nmtype_id); + if (dst_sizes[i]!=size_native) + { + if (H5Tset_size(nmtype_id,dst_sizes[i])<0) + goto out; + } + if (H5Tinsert(mem_type_id,fnames[i],dst_offset[i],nmtype_id) < 0 ) + goto out; + if (H5Tclose(mtype_id)<0) + goto out; + if (H5Tclose(nmtype_id)<0) + goto out; + } + + for ( i=0; i<nfields; i++) + { + free (fnames[i]); + } + free (fnames); + + return mem_type_id; + + /* error zone, gracefully close and free */ +out: + H5E_BEGIN_TRY { + H5Tclose(mtype_id); + H5Tclose(nmtype_id); + } H5E_END_TRY; + for ( i=0; i<nfields; i++) + { + if (fnames[i]) + free (fnames[i]); + } + if (fnames) + free (fnames); + return -1; + +} + |