diff options
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; + +} + |