diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/H5CX.c | 13 | ||||
-rw-r--r-- | src/H5Ipublic.h | 1 | ||||
-rw-r--r-- | src/H5S.c | 21 | ||||
-rw-r--r-- | src/H5Shyper.c | 316 | ||||
-rw-r--r-- | src/H5Spkg.h | 3 | ||||
-rw-r--r-- | src/H5Spoint.c | 34 | ||||
-rw-r--r-- | src/H5Spublic.h | 23 | ||||
-rw-r--r-- | src/H5Sselect.c | 217 | ||||
-rw-r--r-- | src/H5trace.c | 8 |
9 files changed, 615 insertions, 21 deletions
@@ -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; @@ -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 cc1f8d4..4c8e458 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; |