summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAllen Byrne <byrn@hdfgroup.org>2019-06-18 17:12:24 (GMT)
committerAllen Byrne <byrn@hdfgroup.org>2019-06-18 17:12:24 (GMT)
commitd118a47a921fb8c545805dbd9ceea93bb487d9b6 (patch)
tree8749afede87172160e616346992c1607e26a26ca
parente7f16c6f2c7b031d7e9b4ba22a9fcdad4d258360 (diff)
parent712a2a13d8add828d053135a172abb2e819d59ad (diff)
downloadhdf5-d118a47a921fb8c545805dbd9ceea93bb487d9b6.zip
hdf5-d118a47a921fb8c545805dbd9ceea93bb487d9b6.tar.gz
hdf5-d118a47a921fb8c545805dbd9ceea93bb487d9b6.tar.bz2
Merging in latest from upstream (HDFFV/hdf5:refs/heads/develop)
* commit '712a2a13d8add828d053135a172abb2e819d59ad': Fixed a warning in H5CX.c concerning incorrect use of freeing VOL connector info. Add H5S_SEL_ITER_SHARE_WITH_DATASPACE selection iterator creation flag, to share dataspace's selection with iterator (and with caution about not modifying or closing the dataspace while the iterator is open). Fix misc. typos, etc. from code review New hyperslab selection routines and new public selection iterator routines.
-rw-r--r--fortran/src/H5Sf.c159
-rw-r--r--fortran/src/H5Sff.F90304
-rw-r--r--fortran/src/H5f90proto.h3
-rw-r--r--src/H5CX.c13
-rw-r--r--src/H5Ipublic.h1
-rw-r--r--src/H5S.c21
-rw-r--r--src/H5Shyper.c316
-rw-r--r--src/H5Spkg.h3
-rw-r--r--src/H5Spoint.c34
-rw-r--r--src/H5Spublic.h23
-rw-r--r--src/H5Sselect.c217
-rw-r--r--src/H5trace.c8
-rw-r--r--test/tselect.c748
13 files changed, 1829 insertions, 21 deletions
diff --git a/fortran/src/H5Sf.c b/fortran/src/H5Sf.c
index 8abea25..1031914 100644
--- a/fortran/src/H5Sf.c
+++ b/fortran/src/H5Sf.c
@@ -994,6 +994,165 @@ done:
return ret_value;
}
+/****if* H5Sf/h5scombine_hyperslab_c
+ * NAME
+ * h5scombine_hyperslab_c
+ * PURPOSE
+ * Call H5Scombine_hyperslab
+ * INPUTS
+ * space_id - identifier of the dataspace
+ * operator - defines how the new selection is combined
+ * start - offset of start of hyperslab
+ * count - number of blocks included in the hyperslab
+ * stride - hyperslab stride (interval between blocks)
+ * block - size of block in the hyperslab
+ * OUTPUTS
+ * hyper_id - identifier for the new dataspace
+ * RETURNS
+ * 0 on success, -1 on failure
+ * AUTHOR
+ * Elena Pourmal
+ * Monday, October 7, 2002
+ * HISTORY
+ *
+ * SOURCE
+*/
+
+int_f
+h5scombine_hyperslab_c ( hid_t_f *space_id , int_f *op, hsize_t_f *start, hsize_t_f *count, hsize_t_f *stride, hsize_t_f *block, hid_t_f *hyper_id)
+/******/
+{
+ int ret_value = -1;
+ hid_t c_space_id;
+ hid_t c_hyper_id;
+ hsize_t *c_start = NULL;
+ hsize_t *c_count = NULL;
+ hsize_t *c_stride = NULL;
+ hsize_t *c_block = NULL;
+
+ H5S_seloper_t c_op;
+ herr_t status;
+ int rank;
+ int i;
+
+ rank = H5Sget_simple_extent_ndims(*space_id);
+ if (rank < 0 ) return ret_value;
+ c_start = (hsize_t *)HDmalloc(sizeof(hsize_t)*rank);
+ if (c_start == NULL) goto DONE;
+
+ c_count = (hsize_t *)HDmalloc(sizeof(hsize_t)*rank);
+ if (c_count == NULL) goto DONE;
+
+ c_stride = (hsize_t *)HDmalloc(sizeof(hsize_t)*rank);
+ if (c_stride == NULL) goto DONE;
+
+ c_block = (hsize_t *)HDmalloc(sizeof(hsize_t)*rank);
+ if (c_block == NULL) goto DONE;
+
+
+ /*
+ * Reverse dimensions due to C-FORTRAN storage order.
+ */
+
+ for (i=0; i < rank; i++) {
+ int t= (rank - i) - 1;
+ c_start[i] = (hsize_t)start[t];
+ c_count[i] = (hsize_t)count[t];
+ c_stride[i] = (hsize_t)stride[t];
+ c_block[i] = (hsize_t)block[t];
+ }
+
+ c_op = (H5S_seloper_t)*op;
+
+ c_space_id = (hid_t)*space_id;
+ c_hyper_id = H5Scombine_hyperslab(c_space_id, c_op, c_start, c_stride, c_count, c_block);
+ if ( c_hyper_id < 0 ) goto DONE;
+ *hyper_id = (hid_t_f)c_hyper_id;
+ ret_value = 0;
+DONE:
+ if(c_start != NULL) HDfree(c_start);
+ if(c_count != NULL) HDfree(c_count);
+ if(c_stride!= NULL) HDfree(c_stride);
+ if(c_block != NULL) HDfree(c_block);
+ return ret_value;
+}
+/****if* H5Sf/h5scombine_select_c
+ * NAME
+ * h5scombine_select_c
+ * PURPOSE
+ * Call H5Scombine_ select
+ * INPUTS
+ * space1_id - identifier of the first dataspace
+ * operator - defines how the new selection is combined
+ * space2_id - identifier of the second dataspace
+ * OUTPUTS
+ * ds_id - identifier for the new dataspace
+ * RETURNS
+ * 0 on success, -1 on failure
+ * AUTHOR
+ * Elena Pourmal
+ * Monday, October 7, 2002
+ * HISTORY
+ *
+ * SOURCE
+*/
+
+int_f
+h5scombine_select_c ( hid_t_f *space1_id , int_f *op, hid_t_f *space2_id, hid_t_f *ds_id)
+/******/
+{
+ int ret_value = -1;
+ hid_t c_space1_id;
+ hid_t c_space2_id;
+ hid_t c_ds_id;
+ H5S_seloper_t c_op;
+
+ c_op = (H5S_seloper_t)*op;
+
+ c_space1_id = (hid_t)*space1_id;
+ c_space2_id = (hid_t)*space2_id;
+ c_ds_id = H5Scombine_select(c_space1_id, c_op, c_space2_id);
+ if ( c_ds_id < 0 ) return ret_value;
+ *ds_id = (hid_t_f)c_ds_id;
+ ret_value = 0;
+ return ret_value;
+}
+/****if* H5Sf/h5smodify_select_c
+ * NAME
+ * h5smodify_select_c
+ * PURPOSE
+ * Call H5Smodify_select
+ * INPUTS
+ * space1_id - identifier of the first dataspace to modify
+ * operator - defines how the new selection is combined
+ * space2_id - identifier of the second dataspace
+ * RETURNS
+ * 0 on success, -1 on failure
+ * AUTHOR
+ * Elena Pourmal
+ * Monday, October 7, 2002
+ * HISTORY
+ *
+ * SOURCE
+*/
+
+int_f
+h5smodify_select_c ( hid_t_f *space1_id , int_f *op, hid_t_f *space2_id)
+/******/
+{
+ int ret_value = -1;
+ hid_t c_space1_id;
+ hid_t c_space2_id;
+ H5S_seloper_t c_op;
+
+ c_op = (H5S_seloper_t)*op;
+
+ c_space1_id = (hid_t)*space1_id;
+ c_space2_id = (hid_t)*space2_id;
+ if( H5Smodify_select(c_space1_id, c_op, c_space2_id)< 0) return ret_value;
+ ret_value = 0;
+ return ret_value;
+}
/****if* H5Sf/h5sget_select_type_c
* NAME
diff --git a/fortran/src/H5Sff.F90 b/fortran/src/H5Sff.F90
index bd3dcf4..e6f8e4c 100644
--- a/fortran/src/H5Sff.F90
+++ b/fortran/src/H5Sff.F90
@@ -1275,6 +1275,310 @@ CONTAINS
DEALLOCATE(def_stride)
END SUBROUTINE h5sselect_hyperslab_f
+! !$!
+! !$!****s* H5S/h5scombine_hyperslab_f
+! !$!
+! !$! NAME
+! !$! h5scombine_hyperslab_f
+! !$!
+! !$! PURPOSE
+! !$! Combine a hyperslab selection with the current
+! !$! selection for a dataspace
+! !$!
+! !$! INPUTS
+! !$! space_id - dataspace of selection to use
+! !$! operator - flag, valid values are:
+! !$! H5S_SELECT_NOOP_F
+! !$! H5S_SELECT_SET_F
+! !$! H5S_SELECT_OR_F
+! !$! H5S_SELECT_AND_F
+! !$! H5S_SELECT_XOR_F
+! !$! H5S_SELECT_NOTB_F
+! !$! H5S_SELECT_NOTA_F
+! !$! H5S_SELECT_APPEND_F
+! !$! H5S_SELECT_PREPEND_F
+! !$! start - array with hyperslab offsets
+! !$! count - number of blocks included in the
+! !$! hyperslab
+! !$! OUTPUTS
+! !$! hyper_id - identifier for the new hyperslab
+! !$! hdferr: - error code
+! !$! Success: 0
+! !$! Failure: -1
+! !$! OPTIONAL PARAMETERS
+! !$! stride - array with hyperslab strides
+! !$! block - array with hyperslab block sizes
+! !$!
+! !$! AUTHOR
+! !$! Elena Pourmal
+! !$! October 7, 2002
+! !$!
+! !$! HISTORY
+! !$!
+! !$!
+! !$! NOTES
+! !$! Commented out until 1.6 ? 10/08/2002
+! !$!
+! !$! SOURCE
+! SUBROUTINE h5scombine_hyperslab_f(space_id, operator, start, count, &
+! hyper_id, hdferr, stride, block)
+! IMPLICIT NONE
+! INTEGER(HID_T), INTENT(IN) :: space_id ! Dataspace identifier
+! INTEGER, INTENT(IN) :: operator ! Flag, valid values are:
+ ! H5S_SELECT_NOOP_F
+ ! H5S_SELECT_SET_F
+ ! H5S_SELECT_OR_F
+ ! H5S_SELECT_AND_F
+ ! H5S_SELECT_XOR_F
+ ! H5S_SELECT_NOTB_F
+ ! H5S_SELECT_NOTA_F
+ ! H5S_SELECT_APPEND_F
+ ! H5S_SELECT_PREPEND_F
+ !
+! INTEGER(HSIZE_T), DIMENSION(*), INTENT(IN) :: start
+ ! Starting coordinates of the hyperslab
+! INTEGER(HSIZE_T), DIMENSION(*), INTENT(IN) :: count
+ ! Number of blocks to select
+ ! from dataspace
+! INTEGER(HID_T), INTENT(OUT) :: hyper_id ! New hyperslab identifier
+! INTEGER, INTENT(OUT) :: hdferr ! Error code
+! INTEGER(HSIZE_T), DIMENSION(:), OPTIONAL, INTENT(IN) :: stride
+ ! Array of how many elements to move
+ ! in each direction
+! INTEGER(HSIZE_T), DIMENSION(:), OPTIONAL, INTENT(IN) :: block
+ ! Sizes of element block
+! INTEGER(HSIZE_T), DIMENSION(:), ALLOCATABLE :: def_block
+! INTEGER(HSIZE_T), DIMENSION(:), ALLOCATABLE :: def_stride
+! INTEGER :: rank
+! INTEGER :: error1, error2
+
+! INTERFACE
+! INTEGER FUNCTION h5scombine_hyperslab_c(space_id, operator, &
+! start, count, stride, block, hyper_id)
+! USE H5GLOBAL
+! !DEC$IF DEFINED(HDF5F90_WINDOWS)
+! !DEC$ATTRIBUTES C,reference,decorate,alias:'H5SCOMBINE_HYPERSLAB_C'::h5scombine_hyperslab_c
+! !DEC$ENDIF
+! INTEGER(HID_T), INTENT(IN) :: space_id
+! INTEGER, INTENT(IN) :: operator
+! INTEGER(HSIZE_T), DIMENSION(*), INTENT(IN) :: start
+! INTEGER(HSIZE_T), DIMENSION(*), INTENT(IN) :: count
+! INTEGER(HSIZE_T), DIMENSION(*), OPTIONAL, INTENT(IN) :: stride
+! INTEGER(HSIZE_T), DIMENSION(*), OPTIONAL, INTENT(IN) :: block
+! INTEGER(HID_T), INTENT(OUT) :: hyper_id
+! END FUNCTION h5scombine_hyperslab_c
+! END INTERFACE
+
+! if (present(stride).and. present(block)) then
+! hdferr = h5scombine_hyperslab_c(space_id, operator, start, count, &
+! stride, block, hyper_id)
+! return
+! endif
+ ! Case of optional parameters.
+ !
+ ! Find the rank of the dataspace to allocate memory for
+ ! default stride and block arrays.
+ !
+! CALL h5sget_simple_extent_ndims_f(space_id, rank, hdferr)
+! if( hdferr .EQ. -1) return
+ !
+! if (present(stride).and. .not.present(block)) then
+! allocate(def_block(rank), stat=error1)
+! if (error1.NE.0) then
+! hdferr = -1
+! return
+! endif
+! def_block = 1
+! hdferr = h5scombine_hyperslab_c(space_id, operator, start, count, &
+! stride, def_block, hyper_id)
+! deallocate(def_block)
+! return
+! endif
+
+! if (.not.present(stride).and. present(block)) then
+! allocate(def_stride(rank), stat=error2)
+! if (error2.NE.0) then
+! hdferr = -1
+! return
+! endif
+! def_stride = 1
+! hdferr = h5scombine_hyperslab_c(space_id, operator, start, count, &
+! def_stride, block, hyper_id)
+! deallocate(def_stride)
+! return
+! endif
+! allocate(def_block(rank), stat=error1)
+! allocate(def_stride(rank), stat=error2)
+! if ((error1.NE.0) .OR. (error2.NE.0)) then
+! hdferr = -1
+! return
+! endif
+! def_block = 1
+! def_stride = 1
+! hdferr = h5scombine_hyperslab_c(space_id, operator, start, count, &
+! def_stride, def_block, hyper_id)
+! deallocate(def_block)
+! deallocate(def_stride)
+
+! END SUBROUTINE h5scombine_hyperslab_f
+
+! !$!
+! !$!****s* H5S/
+! !$!
+! !$! NAME
+! !$! h5scombine_select_f
+! !$!
+! !$! PURPOSE
+! !$! Combine two hyperslab selections with an operation
+! !$! and return a dataspace with resulting selection.
+! !$!
+! !$! INPUTS
+! !$! space1_id - dataspace of selection to use
+! !$! operator - flag, valid values are:
+! !$! H5S_SELECT_NOOP_F
+! !$! H5S_SELECT_SET_F
+! !$! H5S_SELECT_OR_F
+! !$! H5S_SELECT_AND_F
+! !$! H5S_SELECT_XOR_F
+! !$! H5S_SELECT_NOTB_F
+! !$! H5S_SELECT_NOTA_F
+! !$! H5S_SELECT_APPEND_F
+! !$! H5S_SELECT_PREPEND_F
+! !$! space2_id - dataspace of selection to use
+! !$! OUTPUTS
+! !$! ds_id - idataspace identifier with the new selection
+! !$! hdferr: - error code
+! !$! Success: 0
+! !$! Failure: -1
+! !$! OPTIONAL PARAMETERS - NONE
+! !$!
+! !$! AUTHOR
+! !$! Elena Pourmal
+! !$! October 7, 2002
+! !$!
+! !$! HISTORY
+! !$!
+! !$!
+! !$! NOTES commented out until 1.6 release(?) 10/08/2002
+! !$!
+
+! ! SOURCE
+! !$ SUBROUTINE h5scombine_select_f(space1_id, operator, space2_id, &
+! ds_id, hdferr)
+! IMPLICIT NONE
+! INTEGER(HID_T), INTENT(IN) :: space1_id ! First dataspace identifier
+! INTEGER(HID_T), INTENT(IN) :: space2_id ! Second dataspace identifier
+! INTEGER, INTENT(IN) :: operator ! Flag, valid values are:
+ ! H5S_SELECT_NOOP_F
+ ! H5S_SELECT_SET_F
+ ! H5S_SELECT_OR_F
+ ! H5S_SELECT_AND_F
+ ! H5S_SELECT_XOR_F
+ ! H5S_SELECT_NOTB_F
+ ! H5S_SELECT_NOTA_F
+ ! H5S_SELECT_APPEND_F
+ ! H5S_SELECT_PREPEND_F
+ !
+! INTEGER(HID_T), INTENT(OUT) :: ds_id ! New dataspace identifier
+! INTEGER, INTENT(OUT) :: hdferr ! Error code
+!
+! INTERFACE
+! INTEGER FUNCTION h5scombine_select_c(space1_id, operator, &
+! space2_id, ds_id)
+! USE H5GLOBAL
+! !DEC$IF DEFINED(HDF5F90_WINDOWS)
+! !DEC$ATTRIBUTES C,reference,decorate,alias:'H5SCOMBINE_SELECT_C'::h5scombine_select_c
+! !DEC$ENDIF
+! INTEGER(HID_T), INTENT(IN) :: space1_id
+! INTEGER(HID_T), INTENT(IN) :: space2_id
+! INTEGER, INTENT(IN) :: operator
+! INTEGER(HID_T), INTENT(OUT) :: ds_id
+! END FUNCTION h5scombine_select_c
+! END INTERFACE
+
+! hdferr = h5scombine_select_c(space1_id, operator, space2_id, &
+! ds_id)
+! return
+
+! END SUBROUTINE h5scombine_select_f
+
+! !$!
+! !$!****s* H5S/
+! !$!
+! !$! NAME
+! !$! h5smodify_select_f
+! !$!
+! !$! PURPOSE
+! !$! Refine a hyperslab selection with an operation
+! !$! using second hyperslab
+! !$!
+! !$! INPUTS
+! !$! space1_id - dataspace of selection to modify
+! !$! operator - flag, valid values are:
+! !$! H5S_SELECT_NOOP_F
+! !$! H5S_SELECT_SET_F
+! !$! H5S_SELECT_OR_F
+! !$! H5S_SELECT_AND_F
+! !$! H5S_SELECT_XOR_F
+! !$! H5S_SELECT_NOTB_F
+! !$! H5S_SELECT_NOTA_F
+! !$! H5S_SELECT_APPEND_F
+! !$! H5S_SELECT_PREPEND_F
+! !$! space2_id - dataspace of selection to use
+! !$!
+! !$! OUTPUTS
+! !$! hdferr: - error code
+! !$! Success: 0
+! !$! Failure: -1
+! !$! OPTIONAL PARAMETERS - NONE
+! !$!
+! !$! AUTHOR
+! !$! Elena Pourmal
+! !$! October 7, 2002
+! !$!
+! !$! HISTORY
+! !$!
+! !$!
+! !$! NOTESCommented out until 1.6 release(?) 10/08/2002 EIP
+! !$!
+
+! ! SOURCE
+! SUBROUTINE h5smodify_select_f(space1_id, operator, space2_id, &
+! hdferr)
+! IMPLICIT NONE
+! INTEGER(HID_T), INTENT(INOUT) :: space1_id ! Dataspace identifier to
+ ! modify
+! INTEGER(HID_T), INTENT(IN) :: space2_id ! Second dataspace identifier
+! INTEGER, INTENT(IN) :: operator ! Flag, valid values are:
+ ! H5S_SELECT_NOOP_F
+ ! H5S_SELECT_SET_F
+ ! H5S_SELECT_OR_F
+ ! H5S_SELECT_AND_F
+ ! H5S_SELECT_XOR_F
+ ! H5S_SELECT_NOTB_F
+ ! H5S_SELECT_NOTA_F
+ ! H5S_SELECT_APPEND_F
+ ! H5S_SELECT_PREPEND_F
+ !
+! INTEGER, INTENT(OUT) :: hdferr ! Error code
+
+! INTERFACE
+! INTEGER FUNCTION h5smodify_select_c(space1_id, operator, &
+! space2_id)
+! USE H5GLOBAL
+! !DEC$IF DEFINED(HDF5F90_WINDOWS)
+! !DEC$ATTRIBUTES C,reference,decorate,alias:'H5SMODIFY_SELECT_C'::h5smodify_select_c
+! !DEC$ENDIF
+! INTEGER(HID_T), INTENT(INOUT) :: space1_id
+! INTEGER(HID_T), INTENT(IN) :: space2_id
+! INTEGER, INTENT(IN) :: operator
+! END FUNCTION h5smodify_select_c
+! END INTERFACE
+
+! hdferr = h5smodify_select_c(space1_id, operator, space2_id)
+! return
+
+! END SUBROUTINE h5smodify_select_f
!
!****s* H5S/h5sget_select_type_f
diff --git a/fortran/src/H5f90proto.h b/fortran/src/H5f90proto.h
index b357715..5faf4b4 100644
--- a/fortran/src/H5f90proto.h
+++ b/fortran/src/H5f90proto.h
@@ -121,6 +121,9 @@ H5_FCDLL int_f h5sset_extent_none_c( hid_t_f *space_id );
H5_FCDLL int_f h5sselect_hyperslab_c( hid_t_f *space_id , int_f *op, hsize_t_f *start, hsize_t_f *count, hsize_t_f *stride, hsize_t_f *block);
H5_FCDLL int_f h5sget_select_type_c( hid_t_f *space_id , int_f *op);
H5_FCDLL int_f h5sselect_elements_c( hid_t_f *space_id , int_f *op, size_t_f *nelements, hsize_t_f *coord);
+H5_FCDLL int_f h5scombine_hyperslab_c( hid_t_f *space_id , int_f *op, hsize_t_f *start, hsize_t_f *count, hsize_t_f *stride, hsize_t_f *block, hid_t_f *hyper_id);
+H5_FCDLL int_f h5scombine_select_c( hid_t_f *space1_id , int_f *op, hid_t_f *space2_id, hid_t_f *ds_id);
+H5_FCDLL int_f h5smodify_select_c( hid_t_f *space1_id , int_f *op, hid_t_f *space2_id);
H5_FCDLL int_f h5sdecode_c( _fcd buf, hid_t_f *obj_id );
H5_FCDLL int_f h5sencode_c(_fcd buf, hid_t_f *obj_id, size_t_f *nalloc, hid_t_f *fapl_id );
H5_FCDLL int_f h5sextent_equal_c( hid_t_f * space1_id, hid_t_f *space2_id, hid_t_f *c_equal);
diff --git a/src/H5CX.c b/src/H5CX.c
index 5474b63..22ed893 100644
--- a/src/H5CX.c
+++ b/src/H5CX.c
@@ -982,18 +982,9 @@ H5CX_free_state(H5CX_state_t *api_state)
/* Release the VOL connector property, if it was set */
if(api_state->vol_connector_prop.connector_id) {
/* Clean up any VOL connector info */
- if(api_state->vol_connector_prop.connector_info) {
- H5VL_class_t *connector; /* Pointer to connector */
-
- /* Retrieve the connector for the ID */
- if(NULL == (connector = (H5VL_class_t *)H5I_object(api_state->vol_connector_prop.connector_id)))
- HGOTO_ERROR(H5E_CONTEXT, H5E_BADTYPE, FAIL, "not a VOL connector ID")
-
- /* Free the connector info */
- if(H5VL_free_connector_info(connector, api_state->vol_connector_prop.connector_info) < 0)
+ if(api_state->vol_connector_prop.connector_info)
+ if(H5VL_free_connector_info(api_state->vol_connector_prop.connector_id, api_state->vol_connector_prop.connector_info) < 0)
HGOTO_ERROR(H5E_CONTEXT, H5E_CANTRELEASE, FAIL, "unable to release VOL connector info object")
- } /* end if */
-
/* Decrement connector ID */
if(H5I_dec_ref(api_state->vol_connector_prop.connector_id) < 0)
HDONE_ERROR(H5E_CONTEXT, H5E_CANTDEC, FAIL, "can't close VOL connector ID")
diff --git a/src/H5Ipublic.h b/src/H5Ipublic.h
index 56873ec..def785f 100644
--- a/src/H5Ipublic.h
+++ b/src/H5Ipublic.h
@@ -46,6 +46,7 @@ typedef enum H5I_type_t {
H5I_ERROR_CLASS, /* type ID for error classes */
H5I_ERROR_MSG, /* type ID for error messages */
H5I_ERROR_STACK, /* type ID for error stacks */
+ H5I_SPACE_SEL_ITER, /* type ID for dataspace selection iterator */
H5I_NTYPES /* number of library types, MUST BE LAST! */
} H5I_type_t;
diff --git a/src/H5S.c b/src/H5S.c
index e50985f..5153045 100644
--- a/src/H5S.c
+++ b/src/H5S.c
@@ -93,6 +93,14 @@ static const H5I_class_t H5I_DATASPACE_CLS[1] = {{
(H5I_free_t)H5S_close /* Callback routine for closing objects of this class */
}};
+/* Dataspace selection iterator ID class */
+static const H5I_class_t H5I_SPACE_SEL_ITER_CLS[1] = {{
+ H5I_SPACE_SEL_ITER, /* ID class value */
+ 0, /* Class flags */
+ 0, /* # of reserved IDs for class */
+ (H5I_free_t)H5S_sel_iter_close /* Callback routine for closing objects of this class */
+}};
+
/* Flag indicating "top" of interface has been initialized */
static hbool_t H5S_top_package_initialize_s = FALSE;
@@ -120,6 +128,10 @@ H5S__init_package(void)
if(H5I_register_type(H5I_DATASPACE_CLS) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize dataspace ID class")
+ /* Initialize the atom group for the dataspace selction iterator IDs */
+ if(H5I_register_type(H5I_SPACE_SEL_ITER_CLS) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize dataspace selection iterator ID class")
+
/* Mark "top" of interface as initialized, too */
H5S_top_package_initialize_s = TRUE;
@@ -159,6 +171,11 @@ H5S_top_term_package(void)
n++; /*H5I*/
} /* end if */
+ if(H5I_nmembers(H5I_SPACE_SEL_ITER) > 0) {
+ (void)H5I_clear_type(H5I_SPACE_SEL_ITER, FALSE, FALSE);
+ n++; /*H5I*/
+ } /* end if */
+
/* Mark "top" of interface as closed */
if(0 == n)
H5S_top_package_initialize_s = FALSE;
@@ -198,11 +215,15 @@ H5S_term_package(void)
if(H5_PKG_INIT_VAR) {
/* Sanity checks */
HDassert(0 == H5I_nmembers(H5I_DATASPACE));
+ HDassert(0 == H5I_nmembers(H5I_SPACE_SEL_ITER));
HDassert(FALSE == H5S_top_package_initialize_s);
/* Destroy the dataspace object id group */
n += (H5I_dec_type_ref(H5I_DATASPACE) > 0);
+ /* Destroy the dataspace selection iterator object id group */
+ n += (H5I_dec_type_ref(H5I_SPACE_SEL_ITER) > 0);
+
/* Mark interface as closed */
if(0 == n)
H5_PKG_INIT_VAR = FALSE;
diff --git a/src/H5Shyper.c b/src/H5Shyper.c
index 63f457b..6df368d 100644
--- a/src/H5Shyper.c
+++ b/src/H5Shyper.c
@@ -726,10 +726,27 @@ H5S__hyper_iter_init(const H5S_t *space, H5S_sel_iter_t *iter)
else { /* Initialize the information needed for non-regular hyperslab I/O */
H5S_hyper_span_info_t *spans; /* Pointer to hyperslab span info node */
- /* Share the source dataspace's span tree by incrementing the reference count on it */
- HDassert(space->select.sel_info.hslab->span_lst);
- iter->u.hyp.spans = space->select.sel_info.hslab->span_lst;
- iter->u.hyp.spans->count++;
+ /* If this iterator is created from an API call, by default we clone the
+ * selection now, as the dataspace could be modified or go out of scope.
+ *
+ * However, if the H5S_SEL_ITER_SHARE_WITH_DATASPACE flag is given,
+ * the selection is shared between the selection iterator and the
+ * dataspace. In this case, the application _must_not_ modify or
+ * close the dataspace that the iterator is operating on, or undefined
+ * behavior will occur.
+ */
+ if((iter->flags & H5S_SEL_ITER_API_CALL) &&
+ !(iter->flags & H5S_SEL_ITER_SHARE_WITH_DATASPACE)) {
+ /* Copy the span tree */
+ if(NULL == (iter->u.hyp.spans = H5S__hyper_copy_span(space->select.sel_info.hslab->span_lst, space->extent.rank)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy span tree")
+ } /* end if */
+ else {
+ /* Share the source dataspace's span tree by incrementing the reference count on it */
+ HDassert(space->select.sel_info.hslab->span_lst);
+ iter->u.hyp.spans = space->select.sel_info.hslab->span_lst;
+ iter->u.hyp.spans->count++;
+ } /* end else */
/* Initialize the starting span_info's and spans */
spans = iter->u.hyp.spans;
@@ -3431,7 +3448,7 @@ H5S__get_select_hyper_nblocks(const H5S_t *space, hbool_t app_ref)
/* Check each dimension */
for(ret_value = 1, u = 0; u < space->extent.rank; u++)
ret_value *= (app_ref ? space->select.sel_info.hslab->diminfo.app[u].count :
- space->select.sel_info.hslab->diminfo.opt[u].count);
+ space->select.sel_info.hslab->diminfo.opt[u].count);
} /* end if */
else
ret_value = H5S__hyper_span_nblocks(space->select.sel_info.hslab->span_lst);
@@ -10408,6 +10425,213 @@ done:
} /* end H5S__fill_in_select() */
+/*--------------------------------------------------------------------------
+ NAME
+ H5Scombine_hyperslab
+ PURPOSE
+ Specify a hyperslab to combine with the current hyperslab selection and
+ return a new dataspace with the combined selection as the selection in the
+ new dataspace.
+ USAGE
+ hid_t H5Scombine_hyperslab(dsid, op, start, stride, count, block)
+ hid_t dsid; IN: Dataspace ID of selection to use
+ H5S_seloper_t op; IN: Operation to perform on current selection
+ const hsize_t *start; IN: Offset of start of hyperslab
+ const hsize_t *stride; IN: Hyperslab stride
+ const hsize_t *count; IN: Number of blocks included in hyperslab
+ const hsize_t *block; IN: Size of block in hyperslab
+ RETURNS
+ Dataspace ID on success / H5I_INVALID_HID on failure
+ DESCRIPTION
+ Combines a hyperslab selection with the current selection for a dataspace,
+ creating a new dataspace to return the generated selection.
+ If the current selection is not a hyperslab, it is freed and the hyperslab
+ parameters passed in are combined with the H5S_SEL_ALL hyperslab (ie. a
+ selection composing the entire current extent). If STRIDE or BLOCK is
+ NULL, they are assumed to be set to all '1'.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+hid_t
+H5Scombine_hyperslab(hid_t space_id, H5S_seloper_t op, const hsize_t start[],
+ const hsize_t stride[], const hsize_t count[], const hsize_t block[])
+{
+ H5S_t *space; /* Dataspace to modify selection of */
+ H5S_t *new_space = NULL; /* New dataspace created */
+ hid_t ret_value; /* Return value */
+
+ FUNC_ENTER_API(H5I_INVALID_HID)
+ H5TRACE6("i", "iSs*h*h*h*h", space_id, op, start, stride, count, block);
+
+ /* Check args */
+ if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace")
+ if(start == NULL || count == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "hyperslab not specified")
+ if(!(op >= H5S_SELECT_SET && op <= H5S_SELECT_NOTA))
+ HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, H5I_INVALID_HID, "invalid selection operation")
+
+ /* Generate new space, with combination of selections */
+ if(H5S_combine_hyperslab(space, op, start, stride, count, block, &new_space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, H5I_INVALID_HID, "unable to set hyperslab selection")
+
+ /* Atomize */
+ if((ret_value = H5I_register(H5I_DATASPACE, new_space, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace atom")
+
+done:
+ if(ret_value < 0 && new_space)
+ H5S_close(new_space);
+
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Scombine_hyperslab() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5S__combine_select
+ *
+ * Purpose: Internal version of H5Scombine_select().
+ *
+ * Return: New dataspace on success/NULL on failure
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, October 30, 2001
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5S_t *
+H5S__combine_select(H5S_t *space1, H5S_seloper_t op, H5S_t *space2)
+{
+ H5S_t *new_space = NULL; /* New dataspace generated */
+ H5S_t *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check args */
+ HDassert(space1);
+ HDassert(space2);
+ HDassert(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA);
+
+ /* Check if space1 selections has span trees */
+ if(NULL == space1->select.sel_info.hslab->span_lst)
+ if(H5S__hyper_generate_spans(space1) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, NULL, "dataspace does not have span tree")
+
+ if(NULL == space2->select.sel_info.hslab->span_lst) {
+ hsize_t tmp_start[H5S_MAX_RANK];
+ hsize_t tmp_stride[H5S_MAX_RANK];
+ hsize_t tmp_count[H5S_MAX_RANK];
+ hsize_t tmp_block[H5S_MAX_RANK];
+ unsigned u;
+
+ for(u = 0; u < space2->extent.rank; u++) {
+ tmp_start[u] = space2->select.sel_info.hslab->diminfo.opt[u].start;
+ tmp_stride[u] = space2->select.sel_info.hslab->diminfo.opt[u].stride;
+ tmp_count[u] = space2->select.sel_info.hslab->diminfo.opt[u].count;
+ tmp_block[u] = space2->select.sel_info.hslab->diminfo.opt[u].block;
+ } /* end for */
+
+ /* Combine hyperslab selection with regular selection directly */
+ if(H5S_combine_hyperslab(space1, op, tmp_start, tmp_stride, tmp_count, tmp_block, &new_space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, NULL, "unable to set hyperslab selection")
+ } /* end if */
+ else{
+ /* Combine new_space (a copy of space 1) & space2, with the result in new_space */
+ if(H5S__fill_in_select(space1, op, space2, &new_space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, NULL, "can't clip hyperslab information")
+ } /* end else */
+
+ /* Set unlim_dim */
+ new_space->select.sel_info.hslab->unlim_dim = -1;
+
+ /* Set return value */
+ ret_value = new_space;
+
+done:
+ if(ret_value == NULL && new_space)
+ H5S_close(new_space);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S__combine_select() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Scombine_select
+ PURPOSE
+ Combine two hyperslab selections with an operation, returning a dataspace
+ with the resulting selection.
+ USAGE
+ hid_t H5Scombine_select(space1, op, space2)
+ hid_t space1; IN: First Dataspace ID
+ H5S_seloper_t op; IN: Selection operation
+ hid_t space2; IN: Second Dataspace ID
+ RETURNS
+ Dataspace ID on success / H5I_INVALID_HID on failure
+ DESCRIPTION
+ Combine two existing hyperslab selections with an operation, returning
+ a new dataspace with the resulting selection. The dataspace extent from
+ space1 is copied for the dataspace extent of the newly created dataspace.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+hid_t
+H5Scombine_select(hid_t space1_id, H5S_seloper_t op, hid_t space2_id)
+{
+ H5S_t *space1; /* First Dataspace */
+ H5S_t *space2; /* Second Dataspace */
+ H5S_t *new_space = NULL; /* New Dataspace */
+ hid_t ret_value; /* Return value */
+
+ FUNC_ENTER_API(H5I_INVALID_HID)
+ H5TRACE3("i", "iSsi", space1_id, op, space2_id);
+
+ /* Check args */
+ if(NULL == (space1 = (H5S_t *)H5I_object_verify(space1_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace")
+ if(NULL == (space2 = (H5S_t *)H5I_object_verify(space2_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace")
+ if(!(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA))
+ HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, H5I_INVALID_HID, "invalid selection operation")
+
+ /* Check that both dataspaces have the same rank */
+ if(space1->extent.rank != space2->extent.rank)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "dataspaces not same rank")
+
+ /* Note: currently, the offset of each dataspace is ignored */
+#if 0
+ /* Check that both dataspaces have the same offset */
+ /* Same note as in H5Smodify_select */
+ for(u=0; u<space1->extent.rank; u++) {
+ if(space1->select.offset[u] != space2->select.offset[u])
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "dataspaces not same offset")
+ } /* end for */
+#endif
+
+ /* Check that both dataspaces have hyperslab selections */
+ if(H5S_GET_SELECT_TYPE(space1) != H5S_SEL_HYPERSLABS || H5S_GET_SELECT_TYPE(space2) != H5S_SEL_HYPERSLABS)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "dataspaces don't have hyperslab selections")
+
+ /* Go combine the dataspaces */
+ if(NULL == (new_space = H5S__combine_select(space1, op, space2)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, H5I_INVALID_HID, "unable to create hyperslab selection")
+
+ /* Atomize */
+ if((ret_value = H5I_register(H5I_DATASPACE, new_space, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace atom")
+
+done:
+ if(ret_value < 0 && new_space)
+ H5S_close(new_space);
+
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Scombine_select() */
+
+
/*-------------------------------------------------------------------------
* Function: H5S__modify_select
*
@@ -10470,6 +10694,88 @@ done:
/*--------------------------------------------------------------------------
NAME
+ H5Smodify_select
+ PURPOSE
+ Refine a hyperslab selection with an operation using a second hyperslab
+ to modify it
+ USAGE
+ herr_t H5Smodify_select(space1, op, space2)
+ hid_t space1; IN/OUT: First Dataspace ID
+ H5S_seloper_t op; IN: Selection operation
+ hid_t space2; IN: Second Dataspace ID
+ RETURNS
+ Non-negative on success/Negative on failure
+ DESCRIPTION
+ Refine an existing hyperslab selection with an operation, using a second
+ hyperslab. The first selection is modified to contain the result of
+ space1 operated on by space2.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5Smodify_select(hid_t space1_id, H5S_seloper_t op, hid_t space2_id)
+{
+ H5S_t *space1; /* First Dataspace */
+ H5S_t *space2; /* Second Dataspace */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE3("e", "iSsi", space1_id, op, space2_id);
+
+ /* Check args */
+ if(NULL == (space1 = (H5S_t *)H5I_object_verify(space1_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
+ if(NULL == (space2 = (H5S_t *)H5I_object_verify(space2_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
+ if(!(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA))
+ HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation")
+
+ /* Check that both dataspaces have the same rank */
+ if(space1->extent.rank != space2->extent.rank)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspaces not same rank")
+
+ /* Check that both dataspaces have the same offset */
+ /** Note that this is a tricky part of this function. It's
+ * possible that two dataspaces have different "offset". If the
+ * space2 has smaller offset value than that of space1 in a
+ * dimension, then the span elements of this dimension in
+ * space2 could have negative "low" and "high" values relative
+ * to the offset in space1. In other words, if the bounds of
+ * span elements in space2 are adjusted relative to the offset
+ * in space1, then every span element's bound is computed as
+ * "origin_bound+offset2-offset1". Therefore, if offset2 (the
+ * offset of space2) is smaller, then
+ * "origin_bound+offset2-offset1" could be negative which is
+ * not allowed by the bound type declaration as hsize_t!
+ * As a result, if the op is an OR selection, then the final
+ * result may contain span elements that have negative bound!
+ * So right now, the difference in the offset is totally
+ * ignored!!
+ */
+#if 0
+ for(u=0; u<space1->extent.rank; u++) {
+ if(space1->select.offset[u] != space2->select.offset[u])
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspaces not same offset")
+ } /* end for */
+#endif
+
+ /* Check that both dataspaces have hyperslab selections */
+ if(H5S_GET_SELECT_TYPE(space1) != H5S_SEL_HYPERSLABS || H5S_GET_SELECT_TYPE(space2) != H5S_SEL_HYPERSLABS)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspaces don't have hyperslab selections")
+
+ /* Go refine the first selection */
+ if(H5S__modify_select(space1, op, space2) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to modify hyperslab selection")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Smodify_select() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5S__hyper_proj_int_build_proj
PURPOSE
Secondary iteration routine for H5S__hyper_project_intersection
diff --git a/src/H5Spkg.h b/src/H5Spkg.h
index 93114bd..4752c59 100644
--- a/src/H5Spkg.h
+++ b/src/H5Spkg.h
@@ -70,6 +70,9 @@
/* Length of stack-allocated sequences for "project intersect" routines */
#define H5S_PROJECT_INTERSECT_NSEQS 256
+/* Internal flags for initializing selection iterators */
+#define H5S_SEL_ITER_API_CALL 0x1000 /* Selection iterator created from API call */
+
/* Initial version of the dataspace information */
#define H5O_SDSPACE_VERSION_1 1
diff --git a/src/H5Spoint.c b/src/H5Spoint.c
index 445566a..875c018 100644
--- a/src/H5Spoint.c
+++ b/src/H5Spoint.c
@@ -180,14 +180,32 @@ H5FL_DEFINE_STATIC(H5S_pnt_list_t);
static herr_t
H5S__point_iter_init(const H5S_t *space, H5S_sel_iter_t *iter)
{
- FUNC_ENTER_STATIC_NOERR
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
/* Check args */
HDassert(space && H5S_SEL_POINTS == H5S_GET_SELECT_TYPE(space));
HDassert(iter);
- /* Share point list for internal iterations */
- iter->u.pnt.pnt_lst = space->select.sel_info.pnt_lst;
+ /* If this iterator is created from an API call, by default we clone the
+ * selection now, as the dataspace could be modified or go out of scope.
+ *
+ * However, if the H5S_SEL_ITER_SHARE_WITH_DATASPACE flag is given,
+ * the selection is shared between the selection iterator and the
+ * dataspace. In this case, the application _must_not_ modify or
+ * close the dataspace that the iterator is operating on, or undefined
+ * behavior will occur.
+ */
+ if((iter->flags & H5S_SEL_ITER_API_CALL) &&
+ !(iter->flags & H5S_SEL_ITER_SHARE_WITH_DATASPACE)) {
+ /* Copy the point list */
+ if(NULL == (iter->u.pnt.pnt_lst = H5S__copy_pnt_list(space->select.sel_info.pnt_lst, space->extent.rank)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy point list")
+ } /* end if */
+ else
+ /* OK to share point list for internal iterations */
+ iter->u.pnt.pnt_lst = space->select.sel_info.pnt_lst;
/* Start at the head of the list of points */
iter->u.pnt.curr = iter->u.pnt.pnt_lst->head;
@@ -195,7 +213,8 @@ H5S__point_iter_init(const H5S_t *space, H5S_sel_iter_t *iter)
/* Initialize type of selection iterator */
iter->type = H5S_sel_iter_point;
- FUNC_LEAVE_NOAPI(SUCCEED)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S__point_iter_init() */
@@ -537,13 +556,18 @@ H5S__point_iter_get_seq_list(H5S_sel_iter_t *iter, size_t maxseq, size_t maxelem
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S__point_iter_release(H5S_sel_iter_t H5_ATTR_UNUSED * iter)
+H5S__point_iter_release(H5S_sel_iter_t * iter)
{
FUNC_ENTER_STATIC_NOERR
/* Check args */
HDassert(iter);
+ /* If this iterator copied the point list, we must free it */
+ if((iter->flags & H5S_SEL_ITER_API_CALL) &&
+ !(iter->flags & H5S_SEL_ITER_SHARE_WITH_DATASPACE))
+ H5S__free_pnt_list(iter->u.pnt.pnt_lst);
+
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5S__point_iter_release() */
diff --git a/src/H5Spublic.h b/src/H5Spublic.h
index 84e577b..23e6846 100644
--- a/src/H5Spublic.h
+++ b/src/H5Spublic.h
@@ -44,6 +44,18 @@
* earlier offset than the previous
* one.
*/
+#define H5S_SEL_ITER_SHARE_WITH_DATASPACE 0x0002 /* Don't copy the dataspace
+ * selection when creating the
+ * selection iterator.
+ *
+ * This can improve performance
+ * of creating the iterator, but
+ * the dataspace _MUST_NOT_ be
+ * modified or closed until the
+ * selection iterator is closed
+ * or the iterator's behavior
+ * will be undefined.
+ */
/* Different types of dataspaces */
typedef enum H5S_class_t {
@@ -144,6 +156,11 @@ H5_DLL herr_t H5Sget_select_elem_pointlist(hid_t spaceid, hsize_t startpoint,
H5_DLL herr_t H5Sselect_hyperslab(hid_t space_id, H5S_seloper_t op,
const hsize_t start[], const hsize_t _stride[], const hsize_t count[],
const hsize_t _block[]);
+H5_DLL hid_t H5Scombine_hyperslab(hid_t space_id, H5S_seloper_t op,
+ const hsize_t start[], const hsize_t _stride[], const hsize_t count[],
+ const hsize_t _block[]);
+H5_DLL herr_t H5Smodify_select(hid_t space1_id, H5S_seloper_t op, hid_t space2_id);
+H5_DLL hid_t H5Scombine_select(hid_t space1_id, H5S_seloper_t op, hid_t space2_id);
H5_DLL htri_t H5Sis_regular_hyperslab(hid_t spaceid);
H5_DLL htri_t H5Sget_regular_hyperslab(hid_t spaceid, hsize_t start[],
hsize_t stride[], hsize_t count[], hsize_t block[]);
@@ -151,6 +168,12 @@ H5_DLL hssize_t H5Sget_select_hyper_nblocks(hid_t spaceid);
H5_DLL herr_t H5Sget_select_hyper_blocklist(hid_t spaceid, hsize_t startblock,
hsize_t numblocks, hsize_t buf[/*numblocks*/]);
+/* Operations on dataspace selection iterators */
+H5_DLL hid_t H5Ssel_iter_create(hid_t spaceid, size_t elmt_size, unsigned flags);
+H5_DLL herr_t H5Ssel_iter_get_seq_list(hid_t sel_iter_id, size_t maxseq,
+ size_t maxbytes, size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len);
+H5_DLL herr_t H5Ssel_iter_close(hid_t sel_iter_id);
+
/* Symbols defined for compatibility with previous versions of the HDF5 API.
*
* Use of these symbols is deprecated.
diff --git a/src/H5Sselect.c b/src/H5Sselect.c
index 6983c93..c40ff69 100644
--- a/src/H5Sselect.c
+++ b/src/H5Sselect.c
@@ -40,6 +40,9 @@
/* Local Macros */
/****************/
+/* All the valid public flags to H5Ssel_iter_create() */
+#define H5S_SEL_ITER_ALL_PUBLIC_FLAGS (H5S_SEL_ITER_GET_SEQ_LIST_SORTED | \
+ H5S_SEL_ITER_SHARE_WITH_DATASPACE)
/******************/
@@ -2500,3 +2503,217 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_select_subtract() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Ssel_iter_create
+ PURPOSE
+ Create a dataspace selection iterator for a dataspace's selection
+ USAGE
+ hid_t H5Ssel_iter_create(space)
+ hid_t space; IN: ID of the dataspace with selection to iterate over
+ RETURNS
+ Valid dataspace selection iterator ID on success, H5I_INVALID_HID on failure
+ DESCRIPTION
+ Creates a selection iterator and initializes it to start at the first
+ element selected in the dataspace.
+ PROGRAMMER
+ Quincey Koziol - February 11, 2019
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+hid_t
+H5Ssel_iter_create(hid_t space_id, size_t elmt_size, unsigned flags)
+{
+ H5S_t *space; /* Dataspace with selection to iterate over */
+ H5S_sel_iter_t *sel_iter; /* Selection iterator created */
+ hid_t ret_value; /* Return value */
+
+ FUNC_ENTER_API(H5I_INVALID_HID)
+ H5TRACE3("i", "izIu", space_id, elmt_size, flags);
+
+ /* Check args */
+ if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace")
+ if(elmt_size == 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, H5I_INVALID_HID, "element size must be greater than 0")
+ if(flags != (flags & H5S_SEL_ITER_ALL_PUBLIC_FLAGS))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, H5I_INVALID_HID, "invalid selection iterator flag")
+
+ /* Allocate the iterator */
+ if(NULL == (sel_iter = H5FL_MALLOC(H5S_sel_iter_t)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, H5I_INVALID_HID, "can't allocate selection iterator")
+
+ /* Add flag to indicate that this iterator is from an API call */
+ flags |= H5S_SEL_ITER_API_CALL;
+
+ /* Initialize the selection iterator */
+ if(H5S_select_iter_init(sel_iter, space, elmt_size, flags) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, H5I_INVALID_HID, "unable to initialize selection iterator")
+
+ /* Atomize */
+ if((ret_value = H5I_register(H5I_SPACE_SEL_ITER, sel_iter, TRUE)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace selection iterator atom")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Ssel_iter_create() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Ssel_iter_get_seq_list
+ PURPOSE
+ Retrieve a list of offset / length sequences for the elements in an iterator
+ USAGE
+ herr_t H5Ssel_iter_get_seq_list(sel_iter_id, maxseq, maxbytes, nseq, nbytes, off, len)
+ hid_t sel_iter_id; IN: ID of the dataspace selection iterator to retrieve sequence from
+ size_t maxseq; IN: Max. # of sequences to retrieve
+ size_t maxbytes; IN: Max. # of bytes to retrieve in sequences
+ size_t *nseq; OUT: # of sequences retrieved
+ size_t *nbytes; OUT: # of bytes retrieved, in all sequences
+ hsize_t *off; OUT: Array of sequence offsets
+ size_t *len; OUT: Array of sequence lengths
+ RETURNS
+ Non-negative on success / Negative on failure
+ DESCRIPTION
+ Retrieve a list of offset / length pairs (a list of "sequences") matching
+ the selected elements for an iterator, according to the iteration order for
+ the iterator. The lengths returned are in _bytes_, not elements.
+
+ Note that the iteration order for "all" and "hyperslab" selections is
+ row-major (i.e. "C-ordered"), but the iteration order for "point"
+ selections is "in order selected", unless the H5S_SEL_ITER_GET_SEQ_LIST_SORTED
+ flag is passed to H5Sset_iter_create for a point selection.
+
+ MAXSEQ and MAXBYTES specify the most sequences or bytes possible to
+ place into the OFF and LEN arrays. *NSEQ and *NBYTES return the actual
+ number of sequences and bytes put into the arrays.
+
+ Each call to H5Ssel_iter_get_seq_list() will retrieve the next set
+ of sequences for the selection being iterated over.
+
+ The total number of bytes possible to retrieve from a selection iterator
+ is the 'elmt_size' passed to H5Ssel_iter_create multiplied by the number
+ of elements selected in the dataspace the iterator was created from
+ (which can be retrieved with H5Sget_select_npoints). When there are no
+ further sequences of elements to retrieve, calls to this routine will
+ set *NSEQ and *NBYTES to zero.
+ PROGRAMMER
+ Quincey Koziol - February 11, 2019
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5Ssel_iter_get_seq_list(hid_t sel_iter_id, size_t maxseq, size_t maxbytes,
+ size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len)
+{
+ H5S_sel_iter_t *sel_iter; /* Dataspace selection iterator to operate on */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE7("e", "izz*z*z*h*z", sel_iter_id, maxseq, maxbytes, nseq, nbytes, off,
+ len);
+
+ /* Check args */
+ if(NULL == (sel_iter = (H5S_sel_iter_t *)H5I_object_verify(sel_iter_id, H5I_SPACE_SEL_ITER)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace selection iterator")
+ if(NULL == nseq)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "'nseq' pointer is NULL")
+ if(NULL == nbytes)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "'nbytes' pointer is NULL")
+ if(NULL == off)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "offset array pointer is NULL")
+ if(NULL == len)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "length array pointer is NULL")
+
+ /* Get the sequences of bytes */
+ if(maxseq > 0 && maxbytes > 0) {
+ if(H5S_SELECT_ITER_GET_SEQ_LIST(sel_iter, maxseq, maxbytes, nseq, nbytes, off, len) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "sequence length generation failed")
+ } /* end if */
+ else
+ *nseq = *nbytes = 0;
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Ssel_iter_get_seq_list() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5S_sel_iter_close
+ *
+ * Purpose: Releases a dataspace selection iterator and its memory.
+ *
+ * Return: Non-negative on success / Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Monday, February 11, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5S_sel_iter_close(H5S_sel_iter_t *sel_iter)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(sel_iter);
+
+ /* Call selection type-specific release routine */
+ if(H5S_SELECT_ITER_RELEASE(sel_iter) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "problem releasing a selection iterator's type-specific info")
+
+ /* Release the structure */
+ sel_iter = H5FL_FREE(H5S_sel_iter_t, sel_iter);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S_sel_iter_close() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5Ssel_iter_close
+ PURPOSE
+ Close a dataspace selection iterator
+ USAGE
+ herr_t H5Ssel_iter_close(sel_iter_id)
+ hid_t sel_iter_id; IN: ID of the dataspace selection iterator to close
+ RETURNS
+ Non-negative on success / Negative on failure
+ DESCRIPTION
+ Close a dataspace selection iterator, releasing its state.
+ PROGRAMMER
+ Quincey Koziol - February 11, 2019
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5Ssel_iter_close(hid_t sel_iter_id)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE1("e", "i", sel_iter_id);
+
+ /* Check args */
+ if(NULL == H5I_object_verify(sel_iter_id, H5I_SPACE_SEL_ITER))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace selection iterator")
+
+ /* When the reference count reaches zero the resources are freed */
+ if(H5I_dec_app_ref(sel_iter_id) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "problem freeing dataspace selection iterator ID")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Ssel_iter_close() */
+
diff --git a/src/H5trace.c b/src/H5trace.c
index ff81ae8..9c858fc 100644
--- a/src/H5trace.c
+++ b/src/H5trace.c
@@ -1387,6 +1387,10 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "%ld (err stack)", (long)obj);
break;
+ case H5I_SPACE_SEL_ITER:
+ HDfprintf(out, "%ld (dataspace selection iterator)", (long)obj);
+ break;
+
case H5I_NTYPES:
HDfprintf (out, "%ld (ntypes - error)", (long)obj);
break;
@@ -1568,6 +1572,10 @@ H5_trace(const double *returning, const char *func, const char *type, ...)
HDfprintf(out, "H5I_ERROR_STACK");
break;
+ case H5I_SPACE_SEL_ITER:
+ HDfprintf(out, "H5I_SPACE_SEL_ITER");
+ break;
+
case H5I_NTYPES:
HDfprintf(out, "H5I_NTYPES");
break;
diff --git a/test/tselect.c b/test/tselect.c
index 842fe17..d912df5 100644
--- a/test/tselect.c
+++ b/test/tselect.c
@@ -173,6 +173,9 @@
#define SPACE13_DIM3 50
#define SPACE13_NPOINTS 4
+/* Information for testing selection iterators */
+#define SEL_ITER_MAX_SEQ 256
+
/* Location comparison function */
static int compare_size_t(const void *s1, const void *s2);
@@ -4918,6 +4921,466 @@ test_select_hyper_union(void)
/****************************************************************
**
+** test_select_hyper_union_stagger(): Test basic H5S (dataspace) selection code.
+** Tests unions of staggered hyperslabs. (Uses H5Scombine_hyperslab
+** and H5Smodify_select instead of H5Sselect_hyperslab)
+**
+****************************************************************/
+static void
+test_select_hyper_union_stagger(void)
+{
+ hid_t file_id; /* File ID */
+ hid_t dset_id; /* Dataset ID */
+ hid_t dataspace; /* File dataspace ID */
+ hid_t memspace; /* Memory dataspace ID */
+ hid_t tmp_space; /* Temporary dataspace ID */
+ hid_t tmp2_space; /* Another emporary dataspace ID */
+ hsize_t dimsm[2]={7,7}; /* Memory array dimensions */
+ hsize_t dimsf[2]={6,5}; /* File array dimensions */
+ hsize_t count[2]={3,1}; /* 1st Hyperslab size */
+ hsize_t count2[2]={3,1}; /* 2nd Hyperslab size */
+ hsize_t count3[2]={2,1}; /* 3rd Hyperslab size */
+ hsize_t start[2]={0,0}; /* 1st Hyperslab offset */
+ hsize_t start2[2]={2,1}; /* 2nd Hyperslab offset */
+ hsize_t start3[2]={4,2}; /* 3rd Hyperslab offset */
+ hsize_t count_out[2]={4,2}; /* Hyperslab size in memory */
+ hsize_t start_out[2]={0,3}; /* Hyperslab offset in memory */
+ int data[6][5]; /* Data to write */
+ int data_out[7][7]; /* Data read in */
+ int input_loc[8][2]={{0,0},
+ {1,0},
+ {2,0},
+ {2,1},
+ {3,1},
+ {4,1},
+ {4,2},
+ {5,2}};
+ int output_loc[8][2]={{0,3},
+ {0,4},
+ {1,3},
+ {1,4},
+ {2,3},
+ {2,4},
+ {3,3},
+ {3,4}};
+ int dsetrank=2; /* File Dataset rank */
+ int memrank=2; /* Memory Dataset rank */
+ int i,j; /* Local counting variables */
+ herr_t error;
+ hsize_t stride[2]={1,1};
+ hsize_t block[2]={1,1};
+
+ /* Initialize data to write */
+ for(i=0; i<6; i++)
+ for(j=0; j<5; j++)
+ data[i][j] = j*10 + i;
+
+ /* Create file */
+ file_id=H5Fcreate(FILENAME,H5F_ACC_TRUNC,H5P_DEFAULT,H5P_DEFAULT);
+ CHECK(file_id, FAIL, "H5Fcreate");
+
+ /* Create File Dataspace */
+ dataspace=H5Screate_simple(dsetrank,dimsf,NULL);
+ CHECK(dataspace, FAIL, "H5Screate_simple");
+
+ /* Create File Dataset */
+ dset_id=H5Dcreate2(file_id,"IntArray",H5T_NATIVE_INT,dataspace,H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(dset_id, FAIL, "H5Dcreate2");
+
+ /* Write File Dataset */
+ error=H5Dwrite(dset_id,H5T_NATIVE_INT,dataspace,dataspace,H5P_DEFAULT,data);
+ CHECK(error, FAIL, "H5Dwrite");
+
+ /* Close things */
+ error=H5Sclose(dataspace);
+ CHECK(error, FAIL, "H5Sclose");
+ error = H5Dclose(dset_id);
+ CHECK(error, FAIL, "H5Dclose");
+ error = H5Fclose(file_id);
+ CHECK(error, FAIL, "H5Fclose");
+
+ /* Initialize intput buffer */
+ memset(data_out, 0, 7 * 7 * sizeof(int));
+
+ /* Open file */
+ file_id = H5Fopen(FILENAME, H5F_ACC_RDONLY, H5P_DEFAULT);
+ CHECK(file_id, FAIL, "H5Fopen");
+
+ /* Open dataset */
+ dset_id = H5Dopen2(file_id, "IntArray", H5P_DEFAULT);
+ CHECK(dset_id, FAIL, "H5Dopen2");
+
+ /* Get the dataspace */
+ dataspace = H5Dget_space(dset_id);
+ CHECK(dataspace, FAIL, "H5Dget_space");
+
+ /* Select the hyperslabs */
+ error = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, start, stride, count, block);
+ CHECK(error, FAIL, "H5Sselect_hyperslab");
+ tmp_space = H5Scombine_hyperslab(dataspace, H5S_SELECT_OR, start2, stride, count2, block);
+ CHECK(tmp_space, FAIL, "H5Scombine_hyperslab");
+
+ /* Copy the file dataspace and select hyperslab */
+ tmp2_space = H5Scopy(dataspace);
+ CHECK(tmp2_space, FAIL, "H5Scopy");
+ error=H5Sselect_hyperslab(tmp2_space, H5S_SELECT_SET, start3, stride, count3, block);
+ CHECK(error, FAIL, "H5Sselect_hyperslab");
+
+ /* Combine the copied dataspace with the temporary dataspace */
+ error=H5Smodify_select(tmp_space,H5S_SELECT_OR,tmp2_space);
+ CHECK(error, FAIL, "H5Smodify_select");
+
+ /* Create Memory Dataspace */
+ memspace=H5Screate_simple(memrank,dimsm,NULL);
+ CHECK(memspace, FAIL, "H5Screate_simple");
+
+ /* Select hyperslab in memory */
+ error=H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start_out, stride, count_out, block);
+ CHECK(error, FAIL, "H5Sselect_hyperslab");
+
+ /* Read File Dataset */
+ error=H5Dread(dset_id,H5T_NATIVE_INT,memspace,tmp_space,H5P_DEFAULT,data_out);
+ CHECK(error, FAIL, "H5Dread");
+
+ /* Verify input data */
+ for(i=0; i<8; i++) {
+ if(data[input_loc[i][0]][input_loc[i][1]]!=data_out[output_loc[i][0]][output_loc[i][1]]) {
+ printf("input data #%d is wrong!\n",i);
+ printf("input_loc=[%d][%d]\n",input_loc[i][0],input_loc[i][1]);
+ printf("output_loc=[%d][%d]\n",output_loc[i][0],output_loc[i][1]);
+ printf("data=%d\n",data[input_loc[i][0]][input_loc[i][1]]);
+ TestErrPrintf("data_out=%d\n",data_out[output_loc[i][0]][output_loc[i][1]]);
+ } /* end if */
+ } /* end for */
+
+ /* Close things */
+ error=H5Sclose(tmp2_space);
+ CHECK(error, FAIL, "H5Sclose");
+ error=H5Sclose(tmp_space);
+ CHECK(error, FAIL, "H5Sclose");
+ error=H5Sclose(dataspace);
+ CHECK(error, FAIL, "H5Sclose");
+ error=H5Sclose(memspace);
+ CHECK(error, FAIL, "H5Sclose");
+ error=H5Dclose(dset_id);
+ CHECK(error, FAIL, "H5Dclose");
+ error=H5Fclose(file_id);
+ CHECK(error, FAIL, "H5Fclose");
+}
+
+/****************************************************************
+**
+** test_select_hyper_union_3d(): Test basic H5S (dataspace) selection code.
+** Tests unions of hyperslabs in 3-D (Uses H5Scombine_hyperslab
+** and H5Scombine_select instead of H5Sselect_hyperslab)
+**
+****************************************************************/
+static void
+test_select_hyper_union_3d(void)
+{
+ hid_t fid1; /* HDF5 File IDs */
+ hid_t dataset; /* Dataset ID */
+ hid_t sid1,sid2; /* Dataspace ID */
+ hid_t tmp_space; /* Temporary Dataspace ID */
+ hid_t tmp2_space; /* Another temporary Dataspace ID */
+ hsize_t dims1[] = {SPACE1_DIM1, SPACE1_DIM2, SPACE1_DIM3};
+ hsize_t dims2[] = {SPACE4_DIM1, SPACE4_DIM2, SPACE4_DIM3};
+ hsize_t dims3[] = {SPACE3_DIM1, SPACE3_DIM2};
+ hsize_t start[SPACE1_RANK]; /* Starting location of hyperslab */
+ hsize_t stride[SPACE1_RANK]; /* Stride of hyperslab */
+ hsize_t count[SPACE1_RANK]; /* Element count of hyperslab */
+ hsize_t block[SPACE1_RANK]; /* Block size of hyperslab */
+ struct row_list {
+ size_t z;
+ size_t y;
+ size_t x;
+ size_t l;
+ } rows[]= { /* Array of x,y,z coordinates & length for each row written from memory */
+ {0,0,0,6}, /* 1st face of 3-D object */
+ {0,1,0,6},
+ {0,2,0,6},
+ {0,3,0,6},
+ {0,4,0,6},
+ {1,0,0,6}, /* 2nd face of 3-D object */
+ {1,1,0,6},
+ {1,2,0,6},
+ {1,3,0,6},
+ {1,4,0,6},
+ {2,0,0,6}, /* 3rd face of 3-D object */
+ {2,1,0,10},
+ {2,2,0,10},
+ {2,3,0,10},
+ {2,4,0,10},
+ {2,5,2,8},
+ {2,6,2,8},
+ {3,0,0,6}, /* 4th face of 3-D object */
+ {3,1,0,10},
+ {3,2,0,10},
+ {3,3,0,10},
+ {3,4,0,10},
+ {3,5,2,8},
+ {3,6,2,8},
+ {4,0,0,6}, /* 5th face of 3-D object */
+ {4,1,0,10},
+ {4,2,0,10},
+ {4,3,0,10},
+ {4,4,0,10},
+ {4,5,2,8},
+ {4,6,2,8},
+ {5,1,2,8}, /* 6th face of 3-D object */
+ {5,2,2,8},
+ {5,3,2,8},
+ {5,4,2,8},
+ {5,5,2,8},
+ {5,6,2,8},
+ {6,1,2,8}, /* 7th face of 3-D object */
+ {6,2,2,8},
+ {6,3,2,8},
+ {6,4,2,8},
+ {6,5,2,8},
+ {6,6,2,8},
+ {7,1,2,8}, /* 8th face of 3-D object */
+ {7,2,2,8},
+ {7,3,2,8},
+ {7,4,2,8},
+ {7,5,2,8},
+ {7,6,2,8}};
+ uint8_t *wbuf, /* buffer to write to disk */
+ *rbuf, /* buffer read from disk */
+ *tbuf, /* temporary buffer pointer */
+ *tbuf2; /* temporary buffer pointer */
+ int i,j,k; /* Counters */
+ herr_t ret; /* Generic return value */
+ hsize_t npoints; /* Number of elements in selection */
+
+ /* Output message about test being performed */
+ MESSAGE(5, ("Testing Hyperslab Selection Functions with unions of 3-D hyperslabs\n"));
+
+ /* Allocate write & read buffers */
+ wbuf = (uint8_t *)HDmalloc(sizeof(uint8_t) * SPACE4_DIM1 * SPACE4_DIM2 * SPACE4_DIM3);
+ CHECK(wbuf, NULL, "HDmalloc");
+ rbuf = (uint8_t *)HDcalloc(sizeof(uint8_t), SPACE3_DIM1 * SPACE3_DIM2);
+ CHECK(rbuf, NULL, "HDcalloc");
+
+ /* Initialize write buffer */
+ for(i=0, tbuf=wbuf; i<SPACE4_DIM1; i++)
+ for(j=0; j<SPACE4_DIM2; j++)
+ for(k=0; k<SPACE4_DIM3; k++)
+ *tbuf++=(uint8_t)((((i*SPACE4_DIM2)+j)*SPACE4_DIM3)+k);
+
+ /* Create file */
+ fid1 = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(fid1, FAIL, "H5Fcreate");
+
+/* Test case of two blocks which overlap corners and must be split */
+ /* Create dataspace for dataset on disk */
+ sid1 = H5Screate_simple(SPACE1_RANK, dims1, NULL);
+ CHECK(sid1, FAIL, "H5Screate_simple");
+
+ /* Create dataspace for writing buffer */
+ sid2 = H5Screate_simple(SPACE4_RANK, dims2, NULL);
+ CHECK(sid2, FAIL, "H5Screate_simple");
+
+ /* Select 2x15x13 hyperslab for disk dataset */
+ start[0]=1; start[1]=0; start[2]=0;
+ stride[0]=1; stride[1]=1; stride[2]=1;
+ count[0]=2; count[1]=15; count[2]=13;
+ block[0]=1; block[1]=1; block[2]=1;
+ ret = H5Sselect_hyperslab(sid1,H5S_SELECT_SET,start,stride,count,block);
+ CHECK(ret, FAIL, "H5Sselect_hyperslab");
+
+ /* Select 5x5x6 hyperslab for memory dataset */
+ start[0]=0; start[1]=0; start[2]=0;
+ stride[0]=1; stride[1]=1; stride[2]=1;
+ count[0]=5; count[1]=5; count[2]=6;
+ block[0]=1; block[1]=1; block[2]=1;
+ ret = H5Sselect_hyperslab(sid2,H5S_SELECT_SET,start,stride,count,block);
+ CHECK(ret, FAIL, "H5Sselect_hyperslab");
+
+ /* Union overlapping 15x20 hyperslab for memory dataset (forming a irregularly shaped region) */
+ start[0]=2; start[1]=1; start[2]=2;
+ stride[0]=1; stride[1]=1; stride[2]=1;
+ count[0]=6; count[1]=6; count[2]=8;
+ block[0]=1; block[1]=1; block[2]=1;
+ tmp_space = H5Scombine_hyperslab(sid2,H5S_SELECT_SET,start,stride,count,block);
+ CHECK(tmp_space, FAIL, "H5Sselect_hyperslab");
+
+ /* Combine dataspaces and create new dataspace */
+ tmp2_space = H5Scombine_select(sid2,H5S_SELECT_OR,tmp_space);
+ CHECK(tmp2_space, FAIL, "H5Scombin_select");
+
+ npoints = (hsize_t)H5Sget_select_npoints(tmp2_space);
+ VERIFY(npoints, 15*26, "H5Sget_select_npoints");
+
+ /* Create a dataset */
+ dataset = H5Dcreate2(fid1, SPACE1_NAME, H5T_NATIVE_UCHAR, sid1, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(dataset, FAIL, "H5Dcreate2");
+
+ /* Write selection to disk */
+ ret=H5Dwrite(dataset,H5T_NATIVE_UCHAR,tmp2_space,sid1,H5P_DEFAULT,wbuf);
+ CHECK(ret, FAIL, "H5Dwrite");
+
+ /* Close temporary dataspaces */
+ ret = H5Sclose(tmp_space);
+ CHECK(ret, FAIL, "H5Sclose");
+ ret = H5Sclose(tmp2_space);
+ CHECK(ret, FAIL, "H5Sclose");
+
+ /* Close memory dataspace */
+ ret = H5Sclose(sid2);
+ CHECK(ret, FAIL, "H5Sclose");
+
+ /* Create dataspace for reading buffer */
+ sid2 = H5Screate_simple(SPACE3_RANK, dims3, NULL);
+ CHECK(sid2, FAIL, "H5Screate_simple");
+
+ /* Select 15x26 hyperslab for reading memory dataset */
+ start[0]=0; start[1]=0;
+ stride[0]=1; stride[1]=1;
+ count[0]=15; count[1]=26;
+ block[0]=1; block[1]=1;
+ ret = H5Sselect_hyperslab(sid2,H5S_SELECT_SET,start,stride,count,block);
+ CHECK(ret, FAIL, "H5Sselect_hyperslab");
+
+ /* Read selection from disk */
+ ret=H5Dread(dataset,H5T_NATIVE_UCHAR,sid2,sid1,H5P_DEFAULT,rbuf);
+ CHECK(ret, FAIL, "H5Dread");
+
+ /* Compare data read with data written out */
+ for(i=0,tbuf2=rbuf; i<(int)(sizeof(rows)/sizeof(struct row_list)); i++) {
+ tbuf=wbuf+(rows[i].z*SPACE4_DIM3*SPACE4_DIM2)+(rows[i].y*SPACE4_DIM3)+rows[i].x;
+ for(j=0; j<(int)rows[i].l; j++, tbuf++, tbuf2++) {
+ if(*tbuf!=*tbuf2)
+ TestErrPrintf("%d: hyperslab values don't match!, i=%d, j=%d, *tbuf=%d, *tbuf2=%d\n",__LINE__,i,j,(int)*tbuf,(int)*tbuf2);
+ } /* end for */
+ } /* end for */
+
+ /* Close memory dataspace */
+ ret = H5Sclose(sid2);
+ CHECK(ret, FAIL, "H5Sclose");
+
+ /* Close disk dataspace */
+ ret = H5Sclose(sid1);
+ CHECK(ret, FAIL, "H5Sclose");
+
+ /* Close Dataset */
+ ret = H5Dclose(dataset);
+ CHECK(ret, FAIL, "H5Dclose");
+
+ /* Close file */
+ ret = H5Fclose(fid1);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Free memory buffers */
+ HDfree(wbuf);
+ HDfree(rbuf);
+} /* test_select_hyper_union_3d() */
+
+/****************************************************************
+**
+** test_select_hyper_valid_combination(): Tests invalid and valid
+** combinations of selections on dataspace for H5Scombine_select
+** and H5Smodify_select.
+**
+****************************************************************/
+static void
+test_select_hyper_valid_combination(void)
+{
+ hid_t single_pt_sid; /* Dataspace ID with single point selection */
+ hid_t single_hyper_sid; /* Dataspace ID with single block hyperslab selection */
+ hid_t regular_hyper_sid; /* Dataspace ID with regular hyperslab selection */
+ hid_t non_existent_sid = -1; /* A non-existent space id */
+ hid_t tmp_sid; /* Temporary dataspace ID */
+ hsize_t dims2D[] = {SPACE9_DIM1, SPACE9_DIM2};
+ hsize_t dims3D[] = {SPACE4_DIM1, SPACE4_DIM2, SPACE4_DIM3};
+
+ hsize_t coord1[1][SPACE2_RANK]; /* Coordinates for single point selection */
+ hsize_t start[SPACE4_RANK]; /* Hyperslab start */
+ hsize_t stride[SPACE4_RANK]; /* Hyperslab stride */
+ hsize_t count[SPACE4_RANK]; /* Hyperslab block count */
+ hsize_t block[SPACE4_RANK]; /* Hyperslab block size */
+ herr_t ret; /* Generic return value */
+
+ /* Output message about test being performed */
+ MESSAGE(6, ("Testing Selection Combination Validity\n"));
+ assert(SPACE9_DIM2>=POINT1_NPOINTS);
+
+ /* Create dataspace for single point selection */
+ single_pt_sid = H5Screate_simple(SPACE9_RANK, dims2D, NULL);
+ CHECK(single_pt_sid, FAIL, "H5Screate_simple");
+
+ /* Select sequence of ten points for multiple point selection */
+ coord1[0][0] = 2; coord1[0][1] = 2;
+ ret = H5Sselect_elements(single_pt_sid, H5S_SELECT_SET, (size_t)1, (const hsize_t *)coord1);
+ CHECK(ret, FAIL, "H5Sselect_elements");
+
+ /* Create dataspace for single hyperslab selection */
+ single_hyper_sid = H5Screate_simple(SPACE9_RANK, dims2D, NULL);
+ CHECK(single_hyper_sid, FAIL, "H5Screate_simple");
+
+ /* Select 10x10 hyperslab for single hyperslab selection */
+ start[0]=1; start[1]=1;
+ stride[0]=1; stride[1]=1;
+ count[0]=1; count[1]=1;
+ block[0]=(SPACE9_DIM1-2); block[1]=(SPACE9_DIM2-2);
+ ret = H5Sselect_hyperslab(single_hyper_sid,H5S_SELECT_SET,start,stride,count,block);
+ CHECK(ret, FAIL, "H5Sselect_hyperslab");
+
+ /* Create dataspace for regular hyperslab selection */
+ regular_hyper_sid = H5Screate_simple(SPACE4_RANK, dims3D, NULL);
+ CHECK(regular_hyper_sid, FAIL, "H5Screate_simple");
+
+ /* Select regular, strided hyperslab selection */
+ start[0]=2; start[1]=2; start[2]=2;
+ stride[0]=2; stride[1]=2; stride[2]=2;
+ count[0]=5; count[1]=2; count[2]=5;
+ block[0]=1; block[1]=1; block[2]=1;
+ ret = H5Sselect_hyperslab(regular_hyper_sid,H5S_SELECT_SET,start,stride,count,block);
+ CHECK(ret, FAIL, "H5Sselect_hyperslab");
+
+
+ /* Test all the selections created */
+
+ /* Test the invalid combinations between point and hyperslab */
+ tmp_sid = H5Scombine_select(single_pt_sid, H5S_SELECT_AND, single_hyper_sid);
+ VERIFY(tmp_sid, FAIL, "H5Scombine_select");
+
+ tmp_sid = H5Smodify_select(single_pt_sid, H5S_SELECT_AND, single_hyper_sid);
+ VERIFY(tmp_sid, FAIL, "H5Smodify_select");
+
+ /* Test the invalid combination between two hyperslab but of different dimension size */
+ tmp_sid = H5Scombine_select(single_hyper_sid, H5S_SELECT_AND, regular_hyper_sid);
+ VERIFY(tmp_sid, FAIL, "H5Scombine_select");
+
+ tmp_sid = H5Smodify_select(single_hyper_sid, H5S_SELECT_AND, regular_hyper_sid);
+ VERIFY(tmp_sid, FAIL, "H5Smodify_select");
+
+ /* Test invalid operation inputs to the two functions */
+ tmp_sid = H5Scombine_select(single_hyper_sid, H5S_SELECT_SET, single_hyper_sid);
+ VERIFY(tmp_sid, FAIL, "H5Scombine_select");
+
+ tmp_sid = H5Smodify_select(single_hyper_sid, H5S_SELECT_SET, single_hyper_sid);
+ VERIFY(tmp_sid, FAIL, "H5Smodify_select");
+
+ /* Test inputs in case of non-existent space ids */
+ tmp_sid = H5Scombine_select(single_hyper_sid, H5S_SELECT_AND, non_existent_sid);
+ VERIFY(tmp_sid, FAIL, "H5Scombine_select");
+
+ tmp_sid = H5Smodify_select(single_hyper_sid, H5S_SELECT_AND, non_existent_sid);
+ VERIFY(tmp_sid, FAIL, "H5Smodify_select");
+
+ /* Close dataspaces */
+ ret = H5Sclose(single_pt_sid);
+ CHECK(ret, FAIL, "H5Sclose");
+ ret = H5Sclose(single_hyper_sid);
+ CHECK(ret, FAIL, "H5Sclose");
+ ret = H5Sclose(regular_hyper_sid);
+ CHECK(ret, FAIL, "H5Sclose");
+} /* test_select_hyper_valid_combination() */
+
+
+/****************************************************************
+**
** test_select_hyper_and_2d(): Test basic H5S (dataspace) selection code.
** Tests 'and' of hyperslabs in 2-D
**
@@ -14453,6 +14916,283 @@ test_irreg_io(void)
/****************************************************************
**
+** test_sel_iter(): Test selection iterator API routines.
+**
+****************************************************************/
+static void
+test_sel_iter(void)
+{
+ hid_t sid; /* Dataspace ID */
+ hid_t iter_id; /* Dataspace selection iterator ID */
+ hsize_t dims1[] = {6, 12}; /* 2-D Dataspace dimensions */
+ hsize_t dims2[] = {32}; /* 1-D dataspace dimensions */
+ hsize_t coord1[POINT1_NPOINTS][2]; /* Coordinates for point selection */
+ hsize_t start[2]; /* Hyperslab start */
+ hsize_t stride[2]; /* Hyperslab stride */
+ hsize_t count[2]; /* Hyperslab block count */
+ hsize_t block[2]; /* Hyperslab block size */
+ size_t nseq; /* # of sequences retrieved */
+ size_t nbytes; /* # of bytes retrieved */
+ hsize_t off[SEL_ITER_MAX_SEQ]; /* Offsets for retrieved sequences */
+ size_t len[SEL_ITER_MAX_SEQ]; /* Lengths for retrieved sequences */
+ H5S_sel_type sel_type; /* Selection type */
+ unsigned sel_share; /* Whether to share selection with dataspace */
+ unsigned sel_iter_flags; /* Flags for selection iterator creation */
+ herr_t ret; /* Generic return value */
+
+ /* Output message about test being performed */
+ MESSAGE(6, ("Testing Dataspace Selection Iterators\n"));
+
+ /* Create dataspace */
+ sid = H5Screate_simple(2, dims1, NULL);
+ CHECK(sid, FAIL, "H5Screate_simple");
+
+
+ /* Try creating selection iterator object with bad parameters */
+ H5E_BEGIN_TRY { /* Bad dataspace ID */
+ iter_id = H5Ssel_iter_create(H5I_INVALID_HID, (size_t)1, (unsigned)0);
+ } H5E_END_TRY;
+ VERIFY(iter_id, FAIL, "H5Ssel_iter_create");
+ H5E_BEGIN_TRY { /* Bad element size */
+ iter_id = H5Ssel_iter_create(sid, (size_t)0, (unsigned)0);
+ } H5E_END_TRY;
+ VERIFY(iter_id, FAIL, "H5Ssel_iter_create");
+ H5E_BEGIN_TRY { /* Bad flag(s) */
+ iter_id = H5Ssel_iter_create(sid, (size_t)1, (unsigned)0xffff);
+ } H5E_END_TRY;
+ VERIFY(iter_id, FAIL, "H5Ssel_iter_create");
+
+ /* Try closing selection iterator, with bad parameters */
+ H5E_BEGIN_TRY { /* Invalid ID */
+ ret = H5Ssel_iter_close(H5I_INVALID_HID);
+ } H5E_END_TRY;
+ VERIFY(ret, FAIL, "H5Ssel_iter_close");
+ H5E_BEGIN_TRY { /* Not a selection iterator ID */
+ ret = H5Ssel_iter_close(sid);
+ } H5E_END_TRY;
+ VERIFY(ret, FAIL, "H5Ssel_iter_close");
+
+
+ /* Try with no selection sharing, and with sharing */
+ for(sel_share = 0; sel_share < 2; sel_share++) {
+ /* Set selection iterator sharing flags */
+ if(sel_share)
+ sel_iter_flags = H5S_SEL_ITER_SHARE_WITH_DATASPACE;
+ else
+ sel_iter_flags = 0;
+
+ /* Create selection iterator object */
+ iter_id = H5Ssel_iter_create(sid, (size_t)1, (unsigned)sel_iter_flags);
+ CHECK(iter_id, FAIL, "H5Ssel_iter_create");
+
+ /* Close selection iterator */
+ ret = H5Ssel_iter_close(iter_id);
+ CHECK(ret, FAIL, "H5Ssel_iter_close");
+
+ /* Try closing selection iterator twice */
+ H5E_BEGIN_TRY { /* Invalid ID */
+ ret = H5Ssel_iter_close(iter_id);
+ } H5E_END_TRY;
+ VERIFY(ret, FAIL, "H5Ssel_iter_close");
+
+
+ /* Create selection iterator object */
+ iter_id = H5Ssel_iter_create(sid, (size_t)1, (unsigned)sel_iter_flags);
+ CHECK(iter_id, FAIL, "H5Ssel_iter_create");
+
+ /* Try retrieving sequences, with bad parameters */
+ H5E_BEGIN_TRY { /* Invalid ID */
+ ret = H5Ssel_iter_get_seq_list(H5I_INVALID_HID, (size_t)1, (size_t)1, &nseq, &nbytes, off, len);
+ } H5E_END_TRY;
+ VERIFY(ret, FAIL, "H5Ssel_iter_get_seq_list");
+ H5E_BEGIN_TRY { /* Invalid nseq pointer */
+ ret = H5Ssel_iter_get_seq_list(iter_id, (size_t)1, (size_t)1, NULL, &nbytes, off, len);
+ } H5E_END_TRY;
+ VERIFY(ret, FAIL, "H5Ssel_iter_get_seq_list");
+ H5E_BEGIN_TRY { /* Invalid nbytes pointer */
+ ret = H5Ssel_iter_get_seq_list(iter_id, (size_t)1, (size_t)1, &nseq, NULL, off, len);
+ } H5E_END_TRY;
+ VERIFY(ret, FAIL, "H5Ssel_iter_get_seq_list");
+ H5E_BEGIN_TRY { /* Invalid offset array */
+ ret = H5Ssel_iter_get_seq_list(iter_id, (size_t)1, (size_t)1, &nseq, &nbytes, NULL, len);
+ } H5E_END_TRY;
+ VERIFY(ret, FAIL, "H5Ssel_iter_get_seq_list");
+ H5E_BEGIN_TRY { /* Invalid length array */
+ ret = H5Ssel_iter_get_seq_list(iter_id, (size_t)1, (size_t)1, &nseq, &nbytes, off, NULL);
+ } H5E_END_TRY;
+ VERIFY(ret, FAIL, "H5Ssel_iter_get_seq_list");
+
+ /* Close selection iterator */
+ ret = H5Ssel_iter_close(iter_id);
+ CHECK(ret, FAIL, "H5Ssel_iter_close");
+
+
+ /* Test iterators on various basic selection types */
+ for(sel_type = H5S_SEL_NONE; sel_type <= H5S_SEL_ALL; sel_type = (H5S_sel_type)(sel_type + 1)) {
+ switch(sel_type) {
+ case H5S_SEL_NONE: /* "None" selection */
+ ret = H5Sselect_none(sid);
+ CHECK(ret, FAIL, "H5Sselect_none");
+ break;
+
+ case H5S_SEL_POINTS: /* Point selection */
+ /* Select sequence of ten points */
+ coord1[0][0] = 0; coord1[0][1] = 9;
+ coord1[1][0] = 1; coord1[1][1] = 2;
+ coord1[2][0] = 2; coord1[2][1] = 4;
+ coord1[3][0] = 0; coord1[3][1] = 6;
+ coord1[4][0] = 1; coord1[4][1] = 8;
+ coord1[5][0] = 2; coord1[5][1] = 10;
+ coord1[6][0] = 0; coord1[6][1] = 11;
+ coord1[7][0] = 1; coord1[7][1] = 4;
+ coord1[8][0] = 2; coord1[8][1] = 1;
+ coord1[9][0] = 0; coord1[9][1] = 3;
+ ret = H5Sselect_elements(sid, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, (const hsize_t *)coord1);
+ CHECK(ret, FAIL, "H5Sselect_elements");
+ break;
+
+ case H5S_SEL_HYPERSLABS: /* Hyperslab selection */
+ /* Select regular hyperslab */
+ start[0] = 3; start[1] = 0;
+ stride[0] = 2; stride[1] = 2;
+ count[0] = 2; count[1] = 5;
+ block[0] = 1; block[1] = 1;
+ ret = H5Sselect_hyperslab(sid, H5S_SELECT_SET, start, stride, count, block);
+ CHECK(ret, FAIL, "H5Sselect_hyperslab");
+ break;
+
+ case H5S_SEL_ALL: /* "All" selection */
+ ret = H5Sselect_all(sid);
+ CHECK(ret, FAIL, "H5Sselect_all");
+ break;
+
+ case H5S_SEL_ERROR:
+ case H5S_SEL_N:
+ default:
+ HDassert(0 && "Can't occur");
+ break;
+ } /* end switch */
+
+ /* Create selection iterator object */
+ iter_id = H5Ssel_iter_create(sid, (size_t)1, (unsigned)sel_iter_flags);
+ CHECK(iter_id, FAIL, "H5Ssel_iter_create");
+
+ /* Try retrieving no sequences, with 0 for maxseq & maxbytes */
+ ret = H5Ssel_iter_get_seq_list(iter_id, (size_t)0, (size_t)1, &nseq, &nbytes, off, len);
+ CHECK(ret, FAIL, "H5Ssel_iter_get_seq_list");
+ VERIFY(nseq, 0, "H5Ssel_iter_get_seq_list");
+ VERIFY(nbytes, 0, "H5Ssel_iter_get_seq_list");
+ ret = H5Ssel_iter_get_seq_list(iter_id, (size_t)1, (size_t)0, &nseq, &nbytes, off, len);
+ CHECK(ret, FAIL, "H5Ssel_iter_get_seq_list");
+ VERIFY(nseq, 0, "H5Ssel_iter_get_seq_list");
+ VERIFY(nbytes, 0, "H5Ssel_iter_get_seq_list");
+
+ /* Try retrieving all sequences */
+ ret = H5Ssel_iter_get_seq_list(iter_id, (size_t)SEL_ITER_MAX_SEQ, (size_t)(1024 * 1024), &nseq, &nbytes, off, len);
+ CHECK(ret, FAIL, "H5Ssel_iter_get_seq_list");
+
+ /* Check results from retrieving sequence list */
+ switch(sel_type) {
+ case H5S_SEL_NONE: /* "None" selection */
+ VERIFY(nseq, 0, "H5Ssel_iter_get_seq_list");
+ VERIFY(nbytes, 0, "H5Ssel_iter_get_seq_list");
+ break;
+
+ case H5S_SEL_POINTS: /* Point selection */
+ VERIFY(nseq, 10, "H5Ssel_iter_get_seq_list");
+ VERIFY(nbytes, 10, "H5Ssel_iter_get_seq_list");
+ break;
+
+ case H5S_SEL_HYPERSLABS: /* Hyperslab selection */
+ VERIFY(nseq, 10, "H5Ssel_iter_get_seq_list");
+ VERIFY(nbytes, 10, "H5Ssel_iter_get_seq_list");
+ break;
+
+ case H5S_SEL_ALL: /* "All" selection */
+ VERIFY(nseq, 1, "H5Ssel_iter_get_seq_list");
+ VERIFY(nbytes, 72, "H5Ssel_iter_get_seq_list");
+ break;
+
+ case H5S_SEL_ERROR:
+ case H5S_SEL_N:
+ default:
+ HDassert(0 && "Can't occur");
+ break;
+ } /* end switch */
+
+ /* Close selection iterator */
+ ret = H5Ssel_iter_close(iter_id);
+ CHECK(ret, FAIL, "H5Ssel_iter_close");
+ } /* end for */
+
+ /* Point selection which will merge into smaller # of sequences */
+ coord1[0][0] = 0; coord1[0][1] = 9;
+ coord1[1][0] = 0; coord1[1][1] = 10;
+ coord1[2][0] = 0; coord1[2][1] = 11;
+ coord1[3][0] = 0; coord1[3][1] = 6;
+ coord1[4][0] = 1; coord1[4][1] = 8;
+ coord1[5][0] = 2; coord1[5][1] = 10;
+ coord1[6][0] = 0; coord1[6][1] = 11;
+ coord1[7][0] = 1; coord1[7][1] = 4;
+ coord1[8][0] = 1; coord1[8][1] = 5;
+ coord1[9][0] = 1; coord1[9][1] = 6;
+ ret = H5Sselect_elements(sid, H5S_SELECT_SET, (size_t)POINT1_NPOINTS, (const hsize_t *)coord1);
+ CHECK(ret, FAIL, "H5Sselect_elements");
+
+ /* Create selection iterator object */
+ iter_id = H5Ssel_iter_create(sid, (size_t)1, (unsigned)sel_iter_flags);
+ CHECK(iter_id, FAIL, "H5Ssel_iter_create");
+
+ /* Try retrieving all sequences */
+ ret = H5Ssel_iter_get_seq_list(iter_id, (size_t)SEL_ITER_MAX_SEQ, (size_t)(1024 * 1024), &nseq, &nbytes, off, len);
+ CHECK(ret, FAIL, "H5Ssel_iter_get_seq_list");
+ VERIFY(nseq, 6, "H5Ssel_iter_get_seq_list");
+ VERIFY(nbytes, 10, "H5Ssel_iter_get_seq_list");
+
+ /* Close selection iterator */
+ ret = H5Ssel_iter_close(iter_id);
+ CHECK(ret, FAIL, "H5Ssel_iter_close");
+
+
+ /* Select irregular hyperslab, which will merge into smaller # of sequences */
+ start[0] = 3; start[1] = 0;
+ stride[0] = 2; stride[1] = 2;
+ count[0] = 2; count[1] = 5;
+ block[0] = 1; block[1] = 1;
+ ret = H5Sselect_hyperslab(sid, H5S_SELECT_SET, start, stride, count, block);
+ CHECK(ret, FAIL, "H5Sselect_hyperslab");
+
+ start[0] = 3; start[1] = 3;
+ stride[0] = 2; stride[1] = 2;
+ count[0] = 2; count[1] = 5;
+ block[0] = 1; block[1] = 1;
+ ret = H5Sselect_hyperslab(sid, H5S_SELECT_OR, start, stride, count, block);
+ CHECK(ret, FAIL, "H5Sselect_hyperslab");
+
+ /* Create selection iterator object */
+ iter_id = H5Ssel_iter_create(sid, (size_t)1, (unsigned)sel_iter_flags);
+ CHECK(iter_id, FAIL, "H5Ssel_iter_create");
+
+ /* Try retrieving all sequences */
+ ret = H5Ssel_iter_get_seq_list(iter_id, (size_t)SEL_ITER_MAX_SEQ, (size_t)(1024 * 1024), &nseq, &nbytes, off, len);
+ CHECK(ret, FAIL, "H5Ssel_iter_get_seq_list");
+ VERIFY(nseq, 6, "H5Ssel_iter_get_seq_list");
+ VERIFY(nbytes, 20, "H5Ssel_iter_get_seq_list");
+
+ /* Close selection iterator */
+ ret = H5Ssel_iter_close(iter_id);
+ CHECK(ret, FAIL, "H5Ssel_iter_close");
+
+ } /* end for */
+
+ /* Close dataspace */
+ ret = H5Sclose(sid);
+ CHECK(ret, FAIL, "H5Sclose");
+} /* test_sel_iter() */
+
+
+/****************************************************************
+**
** test_select(): Main H5S selection testing routine.
**
****************************************************************/
@@ -14519,6 +15259,12 @@ test_select(void)
test_select_hyper_offset2();/* Test more selection offset code with hyperslabs */
test_select_point_offset(); /* Test selection offset code with elements */
test_select_hyper_union(); /* Test hyperslab union code */
+
+ /* Fancy hyperslab API tests */
+ test_select_hyper_union_stagger(); /* Test hyperslab union code for staggered slabs */
+ test_select_hyper_union_3d(); /* Test hyperslab union code for 3-D dataset */
+ test_select_hyper_valid_combination(); /* Test different input combinations */
+
test_select_hyper_and_2d(); /* Test hyperslab intersection (AND) code for 2-D dataset */
test_select_hyper_xor_2d(); /* Test hyperslab XOR code for 2-D dataset */
test_select_hyper_notb_2d(); /* Test hyperslab NOTB code for 2-D dataset */
@@ -14622,6 +15368,8 @@ test_select(void)
/* Test irregular selection I/O */
test_irreg_io();
+ /* Test selection iterators */
+ test_sel_iter();
} /* test_select() */