summaryrefslogtreecommitdiffstats
path: root/src/H5Sselect.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Sselect.c')
-rw-r--r--src/H5Sselect.c1265
1 files changed, 1224 insertions, 41 deletions
diff --git a/src/H5Sselect.c b/src/H5Sselect.c
index c4a6bdb..7c239bb 100644
--- a/src/H5Sselect.c
+++ b/src/H5Sselect.c
@@ -10,13 +10,13 @@
#define H5S_PACKAGE /*suppress error about including H5Spkg */
-#include "H5private.h"
-#include "H5Eprivate.h"
-#include "H5FLprivate.h" /*Free Lists */
-#include "H5Iprivate.h"
-#include "H5MMprivate.h"
-#include "H5Spkg.h"
-#include "H5Vprivate.h"
+#include "H5private.h" /* Generic Functions */
+#include "H5Dprivate.h" /* Datasets (for their properties) */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5FLprivate.h" /* Free Lists */
+#include "H5Iprivate.h" /* ID Functions */
+#include "H5Spkg.h" /* Dataspace functions */
+#include "H5Vprivate.h" /* Vector functions */
/* Interface initialization */
#define PABLO_MASK H5Sselect_mask
@@ -32,6 +32,18 @@ static herr_t H5S_get_select_bounds(H5S_t *space, hsize_t *start, hsize_t *end);
/* Declare external the free list for hssize_t arrays */
H5FL_ARR_EXTERN(hssize_t);
+/* Declare a free list to manage arrays of size_t */
+H5FL_ARR_DEFINE_STATIC(size_t,-1);
+
+/* Declare a free list to manage arrays of hsize_t */
+H5FL_ARR_DEFINE_STATIC(hsize_t,-1);
+
+/* Declare a free list to manage the H5S_sel_iter_t struct */
+H5FL_DEFINE_STATIC(H5S_sel_iter_t);
+
+/* Declare a free list to manage blocks of single datatype element data */
+H5FL_BLK_EXTERN(type_elem);
+
/*--------------------------------------------------------------------------
NAME
@@ -207,6 +219,7 @@ H5Sget_select_npoints(hid_t spaceid)
FUNC_LEAVE (ret_value);
} /* H5Sget_select_npoints() */
+
/*--------------------------------------------------------------------------
NAME
@@ -258,6 +271,7 @@ H5S_get_select_npoints (const H5S_t *space)
FUNC_LEAVE (ret_value);
} /* H5S_get_select_npoints() */
+
/*--------------------------------------------------------------------------
NAME
@@ -1220,6 +1234,59 @@ H5S_select_contiguous(const H5S_t *space)
/*--------------------------------------------------------------------------
NAME
+ H5S_select_iter_init
+ PURPOSE
+ Construct an iterator for a dataspace & selection
+ USAGE
+ herr_t H5S_select_iter_init(space, elmt_size, iter)
+ H5S_t *space; IN: Dataspace object containing selection to iterate over
+ size_t elmt_size; IN: Size of element in dataspace
+ H5S_sel_iter_t *iter; OUT: Iterator to initialize
+ RETURNS
+ Non-negative on success, negative on failure
+ DESCRIPTION
+ Genericly initializes an iterator, based on the type of selection in the
+ dataspace.
+--------------------------------------------------------------------------*/
+herr_t
+H5S_select_iter_init(const H5S_t *space, size_t elmt_size, H5S_sel_iter_t *iter)
+{
+ herr_t ret_value=FAIL; /* return value */
+
+ FUNC_ENTER_NOINIT(H5S_select_iter_init);
+
+ assert(space);
+ assert(iter);
+
+ /* Initialize iterator */
+ switch(space->select.type) {
+ case H5S_SEL_POINTS: /* Sequence of points selected */
+ ret_value=H5S_point_init(space,elmt_size,iter);
+ break;
+
+ case H5S_SEL_HYPERSLABS: /* Hyperslab selection defined */
+ ret_value=H5S_hyper_init(space,elmt_size,iter);
+ break;
+
+ case H5S_SEL_ALL: /* Entire extent selected */
+ ret_value=H5S_all_init(space,elmt_size,iter);
+ break;
+
+ case H5S_SEL_NONE: /* Nothing selected */
+ ret_value=FALSE;
+ break;
+
+ case H5S_SEL_ERROR:
+ case H5S_SEL_N:
+ break;
+ }
+
+ FUNC_LEAVE (ret_value);
+} /* end H5S_select_iter_init() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5S_select_iterate
PURPOSE
Iterate over the selected elements in a memory buffer.
@@ -1250,37 +1317,137 @@ herr_t
H5S_select_iterate(void *buf, hid_t type_id, H5S_t *space, H5D_operator_t op,
void *operator_data)
{
- herr_t ret_value=FAIL;
+ H5T_t *dt; /* Datatype structure */
+ H5P_genplist_t *dx_plist; /* Dataset transfer property list */
+ H5S_sel_iter_t *iter=NULL; /* Selection iteration info */
+ uint8_t *loc; /* Current element location in buffer */
+ hssize_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=NULL; /* Array to store sequence offsets */
+ hsize_t curr_off; /* Current offset within sequence */
+ hsize_t tmp_off; /* Temporary offset within sequence */
+ size_t *len=NULL; /* Array to store sequence lengths */
+ size_t curr_len; /* Length of bytes left to process in sequence */
+ size_t vector_size; /* Value for vector size */
+ size_t nseq; /* Number of sequences generated */
+ size_t curr_seq; /* Current sequnce being worked on */
+ size_t nbytes; /* Number of bytes used in sequences */
+ size_t max_bytes; /* Maximum number of bytes allowed in sequences */
+ size_t elmt_size; /* Datatype size */
+ int 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 */
FUNC_ENTER_NOAPI(H5S_select_iterate, FAIL);
/* Check args */
assert(buf);
+ assert(H5I_DATATYPE == H5I_get_type(type_id));
assert(space);
assert(op);
- assert(H5I_DATATYPE == H5I_get_type(type_id));
- switch(space->select.type) {
- case H5S_SEL_POINTS: /* Sequence of points selected */
- ret_value=H5S_point_select_iterate(buf,type_id,space,op,operator_data);
- break;
+ /* Get the hyperslab vector size */
+ /* (from the default data transfer property list, for now) */
+ dx_plist = H5I_object(H5P_DATASET_XFER_DEFAULT);
+ assert(dx_plist);
+ if (H5P_get(dx_plist,H5D_XFER_HYPER_VECTOR_SIZE_NAME,&vector_size)<0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get value");
+
+ /* Allocate the vector I/O arrays */
+ if((len = H5FL_ARR_ALLOC(size_t,vector_size,0))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array");
+ if((off = H5FL_ARR_ALLOC(hsize_t,vector_size,0))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array");
+
+ /* Get the datatype size */
+ if (NULL==(dt=H5I_object(type_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an valid base datatype");
+ if((elmt_size=H5T_get_size(dt))==0)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_BADSIZE, FAIL, "datatype size invalid");
+
+ /* Allocate iterator */
+ if((iter = H5FL_ALLOC(H5S_sel_iter_t,1))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate selection iterator");
+
+ /* Initialize iterator */
+ if (H5S_select_iter_init(space, elmt_size, iter)<0)
+ HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator");
+
+ /* Get the number of elements in selection */
+ if((nelmts = 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.u.simple.rank;
+
+ /* Copy the size of the space */
+ assert(space->extent.u.simple.size);
+ assert(ndims>0);
+ HDmemcpy(space_size, space->extent.u.simple.size, ndims*sizeof(hsize_t));
+ space_size[ndims]=elmt_size;
+
+ /* Compute the maximum number of bytes required */
+ H5_ASSIGN_OVERFLOW(max_bytes,nelmts*elmt_size,hsize_t,size_t);
+
+ /* Loop, while elements left in selection */
+ while(max_bytes>0 && user_ret==0) {
+ /* Get the sequences of bytes */
+ if(H5S_select_get_seq_list(0,space,iter,elmt_size,vector_size,max_bytes,&nseq,&nbytes,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++) {
+ /* Get the current offset */
+ curr_off=off[curr_seq];
+
+ /* Get the number of bytes in sequence */
+ curr_len=len[curr_seq];
+
+ /* Loop, while bytes left in sequence */
+ while(curr_len>0 && user_ret==0) {
+ /* Compute the coordinate from the offset */
+ for(i=ndims, tmp_off=curr_off; i>=0; i--) {
+ coords[i]=tmp_off%space_size[i];
+ tmp_off/=space_size[i];
+ } /* end for */
+
+ /* 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,(hsize_t)ndims,coords,operator_data);
+
+ /* Increment offset in dataspace */
+ curr_off+=elmt_size;
+
+ /* Decrement number of bytes left in sequence */
+ curr_len-=elmt_size;
+ } /* end while */
+ } /* end for */
- case H5S_SEL_HYPERSLABS: /* Hyperslab selection defined */
- ret_value=H5S_hyper_select_iterate(buf,type_id,space,op,operator_data);
- break;
+ /* Decrement number of elements left to process */
+ assert((nbytes%elmt_size)==0);
+ max_bytes-=nbytes;
+ } /* end while */
- case H5S_SEL_ALL: /* Entire extent selected */
- ret_value=H5S_all_select_iterate(buf,type_id,space,op,operator_data);
- break;
+ /* Set return value */
+ ret_value=user_ret;
- case H5S_SEL_NONE: /* Nothing selected */
- ret_value=H5S_none_select_iterate(buf,type_id,space,op,operator_data);
- break;
+done:
+ /* Release selection iterator */
+ if(iter!=NULL) {
+ if (H5S_sel_iter_release(space, iter)<0)
+ HGOTO_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator");
+ H5FL_FREE(H5S_sel_iter_t,iter);
+ } /* end if */
- case H5S_SEL_ERROR:
- case H5S_SEL_N:
- break;
- }
+ /* Release length & offset vectors */
+ if(len!=NULL)
+ H5FL_ARR_FREE(size_t,len);
+ if(off!=NULL)
+ H5FL_ARR_FREE(hsize_t,off);
FUNC_LEAVE(ret_value);
} /* end H5S_select_iterate() */
@@ -1565,10 +1732,21 @@ H5S_select_regular(const H5S_t *space)
REVISION LOG
--------------------------------------------------------------------------*/
herr_t
-H5S_select_fill(void *_fill, size_t fill_size, const H5S_t *space, void *buf)
+H5S_select_fill(void *_fill, size_t fill_size, const H5S_t *space, void *_buf)
{
+ H5P_genplist_t *dx_plist; /* Dataset transfer property list */
+ H5S_sel_iter_t *iter=NULL; /* Selection iteration info */
+ uint8_t *buf; /* Current location in buffer */
void *fill=_fill; /* Alias for fill-value buffer */
- herr_t ret_value=FAIL; /* return value */
+ hssize_t nelmts; /* Number of elements in selection */
+ hsize_t *off=NULL; /* Array to store sequence offsets */
+ size_t *len=NULL; /* Array to store sequence lengths */
+ size_t vector_size; /* Value for vector size */
+ size_t nseq; /* Number of sequences generated */
+ size_t curr_seq; /* Current sequnce being worked on */
+ size_t nbytes; /* Number of bytes used in sequences */
+ size_t max_bytes; /* Total number of bytes in selection */
+ herr_t ret_value=SUCCEED; /* return value */
FUNC_ENTER_NOAPI(H5S_select_fill, FAIL);
@@ -1579,27 +1757,151 @@ H5S_select_fill(void *_fill, size_t fill_size, const H5S_t *space, void *buf)
/* Check if we need a temporary fill value buffer */
if(fill==NULL) {
- if (NULL==(fill = H5MM_calloc(fill_size)))
+ if (NULL==(fill = H5FL_BLK_ALLOC(type_elem,fill_size,1)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "fill value buffer allocation failed");
} /* end if */
- /* Fill the selection in the memory buffer */
+ /* Get the hyperslab vector size */
+ /* (from the default data transfer property list, for now) */
+ dx_plist = H5I_object(H5P_DATASET_XFER_DEFAULT);
+ assert(dx_plist);
+ if (H5P_get(dx_plist,H5D_XFER_HYPER_VECTOR_SIZE_NAME,&vector_size)<0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get value");
+
+ /* Allocate the vector I/O arrays */
+ if((len = H5FL_ARR_ALLOC(size_t,vector_size,0))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array");
+ if((off = H5FL_ARR_ALLOC(hsize_t,vector_size,0))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array");
+
+ /* Allocate iterator */
+ if((iter = H5FL_ALLOC(H5S_sel_iter_t,1))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate selection iterator");
+
+ /* Initialize iterator */
+ if (H5S_select_iter_init(space, fill_size, iter)<0)
+ HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator");
+
+ /* Get the number of elements in selection */
+ if((nelmts = 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_CHECK_OVERFLOW(nelmts,hssize_t,size_t);
+ max_bytes=(size_t)nelmts*fill_size;
+
+ /* Loop, while elements left in selection */
+ while(max_bytes>0) {
+ /* Get the sequences of bytes */
+ if(H5S_select_get_seq_list(0,space,iter,fill_size,vector_size,max_bytes,&nseq,&nbytes,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++) {
+ /* Get offset in memory buffer */
+ buf=(uint8_t *)_buf+off[curr_seq];
+
+ /* Fill each sequence in memory with fill value */
+ assert((len[curr_seq]%fill_size)==0);
+ H5V_array_fill(buf, fill, fill_size, (len[curr_seq]/fill_size));
+ } /* end for */
+
+ /* Decrement number of bytes left to process */
+ max_bytes-=nbytes;
+ } /* end while */
+
+done:
+ /* Release selection iterator */
+ if(iter!=NULL) {
+ if (H5S_sel_iter_release(space, iter)<0)
+ HGOTO_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator");
+ H5FL_FREE(H5S_sel_iter_t,iter);
+ } /* end if */
+
+ /* Release length & offset vectors */
+ if(len!=NULL)
+ H5FL_ARR_FREE(size_t,len);
+ if(off!=NULL)
+ H5FL_ARR_FREE(hsize_t,off);
+
+ /* Release fill value, if allocated */
+ if(_fill==NULL && fill)
+ H5FL_BLK_FREE(type_elem,fill);
+
+ FUNC_LEAVE (ret_value);
+} /* H5S_select_fill() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S_select_get_seq_list
+ PURPOSE
+ Create a list of offsets & lengths for a selection
+ USAGE
+ herr_t H5S_select_get_file_list(flags,space,iter,flag,elem_size,maxseq,maxbytes,nseq,off,len)
+ unsigned flags; IN: Flags for extra information about operation
+ H5S_t *space; IN: Dataspace containing selection to use.
+ H5S_sel_iter_t *iter; IN/OUT: Selection iterator describing last
+ position of interest in selection.
+ unsigned flag; IN: Flag to indicate whether to update the
+ iterator or not.
+ size_t elem_size; IN: Size of an element
+ size_t maxseq; IN: Maximum number of sequences to generate
+ size_t maxbytes; IN: Maximum number of bytes to include in the
+ generated sequences
+ size_t *nseq; OUT: Actual number of sequences generated
+ hsize_t *off; OUT: Array of offsets
+ hsize_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. Updating the iterator is controlled with the FLAG
+ 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
+--------------------------------------------------------------------------*/
+herr_t
+H5S_select_get_seq_list(unsigned flags, const H5S_t *space,H5S_sel_iter_t *iter,
+ size_t elem_size, size_t maxseq, size_t maxbytes, size_t *nseq, size_t *nbytes,
+ hsize_t *off, size_t *len)
+{
+ herr_t ret_value=SUCCEED; /* return value */
+
+ FUNC_ENTER_NOAPI (H5S_select_get_seq_list, FAIL);
+
+ /* Check args */
+ assert(space);
+ assert(iter);
+ assert(elem_size>0);
+ assert(maxseq>0);
+ assert(maxbytes>0);
+ assert(nseq);
+ assert(off);
+ assert(len);
+
+ /* Get the list of sequences for each type selection */
/* [Defer (mostly) to the selection routines] */
switch(space->select.type) {
- case H5S_SEL_POINTS: /* Sequence of points selected */
- ret_value=H5S_point_select_fill(fill,fill_size,space,buf);
+ case H5S_SEL_POINTS: /* Sequence of points selected */
+ ret_value=H5S_point_select_get_seq_list(flags,space,iter,elem_size,maxseq,maxbytes,nseq,nbytes,off,len);
break;
- case H5S_SEL_HYPERSLABS: /* Hyperslab selection defined */
- ret_value=H5S_hyper_select_fill(fill,fill_size,space,buf);
+ case H5S_SEL_HYPERSLABS: /* Hyperslab selection defined */
+ ret_value=H5S_hyper_select_get_seq_list(flags,space,iter,elem_size,maxseq,maxbytes,nseq,nbytes,off,len);
break;
- case H5S_SEL_ALL: /* Entire extent selected */
- ret_value=H5S_all_select_fill(fill,fill_size,space,buf);
+ case H5S_SEL_ALL: /* Entire extent selected */
+ ret_value=H5S_all_select_get_seq_list(flags,space,iter,elem_size,maxseq,maxbytes,nseq,nbytes,off,len);
break;
- case H5S_SEL_NONE: /* Nothing selected */
- ret_value=SUCCEED;
+ case H5S_SEL_NONE: /* Nothing selected */
+ *nseq=0; /* Set the number of sequences generated */
break;
case H5S_SEL_ERROR:
@@ -1608,10 +1910,891 @@ H5S_select_fill(void *_fill, size_t fill_size, const H5S_t *space, void *buf)
break;
} /* end switch */
+#ifdef LATER
done:
- if(_fill==NULL && fill)
- H5MM_xfree(fill);
+#endif /* LATER */
+ FUNC_LEAVE (ret_value);
+} /* H5S_select_get_seq_list() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5S_select_favail
+ *
+ * Purpose: Figure out the optimal number of elements to transfer to/from
+ * the file.
+ *
+ * Return: non-negative number of elements on success, zero on
+ * failure.
+ *
+ * Programmer: Quincey Koziol
+ * Wednesday, July 24, 2002
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+hsize_t
+H5S_select_favail(const H5S_t *space, const H5S_sel_iter_t *iter, hsize_t max)
+{
+ hsize_t ret_value=0; /* Return value */
+
+ FUNC_ENTER_NOAPI (H5S_select_favail, 0);
+
+ /* Check args */
+ assert(space);
+ assert(iter);
+ assert(max>0);
+
+ /* Get the number of elements to transfer for each type of selection */
+ /* [Defer (mostly) to the selection routines] */
+ switch(space->select.type) {
+ case H5S_SEL_POINTS: /* Sequence of points selected */
+ ret_value=H5S_point_favail(space,iter,max);
+ break;
+
+ case H5S_SEL_HYPERSLABS: /* Hyperslab selection defined */
+ ret_value=H5S_hyper_favail(space,iter,max);
+ break;
+
+ case H5S_SEL_ALL: /* Entire extent selected */
+ ret_value=H5S_all_favail(space,iter,max);
+ break;
+
+ case H5S_SEL_NONE: /* Nothing selected */
+ ret_value=0; /* Set the number of elements to transfer */
+ break;
+
+ case H5S_SEL_ERROR:
+ case H5S_SEL_N:
+ assert(0 && "Invalid selection type!");
+ break;
+ } /* end switch */
+
+#ifdef LATER
+done:
+#endif /* LATER */
FUNC_LEAVE (ret_value);
-} /* H5S_select_fill() */
+} /* H5S_select_favail() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5S_select_fscat
+ *
+ * Purpose: Scatters dataset elements from the type conversion buffer BUF
+ * to the file F where the data points are arranged according to
+ * the file data space FILE_SPACE and stored according to
+ * LAYOUT and EFL. Each element is ELMT_SIZE bytes.
+ * The caller is requesting that NELMTS elements are copied.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, June 20, 2002
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5S_select_fscat (H5F_t *f, const struct H5O_layout_t *layout,
+ H5P_genplist_t *dc_plist, size_t elmt_size,
+ const H5S_t *file_space, H5S_sel_iter_t *file_iter,
+ hsize_t nelmts, hid_t dxpl_id, const void *_buf)
+{
+ const uint8_t *buf=_buf; /* Alias for pointer arithmetic */
+ hsize_t *off=NULL; /* Array to store sequence offsets */
+ size_t *len=NULL; /* Array to store sequence lengths */
+ size_t vector_size; /* Value for vector size */
+ size_t maxbytes; /* Number of bytes in the buffer */
+ size_t nseq; /* Number of sequences generated */
+ size_t nbytes; /* Number of bytes used in sequences */
+ H5P_genplist_t *dx_plist; /* Dataset transfer property list */
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5S_select_fscat, FAIL);
+
+ /* Check args */
+ assert (f);
+ assert (layout);
+ assert (elmt_size>0);
+ assert (file_space);
+ assert (file_iter);
+ assert (nelmts>0);
+ assert (_buf);
+
+ /* Get the hyperslab vector size */
+ if(TRUE!=H5P_isa_class(dxpl_id,H5P_DATASET_XFER) || NULL == (dx_plist = H5I_object(dxpl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list");
+ if (H5P_get(dx_plist,H5D_XFER_HYPER_VECTOR_SIZE_NAME,&vector_size)<0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get value");
+
+ /* Allocate the vector I/O arrays */
+ if((len = H5FL_ARR_ALLOC(size_t,vector_size,0))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array");
+ if((off = H5FL_ARR_ALLOC(hsize_t,vector_size,0))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array");
+
+ /* Compute the number of bytes available in buffer */
+ H5_ASSIGN_OVERFLOW(maxbytes,nelmts*elmt_size,hsize_t,size_t);
+
+ /* Loop until all elements are written */
+ while(maxbytes>0) {
+ /* Get list of sequences for selection to write */
+ if(H5S_select_get_seq_list(H5S_GET_SEQ_LIST_SORTED,file_space,file_iter,elmt_size,vector_size,maxbytes,&nseq,&nbytes,off,len)<0)
+ HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed");
+
+ /* Write sequence list out */
+ if (H5F_seq_writev(f, dxpl_id, layout, dc_plist, file_space, elmt_size, nseq, len, off, buf)<0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error");
+
+ /* Update buffer */
+ buf += nbytes;
+
+ /* Decrement number of elements left to process */
+ assert(nbytes%elmt_size==0);
+ maxbytes -= nbytes;
+ } /* end while */
+
+done:
+ if(len!=NULL)
+ H5FL_ARR_FREE(size_t,len);
+ if(off!=NULL)
+ H5FL_ARR_FREE(hsize_t,off);
+ FUNC_LEAVE (ret_value);
+} /* H5S_select_fscat() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5S_select_fgath
+ *
+ * Purpose: Gathers data points from file F and accumulates them in the
+ * type conversion buffer BUF. The LAYOUT argument describes
+ * how the data is stored on disk and EFL describes how the data
+ * is organized in external files. ELMT_SIZE is the size in
+ * bytes of a datum which this function treats as opaque.
+ * FILE_SPACE describes the data space of the dataset on disk
+ * and the elements that have been selected for reading (via
+ * hyperslab, etc). This function will copy at most NELMTS
+ * elements.
+ *
+ * Return: Success: Number of elements copied.
+ * Failure: 0
+ *
+ * Programmer: Quincey Koziol
+ * Monday, June 24, 2002
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+hsize_t
+H5S_select_fgath (H5F_t *f, const struct H5O_layout_t *layout,
+ H5P_genplist_t *dc_plist,
+ size_t elmt_size, const H5S_t *file_space,
+ H5S_sel_iter_t *file_iter, hsize_t nelmts, hid_t dxpl_id,
+ void *_buf/*out*/)
+{
+ uint8_t *buf=_buf; /* Alias for pointer arithmetic */
+ hsize_t *off=NULL; /* Array to store sequence offsets */
+ size_t *len=NULL; /* Array to store sequence lengths */
+ size_t vector_size; /* Value for vector size */
+ size_t maxbytes; /* Number of bytes in the buffer */
+ size_t nseq; /* Number of sequences generated */
+ size_t nbytes; /* Number of bytes used in sequences */
+ H5P_genplist_t *dx_plist; /* Dataset transfer property list */
+ hsize_t ret_value=nelmts; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5S_select_fgath, 0);
+
+ /* Check args */
+ assert (f);
+ assert (layout);
+ assert (elmt_size>0);
+ assert (file_space);
+ assert (file_iter);
+ assert (nelmts>0);
+ assert (_buf);
+
+ /* Get the hyperslab vector size */
+ if(TRUE!=H5P_isa_class(dxpl_id,H5P_DATASET_XFER) || NULL == (dx_plist = H5I_object(dxpl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a file access property list");
+ if (H5P_get(dx_plist,H5D_XFER_HYPER_VECTOR_SIZE_NAME,&vector_size)<0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, 0, "unable to get value");
+
+ /* Allocate the vector I/O arrays */
+ if((len = H5FL_ARR_ALLOC(size_t,vector_size,0))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate I/O length vector array");
+ if((off = H5FL_ARR_ALLOC(hsize_t,vector_size,0))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate I/O offset vector array");
+
+ /* Compute the number of bytes available in buffer */
+ H5_ASSIGN_OVERFLOW(maxbytes,nelmts*elmt_size,hsize_t,size_t);
+
+ /* Loop until all elements are written */
+ while(maxbytes>0) {
+ /* Get list of sequences for selection to write */
+ if(H5S_select_get_seq_list(H5S_GET_SEQ_LIST_SORTED,file_space,file_iter,elmt_size,vector_size,maxbytes,&nseq,&nbytes,off,len)<0)
+ HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed");
+
+ /* Read sequence list in */
+ if (H5F_seq_readv(f, dxpl_id, layout, dc_plist, file_space, elmt_size, nseq, len, off, buf)<0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, 0, "read error");
+
+ /* Update buffer */
+ buf += nbytes;
+
+ /* Decrement number of elements left to process */
+ assert(nbytes%elmt_size==0);
+ maxbytes -= nbytes;
+ } /* end while */
+
+done:
+ if(len!=NULL)
+ H5FL_ARR_FREE(size_t,len);
+ if(off!=NULL)
+ H5FL_ARR_FREE(hsize_t,off);
+ FUNC_LEAVE (ret_value);
+} /* H5S_select_fgath() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5S_select_mscat
+ *
+ * Purpose: Scatters NELMTS data points from the scatter buffer
+ * TSCAT_BUF to the application buffer BUF. Each element is
+ * ELMT_SIZE bytes and they are organized in application memory
+ * according to SPACE.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Monday, July 8, 2002
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5S_select_mscat (const void *_tscat_buf, size_t elmt_size, const H5S_t *space,
+ H5S_sel_iter_t *iter, hsize_t nelmts, hid_t dxpl_id, void *_buf/*out*/)
+{
+ H5P_genplist_t *dx_plist; /* Dataset transfer property list */
+ uint8_t *buf=(uint8_t *)_buf; /* Get local copies for address arithmetic */
+ const uint8_t *tscat_buf=(const uint8_t *)_tscat_buf;
+ hsize_t *off=NULL; /* Array to store sequence offsets */
+ size_t vector_size; /* Value for vector size */
+ size_t *len=NULL; /* Array to store sequence lengths */
+ size_t curr_len; /* Length of bytes left to process in sequence */
+ size_t maxbytes; /* Number of bytes in the buffer */
+ size_t nseq; /* Number of sequences generated */
+ size_t curr_seq; /* Current sequence being processed */
+ size_t nbytes; /* Number of bytes used in sequences */
+ herr_t ret_value=SUCCEED; /* Number of elements scattered */
+
+ FUNC_ENTER_NOAPI(H5S_select_mscat, FAIL);
+
+ /* Check args */
+ assert (tscat_buf);
+ assert (elmt_size>0);
+ assert (space);
+ assert (iter);
+ assert (nelmts>0);
+ assert (buf);
+
+ /* Get the hyperslab vector size */
+ if(TRUE!=H5P_isa_class(dxpl_id,H5P_DATASET_XFER) || NULL == (dx_plist = H5I_object(dxpl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list");
+ if (H5P_get(dx_plist,H5D_XFER_HYPER_VECTOR_SIZE_NAME,&vector_size)<0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get value");
+
+ /* Allocate the vector I/O arrays */
+ if((len = H5FL_ARR_ALLOC(size_t,vector_size,0))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array");
+ if((off = H5FL_ARR_ALLOC(hsize_t,vector_size,0))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array");
+
+ /* Compute the number of bytes available in buffer */
+ H5_ASSIGN_OVERFLOW(maxbytes,nelmts*elmt_size,hsize_t,size_t);
+
+ /* Loop until all elements are written */
+ while(maxbytes>0) {
+ /* Get list of sequences for selection to write */
+ if(H5S_select_get_seq_list(0,space,iter,elmt_size,vector_size,maxbytes,&nseq,&nbytes,off,len)<0)
+ HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed");
+
+ /* Loop, while sequences left to process */
+ for(curr_seq=0; curr_seq<nseq; curr_seq++) {
+ /* Get the number of bytes in sequence */
+ curr_len=len[curr_seq];
+
+ HDmemcpy(buf+off[curr_seq],tscat_buf,curr_len);
+
+ /* Advance offset in destination buffer */
+ tscat_buf+=curr_len;
+ } /* end for */
+
+ /* Decrement number of elements left to process */
+ assert(nbytes%elmt_size==0);
+ maxbytes -= nbytes;
+ } /* end while */
+
+done:
+ if(len!=NULL)
+ H5FL_ARR_FREE(size_t,len);
+ if(off!=NULL)
+ H5FL_ARR_FREE(hsize_t,off);
+ FUNC_LEAVE(ret_value);
+} /* H5S_select_mscat() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5S_select_mgath
+ *
+ * Purpose: Gathers dataset elements from application memory BUF and
+ * copies them into the gather buffer TGATH_BUF.
+ * Each element is ELMT_SIZE bytes and arranged in application
+ * memory according to SPACE.
+ * The caller is requesting that at most NELMTS be gathered.
+ *
+ * Return: Success: Number of elements copied.
+ * Failure: 0
+ *
+ * Programmer: Quincey Koziol
+ * Monday, June 24, 2002
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+hsize_t
+H5S_select_mgath (const void *_buf, size_t elmt_size, const H5S_t *space,
+ H5S_sel_iter_t *iter, hsize_t nelmts, hid_t dxpl_id, void *_tgath_buf/*out*/)
+{
+ H5P_genplist_t *dx_plist; /* Dataset transfer property list */
+ const uint8_t *buf=(const uint8_t *)_buf; /* Get local copies for address arithmetic */
+ uint8_t *tgath_buf=(uint8_t *)_tgath_buf;
+ hsize_t *off=NULL; /* Array to store sequence offsets */
+ size_t vector_size; /* Value for vector size */
+ size_t *len=NULL; /* Array to store sequence lengths */
+ size_t curr_len; /* Length of bytes left to process in sequence */
+ size_t maxbytes; /* Number of bytes in the buffer */
+ size_t nseq; /* Number of sequences generated */
+ size_t curr_seq; /* Current sequence being processed */
+ size_t nbytes; /* Number of bytes used in sequences */
+ hsize_t ret_value=nelmts; /* Number of elements gathered */
+
+ FUNC_ENTER_NOAPI(H5S_select_mgath, 0);
+
+ /* Check args */
+ assert (buf);
+ assert (elmt_size>0);
+ assert (space);
+ assert (iter);
+ assert (nelmts>0);
+ assert (tgath_buf);
+
+ /* Get the hyperslab vector size */
+ if(TRUE!=H5P_isa_class(dxpl_id,H5P_DATASET_XFER) || NULL == (dx_plist = H5I_object(dxpl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a dataset transfer property list");
+ if (H5P_get(dx_plist,H5D_XFER_HYPER_VECTOR_SIZE_NAME,&vector_size)<0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, 0, "unable to get value");
+
+ /* Allocate the vector I/O arrays */
+ if((len = H5FL_ARR_ALLOC(size_t,vector_size,0))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate I/O length vector array");
+ if((off = H5FL_ARR_ALLOC(hsize_t,vector_size,0))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate I/O offset vector array");
+
+ /* Compute the number of bytes available in buffer */
+ H5_ASSIGN_OVERFLOW(maxbytes,nelmts*elmt_size,hsize_t,size_t);
+
+ /* Loop until all elements are written */
+ while(maxbytes>0) {
+ /* Get list of sequences for selection to write */
+ if(H5S_select_get_seq_list(0,space,iter,elmt_size,vector_size,maxbytes,&nseq,&nbytes,off,len)<0)
+ HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed");
+
+ /* Loop, while sequences left to process */
+ for(curr_seq=0; curr_seq<nseq; curr_seq++) {
+ /* Get the number of bytes in sequence */
+ curr_len=len[curr_seq];
+
+ HDmemcpy(tgath_buf,buf+off[curr_seq],curr_len);
+
+ /* Advance offset in gather buffer */
+ tgath_buf+=curr_len;
+ } /* end for */
+
+ /* Decrement number of elements left to process */
+ assert(nbytes%elmt_size==0);
+ maxbytes -= nbytes;
+ } /* end while */
+
+done:
+ if(len!=NULL)
+ H5FL_ARR_FREE(size_t,len);
+ if(off!=NULL)
+ H5FL_ARR_FREE(hsize_t,off);
+ FUNC_LEAVE(ret_value);
+} /* H5S_select_mgath() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5S_select_read
+ *
+ * Purpose: Reads directly from file into application memory.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, July 23, 2002
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5S_select_read(H5F_t *f, const H5O_layout_t *layout, H5P_genplist_t *dc_plist,
+ size_t elmt_size, const H5S_t *file_space,
+ const H5S_t *mem_space, hid_t dxpl_id, void *_buf/*out*/)
+{
+ H5P_genplist_t *dx_plist; /* Dataset transfer property list */
+ H5S_sel_iter_t *mem_iter=NULL; /* Memory selection iteration info */
+ H5S_sel_iter_t *file_iter=NULL; /* File selection iteration info */
+ uint8_t *buf; /* Local buffer pointer, for address arithmetic */
+ hsize_t *mem_off=NULL; /* Array to store sequence offsets in memory */
+ hsize_t *file_off=NULL; /* Array to store sequence offsets in the file */
+ size_t vector_size; /* Value for vector size */
+ size_t *mem_len=NULL; /* Array to store sequence lengths in memory */
+ size_t *file_len=NULL; /* Array to store sequence lengths in the file */
+ size_t maxbytes; /* Number of bytes in selection */
+ size_t mem_nseq; /* Number of sequences generated in the file */
+ size_t file_nseq; /* Number of sequences generated in memory */
+ size_t mem_nbytes; /* Number of bytes used in memory sequences */
+ size_t file_nbytes; /* Number of bytes used in file sequences */
+ size_t curr_mem_seq; /* Current memory sequence to operate on */
+ size_t curr_file_seq; /* Current file sequence to operate on */
+ size_t tmp_file_len; /* Temporary number of bytes in file sequence */
+ unsigned partial_file; /* Whether a partial file sequence was accessed */
+ size_t orig_file_len; /* Original file sequence length for partial file access */
+ size_t orig_file_seq; /* Original file sequence to operate on */
+ size_t tot_file_seq; /* Number of file sequences to access */
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5S_select_read, FAIL);
+
+ /* Get the hyperslab vector size */
+ if(TRUE!=H5P_isa_class(dxpl_id,H5P_DATASET_XFER) || NULL == (dx_plist = H5I_object(dxpl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list");
+ if (H5P_get(dx_plist,H5D_XFER_HYPER_VECTOR_SIZE_NAME,&vector_size)<0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get value");
+
+ /* Allocate the vector I/O arrays */
+ if((mem_len = H5FL_ARR_ALLOC(size_t,vector_size,0))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array");
+ if((mem_off = H5FL_ARR_ALLOC(hsize_t,vector_size,0))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array");
+ if((file_len = H5FL_ARR_ALLOC(size_t,vector_size,0))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array");
+ if((file_off = H5FL_ARR_ALLOC(hsize_t,vector_size,0))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array");
+
+ /* Allocate file iterator */
+ if((file_iter = H5FL_ALLOC(H5S_sel_iter_t,1))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate selection iterator");
+
+ /* Initialize file iterator */
+ if (H5S_select_iter_init(file_space, elmt_size, file_iter)<0)
+ HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator");
+
+ /* Allocate memory iterator */
+ if((mem_iter = H5FL_ALLOC(H5S_sel_iter_t,1))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate selection iterator");
+
+ /* Initialize memory iterator */
+ if (H5S_select_iter_init(mem_space, elmt_size, mem_iter)<0)
+ HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator");
+
+ /* Get number of bytes in selection */
+ maxbytes=H5S_get_select_npoints(file_space)*elmt_size;
+
+ /* Initialize sequence counts */
+ curr_mem_seq=curr_file_seq=0;
+ mem_nseq=file_nseq=0;
+
+ /* Loop, until all bytes are processed */
+ while(maxbytes>0) {
+ /* Check if more file sequences are needed */
+ if(curr_file_seq>=file_nseq) {
+ /* Get sequences for file selection */
+ if(H5S_select_get_seq_list(H5S_GET_SEQ_LIST_SORTED,file_space,file_iter,elmt_size,vector_size,maxbytes,&file_nseq,&file_nbytes,file_off,file_len)<0)
+ HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed");
+
+ /* Start at the beginning of the sequences again */
+ curr_file_seq=0;
+ } /* end if */
+
+ /* Check if more memory sequences are needed */
+ if(curr_mem_seq>=mem_nseq) {
+ /* Get sequences for memory selection */
+ if(H5S_select_get_seq_list(0,mem_space,mem_iter,elmt_size,vector_size,maxbytes,&mem_nseq,&mem_nbytes,mem_off,mem_len)<0)
+ HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed");
+
+ /* Start at the beginning of the sequences again */
+ curr_mem_seq=0;
+
+ /* Set the buffer pointer using the first sequence */
+ H5_CHECK_OVERFLOW(mem_off[0],hsize_t,size_t);
+ buf=(uint8_t *)_buf+(size_t)mem_off[0];
+ } /* end if */
+
+ /* Check if current file sequence will fit into current memory sequence */
+ if(mem_len[curr_mem_seq]>=file_len[curr_file_seq]) {
+ /* Save the current number file sequence */
+ orig_file_seq=curr_file_seq;
+
+ /* Determine how many file sequences will fit into current memory sequence */
+ tmp_file_len=0;
+ tot_file_seq=0;
+ while((tmp_file_len+file_len[curr_file_seq])<=mem_len[curr_mem_seq] && curr_file_seq<file_nseq) {
+ tmp_file_len+=file_len[curr_file_seq];
+ curr_file_seq++;
+ tot_file_seq++;
+ } /* end while */
+
+ /* Check for partial file sequence */
+ if(tmp_file_len<mem_len[curr_mem_seq] && curr_file_seq<file_nseq) {
+ /* Get the original file sequence length */
+ orig_file_len=file_len[curr_file_seq];
+
+ /* Make the last file sequence a partial access */
+ file_len[curr_file_seq]=mem_len[curr_mem_seq]-tmp_file_len;
+
+ /* Increase the number of bytes to access */
+ tmp_file_len=mem_len[curr_mem_seq];
+
+ /* Indicate that there is an extra sequence to include in the file access */
+ tot_file_seq++;
+
+ /* Indicate a partial file sequence */
+ partial_file=1;
+ } /* end if */
+ else
+ partial_file=0;
+
+ /* Read file sequences into current memory sequence */
+ if (H5F_seq_readv(f, dxpl_id, layout, dc_plist, file_space, elmt_size, tot_file_seq, &file_len[orig_file_seq], &file_off[orig_file_seq], buf)<0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error");
+
+ /* Update last file sequence, if it was partially accessed */
+ if(partial_file) {
+ file_off[curr_file_seq]+=orig_file_len-file_len[curr_file_seq];
+ file_len[curr_file_seq]=orig_file_len-file_len[curr_file_seq];
+ } /* end if */
+
+ /* Check if the current memory sequence was only partially accessed */
+ if(tmp_file_len<mem_len[curr_mem_seq]) {
+ /* Adjust current memory sequence */
+ mem_off[curr_mem_seq]+=tmp_file_len;
+ mem_len[curr_mem_seq]-=tmp_file_len;
+
+ /* Adjust memory buffer pointer */
+ buf+=tmp_file_len;
+ } /* end if */
+ else {
+ /* Must have used entire memory sequence, advance to next one */
+ curr_mem_seq++;
+
+ /* Check if it is valid to adjust buffer pointer */
+ if(curr_mem_seq<mem_nseq) {
+ H5_CHECK_OVERFLOW(mem_off[curr_mem_seq],hsize_t,size_t);
+ buf=(uint8_t *)_buf+(size_t)mem_off[curr_mem_seq];
+ } /* end if */
+ } /* end else */
+
+ /* Decrement number of bytes left to process */
+ maxbytes-=tmp_file_len;
+ } /* end if */
+ else {
+ /* Save number of bytes to access */
+ tmp_file_len=mem_len[curr_mem_seq];
+
+ /* Read part of current file sequence into current memory sequence */
+ if (H5F_seq_read(f, dxpl_id, layout, dc_plist, file_space, elmt_size, tmp_file_len, file_off[curr_file_seq], buf)<0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error");
+
+ /* Update current file sequence information */
+ file_off[curr_file_seq]+=tmp_file_len;
+ file_len[curr_file_seq]-=tmp_file_len;
+
+ /* Increment memory sequence */
+ curr_mem_seq++;
+
+ /* Check if it is valid to adjust buffer pointer */
+ if(curr_mem_seq<mem_nseq) {
+ H5_CHECK_OVERFLOW(mem_off[curr_mem_seq],hsize_t,size_t);
+ buf=(uint8_t *)_buf+(size_t)mem_off[curr_mem_seq];
+ } /* end if */
+
+ /* Decrement number of bytes left to process */
+ maxbytes-=tmp_file_len;
+ } /* end else */
+ } /* end while */
+
+done:
+ /* Release file selection iterator */
+ if(file_iter!=NULL) {
+ if (H5S_sel_iter_release(file_space, file_iter)<0)
+ HGOTO_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator");
+ H5FL_FREE(H5S_sel_iter_t,file_iter);
+ } /* end if */
+
+ /* Release memory selection iterator */
+ if(mem_iter!=NULL) {
+ if (H5S_sel_iter_release(mem_space, mem_iter)<0)
+ HGOTO_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator");
+ H5FL_FREE(H5S_sel_iter_t,mem_iter);
+ } /* end if */
+
+ /* Free vector arrays */
+ if(file_len!=NULL)
+ H5FL_ARR_FREE(size_t,file_len);
+ if(file_off!=NULL)
+ H5FL_ARR_FREE(hsize_t,file_off);
+ if(mem_len!=NULL)
+ H5FL_ARR_FREE(size_t,mem_len);
+ if(mem_off!=NULL)
+ H5FL_ARR_FREE(hsize_t,mem_off);
+ FUNC_LEAVE(ret_value);
+} /* end H5S_select_read() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5S_select_write
+ *
+ * Purpose: Writes directly from application memory into a file
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, July 23, 2002
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5S_select_write(H5F_t *f, const H5O_layout_t *layout, H5P_genplist_t *dc_plist,
+ size_t elmt_size, const H5S_t *file_space,
+ const H5S_t *mem_space, hid_t dxpl_id, const void *_buf/*out*/)
+{
+ H5P_genplist_t *dx_plist; /* Dataset transfer property list */
+ H5S_sel_iter_t *mem_iter=NULL; /* Memory selection iteration info */
+ H5S_sel_iter_t *file_iter=NULL; /* File selection iteration info */
+ const uint8_t *buf; /* Local buffer pointer, for address arithmetic */
+ hsize_t *mem_off=NULL; /* Array to store sequence offsets in memory */
+ hsize_t *file_off=NULL; /* Array to store sequence offsets in the file */
+ size_t vector_size; /* Value for vector size */
+ size_t *mem_len=NULL; /* Array to store sequence lengths in memory */
+ size_t *file_len=NULL; /* Array to store sequence lengths in the file */
+ size_t maxbytes; /* Number of bytes in selection */
+ size_t mem_nseq; /* Number of sequences generated in the file */
+ size_t file_nseq; /* Number of sequences generated in memory */
+ size_t mem_nbytes; /* Number of bytes used in memory sequences */
+ size_t file_nbytes; /* Number of bytes used in file sequences */
+ size_t curr_mem_seq; /* Current memory sequence to operate on */
+ size_t curr_file_seq; /* Current file sequence to operate on */
+ size_t tmp_file_len; /* Temporary number of bytes in file sequence */
+ unsigned partial_file; /* Whether a partial file sequence was accessed */
+ size_t orig_file_len; /* Original file sequence length for partial file access */
+ size_t orig_file_seq; /* Original file sequence to operate on */
+ size_t tot_file_seq; /* Number of file sequences to access */
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5S_select_write, FAIL);
+
+ /* Get the hyperslab vector size */
+ if(TRUE!=H5P_isa_class(dxpl_id,H5P_DATASET_XFER) || NULL == (dx_plist = H5I_object(dxpl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset transfer property list");
+ if (H5P_get(dx_plist,H5D_XFER_HYPER_VECTOR_SIZE_NAME,&vector_size)<0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get value");
+
+ /* Allocate the vector I/O arrays */
+ if((mem_len = H5FL_ARR_ALLOC(size_t,vector_size,0))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array");
+ if((mem_off = H5FL_ARR_ALLOC(hsize_t,vector_size,0))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array");
+ if((file_len = H5FL_ARR_ALLOC(size_t,vector_size,0))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array");
+ if((file_off = H5FL_ARR_ALLOC(hsize_t,vector_size,0))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array");
+
+ /* Allocate file iterator */
+ if((file_iter = H5FL_ALLOC(H5S_sel_iter_t,1))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate selection iterator");
+
+ /* Initialize file iterator */
+ if (H5S_select_iter_init(file_space, elmt_size, file_iter)<0)
+ HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator");
+
+ /* Allocate memory iterator */
+ if((mem_iter = H5FL_ALLOC(H5S_sel_iter_t,1))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate selection iterator");
+
+ /* Initialize memory iterator */
+ if (H5S_select_iter_init(mem_space, elmt_size, mem_iter)<0)
+ HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator");
+
+ /* Get number of bytes in selection */
+ maxbytes=H5S_get_select_npoints(file_space)*elmt_size;
+
+ /* Initialize sequence counts */
+ curr_mem_seq=curr_file_seq=0;
+ mem_nseq=file_nseq=0;
+
+ /* Loop, until all bytes are processed */
+ while(maxbytes>0) {
+ /* Check if more file sequences are needed */
+ if(curr_file_seq>=file_nseq) {
+ /* Get sequences for file selection */
+ if(H5S_select_get_seq_list(H5S_GET_SEQ_LIST_SORTED,file_space,file_iter,elmt_size,vector_size,maxbytes,&file_nseq,&file_nbytes,file_off,file_len)<0)
+ HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed");
+
+ /* Start at the beginning of the sequences again */
+ curr_file_seq=0;
+ } /* end if */
+
+ /* Check if more memory sequences are needed */
+ if(curr_mem_seq>=mem_nseq) {
+ /* Get sequences for memory selection */
+ if(H5S_select_get_seq_list(0,mem_space,mem_iter,elmt_size,vector_size,maxbytes,&mem_nseq,&mem_nbytes,mem_off,mem_len)<0)
+ HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed");
+
+ /* Start at the beginning of the sequences again */
+ curr_mem_seq=0;
+
+ /* Set the buffer pointer using the first sequence */
+ H5_CHECK_OVERFLOW(mem_off[0],hsize_t,size_t);
+ buf=(const uint8_t *)_buf+(size_t)mem_off[0];
+ } /* end if */
+
+ /* Check if current file sequence will fit into current memory sequence */
+ if(mem_len[curr_mem_seq]>=file_len[curr_file_seq]) {
+ /* Save the current number file sequence */
+ orig_file_seq=curr_file_seq;
+
+ /* Determine how many file sequences will fit into current memory sequence */
+ tmp_file_len=0;
+ tot_file_seq=0;
+ while((tmp_file_len+file_len[curr_file_seq])<=mem_len[curr_mem_seq] && curr_file_seq<file_nseq) {
+ tmp_file_len+=file_len[curr_file_seq];
+ curr_file_seq++;
+ tot_file_seq++;
+ } /* end while */
+
+ /* Check for partial file sequence */
+ if(tmp_file_len<mem_len[curr_mem_seq] && curr_file_seq<file_nseq) {
+ /* Get the original file sequence length */
+ orig_file_len=file_len[curr_file_seq];
+
+ /* Make the last file sequence a partial access */
+ file_len[curr_file_seq]=mem_len[curr_mem_seq]-tmp_file_len;
+
+ /* Increase the number of bytes to access */
+ tmp_file_len=mem_len[curr_mem_seq];
+
+ /* Indicate that there is an extra sequence to include in the file access */
+ tot_file_seq++;
+
+ /* Indicate a partial file sequence */
+ partial_file=1;
+ } /* end if */
+ else
+ partial_file=0;
+
+ /* Write current memory sequence into file sequences */
+ if (H5F_seq_writev(f, dxpl_id, layout, dc_plist, file_space, elmt_size, tot_file_seq, &file_len[orig_file_seq], &file_off[orig_file_seq], buf)<0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error");
+
+ /* Update last file sequence, if it was partially accessed */
+ if(partial_file) {
+ file_off[curr_file_seq]+=orig_file_len-file_len[curr_file_seq];
+ file_len[curr_file_seq]=orig_file_len-file_len[curr_file_seq];
+ } /* end if */
+
+ /* Check if the current memory sequence was only partially accessed */
+ if(tmp_file_len<mem_len[curr_mem_seq]) {
+ /* Adjust current memory sequence */
+ mem_off[curr_mem_seq]+=tmp_file_len;
+ mem_len[curr_mem_seq]-=tmp_file_len;
+
+ /* Adjust memory buffer pointer */
+ buf+=tmp_file_len;
+ } /* end if */
+ else {
+ /* Must have used entire memory sequence, advance to next one */
+ curr_mem_seq++;
+
+ /* Check if it is valid to adjust buffer pointer */
+ if(curr_mem_seq<mem_nseq) {
+ H5_CHECK_OVERFLOW(mem_off[curr_mem_seq],hsize_t,size_t);
+ buf=(const uint8_t *)_buf+(size_t)mem_off[curr_mem_seq];
+ } /* end if */
+ } /* end else */
+
+ /* Decrement number of bytes left to process */
+ maxbytes-=tmp_file_len;
+ } /* end if */
+ else {
+ /* Save number of bytes to access */
+ tmp_file_len=mem_len[curr_mem_seq];
+
+ /* Write part of current memory sequence to current file sequence */
+ if (H5F_seq_write(f, dxpl_id, layout, dc_plist, file_space, elmt_size, tmp_file_len, file_off[curr_file_seq], buf)<0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error");
+
+ /* Update current file sequence information */
+ file_off[curr_file_seq]+=tmp_file_len;
+ file_len[curr_file_seq]-=tmp_file_len;
+
+ /* Increment memory sequence */
+ curr_mem_seq++;
+
+ /* Check if it is valid to adjust buffer pointer */
+ if(curr_mem_seq<mem_nseq) {
+ H5_CHECK_OVERFLOW(mem_off[curr_mem_seq],hsize_t,size_t);
+ buf=(const uint8_t *)_buf+(size_t)mem_off[curr_mem_seq];
+ } /* end if */
+
+ /* Decrement number of bytes left to process */
+ maxbytes-=tmp_file_len;
+ } /* end else */
+ } /* end while */
+
+done:
+ /* Release file selection iterator */
+ if(file_iter!=NULL) {
+ if (H5S_sel_iter_release(file_space, file_iter)<0)
+ HGOTO_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator");
+ H5FL_FREE(H5S_sel_iter_t,file_iter);
+ } /* end if */
+
+ /* Release memory selection iterator */
+ if(mem_iter!=NULL) {
+ if (H5S_sel_iter_release(mem_space, mem_iter)<0)
+ HGOTO_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator");
+ H5FL_FREE(H5S_sel_iter_t,mem_iter);
+ } /* end if */
+
+ /* Free vector arrays */
+ if(file_len!=NULL)
+ H5FL_ARR_FREE(size_t,file_len);
+ if(file_off!=NULL)
+ H5FL_ARR_FREE(hsize_t,file_off);
+ if(mem_len!=NULL)
+ H5FL_ARR_FREE(size_t,mem_len);
+ if(mem_off!=NULL)
+ H5FL_ARR_FREE(hsize_t,mem_off);
+ FUNC_LEAVE(ret_value);
+} /* end H5S_select_write() */