diff options
Diffstat (limited to 'src/H5Sselect.c')
| -rw-r--r-- | src/H5Sselect.c | 2400 |
1 files changed, 1784 insertions, 616 deletions
diff --git a/src/H5Sselect.c b/src/H5Sselect.c index 91aed1e..c2fb7fa 100644 --- a/src/H5Sselect.c +++ b/src/H5Sselect.c @@ -1,46 +1,81 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright by The HDF Group. * - * Copyright by the Board of Trustees of the University of Illinois. * * All rights reserved. * * * * This file is part of HDF5. The full HDF5 copyright notice, including * * terms governing use, modification, and redistribution, is contained in * - * the files COPYING and Copyright.html. COPYING can be found at the root * - * of the source code distribution tree; Copyright.html can be found at the * - * root level of an installed copy of the electronic HDF5 document set and * - * is linked from the top-level documents page. It can also be found at * - * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * - * access to either file, you may request a copy from help@hdfgroup.org. * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://www.hdfgroup.org/licenses. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* Programmer: Quincey Koziol <koziol@ncsa.uiuc.ued> +/* Programmer: Quincey Koziol * Friday, May 29, 1998 * * Purpose: Dataspace selection functions. */ -#define H5S_PACKAGE /*suppress error about including H5Spkg */ +/****************/ +/* Module Setup */ +/****************/ +#include "H5Smodule.h" /* This source code file is part of the H5S module */ -#include "H5private.h" /* Generic Functions */ -#include "H5Dprivate.h" /* Datasets */ -#include "H5Eprivate.h" /* Error handling */ -#include "H5FLprivate.h" /* Free Lists */ -#include "H5Iprivate.h" /* IDs */ -#include "H5MMprivate.h" /* Memory management */ -#include "H5Spkg.h" /* Dataspaces */ -#include "H5Vprivate.h" /* Vector and array functions */ -#include "H5WBprivate.h" /* Wrapped Buffers */ +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Dprivate.h" /* Datasets */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5FLprivate.h" /* Free Lists */ +#include "H5Iprivate.h" /* IDs */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Spkg.h" /* Dataspaces */ +#include "H5VMprivate.h" /* Vector and array functions */ + +/****************/ +/* 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) + +/******************/ +/* Local Typedefs */ +/******************/ + +/********************/ +/* Local Prototypes */ +/********************/ -/* Local functions */ #ifdef LATER -static herr_t H5S_select_iter_block (const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end); -static htri_t H5S_select_iter_has_next_block (const H5S_sel_iter_t *iter); -static herr_t H5S_select_iter_next_block(H5S_sel_iter_t *iter); +static herr_t H5S__select_iter_block(const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end); +static htri_t H5S__select_iter_has_next_block(const H5S_sel_iter_t *iter); +static herr_t H5S__select_iter_next_block(H5S_sel_iter_t *iter); #endif /* LATER */ +/*****************************/ +/* Library Private Variables */ +/*****************************/ + +/*********************/ +/* Package Variables */ +/*********************/ + +/* Declare a free list to manage the H5S_sel_iter_t struct */ +H5FL_DEFINE(H5S_sel_iter_t); + +/* Declare extern free list to manage sequences of size_t */ +H5FL_SEQ_EXTERN(size_t); + +/* Declare extern free list to manage sequences of hsize_t */ +H5FL_SEQ_EXTERN(hsize_t); + +/*******************/ +/* Local Variables */ +/*******************/ - /*-------------------------------------------------------------------------- NAME H5S_select_offset @@ -67,28 +102,115 @@ H5S_select_offset(H5S_t *space, const hssize_t *offset) /* Check args */ HDassert(space); - HDassert(space->extent.rank); + HDassert(0 < space->extent.rank && space->extent.rank <= H5S_MAX_RANK); HDassert(offset); /* Copy the offset over */ - HDmemcpy(space->select.offset, offset, sizeof(hssize_t)*space->extent.rank); + H5MM_memcpy(space->select.offset, offset, sizeof(hssize_t) * space->extent.rank); /* Indicate that the offset was changed */ space->select.offset_changed = TRUE; FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5S_select_offset() */ +} /* end H5S_select_offset() */ + +/*-------------------------------------------------------------------------- + NAME + H5Soffset_simple + PURPOSE + Changes the offset of a selection within a simple dataspace extent + USAGE + herr_t H5Soffset_simple(space_id, offset) + hid_t space_id; IN: Dataspace object to reset + const hssize_t *offset; IN: Offset to position the selection at + RETURNS + Non-negative on success/Negative on failure + DESCRIPTION + This function creates an offset for the selection within an extent, allowing + the same shaped selection to be moved to different locations within a + dataspace without requiring it to be re-defined. +--------------------------------------------------------------------------*/ +herr_t +H5Soffset_simple(hid_t space_id, const hssize_t *offset) +{ + H5S_t *space; /* Dataspace to modify */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "i*Hs", space_id, offset); + + /* Check args */ + if (NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ID, H5E_BADID, FAIL, "not a dataspace") + if (space->extent.rank == 0 || + (H5S_GET_EXTENT_TYPE(space) == H5S_SCALAR || H5S_GET_EXTENT_TYPE(space) == H5S_NULL)) + HGOTO_ERROR(H5E_ID, H5E_UNSUPPORTED, FAIL, "can't set offset on scalar or null dataspace") + if (offset == NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no offset specified") + + /* Set the selection offset */ + if (H5S_select_offset(space, offset) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't set offset") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Soffset_simple() */ + +/*-------------------------------------------------------------------------- + NAME + H5Sselect_copy + PURPOSE + Copy a selection from one dataspace to another + USAGE + herr_t H5Sselect_copy(dst, src) + hid_t dst; OUT: ID of the destination dataspace + hid_t src; IN: ID of the source dataspace + + RETURNS + Non-negative on success/Negative on failure + DESCRIPTION + Copies all the selection information (including offset) from the source + dataspace to the destination dataspace. + + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5Sselect_copy(hid_t dst_id, hid_t src_id) +{ + H5S_t *src; + H5S_t *dst; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "ii", dst_id, src_id); + + /* Check args */ + if (NULL == (src = (H5S_t *)H5I_object_verify(src_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") + if (NULL == (dst = (H5S_t *)H5I_object_verify(dst_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") + + /* Copy */ + if (H5S_select_copy(dst, src, FALSE) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy selection") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Sselect_copy() */ - /*-------------------------------------------------------------------------- NAME H5S_select_copy PURPOSE Copy a selection from one dataspace to another USAGE - herr_t H5S_select_copy(dst, src) + herr_t H5S_select_copy(dst, src, share_selection) H5S_t *dst; OUT: Pointer to the destination dataspace H5S_t *src; IN: Pointer to the source dataspace + hbool_t; IN: Whether to share the selection between the dataspaces RETURNS Non-negative on success/Negative on failure DESCRIPTION @@ -105,28 +227,31 @@ H5S_select_offset(H5S_t *space, const hssize_t *offset) REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5S_select_copy (H5S_t *dst, const H5S_t *src, hbool_t share_selection) +H5S_select_copy(H5S_t *dst, const H5S_t *src, hbool_t share_selection) { - herr_t ret_value; /* return value */ + herr_t ret_value = FAIL; /* Return value */ FUNC_ENTER_NOAPI(FAIL) /* Check args */ - assert(dst); - assert(src); + HDassert(dst); + HDassert(src); + + /* Release the current selection */ + if (H5S_SELECT_RELEASE(dst) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection") /* Copy regular fields */ - dst->select=src->select; + dst->select = src->select; /* Perform correct type of copy based on the type of selection */ - if((ret_value=(*src->select.type->copy)(dst,src,share_selection))<0) + if ((ret_value = (*src->select.type->copy)(dst, src, share_selection)) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy selection specific information") done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_select_copy() */ +} /* end H5S_select_copy() */ - /*------------------------------------------------------------------------- * Function: H5S_select_release * @@ -141,63 +266,25 @@ done: * pattern, don't call it directly, use the appropriate macro * defined in H5Sprivate.h. * - * Modifications: - * *------------------------------------------------------------------------- */ herr_t H5S_select_release(H5S_t *ds) { - herr_t ret_value; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_NOAPI_NOINIT - assert(ds); + HDassert(ds); /* Call the selection type's release function */ - ret_value=(*ds->select.type->release)(ds); - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5S_select_release() */ - - -/*------------------------------------------------------------------------- - * Function: H5S_select_get_seq_list - * - * Purpose: Retrieves the next sequence of offset/length pairs for an - * iterator on a dataspace - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * Tuesday, May 18, 2004 - * - * Note: This routine participates in the "Inlining C function pointers" - * pattern, don't call it directly, use the appropriate macro - * defined in H5Sprivate.h. - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5S_select_get_seq_list(const H5S_t *space, unsigned flags, - H5S_sel_iter_t *iter, size_t maxseq, size_t maxbytes, - size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len) -{ - herr_t ret_value; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT_NOERR - - HDassert(space); - - /* Call the selection type's get_seq_list function */ - ret_value = (*space->select.type->get_seq_list)(space, flags, iter, maxseq, maxbytes, nseq, nbytes, off, len); + if ((ds->select.type) && ((ret_value = (*ds->select.type->release)(ds)) < 0)) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection") +done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5S_select_get_seq_list() */ +} /* end H5S_select_release() */ - /*------------------------------------------------------------------------- * Function: H5S_select_serial_size * @@ -213,35 +300,34 @@ H5S_select_get_seq_list(const H5S_t *space, unsigned flags, * pattern, don't call it directly, use the appropriate macro * defined in H5Sprivate.h. * - * Modifications: - * *------------------------------------------------------------------------- */ hssize_t -H5S_select_serial_size(const H5S_t *space) +H5S_select_serial_size(H5S_t *space) { - hssize_t ret_value; /* Return value */ + hssize_t ret_value = -1; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR - assert(space); + HDassert(space); /* Call the selection type's serial_size function */ - ret_value=(*space->select.type->serial_size)(space); + ret_value = (*space->select.type->serial_size)(space); FUNC_LEAVE_NOAPI(ret_value) -} /* end H5S_select_serial_size() */ +} /* end H5S_select_serial_size() */ - /*-------------------------------------------------------------------------- NAME H5S_select_serialize PURPOSE Serialize the selection for a dataspace into a buffer USAGE - herr_t H5S_select_serialize(space, buf) + herr_t H5S_select_serialize(space, p) const H5S_t *space; IN: Dataspace with selection to serialize - uint8_t *buf; OUT: Buffer to put serialized selection + uint8_t **p; OUT: Pointer to buffer to put serialized + selection. Will be advanced to end of + serialized selection. RETURNS Non-negative on success/Negative on failure DESCRIPTION @@ -256,22 +342,21 @@ H5S_select_serial_size(const H5S_t *space) REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5S_select_serialize(const H5S_t *space, uint8_t *buf) +H5S_select_serialize(H5S_t *space, uint8_t **p) { - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR - assert(space); - assert(buf); + HDassert(space); + HDassert(p); /* Call the selection type's serialize function */ - ret_value=(*space->select.type->serialize)(space,buf); + ret_value = (*space->select.type->serialize)(space, p); FUNC_LEAVE_NOAPI(ret_value) -} /* end H5S_select_serialize() */ +} /* end H5S_select_serialize() */ - /*-------------------------------------------------------------------------- NAME H5Sget_select_npoints @@ -292,30 +377,29 @@ H5S_select_serialize(const H5S_t *space, uint8_t *buf) hssize_t H5Sget_select_npoints(hid_t spaceid) { - H5S_t *space; /* Dataspace to modify selection of */ - hssize_t ret_value; /* return value */ + H5S_t *space; /* Dataspace to modify selection of */ + hssize_t ret_value; /* return value */ FUNC_ENTER_API(FAIL) H5TRACE1("Hs", "i", spaceid); /* Check args */ - if(NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE))) + if (NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") ret_value = (hssize_t)H5S_GET_SELECT_NPOINTS(space); done: FUNC_LEAVE_API(ret_value) -} /* H5Sget_select_npoints() */ +} /* H5Sget_select_npoints() */ - /*-------------------------------------------------------------------------- NAME H5S_get_select_npoints PURPOSE Get the number of elements in current selection USAGE - hssize_t H5Sget_select_npoints(space) + hsize_t H5Sget_select_npoints(space) H5S_t *space; IN: Dataspace of selection to query RETURNS The number of elements in selection on success, 0 on failure @@ -329,7 +413,7 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -hssize_t +H5_ATTR_PURE hsize_t H5S_get_select_npoints(const H5S_t *space) { FUNC_ENTER_NOAPI_NOINIT_NOERR @@ -337,10 +421,9 @@ H5S_get_select_npoints(const H5S_t *space) /* Check args */ HDassert(space); - FUNC_LEAVE_NOAPI((hssize_t)space->select.num_elem) -} /* H5S_get_select_npoints() */ + FUNC_LEAVE_NOAPI(space->select.num_elem) +} /* end H5S_get_select_npoints() */ - /*-------------------------------------------------------------------------- NAME H5Sselect_valid @@ -354,35 +437,32 @@ H5S_get_select_npoints(const H5S_t *space) TRUE if the selection fits within the extent, FALSE if it does not and Negative on an error. DESCRIPTION - Determines if the current selection at the current offet fits within the + Determines if the current selection at the current offset fits within the extent for the dataspace. GLOBAL VARIABLES COMMENTS, BUGS, ASSUMPTIONS EXAMPLES REVISION LOG - Christian Chilan 01/17/2007 - Changed the error return value from 0 to FAIL. --------------------------------------------------------------------------*/ htri_t H5Sselect_valid(hid_t spaceid) { - H5S_t *space; /* Dataspace to modify selection of */ - htri_t ret_value; /* return value */ + H5S_t *space; /* Dataspace to modify selection of */ + htri_t ret_value; /* return value */ FUNC_ENTER_API(FAIL) H5TRACE1("t", "i", spaceid); /* Check args */ - if(NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE))) + if (NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") ret_value = H5S_SELECT_VALID(space); done: FUNC_LEAVE_API(ret_value) -} /* H5Sselect_valid() */ +} /* end H5Sselect_valid() */ - /*-------------------------------------------------------------------------- NAME H5S_select_valid @@ -396,7 +476,7 @@ done: TRUE if the selection fits within the extent, FALSE if it does not and Negative on an error. DESCRIPTION - Determines if the current selection at the current offet fits within the + Determines if the current selection at the current offset fits within the extent for the dataspace. GLOBAL VARIABLES COMMENTS, BUGS, ASSUMPTIONS @@ -409,18 +489,17 @@ done: htri_t H5S_select_valid(const H5S_t *space) { - htri_t ret_value; /* Return value */ + htri_t ret_value = FAIL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR - assert(space); + HDassert(space); ret_value = (*space->select.type->is_valid)(space); FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_select_valid() */ +} /* end H5S_select_valid() */ - /*-------------------------------------------------------------------------- NAME H5S_select_deserialize @@ -428,9 +507,13 @@ H5S_select_valid(const H5S_t *space) Deserialize the current selection from a user-provided buffer into a real selection in the dataspace. USAGE - herr_t H5S_select_deserialize(space, buf) - H5S_t *space; IN/OUT: Dataspace pointer to place selection into - uint8 *buf; IN: Buffer to retrieve serialized selection from + herr_t H5S_select_deserialize(space, p) + H5S_t **space; IN/OUT: Dataspace pointer to place + selection into. Will be allocated if not + provided. + uint8 **p; OUT: Pointer to buffer holding serialized + selection. Will be advanced to end of + serialized selection. RETURNS Non-negative on success/Negative on failure DESCRIPTION @@ -444,46 +527,49 @@ H5S_select_valid(const H5S_t *space) REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5S_select_deserialize (H5S_t *space, const uint8_t *buf) +H5S_select_deserialize(H5S_t **space, const uint8_t **p) { - const uint8_t *tbuf; /* Temporary pointer to the selection type */ - uint32_t sel_type; /* Pointer to the selection type */ - herr_t ret_value=FAIL; /* return value */ + uint32_t sel_type; /* Pointer to the selection type */ + herr_t ret_value = FAIL; /* Return value */ FUNC_ENTER_NOAPI(FAIL) - assert(space); + HDassert(space); + + /* Selection-type specific coding is moved to the callbacks. */ + + /* Decode selection type */ + UINT32DECODE(*p, sel_type); - tbuf=buf; - UINT32DECODE(tbuf, sel_type); - switch(sel_type) { - case H5S_SEL_POINTS: /* Sequence of points selected */ - ret_value=(*H5S_sel_point->deserialize)(space,buf); + /* Make routine for selection type */ + switch (sel_type) { + case H5S_SEL_POINTS: /* Sequence of points selected */ + ret_value = (*H5S_sel_point->deserialize)(space, p); break; - case H5S_SEL_HYPERSLABS: /* Hyperslab selection defined */ - ret_value=(*H5S_sel_hyper->deserialize)(space,buf); + case H5S_SEL_HYPERSLABS: /* Hyperslab selection defined */ + ret_value = (*H5S_sel_hyper->deserialize)(space, p); break; - case H5S_SEL_ALL: /* Entire extent selected */ - ret_value=(*H5S_sel_all->deserialize)(space,buf); + case H5S_SEL_ALL: /* Entire extent selected */ + ret_value = (*H5S_sel_all->deserialize)(space, p); break; - case H5S_SEL_NONE: /* Nothing selected */ - ret_value=(*H5S_sel_none->deserialize)(space,buf); + case H5S_SEL_NONE: /* Nothing selected */ + ret_value = (*H5S_sel_none->deserialize)(space, p); break; default: break; } - if(ret_value<0) + + if (ret_value < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTLOAD, FAIL, "can't deserialize selection") done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_select_deserialize() */ +} /* end H5S_select_deserialize() */ - /*-------------------------------------------------------------------------- NAME H5Sget_select_bounds @@ -515,27 +601,26 @@ done: REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5Sget_select_bounds(hid_t spaceid, hsize_t start[], hsize_t end[]) +H5Sget_select_bounds(hid_t spaceid, hsize_t start[] /*out*/, hsize_t end[] /*out*/) { - H5S_t *space; /* Dataspace to modify selection of */ - herr_t ret_value; /* return value */ + H5S_t *space; /* Dataspace to modify selection of */ + herr_t ret_value; /* return value */ FUNC_ENTER_API(FAIL) - H5TRACE3("e", "i*h*h", spaceid, start, end); + H5TRACE3("e", "ixx", spaceid, start, end); /* Check args */ - if(start == NULL || end == NULL) + if (start == NULL || end == NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid pointer") - if(NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE))) + if (NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") ret_value = H5S_SELECT_BOUNDS(space, start, end); done: FUNC_LEAVE_API(ret_value) -} /* H5Sget_select_bounds() */ +} /* end H5Sget_select_bounds() */ - /*-------------------------------------------------------------------------- NAME H5S_get_select_bounds @@ -566,21 +651,20 @@ done: herr_t H5S_get_select_bounds(const H5S_t *space, hsize_t *start, hsize_t *end) { - herr_t ret_value; /* return value */ + herr_t ret_value = FAIL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR /* Check args */ - assert(space); - assert(start); - assert(end); + HDassert(space); + HDassert(start); + HDassert(end); - ret_value = (*space->select.type->bounds)(space,start,end); + ret_value = (*space->select.type->bounds)(space, start, end); FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_get_select_bounds() */ +} /* end H5S_get_select_bounds() */ - /*-------------------------------------------------------------------------- NAME H5S_get_select_offset @@ -607,7 +691,7 @@ H5S_get_select_bounds(const H5S_t *space, hsize_t *start, hsize_t *end) herr_t H5S_get_select_offset(const H5S_t *space, hsize_t *offset) { - herr_t ret_value; /* return value */ + herr_t ret_value = FAIL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR @@ -618,9 +702,89 @@ H5S_get_select_offset(const H5S_t *space, hsize_t *offset) ret_value = (*space->select.type->offset)(space, offset); FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_get_select_offset() */ +} /* end H5S_get_select_offset() */ + +/*-------------------------------------------------------------------------- + NAME + H5S_get_select_unlim_dim + PURPOSE + Gets the unlimited dimension in the selection, or -1 if there is no + unlimited dimension. + USAGE + int H5S_get_select_unlim_dim(space) + const H5S_t *space; IN: Dataspace pointer of selection to query + RETURNS + Unlimited dimension in the selection, or -1 if there is no unlimited + dimension (never fails) + DESCRIPTION + Gets the unlimited dimension in the selection, or -1 if there is no + unlimited dimension. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + Currently only implemented for hyperslab selections, all others + simply return -1. + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +int +H5S_get_select_unlim_dim(const H5S_t *space) +{ + herr_t ret_value = FAIL; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + /* Check args */ + HDassert(space); + + ret_value = (*space->select.type->unlim_dim)(space); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S_get_select_unlim_dim() */ + +/*-------------------------------------------------------------------------- + NAME + H5S_get_select_num_elem_non_unlim + PURPOSE + Gets the number of elements in the non-unlimited dimensions + USAGE + herr_t H5S_get_select_num_elem_non_unlim(space,num_elem_non_unlim) + H5S_t *space; IN: Dataspace pointer to check + hsize_t *num_elem_non_unlim; OUT: Number of elements in the non-unlimited dimensions + RETURNS + Non-negative on success/Negative on failure + DESCRIPTION + Returns the number of elements in a slice through the non-unlimited + dimensions of the selection. Fails if the selection has no unlimited + dimension. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_get_select_num_elem_non_unlim(const H5S_t *space, hsize_t *num_elem_non_unlim) +{ + herr_t ret_value = SUCCEED; /* return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Check args */ + HDassert(space); + HDassert(num_elem_non_unlim); + + /* Check for selection callback */ + if (!space->select.type->num_elem_non_unlim) + HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "selection type has no num_elem_non_unlim callback") + + /* Make selection callback */ + if ((*space->select.type->num_elem_non_unlim)(space, num_elem_non_unlim) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, + "can't get number of elements in non-unlimited dimension") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S_get_select_unlim_dim() */ - /*-------------------------------------------------------------------------- NAME H5S_select_is_contiguous @@ -645,19 +809,18 @@ H5S_get_select_offset(const H5S_t *space, hsize_t *offset) htri_t H5S_select_is_contiguous(const H5S_t *space) { - herr_t ret_value; /* return value */ + herr_t ret_value = FAIL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR /* Check args */ - assert(space); + HDassert(space); ret_value = (*space->select.type->is_contiguous)(space); FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_select_is_contiguous() */ +} /* end H5S_select_is_contiguous() */ - /*-------------------------------------------------------------------------- NAME H5S_select_is_single @@ -682,19 +845,18 @@ H5S_select_is_contiguous(const H5S_t *space) htri_t H5S_select_is_single(const H5S_t *space) { - herr_t ret_value; /* return value */ + herr_t ret_value = FAIL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR /* Check args */ - assert(space); + HDassert(space); ret_value = (*space->select.type->is_single)(space); FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_select_is_single() */ +} /* end H5S_select_is_single() */ - /*-------------------------------------------------------------------------- NAME H5S_select_is_regular @@ -717,21 +879,20 @@ H5S_select_is_single(const H5S_t *space) REVISION LOG --------------------------------------------------------------------------*/ htri_t -H5S_select_is_regular(const H5S_t *space) +H5S_select_is_regular(H5S_t *space) { - herr_t ret_value; /* return value */ + herr_t ret_value = FAIL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR /* Check args */ - assert(space); + HDassert(space); ret_value = (*space->select.type->is_regular)(space); FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_select_is_regular() */ +} /* end H5S_select_is_regular() */ - /*-------------------------------------------------------------------------- NAME H5S_select_adjust_u @@ -756,19 +917,107 @@ H5S_select_is_regular(const H5S_t *space) herr_t H5S_select_adjust_u(H5S_t *space, const hsize_t *offset) { - herr_t ret_value; /* return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR /* Check args */ HDassert(space); + HDassert(offset); + /* Perform operation */ ret_value = (*space->select.type->adjust_u)(space, offset); FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_select_adjust_u() */ +} /* end H5S_select_adjust_u() */ + +/*-------------------------------------------------------------------------- + NAME + H5S_select_adjust_s + PURPOSE + Adjust a selection by subtracting an offset + USAGE + herr_t H5S_select_adjust_u(space, offset) + H5S_t *space; IN/OUT: Pointer to dataspace to adjust + const hssize_t *offset; IN: Offset to subtract + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Moves a selection by subtracting an offset from it. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + This routine participates in the "Inlining C function pointers" + pattern, don't call it directly, use the appropriate macro + defined in H5Sprivate.h. + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_select_adjust_s(H5S_t *space, const hssize_t *offset) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + /* Check args */ + HDassert(space); + HDassert(offset); + + /* Perform operation */ + ret_value = (*space->select.type->adjust_s)(space, offset); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S_select_adjust_s() */ + +/*-------------------------------------------------------------------------- + NAME + H5Sselect_adjust + PURPOSE + Adjust a selection by subtracting an offset + USAGE + herr_t H5Sselect_adjust_u(space_id, offset) + hid_t space_id; IN: ID of dataspace to adjust + const hsize_t *offset; IN: Offset to subtract + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Moves a selection by subtracting an offset from it. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5Sselect_adjust(hid_t space_id, const hssize_t *offset) +{ + H5S_t *space; + hsize_t low_bounds[H5S_MAX_RANK]; + hsize_t high_bounds[H5S_MAX_RANK]; + unsigned u; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "i*Hs", space_id, offset); + + if (NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace") + if (NULL == offset) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "NULL offset pointer") + + /* Check bounds */ + if (H5S_SELECT_BOUNDS(space, low_bounds, high_bounds) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get selection bounds") + for (u = 0; u < space->extent.rank; u++) + if (offset[u] > (hssize_t)low_bounds[u]) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "adjustment would move selection below zero offset") + + if (H5S_select_adjust_s(space, offset) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't adjust selection") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Sselect_adjust() */ - /*-------------------------------------------------------------------------- NAME H5S_select_project_scalar @@ -794,7 +1043,7 @@ H5S_select_adjust_u(H5S_t *space, const hsize_t *offset) herr_t H5S_select_project_scalar(const H5S_t *space, hsize_t *offset) { - herr_t ret_value; /* Return value */ + herr_t ret_value = FAIL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR @@ -805,9 +1054,8 @@ H5S_select_project_scalar(const H5S_t *space, hsize_t *offset) ret_value = (*space->select.type->project_scalar)(space, offset); FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_select_project_scalar() */ +} /* end H5S_select_project_scalar() */ - /*-------------------------------------------------------------------------- NAME H5S_select_project_simple @@ -834,7 +1082,7 @@ H5S_select_project_scalar(const H5S_t *space, hsize_t *offset) herr_t H5S_select_project_simple(const H5S_t *space, H5S_t *new_space, hsize_t *offset) { - herr_t ret_value; /* Return value */ + herr_t ret_value = FAIL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR @@ -846,20 +1094,20 @@ H5S_select_project_simple(const H5S_t *space, H5S_t *new_space, hsize_t *offset) ret_value = (*space->select.type->project_simple)(space, new_space, offset); FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_select_project_simple() */ +} /* end H5S_select_project_simple() */ - /*-------------------------------------------------------------------------- NAME H5S_select_iter_init PURPOSE Initializes iteration information for a selection. USAGE - herr_t H5S_select_iter_init(sel_iter, space, elmt_size) + herr_t H5S_select_iter_init(sel_iter, space, elmt_size, flags) H5S_sel_iter_t *sel_iter; OUT: Selection iterator to initialize. H5S_t *space; IN: Dataspace object containing selection to iterate over size_t elmt_size; IN: Size of elements in the selection + unsigned flags; IN: Flags to control iteration behavior RETURNS Non-negative on success, negative on failure. DESCRIPTION @@ -867,9 +1115,9 @@ H5S_select_project_simple(const H5S_t *space, H5S_t *new_space, hsize_t *offset) in the dataspace's selection. --------------------------------------------------------------------------*/ herr_t -H5S_select_iter_init(H5S_sel_iter_t *sel_iter, const H5S_t *space, size_t elmt_size) +H5S_select_iter_init(H5S_sel_iter_t *sel_iter, H5S_t *space, size_t elmt_size, unsigned flags) { - herr_t ret_value; /* Return value */ + herr_t ret_value = FAIL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR @@ -882,23 +1130,28 @@ H5S_select_iter_init(H5S_sel_iter_t *sel_iter, const H5S_t *space, size_t elmt_s /* Save the dataspace's rank */ sel_iter->rank = space->extent.rank; - /* Point to the dataspace dimensions, if there are any */ - if(sel_iter->rank > 0) - sel_iter->dims = space->extent.size; - else - sel_iter->dims = NULL; + /* If dims > 0, copy the dataspace dimensions & selection offset */ + if (sel_iter->rank > 0) { + H5MM_memcpy(sel_iter->dims, space->extent.size, sizeof(hsize_t) * space->extent.rank); + H5MM_memcpy(sel_iter->sel_off, space->select.offset, sizeof(hsize_t) * space->extent.rank); + } /* Save the element size */ sel_iter->elmt_size = elmt_size; + /* Initialize the number of elements to iterate over */ + sel_iter->elmt_left = space->select.num_elem; + + /* Set the flags for the iterator */ + sel_iter->flags = flags; + /* Call initialization routine for selection type */ - ret_value = (*space->select.type->iter_init)(sel_iter, space); + ret_value = (*space->select.type->iter_init)(space, sel_iter); HDassert(sel_iter->type); FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_select_iter_init() */ +} /* end H5S_select_iter_init() */ - /*-------------------------------------------------------------------------- NAME H5S_select_iter_coords @@ -922,31 +1175,31 @@ H5S_select_iter_init(H5S_sel_iter_t *sel_iter, const H5S_t *space, size_t elmt_s REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5S_select_iter_coords (const H5S_sel_iter_t *sel_iter, hsize_t *coords) +H5S_select_iter_coords(const H5S_sel_iter_t *sel_iter, hsize_t *coords) { - herr_t ret_value; /* return value */ + herr_t ret_value = FAIL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR /* Check args */ - assert(sel_iter); - assert(coords); + HDassert(sel_iter); + HDassert(coords); /* Call iter_coords routine for selection type */ - ret_value = (*sel_iter->type->iter_coords)(sel_iter,coords); + ret_value = (*sel_iter->type->iter_coords)(sel_iter, coords); FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_select_iter_coords() */ +} /* end H5S_select_iter_coords() */ #ifdef LATER - + /*-------------------------------------------------------------------------- NAME - H5S_select_iter_block + H5S__select_iter_block PURPOSE Get the block of the current iterator position USAGE - herr_t H5S_select_iter_block(sel_iter,start,end) + herr_t H5S__select_iter_block(sel_iter,start,end) const H5S_sel_iter_t *sel_iter; IN: Selection iterator to query hsize_t *start; OUT: Array to place iterator start block coordinates hsize_t *end; OUT: Array to place iterator end block coordinates @@ -964,25 +1217,24 @@ H5S_select_iter_coords (const H5S_sel_iter_t *sel_iter, hsize_t *coords) REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_select_iter_block (const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end) +H5S__select_iter_block(const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end) { - herr_t ret_value; /* return value */ + herr_t ret_value; /* return value */ - FUNC_ENTER_NOAPI_NOINIT_NOINIT_NOERR + FUNC_ENTER_PACKAGE_NOERR /* Check args */ - assert(iter); - assert(start); - assert(end); + HDassert(iter); + HDassert(start); + HDassert(end); /* Call iter_block routine for selection type */ - ret_value = (*iter->type->iter_block)(iter,start,end); + ret_value = (*iter->type->iter_block)(iter, start, end); FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_select_iter_block() */ +} /* end H5S__select_iter_block() */ #endif /* LATER */ - /*-------------------------------------------------------------------------- NAME H5S_select_iter_nelmts @@ -1004,30 +1256,30 @@ H5S_select_iter_block (const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end) REVISION LOG --------------------------------------------------------------------------*/ hsize_t -H5S_select_iter_nelmts (const H5S_sel_iter_t *sel_iter) +H5S_select_iter_nelmts(const H5S_sel_iter_t *sel_iter) { - hsize_t ret_value; /* return value */ + hsize_t ret_value = 0; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR /* Check args */ - assert(sel_iter); + HDassert(sel_iter); /* Call iter_nelmts routine for selection type */ ret_value = (*sel_iter->type->iter_nelmts)(sel_iter); FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_select_iter_nelmts() */ +} /* end H5S_select_iter_nelmts() */ #ifdef LATER - + /*-------------------------------------------------------------------------- NAME - H5S_select_iter_has_next_block + H5S__select_iter_has_next_block PURPOSE Check if there is another block available in the selection iterator USAGE - htri_t H5S_select_iter_has_next_block(sel_iter) + htri_t H5S__select_iter_has_next_block(sel_iter) const H5S_sel_iter_t *sel_iter; IN: Selection iterator to query RETURNS Non-negative on success, negative on failure. @@ -1043,23 +1295,22 @@ H5S_select_iter_nelmts (const H5S_sel_iter_t *sel_iter) REVISION LOG --------------------------------------------------------------------------*/ static htri_t -H5S_select_iter_has_next_block (const H5S_sel_iter_t *iter) +H5S__select_iter_has_next_block(const H5S_sel_iter_t *iter) { - herr_t ret_value; /* return value */ + herr_t ret_value; /* return value */ - FUNC_ENTER_NOAPI_NOINIT_NOINIT_NOERR + FUNC_ENTER_PACKAGE_NOERR /* Check args */ - assert(iter); + HDassert(iter); /* Call iter_has_next_block routine for selection type */ ret_value = (*iter->type->iter_has_next_block)(iter); FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_select_iter_has_next_block() */ +} /* end H5S__select_iter_has_next_block() */ #endif /* LATER */ - /*-------------------------------------------------------------------------- NAME H5S_select_iter_next @@ -1085,32 +1336,32 @@ H5S_select_iter_has_next_block (const H5S_sel_iter_t *iter) herr_t H5S_select_iter_next(H5S_sel_iter_t *iter, size_t nelem) { - herr_t ret_value; /* return value */ + herr_t ret_value = FAIL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR /* Check args */ - assert(iter); - assert(nelem>0); + HDassert(iter); + HDassert(nelem > 0); /* Call iter_next routine for selection type */ - ret_value = (*iter->type->iter_next)(iter,nelem); + ret_value = (*iter->type->iter_next)(iter, nelem); /* Decrement the number of elements left in selection */ - iter->elmt_left-=nelem; + iter->elmt_left -= nelem; FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_select_iter_next() */ +} /* end H5S_select_iter_next() */ #ifdef LATER - + /*-------------------------------------------------------------------------- NAME - H5S_select_iter_next_block + H5S__select_iter_next_block PURPOSE Advance selection iterator to next block USAGE - herr_t H5S_select_iter_next_block(iter) + herr_t H5S__select_iter_next_block(iter) H5S_sel_iter_t *iter; IN/OUT: Selection iterator to change RETURNS Non-negative on success, negative on failure. @@ -1128,30 +1379,65 @@ H5S_select_iter_next(H5S_sel_iter_t *iter, size_t nelem) REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_select_iter_next_block(H5S_sel_iter_t *iter) +H5S__select_iter_next_block(H5S_sel_iter_t *iter) { - herr_t ret_value; /* return value */ + herr_t ret_value; /* return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_PACKAGE_NOERR /* Check args */ - assert(iter); + HDassert(iter); /* Call iter_next_block routine for selection type */ ret_value = (*iter->type->iter_next_block)(iter); FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_select_iter_next_block() */ +} /* end H5S__select_iter_next_block() */ #endif /* LATER */ - +/*------------------------------------------------------------------------- + * Function: H5S_select_iter_get_seq_list + * + * Purpose: Retrieves the next sequence of offset/length pairs for an + * iterator on a dataspace + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, May 18, 2004 + * + * Note: This routine participates in the "Inlining C function pointers" + * pattern, don't call it directly, use the appropriate macro + * defined in H5Sprivate.h. + * + *------------------------------------------------------------------------- + */ +herr_t +H5S_select_iter_get_seq_list(H5S_sel_iter_t *iter, size_t maxseq, size_t maxelmts, size_t *nseq, + size_t *nelmts, hsize_t *off, size_t *len) +{ + herr_t ret_value = FAIL; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Sanity check */ + HDassert(iter); + + /* Call the selection type's get_seq_list function */ + if ((ret_value = (*iter->type->iter_get_seq_list)(iter, maxseq, maxelmts, nseq, nelmts, off, len)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get selection sequence list") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S_select_iter_get_seq_list() */ + /*-------------------------------------------------------------------------- NAME H5S_select_iter_release PURPOSE Release a selection iterator's resources. USAGE - hssize_t H5S_select_iter_release(sel_iter) + herr_t H5S_select_iter_release(sel_iter) H5S_sel_iter_t *sel_iter; IN: Selection iterator to query RETURNS The number of elements in selection on success, 0 on failure @@ -1168,29 +1454,28 @@ H5S_select_iter_next_block(H5S_sel_iter_t *iter) herr_t H5S_select_iter_release(H5S_sel_iter_t *sel_iter) { - herr_t ret_value; /* return value */ + herr_t ret_value = FAIL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR /* Check args */ - assert(sel_iter); + HDassert(sel_iter); /* Call selection type-specific release routine */ ret_value = (*sel_iter->type->iter_release)(sel_iter); FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_select_iter_release() */ +} /* end H5S_select_iter_release() */ - /*-------------------------------------------------------------------------- NAME H5S_select_iterate PURPOSE Iterate over the selected elements in a memory buffer. USAGE - herr_t H5S_select_iterate(buf, type_id, space, operator, operator_data) + herr_t H5S_select_iterate(buf, type, space, operator, operator_data) void *buf; IN/OUT: Buffer containing elements to iterate over - hid_t type_id; IN: Datatype ID of BUF array. + H5T_t *type; IN: Datatype of BUF array. H5S_t *space; IN: Dataspace object containing selection to iterate over H5D_operator_t op; IN: Function pointer to the routine to be called for each element in BUF iterated over. @@ -1211,75 +1496,80 @@ H5S_select_iter_release(H5S_sel_iter_t *sel_iter) the selection is not modified. --------------------------------------------------------------------------*/ herr_t -H5S_select_iterate(void *buf, hid_t type_id, const H5S_t *space, H5D_operator_t op, - void *operator_data) +H5S_select_iterate(void *buf, const H5T_t *type, H5S_t *space, const H5S_sel_iter_op_t *op, void *op_data) { - H5T_t *dt; /* Datatype structure */ - H5S_sel_iter_t iter; /* Selection iteration info */ - hbool_t iter_init = FALSE; /* Selection iteration info has been initialized */ - uint8_t *loc; /* Current element location in buffer */ - hsize_t coords[H5O_LAYOUT_NDIMS]; /* Coordinates of element in dataspace */ - hssize_t nelmts; /* Number of elements in selection */ - hsize_t space_size[H5O_LAYOUT_NDIMS]; /* Dataspace size */ - hsize_t off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets */ - hsize_t curr_off; /* Current offset within sequence */ - hsize_t tmp_off; /* Temporary offset within sequence */ - size_t len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths */ - size_t curr_len; /* Length of bytes left to process in sequence */ - size_t nseq; /* Number of sequences generated */ - size_t curr_seq; /* Current sequnce being worked on */ - size_t nelem; /* Number of elements used in sequences */ - size_t max_elem; /* Maximum number of elements allowed in sequences */ - size_t elmt_size; /* Datatype size */ - unsigned ndims; /* Number of dimensions in dataspace */ - int i; /* Local Index variable */ - herr_t user_ret=0; /* User's return value */ - herr_t ret_value=SUCCEED; /* Return value */ + H5S_sel_iter_t *iter = NULL; /* Selection iteration info */ + hbool_t iter_init = FALSE; /* Selection iteration info has been initialized */ + hsize_t *off = NULL; /* Array to store sequence offsets */ + size_t *len = NULL; /* Array to store sequence lengths */ + hssize_t nelmts; /* Number of elements in selection */ + hsize_t space_size[H5S_MAX_RANK]; /* Dataspace size */ + size_t max_elem; /* Maximum number of elements allowed in sequences */ + size_t elmt_size; /* Datatype size */ + unsigned ndims; /* Number of dimensions in dataspace */ + herr_t user_ret = 0; /* User's return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) /* Check args */ HDassert(buf); - HDassert(H5I_DATATYPE == H5I_get_type(type_id)); + HDassert(type); HDassert(space); HDassert(op); /* Get the datatype size */ - if(NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an valid base datatype") - if(0 == (elmt_size = H5T_get_size(dt))) + if (0 == (elmt_size = H5T_get_size(type))) HGOTO_ERROR(H5E_DATATYPE, H5E_BADSIZE, FAIL, "datatype size invalid") + /* Allocate the selection iterator */ + if (NULL == (iter = H5FL_MALLOC(H5S_sel_iter_t))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate selection iterator") + /* Initialize iterator */ - if(H5S_select_iter_init(&iter, space, elmt_size) < 0) + if (H5S_select_iter_init(iter, space, elmt_size, 0) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator") - iter_init = TRUE; /* Selection iteration info has been initialized */ + iter_init = TRUE; /* Selection iteration info has been initialized */ /* Get the number of elements in selection */ - if((nelmts = (hssize_t)H5S_GET_SELECT_NPOINTS(space)) < 0) + if ((nelmts = (hssize_t)H5S_GET_SELECT_NPOINTS(space)) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't get number of elements selected") /* Get the rank of the dataspace */ ndims = space->extent.rank; - if(ndims > 0) { - /* Copy the size of the space */ - HDassert(space->extent.size); - HDmemcpy(space_size, space->extent.size, ndims * sizeof(hsize_t)); + if (ndims > 0) { + /* Copy the size of the space */ + HDassert(space->extent.size); + H5MM_memcpy(space_size, space->extent.size, ndims * sizeof(hsize_t)); } /* end if */ space_size[ndims] = elmt_size; /* Compute the maximum number of bytes required */ - H5_ASSIGN_OVERFLOW(max_elem, nelmts, hssize_t, size_t); + H5_CHECKED_ASSIGN(max_elem, size_t, nelmts, hssize_t); + + /* Allocate the offset & length arrays */ + if (NULL == (len = H5FL_SEQ_MALLOC(size_t, H5D_IO_VECTOR_SIZE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate length vector array") + if (NULL == (off = H5FL_SEQ_MALLOC(hsize_t, H5D_IO_VECTOR_SIZE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate offset vector array") /* Loop, while elements left in selection */ - while(max_elem > 0 && user_ret == 0) { + while (max_elem > 0 && user_ret == 0) { + size_t nelem; /* Number of elements used in sequences */ + size_t nseq; /* Number of sequences generated */ + size_t curr_seq; /* Current sequence being worked on */ + /* Get the sequences of bytes */ - if(H5S_SELECT_GET_SEQ_LIST(space, 0, &iter, (size_t)H5D_IO_VECTOR_SIZE, max_elem, &nseq, &nelem, off, len) < 0) + if (H5S_SELECT_ITER_GET_SEQ_LIST(iter, (size_t)H5D_IO_VECTOR_SIZE, max_elem, &nseq, &nelem, off, + len) < 0) HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed") /* Loop, while sequences left to process */ - for(curr_seq=0; curr_seq<nseq && user_ret==0; curr_seq++) { + for (curr_seq = 0; curr_seq < nseq && user_ret == 0; curr_seq++) { + hsize_t curr_off; /* Current offset within sequence */ + size_t curr_len; /* Length of bytes left to process in sequence */ + /* Get the current offset */ curr_off = off[curr_seq]; @@ -1287,9 +1577,14 @@ H5S_select_iterate(void *buf, hid_t type_id, const H5S_t *space, H5D_operator_t curr_len = len[curr_seq]; /* Loop, while bytes left in sequence */ - while(curr_len > 0 && user_ret == 0) { + while (curr_len > 0 && user_ret == 0) { + hsize_t coords[H5S_MAX_RANK]; /* Coordinates of element in dataspace */ + hsize_t tmp_off; /* Temporary offset within sequence */ + uint8_t *loc; /* Current element location in buffer */ + int i; /* Local Index variable */ + /* Compute the coordinate from the offset */ - for(i = (int)ndims, tmp_off = curr_off; i >= 0; i--) { + for (i = (int)ndims, tmp_off = curr_off; i >= 0; i--) { coords[i] = tmp_off % space_size[i]; tmp_off /= space_size[i]; } /* end for */ @@ -1297,33 +1592,57 @@ H5S_select_iterate(void *buf, hid_t type_id, const H5S_t *space, H5D_operator_t /* Get the location within the user's buffer */ loc = (unsigned char *)buf + curr_off; - /* Call user's callback routine */ - user_ret=(*op)(loc,type_id,ndims,coords,operator_data); + /* Check which type of callback to make */ + switch (op->op_type) { + case H5S_SEL_ITER_OP_APP: + /* Make the application callback */ + user_ret = (op->u.app_op.op)(loc, op->u.app_op.type_id, ndims, coords, op_data); + break; + + case H5S_SEL_ITER_OP_LIB: + /* Call the library's callback */ + user_ret = (op->u.lib_op)(loc, type, ndims, coords, op_data); + break; + + default: + HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unsupported op type") + } /* end switch */ + + /* Check for error return from iterator */ + if (user_ret < 0) + HERROR(H5E_DATASPACE, H5E_CANTNEXT, "iteration operator failed"); /* Increment offset in dataspace */ - curr_off+=elmt_size; + curr_off += elmt_size; /* Decrement number of bytes left in sequence */ - curr_len-=elmt_size; + curr_len -= elmt_size; } /* end while */ - } /* end for */ + } /* end for */ /* Decrement number of elements left to process */ - max_elem-=nelem; + max_elem -= nelem; } /* end while */ /* Set return value */ - ret_value=user_ret; + ret_value = user_ret; done: + /* Release resources, if allocated */ + if (len) + len = H5FL_SEQ_FREE(size_t, len); + if (off) + off = H5FL_SEQ_FREE(hsize_t, off); + /* Release selection iterator */ - if(iter_init && H5S_SELECT_ITER_RELEASE(&iter) < 0) + if (iter_init && H5S_SELECT_ITER_RELEASE(iter) < 0) HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator") + if (iter) + iter = H5FL_FREE(H5S_sel_iter_t, iter); FUNC_LEAVE_NOAPI(ret_value) -} /* end H5S_select_iterate() */ +} /* end H5S_select_iterate() */ - /*-------------------------------------------------------------------------- NAME H5Sget_select_type @@ -1336,30 +1655,29 @@ done: Non-negative on success/Negative on failure. Return value is from the set of values in the H5S_sel_type enumerated type. DESCRIPTION - This function retrieves the type of selection currently defined for + This function retrieves the type of selection currently defined for a dataspace. --------------------------------------------------------------------------*/ H5S_sel_type H5Sget_select_type(hid_t space_id) { - H5S_t *space; /* dataspace to modify */ - H5S_sel_type ret_value; /* Return value */ + H5S_t *space; /* dataspace to modify */ + H5S_sel_type ret_value; /* Return value */ FUNC_ENTER_API(H5S_SEL_ERROR) H5TRACE1("St", "i", space_id); /* Check args */ - if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, H5S_SEL_ERROR, "not a dataspace") + if (NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ID, H5E_BADID, H5S_SEL_ERROR, "not a dataspace") /* Set return value */ ret_value = H5S_GET_SELECT_TYPE(space); done: FUNC_LEAVE_API(ret_value) -} /* end H5Sget_select_type() */ +} /* end H5Sget_select_type() */ - /*-------------------------------------------------------------------------- NAME H5S_get_select_type @@ -1372,30 +1690,29 @@ done: Non-negative on success/Negative on failure. Return value is from the set of values in the H5S_sel_type enumerated type. DESCRIPTION - This function retrieves the type of selection currently defined for + This function retrieves the type of selection currently defined for a dataspace. COMMENTS This routine participates in the "Inlining C function pointers" pattern, don't call it directly, use the appropriate macro defined in H5Sprivate.h. --------------------------------------------------------------------------*/ -H5S_sel_type +H5_ATTR_PURE H5S_sel_type H5S_get_select_type(const H5S_t *space) { - H5S_sel_type ret_value; /* Return value */ + H5S_sel_type ret_value = H5S_SEL_ERROR; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR /* Check args */ - assert(space); + HDassert(space); /* Set return value */ - ret_value=H5S_GET_SELECT_TYPE(space); + ret_value = H5S_GET_SELECT_TYPE(space); FUNC_LEAVE_NOAPI(ret_value) -} /* end H5S_get_select_type() */ +} /* end H5S_get_select_type() */ - /*-------------------------------------------------------------------------- NAME H5S_select_shape_same @@ -1410,23 +1727,23 @@ H5S_get_select_type(const H5S_t *space) DESCRIPTION Checks to see if the current selection in the dataspaces are the same dimensionality and shape. + This is primarily used for reading the entire selection in one swoop. GLOBAL VARIABLES COMMENTS, BUGS, ASSUMPTIONS - Assumes that there is only a single "block" for hyperslab selections. + This routine participates in the "Inlining C function pointers" pattern, + don't call it directly, use the appropriate macro defined in H5Sprivate.h. EXAMPLES REVISION LOG - Modified function to view identical shapes with different dimensions - as being the same under some circumstances. --------------------------------------------------------------------------*/ htri_t -H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2) +H5S_select_shape_same(H5S_t *space1, H5S_t *space2) { - H5S_sel_iter_t iter_a; /* Selection a iteration info */ - H5S_sel_iter_t iter_b; /* Selection b iteration info */ - hbool_t iter_a_init = 0; /* Selection a iteration info has been initialized */ - hbool_t iter_b_init = 0; /* Selection b iteration info has been initialized */ - htri_t ret_value = TRUE; /* Return value */ + H5S_sel_iter_t *iter_a = NULL; /* Selection a iteration info */ + H5S_sel_iter_t *iter_b = NULL; /* Selection b iteration info */ + hbool_t iter_a_init = FALSE; /* Selection a iteration info has been initialized */ + hbool_t iter_b_init = FALSE; /* Selection b iteration info has been initialized */ + htri_t ret_value = TRUE; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -1434,197 +1751,178 @@ H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2) HDassert(space1); HDassert(space2); - /* Special case for one or both dataspaces being scalar */ - if(space1->extent.rank == 0 || space2->extent.rank == 0) { - /* Check for different number of elements selected */ - if(H5S_GET_SELECT_NPOINTS(space1) != H5S_GET_SELECT_NPOINTS(space2)) - HGOTO_DONE(FALSE) - } /* end if */ - else { - const H5S_t *space_a; /* Dataspace with larger rank */ - const H5S_t *space_b; /* Dataspace with smaller rank */ - unsigned space_a_rank; /* Number of dimensions of dataspace A */ - unsigned space_b_rank; /* Number of dimensions of dataspace B */ - - /* need to be able to handle spaces of different rank: + /* Check for different number of elements selected */ + if (H5S_GET_SELECT_NPOINTS(space1) != H5S_GET_SELECT_NPOINTS(space2)) + HGOTO_DONE(FALSE) + + /* Check special cases if both dataspaces aren't scalar */ + /* (If only one is, the number of selected points check is sufficient) */ + if (space1->extent.rank > 0 && space2->extent.rank > 0) { + H5S_t *space_a; /* Dataspace with larger rank */ + H5S_t *space_b; /* Dataspace with smaller rank */ + unsigned space_a_rank; /* Number of dimensions of dataspace A */ + unsigned space_b_rank; /* Number of dimensions of dataspace B */ + int space_a_dim; /* Current dimension in dataspace A */ + int space_b_dim; /* Current dimension in dataspace B */ + H5S_sel_type sel_a_type; /* Selection type for dataspace A */ + H5S_sel_type sel_b_type; /* Selection type for dataspace B */ + + /* Need to be able to handle spaces of different rank: * * To simplify logic, let space_a point to the element of the set - * {space1, space2} with the largest rank or space1 if the ranks + * {space1, space2} with the largest rank or space1 if the ranks * are identical. * * Similarly, let space_b point to the element of {space1, space2} * with the smallest rank, or space2 if they are identical. * - * Let: space_a_rank be the rank of space_a, + * Let: space_a_rank be the rank of space_a, * space_b_rank be the rank of space_b, - * delta_rank = space_a_rank - space_b_rank. * - * Set all this up below. + * Set all this up here. */ - if(space1->extent.rank >= space2->extent.rank) { + if (space1->extent.rank >= space2->extent.rank) { space_a = space1; - space_a_rank = space_a->extent.rank; - space_b = space2; - space_b_rank = space_b->extent.rank; } /* end if */ else { space_a = space2; - space_a_rank = space_a->extent.rank; - space_b = space1; - space_b_rank = space_b->extent.rank; } /* end else */ + space_a_rank = space_a->extent.rank; + space_b_rank = space_b->extent.rank; HDassert(space_a_rank >= space_b_rank); HDassert(space_b_rank > 0); - /* Check for different number of elements selected */ - if(H5S_GET_SELECT_NPOINTS(space_a) != H5S_GET_SELECT_NPOINTS(space_b)) - HGOTO_DONE(FALSE) - - /* Check for "easy" cases before getting into generalized block iteration code */ - if((H5S_GET_SELECT_TYPE(space_a) == H5S_SEL_ALL) && (H5S_GET_SELECT_TYPE(space_b) == H5S_SEL_ALL)) { - hsize_t dims1[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #1 */ - hsize_t dims2[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #2 */ - int space_a_dim; /* Current dimension in dataspace A */ - int space_b_dim; /* Current dimension in dataspace B */ - - if(H5S_get_simple_extent_dims(space_a, dims1, NULL) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality") - if(H5S_get_simple_extent_dims(space_b, dims2, NULL) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality") - + /* Get selection type for both dataspaces */ + sel_a_type = H5S_GET_SELECT_TYPE(space_a); + sel_b_type = H5S_GET_SELECT_TYPE(space_b); + + /* If selections aren't "none", compare their bounds */ + if (sel_a_type != H5S_SEL_NONE && sel_b_type != H5S_SEL_NONE) { + hsize_t low_a[H5S_MAX_RANK]; /* Low bound of selection in dataspace a */ + hsize_t low_b[H5S_MAX_RANK]; /* Low bound of selection in dataspace b */ + hsize_t high_a[H5S_MAX_RANK]; /* High bound of selection in dataspace a */ + hsize_t high_b[H5S_MAX_RANK]; /* High bound of selection in dataspace b */ + + /* Get low & high bounds for both dataspaces */ + if (H5S_SELECT_BOUNDS(space_a, low_a, high_a) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, + "can't get selection bounds for first dataspace") + if (H5S_SELECT_BOUNDS(space_b, low_b, high_b) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, + "can't get selection bounds for second dataspace") + + /* Check that the range between the low & high bounds are the same */ space_a_dim = (int)space_a_rank - 1; space_b_dim = (int)space_b_rank - 1; + while (space_b_dim >= 0) { + /* Sanity check */ + HDassert(low_a[space_a_dim] <= high_a[space_a_dim]); + HDassert(low_a[space_b_dim] <= high_a[space_b_dim]); - /* recall that space_a_rank >= space_b_rank. - * - * In the following while loop, we test to see if space_a and space_b - * have identical size in all dimensions they have in common. - */ - while(space_b_dim >= 0) { - if(dims1[space_a_dim] != dims2[space_b_dim]) + /* Verify that the ranges are the same */ + if ((high_a[space_a_dim] - low_a[space_a_dim]) != (high_b[space_b_dim] - low_b[space_b_dim])) HGOTO_DONE(FALSE) + /* Go to next dimension */ space_a_dim--; space_b_dim--; } /* end while */ - /* Since we are selecting the entire spaces, we must also verify that space_a - * has size 1 in all dimensions that it does not share with space_b. - */ - while(space_a_dim >= 0) { - if(dims1[space_a_dim] != 1) - HGOTO_DONE(FALSE) + /* Check that the rest of the ranges in space a are "flat" */ + while (space_a_dim >= 0) { + /* Sanity check */ + HDassert(low_a[space_a_dim] <= high_a[space_a_dim]); - space_a_dim--; - } /* end while */ - } /* end if */ - else if((H5S_GET_SELECT_TYPE(space1) == H5S_SEL_NONE) || (H5S_GET_SELECT_TYPE(space2) == H5S_SEL_NONE)) { - HGOTO_DONE(TRUE) - } /* end if */ - else if((H5S_GET_SELECT_TYPE(space_a) == H5S_SEL_HYPERSLABS && space_a->select.sel_info.hslab->diminfo_valid) - && (H5S_GET_SELECT_TYPE(space_b) == H5S_SEL_HYPERSLABS && space_b->select.sel_info.hslab->diminfo_valid)) { - int space_a_dim; /* Current dimension in dataspace A */ - int space_b_dim; /* Current dimension in dataspace B */ - - space_a_dim = (int)space_a_rank - 1; - space_b_dim = (int)space_b_rank - 1; - - /* check that the shapes are the same in the common dimensions, and that - * block == 1 in all dimensions that appear only in space_a. - */ - while(space_b_dim >= 0) { - if(space_a->select.sel_info.hslab->opt_diminfo[space_a_dim].stride != - space_b->select.sel_info.hslab->opt_diminfo[space_b_dim].stride) - HGOTO_DONE(FALSE) - - if(space_a->select.sel_info.hslab->opt_diminfo[space_a_dim].count != - space_b->select.sel_info.hslab->opt_diminfo[space_b_dim].count) - HGOTO_DONE(FALSE) - - if(space_a->select.sel_info.hslab->opt_diminfo[space_a_dim].block != - space_b->select.sel_info.hslab->opt_diminfo[space_b_dim].block) + /* This range should be flat to be the same in a lower dimension */ + if (low_a[space_a_dim] != high_a[space_a_dim]) HGOTO_DONE(FALSE) space_a_dim--; - space_b_dim--; } /* end while */ - while(space_a_dim >= 0) { - if(space_a->select.sel_info.hslab->opt_diminfo[space_a_dim].block != 1) - HGOTO_DONE(FALSE) + /* Check for a single block in each selection */ + if (H5S_SELECT_IS_SINGLE(space_a) && H5S_SELECT_IS_SINGLE(space_b)) { + /* If both selections are a single block and their bounds are + * the same, then the selections are the same, even if the + * selection types are different. + */ + HGOTO_DONE(TRUE) + } /* end if */ + } /* end if */ - space_a_dim--; - } /* end while */ - } /* end if */ - /* Iterate through all the blocks in the selection */ + /* If the dataspaces have the same selection type, use the selection's + * shape_same operator. + */ + if (sel_a_type == sel_b_type) + ret_value = (*space_a->select.type->shape_same)(space_a, space_b); + /* Otherwise, iterate through all the blocks in the selection */ else { - hsize_t start_a[H5O_LAYOUT_NDIMS]; /* Start point of selection block in dataspace a */ - hsize_t start_b[H5O_LAYOUT_NDIMS]; /* Start point of selection block in dataspace b */ - hsize_t end_a[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace a */ - hsize_t end_b[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace b */ - hsize_t off_a[H5O_LAYOUT_NDIMS]; /* Offset of selection a blocks */ - hsize_t off_b[H5O_LAYOUT_NDIMS]; /* Offset of selection b blocks */ - hbool_t first_block = TRUE; /* Flag to indicate the first block */ + hsize_t start_a[H5S_MAX_RANK]; /* Start point of selection block in dataspace a */ + hsize_t start_b[H5S_MAX_RANK]; /* Start point of selection block in dataspace b */ + hsize_t end_a[H5S_MAX_RANK]; /* End point of selection block in dataspace a */ + hsize_t end_b[H5S_MAX_RANK]; /* End point of selection block in dataspace b */ + hssize_t offset[H5S_MAX_RANK]; /* Offset of selection b blocks relative to selection a blocks */ + hbool_t first_block = TRUE; /* Flag to indicate the first block */ + + /* Allocate the selection iterators */ + if (NULL == (iter_a = H5FL_MALLOC(H5S_sel_iter_t))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate selection iterator") + if (NULL == (iter_b = H5FL_MALLOC(H5S_sel_iter_t))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate selection iterator") /* Initialize iterator for each dataspace selection * Use '0' for element size instead of actual element size to indicate * that the selection iterator shouldn't be "flattened", since we * aren't actually going to be doing I/O with the iterators. */ - if(H5S_select_iter_init(&iter_a, space_a, (size_t)0) < 0) + if (H5S_select_iter_init(iter_a, space_a, (size_t)0, 0) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator a") - iter_a_init = 1; - if(H5S_select_iter_init(&iter_b, space_b, (size_t)0) < 0) + iter_a_init = TRUE; + if (H5S_select_iter_init(iter_b, space_b, (size_t)0, 0) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator b") - iter_b_init = 1; + iter_b_init = TRUE; /* Iterate over all the blocks in each selection */ - while(1) { - int space_a_dim; /* Current dimension in dataspace A */ - int space_b_dim; /* Current dimension in dataspace B */ - htri_t status_a, status_b; /* Status from next block checks */ + while (1) { + htri_t status_a, status_b; /* Status from next block checks */ /* Get the current block for each selection iterator */ - if(H5S_SELECT_ITER_BLOCK(&iter_a, start_a, end_a) < 0) + if (H5S_SELECT_ITER_BLOCK(iter_a, start_a, end_a) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get iterator block a") - if(H5S_SELECT_ITER_BLOCK(&iter_b, start_b, end_b) < 0) + if (H5S_SELECT_ITER_BLOCK(iter_b, start_b, end_b) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get iterator block b") space_a_dim = (int)space_a_rank - 1; space_b_dim = (int)space_b_rank - 1; - /* The first block only compares the sizes and sets the - * relative offsets for later blocks + /* The first block only compares the sizes and sets the + * relative offsets for later blocks */ - if(first_block) { - /* If the block sizes in the common dimensions from + if (first_block) { + /* If the block sizes in the common dimensions from * each selection don't match, get out */ - while(space_b_dim >= 0) { - if((end_a[space_a_dim] - start_a[space_a_dim]) != - (end_b[space_b_dim] - start_b[space_b_dim])) + while (space_b_dim >= 0) { + if ((end_a[space_a_dim] - start_a[space_a_dim]) != + (end_b[space_b_dim] - start_b[space_b_dim])) HGOTO_DONE(FALSE) /* Set the relative locations of the selections */ - off_a[space_a_dim] = start_a[space_a_dim]; - off_b[space_b_dim] = start_b[space_b_dim]; + offset[space_a_dim] = (hssize_t)start_b[space_b_dim] - (hssize_t)start_a[space_a_dim]; space_a_dim--; space_b_dim--; } /* end while */ - /* similarly, if the block size in any dimension that appears only + /* Similarly, if the block size in any dimension that appears only * in space_a is not equal to 1, get out. */ - while(space_a_dim >= 0) { - if((end_a[space_a_dim] - start_a[space_a_dim]) != 0) + while (space_a_dim >= 0) { + if (start_a[space_a_dim] != end_a[space_a_dim]) HGOTO_DONE(FALSE) - /* Set the relative locations of the selections */ - off_a[space_a_dim] = start_a[space_a_dim]; - space_a_dim--; } /* end while */ @@ -1633,16 +1931,16 @@ H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2) } /* end if */ /* Check over the blocks for each selection */ else { - /* for dimensions that space_a and space_b have in common: */ - while(space_b_dim >= 0) { + /* For dimensions that space_a and space_b have in common: */ + while (space_b_dim >= 0) { /* Check if the blocks are in the same relative location */ - if((start_a[space_a_dim] - off_a[space_a_dim]) != - (start_b[space_b_dim] - off_b[space_b_dim])) + if ((hsize_t)((hssize_t)start_a[space_a_dim] + offset[space_a_dim]) != + start_b[space_b_dim]) HGOTO_DONE(FALSE) /* If the block sizes from each selection doesn't match, get out */ - if((end_a[space_a_dim] - start_a[space_a_dim]) != - (end_b[space_b_dim] - start_b[space_b_dim])) + if ((end_a[space_a_dim] - start_a[space_a_dim]) != + (end_b[space_b_dim] - start_b[space_b_dim])) HGOTO_DONE(FALSE) space_a_dim--; @@ -1650,248 +1948,404 @@ H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2) } /* end while */ /* For dimensions that appear only in space_a: */ - while(space_a_dim >= 0) { + while (space_a_dim >= 0) { /* If the block size isn't 1, get out */ - if((end_a[space_a_dim] - start_a[space_a_dim]) != 0) + if (start_a[space_a_dim] != end_a[space_a_dim]) HGOTO_DONE(FALSE) space_a_dim--; } /* end while */ - } /* end else */ + } /* end else */ /* Check if we are able to advance to the next selection block */ - if((status_a = H5S_SELECT_ITER_HAS_NEXT_BLOCK(&iter_a)) < 0) + if ((status_a = H5S_SELECT_ITER_HAS_NEXT_BLOCK(iter_a)) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to check iterator block a") - if((status_b = H5S_SELECT_ITER_HAS_NEXT_BLOCK(&iter_b)) < 0) + if ((status_b = H5S_SELECT_ITER_HAS_NEXT_BLOCK(iter_b)) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to check iterator block b") /* Did we run out of blocks at the same time? */ - if((status_a == FALSE) && (status_b == FALSE)) + if ((status_a == FALSE) && (status_b == FALSE)) break; - else if(status_a != status_b) + else if (status_a != status_b) HGOTO_DONE(FALSE) else { /* Advance to next block in selection iterators */ - if(H5S_SELECT_ITER_NEXT_BLOCK(&iter_a) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to advance to next iterator block a") + if (H5S_SELECT_ITER_NEXT_BLOCK(iter_a) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL, + "unable to advance to next iterator block a") - if(H5S_SELECT_ITER_NEXT_BLOCK(&iter_b) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL, "unable to advance to next iterator block b") + if (H5S_SELECT_ITER_NEXT_BLOCK(iter_b) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL, + "unable to advance to next iterator block b") } /* end else */ - } /* end while */ - } /* end else */ - } /* end else */ + } /* end while */ + } /* end else */ + } /* end if */ done: - if(iter_a_init) - if(H5S_SELECT_ITER_RELEASE(&iter_a) < 0) - HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator a") - if(iter_b_init) - if(H5S_SELECT_ITER_RELEASE(&iter_b) < 0) - HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator b") + if (iter_a_init && H5S_SELECT_ITER_RELEASE(iter_a) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator a") + if (iter_a) + iter_a = H5FL_FREE(H5S_sel_iter_t, iter_a); + if (iter_b_init && H5S_SELECT_ITER_RELEASE(iter_b) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator b") + if (iter_b) + iter_b = H5FL_FREE(H5S_sel_iter_t, iter_b); FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_select_shape_same() */ +} /* end H5S_select_shape_same() */ + +/*-------------------------------------------------------------------------- + NAME + H5Sselect_shape_same + PURPOSE + Check if two selections are the same shape + USAGE + htri_t H5Sselect_shape_same(space1_id, space2_id) + hid_t space1_id; IN: ID of 1st Dataspace pointer to compare + hid_t space2_id; IN: ID of 2nd Dataspace pointer to compare + RETURNS + TRUE/FALSE/FAIL + DESCRIPTION + Checks to see if the current selection in the dataspaces are the same + dimensionality and shape. + This is primarily used for reading the entire selection in one swoop. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +htri_t +H5Sselect_shape_same(hid_t space1_id, hid_t space2_id) +{ + H5S_t *space1, *space2; /* Dataspaces to compare */ + htri_t ret_value; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("t", "ii", space1_id, space2_id); + + if (NULL == (space1 = (H5S_t *)H5I_object_verify(space1_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace") + if (NULL == (space2 = (H5S_t *)H5I_object_verify(space2_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace") + + if ((ret_value = H5S_select_shape_same(space1, space2)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "can't compare selections") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Sselect_shape_same() */ + +/*-------------------------------------------------------------------------- + NAME + H5S_select_intersect_block + PURPOSE + Check if current selection intersects with a block + USAGE + htri_t H5S_select_intersect_block(space, start, end) + const H5S_t *space; IN: Dataspace to compare + const hsize_t *start; IN: Starting coordinate of block + const hsize_t *end; IN: Opposite ("ending") coordinate of block + RETURNS + TRUE / FALSE / FAIL + DESCRIPTION + Checks to see if the current selection in the dataspace intersects with + the block given. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + Assumes that start & end block bounds are _inclusive_, so start == end + value OK. + + This routine participates in the "Inlining C function pointers" pattern, + don't call it directly, use the appropriate macro defined in H5Sprivate.h. +--------------------------------------------------------------------------*/ +htri_t +H5S_select_intersect_block(H5S_t *space, const hsize_t *start, const hsize_t *end) +{ + htri_t ret_value = TRUE; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Check args */ + HDassert(space); + HDassert(start); + HDassert(end); + + /* If selections aren't "none", compare their bounds */ + if (H5S_SEL_NONE != H5S_GET_SELECT_TYPE(space)) { + hsize_t low[H5S_MAX_RANK]; /* Low bound of selection in dataspace */ + hsize_t high[H5S_MAX_RANK]; /* High bound of selection in dataspace */ + unsigned u; /* Local index variable */ + + /* Get low & high bounds for dataspace selection */ + if (H5S_SELECT_BOUNDS(space, low, high) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get selection bounds for dataspace") + + /* Loop over selection bounds and block, checking for overlap */ + for (u = 0; u < space->extent.rank; u++) + /* If selection bounds & block don't overlap, can leave now */ + if (!H5S_RANGE_OVERLAP(low[u], high[u], start[u], end[u])) + HGOTO_DONE(FALSE) + } /* end if */ + + /* Call selection type's intersect routine */ + if ((ret_value = (*space->select.type->intersect_block)(space, start, end)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "can't intersect block with selection") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S_select_intersect_block() */ + +/*-------------------------------------------------------------------------- + NAME + H5Sselect_intersect_block + PURPOSE + Check if current selection intersects with a block + USAGE + htri_t H5Sselect_intersect_block(space_id, start, end) + hid_t space1_id; IN: ID of dataspace pointer to compare + const hsize_t *start; IN: Starting coordinate of block + const hsize_t *end; IN: Opposite ("ending") coordinate of block + RETURNS + TRUE / FALSE / FAIL + DESCRIPTION + Checks to see if the current selection in the dataspace intersects with + the block given. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + Assumes that start & end block bounds are _inclusive_, so start == end + value OK. + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +htri_t +H5Sselect_intersect_block(hid_t space_id, const hsize_t *start, const hsize_t *end) +{ + H5S_t *space; /* Dataspace to query */ + unsigned u; /* Local index value */ + htri_t ret_value = FAIL; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE3("t", "i*h*h", space_id, start, end); + + /* Check arguments */ + if (NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace") + if (NULL == start) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "block start array pointer is NULL") + if (NULL == end) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "block end array pointer is NULL") + + /* Range check start & end values */ + for (u = 0; u < space->extent.rank; u++) + if (start[u] > end[u]) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "block start[%u] (%llu) > end[%u] (%llu)", u, + (unsigned long long)start[u], u, (unsigned long long)end[u]) + + /* Call internal routine to do comparison */ + if ((ret_value = H5S_select_intersect_block(space, start, end)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "can't compare selection and block") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Sselect_intersect_block() */ - /*-------------------------------------------------------------------------- NAME H5S_select_construct_projection PURPOSE Given a dataspace a of rank n with some selection, construct a new - dataspace b of rank m (m != n), with the selection in a being - topologically identical to that in b (as verified by + dataspace b of rank m (m != n), with the selection in a being + topologically identical to that in b (as verified by H5S_select_shape_same(). - This function exists, as some I/O code chokes of topologically - identical selections with different ranks. At least to begin + This function exists, as some I/O code chokes on topologically + identical selections with different ranks. At least to begin with, we will deal with the issue by constructing projections - of the memory dataspace with ranks equaling those of the file + of the memory dataspace with ranks equaling those of the file dataspace. - Note that if m > n, it is possible that the starting point in the - buffer associated with the memory dataspace will have to be - adjusted to match the projected dataspace. If the buf parameter - is not NULL, the function must return an adjusted buffer base - address in *adj_buf_ptr. + Note that if m > n, it is possible that the starting point in the + buffer associated with the memory dataspace will have to be + adjusted to match the projected dataspace. In this case, the amount + of adjustment to be applied to the buffer will be returned via the + buf_adj parameter, if supplied. USAGE - htri_t H5S_select_construct_projection(base_space, + htri_t H5S_select_construct_projection(base_space, new_space_ptr, new_space_rank, - buf, - adj_buf_ptr) + element_size, + buf_adj) const H5S_t *base_space; IN: Ptr to Dataspace to project H5S_t ** new_space_ptr; OUT: Ptr to location in which to return - the address of the projected space + the address of the projected space int new_space_rank; IN: Rank of the projected space. - const void * buf; IN: Base address of the buffer - associated with the base space. - May be NULL. - void ** adj_buf_ptr; OUT: If buf != NULL, store the base - address of the section of buf - that is described by *new_space_ptr - in *adj_buf_ptr. - + hsize_t element_size; IN: size of each element in the selection + ptrdiff_t buf_adj; OUT: amount of adjustment to be applied + to buffer associated with memory + dataspace + RETURNS Non-negative on success/Negative on failure. DESCRIPTION - Construct a new dataspace and associated selection which is a - projection of the supplied dataspace and associated selection into + Construct a new dataspace and associated selection which is a + projection of the supplied dataspace and associated selection into the specified rank. Return it in *new_space_ptr. - If buf is supplied, computes the base address of the projected - selection in buf, and stores the base address in *adj_buf_ptr. - GLOBAL VARIABLES COMMENTS, BUGS, ASSUMPTIONS - The selection in the supplied base_space has thickness 1 in all + The selection in the supplied base_space has thickness 1 in all dimensions greater than new_space_rank. Note that here we count - dimensions from the fastest changing coordinate to the slowest + dimensions from the fastest changing coordinate to the slowest changing changing coordinate. EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5S_select_construct_projection(const H5S_t *base_space, H5S_t **new_space_ptr, - unsigned new_space_rank, const void *buf, void const **adj_buf_ptr, hsize_t element_size) +H5S_select_construct_projection(H5S_t *base_space, H5S_t **new_space_ptr, unsigned new_space_rank, + hsize_t element_size, ptrdiff_t *buf_adj) { - H5S_t * new_space = NULL; /* New dataspace constructed */ - hsize_t base_space_dims[H5S_MAX_RANK]; /* Current dimensions of base dataspace */ - hsize_t base_space_maxdims[H5S_MAX_RANK]; /* Maximum dimensions of base dataspace */ - int sbase_space_rank; /* Signed # of dimensions of base dataspace */ - unsigned base_space_rank; /* # of dimensions of base dataspace */ - hsize_t projected_space_element_offset = 0; /* Offset of selected element in projected buffer */ - herr_t ret_value = SUCCEED; /* Return value */ + H5S_t *new_space = NULL; /* New dataspace constructed */ + hsize_t base_space_dims[H5S_MAX_RANK]; /* Current dimensions of base dataspace */ + hsize_t base_space_maxdims[H5S_MAX_RANK]; /* Maximum dimensions of base dataspace */ + int sbase_space_rank; /* Signed # of dimensions of base dataspace */ + unsigned base_space_rank; /* # of dimensions of base dataspace */ + hsize_t projected_space_element_offset = 0; /* Offset of selected element in projected buffer */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) /* Sanity checks */ HDassert(base_space != NULL); - HDassert((H5S_GET_EXTENT_TYPE(base_space) == H5S_SCALAR) || (H5S_GET_EXTENT_TYPE(base_space) == H5S_SIMPLE)); + HDassert((H5S_GET_EXTENT_TYPE(base_space) == H5S_SCALAR) || + (H5S_GET_EXTENT_TYPE(base_space) == H5S_SIMPLE)); HDassert(new_space_ptr != NULL); HDassert((new_space_rank != 0) || (H5S_GET_SELECT_NPOINTS(base_space) <= 1)); HDassert(new_space_rank <= H5S_MAX_RANK); - HDassert((buf == NULL) || (adj_buf_ptr != NULL)); - HDassert(element_size > 0 ); + HDassert(element_size > 0); /* Get the extent info for the base dataspace */ - if((sbase_space_rank = H5S_get_simple_extent_dims(base_space, base_space_dims, base_space_maxdims)) < 0) + if ((sbase_space_rank = H5S_get_simple_extent_dims(base_space, base_space_dims, base_space_maxdims)) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality of base space") base_space_rank = (unsigned)sbase_space_rank; HDassert(base_space_rank != new_space_rank); /* Check if projected space is scalar */ - if(new_space_rank == 0) { - hssize_t npoints; /* Number of points selected */ + if (new_space_rank == 0) { + hssize_t npoints; /* Number of points selected */ - /* Retreve the number of elements selected */ - if((npoints = (hssize_t)H5S_GET_SELECT_NPOINTS(base_space)) < 0) + /* Retrieve the number of elements selected */ + if ((npoints = (hssize_t)H5S_GET_SELECT_NPOINTS(base_space)) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get number of points selected") HDassert(npoints <= 1); /* Create new scalar dataspace */ - if(NULL == (new_space = H5S_create(H5S_SCALAR))) + if (NULL == (new_space = H5S_create(H5S_SCALAR))) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create scalar dataspace") - + /* No need to register the dataspace(i.e. get an ID) as * we will just be discarding it shortly. */ - /* Selection for the new space will be either all or + /* Selection for the new space will be either all or * none, depending on whether the base space has 0 or * 1 elements selected. * - * Observe that the base space can't have more than + * Observe that the base space can't have more than * one selected element, since its selection has the - * same shape as the file dataspace, and that data + * same shape as the file dataspace, and that data * space is scalar. */ - if(1 == npoints) { + if (1 == npoints) { /* Assuming that the selection in the base dataspace is not - * empty, we must compute the offset of the selected item in + * empty, we must compute the offset of the selected item in * the buffer associated with the base dataspace. * - * Since the new space rank is zero, we know that the - * the base space must have rank at least 1 -- and - * hence it is a simple dataspace. However, the + * Since the new space rank is zero, we know that the + * the base space must have rank at least 1 -- and + * hence it is a simple dataspace. However, the * selection, may be either point, hyperspace, or all. * */ - if(H5S_SELECT_PROJECT_SCALAR(base_space, &projected_space_element_offset) < 0) + if (H5S_SELECT_PROJECT_SCALAR(base_space, &projected_space_element_offset) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "unable to project scalar selection") } /* end if */ else { HDassert(0 == npoints); - if(H5S_select_none(new_space) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't delete default selection") - } /* end else */ - } /* end if */ - else { /* projected space must be simple */ - hsize_t new_space_dims[H5S_MAX_RANK]; /* Current dimensions for new dataspace */ - hsize_t new_space_maxdims[H5S_MAX_RANK];/* Maximum dimensions for new dataspace */ - unsigned rank_diff; /* Difference in ranks */ - + if (H5S_select_none(new_space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't delete default selection") + } /* end else */ + } /* end if */ + else { /* projected space must be simple */ + hsize_t new_space_dims[H5S_MAX_RANK]; /* Current dimensions for new dataspace */ + hsize_t new_space_maxdims[H5S_MAX_RANK]; /* Maximum dimensions for new dataspace */ + unsigned rank_diff; /* Difference in ranks */ + /* Set up the dimensions of the new, projected dataspace. * - * How we do this depends on whether we are projecting up into - * increased dimensions, or down into a reduced number of + * How we do this depends on whether we are projecting up into + * increased dimensions, or down into a reduced number of * dimensions. * - * If we are projecting up (the first half of the following - * if statement), we copy the dimensions of the base data - * space into the fastest changing dimensions of the new + * If we are projecting up (the first half of the following + * if statement), we copy the dimensions of the base data + * space into the fastest changing dimensions of the new * projected dataspace, and set the remaining dimensions to * one. * * If we are projecting down (the second half of the following - * if statement), we just copy the dimensions with the most + * if statement), we just copy the dimensions with the most * quickly changing dimensions into the dims for the projected * data set. * - * This works, because H5S_select_shape_same() will return + * This works, because H5S_select_shape_same() will return * true on selections of different rank iff: * * 1) the selection in the lower rank dataspace matches that - * in the dimensions with the fastest changing indicies in + * in the dimensions with the fastest changing indices in * the larger rank dataspace, and * * 2) the selection has thickness 1 in all ranks that appear - * only in the higher rank dataspace (i.e. those with - * more slowly changing indicies). - */ - if(new_space_rank > base_space_rank) { - hsize_t tmp_dim_size = 1; /* Temporary dimension value, for filling arrays */ + * only in the higher rank dataspace (i.e. those with + * more slowly changing indices). + */ + if (new_space_rank > base_space_rank) { + hsize_t tmp_dim_size = 1; /* Temporary dimension value, for filling arrays */ - /* we must copy the dimensions of the base space into + /* we must copy the dimensions of the base space into * the fastest changing dimensions of the new space, * and set the remaining dimensions to 1 */ rank_diff = new_space_rank - base_space_rank; - H5V_array_fill(new_space_dims, &tmp_dim_size, sizeof(tmp_dim_size), rank_diff); - H5V_array_fill(new_space_maxdims, &tmp_dim_size, sizeof(tmp_dim_size), rank_diff); - HDmemcpy(&new_space_dims[rank_diff], base_space_dims, sizeof(new_space_dims[0]) * base_space_rank); - HDmemcpy(&new_space_maxdims[rank_diff], base_space_maxdims, sizeof(new_space_maxdims[0]) * base_space_rank); - } /* end if */ + H5VM_array_fill(new_space_dims, &tmp_dim_size, sizeof(tmp_dim_size), rank_diff); + H5VM_array_fill(new_space_maxdims, &tmp_dim_size, sizeof(tmp_dim_size), rank_diff); + H5MM_memcpy(&new_space_dims[rank_diff], base_space_dims, + sizeof(new_space_dims[0]) * base_space_rank); + H5MM_memcpy(&new_space_maxdims[rank_diff], base_space_maxdims, + sizeof(new_space_maxdims[0]) * base_space_rank); + } /* end if */ else { /* new_space_rank < base_space_rank */ - /* we must copy the fastest changing dimension of the + /* we must copy the fastest changing dimension of the * base space into the dimensions of the new space. */ rank_diff = base_space_rank - new_space_rank; - HDmemcpy(new_space_dims, &base_space_dims[rank_diff], sizeof(new_space_dims[0]) * new_space_rank); - HDmemcpy(new_space_maxdims, &base_space_maxdims[rank_diff], sizeof(new_space_maxdims[0]) * new_space_rank); + H5MM_memcpy(new_space_dims, &base_space_dims[rank_diff], + sizeof(new_space_dims[0]) * new_space_rank); + H5MM_memcpy(new_space_maxdims, &base_space_maxdims[rank_diff], + sizeof(new_space_maxdims[0]) * new_space_rank); } /* end else */ - /* now have the new space rank and dimensions set up -- + /* now have the new space rank and dimensions set up -- * so we can create the new simple dataspace. */ - if(NULL == (new_space = H5S_create_simple(new_space_rank, new_space_dims, new_space_maxdims))) + if (NULL == (new_space = H5S_create_simple(new_space_rank, new_space_dims, new_space_maxdims))) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace") - + /* No need to register the dataspace(i.e. get an ID) as * we will just be discarding it shortly. */ @@ -1900,29 +2354,31 @@ H5S_select_construct_projection(const H5S_t *base_space, H5S_t **new_space_ptr, * dataspace. We must now project the selection in the base * dataspace into the projected dataspace. */ - if(H5S_SELECT_PROJECT_SIMPLE(base_space, new_space, &projected_space_element_offset) < 0) + if (H5S_SELECT_PROJECT_SIMPLE(base_space, new_space, &projected_space_element_offset) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "unable to project simple selection") - + /* If we get this far, we have created the new dataspace, and projected * the selection in the base dataspace into the new dataspace. * - * If the base dataspace is simple, check to see if the - * offset_changed flag on the base selection has been set -- if so, - * project the offset into the new dataspace and set the + * If the base dataspace is simple, check to see if the + * offset_changed flag on the base selection has been set -- if so, + * project the offset into the new dataspace and set the * offset_changed flag. */ - if(H5S_GET_EXTENT_TYPE(base_space) == H5S_SIMPLE && base_space->select.offset_changed) { - if(new_space_rank > base_space_rank) { + if (H5S_GET_EXTENT_TYPE(base_space) == H5S_SIMPLE && base_space->select.offset_changed) { + if (new_space_rank > base_space_rank) { HDmemset(new_space->select.offset, 0, sizeof(new_space->select.offset[0]) * rank_diff); - HDmemcpy(&new_space->select.offset[rank_diff], base_space->select.offset, sizeof(new_space->select.offset[0]) * base_space_rank); + H5MM_memcpy(&new_space->select.offset[rank_diff], base_space->select.offset, + sizeof(new_space->select.offset[0]) * base_space_rank); } /* end if */ else - HDmemcpy(new_space->select.offset, &base_space->select.offset[rank_diff], sizeof(new_space->select.offset[0]) * new_space_rank); + H5MM_memcpy(new_space->select.offset, &base_space->select.offset[rank_diff], + sizeof(new_space->select.offset[0]) * new_space_rank); /* Propagate the offset changed flag into the new dataspace. */ new_space->select.offset_changed = TRUE; } /* end if */ - } /* end else */ + } /* end else */ /* If we have done the projection correctly, the following assertion * should hold. @@ -1932,38 +2388,25 @@ H5S_select_construct_projection(const H5S_t *base_space, H5S_t **new_space_ptr, /* load the address of the new space into *new_space_ptr */ *new_space_ptr = new_space; - /* now adjust the buffer if required */ - if(buf != NULL) { - if(new_space_rank < base_space_rank) { - /* a bit of pointer magic here: - * - * Since we can't do pointer arithmetic on void pointers, we first - * cast buf to a pointer to byte -- i.e. uint8_t. - * - * We then multiply the projected space element offset we - * calculated earlier by the supplied element size, add this - * value to the type cast buf pointer, cast the result back - * to a pointer to void, and assign the result to *adj_buf_ptr. - */ - *adj_buf_ptr = (const void *)(((const uint8_t *)buf) + - ((size_t)(projected_space_element_offset * element_size))); - } /* end if */ + /* return the buffer adjustment amount if required */ + if (buf_adj != NULL) { + if (new_space_rank < base_space_rank) { + *buf_adj = (ptrdiff_t)(projected_space_element_offset * element_size); + } else /* No adjustment necessary */ - *adj_buf_ptr = buf; - } /* end if */ + *buf_adj = 0; + } done: /* Cleanup on error */ - if(ret_value < 0) { - if(new_space && H5S_close(new_space) < 0) + if (ret_value < 0) + if (new_space && H5S_close(new_space) < 0) HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace") - } /* end if */ FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_select_construct_projection() */ +} /* end H5S_select_construct_projection() */ - /*-------------------------------------------------------------------------- NAME H5S_select_fill @@ -1989,13 +2432,15 @@ done: REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5S_select_fill(const void *fill, size_t fill_size, const H5S_t *space, void *_buf) +H5S_select_fill(const void *fill, size_t fill_size, H5S_t *space, void *_buf) { - H5S_sel_iter_t iter; /* Selection iteration info */ - hbool_t iter_init = 0; /* Selection iteration info has been initialized */ - hssize_t nelmts; /* Number of elements in selection */ - size_t max_elem; /* Total number of elements in selection */ - herr_t ret_value = SUCCEED; /* Return value */ + H5S_sel_iter_t *iter = NULL; /* Selection iteration info */ + hbool_t iter_init = FALSE; /* Selection iteration info has been initialized */ + hsize_t *off = NULL; /* Array to store sequence offsets */ + size_t *len = NULL; /* Array to store sequence lengths */ + hssize_t nelmts; /* Number of elements in selection */ + size_t max_elem; /* Total number of elements in selection */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -2005,40 +2450,49 @@ H5S_select_fill(const void *fill, size_t fill_size, const H5S_t *space, void *_b HDassert(space); HDassert(_buf); + /* Allocate the selection iterator */ + if (NULL == (iter = H5FL_MALLOC(H5S_sel_iter_t))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate selection iterator") + /* Initialize iterator */ - if(H5S_select_iter_init(&iter, space, fill_size) < 0) + if (H5S_select_iter_init(iter, space, fill_size, 0) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator") - iter_init = 1; /* Selection iteration info has been initialized */ + iter_init = TRUE; /* Selection iteration info has been initialized */ /* Get the number of elements in selection */ - if((nelmts = (hssize_t)H5S_GET_SELECT_NPOINTS(space)) < 0) + if ((nelmts = (hssize_t)H5S_GET_SELECT_NPOINTS(space)) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't get number of elements selected") /* Compute the number of bytes to process */ - H5_ASSIGN_OVERFLOW(max_elem, nelmts, hssize_t, size_t); + H5_CHECKED_ASSIGN(max_elem, size_t, nelmts, hssize_t); + + /* Allocate the offset & length arrays */ + if (NULL == (len = H5FL_SEQ_MALLOC(size_t, H5D_IO_VECTOR_SIZE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate length vector array") + if (NULL == (off = H5FL_SEQ_MALLOC(hsize_t, H5D_IO_VECTOR_SIZE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate offset vector array") /* Loop, while elements left in selection */ - while(max_elem > 0) { - hsize_t off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets */ - size_t len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths */ - size_t nseq; /* Number of sequences generated */ - size_t curr_seq; /* Current sequnce being worked on */ - size_t nelem; /* Number of elements used in sequences */ + while (max_elem > 0) { + size_t nseq; /* Number of sequences generated */ + size_t curr_seq; /* Current sequence being worked on */ + size_t nelem; /* Number of elements used in sequences */ /* Get the sequences of bytes */ - if(H5S_SELECT_GET_SEQ_LIST(space, 0, &iter, (size_t)H5D_IO_VECTOR_SIZE, max_elem, &nseq, &nelem, off, len) < 0) + if (H5S_SELECT_ITER_GET_SEQ_LIST(iter, (size_t)H5D_IO_VECTOR_SIZE, max_elem, &nseq, &nelem, off, + len) < 0) HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed") /* Loop over sequences */ - for(curr_seq = 0; curr_seq < nseq; curr_seq++) { - uint8_t *buf; /* Current location in buffer */ + for (curr_seq = 0; curr_seq < nseq; curr_seq++) { + uint8_t *buf; /* Current location in buffer */ /* Get offset in memory buffer */ buf = (uint8_t *)_buf + off[curr_seq]; /* Fill each sequence in memory with fill value */ HDassert((len[curr_seq] % fill_size) == 0); - H5V_array_fill(buf, fill, fill_size, (len[curr_seq] / fill_size)); + H5VM_array_fill(buf, fill, fill_size, (len[curr_seq] / fill_size)); } /* end for */ /* Decrement number of elements left to process */ @@ -2046,10 +2500,724 @@ H5S_select_fill(const void *fill, size_t fill_size, const H5S_t *space, void *_b } /* end while */ done: - /* Release resouces */ - if(iter_init && H5S_SELECT_ITER_RELEASE(&iter) < 0) + /* Release resources, if allocated */ + if (len) + len = H5FL_SEQ_FREE(size_t, len); + if (off) + off = H5FL_SEQ_FREE(hsize_t, off); + + /* Release selection iterator */ + if (iter_init && H5S_SELECT_ITER_RELEASE(iter) < 0) HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator") + if (iter) + iter = H5FL_FREE(H5S_sel_iter_t, iter); FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_select_fill() */ +} /* end H5S_select_fill() */ + +/*-------------------------------------------------------------------------- + NAME + H5S_select_project_intersection + + PURPOSE + Projects the intersection of of the selections of src_space and + src_intersect_space within the selection of src_space as a selection + within the selection of dst_space + + USAGE + herr_t H5S_select_project_intersection(src_space,dst_space,src_intersect_space,proj_space,share_selection) + H5S_t *src_space; IN: Selection that is mapped to dst_space, and intersected with +src_intersect_space H5S_t *dst_space; IN: Selection that is mapped to src_space H5S_t +*src_intersect_space; IN: Selection whose intersection with src_space is projected to dst_space to obtain the +result H5S_t **new_space_ptr; OUT: Will contain the result (intersection of src_intersect_space and src_space +projected from src_space to dst_space) after the operation hbool_t share_selection; IN: Whether we are allowed +to share structures inside dst_space with proj_space + + RETURNS + Non-negative on success/Negative on failure. + + DESCRIPTION + Projects the intersection of of the selections of src_space and + src_intersect_space within the selection of src_space as a selection + within the selection of dst_space. The result is placed in the + selection of new_space_ptr. + + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_select_project_intersection(H5S_t *src_space, H5S_t *dst_space, H5S_t *src_intersect_space, + H5S_t **new_space_ptr, hbool_t share_selection) +{ + H5S_t *new_space = NULL; /* New dataspace constructed */ + H5S_t *tmp_src_intersect_space = NULL; /* Temporary SIS converted from points->hyperslabs */ + H5S_sel_iter_t *ss_iter = NULL; /* Selection iterator for src_space */ + hbool_t ss_iter_init = FALSE; /* Whether ss_iter has been initialized */ + H5S_sel_iter_t *ds_iter = NULL; /* Selection iterator for dst_space */ + hbool_t ds_iter_init = FALSE; /* Whether ds_iter has been initialized */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + HDassert(src_space); + HDassert(dst_space); + HDassert(src_intersect_space); + HDassert(new_space_ptr); + HDassert(H5S_GET_SELECT_NPOINTS(src_space) == H5S_GET_SELECT_NPOINTS(dst_space)); + HDassert(H5S_GET_EXTENT_NDIMS(src_space) == H5S_GET_EXTENT_NDIMS(src_intersect_space)); + + if (NULL == (ss_iter = H5FL_CALLOC(H5S_sel_iter_t))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate selection iterator") + if (NULL == (ds_iter = H5FL_CALLOC(H5S_sel_iter_t))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate selection iterator") + + /* Create new space, using dst extent. Start with "all" selection. */ + if (NULL == (new_space = H5S_create(H5S_SIMPLE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create output dataspace") + if (H5S__extent_copy_real(&new_space->extent, &dst_space->extent, TRUE) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy destination space extent") + + /* If the intersecting space is "all", the intersection must be equal to the + * source space and the projection must be equal to the destination space */ + if (H5S_GET_SELECT_TYPE(src_intersect_space) == H5S_SEL_ALL) { + /* Copy the destination selection. */ + if (H5S_select_copy(new_space, dst_space, FALSE) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy destination space selection") + } /* end if */ + /* If any of the selections contain no elements, the projection must be + * "none" */ + else if ((H5S_GET_SELECT_NPOINTS(src_intersect_space) == 0) || (H5S_GET_SELECT_NPOINTS(src_space) == 0) || + (H5S_GET_SELECT_NPOINTS(dst_space) == 0)) { + /* Change to "none" selection */ + if (H5S_select_none(new_space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection") + } /* end if */ + else { + /* Handle scalar dataspaces. It should not be possible for the source + * intersect space or the source space to be scalar since scalar spaces + * only support all or none selections, and both of those cases are + * covered above, and the source intersect space must have the same + * rank, so it also cannot be scalar, as scalar dataspaces have a rank + * of 0. */ + HDassert(H5S_GET_EXTENT_TYPE(src_space) != H5S_SCALAR); + HDassert(H5S_GET_EXTENT_TYPE(src_intersect_space) != H5S_SCALAR); + + /* Check for scalar dst_space. In this case we simply check if the + * (single) point selected in src_space intersects src_intersect_space, + * if so select all in new_space, otherwise select none. */ + if (H5S_GET_EXTENT_TYPE(dst_space) == H5S_SCALAR) { + hsize_t coords_start[H5S_MAX_RANK]; + hsize_t coords_end[H5S_MAX_RANK]; + htri_t intersect; + + /* Get source space bounds. Should be a single point. */ + if (H5S_SELECT_BOUNDS(src_space, coords_start, coords_end) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get source space bounds") + HDassert(0 == HDmemcmp(coords_start, coords_end, + H5S_GET_EXTENT_NDIMS(src_space) * sizeof(coords_start[0]))); + + /* Check for intersection */ + if ((intersect = H5S_SELECT_INTERSECT_BLOCK(src_intersect_space, coords_start, coords_end)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "can't check for intersection") + + /* Select all or none as appropriate */ + if (intersect) { + if (H5S_select_all(new_space, TRUE) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't select all") + } /* end if */ + else if (H5S_select_none(new_space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection") + } /* end if */ + else { + /* If the source intersect space is a point selection, convert it to a + * hyperslab (discarding ordering). We can get away with this because + * the order does not matter for the source intersect space */ + /* Maybe we should just leave it as a point selection for the point by + * point algorithm? The search through the selection in + * H5S_SELECT_INTERSECT_BLOCK will likely be O(N) either way. -NAF */ + if (H5S_GET_SELECT_TYPE(src_intersect_space) == H5S_SEL_POINTS) { + H5S_pnt_node_t *curr_pnt = src_intersect_space->select.sel_info.pnt_lst->head; + + /* Create dataspace and copy extent */ + if (NULL == (tmp_src_intersect_space = H5S_create(H5S_SIMPLE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, + "unable to create temporary source intersect dataspace") + if (H5S__extent_copy_real(&tmp_src_intersect_space->extent, &src_intersect_space->extent, + FALSE) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, + "unable to copy source intersect space extent") + + /* Iterate over points */ + for (curr_pnt = src_intersect_space->select.sel_info.pnt_lst->head; curr_pnt; + curr_pnt = curr_pnt->next) + /* Add point to hyperslab selection */ + if (H5S_hyper_add_span_element(tmp_src_intersect_space, src_intersect_space->extent.rank, + curr_pnt->pnt) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, + "can't add point to temporary dataspace selection") + + /* Redirect local src_intersect_space pointer (will not affect + * calling function) */ + src_intersect_space = tmp_src_intersect_space; + } /* end for */ + + /* By this point, src_intersect_space must be a hyperslab selection */ + HDassert(H5S_GET_SELECT_TYPE(src_intersect_space) == H5S_SEL_HYPERSLABS); + + /* If either the source space or the destination space is a point + * selection, iterate element by element */ + if ((H5S_GET_SELECT_TYPE(src_space) == H5S_SEL_POINTS) || + (H5S_GET_SELECT_TYPE(dst_space) == H5S_SEL_POINTS)) { + hsize_t coords[H5S_MAX_RANK]; + htri_t intersect; + + /* Start with "none" selection */ + if (H5S_select_none(new_space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection") + + /* Initialize iterators */ + if (H5S_select_iter_init(ss_iter, src_space, 1, H5S_SEL_ITER_SHARE_WITH_DATASPACE) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, + "can't initialize source space selection iterator") + ss_iter_init = TRUE; + if (H5S_select_iter_init(ds_iter, dst_space, 1, H5S_SEL_ITER_SHARE_WITH_DATASPACE) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, + "can't initialize destination space selection iterator") + ds_iter_init = TRUE; + + /* Iterate over points */ + do { + HDassert(ss_iter->elmt_left > 0); + HDassert(ss_iter->elmt_left > 0); + + /* Get SS coords */ + if (H5S_SELECT_ITER_COORDS(ss_iter, coords) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, + "can't get source selection coordinates") + + /* Check for intersection */ + if ((intersect = H5S_SELECT_INTERSECT_BLOCK(src_intersect_space, coords, coords)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "can't check for intersection") + + /* Add point if it intersects */ + if (intersect) { + /* Get DS coords */ + if (H5S_SELECT_ITER_COORDS(ds_iter, coords) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, + "can't get destination selection coordinates") + + /* Add point to new_space */ + if (H5S_select_elements(new_space, H5S_SELECT_APPEND, 1, coords) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, + "can't add point to new selection") + } /* end if */ + + /* Advance iterators */ + if (H5S_SELECT_ITER_NEXT(ss_iter, 1) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL, + "can't advacne source selection iterator") + ss_iter->elmt_left--; + if (H5S_SELECT_ITER_NEXT(ds_iter, 1) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTNEXT, FAIL, + "can't advacne destination selection iterator") + ds_iter->elmt_left--; + } while (ss_iter->elmt_left > 0); + HDassert(H5S_SELECT_ITER_NELMTS(ds_iter) == 0); + } /* end if */ + else { + HDassert(H5S_GET_SELECT_TYPE(src_space) != H5S_SEL_NONE); + HDassert(H5S_GET_SELECT_TYPE(dst_space) != H5S_SEL_NONE); + + /* Source and destination selections are all or hyperslab, + * intersecting selection is hyperslab. Call the hyperslab routine + * to project to another hyperslab selection. */ + if (H5S__hyper_project_intersection(src_space, dst_space, src_intersect_space, new_space, + share_selection) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, + "can't project hyperslab onto destination selection") + } /* end else */ + } /* end else */ + } /* end else */ + + /* load the address of the new space into *new_space_ptr */ + *new_space_ptr = new_space; + +done: + /* Cleanup on error */ + if (ret_value < 0) + if (new_space && H5S_close(new_space) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace") + + /* General cleanup */ + if (tmp_src_intersect_space && H5S_close(tmp_src_intersect_space) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release temporary dataspace") + if (ss_iter_init && H5S_SELECT_ITER_RELEASE(ss_iter) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release source selection iterator") + if (ds_iter_init && H5S_SELECT_ITER_RELEASE(ds_iter) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release destination selection iterator") + + ss_iter = H5FL_FREE(H5S_sel_iter_t, ss_iter); + ds_iter = H5FL_FREE(H5S_sel_iter_t, ds_iter); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S_select_project_intersection() */ + +/*-------------------------------------------------------------------------- + NAME + H5Sselect_project_intersection + + PURPOSE + Projects the intersection of of the selections of src_space_id and + src_intersect_space_id within the selection of src_space_id as a + selection within the selection of dst_space_id. + + USAGE + hid_t H5Sselect_project_intersection(src_space_id,dst_space_d,src_intersect_space_id) + hid_t src_space_id; IN: Selection that is mapped to dst_space_id, and intersected with +src_intersect_space_id hid_t dst_space_id; IN: Selection that is mapped to src_space_id hid_t +src_intersect_space_id; IN: Selection whose intersection with src_space_id is projected to dst_space_id to +obtain the result + + RETURNS + A dataspace with a selection equal to the intersection of + src_intersect_space_id and src_space_id projected from src_space to + dst_space on success, negative on failure. + + DESCRIPTION + Projects the intersection of of the selections of src_space and + src_intersect_space within the selection of src_space as a selection + within the selection of dst_space. The result is placed in the + selection of new_space_ptr. + + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +hid_t +H5Sselect_project_intersection(hid_t src_space_id, hid_t dst_space_id, hid_t src_intersect_space_id) +{ + H5S_t *src_space, *dst_space, *src_intersect_space; /* Input dataspaces */ + H5S_t *proj_space = NULL; /* Output dataspace */ + hid_t ret_value; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE3("i", "iii", src_space_id, dst_space_id, src_intersect_space_id); + + /* Check args */ + if (NULL == (src_space = (H5S_t *)H5I_object_verify(src_space_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace") + if (NULL == (dst_space = (H5S_t *)H5I_object_verify(dst_space_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace") + if (NULL == (src_intersect_space = (H5S_t *)H5I_object_verify(src_intersect_space_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace") + + /* Check numbers of points selected matches in source and destination */ + if (H5S_GET_SELECT_NPOINTS(src_space) != H5S_GET_SELECT_NPOINTS(dst_space)) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, + "number of points selected in source space does not match that in destination space") + + /* Check numbers of dimensions matches in source and source intersect spaces + */ + if (H5S_GET_EXTENT_NDIMS(src_space) != H5S_GET_EXTENT_NDIMS(src_intersect_space)) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, + "rank of source space does not match rank of source intersect space") + + /* Perform operation */ + if (H5S_select_project_intersection(src_space, dst_space, src_intersect_space, &proj_space, FALSE) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCLIP, FAIL, "can't project dataspace intersection") + + /* Register */ + if ((ret_value = H5I_register(H5I_DATASPACE, proj_space, TRUE)) < 0) + HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, FAIL, "unable to register dataspace ID") + +done: + if (ret_value < 0) + if (proj_space && H5S_close(proj_space) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace") + + FUNC_LEAVE_API(ret_value) +} /* end H5Sselect_project_intersection() */ + +/*-------------------------------------------------------------------------- + NAME + H5S_select_subtract + + PURPOSE + Subtract one selection from another + + USAGE + herr_t H5S_select_subtract(space,subtract_space) + H5S_t *space; IN/OUT: Selection to be operated on + H5S_t *subtract_space; IN: Selection that will be subtracted from space + + RETURNS + Non-negative on success/Negative on failure. + + DESCRIPTION + Removes any and all portions of space that are also present in + subtract_space. In essence, performs an A_NOT_B operation with the + two selections. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_select_subtract(H5S_t *space, H5S_t *subtract_space) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Sanity checks */ + HDassert(space); + HDassert(subtract_space); + + /* If either space is using the none selection, then we do not need to do + * anything */ + if ((space->select.type->type != H5S_SEL_NONE) && (subtract_space->select.type->type != H5S_SEL_NONE)) { + /* If subtract_space is using the all selection, set space to none */ + if (subtract_space->select.type->type == H5S_SEL_ALL) { + /* Change to "none" selection */ + if (H5S_select_none(space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection") + } /* end if */ + /* If either selection is a point selection, fail currently */ + else if ((subtract_space->select.type->type == H5S_SEL_POINTS) || + (space->select.type->type == H5S_SEL_POINTS)) { + HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "point selections not currently supported") + } /* end if */ + else { + /* Check for all selection in space, convert to hyperslab */ + if (space->select.type->type == H5S_SEL_ALL) { + /* Convert current "all" selection to "real" hyperslab selection */ + /* Then allow operation to proceed */ + hsize_t tmp_start[H5S_MAX_RANK]; /* Temporary start information */ + hsize_t tmp_stride[H5S_MAX_RANK]; /* Temporary stride information */ + hsize_t tmp_count[H5S_MAX_RANK]; /* Temporary count information */ + hsize_t tmp_block[H5S_MAX_RANK]; /* Temporary block information */ + unsigned u; /* Local index variable */ + + /* Fill in temporary information for the dimensions */ + for (u = 0; u < space->extent.rank; u++) { + tmp_start[u] = 0; + tmp_stride[u] = 1; + tmp_count[u] = 1; + tmp_block[u] = space->extent.size[u]; + } /* end for */ + + /* Convert to hyperslab selection */ + if (H5S_select_hyperslab(space, H5S_SELECT_SET, tmp_start, tmp_stride, tmp_count, tmp_block) < + 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection") + } /* end if */ + + HDassert(space->select.type->type == H5S_SEL_HYPERSLABS); + HDassert(subtract_space->select.type->type == H5S_SEL_HYPERSLABS); + + /* Both spaces are now hyperslabs, perform the operation */ + if (H5S__modify_select(space, H5S_SELECT_NOTB, subtract_space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't subtract hyperslab") + } /* end else */ + } /* end if */ + +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") + + /* Register */ + 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 ID") + +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 /*out*/, + size_t *nbytes /*out*/, hsize_t *off /*out*/, size_t *len /*out*/) +{ + 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", "izzxxxx", 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 && sel_iter->elmt_left > 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() */ + +/*-------------------------------------------------------------------------- + NAME + H5Ssel_iter_reset + PURPOSE + Resets a dataspace selection iterator back to an initial state. + USAGE + herr_t H5Ssel_iter_reset(sel_iter_id) + hid_t sel_iter_id; IN: ID of the dataspace selection iterator to + reset + hid_t space_id; IN: ID of the dataspace with selection to + iterate over + RETURNS + Non-negative on success / Negative on failure + DESCRIPTION + Resets a dataspace selection iterator back to an initial state so that + the iterator may be used for iteration once again. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5Ssel_iter_reset(hid_t sel_iter_id, hid_t space_id) +{ + H5S_sel_iter_t *sel_iter; + H5S_t *space; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "ii", sel_iter_id, space_id); + + /* 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 == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace") + + /* 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") + + /* Simply re-initialize iterator */ + if (H5S_select_iter_init(sel_iter, space, sel_iter->elmt_size, sel_iter->flags) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to re-initialize selection iterator") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Ssel_iter_reset() */ + +/*------------------------------------------------------------------------- + * Function: H5S__sel_iter_close_cb + * + * Purpose: Called when the ref count reaches zero on a selection iterator's ID + * + * Return: Non-negative on success / Negative on failure + * + * Programmer: Quincey Koziol + * Wednesday, April 8, 2020 + * + *------------------------------------------------------------------------- + */ +herr_t +H5S__sel_iter_close_cb(H5S_sel_iter_t *_sel_iter, void H5_ATTR_UNUSED **request) +{ + H5S_sel_iter_t *sel_iter = (H5S_sel_iter_t *)_sel_iter; /* The selection iterator to close */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Sanity check */ + HDassert(sel_iter); + + /* Close the selection iterator object */ + if (H5S_sel_iter_close(sel_iter) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CLOSEERROR, FAIL, "unable to close selection iterator"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S__sel_iter_close_cb() */ + +/*------------------------------------------------------------------------- + * 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() */ |
