diff --git a/MANIFEST b/MANIFEST index d5be43653a6..e2960f6de12 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1139,6 +1139,7 @@ ./test/cache_tagging.c ./test/chunk_info.c ./test/cmpd_dset.c +./test/cmpd_dtransform.c ./test/cork.c ./test/corrupt_stab_msg.h5 ./test/cross_read.c diff --git a/src/H5T.c b/src/H5T.c index de2a1002501..587ba0f3aa3 100644 --- a/src/H5T.c +++ b/src/H5T.c @@ -3408,8 +3408,8 @@ H5T__create(H5T_class_t type, size_t size) * Note: Common code for both H5T_copy and H5T_copy_reopen, as part of * the const-correct datatype copying routines. * - * Programmer: David Young - * January 18, 2020 + * Programmer: David Young + * January 18, 2020 * *------------------------------------------------------------------------- */ @@ -3462,8 +3462,8 @@ H5T__initiate_copy(const H5T_t *old_dt) * Return: Success: Pointer to a new copy of the OLD_DT argument. * Failure: NULL * - * Programmer: David Young - * January 18, 2020 + * Programmer: David Young + * January 18, 2020 * *------------------------------------------------------------------------- */ @@ -3490,8 +3490,8 @@ H5T__copy_transient(H5T_t *old_dt) * Return: Success: Pointer to a new copy of the OLD_DT argument. * Failure: NULL * - * Programmer: David Young - * January 18, 2020 + * Programmer: David Young + * January 18, 2020 * *------------------------------------------------------------------------- */ @@ -3521,8 +3521,8 @@ H5T__copy_all(H5T_t *old_dt) * * Note: Common code for both H5T_copy and H5T_copy_reopen. * - * Programmer: David Young - * January 18, 2020 + * Programmer: David Young + * January 18, 2020 * *------------------------------------------------------------------------- */ @@ -3794,8 +3794,8 @@ H5T_copy(const H5T_t *old_dt, H5T_copy_t method) * Return: Success: Pointer to a new copy of the OLD_DT argument. * Failure: NULL * - * Programmer: David Young - * January 18, 2020 + * Programmer: David Young + * January 18, 2020 * *------------------------------------------------------------------------- */ @@ -5270,7 +5270,10 @@ H5T__path_find_real(const H5T_t *src, const H5T_t *dst, const char *name, H5T_co } /* end else-if */ /* Set the flag to indicate both source and destination types are compound types - * for the optimization of data reading (in H5Dio.c). */ + * for the optimization of data reading (in H5Dio.c). + * Make sure that path->are_compounds is only TRUE for compound types. + */ + path->are_compounds = FALSE; if (H5T_COMPOUND == H5T_get_class(src, TRUE) && H5T_COMPOUND == H5T_get_class(dst, TRUE)) path->are_compounds = TRUE; diff --git a/src/H5Ztrans.c b/src/H5Ztrans.c index 0224c779c37..7d55efd3d1c 100644 --- a/src/H5Ztrans.c +++ b/src/H5Ztrans.c @@ -1538,10 +1538,20 @@ H5Z_xform_create(const char *expr) "unable to allocate memory for data transform expression") /* Find the number of times "x" is used in this equation, and allocate room for storing that many points + * A more sophisticated check is needed to support scientific notation. */ - for (i = 0; i < HDstrlen(expr); i++) - if (HDisalpha(expr[i])) + for (i = 0; i < HDstrlen(expr); i++) { + if (HDisalpha(expr[i])) { + if ((i > 0) && (i < (HDstrlen(expr) - 1))) { + if (((expr[i] == 'E') || (expr[i] == 'e')) && + (HDisdigit(expr[i - 1]) || (expr[i - 1] == '.')) && + (HDisdigit(expr[i + 1]) || (expr[i + 1] == '-') || (expr[i + 1] == '+'))) + continue; + } + count++; + } + } /* When there are no "x"'s in the equation (ie, simple transform case), * we don't need to allocate any space since no array will have to be diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ecfce90c12f..28284025590 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -331,6 +331,7 @@ set (H5_TESTS thread_id # special link vol timer + cmpd_dtransform ) macro (ADD_H5_EXE file) diff --git a/test/Makefile.am b/test/Makefile.am index 66bccbbf23b..a60de2d68e6 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -60,7 +60,7 @@ TEST_PROG= testhdf5 \ cache cache_api cache_image cache_tagging lheap ohdr \ stab gheap evict_on_close farray earray btree2 fheap \ pool accum hyperslab istore bittests dt_arith page_buffer \ - dtypes dsets chunk_info cmpd_dset filter_fail extend direct_chunk \ + dtypes dsets chunk_info cmpd_dset cmpd_dtransform filter_fail extend direct_chunk \ external efc objcopy objcopy_ref links unlink twriteorder big mtime \ fillval mount \ flush1 flush2 app_ref enum set_extent ttsafe enc_dec_plist \ diff --git a/test/cmpd_dtransform.c b/test/cmpd_dtransform.c new file mode 100644 index 00000000000..ef5ad750285 --- /dev/null +++ b/test/cmpd_dtransform.c @@ -0,0 +1,136 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://www.hdfgroup.org/licenses. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: Jan-Willem Blokland + * December 1, 2020 + * + * Purpose: Test writing compounded attribute followed by + * writing data with a data transform function. + */ + +#include "h5test.h" + +#define FILENAME "cmpd_dtransform.h5" +#define LENGTH 11 + +typedef struct { + char name[64]; + char unit[64]; +} att_t; + +int +main(void) +{ + hsize_t dima[] = {1}; + hsize_t dims[] = {LENGTH}; + hid_t str_dtyp_id, att_dtyp_id, file_id, fspace_id, dset_id, att_dspc_id, att_attr_id, dxpl_id; + + /* Compound datatype */ + att_t *atts = HDmalloc(sizeof(att_t)); + HDstrcpy(atts[0].name, "Name"); + HDstrcpy(atts[0].unit, "Unit"); + + /* String type */ + if ((str_dtyp_id = H5Tcopy(H5T_C_S1)) < 0) + TEST_ERROR; + H5Tset_size(str_dtyp_id, 64); + + /* Attribute type */ + if ((att_dtyp_id = H5Tcreate(H5T_COMPOUND, sizeof(att_t))) < 0) + TEST_ERROR; + H5Tinsert(att_dtyp_id, "NAME", HOFFSET(att_t, name), str_dtyp_id); + H5Tinsert(att_dtyp_id, "UNIT", HOFFSET(att_t, unit), str_dtyp_id); + + /* Create file. */ + if ((file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR; + + /* Create file dataspace. */ + if ((fspace_id = H5Screate_simple(1, dims, NULL)) < 0) + TEST_ERROR; + + /* Create dataset. */ + if ((dset_id = H5Dcreate2(file_id, "test_dset", H5T_NATIVE_INT, fspace_id, H5P_DEFAULT, H5P_DEFAULT, + H5P_DEFAULT)) < 0) + TEST_ERROR; + + /* Write the attribute (compound) to the dataset */ + if ((att_dspc_id = H5Screate_simple(1, dima, NULL)) < 0) + TEST_ERROR; + if ((att_attr_id = + H5Acreate2(dset_id, "ATTRIBUTES", att_dtyp_id, att_dspc_id, H5P_DEFAULT, H5P_DEFAULT)) < 0) + TEST_ERROR; + if (H5Awrite(att_attr_id, att_dtyp_id, atts) < 0) + TEST_ERROR; + + /* Create dataset transfer property list */ + const char *expr = "2*x"; + if ((dxpl_id = H5Pcreate(H5P_DATASET_XFER)) < 0) + TEST_ERROR; + if (H5Pset_data_transform(dxpl_id, expr) < 0) { + HDprintf("**** ERROR: H5Pset_data_transform (expression: %s) ****\n", expr); + TEST_ERROR; + } + + int *data = HDmalloc(LENGTH * sizeof(int)); + int *data_res = HDmalloc(LENGTH * sizeof(int)); + for (unsigned i = 0; i < LENGTH; i++) { + data[i] = 10; + data_res[i] = 2 * data[i]; + } + + /* Write the data */ + if (H5Dwrite(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, dxpl_id, data) < 0) + TEST_ERROR; + + /* Read attribute */ + att_t *atts_res = HDmalloc(sizeof(att_t)); + if (H5Aread(att_attr_id, att_dtyp_id, atts_res) < 0) + TEST_ERROR; + + /* Verify attribute */ + if (HDstrcmp(atts_res[0].name, atts[0].name) != 0) + TEST_ERROR; + if (HDstrcmp(atts_res[0].unit, atts[0].unit) != 0) + TEST_ERROR; + + /* Read the data */ + if (H5Dread(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data) < 0) + TEST_ERROR; + + /* Verify data */ + for (unsigned idx = 0; idx < LENGTH; idx++) { + if (data[idx] != data_res[idx]) + TEST_ERROR; + } + + HDfree(atts); + HDfree(atts_res); + HDfree(data); + HDfree(data_res); + + /* Close all identifiers. */ + H5Pclose(dxpl_id); + H5Aclose(att_attr_id); + H5Sclose(att_dspc_id); + H5Dclose(dset_id); + H5Sclose(fspace_id); + H5Fclose(file_id); + H5Tclose(att_dtyp_id); + H5Tclose(str_dtyp_id); + + return 0; + +error: + return 1; +} diff --git a/test/dtransform.c b/test/dtransform.c index c679d30a74b..9445d83eb17 100644 --- a/test/dtransform.c +++ b/test/dtransform.c @@ -581,6 +581,7 @@ test_specials(hid_t file) const char *special3 = "1000/x"; const char *special4 = "-x"; const char *special5 = "+x"; + const char *special6 = "2e+1*x"; TESTING("data transform of some special cases") @@ -702,6 +703,29 @@ test_specials(hid_t file) COMPARE_INT(read_buf, data_res) + if (H5Dclose(dset_id) < 0) + TEST_ERROR + + /*----------------------------- + * Operation 6: 2e+1*x + *----------------------------*/ + if (H5Pset_data_transform(dxpl_id, special6) < 0) + TEST_ERROR; + + for (row = 0; row < ROWS; row++) + for (col = 0; col < COLS; col++) + data_res[row][col] = transformData[row][col] * 20; + + if ((dset_id = H5Dcreate2(file, "/special6", H5T_NATIVE_INT, dataspace, H5P_DEFAULT, H5P_DEFAULT, + H5P_DEFAULT)) < 0) + TEST_ERROR + if (H5Dwrite(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, dxpl_id, transformData) < 0) + TEST_ERROR + if (H5Dread(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, read_buf) < 0) + TEST_ERROR + + COMPARE_INT(read_buf, data_res) + if (H5Dclose(dset_id) < 0) TEST_ERROR