summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlbert Cheng <acheng@hdfgroup.org>2004-05-03 23:34:42 (GMT)
committerAlbert Cheng <acheng@hdfgroup.org>2004-05-03 23:34:42 (GMT)
commit0c6229a68d8a8e6148f8a975c5392f62c4b3a35e (patch)
tree84d752bcf68e1ba3ee89cfa3e49f61e7ad0a853a
parentecd3870fa2a8a6a16548592506722d20606be64e (diff)
downloadhdf5-0c6229a68d8a8e6148f8a975c5392f62c4b3a35e.zip
hdf5-0c6229a68d8a8e6148f8a975c5392f62c4b3a35e.tar.gz
hdf5-0c6229a68d8a8e6148f8a975c5392f62c4b3a35e.tar.bz2
[svn-r8479] Purpose:
New Feature Description: Add the data transform function, H5Pset_transform(). Platforms tested: "h5committested". Copper was down. Ran parallel tests in sol instead. Misc. update:
-rw-r--r--MANIFEST4
-rw-r--r--src/H5D.c234
-rw-r--r--src/H5Dio.c94
-rw-r--r--src/H5Dprivate.h10
-rw-r--r--src/H5Pdxpl.c45
-rw-r--r--src/H5Ppublic.h2
-rw-r--r--src/H5Zprivate.h47
-rw-r--r--src/H5Ztrans.c1626
-rw-r--r--src/Makefile.in2
-rw-r--r--test/Makefile.in7
-rw-r--r--test/dtransform.c110
11 files changed, 2159 insertions, 22 deletions
diff --git a/MANIFEST b/MANIFEST
index 5ee300b..bd4a61b 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -778,8 +778,7 @@
./src/H5Dprivate.h
./src/H5Dpublic.h
./src/H5Dpkg.h
-./src/H5DZ.c
-./src/H5DZtrans.c
+./src/H5Ztrans.c
./src/H5E.c
./src/H5Edefin.h
./src/H5Einit.h
@@ -963,6 +962,7 @@
./test/deflate.h5
./test/dsets.c
./test/dtypes.c
+./test/dtransform.c
./test/enum.c
./test/extend.c
./test/external.c
diff --git a/src/H5D.c b/src/H5D.c
index 58aa1a3..aae16c6 100644
--- a/src/H5D.c
+++ b/src/H5D.c
@@ -28,6 +28,7 @@
#include "H5MMprivate.h" /* Memory management */
#include "H5Sprivate.h" /* Dataspaces */
#include "H5Vprivate.h" /* Vectors and arrays */
+#include "H5Zprivate.h"
/*#define H5D_DEBUG*/
@@ -52,6 +53,14 @@ static herr_t H5D_extend(H5D_t *dataset, const hsize_t *size, hid_t dxpl_id);
static herr_t H5D_set_extent(H5D_t *dataset, const hsize_t *size, hid_t dxpl_id);
static herr_t H5D_close(H5D_t *dataset);
+static herr_t H5D_xfer_xform_set(hid_t prop_id, const char* name, size_t size, void* value);
+static herr_t H5D_xfer_xform_del(hid_t prop_id, const char* name, size_t size, void* value);
+static herr_t H5D_xfer_xform_copy(const char* name, size_t size, void* value);
+static herr_t H5D_xfer_xform_close(const char* name, size_t size, void* value);
+
+
+
+
/* Internal data structure for computing variable-length dataset's total size */
typedef struct {
hid_t dataset_id; /* ID of the dataset we are working on */
@@ -128,6 +137,7 @@ H5D_init_interface(void)
{
/* Dataset Transfer property class variables. In sequence, they are,
* - Transfer Property list class to modify
+ * - Default value for maximum data transform buffer size
* - Default value for maximum temp buffer size
* - Default value for type conversion buffer
* - Default value for background buffer
@@ -148,6 +158,7 @@ H5D_init_interface(void)
* - Default value for datatype conversion callback
*/
H5P_genclass_t *xfer_pclass;
+ void* def_xfer_xform = H5D_XFER_XFORM_DEF;
size_t def_max_temp_buf = H5D_XFER_MAX_TEMP_BUF_DEF;
void *def_tconv_buf = H5D_XFER_TCONV_BUF_DEF;
void *def_bkgr_buf = H5D_XFER_BKGR_BUF_DEF;
@@ -189,7 +200,7 @@ H5D_init_interface(void)
H5P_genplist_t *def_dcpl; /* Default Dataset Creation Property list */
size_t nprops; /* Number of properties */
herr_t ret_value = SUCCEED; /* Return value */
-
+
FUNC_ENTER_NOAPI_NOINIT(H5D_init_interface)
/* Initialize the atom group for the dataset IDs */
@@ -210,6 +221,10 @@ H5D_init_interface(void)
/* Assume that if there are properties in the class, they are the default ones */
if(nprops==0) {
+ /* Register the data transform property */
+ if(H5P_register(xfer_pclass,H5D_XFER_XFORM,H5D_XFER_XFORM_SIZE,&def_xfer_xform,NULL,H5D_XFER_XFORM_SET,NULL,H5D_XFER_XFORM_DEL,H5D_XFER_XFORM_COPY,NULL,H5D_XFER_XFORM_CLOSE)<0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+
/* Register the max. temp buffer size property */
if(H5P_register(xfer_pclass,H5D_XFER_MAX_TEMP_BUF_NAME,H5D_XFER_MAX_TEMP_BUF_SIZE,&def_max_temp_buf,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
@@ -439,6 +454,219 @@ H5D_term_interface(void)
FUNC_LEAVE_NOAPI(n)
}
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_xfer_xform_set
+ *
+ * Purpose: Callback for setting a data transform property. This generates
+ * the parse tree for the data transform, as well as saving the transform
+ * locally.
+ *
+ * Return: Success: SUCCEED, Failure: FAIL
+ *
+ * Programmer: Leon Arber, larber@uiuc.edu
+ *
+ * Date: April 9, 2004
+ *
+ * Comments: private, calls H5Z_xform_parse and H5Z_xform_reduce_tree
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_xfer_xform_set(hid_t prop_id, const char UNUSED *name, size_t UNUSED size, void* value)
+{
+ H5P_genplist_t *new_plist;
+ void* parse_root;
+ H5Z_data_xform* data_xform_prop;
+ int exp_size;
+ herr_t ret_value=SUCCEED;
+
+ exp_size = strlen(*(char**)value) + 1;
+ data_xform_prop = (H5Z_data_xform*) HDmalloc(sizeof(H5Z_data_xform));
+
+ FUNC_ENTER_NOAPI(H5D_xfer_xform_set, FAIL)
+
+ /* Verify property list ID */
+ if (NULL == (new_plist = H5I_object(prop_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data transform property list")
+
+ if (value == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "cannot parse a null expression")
+ else
+ {
+#ifdef H5Z_XFORM_DEBUG
+ printf("Adding a new dataset transfer prop. Parsing a new tree from %s\n",*(char**) value);
+#endif
+
+ /* copy the user's string into the property */
+ data_xform_prop->xform_exp = HDmalloc(exp_size);
+ strncpy(data_xform_prop->xform_exp, *(char**)value, exp_size);
+
+
+ /* we generate the parse tree right here and store a poitner to its root in the property. */
+ parse_root = H5Z_xform_parse(*(H5Z_node**)value);
+ H5Z_xform_reduce_tree((H5Z_node*)parse_root);
+ if(parse_root)
+ {
+ data_xform_prop->parse_root = parse_root;
+ HDmemcpy(value, &data_xform_prop, sizeof(void*));
+ }
+ else
+ {
+ /* if we couldn't parse the user's string, we're not going to store it */
+ data_xform_prop->parse_root = NULL;
+ free(data_xform_prop->xform_exp);
+ data_xform_prop->xform_exp = NULL;
+ free(data_xform_prop);
+ *(H5Z_data_xform**)value = NULL;
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "error parsing data transform expression")
+ }
+ }
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_xfer_xform_del
+ *
+ * Purpose: Frees memory allocated by H5D_xfer_xform_set
+ *
+ * Return: Success: SUCCEED, Failure: FAIL
+ *
+ * Programmer: Leon Arber larber@uiuc.edu
+ *
+ *
+ * Date: April 9, 2004
+ *
+ * Comments: Private function, calls private H5Z_xform_destroy_parse_tree
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_xfer_xform_del(hid_t UNUSED prop_id, const char UNUSED *name, size_t UNUSED size, void *value)
+{
+#ifdef H5Z_XFORM_DEBUG
+ fprintf(stderr, "Freeing memory b/c of delete\n");
+#endif
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(H5D_xfer_xform_del, FAIL)
+
+ assert(value);
+
+
+ if( *(H5Z_data_xform**)value != NULL)
+ {
+ H5Z_xform_destroy_parse_tree(((*((H5Z_data_xform**)value)))->parse_root);
+ HDfree(((*((H5Z_data_xform**)value)))->xform_exp);
+ HDfree(*(H5Z_data_xform**)value);
+ *(H5Z_data_xform**)value = NULL;
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_xfer_xform_copy
+ *
+ * Purpose: Creates a copy of the user's data transform string and its
+ * associated parse tree.
+ *
+ * Return: Success: SUCCEED, Failure: FAIL
+ *
+ * Programmer: Leon Arber larber@uiuc.edu
+ *
+ *
+ * Date: April 9, 2004
+ *
+ * Comments: Public function, calls private H5Z_xform_copy_tree
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_xfer_xform_copy(const char UNUSED *name, size_t UNUSED size, void *value)
+{
+ H5Z_node* new_tree;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(H5D_xfer_xform_copy, FAIL)
+
+ /* this will involved generating a new parse tree by copying every single node in the old one */
+ H5Z_data_xform* data_xform_prop;
+ data_xform_prop = (H5Z_data_xform*) HDmalloc(sizeof(H5Z_data_xform));
+
+ data_xform_prop->xform_exp = (char*) HDmalloc(strlen( ((*(H5Z_data_xform**)value))->xform_exp) + 1);
+ strcpy(data_xform_prop->xform_exp, ((*(H5Z_data_xform**)value))->xform_exp);
+ if( (new_tree = (H5Z_node*)H5Z_xform_copy_tree( ((*(H5Z_data_xform**)value))->parse_root)) == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "error copying the parse tree")
+ else
+ data_xform_prop->parse_root = new_tree;
+
+ *(H5Z_data_xform**)value = data_xform_prop;
+
+done:
+FUNC_LEAVE_NOAPI(ret_value)
+
+
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_xfer_xform_close
+ *
+ * Purpose: Frees memory allocated by H5D_xfer_xform_set
+ *
+ * Return: Success: SUCCEED, Failure: FAIL
+ *
+ * Programmer: Leon Arber larber@uiuc.edu
+ *
+ * Date: April 9, 2004
+ *
+ * Comments: private function, calls H5Z_xform_destroy_parse_tree
+ * Identical to H5D_xfer_xform_del
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D_xfer_xform_close(const char UNUSED *name, size_t UNUSED size, void *value)
+{
+#ifdef H5Z_XFORM_DEBUG
+ fprintf(stderr, "Freeing memory b/c of close\n");
+#endif
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(H5D_xfer_xform_close, FAIL)
+
+ assert(value);
+
+ if( *(H5Z_data_xform**)value != NULL)
+ {
+ H5Z_xform_destroy_parse_tree(((*((H5Z_data_xform**)value)))->parse_root);
+ HDfree(((*((H5Z_data_xform**)value)))->xform_exp);
+ HDfree(*(H5Z_data_xform**)value);
+ *(H5Z_data_xform**)value = NULL;
+ }
+
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+}
+
+
+
+
+
/*-------------------------------------------------------------------------
* Function: H5D_crt_copy
@@ -3560,7 +3788,7 @@ done:
* Purpose: Modifies the dimensions of a dataset, based on H5Dextend.
* Can change to a lower dimension.
*
- * Return: Success: 0, Failure: -1
+ * Return: Success: SUCCEED, Failure: FAIL
*
* Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
* Robb Matzke
@@ -3603,7 +3831,7 @@ done:
* Purpose: Based in H5D_extend, allows change to a lower dimension,
* calls H5S_set_extent and H5F_istore_prune_by_extent instead
*
- * Return: Success: 0, Failure: -1
+ * Return: Success: SUCCEED, Failure: FAIL
*
* Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
* Robb Matzke
diff --git a/src/H5Dio.c b/src/H5Dio.c
index 227d0d7..48492b2 100644
--- a/src/H5Dio.c
+++ b/src/H5Dio.c
@@ -27,6 +27,8 @@
#include "H5Sprivate.h" /* Dataspace functions */
#include "H5TBprivate.h" /* Threaded, balanced, binary trees (TBBTs) */
#include "H5Vprivate.h" /* Vector and array functions */
+#include "H5Tpublic.h"
+#include "H5Zprivate.h"
/*#define H5D_DEBUG*/
@@ -129,6 +131,7 @@ H5FL_BLK_DEFINE(type_conv);
/* Declare a free list to manage the H5D_chunk_info_t struct */
H5FL_DEFINE_STATIC(H5D_chunk_info_t);
+
/*--------------------------------------------------------------------------
NAME
@@ -306,7 +309,10 @@ H5D_get_dxpl_cache_real(hid_t dxpl_id, H5D_dxpl_cache_t *cache)
/* Get the dataset transfer property list */
if (NULL == (dx_plist = H5I_object(dxpl_id)))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list")
-
+
+ /* Get the data transform property */
+ H5P_get(dx_plist, H5D_XFER_XFORM, &cache->data_xform_prop);
+
/* Get maximum temporary buffer size */
if(H5P_get(dx_plist, H5D_XFER_MAX_TEMP_BUF_NAME, &cache->max_temp_buf)<0)
HGOTO_ERROR (H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve maximum temporary buffer size")
@@ -1030,6 +1036,8 @@ done:
* Modifications:
* QAK - 2003/04/17
* Hacked on it a lot. :-)
+ * Leon Arber: 4/20/04
+ * Added support for data transforms.
*
*-------------------------------------------------------------------------
*/
@@ -1062,13 +1070,19 @@ H5D_contig_read(hsize_t nelmts, H5D_t *dataset, const H5T_t *mem_type,
hsize_t n, smine_nelmts; /*elements per strip */
herr_t ret_value = SUCCEED; /*return value */
+ hid_t array_type;
+
FUNC_ENTER_NOAPI_NOINIT(H5D_contig_read)
-
+
+ /* Inits for data transforms, if needed */
+ array_type = H5Z_xform_find_type(mem_type);
+
/*
* If there is no type conversion then read directly into the
* application's buffer. This saves at least one mem-to-mem copy.
*/
- if (H5T_path_noop(tpath)) {
+
+ if ( (dxpl_cache->data_xform_prop == NULL) && H5T_path_noop(tpath)) {
#ifdef H5S_DEBUG
H5_timer_begin(&timer);
#endif
@@ -1090,10 +1104,10 @@ H5D_contig_read(hsize_t nelmts, H5D_t *dataset, const H5T_t *mem_type,
if (status<0) {
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "optimized read failed")
} else
- /* direct xfer accomplished successfully */
+ /* direct xfer accomplished successfully */
HGOTO_DONE(SUCCEED)
} /* end if */
-
+
/*
* This is the general case(type conversion).
*/
@@ -1205,6 +1219,15 @@ H5D_contig_read(hsize_t nelmts, H5D_t *dataset, const H5T_t *mem_type,
if (H5T_convert(tpath, src_id, dst_id, smine_nelmts, 0, 0, tconv_buf, bkg_buf, dxpl_id)<0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "data type conversion failed")
+
+ /* Added by LA to do data transforms */
+
+ if(dxpl_cache->data_xform_prop)
+ H5Z_xform_eval(dxpl_cache->data_xform_prop->parse_root, tconv_buf, smine_nelmts, array_type);
+
+ /* end of LA additions */
+
+
/*
* Scatter the data into memory.
*/
@@ -1213,6 +1236,8 @@ H5D_contig_read(hsize_t nelmts, H5D_t *dataset, const H5T_t *mem_type,
#endif
status = H5S_select_mscat(tconv_buf, mem_space,
&mem_iter, smine_nelmts, dxpl_cache, buf/*out*/);
+
+
#ifdef H5S_DEBUG
H5_timer_end(&(sconv->stats[1].scat_timer), &timer);
sconv->stats[1].scat_nbytes += smine_nelmts * dst_type_size;
@@ -1260,6 +1285,8 @@ done:
* Modifications:
* QAK - 2003/04/17
* Hacked on it a lot. :-)
+ * Leon Arber: 4/20/04
+ * Added support for data transforms.
*
*-------------------------------------------------------------------------
*/
@@ -1290,14 +1317,21 @@ H5D_contig_write(hsize_t nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5
hsize_t smine_start; /*strip mine start loc */
hsize_t n, smine_nelmts; /*elements per strip */
herr_t ret_value = SUCCEED; /*return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5D_contig_write)
+ hid_t array_type;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_contig_write)
+
+ /*TODO: This should be the type of the destination file...not the memory source. Where do we get this? */
+ /* Inits for the data transform, if needed */
+ array_type = H5Z_xform_find_type(mem_type);
+
/*
* If there is no type conversion then write directly from the
* application's buffer. This saves at least one mem-to-mem copy.
*/
- if (H5T_path_noop(tpath)) {
+
+ if ( (dxpl_cache->data_xform_prop == NULL) && H5T_path_noop(tpath)) {
#ifdef H5S_DEBUG
H5_timer_begin(&timer);
#endif
@@ -1305,10 +1339,11 @@ H5D_contig_write(hsize_t nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5
status = (sconv->write)(dataset->ent.file, &(dataset->layout),
&dataset->dcpl_cache, (H5D_storage_t *)&(dataset->efl), (size_t)nelmts, H5T_get_size(dataset->type),
file_space, mem_space, dxpl_cache, dxpl_id, buf);
+
#ifdef H5S_DEBUG
- H5_timer_end(&(sconv->stats[0].write_timer), &timer);
- sconv->stats[0].write_nbytes += nelmts * H5T_get_size(mem_type);
- sconv->stats[0].write_ncalls++;
+ H5_timer_end(&(sconv->stats[0].write_timer), &timer);
+ sconv->stats[0].write_nbytes += nelmts * H5T_get_size(mem_type);
+ sconv->stats[0].write_ncalls++;
#endif
/* Check return value from optimized write */
@@ -1437,6 +1472,11 @@ H5D_contig_write(hsize_t nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5
#ifdef H5S_DEBUG
H5_timer_begin(&timer);
#endif
+
+ /* LA additions for data transforms */
+ if(dxpl_cache->data_xform_prop)
+ H5Z_xform_eval(dxpl_cache->data_xform_prop->parse_root, tconv_buf, smine_nelmts, array_type);
+ /* End of LA modifications */
status = H5S_select_fscat(dataset->ent.file, &(dataset->layout),
&dataset->dcpl_cache, (H5D_storage_t *)&(dataset->efl), file_space, &file_iter,
smine_nelmts, dxpl_cache, dxpl_id, tconv_buf);
@@ -1451,6 +1491,7 @@ H5D_contig_write(hsize_t nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5
} /* end for */
done:
+
/* Release selection iterators */
if(file_iter_init) {
if(H5S_select_iter_release(&file_iter)<0)
@@ -1487,7 +1528,10 @@ done:
* Modifications:
* QAK - 2003/04/17
* Hacked on it a lot. :-)
+ * Leon Arber: 4/20/04
+ * Added support for data transforms.
*
+
*-------------------------------------------------------------------------
*/
/* ARGSUSED */
@@ -1524,18 +1568,21 @@ UNUSED
uint8_t *bkg_buf = NULL; /*background buffer */
H5D_storage_t store; /*union of EFL and chunk pointer in file space */
herr_t ret_value = SUCCEED; /*return value */
-
+ hid_t array_type;
+
FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_read)
/* Map elements between file and memory for each chunk*/
if(H5D_create_chunk_map(dataset, mem_type, file_space, mem_space, &fm)<0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't build chunk mapping")
+ array_type = H5Z_xform_find_type(mem_type);
+
/*
* If there is no type conversion then read directly into the
* application's buffer. This saves at least one mem-to-mem copy.
*/
- if (H5T_path_noop(tpath)) {
+ if ( (dxpl_cache->data_xform_prop == NULL) && H5T_path_noop(tpath)) {
#ifdef H5S_DEBUG
H5_timer_begin(&timer);
#endif
@@ -1705,6 +1752,13 @@ UNUSED
tconv_buf, bkg_buf, dxpl_id)<0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "data type conversion failed")
+ /* LA additions for data transforms */
+ if(dxpl_cache->data_xform_prop)
+ H5Z_xform_eval(dxpl_cache->data_xform_prop->parse_root, tconv_buf, smine_nelmts, array_type);
+
+
+
+
/*
* Scatter the data into memory.
*/
@@ -1784,6 +1838,8 @@ done:
* Modifications:
* QAK - 2003/04/17
* Hacked on it a lot. :-)
+ * Leon Arber: 4/20/04
+ * Added support for data transforms.
*
*-------------------------------------------------------------------------
*/
@@ -1821,9 +1877,12 @@ nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space,
uint8_t *bkg_buf = NULL; /*background buffer */
H5D_storage_t store; /*union of EFL and chunk pointer in file space */
herr_t ret_value = SUCCEED; /*return value */
+ hid_t array_type;
FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_write)
+ array_type = H5Z_xform_find_type(mem_type);
+
#ifdef QAK
{
int mpi_rank;
@@ -1850,7 +1909,7 @@ nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space,
* If there is no type conversion then write directly from the
* application's buffer. This saves at least one mem-to-mem copy.
*/
- if (H5T_path_noop(tpath)) {
+ if ((dxpl_cache->data_xform_prop == NULL) && H5T_path_noop(tpath)) {
#ifdef H5S_DEBUG
H5_timer_begin(&timer);
#endif
@@ -2043,6 +2102,13 @@ nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space,
tconv_buf, bkg_buf, dxpl_id)<0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "data type conversion failed")
+ /* LA additions for data transforms */
+ if(dxpl_cache->data_xform_prop)
+ H5Z_xform_eval(dxpl_cache->data_xform_prop->parse_root, tconv_buf, smine_nelmts, array_type);
+
+
+
+
/*
* Scatter the data out to the file.
*/
diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h
index e52f51c..5489659 100644
--- a/src/H5Dprivate.h
+++ b/src/H5Dprivate.h
@@ -74,6 +74,15 @@
#define H5D_CRT_DATA_PIPELINE_CMP H5D_crt_data_pipeline_cmp
/* ======== Data transfer properties ======== */
+/* Definitions for data transform property */
+#define H5D_XFER_XFORM "data_transform"
+#define H5D_XFER_XFORM_SIZE sizeof(void *)
+#define H5D_XFER_XFORM_DEF NULL
+#define H5D_XFER_XFORM_SET H5D_xfer_xform_set
+#define H5D_XFER_XFORM_DEL H5D_xfer_xform_del
+#define H5D_XFER_XFORM_COPY H5D_xfer_xform_copy
+#define H5D_XFER_XFORM_CLOSE H5D_xfer_xform_close
+
/* Definitions for maximum temp buffer size property */
#define H5D_XFER_MAX_TEMP_BUF_NAME "max_temp_buf"
#define H5D_XFER_MAX_TEMP_BUF_SIZE sizeof(size_t)
@@ -171,6 +180,7 @@ typedef struct H5D_dxpl_cache_t {
#endif /*H5_HAVE_PARALLEL*/
H5Z_EDC_t err_detect; /* Error detection info (H5D_XFER_EDC_NAME) */
H5Z_cb_t filter_cb; /* Filter callback function (H5D_XFER_FILTER_CB_NAME) */
+ H5Z_data_xform* data_xform_prop; /* Data transform prop (H5D_XFER_XFORM) */
} H5D_dxpl_cache_t;
/* Typedef for cached dataset creation property list information */
diff --git a/src/H5Pdxpl.c b/src/H5Pdxpl.c
index 04f4783..36bf77e 100644
--- a/src/H5Pdxpl.c
+++ b/src/H5Pdxpl.c
@@ -31,6 +31,51 @@ static int interface_initialize_g = 0;
/* Static function prototypes */
+/*-------------------------------------------------------------------------
+ * Function: H5Pset_data_transform
+ *
+ * Purpose:
+ * Sets data transform expression.
+ *
+ *
+ * Return: Returns a non-negative value if successful; otherwise returns a negative value.
+ *
+ *
+ * Programmer: Leon Arber
+ * Monday, March 07, 2004
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t H5Pset_data_transform(hid_t plist_id, char* expression)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ herr_t ret_value=SUCCEED; /* return value */
+
+ FUNC_ENTER_API(H5Pset_data_transform, FAIL);
+
+ /* H5TRACE4("e","izxx",plist_id,expression); */
+
+ /* Check arguments */
+ if (expression == NULL)
+ HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "expression cannot be NULL");
+
+ /* Get the plist structure */
+ if(NULL == (plist = H5P_object_verify(plist_id,H5P_DATASET_XFER)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID");
+
+ /* Update property list */
+ if(H5P_set(plist, H5D_XFER_XFORM, &expression)<0)
+ HGOTO_ERROR (H5E_PLIST, H5E_CANTSET, FAIL, "Error setting data transform expression");
+
+done:
+ FUNC_LEAVE_API(ret_value);
+}
+
+
+
+
/*-------------------------------------------------------------------------
* Function: H5Pset_buffer
diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h
index cae9337..8368c84 100644
--- a/src/H5Ppublic.h
+++ b/src/H5Ppublic.h
@@ -197,6 +197,7 @@ H5_DLL herr_t H5Pset_layout(hid_t plist_id, H5D_layout_t layout);
H5_DLL H5D_layout_t H5Pget_layout(hid_t plist_id);
H5_DLL herr_t H5Pset_chunk(hid_t plist_id, int ndims, const hsize_t dim[]);
H5_DLL int H5Pget_chunk(hid_t plist_id, int max_ndims, hsize_t dim[]/*out*/);
+H5_DLL herr_t H5Pset_data_transform(hid_t plist_id, char* expression);
H5_DLL herr_t H5Pset_external(hid_t plist_id, const char *name, off_t offset,
hsize_t size);
H5_DLL int H5Pget_external_count(hid_t plist_id);
@@ -217,6 +218,7 @@ H5_DLL herr_t H5Pset_family_offset(hid_t fapl_id, hsize_t offset);
H5_DLL herr_t H5Pget_family_offset(hid_t fapl_id, hsize_t *offset);
H5_DLL herr_t H5Pset_multi_type(hid_t fapl_id, H5FD_mem_t type);
H5_DLL herr_t H5Pget_multi_type(hid_t fapl_id, H5FD_mem_t *type);
+
H5_DLL herr_t H5Pset_buffer(hid_t plist_id, size_t size, void *tconv,
void *bkg);
H5_DLL size_t H5Pget_buffer(hid_t plist_id, void **tconv/*out*/,
diff --git a/src/H5Zprivate.h b/src/H5Zprivate.h
index d87f735..48620be 100644
--- a/src/H5Zprivate.h
+++ b/src/H5Zprivate.h
@@ -19,6 +19,10 @@
#ifndef _H5Zprivate_H
#define _H5Zprivate_H
+#include "H5private.h" /* Generic Functions */
+#include "H5Tprivate.h"
+#include "H5Eprivate.h"
+#include "H5Iprivate.h"
#include "H5Zpublic.h"
/* Structure to store information about each filter's parameters */
@@ -30,6 +34,41 @@ typedef struct {
unsigned *cd_values; /*client data values */
} H5Z_filter_info_t;
+
+/* Token types */
+typedef enum {
+ ERROR,
+ H5Z_INTEGER, /* this represents an integer type in the data transform expression */
+ H5Z_FLOAT, /* this represents a floating point type in the data transform expression */
+ SYMBOL,
+ PLUS,
+ MINUS,
+ MULT,
+ DIVIDE,
+ LPAREN,
+ RPAREN,
+ END
+} H5Z_token_type;
+
+typedef union {
+ char *sym_val;
+ long int_val;
+ double float_val;
+} H5Z_num_val;
+
+
+typedef struct H5Z_node {
+ struct H5Z_node *lchild;
+ struct H5Z_node *rchild;
+ H5Z_token_type type;
+ H5Z_num_val value;
+} H5Z_node;
+
+typedef struct {
+ char* xform_exp;
+ H5Z_node* parse_root;
+} H5Z_data_xform;
+
/* Special parameters for szip compression */
/* [These are aliases for the similar definitions in szlib.h, which we can't
* include directly due to the duplication of various symbols with the zlib.h
@@ -60,5 +99,13 @@ H5_DLL H5Z_filter_info_t *H5Z_filter_info(const struct H5O_pline_t *pline,
H5_DLL htri_t H5Z_all_filters_avail(const struct H5O_pline_t *pline);
H5_DLL herr_t H5Z_delete(struct H5O_pline_t *pline, H5Z_filter_t filter);
+/* Data Transform Functions */
+H5_DLL void H5Z_xform_destroy_parse_tree(H5Z_node *tree);
+H5_DLL void H5Z_xform_eval(H5Z_node *tree, void* array, hsize_t array_size, hid_t array_type);
+H5_DLL void* H5Z_xform_parse(const char *expression);
+H5_DLL hid_t H5Z_xform_find_type(H5T_t* type);
+H5_DLL void H5Z_xform_reduce_tree(H5Z_node* tree);
+H5_DLL void* H5Z_xform_copy_tree(H5Z_node* tree);
+
#endif
diff --git a/src/H5Ztrans.c b/src/H5Ztrans.c
new file mode 100644
index 0000000..3aa4595
--- /dev/null
+++ b/src/H5Ztrans.c
@@ -0,0 +1,1626 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include "H5Zprivate.h"
+
+typedef struct result {
+ H5Z_token_type type;
+ H5Z_num_val value;
+ H5T_class_t ar_type;
+} H5Z_result;
+
+
+/* The token */
+typedef struct {
+ const char *tok_expr; /* Holds the original expression */
+
+ /* Current token values */
+ H5Z_token_type tok_type; /* The type of the current token */
+ const char *tok_begin; /* The beginning of the current token */
+ const char *tok_end; /* The end of the current token */
+
+ /* Previous token values */
+ H5Z_token_type tok_last_type; /* The type of the last token */
+ const char *tok_last_begin; /* The beginning of the last token */
+ const char *tok_last_end; /* The end of the last token */
+} H5Z_token;
+
+
+
+
+/* Interface initialization */
+static int interface_initialize_g = 0;
+#define INTERFACE_INIT NULL
+
+static H5Z_token *H5Z_get_token(H5Z_token *current);
+static H5Z_node *H5Z_parse_expression(H5Z_token *current);
+static H5Z_node *H5Z_parse_term(H5Z_token *current);
+static H5Z_node *H5Z_parse_factor(H5Z_token *current);
+static H5Z_node *H5Z_new_node(H5Z_token_type type);
+static void H5Z_do_op(H5Z_node* tree);
+static H5Z_result H5Z_eval_full(H5Z_node *tree, void* array, hsize_t array_size, hid_t array_type);
+
+
+#ifdef H5Z_XFORM_DEBUG
+static void H5Z_XFORM_DEBUG(H5Z_node *tree);
+static void H5Z_print(H5Z_node *tree, FILE *stream);
+#endif /* H5Z_XFORM_DEBUG */
+
+
+/*
+ * Programmer: Bill Wendling <wendling@ncsa.uiuc.edu>
+ * 25. August 2003
+ */
+
+/*
+ * This is the context-free grammar for our expressions:
+ *
+ * expr := term | term '+ term | term '-' term
+ * term := factor | factor '*' factor | factor '/' factor
+ * factor := number |
+ * symbol |
+ * '-' factor | // unary minus
+ * '+' factor | // unary plus
+ * '(' expr ')'
+ * symbol := [a-zA-Z][a-zA-Z0-9]*
+ * number := H5Z_INTEGER | FLOAT
+ * // H5Z_INTEGER is a C long int
+ * // FLOAT is a C double
+ */
+/*-------------------------------------------------------------------------
+ * Function: H5Z_unget_token
+ * Purpose: Rollback the H5Z_token to the previous H5Z_token retrieved. There
+ * should only need to be one level of rollback necessary
+ * for our grammar.
+ * Return: Always succeeds.
+ * Programmer: Bill Wendling
+ * 26. August 2003
+ * Modifications:
+ * Leon Arber: Added FUNC_ENTER / FUNC_LEAVE pairs
+*
+ *-------------------------------------------------------------------------
+ */
+static void
+H5Z_unget_token(H5Z_token *current)
+{
+ /* check args */
+ assert(current);
+
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5Z_unget_token)
+
+ current->tok_type = current->tok_last_type;
+ current->tok_begin = current->tok_last_begin;
+ current->tok_end = current->tok_last_end;
+
+ FUNC_LEAVE_NOAPI_VOID
+
+
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5Z_get_token
+ * Purpose: Determine what the next valid H5Z_token is in the expression
+ * string. The current position within the H5Z_token string is
+ * kept internal to the H5Z_token and handled by this and the
+ * unget_H5Z_token function.
+ * Return: Succeess: The passed in H5Z_token with a valid tok_type
+ * field.
+ * NULLure: The passed in H5Z_token but with the tok_type
+ * field set to ERROR.
+ * Programmer: Bill Wendling
+ * 26. August 2003
+ * Modifications:
+ * Leon Arber: Added FUNC_ENTER / FUNC_LEAVE pairs
+ *-------------------------------------------------------------------------
+ */
+static H5Z_token *
+H5Z_get_token(H5Z_token *current)
+{
+
+ void* ret_value=current;
+
+ FUNC_ENTER_NOAPI(H5Z_get_token, NULL)
+
+
+ /* check args */
+ assert(current);
+
+ /* Save the last position for possible ungets */
+ current->tok_last_type = current->tok_type;
+ current->tok_last_begin = current->tok_begin;
+ current->tok_last_end = current->tok_end;
+
+ current->tok_begin = current->tok_end;
+
+ while (current->tok_begin[0] != '\0') {
+ if (isspace(current->tok_begin[0])) {
+ /* ignore whitespace */
+ } else if (isdigit(current->tok_begin[0]) ||
+ current->tok_begin[0] == '.') {
+ current->tok_end = current->tok_begin;
+
+ /*
+ * H5Z_INTEGER := digit-sequence
+ * digit-sequence := digit | digit digit-sequence
+ * digit := 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
+ */
+ if (current->tok_end[0] != '.') {
+ /* is number */
+ current->tok_type = H5Z_INTEGER;
+
+ while (isdigit(current->tok_end[0]))
+ ++current->tok_end;
+ }
+
+ /*
+ * float := digit-sequence exponent |
+ * dotted-digits exponent?
+ * dotted-digits := digit-sequence '.' digit-sequence? |
+ * '.' digit-sequence
+ * exponent := [Ee] [-+]? digit-sequence
+ */
+ if (current->tok_end[0] == '.' ||
+ current->tok_end[0] == 'e' ||
+ current->tok_end[0] == 'E') {
+ current->tok_type = H5Z_FLOAT;
+
+ if (current->tok_end[0] == '.')
+ do {
+ ++current->tok_end;
+ } while (isdigit(current->tok_end[0]));
+
+ if (current->tok_end[0] == 'e' ||
+ current->tok_end[0] == 'E') {
+ ++current->tok_end;
+
+ if (current->tok_end[0] == '-' ||
+ current->tok_end[0] == '+')
+ ++current->tok_end;
+
+ if (!isdigit(current->tok_end[0])) {
+ current->tok_type = ERROR;
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, current, "Invalidly formatted floating point number")
+ }
+
+ while (isdigit(current->tok_end[0]))
+ ++current->tok_end;
+ }
+
+ /* Check that this is a properly formatted numerical value */
+ if (isalpha(current->tok_end[0]) || current->tok_end[0] == '.') {
+ current->tok_type = ERROR;
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, current, "Invalidly formatted floating point number")
+ }
+ }
+
+ break;
+ } else if (isalpha(current->tok_begin[0])) {
+ /* is symbol */
+ current->tok_type = SYMBOL;
+ current->tok_end = current->tok_begin;
+
+ while (isalnum(current->tok_end[0]))
+ ++current->tok_end;
+
+ break;
+ } else {
+ /* should be +, -, *, /, (, or ) */
+ switch (current->tok_begin[0]) {
+ case '+': current->tok_type = PLUS; break;
+ case '-': current->tok_type = MINUS; break;
+ case '*': current->tok_type = MULT; break;
+ case '/': current->tok_type = DIVIDE; break;
+ case '(': current->tok_type = LPAREN; break;
+ case ')': current->tok_type = RPAREN; break;
+ default:
+ current->tok_type = ERROR;
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, current, "Unknown H5Z_token in data transform expression ")
+ }
+
+ current->tok_end = current->tok_begin + 1;
+ break;
+ }
+
+ ++current->tok_begin;
+ }
+
+ if (current->tok_begin[0] == '\0')
+ current->tok_type = END;
+
+ HGOTO_DONE(current);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5Z_xform_destroy_parse_tree
+ * Purpose: Recursively destroys the expression tree.
+ * Return: Nothing
+ * Programmer: Bill Wendling
+ * 25. August 2003
+ * Modifications:
+ * Leon Arber: Added FUNC_ENTER / FUNC_LEAVE pairs
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+H5Z_xform_destroy_parse_tree(H5Z_node *tree)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5Z_xform_destroy_parse_tree)
+
+ if (!tree)
+ return;
+
+ if (tree->type == SYMBOL)
+ HDfree(tree->value.sym_val);
+
+ H5Z_xform_destroy_parse_tree(tree->lchild);
+ H5Z_xform_destroy_parse_tree(tree->rchild);
+ HDfree(tree);
+ tree = NULL;
+
+ FUNC_LEAVE_NOAPI_VOID
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Z_parse
+ * Purpose: Entry function for parsing the expression string.
+ * Return: Success: Valid H5Z_node ptr to an expression tree.
+ * NULLure: NULL
+ * Programmer: Bill Wendling
+ * 26. August 2003
+ * Modifications:
+ * Leon Arber: Added FUNC_ENTER / FUNC_LEAVE pairs
+ *
+ *-------------------------------------------------------------------------
+ */
+void *
+H5Z_xform_parse(const char *expression)
+{
+ H5Z_token tok;
+ void* ret_value;
+
+ FUNC_ENTER_NOAPI(H5Z_xform_parse, NULL)
+
+ if (!expression)
+ return NULL;
+
+ /* Set up the initial H5Z_token for parsing */
+ tok.tok_expr = tok.tok_begin = tok.tok_end = expression;
+
+ ret_value = (void*)H5Z_parse_expression(&tok);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5Z_parse_expression
+ * Purpose: Beginning of the recursive descent parser to parse the
+ * expression. An expression is:
+ *
+ * expr := term | term '+' term | term '-' term
+ *
+ * Return: Success: Valid H5Z_node ptr to expression tree
+ * NULLure: NULL
+ * Programmer: Bill Wendling
+ * 26. August 2003
+ * Modifications:
+ * Leon Arber: Added FUNC_ENTER / FUNC_LEAVE pairs
+*
+ *-------------------------------------------------------------------------
+ */
+static H5Z_node *
+H5Z_parse_expression(H5Z_token *current)
+{
+ void* ret_value=NULL;
+
+ FUNC_ENTER_NOAPI(H5Z_parse_expression, NULL)
+
+ H5Z_node *expr = H5Z_parse_term(current);
+
+ for (;;) {
+ H5Z_node *new_node;
+ new_node = NULL;
+
+ current = H5Z_get_token(current);
+
+ switch (current->tok_type) {
+ case PLUS:
+ new_node = H5Z_new_node(PLUS);
+
+ if (!new_node) {
+ H5Z_xform_destroy_parse_tree(expr);
+ expr = NULL;
+ HGOTO_DONE(expr)
+ }
+
+ new_node->lchild = expr;
+ new_node->rchild = H5Z_parse_term(current);
+
+ if (!new_node->rchild) {
+ H5Z_xform_destroy_parse_tree(new_node);
+ expr = NULL;
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Error parsing data transform expression")
+ }
+
+ expr = new_node;
+ break;
+ case MINUS:
+ new_node = H5Z_new_node(MINUS);
+
+ if (!new_node) {
+ H5Z_xform_destroy_parse_tree(expr);
+ expr = NULL;
+ HGOTO_DONE(expr)
+ }
+
+ new_node->lchild = expr;
+ new_node->rchild = H5Z_parse_term(current);
+
+ if (!new_node->rchild) {
+ H5Z_xform_destroy_parse_tree(new_node);
+ expr = NULL;
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Error parsing data transform expression")
+ }
+
+ expr = new_node;
+ break;
+ case RPAREN:
+ H5Z_unget_token(current);
+ HGOTO_DONE(expr)
+ case END:
+ HGOTO_DONE(expr)
+ default:
+ H5Z_xform_destroy_parse_tree(expr);
+ expr = NULL;
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Error parsing data transform expression")
+ }
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(expr)
+
+
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5Z_parse_term
+ * Purpose: Parses a term in our expression language. A term is:
+ *
+ * term := factor | factor '*' factor | factor '/' factor
+ *
+ * Return: Success: Valid H5Z_node ptr to expression tree
+ * NULLure: NULL
+ * Programmer: Bill Wendling
+ * 26. August 2003
+ * Modifications:
+ * Leon Arber: Added FUNC_ENTER / FUNC_LEAVE pairs
+*
+ *-------------------------------------------------------------------------
+ */
+static H5Z_node *
+H5Z_parse_term(H5Z_token *current)
+{
+ H5Z_node *term = NULL;
+ void* ret_value=NULL;
+
+ FUNC_ENTER_NOAPI(H5Z_parse_term, NULL);
+ term = H5Z_parse_factor(current);
+
+ for (;;) {
+ H5Z_node *new_node;
+ new_node = NULL;
+
+ current = H5Z_get_token(current);
+
+ switch (current->tok_type) {
+ case MULT:
+ new_node = H5Z_new_node(MULT);
+
+ if (!new_node) {
+ H5Z_xform_destroy_parse_tree(term);
+ term = NULL;
+ HGOTO_DONE(term)
+ }
+
+ new_node->lchild = term;
+ new_node->rchild = H5Z_parse_factor(current);
+
+ if (!new_node->rchild) {
+ H5Z_xform_destroy_parse_tree(term);
+ term = NULL;
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Error parsing data transform expression")
+ }
+
+ term = new_node;
+ break;
+ case DIVIDE:
+ new_node = H5Z_new_node(DIVIDE);
+
+ if (!new_node) {
+ H5Z_xform_destroy_parse_tree(term);
+ term = NULL;
+ HGOTO_DONE(term)
+ }
+
+ new_node->lchild = term;
+ new_node->rchild = H5Z_parse_factor(current);
+ term = new_node;
+
+ if (!new_node->rchild) {
+ H5Z_xform_destroy_parse_tree(term);
+ term = NULL;
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Error parsing data transform expression")
+ }
+
+ break;
+ case RPAREN:
+ H5Z_unget_token(current);
+ HGOTO_DONE(term)
+ case END:
+ HGOTO_DONE(term)
+ default:
+ H5Z_unget_token(current);
+ HGOTO_DONE(term)
+ }
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(term)
+
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5Z_parse_factor
+ * Purpose: Parses a factor in our expression language. A factor is:
+ *
+ * factor := number | // C long or double
+ * symbol | // C identifier
+ * '-' factor | // unary minus
+ * '+' factor | // unary plus
+ * '(' expr ')'
+ *
+ * Return: Success: Valid H5Z_node ptr to expression tree
+ * NULLure: NULL
+ * Programmer: Bill Wendling
+ * 26. August 2003
+ * Modifications:
+ * Leon Arber: Added FUNC_ENTER / FUNC_LEAVE pairs
+*
+ *-------------------------------------------------------------------------
+ */
+static H5Z_node *
+H5Z_parse_factor(H5Z_token *current)
+{
+ H5Z_node *factor=NULL;
+ H5Z_node *new_node=NULL;
+ void* ret_value=NULL;
+
+ FUNC_ENTER_NOAPI(H5Z_parse_factor, NULL);
+
+ current = H5Z_get_token(current);
+
+ switch (current->tok_type) {
+ case H5Z_INTEGER:
+ factor = H5Z_new_node(H5Z_INTEGER);
+
+ if (!factor)
+ HGOTO_DONE(factor)
+
+ sscanf(current->tok_begin, "%ld", &factor->value.int_val);
+ break;
+ case H5Z_FLOAT:
+ factor = H5Z_new_node(H5Z_FLOAT);
+
+ if (!factor)
+ HGOTO_DONE(factor)
+
+ sscanf(current->tok_begin, "%lf", &factor->value.float_val);
+ break;
+ case SYMBOL:
+ factor = H5Z_new_node(SYMBOL);
+
+ if (!factor)
+ HGOTO_DONE(factor)
+
+ factor->value.sym_val = HDcalloc(current->tok_end - current->tok_begin + 1, 1);
+ HDstrncpy(factor->value.sym_val, current->tok_begin,
+ current->tok_end - current->tok_begin);
+ break;
+ case LPAREN:
+ factor = H5Z_parse_expression(current);
+
+ if (!factor)
+ HGOTO_DONE(factor)
+
+ current = H5Z_get_token(current);
+
+ if (current->tok_type != RPAREN) {
+ H5Z_xform_destroy_parse_tree(factor);
+ factor = NULL;
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Syntax error in data transform expression")
+ }
+
+ break;
+ case RPAREN:
+ /* We shouldn't see a ) right now */
+ H5Z_xform_destroy_parse_tree(factor);
+ factor = NULL;
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Syntax error: unexpected ')' ")
+ case PLUS:
+ /* unary + */
+ new_node = H5Z_parse_factor(current);
+
+ if (new_node) {
+ if (new_node->type != H5Z_INTEGER && new_node->type != H5Z_FLOAT &&
+ new_node->type != SYMBOL) {
+ H5Z_xform_destroy_parse_tree(new_node);
+ H5Z_xform_destroy_parse_tree(factor);
+ factor=NULL;
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Error parsing data transform expression")
+ }
+
+ factor = new_node;
+ new_node = H5Z_new_node(PLUS);
+
+ if (!new_node) {
+ H5Z_xform_destroy_parse_tree(factor);
+ factor = NULL;
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Error parsing data transform expression")
+ }
+
+ new_node->rchild = factor;
+ factor = new_node;
+ } else {
+ H5Z_xform_destroy_parse_tree(factor);
+ factor = NULL;
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Error parsing data transform expression")
+ }
+
+ break;
+ case MINUS:
+ /* unary - */
+ new_node = H5Z_parse_factor(current);
+
+ if (new_node) {
+ if (new_node->type != H5Z_INTEGER && new_node->type != H5Z_FLOAT &&
+ new_node->type != SYMBOL) {
+ H5Z_xform_destroy_parse_tree(new_node);
+ H5Z_xform_destroy_parse_tree(factor);
+ factor = NULL;
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Error parsing data transform expression")
+ }
+
+ factor = new_node;
+ new_node = H5Z_new_node(MINUS);
+
+ if (!new_node) {
+ H5Z_xform_destroy_parse_tree(factor);
+ factor = NULL;
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Error parsing data transform expression")
+ }
+
+ new_node->rchild = factor;
+ factor = new_node;
+ } else {
+ H5Z_xform_destroy_parse_tree(factor);
+ factor = NULL;
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Error parsing data transform expression")
+ }
+
+ break;
+ case END:
+ HGOTO_DONE(factor)
+ }
+
+done:
+
+ FUNC_LEAVE_NOAPI(factor);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5Z_new_node
+ * Purpose: Create and initilize a new H5Z_node structure.
+ * Return: Success: Valid H5Z_node ptr
+ * NULLure: NULL
+ * Programmer: Bill Wendling
+ * 26. August 2003
+ * Modifications:
+ * Leon Arber: Added FUNC_ENTER / FUNC_LEAVE pairs
+*
+ *-------------------------------------------------------------------------
+ */
+static H5Z_node *
+H5Z_new_node(H5Z_token_type type)
+{
+ H5Z_node* ret_value;
+ H5Z_node* new_node;
+
+ FUNC_ENTER_NOAPI(H5Z_new_node, NULL)
+
+ new_node = HDcalloc(1, sizeof(H5Z_node));
+
+ if (new_node)
+ new_node->type = type;
+ else
+ assert(new_node);
+
+done:
+
+ FUNC_LEAVE_NOAPI(new_node);
+}
+
+#ifdef H5Z_XFORM_DEBUG
+/*-------------------------------------------------------------------------
+ * Function: H5Z_XFORM_DEBUG
+ * Purpose: Print out the expression in a nice format which displays
+ * the precedences explicitly with parentheses.
+ * Return: Nothing
+ * Programmer: Bill Wendling
+ * 26. August 2003
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+
+static void
+H5Z_XFORM_DEBUG(H5Z_node *tree)
+{
+ int i;
+ printf("Expression: ");
+ H5Z_result res;
+ res = H5Z_eval(tree);
+
+ if(res.type == H5Z_INTEGER)
+ printf("H5Z_result is: %d",res.value.int_val );
+ else if(res.type == H5Z_FLOAT)
+ printf("H5Z_result is: %f",res.value.float_val );
+ else
+ {
+ printf("H5Z_result is ");
+ for(i=0; i<5; i++)
+ printf("%d ", array[i]);
+ }
+ printf("\n");
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5Z_print
+ * Purpose: Print out the expression in a nice format which displays
+ * the precedences explicitly with parentheses.
+ * Return: Nothing
+ * Programmer: Bill Wendling
+ * 26. August 2003
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void
+H5Z_print(H5Z_node *tree, FILE *stream)
+{
+ /* check args */
+ assert(stream);
+
+ if (!tree)
+ return;
+
+ if (tree->type == H5Z_INTEGER) {
+ fprintf(stream, "%ld", tree->value.int_val);
+ } else if (tree->type == H5Z_FLOAT) {
+ fprintf(stream, "%f", tree->value.float_val);
+ } else if (tree->type == SYMBOL) {
+ fprintf(stream, "%s", tree->value.sym_val);
+ } else {
+ fprintf(stream, "(");
+ H5Z_print(tree->lchild, stream);
+
+ switch (tree->type) {
+ case PLUS: fprintf(stream, "+"); break;
+ case MINUS: fprintf(stream, "-"); break;
+ case MULT: fprintf(stream, "*"); break;
+ case DIVIDE: fprintf(stream, "/"); break;
+ default: fprintf(stream, "Invalid expression tree\n");
+ return;
+ }
+
+ H5Z_print(tree->rchild, stream);
+ fprintf(stream, ")");
+ }
+}
+#endif /* H5Z_XFORM_DEBUG */
+
+
+void H5Z_xform_eval(H5Z_node *tree, void* array, hsize_t array_size, hid_t array_type)
+{
+ unsigned int i;
+ int n;
+ float f;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5Z_xform_eval)
+
+
+ if( tree->type == H5Z_INTEGER)
+ {
+ if(array_type == H5T_NATIVE_INT)
+ {
+ n = tree->value.int_val;
+ for(i=0; i<array_size; i++)
+ *((int*)array + i) = n;
+
+ }
+ else if(array_type == H5T_NATIVE_FLOAT)
+ {
+ f = (float)tree->value.int_val;
+ for(i=0; i<array_size; i++)
+ *((float*)array + i) = f;
+ }
+ }
+ else if (tree->type == H5Z_FLOAT)
+ {
+ for(i=0; i<array_size; i++)
+ {
+ if(array_type == H5T_NATIVE_INT)
+ {
+ n = (int)tree->value.float_val;
+ for(i=0; i<array_size; i++)
+ *((int*)array + i) = n;
+
+ }
+ else if(array_type == H5T_NATIVE_FLOAT)
+ {
+ f = tree->value.float_val;
+ for(i=0; i<array_size; i++)
+ *((float*)array + i) = f;
+ }
+ }
+ }
+ else
+ H5Z_eval_full(tree, array, array_size, array_type);
+
+ FUNC_LEAVE_NOAPI_VOID
+}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Z_eval
+ * Return: Nothing
+ * Programmer: Leon Arber
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5Z_result
+H5Z_eval_full(H5Z_node *tree, void* array, hsize_t array_size, hid_t array_type)
+{
+
+ H5Z_result res, resl, resr;
+ int n;
+ unsigned int i;
+ float f;
+ H5Z_result ret_value;
+ ret_value.type = ERROR;
+
+ FUNC_ENTER_NOAPI(H5Z_eval_full, ret_value);
+
+ /*if (!tree)
+ {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "tree was NULL")
+ }*/
+
+ /* check args */
+ assert(tree);
+
+ if (tree->type == H5Z_INTEGER)
+ {
+ res.type = H5Z_INTEGER;
+ res.value = tree->value;
+ HGOTO_DONE(res)
+ }
+ else if (tree->type == H5Z_FLOAT)
+ {
+ res.type = H5Z_FLOAT;
+ res.value = tree->value;
+ HGOTO_DONE(res)
+ }
+ else if (tree->type == SYMBOL)
+ {
+ res.type = SYMBOL;
+ res.value = tree->value;
+ res.ar_type = array_type;
+ HGOTO_DONE(res)
+ }
+ else
+ {
+ resl = H5Z_eval_full(tree->lchild, array, array_size, array_type);
+ resr = H5Z_eval_full(tree->rchild, array, array_size, array_type);
+ switch (tree->type)
+ {
+ case PLUS:
+ if( (resl.type == SYMBOL) && (resr.type==H5Z_INTEGER))
+ {
+ res.type = SYMBOL;
+ for(i=0; i<array_size; i++)
+ {
+ if(array_type == H5T_NATIVE_INT)
+ {
+ n = resr.value.int_val + *((int*)array + i);
+ *((int*)array + i) = n;
+ }
+ else if(array_type == H5T_NATIVE_FLOAT)
+ {
+ f = resr.value.int_val +*((float*)array + i);
+ *((float*)array + i) = f;
+ }
+ }
+ HGOTO_DONE(res)
+ }
+ else if( (resl.type == SYMBOL) && (resr.type==H5Z_FLOAT))
+ {
+ res.type = SYMBOL;
+ for(i=0; i<array_size; i++)
+ {
+ if(array_type == H5T_NATIVE_INT)
+ {
+ n = resr.value.float_val + *((int*)array + i);
+ *((int*)array + i) = n;
+ }
+ else if(array_type == H5T_NATIVE_FLOAT)
+ {
+ f = resr.value.float_val +*((float*)array + i);
+ *((float*)array + i) = f;
+ }
+ }
+ HGOTO_DONE(res)
+ }
+ else if( (resr.type == SYMBOL) && (resl.type==H5Z_INTEGER))
+ {
+ res.type = SYMBOL;
+ for(i=0; i<array_size; i++)
+ {
+ if(array_type == H5T_NATIVE_INT)
+ {
+ n = resl.value.int_val + *((int*)array + i);
+ *((int*)array + i) = n;
+ }
+ else if(array_type == H5T_NATIVE_FLOAT)
+ {
+ f = resl.value.int_val +*((float*)array + i);
+ *((float*)array + i) = f;
+ }
+ }
+ HGOTO_DONE(res)
+
+ }
+ else if( (resr.type == SYMBOL) && (resl.type==H5Z_FLOAT))
+ {
+
+ res.type = SYMBOL;
+ for(i=0; i<array_size; i++)
+ {
+ if(array_type == H5T_NATIVE_INT)
+ {
+ n = resl.value.float_val + *((int*)array + i);
+ *((int*)array + i) = n;
+ }
+ else if(array_type == H5T_NATIVE_FLOAT)
+ {
+ f = resl.value.float_val +*((float*)array + i);
+ *((float*)array + i) = f;
+ }
+ }
+ HGOTO_DONE(res)
+ }
+ else
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, ret_value, "Unexpected type conversion operation")
+
+ HGOTO_DONE(res)
+ break;
+ case MINUS:
+
+ if( (resl.type == SYMBOL) && (resr.type==H5Z_INTEGER))
+ {
+ res.type = SYMBOL;
+ for(i=0; i<array_size; i++)
+ {
+ if(array_type == H5T_NATIVE_INT)
+ {
+ n = *((int*)array + i) - resr.value.int_val;
+ *((int*)array + i) = n;
+ /* array[i] += resr.value.int_val;*/
+ }
+ else if(array_type == H5T_NATIVE_FLOAT)
+ {
+ f =*((float*)array + i) - resr.value.int_val;
+ *((float*)array + i) = f;
+ }
+ }
+ HGOTO_DONE(res)
+ }
+ else if( (resl.type == SYMBOL) && (resr.type==H5Z_FLOAT)) /*we can't upgrade an array w/o allocating more memory, so we downgrade the float_val to an int.*/
+ {
+ res.type = SYMBOL;
+ for(i=0; i<array_size; i++)
+ {
+ if(array_type == H5T_NATIVE_INT)
+ {
+ n = *((int*)array + i) - resr.value.float_val;
+ *((int*)array + i) = n;
+ }
+ else if(array_type == H5T_NATIVE_FLOAT)
+ {
+ f =*((float*)array + i) - resr.value.float_val;
+ *((float*)array + i) = f;
+ }
+ }
+ HGOTO_DONE(res)
+ }
+ else if( (resr.type == SYMBOL) && (resl.type==H5Z_INTEGER))
+ {
+ res.type = SYMBOL;
+ for(i=0; i<array_size; i++)
+ {
+ if(array_type == H5T_NATIVE_INT)
+ {
+ n = resl.value.int_val - *((int*)array + i);
+ *((int*)array + i) = n;
+ }
+ else if(array_type == H5T_NATIVE_FLOAT)
+ {
+ f = resl.value.int_val -*((float*)array + i);
+ *((float*)array + i) = f;
+ }
+ }
+ HGOTO_DONE(res)
+
+ }
+ else if( (resr.type == SYMBOL) && (resl.type==H5Z_FLOAT))
+ {
+
+ res.type = SYMBOL;
+ for(i=0; i<array_size; i++)
+ {
+ if(array_type == H5T_NATIVE_INT)
+ {
+ n = resl.value.float_val - *((int*)array + i);
+ *((int*)array + i) = n;
+ }
+ else if(array_type == H5T_NATIVE_FLOAT)
+ {
+ f = resl.value.float_val -*((float*)array + i);
+ *((float*)array + i) = f;
+ }
+ }
+ HGOTO_DONE(res)
+ }
+ else
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, ret_value, "Unexpected type conversion operation")
+
+
+ HGOTO_DONE(res)
+ break;
+
+
+ case MULT:
+
+ if( (resl.type == SYMBOL) && (resr.type==H5Z_INTEGER))
+ {
+ res.type = SYMBOL;
+ for(i=0; i<array_size; i++)
+ {
+ if(array_type == H5T_NATIVE_INT)
+ {
+ n = resr.value.int_val * *((int*)array + i);
+ *((int*)array + i) = n;
+ }
+ else if(array_type == H5T_NATIVE_FLOAT)
+ {
+ f = resr.value.int_val **((float*)array + i);
+ *((float*)array + i) = f;
+ }
+ }
+ HGOTO_DONE(res)
+ }
+ else if( (resl.type == SYMBOL) && (resr.type==H5Z_FLOAT))
+ {
+ res.type = SYMBOL;
+ for(i=0; i<array_size; i++)
+ {
+ if(array_type == H5T_NATIVE_INT)
+ {
+ n = resr.value.float_val * *((int*)array + i);
+ *((int*)array + i) = n;
+ }
+ else if(array_type == H5T_NATIVE_FLOAT)
+ {
+ f = resr.value.float_val **((float*)array + i);
+ *((float*)array + i) = f;
+ }
+ }
+ HGOTO_DONE(res)
+ }
+ else if( (resr.type == SYMBOL) && (resl.type==H5Z_INTEGER))
+ {
+ res.type = SYMBOL;
+ for(i=0; i<array_size; i++)
+ {
+ if(array_type == H5T_NATIVE_INT)
+ {
+ n = resl.value.int_val * *((int*)array + i);
+ *((int*)array + i) = n;
+ }
+ else if(array_type == H5T_NATIVE_FLOAT)
+ {
+ f = resl.value.int_val **((float*)array + i);
+ *((float*)array + i) = f;
+ }
+ }
+ HGOTO_DONE(res)
+
+ }
+ else if( (resr.type == SYMBOL) && (resl.type==H5Z_FLOAT))
+ {
+
+ res.type = SYMBOL;
+ for(i=0; i<array_size; i++)
+ {
+ if(array_type == H5T_NATIVE_INT)
+ {
+ n = resl.value.float_val * *((int*)array + i);
+ *((int*)array + i) = n;
+ }
+ else if(array_type == H5T_NATIVE_FLOAT)
+ {
+ f = resl.value.float_val **((float*)array + i);
+ *((float*)array + i) = f;
+ }
+ }
+ HGOTO_DONE(res)
+ }
+ else
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, ret_value, "Unexpected type operation")
+
+ HGOTO_DONE(res)
+ break;
+
+
+ case DIVIDE:
+
+ if( (resl.type == SYMBOL) && (resr.type==H5Z_INTEGER))
+ {
+ res.type = SYMBOL;
+ for(i=0; i<array_size; i++)
+ {
+ if(array_type == H5T_NATIVE_INT)
+ {
+ n = *((int*)array + i) / resr.value.int_val;
+ *((int*)array + i) = n;
+ }
+ else if(array_type == H5T_NATIVE_FLOAT)
+ {
+ f =*((float*)array + i) / resr.value.int_val ;
+ *((float*)array + i) = f;
+ }
+ }
+ HGOTO_DONE(res)
+ }
+ else if( (resl.type == SYMBOL) && (resr.type==H5Z_FLOAT))
+ {
+ res.type = SYMBOL;
+ for(i=0; i<array_size; i++)
+ {
+ if(array_type == H5T_NATIVE_INT)
+ {
+ n = *((int*)array + i) / resr.value.float_val;
+ *((int*)array + i) = n;
+ }
+ else if(array_type == H5T_NATIVE_FLOAT)
+ {
+ f =*((float*)array + i) / resr.value.float_val;
+ *((float*)array + i) = f;
+ }
+ }
+ HGOTO_DONE(res)
+ }
+ else if( (resr.type == SYMBOL) && (resl.type==H5Z_INTEGER))
+ {
+ res.type = SYMBOL;
+ for(i=0; i<array_size; i++)
+ {
+ if(array_type == H5T_NATIVE_INT)
+ {
+ n = resl.value.int_val / *((int*)array + i);
+ *((int*)array + i) = n;
+ }
+ else if(array_type == H5T_NATIVE_FLOAT)
+ {
+ f = resl.value.int_val / *((float*)array + i);
+ *((float*)array + i) = f;
+ }
+ }
+ HGOTO_DONE(res)
+
+ }
+ else if( (resr.type == SYMBOL) && (resl.type==H5Z_FLOAT))
+ {
+
+ res.type = SYMBOL;
+ for(i=0; i<array_size; i++)
+ {
+ if(array_type == H5T_NATIVE_INT)
+ {
+ n = resl.value.float_val / *((int*)array + i);
+ *((int*)array + i) = n;
+ }
+ else if(array_type == H5T_NATIVE_FLOAT)
+ {
+ f = resl.value.float_val / *((float*)array + i);
+ *((float*)array + i) = f;
+ }
+ }
+ HGOTO_DONE(res)
+ }
+ else
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, ret_value, "Unexpected type operation")
+
+ HGOTO_DONE(res)
+ break;
+
+
+
+ default:
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, ret_value, "Invalid expression tree")
+ }
+
+ }
+
+done:
+
+ FUNC_LEAVE_NOAPI(res)
+
+}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Z_find_type
+ * Return: Native type of datatype that is passed in
+ * Programmer: Leon Arber, 4/20/04
+ * Modifications:
+ *
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t H5Z_xform_find_type(H5T_t* type)
+{
+ hid_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(H5Z_xform_find_type, FAIL);
+
+ assert(type);
+
+/* H5T_NATIVE_CHAR
+ H5T_NATIVE_SHORT
+ H5T_NATIVE_INT
+ H5T_NATIVE_LONG
+ H5T_NATIVE_LLONG
+
+ H5T_NATIVE_UCHAR
+ H5T_NATIVE_USHORT
+ H5T_NATIVE_UINT
+ H5T_NATIVE_ULONG
+ H5T_NATIVE_ULLONG
+
+ H5T_NATIVE_FLOAT
+ H5T_NATIVE_DOUBLE
+ H5T_NATIVE_LDOUBLE
+*/
+
+ /* Check for SHORT type */
+ if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_SHORT,H5I_DATATYPE) ))==0)
+ HGOTO_DONE(H5T_NATIVE_SHORT)
+
+ /* Check for INT type */
+ else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_INT,H5I_DATATYPE)))==0)
+ HGOTO_DONE(H5T_NATIVE_INT)
+
+ /* Check for LONG type */
+ else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_LONG,H5I_DATATYPE)))==0)
+ HGOTO_DONE(H5T_NATIVE_LONG)
+
+ /* Check for LONGLONG type */
+ else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_LLONG,H5I_DATATYPE)))==0)
+ HGOTO_DONE(H5T_NATIVE_LLONG)
+
+ /* Check for UCHAR type */
+ else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_UCHAR,H5I_DATATYPE)))==0)
+ HGOTO_DONE(H5T_NATIVE_UCHAR)
+
+ /* Check for USHORT type */
+ else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_USHORT,H5I_DATATYPE)))==0)
+ HGOTO_DONE(H5T_NATIVE_USHORT)
+
+ /* Check for UINT type */
+ else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_UINT,H5I_DATATYPE)))==0)
+ HGOTO_DONE(H5T_NATIVE_UINT)
+
+ /* Check for ULONG type */
+ else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_ULONG,H5I_DATATYPE)))==0)
+ HGOTO_DONE(H5T_NATIVE_ULONG)
+
+ /* Check for ULONGLONG type */
+ else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_ULLONG,H5I_DATATYPE)))==0)
+ HGOTO_DONE(H5T_NATIVE_ULLONG)
+
+ /* Check for FLOAT type */
+ else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_FLOAT,H5I_DATATYPE)))==0)
+ HGOTO_DONE(H5T_NATIVE_FLOAT)
+
+ /* Check for DOUBLE type */
+ else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_DOUBLE,H5I_DATATYPE)))==0)
+ HGOTO_DONE(H5T_NATIVE_DOUBLE)
+
+
+ /* Check for LONGDOUBLE type */
+ else if((H5T_cmp(type, H5I_object_verify(H5T_NATIVE_LDOUBLE,H5I_DATATYPE)))==0)
+ HGOTO_DONE(H5T_NATIVE_LDOUBLE)
+ else
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "could not find matching type");
+
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5Z_xform_copy_tree
+ * Purpose: Makes a copy of the parse tree passed in.
+ * Return: A pointer to a root for a new parse tree which is a copy
+ * of the one passed in.
+ * Programmer: Leon Arber
+ * April 1, 2004.
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void* H5Z_xform_copy_tree(H5Z_node* tree)
+{
+ H5Z_node* ret_value=NULL;
+
+ FUNC_ENTER_NOAPI(H5Z_xform_copy_tree, NULL)
+
+ assert(tree);
+
+ if(tree->type == H5Z_INTEGER)
+ {
+ if ((ret_value = (H5Z_node*) HDmalloc(sizeof(H5Z_node))) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "Ran out of memory trying to copy parse tree")
+ else
+ {
+ ret_value -> type = H5Z_INTEGER;
+ ret_value ->value.int_val = tree->value.int_val;
+ }
+ }
+ else if (tree->type == H5Z_FLOAT)
+ {
+ if ((ret_value = (H5Z_node*) HDmalloc(sizeof(H5Z_node))) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "Ran out of memory trying to copy parse tree")
+ else
+ {
+ ret_value -> type = H5Z_FLOAT;
+ ret_value ->value.float_val = tree->value.float_val;
+ }
+ }
+ else if(tree->type == SYMBOL)
+ {
+ if ((ret_value = (H5Z_node*) HDmalloc(sizeof(H5Z_node))) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "Ran out of memory trying to copy parse tree")
+ else
+ {
+ ret_value -> type = SYMBOL;
+ if ((ret_value->value.sym_val = (char*) HDmalloc(strlen(tree->value.sym_val)+1)) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "Ran out of memory trying to copy parse tree")
+ else
+ strcpy(ret_value ->value.sym_val, tree->value.sym_val);
+ }
+ }
+ else if(tree->type == MULT)
+ {
+ if ((ret_value = (H5Z_node*) HDmalloc(sizeof(H5Z_node))) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "Ran out of memory trying to copy parse tree")
+ else
+ {
+ ret_value->type = MULT;
+ ret_value->lchild = (H5Z_node*) H5Z_xform_copy_tree(tree->lchild);
+ ret_value->rchild = (H5Z_node*) H5Z_xform_copy_tree(tree->rchild);
+ }
+ }
+ else if(tree->type == PLUS)
+ {
+ if ((ret_value = (H5Z_node*) HDmalloc(sizeof(H5Z_node))) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "Ran out of memory trying to copy parse tree")
+ else
+ {
+ ret_value->type = PLUS;
+ ret_value->lchild = (H5Z_node*) H5Z_xform_copy_tree(tree->lchild);
+ ret_value->rchild = (H5Z_node*) H5Z_xform_copy_tree(tree->rchild);
+ }
+ }
+ else if(tree->type == MINUS)
+ {
+ if ((ret_value = (H5Z_node*) HDmalloc(sizeof(H5Z_node))) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "Ran out of memory trying to copy parse tree")
+ else
+ {
+ ret_value->type = MINUS;
+ ret_value->lchild = (H5Z_node*) H5Z_xform_copy_tree(tree->lchild);
+ ret_value->rchild = (H5Z_node*) H5Z_xform_copy_tree(tree->rchild);
+ }
+ }
+ else if(tree->type == DIVIDE)
+ {
+ if ((ret_value = (H5Z_node*) HDmalloc(sizeof(H5Z_node))) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "Ran out of memory trying to copy parse tree")
+ else
+ {
+ ret_value->type = DIVIDE;
+ ret_value->lchild = (H5Z_node*) H5Z_xform_copy_tree(tree->lchild);
+ ret_value->rchild = (H5Z_node*) H5Z_xform_copy_tree(tree->rchild);
+ }
+ }
+ else
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Error in parse tree while trying to copy")
+
+
+
+ done:
+ FUNC_LEAVE_NOAPI(ret_value)
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5Z_xform_reduce_tree
+ * Purpose: Simplifies parse tree passed in by performing any obvious
+ * and trivial arithemtic calculations.
+ *
+ * Return: None.
+ * Programmer: Leon Arber
+ * April 1, 2004.
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void H5Z_xform_reduce_tree(H5Z_node* tree)
+{
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5Z_xform_reduce_tree)
+
+ if(!tree)
+ goto done;
+
+ if((tree->type == PLUS) || (tree->type == DIVIDE) ||(tree->type == MULT) ||(tree->type == MINUS))
+ {
+ if(((tree->lchild->type == H5Z_INTEGER) || (tree->lchild->type == H5Z_FLOAT)) && ((tree->rchild->type == H5Z_INTEGER) || (tree->rchild->type == H5Z_FLOAT)))
+ H5Z_do_op(tree);
+ else
+ {
+ H5Z_xform_reduce_tree(tree->lchild);
+ if(((tree->lchild->type == H5Z_INTEGER) || (tree->lchild->type == H5Z_FLOAT)) && ((tree->rchild->type == H5Z_INTEGER) || (tree->rchild->type == H5Z_FLOAT)))
+ H5Z_do_op(tree);
+
+ H5Z_xform_reduce_tree(tree->rchild);
+ if(((tree->lchild->type == H5Z_INTEGER) || (tree->lchild->type == H5Z_FLOAT)) && ((tree->rchild->type == H5Z_INTEGER) || (tree->rchild->type == H5Z_FLOAT)))
+ H5Z_do_op(tree);
+ }
+ }
+ goto done;
+
+done:
+ FUNC_LEAVE_NOAPI_VOID;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: H5Z_do_op
+ * Purpose: If the root of the tree passed in points to a simple
+ * arithmetic operation and the left and right subtrees are both
+ * integer or floating point values, this function does that
+ * operation, free the left and rigt subtrees, and replaces
+ * the root with the result of the operation.
+ * Return: None.
+ * Programmer: Leon Arber
+ * April 1, 2004.
+ * Modifications:
+*
+ *-------------------------------------------------------------------------
+ */
+static void H5Z_do_op(H5Z_node* tree)
+{
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5Z_do_op)
+
+
+ if(tree->type == DIVIDE)
+ {
+ if((tree->lchild->type == H5Z_INTEGER) && (tree->rchild->type==H5Z_INTEGER))
+ {
+ tree->type = H5Z_INTEGER;
+ tree->value.int_val = tree->lchild->value.int_val / tree->rchild->value.int_val;
+ HDfree(tree->lchild);
+ HDfree(tree->rchild);
+ tree->lchild = NULL;
+ tree->rchild = NULL;
+ }
+ else if((tree->lchild->type == H5Z_FLOAT) && (tree->rchild->type == H5Z_FLOAT))
+ {
+ tree->type = H5Z_FLOAT;
+ tree->value.float_val = tree->lchild->value.float_val / tree->rchild->value.float_val;
+ HDfree(tree->lchild);
+ HDfree(tree->rchild);
+ tree->lchild = NULL;
+ tree->rchild = NULL;
+ }
+ else if( (tree->lchild->type == H5Z_FLOAT) && (tree->rchild->type==H5Z_INTEGER))
+ {
+ tree->type = H5Z_FLOAT;
+ tree->value.float_val = tree->lchild->value.float_val / tree->rchild->value.int_val;
+ HDfree(tree->lchild);
+ HDfree(tree->rchild);
+ tree->lchild = NULL;
+ tree->rchild = NULL;
+ }
+ else if( (tree->lchild->type == H5Z_INTEGER) && (tree->rchild->type == H5Z_FLOAT))
+ {
+ tree->type = H5Z_FLOAT;
+ tree->value.float_val = tree->lchild->value.int_val / tree->rchild->value.float_val;
+ HDfree(tree->lchild);
+ HDfree(tree->rchild);
+ tree->lchild = NULL;
+ tree->rchild = NULL;
+ }
+
+ }
+ else if(tree->type == MULT)
+ {
+
+
+ if((tree->lchild->type == H5Z_INTEGER) && (tree->rchild->type==H5Z_INTEGER))
+ {
+ tree->type = H5Z_INTEGER;
+ tree->value.int_val = tree->lchild->value.int_val * tree->rchild->value.int_val;
+ HDfree(tree->lchild);
+ HDfree(tree->rchild);
+ tree->lchild = NULL;
+ tree->rchild = NULL;
+ }
+ else if((tree->lchild->type == H5Z_FLOAT) && (tree->rchild->type == H5Z_FLOAT))
+ {
+ tree->type = H5Z_FLOAT;
+ tree->value.float_val = tree->lchild->value.float_val * tree->rchild->value.float_val;
+ HDfree(tree->lchild);
+ HDfree(tree->rchild);
+ tree->lchild = NULL;
+ tree->rchild = NULL;
+ }
+ else if( (tree->lchild->type == H5Z_FLOAT) && (tree->rchild->type==H5Z_INTEGER))
+ {
+ tree->type = H5Z_FLOAT;
+ tree->value.float_val = tree->lchild->value.float_val * tree->rchild->value.int_val;
+ HDfree(tree->lchild);
+ HDfree(tree->rchild);
+ tree->lchild = NULL;
+ tree->rchild = NULL;
+ }
+ else if( (tree->lchild->type == H5Z_INTEGER) && (tree->rchild->type == H5Z_FLOAT))
+ {
+ tree->type = H5Z_FLOAT;
+ tree->value.float_val = tree->lchild->value.int_val * tree->rchild->value.float_val;
+ HDfree(tree->lchild);
+ HDfree(tree->rchild);
+ tree->lchild = NULL;
+ tree->rchild = NULL;
+ }
+
+ }
+ else if(tree->type == PLUS)
+ {
+
+
+ if((tree->lchild->type == H5Z_INTEGER) && (tree->rchild->type==H5Z_INTEGER))
+ {
+ tree->type = H5Z_INTEGER;
+ tree->value.int_val = tree->lchild->value.int_val + tree->rchild->value.int_val;
+ HDfree(tree->lchild);
+ HDfree(tree->rchild);
+ tree->lchild = NULL;
+ tree->rchild = NULL;
+ }
+ else if((tree->lchild->type == H5Z_FLOAT) && (tree->rchild->type == H5Z_FLOAT))
+ {
+ tree->type = H5Z_FLOAT;
+ tree->value.float_val = tree->lchild->value.float_val + tree->rchild->value.float_val;
+ HDfree(tree->lchild);
+ HDfree(tree->rchild);
+ tree->lchild = NULL;
+ tree->rchild = NULL;
+ }
+ else if( (tree->lchild->type == H5Z_FLOAT) && (tree->rchild->type==H5Z_INTEGER))
+ {
+ tree->type = H5Z_FLOAT;
+ tree->value.float_val = tree->lchild->value.float_val + tree->rchild->value.int_val;
+ HDfree(tree->lchild);
+ HDfree(tree->rchild);
+ tree->lchild = NULL;
+ tree->rchild = NULL;
+ }
+ else if( (tree->lchild->type == H5Z_INTEGER) && (tree->rchild->type == H5Z_FLOAT))
+ {
+ tree->type = H5Z_FLOAT;
+ tree->value.float_val = tree->lchild->value.int_val + tree->rchild->value.float_val;
+ HDfree(tree->lchild);
+ HDfree(tree->rchild);
+ tree->lchild = NULL;
+ tree->rchild = NULL;
+ }
+
+ }
+ else if(tree->type == MINUS)
+ {
+
+
+ if((tree->lchild->type == H5Z_INTEGER) && (tree->rchild->type==H5Z_INTEGER))
+ {
+ tree->type = H5Z_INTEGER;
+ tree->value.int_val = tree->lchild->value.int_val - tree->rchild->value.int_val;
+ HDfree(tree->lchild);
+ HDfree(tree->rchild);
+ tree->lchild = NULL;
+ tree->rchild = NULL;
+ }
+ else if((tree->lchild->type == H5Z_FLOAT) && (tree->rchild->type == H5Z_FLOAT))
+ {
+ tree->type = H5Z_FLOAT;
+ tree->value.float_val = tree->lchild->value.float_val - tree->rchild->value.float_val;
+ HDfree(tree->lchild);
+ HDfree(tree->rchild);
+ tree->lchild = NULL;
+ tree->rchild = NULL;
+ }
+ else if( (tree->lchild->type == H5Z_FLOAT) && (tree->rchild->type==H5Z_INTEGER))
+ {
+ tree->type = H5Z_FLOAT;
+ tree->value.float_val = tree->lchild->value.float_val - tree->rchild->value.int_val;
+ HDfree(tree->lchild);
+ HDfree(tree->rchild);
+ tree->lchild = NULL;
+ tree->rchild = NULL;
+ }
+ else if( (tree->lchild->type == H5Z_INTEGER) && (tree->rchild->type == H5Z_FLOAT))
+ {
+ tree->type = H5Z_FLOAT;
+ tree->value.float_val = tree->lchild->value.int_val - tree->rchild->value.float_val;
+ HDfree(tree->lchild);
+ HDfree(tree->rchild);
+ tree->lchild = NULL;
+ tree->rchild = NULL;
+ }
+ }
+
+ FUNC_LEAVE_NOAPI_VOID;
+
+}
diff --git a/src/Makefile.in b/src/Makefile.in
index ab39296..c08141a 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -45,7 +45,7 @@ LIB_SRC=H5.c H5A.c H5AC.c H5B.c H5D.c H5Dio.c H5E.c H5F.c H5Fcontig.c \
H5Tconv.c H5Tcset.c H5Tenum.c H5Tfields.c H5Tfixed.c H5Tfloat.c \
H5Tinit.c H5Tnative.c H5Toffset.c H5Topaque.c H5Torder.c H5Tpad.c \
H5Tprecis.c H5Tstrpad.c H5Tvlen.c H5TB.c H5TS.c H5V.c H5Z.c \
- H5Zdeflate.c H5Zfletcher32.c H5Zshuffle.c H5Zszip.c
+ H5Zdeflate.c H5Zfletcher32.c H5Zshuffle.c H5Zszip.c H5Ztrans.c
LIB_OBJ=$(LIB_SRC:.c=.lo)
diff --git a/test/Makefile.in b/test/Makefile.in
index 3951d7a..e0d3a54 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -31,7 +31,7 @@ TEST_PROGS=testhdf5 lheap ohdr stab gheap hyperslab istore bittests dtypes
dsets cmpd_dset extend external links unlink big mtime fillval mount \
flush1 flush2 enum gass_write gass_read gass_append set_extent \
srb_write srb_append srb_read ttsafe stream_test getname file_handle \
- ntypes dangle
+ ntypes dangle dtransform
## Test programs for Error API
ERR_PROGS=error_test err_compat
@@ -83,7 +83,7 @@ TEST_SRC=big.c bittests.c cmpd_dset.c dsets.c dtypes.c extend.c \
ttsafe_cancel.c ttsafe_acreate.c gass_write.c gass_read.c \
gass_append.c srb_read.c srb_write.c srb_append.c stream_test.c \
set_extent.c getname.c file_handle.c ntypes.c dangle.c error_test.c \
- err_compat.c
+ err_compat.c dtransform.c
TEST_OBJ=$(TEST_SRC:.c=.lo)
@@ -230,4 +230,7 @@ error_test: error_test.lo
err_compat: err_compat.lo
@$(LT_LINK_EXE) $(CFLAGS) -o $@ err_compat.lo $(LIB) $(LIBHDF5) $(LDFLAGS) $(LIBS)
+dtransform: dtransform.lo
+ @$(LT_LINK_EXE) $(CFLAGS) -o $@ dtransform.lo $(LIB) $(LIBHDF5) $(LDFLAGS) $(LIBS)
+
@CONCLUDE@
diff --git a/test/dtransform.c b/test/dtransform.c
new file mode 100644
index 0000000..0f2e4e8
--- /dev/null
+++ b/test/dtransform.c
@@ -0,0 +1,110 @@
+#include "h5test.h"
+
+#define ROWS 12
+#define COLS 18
+#define TOL 2
+
+int compare(int* a, int* b);
+
+int main()
+{
+
+ hid_t file_id, dxpl_id_f_to_c, dxpl_id_c_to_f, dset_id, datatype, dataspace;
+ hsize_t dim[2] = {ROWS, COLS};
+ char* f_to_c = "(5/9.0)*(x-32)";
+ char* c_to_f = "(9/5.0)*x + 32";
+ int windchillF[ROWS][COLS] =
+ { {36, 31, 25, 19, 13, 7, 1, -5, -11, -16, -22, -28, -34, -40, -46, -52, -57, -63 },
+ {34, 27, 21, 15, 9, 3, -4, -10, -16, -22, -28, -35, -41, -47, -53, -59, -66, -72 } ,
+ {32, 25, 19, 13, 6, 0, -7, -13, -19, -26, -32, -39, -45, -51, -58, -64, -71, -77 },
+ {30, 24, 17, 11, 4, -2, -9, -15, -22, -29, -35, -42, -48, -55, -61, -68, -74, -81 },
+ {29, 23, 16, 9, 3, -4, -11, -17, -24, -31, -37, -44, -51, -58, -64, -71, -78, -84 },
+ {28, 22, 15, 8, 1, -5, -12, -19, -26, -33, -39, -46, -53, -60, -67, -73, -80, -87 },
+ {28, 21, 14, 7, 0, -7, -14, -21, -27, -34, -41, -48, -55, -62, -69, -76, -82, -89 },
+ {27, 20, 13, 6, -1, -8, -15, -22, -29, -36, -43, -50, -57, -64, -71, -78, -84, -91 },
+ {26, 19, 12, 5, -2, -9, -16, -23, -30, -37, -44, -51, -58, -65, -72, -79, -86, -93 },
+ {26, 19, 12, 4, -3, -10, -17, -24, -31, -38, -45, -52, -60, -67, -74, -81, -88, -95},
+ {25, 18, 11, 4, -3, -11, -18, -25, -32, -39, -46, -54, -61, -68, -75, -82, -89, -97},
+ {25, 17, 10, 3, -4, -11, -19, -26, -33, -40, -48, -55, -62, -69, -76, -84, -91, -98}
+ };
+ int windchillCread[ROWS][COLS];
+ int windchillFread[ROWS][COLS];
+ int windchillCcalc[ROWS][COLS];
+ herr_t err;
+ int row, col;
+
+
+ TESTING("data transform");
+
+ dxpl_id_f_to_c = H5Pcreate(H5P_DATASET_XFER);
+ dxpl_id_c_to_f = H5Pcreate(H5P_DATASET_XFER);
+
+ err= H5Pset_data_transform(dxpl_id_f_to_c, f_to_c);
+ err= H5Pset_data_transform(dxpl_id_c_to_f, c_to_f);
+
+
+ file_id = H5Fcreate("dtransform.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+
+ dataspace = H5Screate_simple(2, dim, NULL);
+
+ datatype = H5Tcopy(H5T_NATIVE_INT);
+
+ dset_id = H5Dcreate(file_id, "/transformtest", datatype, dataspace, H5P_DEFAULT);
+
+ err = H5Dwrite(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, dxpl_id_f_to_c, windchillF);
+ err = H5Dread(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, windchillCread);
+
+ for(row = 0; row<ROWS; row++)
+ {
+ for(col = 0; col<COLS; col++)
+ windchillCcalc[row][col] = (5/9.0)*(windchillF[row][col] - 32);
+ }
+
+ if( (compare(windchillCread, windchillCcalc)) == 0)
+ {
+ fprintf(stderr, "ERROR: Conversion failed to match computed data\n");
+ TEST_ERROR;
+ }
+ else
+ {
+ err = H5Dread(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, dxpl_id_c_to_f, windchillFread);
+ if( (compare(windchillF, windchillFread)) == 0)
+ {
+ fprintf(stderr, "ERROR: Conversion failed to match computed data\n");
+ TEST_ERROR;
+ }
+ }
+
+
+ /* Close the objects we opened/created */
+ err = H5Sclose(dataspace);
+ err = H5Tclose(datatype);
+ err = H5Dclose(dset_id);
+ err = H5Fclose(file_id);
+ err = H5Pclose(dxpl_id_f_to_c);
+ err = H5Pclose(dxpl_id_c_to_f);
+
+ PASSED();
+
+ return 0;
+
+error:
+ return -1;
+}
+
+int compare(int* a, int* b)
+{
+ int row, col;
+ for(row = 0; row<ROWS; row++)
+ {
+ for(col = 0; col<COLS; col++)
+ {
+ if( !((a[row*COLS + col] <= (b[row*COLS + col] + TOL)) && (a[row*COLS + col] >= (b[row*COLS + col] - TOL))) )
+ return 0;
+ }
+ }
+ return 1;
+}
+
+
+