summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Fortner <nfortne2@hdfgroup.org>2013-02-13 21:55:48 (GMT)
committerNeil Fortner <nfortne2@hdfgroup.org>2013-02-13 21:55:48 (GMT)
commit749522bbd654596191c7cad929c00b1a62466cda (patch)
tree6457ae1e2e92166aee3d608b4760565e16744a7d
parent8dcb0ee3d069b03c1146086dc186fc135ae83bf2 (diff)
downloadhdf5-749522bbd654596191c7cad929c00b1a62466cda.zip
hdf5-749522bbd654596191c7cad929c00b1a62466cda.tar.gz
hdf5-749522bbd654596191c7cad929c00b1a62466cda.tar.bz2
[svn-r23265] Merge revisions 23230, 23234, and 23237 to 1.8 branch
Purpose: Implement H5Dscatter and H5Dgather Description: Adds 2 new API functions, H5Dscatter and H5Dgather. H5Dscatter retrieves data from a specified callback function and scatters it into a selection, defined by a supplied dataspace, within a supplied memory buffer. H5Dgather gathers data from a selection within a supplied memory buffer and passes it in a contiguous form to a supplied callback function. Added tests for these functions Tested: jam, ostrich, koala (h5committest); ummon; ummon (1.8)
-rwxr-xr-xbin/trace2
-rw-r--r--release_docs/RELEASE.txt3
-rw-r--r--src/H5Dpublic.h13
-rw-r--r--src/H5Dscatgath.c204
-rw-r--r--test/dsets.c1028
5 files changed, 1249 insertions, 1 deletions
diff --git a/bin/trace b/bin/trace
index 3e82f43..3638810 100755
--- a/bin/trace
+++ b/bin/trace
@@ -96,7 +96,9 @@ $Source = "";
"H5A_operator2_t" => "x",
"H5A_info_t" => "x",
"H5AC_cache_config_t" => "x",
+ "H5D_gather_func_t" => "x",
"H5D_operator_t" => "x",
+ "H5D_scatter_func_t" => "x",
"H5E_auto_t" => "x",
"H5E_auto1_t" => "x",
"H5E_auto2_t" => "x",
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt
index 3084849..641b985 100644
--- a/release_docs/RELEASE.txt
+++ b/release_docs/RELEASE.txt
@@ -63,6 +63,9 @@ New Features
Library
-------
+ - Added new API functions H5Dscatter and H5Dgather to scatter data to and
+ and gather data from a selection within a memory buffer.
+ (NAF - 2013/02/05)
- The library now supports the data conversion from enumeration to numeric
(integer and floating-point number) datatypes. See Issue 8221.
(SLU - 2012/10/23)
diff --git a/src/H5Dpublic.h b/src/H5Dpublic.h
index 523f2b2..484b176 100644
--- a/src/H5Dpublic.h
+++ b/src/H5Dpublic.h
@@ -107,6 +107,15 @@ extern "C" {
typedef herr_t (*H5D_operator_t)(void *elem, hid_t type_id, unsigned ndim,
const hsize_t *point, void *operator_data);
+/* Define the operator function pointer for H5Dscatter() */
+typedef herr_t (*H5D_scatter_func_t)(void **src_buf/*out*/,
+ size_t *src_buf_bytes_used/*out*/,
+ void *op_data);
+
+/* Define the operator function pointer for H5Dgather() */
+typedef herr_t (*H5D_gather_func_t)(const void *dst_buf,
+ size_t dst_buf_bytes_used, void *op_data);
+
H5_DLL hid_t H5Dcreate2(hid_t loc_id, const char *name, hid_t type_id,
hid_t space_id, hid_t lcpl_id, hid_t dcpl_id, hid_t dapl_id);
H5_DLL hid_t H5Dcreate_anon(hid_t file_id, hid_t type_id, hid_t space_id,
@@ -131,6 +140,10 @@ H5_DLL herr_t H5Dvlen_get_buf_size(hid_t dataset_id, hid_t type_id, hid_t space_
H5_DLL herr_t H5Dfill(const void *fill, hid_t fill_type, void *buf,
hid_t buf_type, hid_t space);
H5_DLL herr_t H5Dset_extent(hid_t dset_id, const hsize_t size[]);
+H5_DLL herr_t H5Dscatter(H5D_scatter_func_t op, void *op_data, hid_t type_id,
+ hid_t dst_space_id, void *dst_buf);
+H5_DLL herr_t H5Dgather(hid_t src_space_id, void *src_buf, hid_t type_id,
+ size_t dst_buf_size, void *dst_buf, H5D_gather_func_t op, void *op_data);
H5_DLL herr_t H5Ddebug(hid_t dset_id);
/* Symbols defined for compatibility with previous versions of the HDF5 API.
diff --git a/src/H5Dscatgath.c b/src/H5Dscatgath.c
index 49b6132..60a8800 100644
--- a/src/H5Dscatgath.c
+++ b/src/H5Dscatgath.c
@@ -27,6 +27,7 @@
#include "H5Dpkg.h" /* Dataset functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free Lists */
+#include "H5Iprivate.h" /* IDs */
/****************/
@@ -361,7 +362,7 @@ done:
* copies them into the gather buffer TGATH_BUF.
* Each element is ELMT_SIZE bytes and arranged in application
* memory according to SPACE.
- * The caller is requesting that at most NELMTS be gathered.
+ * The caller is requesting that exactly NELMTS be gathered.
*
* Return: Success: Number of elements copied.
* Failure: 0
@@ -899,3 +900,204 @@ H5D__compound_opt_write(size_t nelmts, const H5D_type_info_t *type_info)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5D__compound_opt_write() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5Dscatter
+ *
+ * Purpose: Scatters data provided by the callback op to the
+ * destination buffer dst_buf, where the dimensions of
+ * dst_buf and the selection to be scattered to are specified
+ * by the dataspace dst_space_id. The type of the data to be
+ * scattered is specified by type_id.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * 14 Jan 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Dscatter(H5D_scatter_func_t op, void *op_data, hid_t type_id,
+ hid_t dst_space_id, void *dst_buf)
+{
+ H5T_t *type; /* Datatype */
+ H5S_t *dst_space; /* Dataspace */
+ H5S_sel_iter_t iter; /* Selection iteration info*/
+ hbool_t iter_init = FALSE; /* Selection iteration info has been initialized */
+ void *src_buf = NULL; /* Source (contiguous) data buffer */
+ size_t src_buf_nbytes = 0; /* Size of src_buf */
+ size_t type_size; /* Datatype element size */
+ hssize_t nelmts; /* Number of remaining elements in selection */
+ size_t nelmts_scatter = 0; /* Number of elements to scatter to dst_buf */
+ H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */
+ H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE5("e", "x*xii*x", op, op_data, type_id, dst_space_id, dst_buf);
+
+ /* Check args */
+ if(op == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid callback function pointer")
+ if(NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
+ if(NULL == (dst_space= (H5S_t *)H5I_object_verify(dst_space_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
+ if(dst_buf == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no destination buffer provided")
+
+ /* Fill the DXPL cache values for later use */
+ if(H5D__get_dxpl_cache(H5P_DATASET_XFER_DEFAULT, &dxpl_cache) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
+
+ /* Get datatype element size */
+ if(0 == (type_size = H5T_GET_SIZE(type)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get datatype size")
+
+ /* Get number of elements in dataspace */
+ if((nelmts = (hssize_t)H5S_GET_SELECT_NPOINTS(dst_space)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCOUNT, FAIL, "unable to get number of elements in selection")
+
+ /* Initialize selection iterator */
+ if(H5S_select_iter_init(&iter, dst_space, type_size) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize selection iterator information")
+ iter_init = TRUE;
+
+ /* Loop until all data has been scattered */
+ while(nelmts > 0) {
+ /* Make callback to retrieve data */
+ if(op(&src_buf, &src_buf_nbytes, op_data) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CALLBACK, FAIL, "callback operator returned failure")
+
+ /* Calculate number of elements */
+ nelmts_scatter = src_buf_nbytes / type_size;
+
+ /* Check callback results */
+ if(!src_buf)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "callback did not return a buffer")
+ if(src_buf_nbytes == 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "callback returned a buffer size of 0")
+ if(src_buf_nbytes % type_size)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "buffer size is not a multiple of datatype size")
+ if(nelmts_scatter > (size_t)nelmts)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "callback returned more elements than in selection")
+
+ /* Scatter data */
+ if(H5D__scatter_mem(src_buf, dst_space, &iter, nelmts_scatter, dxpl_cache, dst_buf) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "scatter failed")
+
+ nelmts -= (hssize_t)nelmts_scatter;
+ } /* end while */
+
+done:
+ /* Release selection iterator */
+ if(iter_init) {
+ if(H5S_SELECT_ITER_RELEASE(&iter) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
+ } /* end if */
+
+ FUNC_LEAVE_API(ret_value)
+} /* H5Dscatter() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Dgather
+ *
+ * Purpose: Gathers data provided from the source buffer src_buf to
+ * contiguous buffer dst_buf, then calls the callback op.
+ * The dimensions of src_buf and the selection to be gathered
+ * are specified by the dataspace src_space_id. The type of
+ * the data to be gathered is specified by type_id.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * 16 Jan 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Dgather(hid_t src_space_id, void *src_buf, hid_t type_id, size_t dst_buf_size,
+ void *dst_buf, H5D_gather_func_t op, void *op_data)
+{
+ H5T_t *type; /* Datatype */
+ H5S_t *src_space; /* Dataspace */
+ H5S_sel_iter_t iter; /* Selection iteration info*/
+ hbool_t iter_init = FALSE; /* Selection iteration info has been initialized */
+ size_t type_size; /* Datatype element size */
+ hssize_t nelmts; /* Number of remaining elements in selection */
+ size_t dst_buf_nelmts; /* Number of elements that can fit in dst_buf */
+ size_t nelmts_gathered; /* Number of elements gathered from src_buf */
+ H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */
+ H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE7("e", "i*xiz*xx*x", src_space_id, src_buf, type_id, dst_buf_size,
+ dst_buf, op, op_data);
+
+ /* Check args */
+ if(NULL == (src_space= (H5S_t *)H5I_object_verify(src_space_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
+ if(src_buf == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no source buffer provided")
+ if(NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
+ if(dst_buf_size == 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "destination buffer size is 0")
+ if(dst_buf == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no destination buffer provided")
+
+ /* Fill the DXPL cache values for later use */
+ if(H5D__get_dxpl_cache(H5P_DATASET_XFER_DEFAULT, &dxpl_cache) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
+
+ /* Get datatype element size */
+ if(0 == (type_size = H5T_GET_SIZE(type)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get datatype size")
+
+ /* Get number of elements in dst_buf_size */
+ dst_buf_nelmts = dst_buf_size / type_size;
+ if(dst_buf_nelmts == 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "destination buffer is not large enough to hold one element")
+
+ /* Get number of elements in dataspace */
+ if((nelmts = (hssize_t)H5S_GET_SELECT_NPOINTS(src_space)) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCOUNT, FAIL, "unable to get number of elements in selection")
+
+ /* If dst_buf is not large enough to hold all the elements, make sure there
+ * is a callback */
+ if(((size_t)nelmts > dst_buf_nelmts) && (op == NULL))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no callback supplied and destination buffer too small")
+
+ /* Initialize selection iterator */
+ if(H5S_select_iter_init(&iter, src_space, type_size) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize selection iterator information")
+ iter_init = TRUE;
+
+ /* Loop until all data has been scattered */
+ while(nelmts > 0) {
+ /* Gather data */
+ if(0 == (nelmts_gathered = H5D__gather_mem(src_buf, src_space, &iter, MIN(dst_buf_nelmts, (size_t)nelmts), dxpl_cache, dst_buf)))
+ HGOTO_ERROR(H5E_IO, H5E_CANTCOPY, FAIL, "gather failed")
+ HDassert(nelmts_gathered == MIN(dst_buf_nelmts, (size_t)nelmts));
+
+ /* Make callback to process dst_buf */
+ if(op && op(dst_buf, nelmts_gathered * type_size, op_data) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CALLBACK, FAIL, "callback operator returned failure")
+
+ nelmts -= (hssize_t)nelmts_gathered;
+ HDassert(op || (nelmts == 0));
+ } /* end while */
+
+done:
+ /* Release selection iterator */
+ if(iter_init) {
+ if(H5S_SELECT_ITER_RELEASE(&iter) < 0)
+ HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release selection iterator")
+ } /* end if */
+
+ FUNC_LEAVE_API(ret_value)
+} /* H5Dgather() */
+
diff --git a/test/dsets.c b/test/dsets.c
index 7283aae..abbbe2c 100644
--- a/test/dsets.c
+++ b/test/dsets.c
@@ -8251,6 +8251,1028 @@ error:
/*-------------------------------------------------------------------------
+ * Function: test_scatter
+ *
+ * Purpose: Tests H5Dscatter with a variety of different selections
+ * and source buffer sizes.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Neil Fortner
+ * Wednesday, January 16, 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+typedef struct scatter_info_t {
+ int *src_buf; /* Source data buffer */
+ size_t block; /* Maximum number of elements to return to H5Dscatter() */
+ size_t size; /* Remaining number of elements to return */
+} scatter_info_t;
+
+#define TEST_SCATTER_CHECK_ARR(ARR, EXP) \
+ for(i=0; i<(int)(sizeof(ARR)/sizeof(ARR[0])); i++) \
+ for(j=0; j<(int)(sizeof(ARR[0])/sizeof(ARR[0][0])); j++) \
+ for(k=0; k<(int)(sizeof(ARR[0][0])/sizeof(ARR[0][0][0])); k++) \
+ if(ARR[i][j][k] != EXP[i][j][k]) { \
+ H5_FAILED(); AT(); \
+ printf(" " #ARR "[%d][%d][%d] == %d, " #EXP "[%d][%d][%d] == %d\n", i, j, k, ARR[i][j][k], i, j, k, EXP[i][j][k]); \
+ goto error; \
+ }
+
+static herr_t
+scatter_cb(void **src_buf/*out*/, size_t *src_buf_bytes_used/*out*/,
+ void *_scatter_info)
+{
+ scatter_info_t *scatter_info = (scatter_info_t *)_scatter_info;
+ size_t nelmts; /* Number of elements to return in src_buf */
+
+ /* Calculate number of elements */
+ nelmts = MIN(scatter_info->block, scatter_info->size);
+ HDassert(nelmts > 0);
+
+ /* Set output variables */
+ *src_buf = (void *)scatter_info->src_buf;
+ *src_buf_bytes_used = nelmts * sizeof(scatter_info->src_buf[0]);
+
+ /* Update scatter_info */
+ scatter_info->src_buf += nelmts;
+ scatter_info->size -= nelmts;
+
+ return SUCCEED;
+}
+
+static herr_t
+test_scatter(void)
+{
+ hid_t sid = -1; /* Dataspace ID */
+ hsize_t dim[3] = {8, 5, 8}; /* Dataspace dimensions */
+ hsize_t start[3] = {0, 0, 0};
+ hsize_t stride[3] = {0, 0, 0};
+ hsize_t count[3] = {0, 0, 0};
+ hsize_t block[3] = {0, 0, 0};
+ hsize_t start2[3] = {0, 0, 0};
+ hsize_t count2[3] = {0, 0, 0};
+ hsize_t point[4][3] = {{2, 3, 2}, {3, 0, 2}, {7, 2, 0}, {0, 1, 5}};
+ size_t src_buf_size;
+ int src_buf[36]; /* Source data buffer */
+ int dst_buf[8][5][8]; /* Destination data buffer */
+ int expect_dst_buf[8][5][8]; /* Expected destination data buffer */
+ scatter_info_t scatter_info; /* Operator data for callback */
+ int i, j, k, src_i; /* Local index variables */
+
+ TESTING("H5Dscatter()");
+
+ /* Create dataspace */
+ if((sid = H5Screate_simple(3, dim, NULL)) < 0) TEST_ERROR
+
+ /* Initialize src_buf */
+ for(i=0; i<(int)(sizeof(src_buf)/sizeof(src_buf[0])); i++)
+ src_buf[i] = i + 1;
+
+
+ /*
+ * Test 1: Simple case
+ */
+ /* Select hyperslab */
+ count[0] = 1;
+ count[1] = 1;
+ count[2] = 8;
+ if(H5Sselect_hyperslab(sid, H5S_SELECT_SET, start, NULL ,count, NULL) < 0)
+ TEST_ERROR
+
+ /* Initialize dst_buf and expect_dst_buf */
+ (void)HDmemset(expect_dst_buf, 0, sizeof(expect_dst_buf));
+ for(i=0; i<8; i++)
+ expect_dst_buf[0][0][i] = src_buf[i];
+
+ /* Loop over buffer sizes */
+ for(src_buf_size=1; src_buf_size<=9; src_buf_size++) {
+ /* Reset dst_buf */
+ (void)HDmemset(dst_buf, 0, sizeof(dst_buf));
+
+ /* Set up scatter info */
+ scatter_info.src_buf = src_buf;
+ scatter_info.block = src_buf_size;
+ scatter_info.size = 8;
+
+ /* Scatter data */
+ if(H5Dscatter(scatter_cb, &scatter_info, H5T_NATIVE_INT, sid, dst_buf) < 0)
+ TEST_ERROR
+
+ /* Verify data */
+ TEST_SCATTER_CHECK_ARR(dst_buf, expect_dst_buf)
+ } /* end for */
+
+
+ /*
+ * Test 2: Single block in dataset
+ */
+ /* Select hyperslab */
+ start[0] = 3;
+ start[1] = 2;
+ start[2] = 4;
+ count[0] = 2;
+ count[1] = 3;
+ count[2] = 2;
+ if(H5Sselect_hyperslab(sid, H5S_SELECT_SET, start, NULL ,count, NULL) < 0)
+ TEST_ERROR
+
+ /* Initialize expect_dst_buf */
+ (void)HDmemset(expect_dst_buf, 0, sizeof(expect_dst_buf));
+ src_i = 0;
+ for(i=3; i<5; i++)
+ for(j=2; j<5; j++)
+ for(k=4; k<6; k++)
+ expect_dst_buf[i][j][k] = src_buf[src_i++];
+
+ /* Loop over buffer sizes */
+ for(src_buf_size=1; src_buf_size<=13; src_buf_size++) {
+ /* Reset dst_buf */
+ (void)HDmemset(dst_buf, 0, sizeof(dst_buf));
+
+ /* Set up scatter info */
+ scatter_info.src_buf = src_buf;
+ scatter_info.block = src_buf_size;
+ scatter_info.size = 12;
+
+ /* Scatter data */
+ if(H5Dscatter(scatter_cb, &scatter_info, H5T_NATIVE_INT, sid, dst_buf) < 0)
+ TEST_ERROR
+
+ /* Verify data */
+ TEST_SCATTER_CHECK_ARR(dst_buf, expect_dst_buf)
+ } /* end for */
+
+
+ /*
+ * Test 3: Multiple blocks
+ */
+ /* Select hyperslab */
+ start[0] = 1;
+ start[1] = 1;
+ start[2] = 1;
+ stride[0] = 3;
+ stride[1] = 4;
+ stride[2] = 5;
+ count[0] = 3;
+ count[1] = 1;
+ count[2] = 2;
+ block[0] = 1;
+ block[1] = 3;
+ block[2] = 2;
+ if(H5Sselect_hyperslab(sid, H5S_SELECT_SET, start, stride ,count, block) < 0)
+ TEST_ERROR
+
+ /* Initialize expect_dst_buf */
+ /* Iterate over block containing selection, checking if each element is in
+ * selection. Note that the algorithm used here (if statement) would not
+ * work for overlapping hyperslabs. */
+ (void)HDmemset(expect_dst_buf, 0, sizeof(expect_dst_buf));
+ src_i = 0;
+ for(i=1; i<8; i++)
+ for(j=1; j<4; j++)
+ for(k=1; k<8; k++)
+ if((hsize_t)i >= start[0]
+ && ((hsize_t)i - start[0]) % stride[0] < block[0]
+ && ((hsize_t)i - start[0]) / stride[0] < count[0]
+ && (hsize_t)j >= start[1]
+ && ((hsize_t)j - start[1]) % stride[1] < block[1]
+ && ((hsize_t)j - start[1]) / stride[1] < count[1]
+ && (hsize_t)k >= start[2]
+ && ((hsize_t)k - start[2]) % stride[2] < block[2]
+ && ((hsize_t)k - start[2]) / stride[2] < count[2])
+ expect_dst_buf[i][j][k] = src_buf[src_i++];
+
+ /* Loop over buffer sizes */
+ for(src_buf_size=1; src_buf_size<=37; src_buf_size++) {
+ /* Reset dst_buf */
+ (void)HDmemset(dst_buf, 0, sizeof(dst_buf));
+
+ /* Set up scatter info */
+ scatter_info.src_buf = src_buf;
+ scatter_info.block = src_buf_size;
+ scatter_info.size = 36;
+
+ /* Scatter data */
+ if(H5Dscatter(scatter_cb, &scatter_info, H5T_NATIVE_INT, sid, dst_buf) < 0)
+ TEST_ERROR
+
+ /* Verify data */
+ TEST_SCATTER_CHECK_ARR(dst_buf, expect_dst_buf)
+ } /* end for */
+
+
+ /*
+ * Test 4: Compound selection
+ */
+ /* Select hyperslabs */
+ start[0] = 2;
+ start[1] = 1;
+ start[2] = 1;
+ count[0] = 2;
+ count[1] = 3;
+ count[2] = 2;
+ if(H5Sselect_hyperslab(sid, H5S_SELECT_SET, start, NULL ,count, NULL) < 0)
+ TEST_ERROR
+ start2[0] = 1;
+ start2[1] = 2;
+ start2[2] = 2;
+ count2[0] = 3;
+ count2[1] = 2;
+ count2[2] = 2;
+ if(H5Sselect_hyperslab(sid, H5S_SELECT_XOR, start2, NULL ,count2, NULL) < 0)
+ TEST_ERROR
+
+ /* Initialize expect_dst_buf */
+ /* Iterate over block containing selection, checking if each element is in
+ * selection. */
+ (void)HDmemset(expect_dst_buf, 0, sizeof(expect_dst_buf));
+ src_i = 0;
+ for(i=1; i<4; i++)
+ for(j=1; j<4; j++)
+ for(k=1; k<4; k++)
+ if(!(((hsize_t)i >= start[0] && (hsize_t)i < start[0] + count[0])
+ && ((hsize_t)j >= start[1] && (hsize_t)j < start[1] + count[1])
+ && ((hsize_t)k >= start[2] && (hsize_t)k < start[2] + count[2]))
+ != !(((hsize_t)i >= start2[0] && (hsize_t)i < start2[0] + count2[0])
+ && ((hsize_t)j >= start2[1] && (hsize_t)j < start2[1] + count2[1])
+ && ((hsize_t)k >= start2[2] && (hsize_t)k < start2[2] + count2[2])))
+ expect_dst_buf[i][j][k] = src_buf[src_i++];
+
+ /* Loop over buffer sizes */
+ for(src_buf_size=1; src_buf_size<=17; src_buf_size++) {
+ /* Reset dst_buf */
+ (void)HDmemset(dst_buf, 0, sizeof(dst_buf));
+
+ /* Set up scatter info */
+ scatter_info.src_buf = src_buf;
+ scatter_info.block = src_buf_size;
+ scatter_info.size = 16;
+
+ /* Scatter data */
+ if(H5Dscatter(scatter_cb, &scatter_info, H5T_NATIVE_INT, sid, dst_buf) < 0)
+ TEST_ERROR
+
+ /* Verify data */
+ TEST_SCATTER_CHECK_ARR(dst_buf, expect_dst_buf)
+ } /* end for */
+
+
+ /*
+ * Test 5: Point selection
+ */
+ /* Select hyperslabs */
+ if(H5Sselect_elements(sid, H5S_SELECT_SET, sizeof(point) / sizeof(point[0]), (hsize_t *)point) < 0)
+ TEST_ERROR
+
+ /* Initialize expect_dst_buf */
+ /* Iterate over block containing selection, checking if each element is in
+ * selection. */
+ (void)HDmemset(expect_dst_buf, 0, sizeof(expect_dst_buf));
+ for(i=0; i<(int)(sizeof(point) / sizeof(point[0])); i++)
+ expect_dst_buf[point[i][0]][point[i][1]][point[i][2]]
+ = src_buf[i];
+
+ /* Loop over buffer sizes */
+ for(src_buf_size=1; src_buf_size<=5; src_buf_size++) {
+ /* Reset dst_buf */
+ (void)HDmemset(dst_buf, 0, sizeof(dst_buf));
+
+ /* Set up scatter info */
+ scatter_info.src_buf = src_buf;
+ scatter_info.block = src_buf_size;
+ scatter_info.size = 4;
+
+ /* Scatter data */
+ if(H5Dscatter(scatter_cb, &scatter_info, H5T_NATIVE_INT, sid, dst_buf) < 0)
+ TEST_ERROR
+
+ /* Verify data */
+ TEST_SCATTER_CHECK_ARR(dst_buf, expect_dst_buf)
+ } /* end for */
+
+
+ /* Close everything */
+ if(H5Sclose(sid) < 0) TEST_ERROR
+
+ PASSED();
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Sclose(sid);
+ } H5E_END_TRY;
+ return -1;
+} /* end test_scatter() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_gather
+ *
+ * Purpose: Tests H5Dgather with a variety of different selections and
+ * destination buffer sizes.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Neil Fortner
+ * Wednesday, January 16, 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+typedef struct gather_info_t {
+ int *expect_dst_buf; /* Expected destination data buffer */
+ size_t max_nelmts; /* Maximum number of elements passed to callback */
+ hbool_t last_call; /* Whether this should be the last time the callback is called */
+} gather_info_t;
+
+static herr_t
+gather_cb(const void *dst_buf, size_t dst_buf_bytes_used,
+ void *_gather_info)
+{
+ gather_info_t *gather_info = (gather_info_t *)_gather_info;
+ size_t nelmts; /* Number of elements in src_buf */
+ int i; /* Local index variable */
+
+ HDassert(dst_buf_bytes_used > 0);
+
+ /* Calculate number of elements */
+ nelmts = dst_buf_bytes_used / sizeof(gather_info->expect_dst_buf[0]);
+
+ /* Make sure the number of bytes is a multiple of the number of elements */
+ if(nelmts * sizeof(gather_info->expect_dst_buf[0]) != dst_buf_bytes_used)
+ TEST_ERROR
+
+ /* Make sure we weren't passed more data than we requested to be passed at
+ * once */
+ if(nelmts > gather_info->max_nelmts)
+ TEST_ERROR
+
+ /* If we were passed less data than requested, make sure this is the last
+ * time the callback was called */
+ if(gather_info->last_call)
+ TEST_ERROR
+ if(nelmts < gather_info->max_nelmts)
+ gather_info->last_call = TRUE;
+
+ /* Compare data and expected data */
+ for(i=0; i<(int)nelmts; i++)
+ if(((const int *)dst_buf)[i] != *((gather_info->expect_dst_buf)++))
+ TEST_ERROR
+
+ return SUCCEED;
+
+error:
+ return FAIL;
+}
+
+static herr_t
+test_gather(void)
+{
+ hid_t sid = -1; /* Dataspace ID */
+ hsize_t dim[3] = {8, 5, 8}; /* Dataspace dimensions */
+ hsize_t start[3] = {0, 0, 0};
+ hsize_t stride[3] = {0, 0, 0};
+ hsize_t count[3] = {0, 0, 0};
+ hsize_t block[3] = {0, 0, 0};
+ hsize_t start2[3] = {0, 0, 0};
+ hsize_t count2[3] = {0, 0, 0};
+ hsize_t point[4][3] = {{2, 3, 2}, {3, 0, 2}, {7, 2, 0}, {0, 1, 5}};
+ size_t dst_buf_size;
+ int src_buf[8][5][8]; /* Source data buffer */
+ int dst_buf[36]; /* Destination data buffer */
+ int expect_dst_buf[36]; /* Expected destination data buffer */
+ gather_info_t gather_info; /* Operator data for callback */
+ int i, j, k, dst_i; /* Local index variables */
+
+ TESTING("H5Dgather()");
+
+ /* Create dataspace */
+ if((sid = H5Screate_simple(3, dim, NULL)) < 0) TEST_ERROR
+
+ /* Initialize src_buf */
+ for(i=0; i<(int)(sizeof(src_buf)/sizeof(src_buf[0])); i++)
+ for(j=0; j<(int)(sizeof(src_buf[0])/sizeof(src_buf[0][0])); j++)
+ for(k=0; k<(int)(sizeof(src_buf[0][0])/sizeof(src_buf[0][0][0])); k++)
+ src_buf[i][j][k] = 1 + k
+ + (int)(sizeof(src_buf[0][0]) / sizeof(src_buf[0][0][0])) * j
+ + (int)(sizeof(src_buf[0]) / sizeof(src_buf[0][0][0])) * i;
+
+
+ /*
+ * Test 1: Simple case
+ */
+ /* Select hyperslab */
+ count[0] = 1;
+ count[1] = 1;
+ count[2] = 8;
+ if(H5Sselect_hyperslab(sid, H5S_SELECT_SET, start, NULL ,count, NULL) < 0)
+ TEST_ERROR
+
+ /* Initialize expect_dst_buf */
+ (void)HDmemset(expect_dst_buf, 0, sizeof(expect_dst_buf));
+ for(i=0; i<8; i++)
+ expect_dst_buf[i] = src_buf[0][0][i];
+
+ /* Loop over buffer sizes */
+ for(dst_buf_size=1; dst_buf_size<=9; dst_buf_size++) {
+ /* Reset dst_buf */
+ (void)HDmemset(dst_buf, 0, sizeof(dst_buf));
+
+ /* Initialize gather_info */
+ gather_info.expect_dst_buf = expect_dst_buf;
+ gather_info.max_nelmts = dst_buf_size;
+ gather_info.last_call = FALSE;
+
+ /* Gather data */
+ if(H5Dgather(sid, src_buf, H5T_NATIVE_INT, dst_buf_size * sizeof(dst_buf[0]), dst_buf, gather_cb, &gather_info) < 0)
+ TEST_ERROR
+
+ /* Verify that all data has been gathered (and verified) */
+ if(gather_info.expect_dst_buf - expect_dst_buf != 8) TEST_ERROR
+ } /* end for */
+
+ /* Test without a callback */
+ /* Loop over buffer sizes */
+ for(dst_buf_size=8; dst_buf_size<=9; dst_buf_size++) {
+ /* Reset dst_buf */
+ (void)HDmemset(dst_buf, 0, sizeof(dst_buf));
+
+ /* Gather data */
+ if(H5Dgather(sid, src_buf, H5T_NATIVE_INT, dst_buf_size * sizeof(dst_buf[0]), dst_buf, NULL, NULL) < 0)
+ TEST_ERROR
+
+ /* Verify data */
+ for(i=0; i<(int)(sizeof(dst_buf)/sizeof(dst_buf[0])); i++)
+ if(dst_buf[i] != expect_dst_buf[i])
+ TEST_ERROR
+ } /* end for */
+
+ /* Test with a dst_buf_size that is not a multiple of the datatype size */
+ /* Reset dst_buf */
+ dst_buf_size = 7;
+ (void)HDmemset(dst_buf, 0, sizeof(dst_buf));
+
+ /* Initialize gather_info */
+ gather_info.expect_dst_buf = expect_dst_buf;
+ gather_info.max_nelmts = dst_buf_size - 1;
+ gather_info.last_call = FALSE;
+
+ /* Gather data */
+ if(H5Dgather(sid, src_buf, H5T_NATIVE_INT, dst_buf_size * sizeof(dst_buf[0]) - 1, dst_buf, gather_cb, &gather_info) < 0)
+ TEST_ERROR
+
+ /* Verify that all data has been gathered (and verified) */
+ if(gather_info.expect_dst_buf - expect_dst_buf != 8) TEST_ERROR
+
+
+ /*
+ * Test 2: Single block in dataset
+ */
+ /* Select hyperslab */
+ start[0] = 3;
+ start[1] = 2;
+ start[2] = 4;
+ count[0] = 2;
+ count[1] = 3;
+ count[2] = 2;
+ if(H5Sselect_hyperslab(sid, H5S_SELECT_SET, start, NULL ,count, NULL) < 0)
+ TEST_ERROR
+
+ /* Initialize expect_dst_buf */
+ (void)HDmemset(expect_dst_buf, 0, sizeof(expect_dst_buf));
+ dst_i = 0;
+ for(i=3; i<5; i++)
+ for(j=2; j<5; j++)
+ for(k=4; k<6; k++)
+ expect_dst_buf[dst_i++] = src_buf[i][j][k];
+
+ /* Loop over buffer sizes */
+ for(dst_buf_size=1; dst_buf_size<=13; dst_buf_size++) {
+ /* Reset dst_buf */
+ (void)HDmemset(dst_buf, 0, sizeof(dst_buf));
+
+ /* Initialize gather_info */
+ gather_info.expect_dst_buf = expect_dst_buf;
+ gather_info.max_nelmts = dst_buf_size;
+ gather_info.last_call = FALSE;
+
+ /* Gather data */
+ if(H5Dgather(sid, src_buf, H5T_NATIVE_INT, dst_buf_size * sizeof(dst_buf[0]), dst_buf, gather_cb, &gather_info) < 0)
+ TEST_ERROR
+
+ /* Verify that all data has been gathered (and verified) */
+ if(gather_info.expect_dst_buf - expect_dst_buf != 12) TEST_ERROR
+ } /* end for */
+
+
+ /*
+ * Test 3: Multiple blocks
+ */
+ /* Select hyperslab */
+ start[0] = 1;
+ start[1] = 1;
+ start[2] = 1;
+ stride[0] = 3;
+ stride[1] = 4;
+ stride[2] = 5;
+ count[0] = 3;
+ count[1] = 1;
+ count[2] = 2;
+ block[0] = 1;
+ block[1] = 3;
+ block[2] = 2;
+ if(H5Sselect_hyperslab(sid, H5S_SELECT_SET, start, stride ,count, block) < 0)
+ TEST_ERROR
+
+ /* Initialize expect_dst_buf */
+ /* Iterate over block containing selection, checking if each element is in
+ * selection. Note that the algorithm used here (if statement) would not
+ * work for overlapping hyperslabs. */
+ (void)HDmemset(expect_dst_buf, 0, sizeof(expect_dst_buf));
+ dst_i = 0;
+ for(i=1; i<8; i++)
+ for(j=1; j<4; j++)
+ for(k=1; k<8; k++)
+ if((hsize_t)i >= start[0]
+ && ((hsize_t)i - start[0]) % stride[0] < block[0]
+ && ((hsize_t)i - start[0]) / stride[0] < count[0]
+ && (hsize_t)j >= start[1]
+ && ((hsize_t)j - start[1]) % stride[1] < block[1]
+ && ((hsize_t)j - start[1]) / stride[1] < count[1]
+ && (hsize_t)k >= start[2]
+ && ((hsize_t)k - start[2]) % stride[2] < block[2]
+ && ((hsize_t)k - start[2]) / stride[2] < count[2])
+ expect_dst_buf[dst_i++] = src_buf[i][j][k];
+
+ /* Loop over buffer sizes */
+ for(dst_buf_size=1; dst_buf_size<=37; dst_buf_size++) {
+ /* Reset dst_buf */
+ (void)HDmemset(dst_buf, 0, sizeof(dst_buf));
+
+ /* Initialize gather_info */
+ gather_info.expect_dst_buf = expect_dst_buf;
+ gather_info.max_nelmts = dst_buf_size;
+ gather_info.last_call = FALSE;
+
+ /* Gather data */
+ if(H5Dgather(sid, src_buf, H5T_NATIVE_INT, dst_buf_size * sizeof(dst_buf[0]), dst_buf, gather_cb, &gather_info) < 0)
+ TEST_ERROR
+
+ /* Verify that all data has been gathered (and verified) */
+ if(gather_info.expect_dst_buf - expect_dst_buf != 36) TEST_ERROR
+ } /* end for */
+
+
+ /*
+ * Test 4: Compound selection
+ */
+ /* Select hyperslabs */
+ start[0] = 2;
+ start[1] = 1;
+ start[2] = 1;
+ count[0] = 2;
+ count[1] = 3;
+ count[2] = 2;
+ if(H5Sselect_hyperslab(sid, H5S_SELECT_SET, start, NULL ,count, NULL) < 0)
+ TEST_ERROR
+ start2[0] = 1;
+ start2[1] = 2;
+ start2[2] = 2;
+ count2[0] = 3;
+ count2[1] = 2;
+ count2[2] = 2;
+ if(H5Sselect_hyperslab(sid, H5S_SELECT_XOR, start2, NULL ,count2, NULL) < 0)
+ TEST_ERROR
+
+ /* Initialize expect_dst_buf */
+ /* Iterate over block containing selection, checking if each element is in
+ * selection. */
+ (void)HDmemset(expect_dst_buf, 0, sizeof(expect_dst_buf));
+ dst_i = 0;
+ for(i=1; i<4; i++)
+ for(j=1; j<4; j++)
+ for(k=1; k<4; k++)
+ if(!(((hsize_t)i >= start[0] && (hsize_t)i < start[0] + count[0])
+ && ((hsize_t)j >= start[1] && (hsize_t)j < start[1] + count[1])
+ && ((hsize_t)k >= start[2] && (hsize_t)k < start[2] + count[2]))
+ != !(((hsize_t)i >= start2[0] && (hsize_t)i < start2[0] + count2[0])
+ && ((hsize_t)j >= start2[1] && (hsize_t)j < start2[1] + count2[1])
+ && ((hsize_t)k >= start2[2] && (hsize_t)k < start2[2] + count2[2])))
+ expect_dst_buf[dst_i++] = src_buf[i][j][k];
+
+ /* Loop over buffer sizes */
+ for(dst_buf_size=1; dst_buf_size<=17; dst_buf_size++) {
+ /* Reset dst_buf */
+ (void)HDmemset(dst_buf, 0, sizeof(dst_buf));
+
+ /* Initialize gather_info */
+ gather_info.expect_dst_buf = expect_dst_buf;
+ gather_info.max_nelmts = dst_buf_size;
+ gather_info.last_call = FALSE;
+
+ /* Gather data */
+ if(H5Dgather(sid, src_buf, H5T_NATIVE_INT, dst_buf_size * sizeof(dst_buf[0]), dst_buf, gather_cb, &gather_info) < 0)
+ TEST_ERROR
+
+ /* Verify that all data has been gathered (and verified) */
+ if(gather_info.expect_dst_buf - expect_dst_buf != 16) TEST_ERROR
+ } /* end for */
+
+
+ /*
+ * Test 5: Point selection
+ */
+ /* Select hyperslabs */
+ if(H5Sselect_elements(sid, H5S_SELECT_SET, sizeof(point) / sizeof(point[0]), (hsize_t *)point) < 0)
+ TEST_ERROR
+
+ /* Initialize expect_dst_buf */
+ /* Iterate over block containing selection, checking if each element is in
+ * selection. */
+ (void)HDmemset(expect_dst_buf, 0, sizeof(expect_dst_buf));
+ for(i=0; i<(int)(sizeof(point) / sizeof(point[0])); i++)
+ expect_dst_buf[i] = src_buf[point[i][0]][point[i][1]][point[i][2]];
+
+ /* Loop over buffer sizes */
+ for(dst_buf_size=1; dst_buf_size<=5; dst_buf_size++) {
+ /* Reset dst_buf */
+ (void)HDmemset(dst_buf, 0, sizeof(dst_buf));
+
+ /* Initialize gather_info */
+ gather_info.expect_dst_buf = expect_dst_buf;
+ gather_info.max_nelmts = dst_buf_size;
+ gather_info.last_call = FALSE;
+
+ /* Gather data */
+ if(H5Dgather(sid, src_buf, H5T_NATIVE_INT, dst_buf_size * sizeof(dst_buf[0]), dst_buf, gather_cb, &gather_info) < 0)
+ TEST_ERROR
+
+ /* Verify that all data has been gathered (and verified) */
+ if(gather_info.expect_dst_buf - expect_dst_buf != 4) TEST_ERROR
+ } /* end for */
+
+
+ /* Close everything */
+ if(H5Sclose(sid) < 0) TEST_ERROR
+
+ PASSED();
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Sclose(sid);
+ } H5E_END_TRY;
+ return -1;
+} /* end test_gather() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_scatter_error
+ *
+ * Purpose: Tests H5Dscatter with a variety of different conditions
+ * that should cause errors.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Neil Fortner
+ * Monday, February 4, 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+scatter_error_cb_fail(void **src_buf/*out*/, size_t *src_buf_bytes_used/*out*/,
+ void *_scatter_info)
+{
+ scatter_info_t *scatter_info = (scatter_info_t *)_scatter_info;
+ size_t nelmts; /* Number of elements to return in src_buf */
+
+ /* Calculate number of elements */
+ nelmts = MIN(scatter_info->block, scatter_info->size);
+ HDassert(nelmts > 0);
+
+ /* Set output variables */
+ *src_buf = (void *)scatter_info->src_buf;
+ *src_buf_bytes_used = nelmts * sizeof(scatter_info->src_buf[0]);
+
+ return FAIL;
+}
+
+static herr_t
+scatter_error_cb_null(void **src_buf/*out*/, size_t *src_buf_bytes_used/*out*/,
+ void *_scatter_info)
+{
+ scatter_info_t *scatter_info = (scatter_info_t *)_scatter_info;
+ size_t nelmts; /* Number of elements to return in src_buf */
+
+ /* Calculate number of elements */
+ nelmts = MIN(scatter_info->block, scatter_info->size);
+ HDassert(nelmts > 0);
+
+ /* Set output variables */
+ *src_buf = NULL;
+ *src_buf_bytes_used = nelmts * sizeof(scatter_info->src_buf[0]);
+
+ return SUCCEED;
+}
+
+static herr_t
+scatter_error_cb_unalign(void **src_buf/*out*/, size_t *src_buf_bytes_used/*out*/,
+ void *_src_buf_bytes_used)
+{
+ /* Set output variables */
+ *src_buf = _src_buf_bytes_used;
+ *src_buf_bytes_used = *(size_t *)_src_buf_bytes_used;
+
+ return SUCCEED;
+}
+
+static herr_t
+test_scatter_error(void)
+{
+ hid_t sid = -1; /* Dataspace ID */
+ hsize_t dim[1] = {10}; /* Dataspace dimensions */
+ hsize_t start[3] = {2};
+ hsize_t count[3] = {6};
+ int src_buf[7]; /* Source data buffer */
+ int dst_buf[10]; /* Destination data buffer */
+ scatter_info_t scatter_info; /* Operator data for callback */
+ size_t cb_unalign_nbytes; /* Number of bytes to return for unaligned test */
+ herr_t ret; /* Return value */
+ int i; /* Local index variable */
+
+ TESTING("H5Dscatter() error conditions");
+
+ /* Create dataspace */
+ if((sid = H5Screate_simple(1, dim, NULL)) < 0) TEST_ERROR
+
+ /* Initialize src_buf */
+ for(i=0; i<(int)(sizeof(src_buf)/sizeof(src_buf[0])); i++)
+ src_buf[i] = i + 1;
+
+ /* Select hyperslab */
+ if(H5Sselect_hyperslab(sid, H5S_SELECT_SET, start, NULL ,count, NULL) < 0)
+ TEST_ERROR
+
+ /* Verify that base configuration passes */
+ scatter_info.src_buf = src_buf;
+ scatter_info.block = sizeof(src_buf)/sizeof(src_buf[0]);
+ scatter_info.size = 6;
+ if(H5Dscatter(scatter_cb, &scatter_info, H5T_NATIVE_INT, sid, dst_buf) < 0)
+ TEST_ERROR
+
+
+ /*
+ * Test invalid parameters
+ */
+ scatter_info.src_buf = src_buf;
+ scatter_info.size = 6;
+ H5E_BEGIN_TRY {
+ ret = H5Dscatter(NULL, NULL, H5T_NATIVE_INT, sid, dst_buf);
+ } H5E_END_TRY
+ if(ret >= 0) TEST_ERROR
+
+ scatter_info.src_buf = src_buf;
+ scatter_info.size = 6;
+ H5E_BEGIN_TRY {
+ ret = H5Dscatter(scatter_cb, &scatter_info, sid, sid, dst_buf);
+ } H5E_END_TRY
+ if(ret >= 0) TEST_ERROR
+
+ scatter_info.src_buf = src_buf;
+ scatter_info.size = 6;
+ H5E_BEGIN_TRY {
+ ret = H5Dscatter(scatter_cb, &scatter_info, H5T_NATIVE_INT, H5T_NATIVE_INT, dst_buf);
+ } H5E_END_TRY
+ if(ret >= 0) TEST_ERROR
+
+ scatter_info.src_buf = src_buf;
+ scatter_info.size = 6;
+ H5E_BEGIN_TRY {
+ ret = H5Dscatter(scatter_cb, &scatter_info, H5T_NATIVE_INT, sid, NULL);
+ } H5E_END_TRY
+ if(ret >= 0) TEST_ERROR
+
+
+ /*
+ * Test returning too many elements in callback
+ */
+ scatter_info.src_buf = src_buf;
+ scatter_info.size = 7;
+ H5E_BEGIN_TRY {
+ ret = H5Dscatter(scatter_cb, &scatter_info, H5T_NATIVE_INT, sid, dst_buf);
+ } H5E_END_TRY
+ if(ret >= 0) TEST_ERROR
+
+
+ /*
+ * Test callback returns failure
+ */
+ scatter_info.src_buf = src_buf;
+ scatter_info.size = 6;
+ H5E_BEGIN_TRY {
+ ret = H5Dscatter(scatter_error_cb_fail, &scatter_info, H5T_NATIVE_INT, sid, dst_buf);
+ } H5E_END_TRY
+ if(ret >= 0) TEST_ERROR
+
+
+ /*
+ * Test callback returns NULL buffer
+ */
+ scatter_info.src_buf = src_buf;
+ scatter_info.size = 6;
+ H5E_BEGIN_TRY {
+ ret = H5Dscatter(scatter_error_cb_null, &scatter_info, H5T_NATIVE_INT, sid, dst_buf);
+ } H5E_END_TRY
+ if(ret >= 0) TEST_ERROR
+
+
+ /*
+ * Test callback returns 0 for src_buf_bytes_used
+ */
+ cb_unalign_nbytes = 0;
+ H5E_BEGIN_TRY {
+ ret = H5Dscatter(scatter_error_cb_unalign, &cb_unalign_nbytes, H5T_NATIVE_INT, sid, dst_buf);
+ } H5E_END_TRY
+ if(ret >= 0) TEST_ERROR
+
+
+ /*
+ * Test callback returns src_buf_bytes_used that is not a multiple of
+ * datatype size
+ */
+ cb_unalign_nbytes = sizeof(src_buf[0]) - 1;
+ H5E_BEGIN_TRY {
+ ret = H5Dscatter(scatter_error_cb_unalign, &cb_unalign_nbytes, H5T_NATIVE_INT, sid, dst_buf);
+ } H5E_END_TRY
+ if(ret >= 0) TEST_ERROR
+
+ cb_unalign_nbytes = sizeof(src_buf[0]) + 1;
+ H5E_BEGIN_TRY {
+ ret = H5Dscatter(scatter_error_cb_unalign, &cb_unalign_nbytes, H5T_NATIVE_INT, sid, dst_buf);
+ } H5E_END_TRY
+ if(ret >= 0) TEST_ERROR
+
+
+ /* Close everything */
+ if(H5Sclose(sid) < 0) TEST_ERROR
+
+ PASSED();
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Sclose(sid);
+ } H5E_END_TRY;
+ return -1;
+} /* end test_scatter_error() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_gather_error
+ *
+ * Purpose: Tests H5Dgather with a variety of different conditions
+ * that should cause errors.
+ *
+ * Return: Success: 0
+ * Failure: -1
+ *
+ * Programmer: Neil Fortner
+ * Monday, February 4, 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+gather_error_cb_fail(const void UNUSED *dst_buf,
+ size_t UNUSED dst_buf_bytes_used, void UNUSED *op_data)
+{
+ return FAIL;
+}
+
+static herr_t
+test_gather_error(void)
+{
+ hid_t sid = -1; /* Dataspace ID */
+ hsize_t dim[1] = {10}; /* Dataspace dimensions */
+ hsize_t start[1] = {2};
+ hsize_t count[1] = {6};
+ int src_buf[10]; /* Source data buffer */
+ int dst_buf[6]; /* Destination data buffer */
+ int expect_dst_buf[6]; /* Expected destination data buffer */
+ gather_info_t gather_info; /* Operator data for callback */
+ herr_t ret; /* Return value */
+ int i; /* Local index variable */
+
+ TESTING("H5Dgather() error conditions");
+
+ /* Create dataspace */
+ if((sid = H5Screate_simple(1, dim, NULL)) < 0) TEST_ERROR
+
+ /* Initialize src_buf */
+ for(i=0; i<(int)(sizeof(src_buf)/sizeof(src_buf[0])); i++)
+ src_buf[i] = 1 + i;
+
+ /* Select hyperslab */
+ if(H5Sselect_hyperslab(sid, H5S_SELECT_SET, start, NULL ,count, NULL) < 0)
+ TEST_ERROR
+
+ /* Initialize expect_dst_buf */
+ (void)HDmemset(expect_dst_buf, 0, sizeof(expect_dst_buf));
+ for(i=0; i<6; i++)
+ expect_dst_buf[i] = src_buf[i + 2];
+
+ /* Verify that base configuration passes */
+ gather_info.expect_dst_buf = expect_dst_buf;
+ gather_info.max_nelmts = 6;
+ gather_info.last_call = FALSE;
+ if(H5Dgather(sid, src_buf, H5T_NATIVE_INT, 6 * sizeof(dst_buf[0]), dst_buf, gather_cb, &gather_info) < 0)
+ TEST_ERROR
+
+ /*
+ * Test invalid parameters
+ */
+ gather_info.expect_dst_buf = expect_dst_buf;
+ gather_info.last_call = FALSE;
+ H5E_BEGIN_TRY {
+ ret = H5Dgather(H5T_NATIVE_INT, src_buf, H5T_NATIVE_INT, 6 * sizeof(dst_buf[0]), dst_buf, gather_cb, &gather_info);
+ } H5E_END_TRY
+ if(ret >= 0) TEST_ERROR
+
+ gather_info.expect_dst_buf = expect_dst_buf;
+ gather_info.last_call = FALSE;
+ H5E_BEGIN_TRY {
+ ret = H5Dgather(sid, NULL, H5T_NATIVE_INT, 6 * sizeof(dst_buf[0]), dst_buf, gather_cb, &gather_info);
+ } H5E_END_TRY
+ if(ret >= 0) TEST_ERROR
+
+ gather_info.expect_dst_buf = expect_dst_buf;
+ gather_info.last_call = FALSE;
+ H5E_BEGIN_TRY {
+ ret = H5Dgather(sid, src_buf, sid, 6 * sizeof(dst_buf[0]), dst_buf, gather_cb, &gather_info);
+ } H5E_END_TRY
+ if(ret >= 0) TEST_ERROR
+
+ gather_info.expect_dst_buf = expect_dst_buf;
+ gather_info.last_call = FALSE;
+ H5E_BEGIN_TRY {
+ ret = H5Dgather(sid, src_buf, H5T_NATIVE_INT, 0, dst_buf, gather_cb, &gather_info);
+ } H5E_END_TRY
+ if(ret >= 0) TEST_ERROR
+
+ gather_info.expect_dst_buf = expect_dst_buf;
+ gather_info.last_call = FALSE;
+ H5E_BEGIN_TRY {
+ ret = H5Dgather(sid, src_buf, H5T_NATIVE_INT, 1, dst_buf, gather_cb, &gather_info);
+ } H5E_END_TRY
+ if(ret >= 0) TEST_ERROR
+
+ gather_info.expect_dst_buf = expect_dst_buf;
+ gather_info.last_call = FALSE;
+ H5E_BEGIN_TRY {
+ ret = H5Dgather(sid, src_buf, H5T_NATIVE_INT, 6 * sizeof(dst_buf[0]), NULL, gather_cb, &gather_info);
+ } H5E_END_TRY
+ if(ret >= 0) TEST_ERROR
+
+ gather_info.expect_dst_buf = expect_dst_buf;
+ gather_info.last_call = FALSE;
+ H5E_BEGIN_TRY {
+ ret = H5Dgather(sid, src_buf, H5T_NATIVE_INT, 5 * sizeof(dst_buf[0]), dst_buf, NULL, &gather_info);
+ } H5E_END_TRY
+ if(ret >= 0) TEST_ERROR
+
+
+ /*
+ * Test callback returns failure
+ */
+ gather_info.expect_dst_buf = expect_dst_buf;
+ gather_info.last_call = FALSE;
+ H5E_BEGIN_TRY {
+ ret = H5Dgather(sid, src_buf, H5T_NATIVE_INT, 6 * sizeof(dst_buf[0]), dst_buf, gather_error_cb_fail, NULL);
+ } H5E_END_TRY
+ if(ret >= 0) TEST_ERROR
+
+
+ /* Close everything */
+ if(H5Sclose(sid) < 0) TEST_ERROR
+
+ PASSED();
+
+ return 0;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Sclose(sid);
+ } H5E_END_TRY;
+ return -1;
+} /* end test_gather_error() */
+
+
+/*-------------------------------------------------------------------------
* Function: main
*
* Purpose: Tests the dataset interface (H5D)
@@ -8386,6 +9408,12 @@ main(void)
/* Close 2nd FAPL */
if(H5Pclose(fapl2) < 0) TEST_ERROR
+ /* Tests that do not use files */
+ nerrors += (test_scatter() < 0 ? 1 : 0);
+ nerrors += (test_gather() < 0 ? 1 : 0);
+ nerrors += (test_scatter_error() < 0 ? 1 : 0);
+ nerrors += (test_gather_error() < 0 ? 1 : 0);
+
/* Verify symbol table messages are cached */
nerrors += (h5_verify_cached_stabs(FILENAME, fapl) < 0 ? 1 : 0);