diff options
Diffstat (limited to 'src/H5Spoint.c')
-rw-r--r-- | src/H5Spoint.c | 1577 |
1 files changed, 1053 insertions, 524 deletions
diff --git a/src/H5Spoint.c b/src/H5Spoint.c index aea7d5c..875c018 100644 --- a/src/H5Spoint.c +++ b/src/H5Spoint.c @@ -18,182 +18,252 @@ * Purpose: Point selection dataspace I/O functions. */ +/****************/ +/* Module Setup */ +/****************/ + #include "H5Smodule.h" /* This source code file is part of the H5S module */ -#include "H5private.h" /* Generic Functions */ -#include "H5Eprivate.h" /* Error handling */ -#include "H5FLprivate.h" /* Free Lists */ -#include "H5Iprivate.h" /* ID Functions */ -#include "H5MMprivate.h" /* Memory Management functions */ -#include "H5Spkg.h" /* Dataspace functions */ -#include "H5VMprivate.h" /* Vector functions */ +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5CXprivate.h" /* API Contexts */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5FLprivate.h" /* Free Lists */ +#include "H5Iprivate.h" /* ID Functions */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Spkg.h" /* Dataspace functions */ +#include "H5VMprivate.h" /* Vector functions */ + + +/****************/ +/* Local Macros */ +/****************/ + -/* Static function prototypes */ +/******************/ +/* Local Typedefs */ +/******************/ + +/* Define alias for hsize_t, for allocating H5S_pnt_node_t + point objects */ +/* (Makes it easier to understand the alloc / free calls) */ +typedef hsize_t hcoords_t; + + +/********************/ +/* Local Prototypes */ +/********************/ +static herr_t H5S__point_add(H5S_t *space, H5S_seloper_t op, size_t num_elem, + const hsize_t *coord); +static H5S_pnt_list_t *H5S__copy_pnt_list(const H5S_pnt_list_t *src, + unsigned rank); +static void H5S__free_pnt_list(H5S_pnt_list_t *pnt_lst); /* Selection callbacks */ -static herr_t H5S_point_copy(H5S_t *dst, const H5S_t *src, hbool_t share_selection); -static herr_t H5S_point_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); -static herr_t H5S_point_release(H5S_t *space); -static htri_t H5S_point_is_valid(const H5S_t *space); -static hssize_t H5S_point_serial_size(const H5S_t *space); -static herr_t H5S_point_serialize(const H5S_t *space, uint8_t **p); -static herr_t H5S_point_deserialize(H5S_t *space, uint32_t version, uint8_t flags, - const uint8_t **p); -static herr_t H5S_point_bounds(const H5S_t *space, hsize_t *start, hsize_t *end); -static herr_t H5S_point_offset(const H5S_t *space, hsize_t *off); +static herr_t H5S__point_copy(H5S_t *dst, const H5S_t *src, hbool_t share_selection); +static herr_t H5S__point_release(H5S_t *space); +static htri_t H5S__point_is_valid(const H5S_t *space); +static hssize_t H5S__point_serial_size(const H5S_t *space); +static herr_t H5S__point_serialize(const H5S_t *space, uint8_t **p); +static herr_t H5S__point_deserialize(H5S_t **space, const uint8_t **p); +static herr_t H5S__point_bounds(const H5S_t *space, hsize_t *start, hsize_t *end); +static herr_t H5S__point_offset(const H5S_t *space, hsize_t *off); static int H5S__point_unlim_dim(const H5S_t *space); -static htri_t H5S_point_is_contiguous(const H5S_t *space); -static htri_t H5S_point_is_single(const H5S_t *space); -static htri_t H5S_point_is_regular(const H5S_t *space); -static herr_t H5S_point_adjust_u(H5S_t *space, const hsize_t *offset); -static herr_t H5S_point_project_scalar(const H5S_t *space, hsize_t *offset); -static herr_t H5S_point_project_simple(const H5S_t *space, H5S_t *new_space, hsize_t *offset); -static herr_t H5S_point_iter_init(H5S_sel_iter_t *iter, const H5S_t *space); +static htri_t H5S__point_is_contiguous(const H5S_t *space); +static htri_t H5S__point_is_single(const H5S_t *space); +static htri_t H5S__point_is_regular(const H5S_t *space); +static htri_t H5S__point_shape_same(const H5S_t *space1, const H5S_t *space2); +static herr_t H5S__point_adjust_u(H5S_t *space, const hsize_t *offset); +static herr_t H5S__point_project_scalar(const H5S_t *space, hsize_t *offset); +static herr_t H5S__point_project_simple(const H5S_t *space, H5S_t *new_space, + hsize_t *offset); +static herr_t H5S__point_iter_init(const H5S_t *space, H5S_sel_iter_t *iter); +static herr_t H5S__point_get_version_enc_size(const H5S_t *space, + uint32_t *version, uint8_t *enc_size); /* Selection iteration callbacks */ -static herr_t H5S_point_iter_coords(const H5S_sel_iter_t *iter, hsize_t *coords); -static herr_t H5S_point_iter_block(const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end); -static hsize_t H5S_point_iter_nelmts(const H5S_sel_iter_t *iter); -static htri_t H5S_point_iter_has_next_block(const H5S_sel_iter_t *iter); -static herr_t H5S_point_iter_next(H5S_sel_iter_t *sel_iter, size_t nelem); -static herr_t H5S_point_iter_next_block(H5S_sel_iter_t *sel_iter); -static herr_t H5S_point_iter_release(H5S_sel_iter_t *sel_iter); +static herr_t H5S__point_iter_coords(const H5S_sel_iter_t *iter, hsize_t *coords); +static herr_t H5S__point_iter_block(const H5S_sel_iter_t *iter, hsize_t *start, + hsize_t *end); +static hsize_t H5S__point_iter_nelmts(const H5S_sel_iter_t *iter); +static htri_t H5S__point_iter_has_next_block(const H5S_sel_iter_t *iter); +static herr_t H5S__point_iter_next(H5S_sel_iter_t *sel_iter, size_t nelem); +static herr_t H5S__point_iter_next_block(H5S_sel_iter_t *sel_iter); +static herr_t H5S__point_iter_get_seq_list(H5S_sel_iter_t *iter, size_t maxseq, + size_t maxbytes, size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len); +static herr_t H5S__point_iter_release(H5S_sel_iter_t *sel_iter); + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*********************/ +/* Package Variables */ +/*********************/ /* Selection properties for point selections */ const H5S_select_class_t H5S_sel_point[1] = {{ H5S_SEL_POINTS, /* Methods on selection */ - H5S_point_copy, - H5S_point_get_seq_list, - H5S_point_release, - H5S_point_is_valid, - H5S_point_serial_size, - H5S_point_serialize, - H5S_point_deserialize, - H5S_point_bounds, - H5S_point_offset, + H5S__point_copy, + H5S__point_release, + H5S__point_is_valid, + H5S__point_serial_size, + H5S__point_serialize, + H5S__point_deserialize, + H5S__point_bounds, + H5S__point_offset, H5S__point_unlim_dim, NULL, - H5S_point_is_contiguous, - H5S_point_is_single, - H5S_point_is_regular, - H5S_point_adjust_u, - H5S_point_project_scalar, - H5S_point_project_simple, - H5S_point_iter_init, + H5S__point_is_contiguous, + H5S__point_is_single, + H5S__point_is_regular, + H5S__point_shape_same, + H5S__point_adjust_u, + H5S__point_project_scalar, + H5S__point_project_simple, + H5S__point_iter_init, }}; +/* Format version bounds for dataspace hyperslab selection */ +const unsigned H5O_sds_point_ver_bounds[] = { + H5S_POINT_VERSION_1, /* H5F_LIBVER_EARLIEST */ + H5S_POINT_VERSION_1, /* H5F_LIBVER_V18 */ + H5S_POINT_VERSION_1, /* H5F_LIBVER_V110 */ + H5S_POINT_VERSION_2 /* H5F_LIBVER_LATEST */ +}; + +/*******************/ +/* Local Variables */ +/*******************/ + /* Iteration properties for point selections */ static const H5S_sel_iter_class_t H5S_sel_iter_point[1] = {{ H5S_SEL_POINTS, /* Methods on selection iterator */ - H5S_point_iter_coords, - H5S_point_iter_block, - H5S_point_iter_nelmts, - H5S_point_iter_has_next_block, - H5S_point_iter_next, - H5S_point_iter_next_block, - H5S_point_iter_release, + H5S__point_iter_coords, + H5S__point_iter_block, + H5S__point_iter_nelmts, + H5S__point_iter_has_next_block, + H5S__point_iter_next, + H5S__point_iter_next_block, + H5S__point_iter_get_seq_list, + H5S__point_iter_release, }}; -/* Declare a free list to manage the H5S_pnt_node_t struct */ -H5FL_DEFINE_STATIC(H5S_pnt_node_t); +/* Declare a free list to manage the H5S_pnt_node_t + hcoords_t array struct */ +H5FL_BARR_DEFINE_STATIC(H5S_pnt_node_t, hcoords_t, H5S_MAX_RANK); /* Declare a free list to manage the H5S_pnt_list_t struct */ H5FL_DEFINE_STATIC(H5S_pnt_list_t); + /*------------------------------------------------------------------------- - * Function: H5S_point_iter_init + * Function: H5S__point_iter_init * * Purpose: Initializes iteration information for point selection. * - * Return: non-negative on success, negative on failure. + * Return: Non-negative on success, negative on failure. * * Programmer: Quincey Koziol * Tuesday, June 16, 1998 * - * Modifications: - * *------------------------------------------------------------------------- */ static herr_t -H5S_point_iter_init(H5S_sel_iter_t *iter, const H5S_t *space) +H5S__point_iter_init(const H5S_t *space, H5S_sel_iter_t *iter) { - FUNC_ENTER_NOAPI_NOINIT_NOERR + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC /* Check args */ - HDassert(space && H5S_SEL_POINTS==H5S_GET_SELECT_TYPE(space)); + HDassert(space && H5S_SEL_POINTS == H5S_GET_SELECT_TYPE(space)); HDassert(iter); - /* Initialize the number of points to iterate over */ - iter->elmt_left=space->select.num_elem; + /* If this iterator is created from an API call, by default we clone the + * selection now, as the dataspace could be modified or go out of scope. + * + * However, if the H5S_SEL_ITER_SHARE_WITH_DATASPACE flag is given, + * the selection is shared between the selection iterator and the + * dataspace. In this case, the application _must_not_ modify or + * close the dataspace that the iterator is operating on, or undefined + * behavior will occur. + */ + if((iter->flags & H5S_SEL_ITER_API_CALL) && + !(iter->flags & H5S_SEL_ITER_SHARE_WITH_DATASPACE)) { + /* Copy the point list */ + if(NULL == (iter->u.pnt.pnt_lst = H5S__copy_pnt_list(space->select.sel_info.pnt_lst, space->extent.rank))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy point list") + } /* end if */ + else + /* OK to share point list for internal iterations */ + iter->u.pnt.pnt_lst = space->select.sel_info.pnt_lst; /* Start at the head of the list of points */ - iter->u.pnt.curr=space->select.sel_info.pnt_lst->head; + iter->u.pnt.curr = iter->u.pnt.pnt_lst->head; /* Initialize type of selection iterator */ - iter->type=H5S_sel_iter_point; + iter->type = H5S_sel_iter_point; - FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5S_point_iter_init() */ +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S__point_iter_init() */ /*------------------------------------------------------------------------- - * Function: H5S_point_iter_coords + * Function: H5S__point_iter_coords * * Purpose: Retrieve the current coordinates of iterator for current * selection * - * Return: non-negative on success, negative on failure + * Return: Non-negative on success, negative on failure * * Programmer: Quincey Koziol * Tuesday, April 22, 2003 * - * Modifications: - * *------------------------------------------------------------------------- */ static herr_t -H5S_point_iter_coords (const H5S_sel_iter_t *iter, hsize_t *coords) +H5S__point_iter_coords(const H5S_sel_iter_t *iter, hsize_t *coords) { - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR /* Check args */ HDassert(iter); HDassert(coords); /* Copy the offset of the current point */ - HDmemcpy(coords,iter->u.pnt.curr->pnt,sizeof(hsize_t)*iter->rank); + H5MM_memcpy(coords, iter->u.pnt.curr->pnt, sizeof(hsize_t) * iter->rank); FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5S_point_iter_coords() */ +} /* end H5S__point_iter_coords() */ /*------------------------------------------------------------------------- - * Function: H5S_point_iter_block + * Function: H5S__point_iter_block * * Purpose: Retrieve the current block of iterator for current * selection * - * Return: non-negative on success, negative on failure + * Return: Non-negative on success, negative on failure * * Programmer: Quincey Koziol * Monday, June 2, 2003 * - * Modifications: - * *------------------------------------------------------------------------- */ static herr_t -H5S_point_iter_block (const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end) +H5S__point_iter_block(const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end) { - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR /* Check args */ HDassert(iter); @@ -201,46 +271,44 @@ H5S_point_iter_block (const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end) HDassert(end); /* Copy the current point as a block */ - HDmemcpy(start,iter->u.pnt.curr->pnt,sizeof(hsize_t)*iter->rank); - HDmemcpy(end,iter->u.pnt.curr->pnt,sizeof(hsize_t)*iter->rank); + H5MM_memcpy(start, iter->u.pnt.curr->pnt, sizeof(hsize_t) * iter->rank); + H5MM_memcpy(end, iter->u.pnt.curr->pnt, sizeof(hsize_t) * iter->rank); FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5S_point_iter_block() */ +} /* end H5S__point_iter_block() */ /*------------------------------------------------------------------------- - * Function: H5S_point_iter_nelmts + * Function: H5S__point_iter_nelmts * * Purpose: Return number of elements left to process in iterator * - * Return: non-negative number of elements on success, zero on failure + * Return: Non-negative number of elements on success, zero on failure * * Programmer: Quincey Koziol * Tuesday, June 16, 1998 * - * Modifications: - * *------------------------------------------------------------------------- */ static hsize_t -H5S_point_iter_nelmts (const H5S_sel_iter_t *iter) +H5S__point_iter_nelmts(const H5S_sel_iter_t *iter) { - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR /* Check args */ HDassert(iter); FUNC_LEAVE_NOAPI(iter->elmt_left) -} /* H5S_point_iter_nelmts() */ +} /* end H5S__point_iter_nelmts() */ /*-------------------------------------------------------------------------- NAME - H5S_point_iter_has_next_block + H5S__point_iter_has_next_block PURPOSE Check if there is another block left in the current iterator USAGE - htri_t H5S_point_iter_has_next_block(iter) + htri_t H5S__point_iter_has_next_block(iter) const H5S_sel_iter_t *iter; IN: Pointer to selection iterator RETURNS Non-negative (TRUE/FALSE) on success/Negative on failure @@ -252,31 +320,31 @@ H5S_point_iter_nelmts (const H5S_sel_iter_t *iter) REVISION LOG --------------------------------------------------------------------------*/ static htri_t -H5S_point_iter_has_next_block(const H5S_sel_iter_t *iter) +H5S__point_iter_has_next_block(const H5S_sel_iter_t *iter) { - htri_t ret_value=TRUE; /* Return value */ + htri_t ret_value = TRUE; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR /* Check args */ HDassert(iter); /* Check if there is another point in the list */ - if(iter->u.pnt.curr->next==NULL) + if(iter->u.pnt.curr->next == NULL) HGOTO_DONE(FALSE); done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_point_iter_has_next_block() */ +} /* end H5S__point_iter_has_next_block() */ /*-------------------------------------------------------------------------- NAME - H5S_point_iter_next + H5S__point_iter_next PURPOSE Increment selection iterator USAGE - herr_t H5S_point_iter_next(iter, nelem) + herr_t H5S__point_iter_next(iter, nelem) H5S_sel_iter_t *iter; IN: Pointer to selection iterator size_t nelem; IN: Number of elements to advance by RETURNS @@ -289,31 +357,31 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_point_iter_next(H5S_sel_iter_t *iter, size_t nelem) +H5S__point_iter_next(H5S_sel_iter_t *iter, size_t nelem) { - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR /* Check args */ HDassert(iter); - HDassert(nelem>0); + HDassert(nelem > 0); /* Increment the iterator */ - while(nelem>0) { - iter->u.pnt.curr=iter->u.pnt.curr->next; + while(nelem > 0) { + iter->u.pnt.curr = iter->u.pnt.curr->next; nelem--; } /* end while */ FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5S_point_iter_next() */ +} /* end H5S__point_iter_next() */ /*-------------------------------------------------------------------------- NAME - H5S_point_iter_next_block + H5S__point_iter_next_block PURPOSE Increment selection iterator to next block USAGE - herr_t H5S_point_iter_next_block(iter) + herr_t H5S__point_iter_next_block(iter) H5S_sel_iter_t *iter; IN: Pointer to selection iterator RETURNS Non-negative on success/Negative on failure @@ -325,27 +393,158 @@ H5S_point_iter_next(H5S_sel_iter_t *iter, size_t nelem) REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_point_iter_next_block(H5S_sel_iter_t *iter) +H5S__point_iter_next_block(H5S_sel_iter_t *iter) { - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR /* Check args */ HDassert(iter); /* Increment the iterator */ - iter->u.pnt.curr=iter->u.pnt.curr->next; + iter->u.pnt.curr = iter->u.pnt.curr->next; FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5S_point_iter_next_block() */ +} /* end H5S__point_iter_next_block() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S__point_iter_get_seq_list + PURPOSE + Create a list of offsets & lengths for a selection + USAGE + herr_t H5S__point_iter_get_seq_list(iter,maxseq,maxelem,nseq,nelem,off,len) + H5S_sel_iter_t *iter; IN/OUT: Selection iterator describing last + position of interest in selection. + size_t maxseq; IN: Maximum number of sequences to generate + size_t maxelem; IN: Maximum number of elements to include in the + generated sequences + size_t *nseq; OUT: Actual number of sequences generated + size_t *nelem; OUT: Actual number of elements in sequences generated + hsize_t *off; OUT: Array of offsets (in bytes) + size_t *len; OUT: Array of lengths (in bytes) + RETURNS + Non-negative on success/Negative on failure. + DESCRIPTION + Use the selection in the dataspace to generate a list of byte offsets and + lengths for the region(s) selected. Start/Restart from the position in the + ITER parameter. The number of sequences generated is limited by the MAXSEQ + parameter and the number of sequences actually generated is stored in the + NSEQ parameter. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5S__point_iter_get_seq_list(H5S_sel_iter_t *iter, size_t maxseq, size_t maxelem, + size_t *nseq, size_t *nelem, hsize_t *off, size_t *len) +{ + size_t io_left; /* The number of bytes left in the selection */ + size_t start_io_left; /* The initial number of bytes left in the selection */ + H5S_pnt_node_t *node; /* Point node */ + unsigned ndims; /* Dimensionality of dataspace*/ + hsize_t acc; /* Coordinate accumulator */ + hsize_t loc; /* Coordinate offset */ + size_t curr_seq; /* Current sequence being operated on */ + int i; /* Local index variable */ + herr_t ret_value = SUCCEED; /* return value */ + + FUNC_ENTER_STATIC_NOERR + + /* Check args */ + HDassert(iter); + HDassert(maxseq > 0); + HDassert(maxelem > 0); + HDassert(nseq); + HDassert(nelem); + HDassert(off); + HDassert(len); + + /* Choose the minimum number of bytes to sequence through */ + H5_CHECK_OVERFLOW(iter->elmt_left, hsize_t, size_t); + start_io_left = io_left = (size_t)MIN(iter->elmt_left, maxelem); + + /* Get the dataspace's rank */ + ndims = iter->rank; + + /* Walk through the points in the selection, starting at the current */ + /* location in the iterator */ + node = iter->u.pnt.curr; + curr_seq = 0; + while(NULL != node) { + /* Compute the offset of each selected point in the buffer */ + for(i = (int)(ndims - 1), acc = iter->elmt_size, loc = 0; i >= 0; i--) { + loc += (hsize_t)((hssize_t)node->pnt[i] + iter->sel_off[i]) * acc; + acc *= iter->dims[i]; + } /* end for */ + + /* Check if this is a later point in the selection */ + if(curr_seq > 0) { + /* If a sorted sequence is requested, make certain we don't go backwards in the offset */ + if((iter->flags & H5S_SEL_ITER_GET_SEQ_LIST_SORTED) && loc < off[curr_seq - 1]) + break; + + /* Check if this point extends the previous sequence */ + /* (Unlikely, but possible) */ + if(loc == (off[curr_seq - 1] + len[curr_seq - 1])) { + /* Extend the previous sequence */ + len[curr_seq - 1] += iter->elmt_size; + } /* end if */ + else { + /* Add a new sequence */ + off[curr_seq] = loc; + len[curr_seq] = iter->elmt_size; + + /* Increment sequence count */ + curr_seq++; + } /* end else */ + } /* end if */ + else { + /* Add a new sequence */ + off[curr_seq] = loc; + len[curr_seq] = iter->elmt_size; + + /* Increment sequence count */ + curr_seq++; + } /* end else */ + + /* Decrement number of elements left to process */ + io_left--; + + /* Move the iterator */ + iter->u.pnt.curr = node->next; + iter->elmt_left--; + + /* Check if we're finished with all sequences */ + if(curr_seq == maxseq) + break; + + /* Check if we're finished with all the elements available */ + if(io_left == 0) + break; + + /* Advance to the next point */ + node = node->next; + } /* end while */ + + /* Set the number of sequences generated */ + *nseq = curr_seq; + + /* Set the number of elements used */ + *nelem = start_io_left - io_left; + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S__point_iter_get_seq_list() */ /*-------------------------------------------------------------------------- NAME - H5S_point_iter_release + H5S__point_iter_release PURPOSE Release point selection iterator information for a dataspace USAGE - herr_t H5S_point_iter_release(iter) + herr_t H5S__point_iter_release(iter) H5S_sel_iter_t *iter; IN: Pointer to selection iterator RETURNS Non-negative on success/Negative on failure @@ -357,24 +556,29 @@ H5S_point_iter_next_block(H5S_sel_iter_t *iter) REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_point_iter_release (H5S_sel_iter_t H5_ATTR_UNUSED * iter) +H5S__point_iter_release(H5S_sel_iter_t * iter) { - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR /* Check args */ HDassert(iter); + /* If this iterator copied the point list, we must free it */ + if((iter->flags & H5S_SEL_ITER_API_CALL) && + !(iter->flags & H5S_SEL_ITER_SHARE_WITH_DATASPACE)) + H5S__free_pnt_list(iter->u.pnt.pnt_lst); + FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5S_point_iter_release() */ +} /* end H5S__point_iter_release() */ /*-------------------------------------------------------------------------- NAME - H5S_point_add + H5S__point_add PURPOSE Add a series of elements to a point selection USAGE - herr_t H5S_point_add(space, num_elem, coord) + herr_t H5S__point_add(space, num_elem, coord) H5S_t *space; IN: Dataspace of selection to modify size_t num_elem; IN: Number of elements in COORD array. const hsize_t *coord[]; IN: The location of each element selected @@ -388,31 +592,32 @@ H5S_point_iter_release (H5S_sel_iter_t H5_ATTR_UNUSED * iter) REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_point_add(H5S_t *space, H5S_seloper_t op, size_t num_elem, const hsize_t *coord) +H5S__point_add(H5S_t *space, H5S_seloper_t op, size_t num_elem, const hsize_t *coord) { H5S_pnt_node_t *top = NULL, *curr = NULL, *new_node = NULL; /* Point selection nodes */ unsigned u; /* Counter */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC + /* Sanity checks */ HDassert(space); HDassert(num_elem > 0); HDassert(coord); HDassert(op == H5S_SELECT_SET || op == H5S_SELECT_APPEND || op == H5S_SELECT_PREPEND); for(u = 0; u < num_elem; u++) { + unsigned dim; /* Counter for dimensions */ + /* Allocate space for the new node */ - if(NULL == (new_node = H5FL_MALLOC(H5S_pnt_node_t))) + if(NULL == (new_node = (H5S_pnt_node_t *)H5FL_ARR_MALLOC(hcoords_t, space->extent.rank))) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate point node") /* Initialize fields in node */ new_node->next = NULL; - if(NULL == (new_node->pnt = (hsize_t *)H5MM_malloc(space->extent.rank * sizeof(hsize_t)))) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate coordinate information") /* Copy over the coordinates */ - HDmemcpy(new_node->pnt, coord + (u * space->extent.rank), (space->extent.rank * sizeof(hsize_t))); + H5MM_memcpy(new_node->pnt, coord + (u * space->extent.rank), (space->extent.rank * sizeof(hsize_t))); /* Link into list */ if(top == NULL) @@ -420,6 +625,17 @@ H5S_point_add(H5S_t *space, H5S_seloper_t op, size_t num_elem, const hsize_t *co else curr->next = new_node; curr = new_node; + + /* Update bound box */ + /* (Note: when op is H5S_SELECT_SET, the bound box has been reset + * inside H5S_select_elements, the only caller of this function. + * So the following bound box update procedure works correctly + * for the SET operation) + */ + for(dim = 0; dim < space->extent.rank; dim++) { + space->select.sel_info.pnt_lst->low_bounds[dim] = MIN(space->select.sel_info.pnt_lst->low_bounds[dim], curr->pnt[dim]); + space->select.sel_info.pnt_lst->high_bounds[dim] = MAX(space->select.sel_info.pnt_lst->high_bounds[dim], curr->pnt[dim]); + } /* end for */ } /* end for */ new_node = NULL; @@ -431,20 +647,22 @@ H5S_point_add(H5S_t *space, H5S_seloper_t op, size_t num_elem, const hsize_t *co /* Put new list in point selection */ space->select.sel_info.pnt_lst->head = top; + + /* Change the tail pointer if tail has not been set */ + if(NULL == space->select.sel_info.pnt_lst->tail) + space->select.sel_info.pnt_lst->tail = curr; } /* end if */ else { /* op==H5S_SELECT_APPEND */ H5S_pnt_node_t *tmp_node; /* Temporary point selection node */ tmp_node = space->select.sel_info.pnt_lst->head; if(tmp_node != NULL) { - while(tmp_node->next != NULL) - tmp_node = tmp_node->next; - - /* Append new list to point selection */ - tmp_node->next = top; + HDassert(space->select.sel_info.pnt_lst->tail); + space->select.sel_info.pnt_lst->tail->next = top; } /* end if */ else space->select.sel_info.pnt_lst->head = top; + space->select.sel_info.pnt_lst->tail = curr; } /* end else */ /* Set the number of elements in the new selection */ @@ -457,28 +675,27 @@ done: if(ret_value < 0) { /* Release possibly partially initialized new node */ if(new_node) - new_node = H5FL_FREE(H5S_pnt_node_t, new_node); + new_node = (H5S_pnt_node_t *)H5FL_ARR_FREE(hcoords_t, new_node); /* Release possible linked list of nodes */ while(top) { - curr = top->next; - H5MM_xfree(top->pnt); - top = H5FL_FREE(H5S_pnt_node_t, top); + curr = top->next; + top = (H5S_pnt_node_t *)H5FL_ARR_FREE(hcoords_t, top); top = curr; } /* end while */ } /* end if */ FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_point_add() */ +} /* end H5S__point_add() */ /*-------------------------------------------------------------------------- NAME - H5S_point_release + H5S__point_release PURPOSE Release point selection information for a dataspace USAGE - herr_t H5S_point_release(space) + herr_t H5S__point_release(space) H5S_t *space; IN: Pointer to dataspace RETURNS Non-negative on success/Negative on failure @@ -490,32 +707,24 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_point_release (H5S_t *space) +H5S__point_release(H5S_t *space) { - H5S_pnt_node_t *curr, *next; /* Point selection nodes */ - - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR /* Check args */ HDassert(space); - /* Delete all the nodes from the list */ - curr = space->select.sel_info.pnt_lst->head; - while(curr != NULL) { - next = curr->next; - H5MM_xfree(curr->pnt); - curr = H5FL_FREE(H5S_pnt_node_t, curr); - curr = next; - } /* end while */ + /* Free the point list */ + H5S__free_pnt_list(space->select.sel_info.pnt_lst); - /* Free & reset the point list header */ - space->select.sel_info.pnt_lst = H5FL_FREE(H5S_pnt_list_t, space->select.sel_info.pnt_lst); + /* Reset the point list header */ + space->select.sel_info.pnt_lst = NULL; /* Reset the number of elements in the selection */ space->select.num_elem = 0; FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5S_point_release() */ +} /* end H5S__point_release() */ /*-------------------------------------------------------------------------- @@ -539,10 +748,7 @@ H5S_point_release (H5S_t *space) array elements are iterated through when I/O is performed. Duplicate coordinates are not checked for. The selection operator, OP, determines how the new selection is to be combined with the existing selection for - the dataspace. Currently, only H5S_SELECT_SET is supported, which replaces - the existing selection with the one defined in this call. When operators - other than H5S_SELECT_SET are used to combine a new selection with an - existing selection, the selection ordering is reset to 'C' array ordering. + the dataspace. GLOBAL VARIABLES COMMENTS, BUGS, ASSUMPTIONS EXAMPLES @@ -552,9 +758,9 @@ herr_t H5S_select_elements(H5S_t *space, H5S_seloper_t op, size_t num_elem, const hsize_t *coord) { - herr_t ret_value = SUCCEED; /* return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_NOAPI(FAIL) /* Check args */ HDassert(space); @@ -568,12 +774,19 @@ H5S_select_elements(H5S_t *space, H5S_seloper_t op, size_t num_elem, HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release point selection") /* Allocate space for the point selection information if necessary */ - if(H5S_GET_SELECT_TYPE(space) != H5S_SEL_POINTS || space->select.sel_info.pnt_lst == NULL) + if(H5S_GET_SELECT_TYPE(space) != H5S_SEL_POINTS || space->select.sel_info.pnt_lst == NULL) { + hsize_t tmp = HSIZET_MAX; + if(NULL == (space->select.sel_info.pnt_lst = H5FL_CALLOC(H5S_pnt_list_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate element information") + /* Set the bound box to the default value */ + H5VM_array_fill(space->select.sel_info.pnt_lst->low_bounds, &tmp, sizeof(hsize_t), space->extent.rank); + HDmemset(space->select.sel_info.pnt_lst->high_bounds, 0, sizeof(hsize_t) * space->extent.rank); + } /* end if */ + /* Add points to selection */ - if(H5S_point_add(space, op, num_elem, coord) < 0) + if(H5S__point_add(space, op, num_elem, coord) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert elements") /* Set selection type */ @@ -581,61 +794,61 @@ H5S_select_elements(H5S_t *space, H5S_seloper_t op, size_t num_elem, done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_select_elements() */ +} /* end H5S_select_elements() */ /*-------------------------------------------------------------------------- NAME - H5S_point_copy + H5S__copy_pnt_list PURPOSE - Copy a selection from one dataspace to another + Copy a point selection list USAGE - herr_t H5S_point_copy(dst, src) - H5S_t *dst; OUT: Pointer to the destination dataspace - H5S_t *src; IN: Pointer to the source dataspace + H5S_pnt_list_t *H5S__copy_pnt_list(src) + const H5S_pnt_list_t *src; IN: Pointer to the source point list + unsigned rank; IN: # of dimensions for points RETURNS - Non-negative on success/Negative on failure + Non-NULL pointer to new point list on success / NULL on failure DESCRIPTION - Copies all the point selection information from the source - dataspace to the destination dataspace. + Copies point selection information from the source point list to newly + created point list. GLOBAL VARIABLES COMMENTS, BUGS, ASSUMPTIONS EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -static herr_t -H5S_point_copy(H5S_t *dst, const H5S_t *src, hbool_t H5_ATTR_UNUSED share_selection) +static H5S_pnt_list_t * +H5S__copy_pnt_list(const H5S_pnt_list_t *src, unsigned rank) { - H5S_pnt_node_t *curr, *new_node, *new_tail; /* Point information nodes */ - herr_t ret_value = SUCCEED; /* Return value */ + H5S_pnt_list_t *dst = NULL; /* New point list */ + H5S_pnt_node_t *curr, *new_tail; /* Point information nodes */ + H5S_pnt_list_t *ret_value = NULL; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC + /* Sanity checks */ HDassert(src); - HDassert(dst); + HDassert(rank > 0); /* Allocate room for the head of the point list */ - if(NULL == (dst->select.sel_info.pnt_lst = H5FL_MALLOC(H5S_pnt_list_t))) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate point list node") + if(NULL == (dst = H5FL_MALLOC(H5S_pnt_list_t))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate point list node") - curr = src->select.sel_info.pnt_lst->head; + curr = src->head; new_tail = NULL; while(curr) { + H5S_pnt_node_t *new_node; /* New point information node */ + /* Create new point */ - if(NULL == (new_node = H5FL_MALLOC(H5S_pnt_node_t))) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate point node") + if(NULL == (new_node = (H5S_pnt_node_t *)H5FL_ARR_MALLOC(hcoords_t, rank))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate point node") new_node->next = NULL; - if(NULL == (new_node->pnt = (hsize_t *)H5MM_malloc(src->extent.rank * sizeof(hsize_t)))) { - new_node = H5FL_FREE(H5S_pnt_node_t, new_node); - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate coordinate information") - } /* end if */ /* Copy over the point's coordinates */ - HDmemcpy(new_node->pnt, curr->pnt, (src->extent.rank * sizeof(hsize_t))); + H5MM_memcpy(new_node->pnt, curr->pnt, (rank * sizeof(hsize_t))); /* Keep the order the same when copying */ if(NULL == new_tail) - new_tail = dst->select.sel_info.pnt_lst->head = new_node; + new_tail = dst->head = new_node; else { new_tail->next = new_node; new_tail = new_node; @@ -643,35 +856,114 @@ H5S_point_copy(H5S_t *dst, const H5S_t *src, hbool_t H5_ATTR_UNUSED share_select curr = curr->next; } /* end while */ + dst->tail = new_tail; + + /* Copy the selection bounds */ + H5MM_memcpy(dst->high_bounds, src->high_bounds, (rank * sizeof(hsize_t))); + H5MM_memcpy(dst->low_bounds, src->low_bounds, (rank * sizeof(hsize_t))); + + /* Set return value */ + ret_value = dst; done: - if(ret_value < 0 && dst->select.sel_info.pnt_lst) { - /* Traverse the (incomplete?) dst list, freeing all memory */ - curr = dst->select.sel_info.pnt_lst->head; - while(curr) { - H5S_pnt_node_t *tmp_node = curr; - - curr->pnt = (hsize_t *)H5MM_xfree(curr->pnt); - curr = curr->next; - tmp_node = H5FL_FREE(H5S_pnt_node_t, tmp_node); - } /* end while */ + if(NULL == ret_value && dst) + H5S__free_pnt_list(dst); - dst->select.sel_info.pnt_lst = H5FL_FREE(H5S_pnt_list_t, dst->select.sel_info.pnt_lst); - } /* end if */ + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S__copy_pnt_list() */ + +/*-------------------------------------------------------------------------- + NAME + H5S__free_pnt_list + PURPOSE + Free a point selection list + USAGE + void H5S__free_pnt_list(pnt_lst) + H5S_pnt_list_t *pnt_lst; IN: Pointer to the point list to free + RETURNS + None + DESCRIPTION + Frees point selection information from the point list + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static void +H5S__free_pnt_list(H5S_pnt_list_t *pnt_lst) +{ + H5S_pnt_node_t *curr; /* Point information nodes */ + + FUNC_ENTER_STATIC_NOERR + + /* Sanity checks */ + HDassert(pnt_lst); + + /* Traverse the list, freeing all memory */ + curr = pnt_lst->head; + while(curr) { + H5S_pnt_node_t *tmp_node = curr; + + curr = curr->next; + tmp_node = (H5S_pnt_node_t *)H5FL_ARR_FREE(hcoords_t, tmp_node); + } /* end while */ + + H5FL_FREE(H5S_pnt_list_t, pnt_lst); + + FUNC_LEAVE_NOAPI_VOID +} /* end H5S__free_pnt_list() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S__point_copy + PURPOSE + Copy a selection from one dataspace to another + USAGE + herr_t H5S__point_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 share_selection; IN: Whether to share the selection between the dataspaces + RETURNS + Non-negative on success/Negative on failure + DESCRIPTION + Copies all the point selection information from the source + dataspace to the destination dataspace. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5S__point_copy(H5S_t *dst, const H5S_t *src, hbool_t H5_ATTR_UNUSED share_selection) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Sanity check */ + HDassert(src); + HDassert(dst); + + /* Allocate room for the head of the point list */ + if(NULL == (dst->select.sel_info.pnt_lst = H5S__copy_pnt_list(src->select.sel_info.pnt_lst, src->extent.rank))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy point list") + +done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5S_point_copy() */ +} /* end H5S__point_copy() */ /*-------------------------------------------------------------------------- NAME - H5S_point_is_valid + H5S__point_is_valid PURPOSE Check whether the selection fits within the extent, with the current offset defined. USAGE - htri_t H5S_point_is_valid(space); - H5S_t *space; IN: Dataspace pointer to query + htri_t H5S__point_is_valid(space); + const H5S_t *space; IN: Dataspace pointer to query RETURNS TRUE if the selection fits within the extent, FALSE if it does not and Negative on an error. @@ -684,34 +976,27 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static htri_t -H5S_point_is_valid (const H5S_t *space) +H5S__point_is_valid(const H5S_t *space) { - H5S_pnt_node_t *curr; /* Point information nodes */ unsigned u; /* Counter */ htri_t ret_value = TRUE; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR HDassert(space); - /* Check each point to determine whether selection+offset is within extent */ - curr = space->select.sel_info.pnt_lst->head; - while(curr != NULL) { - /* Check each dimension */ - for(u = 0; u < space->extent.rank; u++) { - /* Check if an offset has been defined */ - /* Bounds check the selected point + offset against the extent */ - if(((curr->pnt[u] + (hsize_t)space->select.offset[u]) > space->extent.size[u]) - || (((hssize_t)curr->pnt[u] + space->select.offset[u]) < 0)) - HGOTO_DONE(FALSE) - } /* end for */ - - curr = curr->next; - } /* end while */ + /* Check each dimension */ + for(u = 0; u < space->extent.rank; u++) { + /* Bounds check the selected point + offset against the extent */ + if((space->select.sel_info.pnt_lst->high_bounds[u] + (hsize_t)space->select.offset[u]) > space->extent.size[u]) + HGOTO_DONE(FALSE) + if(((hssize_t)space->select.sel_info.pnt_lst->low_bounds[u] + space->select.offset[u]) < 0) + HGOTO_DONE(FALSE) + } /* end for */ done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5S_point_is_valid() */ +} /* end H5S__point_is_valid() */ /*-------------------------------------------------------------------------- @@ -750,18 +1035,136 @@ H5Sget_select_elem_npoints(hid_t spaceid) done: FUNC_LEAVE_API(ret_value) -} /* H5Sget_select_elem_npoints() */ +} /* end H5Sget_select_elem_npoints() */ /*-------------------------------------------------------------------------- NAME - H5S_point_serial_size + H5S__point_get_version_enc_size + PURPOSE + Determine the version and the size (2, 4 or 8 bytes) to encode point selection info + USAGE + hssize_t H5S__point_set_enc_size(space, version, enc_size) + const H5S_t *space: IN: Dataspace ID of selection to query + uint32_t *version: OUT: The version to use for encoding + uint8_t *enc_size: OUT: The size to use for encoding + RETURNS + The version and the size to encode point selection info + DESCRIPTION + Determine the version to use for encoding points selection info based + on the following: + (1) the low/high bounds setting in fapl + (2) whether the number of points or selection high bounds exceeds H5S_UINT32_MAX or not + + Determine the encoded size based on version: + --For version 2, the encoded size of point selection info is determined + by the maximum size for: + (a) storing the number of points + (b) storing the selection high bounds + + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5S__point_get_version_enc_size(const H5S_t *space, uint32_t *version, uint8_t *enc_size) +{ + hbool_t count_up_version = FALSE; /* Whether number of points exceed H5S_UINT32_MAX */ + hbool_t bound_up_version = FALSE; /* Whether high bounds exceed H5S_UINT32_MAX */ + H5F_libver_t low_bound; /* The 'low' bound of library format versions */ + H5F_libver_t high_bound; /* The 'high' bound of library format versions */ + uint32_t tmp_version; /* Local temporary version */ + hsize_t bounds_start[H5S_MAX_RANK]; /* Starting coordinate of bounding box */ + hsize_t bounds_end[H5S_MAX_RANK]; /* Opposite coordinate of bounding box */ + hsize_t max_size = 0; /* Maximum selection size */ + unsigned u; /* Local index veriable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Get bounding box for the selection */ + HDmemset(bounds_end, 0, sizeof(bounds_end)); + if(H5S__point_bounds(space, bounds_start, bounds_end) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get selection bounds") + + /* Determine whether number of points or high bounds exceeds (2^32 - 1) */ + if(space->select.num_elem > H5S_UINT32_MAX) + count_up_version = TRUE; + else + for(u = 0; u < space->extent.rank; u++) + if(bounds_end[u] > H5S_UINT32_MAX) { + bound_up_version = TRUE; + break; + } /* end if */ + + /* If exceed (2^32 -1) */ + if(count_up_version || bound_up_version) + tmp_version = H5S_POINT_VERSION_2; + else + tmp_version = H5S_POINT_VERSION_1; + + /* Get the file's low/high bounds */ + if(H5CX_get_libver_bounds(&low_bound, &high_bound) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get low/high bounds from API context") + + /* Upgrade to the version indicated by the file's low bound if higher */ + tmp_version = MAX(tmp_version, H5O_sds_point_ver_bounds[low_bound]); + + /* Version bounds check */ + if(tmp_version > H5O_sds_point_ver_bounds[high_bound]) { + if(count_up_version) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "The number of points in point selection exceeds 2^32") + else if(bound_up_version) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "The end of bounding box in point selection exceeds 2^32") + else + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "Dataspace point selection version out of bounds") + } /* end if */ + + /* Set the version to return */ + *version = tmp_version; + + /* Get the encoded size use based on version */ + switch(tmp_version) { + case H5S_POINT_VERSION_1: + *enc_size = H5S_SELECT_INFO_ENC_SIZE_4; + break; + + case H5S_POINT_VERSION_2: + /* Find max for num_elem and bounds_end[] */ + max_size = space->select.num_elem; + for(u = 0; u < space->extent.rank; u++) + if(bounds_end[u] > max_size) + max_size = bounds_end[u]; + + /* Determine the encoding size */ + if(max_size > H5S_UINT32_MAX) + *enc_size = H5S_SELECT_INFO_ENC_SIZE_8; + else if(max_size > H5S_UINT16_MAX) + *enc_size = H5S_SELECT_INFO_ENC_SIZE_4; + else + *enc_size = H5S_SELECT_INFO_ENC_SIZE_2; + break; + + default: + HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown point info size") + break; + } /* end switch */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S__point_get_version_enc_size() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S__point_serial_size PURPOSE Determine the number of bytes needed to store the serialized point selection information. USAGE - hssize_t H5S_point_serial_size(space) - H5S_t *space; IN: Dataspace pointer to query + hssize_t H5S__point_serial_size(space) + const H5S_t *space; IN: Dataspace pointer to query RETURNS The number of bytes required on success, negative on an error. DESCRIPTION @@ -773,35 +1176,52 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static hssize_t -H5S_point_serial_size (const H5S_t *space) +H5S__point_serial_size(const H5S_t *space) { + uint32_t version; /* Version number */ + uint8_t enc_size; /* Encoded size of point selection info */ hssize_t ret_value = -1; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC HDassert(space); - /* Basic number of bytes required to serialize point selection: - * <type (4 bytes)> + <version (4 bytes)> + <padding (4 bytes)> + - * <length (4 bytes)> + <rank (4 bytes)> + <# of points (4 bytes)> = 24 bytes - */ - ret_value = 24; + /* Determine the version and encoded size for point selection */ + if(H5S__point_get_version_enc_size(space, &version, &enc_size) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't determine hyper version") + + /* Basic number of bytes required to serialize point selection: */ + if(version >= H5S_POINT_VERSION_2) + /* + * <type (4 bytes)> + <version (4 bytes)> + + * <size of point info (1 byte)> + rank (4 bytes)> + */ + ret_value=13; + else + /* + * <type (4 bytes)> + <version (4 bytes)> + <padding (4 bytes)> + + * <length (4 bytes)> + <rank (4 bytes)> + */ + ret_value = 20; + + /* <num points (depend on enc_size)> */ + ret_value += enc_size; /* Count points in selection */ - /* (Add 4 bytes times the rank for each element selected) */ - ret_value += (4 * space->extent.rank) * (hssize_t)H5S_GET_SELECT_NPOINTS(space); + ret_value += (hssize_t) (enc_size * space->extent.rank * space->select.num_elem); +done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5S_point_serial_size() */ +} /* end H5S__point_serial_size() */ /*-------------------------------------------------------------------------- NAME - H5S_point_serialize + H5S__point_serialize PURPOSE Serialize the current selection into a user-provided buffer. USAGE - herr_t H5S_point_serialize(space, p) + herr_t H5S__point_serialize(space, p) const H5S_t *space; IN: Dataspace with selection to serialize uint8_t **p; OUT: Pointer to buffer to put serialized selection. Will be advanced to end of @@ -817,70 +1237,126 @@ H5S_point_serial_size (const H5S_t *space) REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_point_serialize (const H5S_t *space, uint8_t **p) +H5S__point_serialize(const H5S_t *space, uint8_t **p) { H5S_pnt_node_t *curr; /* Point information nodes */ - uint8_t *pp = (*p); /* Local pointer for decoding */ - uint8_t *lenp; /* pointer to length location for later storage */ + uint8_t *pp; /* Local pointer for decoding */ + uint8_t *lenp = NULL; /* pointer to length location for later storage */ uint32_t len=0; /* number of bytes used */ unsigned u; /* local counting variable */ + uint32_t version; /* Version number */ + uint8_t enc_size; /* Encoded size of point selection info */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC /* Check args */ HDassert(space); HDassert(p); + pp = (*p); HDassert(pp); + /* Determine the version and encoded size for point selection info */ + if(H5S__point_get_version_enc_size(space, &version, &enc_size) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't determine hyper version") + /* Store the preamble information */ UINT32ENCODE(pp, (uint32_t)H5S_GET_SELECT_TYPE(space)); /* Store the type of selection */ - UINT32ENCODE(pp, (uint32_t)1); /* Store the version number */ - UINT32ENCODE(pp, (uint32_t)0); /* Store the un-used padding */ - lenp = pp; /* Keep the pointer to the length location for later */ - pp += 4; /* Skip over space for length */ + + UINT32ENCODE(pp, version); /* Store the version number */ + if(version >= 2) { + *(pp)++ = enc_size; /* Store size of point info */ + } else { + HDassert(version == H5S_POINT_VERSION_1); + UINT32ENCODE(pp, (uint32_t)0); /* Store the un-used padding */ + lenp = pp; /* Keep the pointer to the length location for later */ + pp += 4; /* Skip over space for length */ + len += 8; /* Add in advance # of bytes for num of dimensions and num elements */ + } /* Encode number of dimensions */ UINT32ENCODE(pp, (uint32_t)space->extent.rank); - len+=4; - /* Encode number of elements */ - UINT32ENCODE(pp, (uint32_t)space->select.num_elem); - len+=4; + switch(enc_size) { + case H5S_SELECT_INFO_ENC_SIZE_2: + HDassert(version == H5S_POINT_VERSION_2); + + /* Encode number of elements */ + UINT16ENCODE(pp, (uint16_t)space->select.num_elem); + + /* Encode each point in selection */ + curr=space->select.sel_info.pnt_lst->head; + while(curr!=NULL) { + /* Encode each point */ + for(u=0; u<space->extent.rank; u++) + UINT16ENCODE(pp, (uint16_t)curr->pnt[u]); + curr=curr->next; + } /* end while */ + break; + + case H5S_SELECT_INFO_ENC_SIZE_4: + HDassert(version == H5S_POINT_VERSION_1 || version == H5S_POINT_VERSION_2); - /* Encode each point in selection */ - curr=space->select.sel_info.pnt_lst->head; - while(curr!=NULL) { - /* Add 4 bytes times the rank for each element selected */ - len+=4*space->extent.rank; + /* Encode number of elements */ + UINT32ENCODE(pp, (uint32_t)space->select.num_elem); - /* Encode each point */ - for(u=0; u<space->extent.rank; u++) - UINT32ENCODE(pp, (uint32_t)curr->pnt[u]); + /* Encode each point in selection */ + curr=space->select.sel_info.pnt_lst->head; + while(curr!=NULL) { + /* Encode each point */ + for(u=0; u<space->extent.rank; u++) + UINT32ENCODE(pp, (uint32_t)curr->pnt[u]); + curr=curr->next; + } /* end while */ - curr=curr->next; - } /* end while */ + /* Add 4 bytes times the rank for each element selected */ + if(version == H5S_POINT_VERSION_1) + len += (uint32_t)space->select.num_elem * 4 * space->extent.rank; + break; + + case H5S_SELECT_INFO_ENC_SIZE_8: + HDassert(version == H5S_POINT_VERSION_2); + + /* Encode number of elements */ + UINT64ENCODE(pp, space->select.num_elem); + + /* Encode each point in selection */ + curr=space->select.sel_info.pnt_lst->head; + while(curr!=NULL) { + /* Encode each point */ + for(u=0; u<space->extent.rank; u++) + UINT64ENCODE(pp, curr->pnt[u]); + curr=curr->next; + } /* end while */ + break; + + default: + HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown point info size") + break; + + } /* end switch */ - /* Encode length */ - UINT32ENCODE(lenp, (uint32_t)len); /* Store the length of the extra information */ + if(version == H5S_POINT_VERSION_1) + UINT32ENCODE(lenp, (uint32_t)len); /* Store the length of the extra information */ /* Update encoding pointer */ *p = pp; - FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5S_point_serialize() */ +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S__point_serialize() */ + /*-------------------------------------------------------------------------- NAME - H5S_point_deserialize + H5S__point_deserialize PURPOSE Deserialize the current selection from a user-provided buffer. USAGE - herr_t H5S_point_deserialize(space, p) - H5S_t *space; IN/OUT: Dataspace pointer to place + herr_t H5S__point_deserialize(space, p) + H5S_t **space; IN/OUT: Dataspace pointer to place selection into - uint32_t version IN: Selection version - uint8_t flags IN: Selection flags uint8 **p; OUT: Pointer to buffer holding serialized selection. Will be advanced to end of serialized selection. @@ -895,28 +1371,85 @@ H5S_point_serialize (const H5S_t *space, uint8_t **p) REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_point_deserialize(H5S_t *space, uint32_t H5_ATTR_UNUSED version, uint8_t H5_ATTR_UNUSED flags, - const uint8_t **p) +H5S__point_deserialize(H5S_t **space, const uint8_t **p) { - H5S_seloper_t op = H5S_SELECT_SET; /* Selection operation */ + H5S_t *tmp_space = NULL; /* Pointer to actual dataspace to use, + either *space or a newly allocated one */ + hsize_t dims[H5S_MAX_RANK]; /* Dimension sizes */ + uint32_t version; /* Version number */ + uint8_t enc_size = 0; /* Encoded size of selection info */ hsize_t *coord = NULL, *tcoord; /* Pointer to array of elements */ - const uint8_t *pp = (*p); /* Local pointer for decoding */ - size_t num_elem = 0; /* Number of elements in selection */ + const uint8_t *pp; /* Local pointer for decoding */ + uint64_t num_elem = 0; /* Number of elements in selection */ unsigned rank; /* Rank of points */ unsigned i, j; /* local counting variables */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC /* Check args */ - HDassert(space); HDassert(p); + pp = (*p); HDassert(pp); - /* Deserialize points to select */ - /* (The header and rank have already beed decoded) */ - rank = space->extent.rank; /* Retrieve rank from space */ - UINT32DECODE(pp, num_elem); /* decode the number of points */ + /* As part of the efforts to push all selection-type specific coding + to the callbacks, the coding for the allocation of a null dataspace + is moved from H5S_select_deserialize() in H5Sselect.c to here. + This is needed for decoding virtual layout in H5O__layout_decode() */ + /* Allocate space if not provided */ + if(!*space) { + if(NULL == (tmp_space = H5S_create(H5S_SIMPLE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create dataspace") + } /* end if */ + else + tmp_space = *space; + + /* Decode version */ + UINT32DECODE(pp, version); + + if(version >= (uint32_t)H5S_POINT_VERSION_2) + /* Decode size of point info */ + enc_size = *(pp)++; + else { + /* Skip over the remainder of the header */ + pp += 8; + enc_size = H5S_SELECT_INFO_ENC_SIZE_4; + } + + /* Check encoded size */ + if(enc_size & ~H5S_SELECT_INFO_ENC_SIZE_BITS) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTLOAD, FAIL, "unknown size of point/offset info for selection") + + /* Decode the rank of the point selection */ + UINT32DECODE(pp,rank); + + if(!*space) { + /* Patch the rank of the allocated dataspace */ + (void)HDmemset(dims, 0, (size_t)rank * sizeof(dims[0])); + if(H5S_set_extent_simple(tmp_space, rank, dims, NULL) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't set dimensions") + } /* end if */ + else + /* Verify the rank of the provided dataspace */ + if(rank != tmp_space->extent.rank) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "rank of serialized selection does not match dataspace") + + /* decode the number of points */ + switch(enc_size) { + case H5S_SELECT_INFO_ENC_SIZE_2: + UINT16DECODE(pp, num_elem); + break; + case H5S_SELECT_INFO_ENC_SIZE_4: + UINT32DECODE(pp, num_elem); + break; + case H5S_SELECT_INFO_ENC_SIZE_8: + UINT64DECODE(pp, num_elem); + break; + default: + HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown point info size") + break; + } /* end switch */ + /* Allocate space for the coordinates */ if(NULL == (coord = (hsize_t *)H5MM_malloc(num_elem * rank * sizeof(hsize_t)))) @@ -925,32 +1458,56 @@ H5S_point_deserialize(H5S_t *space, uint32_t H5_ATTR_UNUSED version, uint8_t H5_ /* Retrieve the coordinates from the buffer */ for(tcoord = coord, i = 0; i < num_elem; i++) for(j = 0; j < (unsigned)rank; j++, tcoord++) - UINT32DECODE(pp, *tcoord); + switch(enc_size) { + case H5S_SELECT_INFO_ENC_SIZE_2: + UINT16DECODE(pp, *tcoord); + break; + + case H5S_SELECT_INFO_ENC_SIZE_4: + UINT32DECODE(pp, *tcoord); + break; + + case H5S_SELECT_INFO_ENC_SIZE_8: + UINT64DECODE(pp, *tcoord); + break; + default: + HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown point info size") + break; + } /* end switch */ /* Select points */ - if(H5S_select_elements(space, op, num_elem, (const hsize_t *)coord) < 0) + if(H5S_select_elements(tmp_space, H5S_SELECT_SET, num_elem, (const hsize_t *)coord) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection") /* Update decoding pointer */ *p = pp; + /* Return space to the caller if allocated */ + if(!*space) + *space = tmp_space; + done: + /* Free temporary space if not passed to caller (only happens on error) */ + if(!*space && tmp_space) + if(H5S_close(tmp_space) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "can't close dataspace") + /* Free the coordinate array if necessary */ if(coord != NULL) H5MM_xfree(coord); FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_point_deserialize() */ +} /* end H5S__point_deserialize() */ /*-------------------------------------------------------------------------- NAME - H5S_get_select_elem_pointlist + H5S__get_select_elem_pointlist PURPOSE Get the list of element points currently selected USAGE - herr_t H5S_get_select_elem_pointlist(space, hsize_t *buf) - H5S_t *space; IN: Dataspace pointer of selection to query + herr_t H5S__get_select_elem_pointlist(space, hsize_t *buf) + const H5S_t *space; IN: Dataspace pointer of selection to query hsize_t startpoint; IN: Element point to start with hsize_t numpoints; IN: Number of element points to get hsize_t *buf; OUT: List of element points selected @@ -973,12 +1530,13 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_get_select_elem_pointlist(H5S_t *space, hsize_t startpoint, hsize_t numpoints, hsize_t *buf) +H5S__get_select_elem_pointlist(const H5S_t *space, hsize_t startpoint, + hsize_t numpoints, hsize_t *buf) { H5S_pnt_node_t *node; /* Point node */ unsigned rank; /* Dataspace rank */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR HDassert(space); HDassert(buf); @@ -997,14 +1555,14 @@ H5S_get_select_elem_pointlist(H5S_t *space, hsize_t startpoint, hsize_t numpoint /* Iterate through the node, copying each point's information */ while(node != NULL && numpoints > 0) { - HDmemcpy(buf, node->pnt, sizeof(hsize_t) * rank); + H5MM_memcpy(buf, node->pnt, sizeof(hsize_t) * rank); buf += rank; numpoints--; node = node->next; } /* end while */ FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5S_get_select_elem_pointlist() */ +} /* end H5S__get_select_elem_pointlist() */ /*-------------------------------------------------------------------------- @@ -1054,20 +1612,20 @@ H5Sget_select_elem_pointlist(hid_t spaceid, hsize_t startpoint, if(H5S_GET_SELECT_TYPE(space) != H5S_SEL_POINTS) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a point selection") - ret_value = H5S_get_select_elem_pointlist(space, startpoint, numpoints, buf); + ret_value = H5S__get_select_elem_pointlist(space, startpoint, numpoints, buf); done: FUNC_LEAVE_API(ret_value) -} /* H5Sget_select_elem_pointlist() */ +} /* end H5Sget_select_elem_pointlist() */ /*-------------------------------------------------------------------------- NAME - H5S_point_bounds + H5S__point_bounds PURPOSE Gets the bounding box containing the selection. USAGE - herr_t H5S_point_bounds(space, start, end) + herr_t H5S__point_bounds(space, start, end) H5S_t *space; IN: Dataspace pointer of selection to query hsize_t *start; OUT: Starting coordinate of bounding box hsize_t *end; OUT: Opposite coordinate of bounding box @@ -1088,57 +1646,44 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_point_bounds(const H5S_t *space, hsize_t *start, hsize_t *end) +H5S__point_bounds(const H5S_t *space, hsize_t *start, hsize_t *end) { - H5S_pnt_node_t *node; /* Point node */ - unsigned rank; /* Dataspace rank */ unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC /* Sanity check */ HDassert(space); HDassert(start); HDassert(end); - /* Get the dataspace extent rank */ - rank = space->extent.rank; - - /* Set the start and end arrays up */ - for(u = 0; u < rank; u++) { - start[u] = HSIZET_MAX; - end[u] = 0; - } /* end for */ + /* Loop over dimensions */ + for(u = 0; u < space->extent.rank; u++) { + /* Sanity check */ + HDassert(space->select.sel_info.pnt_lst->low_bounds[u] <= space->select.sel_info.pnt_lst->high_bounds[u]); - /* Iterate through the node, checking the bounds on each element */ - node = space->select.sel_info.pnt_lst->head; - while(node != NULL) { - for(u = 0; u < rank; u++) { - /* Check for offset moving selection negative */ - if(((hssize_t)node->pnt[u] + space->select.offset[u]) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds") + /* Check for offset moving selection negative */ + if(((hssize_t)space->select.sel_info.pnt_lst->low_bounds[u] + space->select.offset[u]) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds") - if(start[u] > (hsize_t)((hssize_t)node->pnt[u] + space->select.offset[u])) - start[u] = (hsize_t)((hssize_t)node->pnt[u] + space->select.offset[u]); - if(end[u] < (hsize_t)((hssize_t)node->pnt[u] + space->select.offset[u])) - end[u] = (hsize_t)((hssize_t)node->pnt[u] + space->select.offset[u]); - } /* end for */ - node = node->next; - } /* end while */ + /* Set the low & high bounds in this dimension */ + start[u] = (hsize_t)((hssize_t)space->select.sel_info.pnt_lst->low_bounds[u] + space->select.offset[u]); + end[u] = (hsize_t)((hssize_t)space->select.sel_info.pnt_lst->high_bounds[u] + space->select.offset[u]); + } /* end for */ done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_point_bounds() */ +} /* end H5S__point_bounds() */ /*-------------------------------------------------------------------------- NAME - H5S_point_offset + H5S__point_offset PURPOSE Gets the linear offset of the first element for the selection. USAGE - herr_t H5S_point_offset(space, offset) + herr_t H5S__point_offset(space, offset) const H5S_t *space; IN: Dataspace pointer of selection to query hsize_t *offset; OUT: Linear offset of first element in selection RETURNS @@ -1153,7 +1698,7 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_point_offset(const H5S_t *space, hsize_t *offset) +H5S__point_offset(const H5S_t *space, hsize_t *offset) { const hsize_t *pnt; /* Pointer to a selected point's coordinates */ const hssize_t *sel_offset; /* Pointer to the selection's offset */ @@ -1162,7 +1707,7 @@ H5S_point_offset(const H5S_t *space, hsize_t *offset) int i; /* index variable */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_STATIC HDassert(space); HDassert(offset); @@ -1193,7 +1738,7 @@ H5S_point_offset(const H5S_t *space, hsize_t *offset) done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_point_offset() */ +} /* end H5S__point_offset() */ /*-------------------------------------------------------------------------- @@ -1227,11 +1772,11 @@ H5S__point_unlim_dim(const H5S_t H5_ATTR_UNUSED *space) /*-------------------------------------------------------------------------- NAME - H5S_point_is_contiguous + H5S__point_is_contiguous PURPOSE Check if a point selection is contiguous within the dataspace extent. USAGE - htri_t H5S_point_is_contiguous(space) + htri_t H5S__point_is_contiguous(space) H5S_t *space; IN: Dataspace pointer to check RETURNS TRUE/FALSE/FAIL @@ -1247,31 +1792,31 @@ H5S__point_unlim_dim(const H5S_t H5_ATTR_UNUSED *space) REVISION LOG --------------------------------------------------------------------------*/ static htri_t -H5S_point_is_contiguous(const H5S_t *space) +H5S__point_is_contiguous(const H5S_t *space) { htri_t ret_value = FAIL; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR HDassert(space); /* One point is definitely contiguous */ - if(space->select.num_elem==1) - ret_value=TRUE; + if(space->select.num_elem == 1) + ret_value = TRUE; else /* More than one point might be contiguous, but it's complex to check and we don't need it right now */ - ret_value=FALSE; + ret_value = FALSE; FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_point_is_contiguous() */ +} /* end H5S__point_is_contiguous() */ /*-------------------------------------------------------------------------- NAME - H5S_point_is_single + H5S__point_is_single PURPOSE Check if a point selection is single within the dataspace extent. USAGE - htri_t H5S_point_is_single(space) + htri_t H5S__point_is_single(space) H5S_t *space; IN: Dataspace pointer to check RETURNS TRUE/FALSE/FAIL @@ -1284,31 +1829,31 @@ H5S_point_is_contiguous(const H5S_t *space) REVISION LOG --------------------------------------------------------------------------*/ static htri_t -H5S_point_is_single(const H5S_t *space) +H5S__point_is_single(const H5S_t *space) { htri_t ret_value = FAIL; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR HDassert(space); /* One point is definitely 'single' :-) */ - if(space->select.num_elem==1) - ret_value=TRUE; + if(space->select.num_elem == 1) + ret_value = TRUE; else - ret_value=FALSE; + ret_value = FALSE; FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_point_is_single() */ +} /* end H5S__point_is_single() */ /*-------------------------------------------------------------------------- NAME - H5S_point_is_regular + H5S__point_is_regular PURPOSE Check if a point selection is "regular" USAGE - htri_t H5S_point_is_regular(space) + htri_t H5S__point_is_regular(space) const H5S_t *space; IN: Dataspace pointer to check RETURNS TRUE/FALSE/FAIL @@ -1324,32 +1869,140 @@ H5S_point_is_single(const H5S_t *space) REVISION LOG --------------------------------------------------------------------------*/ static htri_t -H5S_point_is_regular(const H5S_t *space) +H5S__point_is_regular(const H5S_t *space) { htri_t ret_value = FAIL; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR /* Check args */ HDassert(space); /* Only simple check for regular points for now... */ - if(space->select.num_elem==1) - ret_value=TRUE; + if(space->select.num_elem == 1) + ret_value = TRUE; else - ret_value=FALSE; + ret_value = FALSE; FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_point_is_regular() */ +} /* end H5S__point_is_regular() */ /*-------------------------------------------------------------------------- NAME - H5S_point_adjust_u + H5S__point_shape_same + PURPOSE + Check if a two "point" selections are the same shape + USAGE + htri_t H5S__point_shape_same(space1, space2) + const H5S_t *space1; IN: First dataspace to check + const H5S_t *space2; IN: Second dataspace to check + RETURNS + TRUE / FALSE / FAIL + DESCRIPTION + Checks to see if the current selection in each dataspace are the same + shape. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static htri_t +H5S__point_shape_same(const H5S_t *space1, const H5S_t *space2) +{ + H5S_pnt_node_t *pnt1, *pnt2; /* Point information nodes */ + hssize_t offset[H5S_MAX_RANK]; /* Offset between the selections */ + unsigned space1_rank; /* Number of dimensions of first dataspace */ + unsigned space2_rank; /* Number of dimensions of second dataspace */ + int space1_dim; /* Current dimension in first dataspace */ + int space2_dim; /* Current dimension in second dataspace */ + htri_t ret_value = TRUE; /* Return value */ + + FUNC_ENTER_STATIC_NOERR + + /* Check args */ + HDassert(space1); + HDassert(space2); + + /* Get dataspace ranks */ + space1_rank = space1->extent.rank; + space2_rank = space2->extent.rank; + + /* Sanity check */ + HDassert(space1_rank >= space2_rank); + HDassert(space2_rank > 0); + + /* Initialize dimensions */ + space1_dim = (int)space1_rank - 1; + space2_dim = (int)space2_rank - 1; + + /* Look at first point in each selection to compute the offset for common + * dimensions. + */ + pnt1 = space1->select.sel_info.pnt_lst->head; + pnt2 = space2->select.sel_info.pnt_lst->head; + while(space2_dim >= 0) { + /* Set the relative locations of the selections */ + offset[space1_dim] = (hssize_t)pnt2->pnt[space2_dim] - (hssize_t)pnt1->pnt[space1_dim]; + + space1_dim--; + space2_dim--; + } /* end while */ + + /* For dimensions that appear only in space1: */ + while(space1_dim >= 0) { + /* Set the absolute offset of the remaining dimensions */ + offset[space1_dim] = (hssize_t)pnt1->pnt[space1_dim]; + + space1_dim--; + } /* end while */ + + /* Advance to next point */ + pnt1 = pnt1->next; + pnt2 = pnt2->next; + + /* Loop over remaining points */ + while(pnt1 && pnt2) { + /* Initialize dimensions */ + space1_dim = (int)space1_rank - 1; + space2_dim = (int)space2_rank - 1; + + /* Compare locations in common dimensions, including relative offset */ + while(space2_dim >= 0) { + if((hsize_t)((hssize_t)pnt1->pnt[space1_dim] + offset[space1_dim]) != pnt2->pnt[space2_dim]) + HGOTO_DONE(FALSE) + + space1_dim--; + space2_dim--; + } /* end while */ + + /* For dimensions that appear only in space1: */ + while(space1_dim >= 0) { + /* Compare the absolute offset in the remaining dimensions */ + if((hssize_t)pnt1->pnt[space1_dim] != offset[space1_dim]) + HGOTO_DONE(FALSE) + + space1_dim--; + } /* end while */ + + + /* Advance to next point */ + pnt1 = pnt1->next; + pnt2 = pnt2->next; + } /* end while */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S__point_shape_same() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S__point_adjust_u PURPOSE Adjust a "point" selection by subtracting an offset USAGE - herr_t H5S_point_adjust_u(space, offset) + herr_t H5S__point_adjust_u(space, offset) H5S_t *space; IN/OUT: Pointer to dataspace to adjust const hsize_t *offset; IN: Offset to subtract RETURNS @@ -1362,12 +2015,13 @@ H5S_point_is_regular(const H5S_t *space) REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_point_adjust_u(H5S_t *space, const hsize_t *offset) +H5S__point_adjust_u(H5S_t *space, const hsize_t *offset) { H5S_pnt_node_t *node; /* Point node */ unsigned rank; /* Dataspace rank */ + unsigned u; /* Local index variable */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR HDassert(space); HDassert(offset); @@ -1376,8 +2030,6 @@ H5S_point_adjust_u(H5S_t *space, const hsize_t *offset) node = space->select.sel_info.pnt_lst->head; rank = space->extent.rank; while(node) { - unsigned u; /* Local index variable */ - /* Adjust each coordinate for point node */ for(u = 0; u < rank; u++) { /* Check for offset moving selection negative */ @@ -1391,17 +2043,23 @@ H5S_point_adjust_u(H5S_t *space, const hsize_t *offset) node = node->next; } /* end while */ + /* update the bound box of the selection */ + for(u = 0; u < rank; u++) { + space->select.sel_info.pnt_lst->low_bounds[u] -= offset[u]; + space->select.sel_info.pnt_lst->high_bounds[u] -= offset[u]; + } /* end for */ + FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5S_point_adjust_u() */ +} /* end H5S__point_adjust_u() */ /*------------------------------------------------------------------------- - * Function: H5S_point_project_scalar + * Function: H5S__point_project_scalar * * Purpose: Projects a single element point selection into a scalar * dataspace * - * Return: non-negative on success, negative on failure. + * Return: Non-negative on success, negative on failure. * * Programmer: Quincey Koziol * Sunday, July 18, 2010 @@ -1409,12 +2067,12 @@ H5S_point_adjust_u(H5S_t *space, const hsize_t *offset) *------------------------------------------------------------------------- */ static herr_t -H5S_point_project_scalar(const H5S_t *space, hsize_t *offset) +H5S__point_project_scalar(const H5S_t *space, hsize_t *offset) { const H5S_pnt_node_t *node; /* Point node */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC /* Check args */ HDassert(space && H5S_SEL_POINTS == H5S_GET_SELECT_TYPE(space)); @@ -1428,20 +2086,20 @@ H5S_point_project_scalar(const H5S_t *space, hsize_t *offset) HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "point selection of one element has more than one node!") /* Calculate offset of selection in projected buffer */ - *offset = H5VM_array_offset(space->extent.rank, space->extent.size, node->pnt); + *offset = H5VM_array_offset(space->extent.rank, space->extent.size, node->pnt); done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_point_project_scalar() */ +} /* end H5S__point_project_scalar() */ /*------------------------------------------------------------------------- - * Function: H5S_point_project_simple + * Function: H5S__point_project_simple * * Purpose: Projects a point selection onto/into a simple dataspace * of a different rank * - * Return: non-negative on success, negative on failure. + * Return: Non-negative on success, negative on failure. * * Programmer: Quincey Koziol * Sunday, July 18, 2010 @@ -1449,15 +2107,16 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5S_point_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *offset) +H5S__point_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *offset) { const H5S_pnt_node_t *base_node; /* Point node in base space */ H5S_pnt_node_t *new_node; /* Point node in new space */ H5S_pnt_node_t *prev_node; /* Previous point node in new space */ unsigned rank_diff; /* Difference in ranks between spaces */ + unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC /* Check args */ HDassert(base_space && H5S_SEL_POINTS == H5S_GET_SELECT_TYPE(base_space)); @@ -1481,24 +2140,20 @@ H5S_point_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *off /* Calculate offset of selection in projected buffer */ HDmemset(block, 0, sizeof(block)); - HDmemcpy(block, base_space->select.sel_info.pnt_lst->head->pnt, sizeof(hsize_t) * rank_diff); - *offset = H5VM_array_offset(base_space->extent.rank, base_space->extent.size, block); + H5MM_memcpy(block, base_space->select.sel_info.pnt_lst->head->pnt, sizeof(hsize_t) * rank_diff); + *offset = H5VM_array_offset(base_space->extent.rank, base_space->extent.size, block); /* Iterate through base space's point nodes, copying the point information */ base_node = base_space->select.sel_info.pnt_lst->head; prev_node = NULL; while(base_node) { /* Create new point */ - if(NULL == (new_node = H5FL_MALLOC(H5S_pnt_node_t))) + if(NULL == (new_node = (H5S_pnt_node_t *)H5FL_ARR_MALLOC(hcoords_t, new_space->extent.rank))) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate point node") new_node->next = NULL; - if(NULL == (new_node->pnt = (hsize_t *)H5MM_malloc(new_space->extent.rank * sizeof(hsize_t)))) { - new_node = H5FL_FREE(H5S_pnt_node_t, new_node); - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate coordinate information") - } /* end if */ /* Copy over the point's coordinates */ - HDmemcpy(new_node->pnt, &base_node->pnt[rank_diff], (new_space->extent.rank * sizeof(hsize_t))); + H5MM_memcpy(new_node->pnt, &base_node->pnt[rank_diff], (new_space->extent.rank * sizeof(hsize_t))); /* Keep the order the same when copying */ if(NULL == prev_node) @@ -1511,6 +2166,12 @@ H5S_point_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *off /* Advance to next node */ base_node = base_node->next; } /* end while */ + + /* Update the bounding box */ + for(u = 0; u < new_space->extent.rank; u++) { + new_space->select.sel_info.pnt_lst->low_bounds[u] = base_space->select.sel_info.pnt_lst->low_bounds[u + rank_diff]; + new_space->select.sel_info.pnt_lst->high_bounds[u] = base_space->select.sel_info.pnt_lst->high_bounds[u + rank_diff]; + } /* end for */ } /* end if */ else { HDassert(new_space->extent.rank > base_space->extent.rank); @@ -1526,17 +2187,13 @@ H5S_point_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *off prev_node = NULL; while(base_node) { /* Create new point */ - if(NULL == (new_node = H5FL_MALLOC(H5S_pnt_node_t))) + if(NULL == (new_node = (H5S_pnt_node_t *)H5FL_ARR_MALLOC(hcoords_t, new_space->extent.rank))) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate point node") new_node->next = NULL; - if(NULL == (new_node->pnt = (hsize_t *)H5MM_malloc(new_space->extent.rank * sizeof(hsize_t)))) { - new_node = H5FL_FREE(H5S_pnt_node_t, new_node); - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate coordinate information") - } /* end if */ /* Copy over the point's coordinates */ HDmemset(new_node->pnt, 0, sizeof(hsize_t) * rank_diff); - HDmemcpy(&new_node->pnt[rank_diff], base_node->pnt, (new_space->extent.rank * sizeof(hsize_t))); + H5MM_memcpy(&new_node->pnt[rank_diff], base_node->pnt, (new_space->extent.rank * sizeof(hsize_t))); /* Keep the order the same when copying */ if(NULL == prev_node) @@ -1549,6 +2206,16 @@ H5S_point_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *off /* Advance to next node */ base_node = base_node->next; } /* end while */ + + /* Update the bounding box */ + for(u = 0; u < rank_diff; u++) { + new_space->select.sel_info.pnt_lst->low_bounds[u] = 0; + new_space->select.sel_info.pnt_lst->high_bounds[u] = 0; + } /* end for */ + for(; u < new_space->extent.rank; u++) { + new_space->select.sel_info.pnt_lst->low_bounds[u] = base_space->select.sel_info.pnt_lst->low_bounds[u - rank_diff]; + new_space->select.sel_info.pnt_lst->high_bounds[u] = base_space->select.sel_info.pnt_lst->high_bounds[u - rank_diff]; + } /* end for */ } /* end else */ /* Number of elements selected will be the same */ @@ -1559,7 +2226,7 @@ H5S_point_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *off done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_point_project_simple() */ +} /* end H5S__point_project_simple() */ /*-------------------------------------------------------------------------- @@ -1620,143 +2287,5 @@ H5Sselect_elements(hid_t spaceid, H5S_seloper_t op, size_t num_elem, done: FUNC_LEAVE_API(ret_value) -} /* H5Sselect_elements() */ - - -/*-------------------------------------------------------------------------- - NAME - H5S_point_get_seq_list - PURPOSE - Create a list of offsets & lengths for a selection - USAGE - herr_t H5S_point_get_seq_list(space,flags,iter,maxseq,maxelem,nseq,nelem,off,len) - H5S_t *space; IN: Dataspace containing selection to use. - unsigned flags; IN: Flags for extra information about operation - H5S_sel_iter_t *iter; IN/OUT: Selection iterator describing last - position of interest in selection. - size_t maxseq; IN: Maximum number of sequences to generate - size_t maxelem; IN: Maximum number of elements to include in the - generated sequences - size_t *nseq; OUT: Actual number of sequences generated - size_t *nelem; OUT: Actual number of elements in sequences generated - hsize_t *off; OUT: Array of offsets - size_t *len; OUT: Array of lengths - RETURNS - Non-negative on success/Negative on failure. - DESCRIPTION - Use the selection in the dataspace to generate a list of byte offsets and - lengths for the region(s) selected. Start/Restart from the position in the - ITER parameter. The number of sequences generated is limited by the MAXSEQ - parameter and the number of sequences actually generated is stored in the - NSEQ parameter. - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - EXAMPLES - REVISION LOG ---------------------------------------------------------------------------*/ -static herr_t -H5S_point_get_seq_list(const H5S_t *space, unsigned flags, H5S_sel_iter_t *iter, - size_t maxseq, size_t maxelem, size_t *nseq, size_t *nelem, - hsize_t *off, size_t *len) -{ - size_t io_left; /* The number of bytes left in the selection */ - size_t start_io_left; /* The initial number of bytes left in the selection */ - H5S_pnt_node_t *node; /* Point node */ - hsize_t dims[H5O_LAYOUT_NDIMS]; /* Total size of memory buf */ - int ndims; /* Dimensionality of space*/ - hsize_t acc; /* Coordinate accumulator */ - hsize_t loc; /* Coordinate offset */ - size_t curr_seq; /* Current sequence being operated on */ - int i; /* Local index variable */ - herr_t ret_value=SUCCEED; /* return value */ - - FUNC_ENTER_NOAPI_NOINIT - - /* Check args */ - HDassert(space); - HDassert(iter); - HDassert(maxseq > 0); - HDassert(maxelem > 0); - HDassert(nseq); - HDassert(nelem); - HDassert(off); - HDassert(len); - - /* Choose the minimum number of bytes to sequence through */ - H5_CHECK_OVERFLOW(iter->elmt_left, hsize_t, size_t); - start_io_left = io_left = (size_t)MIN(iter->elmt_left, maxelem); - - /* Get the dataspace dimensions */ - if((ndims = H5S_get_simple_extent_dims (space, dims, NULL)) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to retrieve dataspace dimensions") - - /* Walk through the points in the selection, starting at the current */ - /* location in the iterator */ - node = iter->u.pnt.curr; - curr_seq = 0; - while(NULL != node) { - /* Compute the offset of each selected point in the buffer */ - for(i = ndims - 1, acc = iter->elmt_size, loc = 0; i >= 0; i--) { - loc += (hsize_t)((hssize_t)node->pnt[i] + space->select.offset[i]) * acc; - acc *= dims[i]; - } /* end for */ - - /* Check if this is a later point in the selection */ - if(curr_seq>0) { - /* If a sorted sequence is requested, make certain we don't go backwards in the offset */ - if((flags&H5S_GET_SEQ_LIST_SORTED) && loc<off[curr_seq-1]) - break; - - /* Check if this point extends the previous sequence */ - /* (Unlikely, but possible) */ - if(loc==(off[curr_seq-1]+len[curr_seq-1])) { - /* Extend the previous sequence */ - len[curr_seq-1]+=iter->elmt_size; - } /* end if */ - else { - /* Add a new sequence */ - off[curr_seq]=loc; - len[curr_seq]=iter->elmt_size; - - /* Increment sequence count */ - curr_seq++; - } /* end else */ - } /* end if */ - else { - /* Add a new sequence */ - off[curr_seq]=loc; - len[curr_seq]=iter->elmt_size; - - /* Increment sequence count */ - curr_seq++; - } /* end else */ - - /* Decrement number of elements left to process */ - io_left--; - - /* Move the iterator */ - iter->u.pnt.curr=node->next; - iter->elmt_left--; - - /* Check if we're finished with all sequences */ - if(curr_seq==maxseq) - break; - - /* Check if we're finished with all the elements available */ - if(io_left==0) - break; - - /* Advance to the next point */ - node=node->next; - } /* end while */ - - /* Set the number of sequences generated */ - *nseq=curr_seq; - - /* Set the number of elements used */ - *nelem=start_io_left-io_left; - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5S_point_get_seq_list() */ +} /* end H5Sselect_elements() */ |