summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2007-11-29 18:44:07 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2007-11-29 18:44:07 (GMT)
commit765f0159ffa71c77754583d97a2b9e494d381ebe (patch)
treeb52931bca7b603c4e73df53dca322afeefcedcfd /src
parent44fa94541b3de90b358f4921725bab2cbe953c4d (diff)
downloadhdf5-765f0159ffa71c77754583d97a2b9e494d381ebe.zip
hdf5-765f0159ffa71c77754583d97a2b9e494d381ebe.tar.gz
hdf5-765f0159ffa71c77754583d97a2b9e494d381ebe.tar.bz2
[svn-r14307] Description:
- Extracted common code from H5D_select_read/H5D_select_write into single routine (H5D_select_io) and made H5D_select_read/H5D_select_write "gateway" routines, passing I/O buffer to operate on in "op" struct. - Create optimized pathway in H5D_select_io for I/O operations on single elements. - Make "get linear offset of first element" callback for each type of selection (used in "optimized pathway", above) Tested on: FreeBSD/32 6.2 (duty) in debug mode FreeBSD/64 6.2 (liberty) w/C++ & FORTRAN, in debug mode Linux/32 2.6 (kagiso) w/PGI compilers, w/C++ & FORTRAN, w/threadsafe, in debug mode Linux/64-amd64 2.6 (smirom) w/default API=1.6.x, w/C++ & FORTRAN, in production mode Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN, in production mode Solaris/32 2.10 (linew) w/deprecated symbols disabled, w/C++ & FORTRAN, w/szip filter, in production mode Mac OS X/32 10.4.10 (amazon) in debug mode Linux/64-ia64 2.4 (tg-login3) w/parallel, w/FORTRAN, in production mode
Diffstat (limited to 'src')
-rw-r--r--src/H5Dselect.c416
-rw-r--r--src/H5Sall.c61
-rw-r--r--src/H5Shyper.c119
-rw-r--r--src/H5Snone.c41
-rw-r--r--src/H5Spkg.h5
-rw-r--r--src/H5Spoint.c110
-rw-r--r--src/H5Sprivate.h3
-rw-r--r--src/H5Sselect.c40
8 files changed, 540 insertions, 255 deletions
diff --git a/src/H5Dselect.c b/src/H5Dselect.c
index 105b4e5..f08672f 100644
--- a/src/H5Dselect.c
+++ b/src/H5Dselect.c
@@ -46,6 +46,18 @@
/* Local Prototypes */
/********************/
+/* Struct for holding the vectorized I/O operation buffers "loosely" */
+typedef struct {
+ enum {
+ H5S_SELECT_READ, /* Read selection */
+ H5S_SELECT_WRITE /* Write selection */
+ } op_type;
+ union {
+ void *rbuf; /* Buffer for read */
+ const void *wbuf; /* Buffer to write */
+ } u;
+} H5D_select_buf_t;
+
/*********************/
/* Package Variables */
/*********************/
@@ -419,153 +431,199 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5D_select_read
+ * Function: H5D_select_io
*
- * Purpose: Reads directly from file into application memory.
+ * Purpose: Perform I/O directly from application memory and a file
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
- * Tuesday, July 23, 2002
+ * Tuesday, November 27, 2007
*
*-------------------------------------------------------------------------
*/
-herr_t
-H5D_select_read(H5D_io_info_t *io_info,
+static herr_t
+H5D_select_io(H5D_io_info_t *io_info,
size_t nelmts, size_t elmt_size,
const H5S_t *file_space, const H5S_t *mem_space,
haddr_t addr, void *chunk/*in*/,
- void *buf/*out*/)
+ const H5D_select_buf_t *io_buf)
{
H5S_sel_iter_t mem_iter; /* Memory selection iteration info */
- hbool_t mem_iter_init=0; /* Memory selection iteration info has been initialized */
+ hbool_t mem_iter_init = 0; /* Memory selection iteration info has been initialized */
H5S_sel_iter_t file_iter; /* File selection iteration info */
- hbool_t file_iter_init=0; /* File selection iteration info has been initialized */
+ hbool_t file_iter_init = 0; /* File selection iteration info has been initialized */
hsize_t _mem_off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets in memory */
- hsize_t *mem_off=NULL; /* Pointer to sequence offsets in memory */
+ hsize_t *mem_off = NULL; /* Pointer to sequence offsets in memory */
hsize_t _file_off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets in the file */
- hsize_t *file_off=NULL; /* Pointer to sequence offsets in the file */
+ hsize_t *file_off = NULL; /* Pointer to sequence offsets in the file */
size_t _mem_len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths in memory */
- size_t *mem_len=NULL; /* Pointer to sequence lengths in memory */
+ size_t *mem_len = NULL; /* Pointer to sequence lengths in memory */
size_t _file_len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths in the file */
- size_t *file_len=NULL; /* Pointer to sequence lengths in the file */
- size_t mem_nseq; /* Number of sequences generated in the file */
- size_t file_nseq; /* Number of sequences generated in memory */
- size_t mem_nelem; /* Number of elements used in memory sequences */
- size_t file_nelem; /* Number of elements used in file sequences */
+ size_t *file_len = NULL; /* Pointer to sequence lengths in the file */
size_t curr_mem_seq; /* Current memory sequence to operate on */
size_t curr_file_seq; /* Current file sequence to operate on */
+ size_t mem_nseq; /* Number of sequences generated in the file */
+ size_t file_nseq; /* Number of sequences generated in memory */
ssize_t tmp_file_len; /* Temporary number of bytes in file sequence */
- herr_t ret_value=SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5D_select_read, FAIL);
+ FUNC_ENTER_NOAPI(H5D_select_io, FAIL)
/* Check args */
- assert(io_info);
- assert(io_info->dset);
- assert(io_info->dxpl_cache);
- assert(io_info->store);
- assert(buf);
- assert(TRUE==H5P_isa_class(io_info->dxpl_id,H5P_DATASET_XFER));
-
- /* Initialize file iterator */
- if (H5S_select_iter_init(&file_iter, file_space, elmt_size)<0)
- HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator");
- file_iter_init=1; /* File selection iteration info has been initialized */
-
- /* Initialize memory iterator */
- if (H5S_select_iter_init(&mem_iter, mem_space, elmt_size)<0)
- HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator");
- mem_iter_init=1; /* Memory selection iteration info has been initialized */
+ HDassert(io_info);
+ HDassert(io_info->dset);
+ HDassert(io_info->store);
+ HDassert(TRUE == H5P_isa_class(io_info->dxpl_id, H5P_DATASET_XFER));
+ HDassert(io_buf->u.rbuf);
/* Allocate the vector I/O arrays */
if(io_info->dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if((mem_len = H5FL_SEQ_MALLOC(size_t,io_info->dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array");
- if((mem_off = H5FL_SEQ_MALLOC(hsize_t,io_info->dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array");
- if((file_len = H5FL_SEQ_MALLOC(size_t,io_info->dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array");
- if((file_off = H5FL_SEQ_MALLOC(hsize_t,io_info->dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array");
+ if(NULL == (mem_len = H5FL_SEQ_MALLOC(size_t,io_info->dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array")
+ if(NULL == (mem_off = H5FL_SEQ_MALLOC(hsize_t,io_info->dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array")
+ if(NULL == (file_len = H5FL_SEQ_MALLOC(size_t,io_info->dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array")
+ if(NULL == (file_off = H5FL_SEQ_MALLOC(hsize_t,io_info->dxpl_cache->vec_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array")
} /* end if */
else {
- mem_len=_mem_len;
- mem_off=_mem_off;
- file_len=_file_len;
- file_off=_file_off;
+ mem_len = _mem_len;
+ mem_off = _mem_off;
+ file_len = _file_len;
+ file_off = _file_off;
} /* end else */
- /* Initialize sequence counts */
- curr_mem_seq=curr_file_seq=0;
- mem_nseq=file_nseq=0;
-
- /* Loop, until all bytes are processed */
- while(nelmts>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(file_space,H5S_GET_SEQ_LIST_SORTED,&file_iter,io_info->dxpl_cache->vec_size,nelmts,&file_nseq,&file_nelem,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;
+ /* Check for only one element in selection */
+ if(nelmts == 1) {
+ /* Get offset of first element in selections */
+ if(H5S_SELECT_OFFSET(file_space, file_off) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "can't retrieve file selection offset")
+ if(H5S_SELECT_OFFSET(mem_space, mem_off) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "can't retrieve memory selection offset")
+
+ /* Set up necessary information for I/O operation */
+ file_nseq = mem_nseq = 1;
+ curr_mem_seq = curr_file_seq = 0;
+ *file_off *= elmt_size;
+ *mem_off *= elmt_size;
+ *file_len = *mem_len = elmt_size;
+
+ /* Perform I/O on memory and file sequences */
+ if(io_buf->op_type == H5S_SELECT_READ) {
+ if((tmp_file_len = (*io_info->ops.readvv)(io_info,
+ file_nseq, &curr_file_seq, file_len, file_off,
+ mem_nseq, &curr_mem_seq, mem_len, mem_off,
+ addr, chunk, io_buf->u.rbuf)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error")
} /* 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(mem_space,0,&mem_iter,io_info->dxpl_cache->vec_size,nelmts,&mem_nseq,&mem_nelem,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;
- } /* end if */
-
- /* Read file sequences into current memory sequence */
- if ((tmp_file_len=(*io_info->ops.readvv)(io_info,
- file_nseq, &curr_file_seq, file_len, file_off,
- mem_nseq, &curr_mem_seq, mem_len, mem_off,
- addr, chunk, buf))<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error");
+ else {
+ HDassert(io_buf->op_type == H5S_SELECT_WRITE);
+ if((tmp_file_len = (*io_info->ops.writevv)(io_info,
+ file_nseq, &curr_file_seq, file_len, file_off,
+ mem_nseq, &curr_mem_seq, mem_len, mem_off,
+ addr, chunk, io_buf->u.wbuf)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error")
+ } /* end else */
/* Decrement number of elements left to process */
- assert((tmp_file_len%elmt_size)==0);
- nelmts-=(tmp_file_len/elmt_size);
- } /* end while */
+ HDassert((tmp_file_len % elmt_size) == 0);
+ } /* end if */
+ else {
+ size_t mem_nelem; /* Number of elements used in memory sequences */
+ size_t file_nelem; /* Number of elements used in file sequences */
+
+ /* Initialize file iterator */
+ if(H5S_select_iter_init(&file_iter, file_space, elmt_size) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
+ file_iter_init = 1; /* File selection iteration info has been initialized */
+
+ /* Initialize memory iterator */
+ if(H5S_select_iter_init(&mem_iter, mem_space, elmt_size) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
+ mem_iter_init = 1; /* Memory selection iteration info has been initialized */
+
+ /* Initialize sequence counts */
+ curr_mem_seq = curr_file_seq = 0;
+ mem_nseq = file_nseq = 0;
+
+ /* Loop, until all bytes are processed */
+ while(nelmts > 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(file_space, H5S_GET_SEQ_LIST_SORTED, &file_iter, io_info->dxpl_cache->vec_size, nelmts, &file_nseq, &file_nelem, 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(mem_space, 0, &mem_iter, io_info->dxpl_cache->vec_size, nelmts, &mem_nseq, &mem_nelem, 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;
+ } /* end if */
+
+ /* Perform I/O on memory and file sequences */
+ if(io_buf->op_type == H5S_SELECT_READ) {
+ if((tmp_file_len = (*io_info->ops.readvv)(io_info,
+ file_nseq, &curr_file_seq, file_len, file_off,
+ mem_nseq, &curr_mem_seq, mem_len, mem_off,
+ addr, chunk, io_buf->u.rbuf)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error")
+ } /* end if */
+ else {
+ HDassert(io_buf->op_type == H5S_SELECT_WRITE);
+ if((tmp_file_len = (*io_info->ops.writevv)(io_info,
+ file_nseq, &curr_file_seq, file_len, file_off,
+ mem_nseq, &curr_mem_seq, mem_len, mem_off,
+ addr, chunk, io_buf->u.wbuf)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error")
+ } /* end else */
+
+ /* Decrement number of elements left to process */
+ HDassert((tmp_file_len % elmt_size) == 0);
+ nelmts -= (tmp_file_len / elmt_size);
+ } /* end while */
+ } /* end else */
done:
/* Release file selection iterator */
- if(file_iter_init) {
- if (H5S_SELECT_ITER_RELEASE(&file_iter)<0)
- HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator");
- } /* end if */
+ if(file_iter_init)
+ if(H5S_SELECT_ITER_RELEASE(&file_iter) < 0)
+ HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator")
/* Release memory selection iterator */
- if(mem_iter_init) {
- if (H5S_SELECT_ITER_RELEASE(&mem_iter)<0)
- HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator");
- } /* end if */
+ if(mem_iter_init)
+ if(H5S_SELECT_ITER_RELEASE(&mem_iter) < 0)
+ HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator")
/* Free vector arrays */
if(io_info->dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if(file_len!=NULL)
- H5FL_SEQ_FREE(size_t,file_len);
- if(file_off!=NULL)
- H5FL_SEQ_FREE(hsize_t,file_off);
- if(mem_len!=NULL)
- H5FL_SEQ_FREE(size_t,mem_len);
- if(mem_off!=NULL)
- H5FL_SEQ_FREE(hsize_t,mem_off);
+ if(file_len != NULL)
+ H5FL_SEQ_FREE(size_t, file_len);
+ if(file_off != NULL)
+ H5FL_SEQ_FREE(hsize_t, file_off);
+ if(mem_len != NULL)
+ H5FL_SEQ_FREE(size_t, mem_len);
+ if(mem_off != NULL)
+ H5FL_SEQ_FREE(hsize_t, mem_off);
} /* end if */
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5D_select_read() */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_select_io() */
/*-------------------------------------------------------------------------
- * Function: H5D_select_write
+ * Function: H5D_select_read
*
- * Purpose: Writes directly from application memory into a file
+ * Purpose: Reads directly from file into application memory.
*
* Return: Non-negative on success/Negative on failure
*
@@ -575,133 +633,63 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5D_select_write(H5D_io_info_t *io_info,
+H5D_select_read(H5D_io_info_t *io_info,
size_t nelmts, size_t elmt_size,
const H5S_t *file_space, const H5S_t *mem_space,
haddr_t addr, void *chunk/*in*/,
- const void *buf/*out*/)
+ void *buf/*out*/)
{
- H5S_sel_iter_t mem_iter; /* Memory selection iteration info */
- hbool_t mem_iter_init=0; /* Memory selection iteration info has been initialized */
- H5S_sel_iter_t file_iter; /* File selection iteration info */
- hbool_t file_iter_init=0; /* File selection iteration info has been initialized */
- hsize_t _mem_off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets in memory */
- hsize_t *mem_off=NULL; /* Pointer to sequence offsets in memory */
- hsize_t _file_off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets in the file */
- hsize_t *file_off=NULL; /* Pointer to sequence offsets in the file */
- size_t _mem_len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths in memory */
- size_t *mem_len=NULL; /* Pointer to sequence lengths in memory */
- size_t _file_len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths in the file */
- size_t *file_len=NULL; /* Pointer to sequence lengths in the file */
- size_t mem_nseq; /* Number of sequences generated in the file */
- size_t file_nseq; /* Number of sequences generated in memory */
- size_t mem_nelem; /* Number of elements used in memory sequences */
- size_t file_nelem; /* Number of elements 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 */
- ssize_t tmp_file_len; /* Temporary number of bytes in file sequence */
- herr_t ret_value=SUCCEED; /* Return value */
+ H5D_select_buf_t io_buf; /* Selection I/O operation to perform */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI(H5D_select_write, FAIL);
+ FUNC_ENTER_NOAPI(H5D_select_read, FAIL)
- /* Check args */
- assert(io_info);
- assert(io_info->dset);
- assert(io_info->store);
- assert(TRUE==H5P_isa_class(io_info->dxpl_id,H5P_DATASET_XFER));
- assert(buf);
-
- /* Allocate the vector I/O arrays */
- if(io_info->dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if((mem_len = H5FL_SEQ_MALLOC(size_t,io_info->dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array");
- if((mem_off = H5FL_SEQ_MALLOC(hsize_t,io_info->dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array");
- if((file_len = H5FL_SEQ_MALLOC(size_t,io_info->dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O length vector array");
- if((file_off = H5FL_SEQ_MALLOC(hsize_t,io_info->dxpl_cache->vec_size))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array");
- } /* end if */
- else {
- mem_len=_mem_len;
- mem_off=_mem_off;
- file_len=_file_len;
- file_off=_file_off;
- } /* end else */
-
- /* Initialize file iterator */
- if (H5S_select_iter_init(&file_iter, file_space, elmt_size)<0)
- HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator");
- file_iter_init=1; /* File selection iteration info has been initialized */
-
- /* Initialize memory iterator */
- if (H5S_select_iter_init(&mem_iter, mem_space, elmt_size)<0)
- HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator");
- mem_iter_init=1; /* Memory selection iteration info has been initialized */
+ /* Construct proper I/O operation */
+ io_buf.op_type = H5S_SELECT_READ;
+ io_buf.u.rbuf = buf;
- /* Initialize sequence counts */
- curr_mem_seq=curr_file_seq=0;
- mem_nseq=file_nseq=0;
+ /* Call generic selection operation */
+ if(H5D_select_io(io_info, nelmts, elmt_size, file_space, mem_space, addr, chunk, &io_buf) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error")
- /* Loop, until all bytes are processed */
- while(nelmts>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(file_space,H5S_GET_SEQ_LIST_SORTED,&file_iter,io_info->dxpl_cache->vec_size,nelmts,&file_nseq,&file_nelem,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 */
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5D_select_read() */
- /* Check if more memory sequences are needed */
- if(curr_mem_seq>=mem_nseq) {
- /* Get sequences for memory selection */
- if(H5S_SELECT_GET_SEQ_LIST(mem_space,0,&mem_iter,io_info->dxpl_cache->vec_size,nelmts,&mem_nseq,&mem_nelem,mem_off,mem_len)<0)
- HGOTO_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed");
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_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
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_select_write(H5D_io_info_t *io_info,
+ size_t nelmts, size_t elmt_size,
+ const H5S_t *file_space, const H5S_t *mem_space,
+ haddr_t addr, void *chunk/*in*/,
+ const void *buf/*out*/)
+{
+ H5D_select_buf_t io_buf; /* Selection I/O operation to perform */
+ herr_t ret_value = SUCCEED; /* Return value */
- /* Start at the beginning of the sequences again */
- curr_mem_seq=0;
- } /* end if */
+ FUNC_ENTER_NOAPI(H5D_select_write, FAIL)
- /* Write memory sequences into file sequences */
- if ((tmp_file_len=(*io_info->ops.writevv)(io_info,
- file_nseq, &curr_file_seq, file_len, file_off,
- mem_nseq, &curr_mem_seq, mem_len, mem_off,
- addr, chunk, buf))<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error");
+ /* Construct proper I/O operation */
+ io_buf.op_type = H5S_SELECT_WRITE;
+ io_buf.u.wbuf = buf;
- /* Decrement number of elements left to process */
- assert((tmp_file_len%elmt_size)==0);
- nelmts-=(tmp_file_len/elmt_size);
- } /* end while */
+ /* Call generic selection operation */
+ if(H5D_select_io(io_info, nelmts, elmt_size, file_space, mem_space, addr, chunk, &io_buf) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error")
done:
- /* Release file selection iterator */
- if(file_iter_init) {
- if (H5S_SELECT_ITER_RELEASE(&file_iter)<0)
- HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator");
- } /* end if */
-
- /* Release memory selection iterator */
- if(mem_iter_init) {
- if (H5S_SELECT_ITER_RELEASE(&mem_iter)<0)
- HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator");
- } /* end if */
-
- /* Free vector arrays */
- if(io_info->dxpl_cache->vec_size != H5D_IO_VECTOR_SIZE) {
- if(file_len!=NULL)
- H5FL_SEQ_FREE(size_t,file_len);
- if(file_off!=NULL)
- H5FL_SEQ_FREE(hsize_t,file_off);
- if(mem_len!=NULL)
- H5FL_SEQ_FREE(size_t,mem_len);
- if(mem_off!=NULL)
- H5FL_SEQ_FREE(hsize_t,mem_off);
- } /* end if */
-
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_select_write() */
diff --git a/src/H5Sall.c b/src/H5Sall.c
index 5d01fec..c603251 100644
--- a/src/H5Sall.c
+++ b/src/H5Sall.c
@@ -42,6 +42,7 @@ static hssize_t H5S_all_serial_size(const H5S_t *space);
static herr_t H5S_all_serialize(const H5S_t *space, uint8_t *buf);
static herr_t H5S_all_deserialize(H5S_t *space, const uint8_t *buf);
static herr_t H5S_all_bounds(const H5S_t *space, hsize_t *start, hsize_t *end);
+static herr_t H5S_all_offset(const H5S_t *space, hsize_t *off);
static htri_t H5S_all_is_contiguous(const H5S_t *space);
static htri_t H5S_all_is_single(const H5S_t *space);
static htri_t H5S_all_is_regular(const H5S_t *space);
@@ -70,6 +71,7 @@ const H5S_select_class_t H5S_sel_all[1] = {{
H5S_all_serialize,
H5S_all_deserialize,
H5S_all_bounds,
+ H5S_all_offset,
H5S_all_is_contiguous,
H5S_all_is_single,
H5S_all_is_regular,
@@ -585,26 +587,61 @@ done:
herr_t
H5S_all_bounds(const H5S_t *space, hsize_t *start, hsize_t *end)
{
- int rank; /* Dataspace rank */
- int i; /* index variable */
+ unsigned rank; /* Dataspace rank */
+ unsigned i; /* index variable */
- FUNC_ENTER_NOAPI_NOFUNC(H5S_all_bounds);
+ FUNC_ENTER_NOAPI_NOFUNC(H5S_all_bounds)
- assert(space);
- assert(start);
- assert(end);
+ HDassert(space);
+ HDassert(start);
+ HDassert(end);
/* Get the dataspace extent rank */
- rank=space->extent.rank;
+ rank = space->extent.rank;
/* Just copy over the complete extent */
- for(i=0; i<rank; i++) {
- start[i]=0;
- end[i]=space->extent.size[i]-1;
+ for(i = 0; i < rank; i++) {
+ start[i] = 0;
+ end[i] = space->extent.size[i] - 1;
} /* end for */
- FUNC_LEAVE_NOAPI(SUCCEED);
-} /* H5Sget_all_bounds() */
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5S_all_bounds() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S_all_offset
+ PURPOSE
+ Gets the linear offset of the first element for the selection.
+ USAGE
+ herr_t H5S_all_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
+ Non-negative on success, negative on failure
+ DESCRIPTION
+ Retrieves the linear offset (in "units" of elements) of the first element
+ selected within the dataspace.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Calling this function on a "none" selection returns fail.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5S_all_offset(const H5S_t *space, hsize_t *offset)
+{
+ FUNC_ENTER_NOAPI_NOFUNC(H5S_all_offset)
+
+ HDassert(space);
+ HDassert(offset);
+
+ /* 'All' selections always start at offset 0 */
+ *offset = 0;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5S_all_offset() */
/*--------------------------------------------------------------------------
diff --git a/src/H5Shyper.c b/src/H5Shyper.c
index 8acbfd5..9ca1fdc 100644
--- a/src/H5Shyper.c
+++ b/src/H5Shyper.c
@@ -57,6 +57,7 @@ static hssize_t H5S_hyper_serial_size(const H5S_t *space);
static herr_t H5S_hyper_serialize(const H5S_t *space, uint8_t *buf);
static herr_t H5S_hyper_deserialize(H5S_t *space, const uint8_t *buf);
static herr_t H5S_hyper_bounds(const H5S_t *space, hsize_t *start, hsize_t *end);
+static herr_t H5S_hyper_offset(const H5S_t *space, hsize_t *offset);
static htri_t H5S_hyper_is_contiguous(const H5S_t *space);
static htri_t H5S_hyper_is_single(const H5S_t *space);
static htri_t H5S_hyper_is_regular(const H5S_t *space);
@@ -90,6 +91,7 @@ const H5S_select_class_t H5S_sel_hyper[1] = {{
H5S_hyper_serialize,
H5S_hyper_deserialize,
H5S_hyper_bounds,
+ H5S_hyper_offset,
H5S_hyper_is_contiguous,
H5S_hyper_is_single,
H5S_hyper_is_regular,
@@ -2708,6 +2710,114 @@ done:
/*--------------------------------------------------------------------------
NAME
+ H5S_hyper_offset
+ PURPOSE
+ Gets the linear offset of the first element for the selection.
+ USAGE
+ herr_t H5S_hyper_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
+ Non-negative on success, negative on failure
+ DESCRIPTION
+ Retrieves the linear offset (in "units" of elements) of the first element
+ selected within the dataspace.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Calling this function on a "none" selection returns fail.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5S_hyper_offset(const H5S_t *space, hsize_t *offset)
+{
+ const hssize_t *sel_offset; /* Pointer to the selection's offset */
+ const hsize_t *dim_size; /* Pointer to a dataspace's extent */
+ hsize_t accum; /* Accumulator for dimension sizes */
+ int rank; /* Dataspace rank */
+ int i; /* index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5S_hyper_offset, FAIL)
+
+ HDassert(space);
+ HDassert(offset);
+
+ /* Start at linear offset 0 */
+ *offset = 0;
+
+ /* Set up pointers to arrays of values */
+ rank = space->extent.rank;
+ sel_offset = space->select.offset;
+ dim_size = space->extent.size;
+
+ /* Check for a "regular" hyperslab selection */
+ if(space->select.sel_info.hslab->diminfo_valid) {
+ const H5S_hyper_dim_t *diminfo = space->select.sel_info.hslab->opt_diminfo; /* Local alias for diminfo */
+
+ /* Loop through starting coordinates, calculating the linear offset */
+ accum = 1;
+ for(i = (rank - 1); i >= 0; i--) {
+ hssize_t hyp_offset = (hssize_t)diminfo[i].start + sel_offset[i]; /* Hyperslab's offset in this dimension */
+
+ /* Check for offset moving selection out of the dataspace */
+ if(hyp_offset < 0 || (hsize_t)hyp_offset >= dim_size[i])
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds")
+
+ /* Add the hyperslab's offset in this dimension to the total linear offset */
+ *offset += hyp_offset * accum;
+
+ /* Increase the accumulator */
+ accum *= dim_size[i];
+ } /* end for */
+ } /* end if */
+ else {
+ const H5S_hyper_span_t *span; /* Hyperslab span node */
+ hsize_t dim_accum[H5S_MAX_RANK]; /* Accumulators, for each dimension */
+
+ /* Calculate the accumulator for each dimension */
+ accum = 1;
+ for(i = (rank - 1); i >= 0; i--) {
+ /* Set the accumulator for this dimension */
+ dim_accum[i] = accum;
+
+ /* Increase the accumulator */
+ accum *= dim_size[i];
+ } /* end for */
+
+ /* Get information for the first span, in the slowest changing dimension */
+ span = space->select.sel_info.hslab->span_lst->head;
+
+ /* Work down the spans, computing the linear offset */
+ i = 0;
+ while(span) {
+ hssize_t hyp_offset = (hssize_t)span->low + sel_offset[i]; /* Hyperslab's offset in this dimension */
+
+ /* Check for offset moving selection out of the dataspace */
+ if(hyp_offset < 0 || (hsize_t)hyp_offset >= dim_size[i])
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds")
+
+ /* Add the hyperslab's offset in this dimension to the total linear offset */
+ *offset += hyp_offset * dim_accum[i];
+
+ /* Advance to first span in "down" dimension */
+ if(span->down) {
+ HDassert(span->down->head);
+ span = span->down->head;
+ } /* end if */
+ else
+ span = NULL;
+ i++;
+ } /* end while */
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5S_hyper_offset() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5S_hyper_is_contiguous
PURPOSE
Check if a hyperslab selection is contiguous within the dataspace extent.
@@ -2727,12 +2837,10 @@ done:
htri_t
H5S_hyper_is_contiguous(const H5S_t *space)
{
- H5S_hyper_span_info_t *spans; /* Hyperslab span info node */
- H5S_hyper_span_t *span; /* Hyperslab span node */
- unsigned u; /* index variable */
unsigned small_contiguous, /* Flag for small contiguous block */
large_contiguous; /* Flag for large contiguous block */
- htri_t ret_value=FALSE; /* return value */
+ unsigned u; /* index variable */
+ htri_t ret_value = FALSE; /* Return value */
FUNC_ENTER_NOAPI_NOFUNC(H5S_hyper_is_contiguous);
@@ -2791,6 +2899,9 @@ H5S_hyper_is_contiguous(const H5S_t *space)
ret_value=TRUE;
} /* end if */
else {
+ H5S_hyper_span_info_t *spans; /* Hyperslab span info node */
+ H5S_hyper_span_t *span; /* Hyperslab span node */
+
/*
* For a hyperslab to be contiguous, it must have only one block and
* (either it's size must be the same as the dataspace extent's in all
diff --git a/src/H5Snone.c b/src/H5Snone.c
index 89a1875..88ab67f 100644
--- a/src/H5Snone.c
+++ b/src/H5Snone.c
@@ -43,6 +43,7 @@ static hssize_t H5S_none_serial_size(const H5S_t *space);
static herr_t H5S_none_serialize(const H5S_t *space, uint8_t *buf);
static herr_t H5S_none_deserialize(H5S_t *space, const uint8_t *buf);
static herr_t H5S_none_bounds(const H5S_t *space, hsize_t *start, hsize_t *end);
+static herr_t H5S_none_offset(const H5S_t *space, hsize_t *off);
static htri_t H5S_none_is_contiguous(const H5S_t *space);
static htri_t H5S_none_is_single(const H5S_t *space);
static htri_t H5S_none_is_regular(const H5S_t *space);
@@ -71,6 +72,7 @@ const H5S_select_class_t H5S_sel_none[1] = {{
H5S_none_serialize,
H5S_none_deserialize,
H5S_none_bounds,
+ H5S_none_offset,
H5S_none_is_contiguous,
H5S_none_is_single,
H5S_none_is_regular,
@@ -565,11 +567,43 @@ H5S_none_bounds(const H5S_t UNUSED *space, hsize_t UNUSED *start, hsize_t UNUSED
/*--------------------------------------------------------------------------
NAME
+ H5S_none_offset
+ PURPOSE
+ Gets the linear offset of the first element for the selection.
+ USAGE
+ herr_t H5S_none_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
+ Non-negative on success, negative on failure
+ DESCRIPTION
+ Retrieves the linear offset (in "units" of elements) of the first element
+ selected within the dataspace.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Calling this function on a "none" selection returns fail.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5S_none_offset(const H5S_t *space, hsize_t *offset)
+{
+ FUNC_ENTER_NOAPI_NOFUNC(H5S_none_offset)
+
+ HDassert(space);
+ HDassert(offset);
+
+ FUNC_LEAVE_NOAPI(FAIL)
+} /* H5S_none_offset() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5S_none_is_contiguous
PURPOSE
Check if a "none" selection is contiguous within the dataspace extent.
USAGE
- htri_t H5S_all_is_contiguous(space)
+ htri_t H5S_none_is_contiguous(space)
H5S_t *space; IN: Dataspace pointer to check
RETURNS
TRUE/FALSE/FAIL
@@ -767,7 +801,7 @@ done:
PURPOSE
Create a list of offsets & lengths for a selection
USAGE
- herr_t H5S_all_get_seq_list(space,flags,iter,maxseq,maxelem,nseq,nelem,off,len)
+ herr_t H5S_none_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
@@ -816,4 +850,5 @@ H5S_none_get_seq_list(const H5S_t UNUSED *space, unsigned UNUSED flags, H5S_sel_
*nelem=0;
FUNC_LEAVE_NOAPI(SUCCEED);
-} /* end H5S_all_get_seq_list() */
+} /* end H5S_none_get_seq_list() */
+
diff --git a/src/H5Spkg.h b/src/H5Spkg.h
index 71cc43b..3fe2ac3 100644
--- a/src/H5Spkg.h
+++ b/src/H5Spkg.h
@@ -133,8 +133,10 @@ typedef hssize_t (*H5S_sel_serial_size_func_t)(const H5S_t *space);
typedef herr_t (*H5S_sel_serialize_func_t)(const H5S_t *space, uint8_t *buf);
/* Method to store create selection from "serialized" form (a byte sequence suitable for storing on disk) */
typedef herr_t (*H5S_sel_deserialize_func_t)(H5S_t *space, const uint8_t *buf);
-/* Method to determine to smallest n-D bounding box containing the current selection */
+/* Method to determine smallest n-D bounding box containing the current selection */
typedef herr_t (*H5S_sel_bounds_func_t)(const H5S_t *space, hsize_t *start, hsize_t *end);
+/* Method to determine linear offset of initial element in selection within dataspace */
+typedef herr_t (*H5S_sel_offset_func_t)(const H5S_t *space, hsize_t *offset);
/* Method to determine if current selection is contiguous */
typedef htri_t (*H5S_sel_is_contiguous_func_t)(const H5S_t *space);
/* Method to determine if current selection is a single block */
@@ -159,6 +161,7 @@ typedef struct {
H5S_sel_serialize_func_t serialize; /* Method to store current selection in "serialized" form (a byte sequence suitable for storing on disk) */
H5S_sel_deserialize_func_t deserialize; /* Method to store create selection from "serialized" form (a byte sequence suitable for storing on disk) */
H5S_sel_bounds_func_t bounds; /* Method to determine to smallest n-D bounding box containing the current selection */
+ H5S_sel_offset_func_t offset; /* Method to determine linear offset of initial element in selection within dataspace */
H5S_sel_is_contiguous_func_t is_contiguous; /* Method to determine if current selection is contiguous */
H5S_sel_is_single_func_t is_single; /* Method to determine if current selection is a single block */
H5S_sel_is_regular_func_t is_regular; /* Method to determine if current selection is "regular" */
diff --git a/src/H5Spoint.c b/src/H5Spoint.c
index eb37945..78c401c 100644
--- a/src/H5Spoint.c
+++ b/src/H5Spoint.c
@@ -44,6 +44,7 @@ static hssize_t H5S_point_serial_size(const H5S_t *space);
static herr_t H5S_point_serialize(const H5S_t *space, uint8_t *buf);
static herr_t H5S_point_deserialize(H5S_t *space, const uint8_t *buf);
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 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);
@@ -72,6 +73,7 @@ const H5S_select_class_t H5S_sel_point[1] = {{
H5S_point_serialize,
H5S_point_deserialize,
H5S_point_bounds,
+ H5S_point_offset,
H5S_point_is_contiguous,
H5S_point_is_single,
H5S_point_is_regular,
@@ -1038,48 +1040,114 @@ static herr_t
H5S_point_bounds(const H5S_t *space, hsize_t *start, hsize_t *end)
{
H5S_pnt_node_t *node; /* Point node */
- int rank; /* Dataspace rank */
- int i; /* index variable */
- herr_t ret_value=SUCCEED; /* Return value */
+ unsigned rank; /* Dataspace rank */
+ unsigned u; /* index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5S_point_bounds);
+ FUNC_ENTER_NOAPI_NOINIT(H5S_point_bounds)
- assert(space);
- assert(start);
- assert(end);
+ HDassert(space);
+ HDassert(start);
+ HDassert(end);
/* Get the dataspace extent rank */
- rank=space->extent.rank;
+ rank = space->extent.rank;
/* Set the start and end arrays up */
- for(i=0; i<rank; i++) {
- start[i]=HSIZET_MAX;
- end[i]=0;
+ for(u = 0; u < rank; u++) {
+ start[u] = HSIZET_MAX;
+ end[u] = 0;
} /* end for */
/* Iterate through the node, checking the bounds on each element */
- node=space->select.sel_info.pnt_lst->head;
- while(node!=NULL) {
- for(i=0; i<rank; i++) {
+ 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[i]+space->select.offset[i])<0)
+ if(((hssize_t)node->pnt[u] + space->select.offset[u]) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds")
- if(start[i]>(node->pnt[i]+space->select.offset[i]))
- start[i]=node->pnt[i]+space->select.offset[i];
- if(end[i]<(node->pnt[i]+space->select.offset[i]))
- end[i]=node->pnt[i]+space->select.offset[i];
+ if(start[u] > (node->pnt[u] + space->select.offset[u]))
+ start[u] = node->pnt[u] + space->select.offset[u];
+ if(end[u] < (node->pnt[u] + space->select.offset[u]))
+ end[u] = node->pnt[u] + space->select.offset[u];
} /* end for */
- node=node->next;
+ node = node->next;
} /* end while */
done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5S_point_bounds() */
/*--------------------------------------------------------------------------
NAME
+ H5S_point_offset
+ PURPOSE
+ Gets the linear offset of the first element for the selection.
+ USAGE
+ 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
+ Non-negative on success, negative on failure
+ DESCRIPTION
+ Retrieves the linear offset (in "units" of elements) of the first element
+ selected within the dataspace.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Calling this function on a "none" selection returns fail.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+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 */
+ const hsize_t *dim_size; /* Pointer to a dataspace's extent */
+ hsize_t accum; /* Accumulator for dimension sizes */
+ int rank; /* Dataspace rank */
+ int i; /* index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5S_point_offset, FAIL)
+
+ HDassert(space);
+ HDassert(offset);
+
+ /* Start at linear offset 0 */
+ *offset = 0;
+
+ /* Set up pointers to arrays of values */
+ pnt = space->select.sel_info.pnt_lst->head->pnt;
+ sel_offset = space->select.offset;
+ dim_size = space->extent.size;
+
+ /* Loop through coordinates, calculating the linear offset */
+ rank = space->extent.rank;
+ accum = 1;
+ for(i = (rank - 1); i >= 0; i--) {
+ hssize_t pnt_offset = (hssize_t)pnt[i] + sel_offset[i]; /* Point's offset in this dimension */
+
+ /* Check for offset moving selection out of the dataspace */
+ if(pnt_offset < 0 || (hsize_t)pnt_offset >= dim_size[i])
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds")
+
+ /* Add the point's offset in this dimension to the total linear offset */
+ *offset += pnt_offset * accum;
+
+ /* Increase the accumulator */
+ accum *= dim_size[i];
+ } /* end for */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5S_point_offset() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5S_point_is_contiguous
PURPOSE
Check if a point selection is contiguous within the dataspace extent.
diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h
index ec48de9..8970890 100644
--- a/src/H5Sprivate.h
+++ b/src/H5Sprivate.h
@@ -152,6 +152,7 @@ typedef struct H5S_iostats_t {
#define H5S_SELECT_SERIAL_SIZE(S) ((*(S)->select.type->serial_size)(S))
#define H5S_SELECT_SERIALIZE(S,BUF) ((*(S)->select.type->serialize)(S,BUF))
#define H5S_SELECT_BOUNDS(S,START,END) ((*(S)->select.type->bounds)(S,START,END))
+#define H5S_SELECT_OFFSET(S, OFFSET) ((*(S)->select.type->offset)(S, OFFSET))
#define H5S_SELECT_IS_CONTIGUOUS(S) ((*(S)->select.type->is_contiguous)(S))
#define H5S_SELECT_IS_SINGLE(S) ((*(S)->select.type->is_single)(S))
#define H5S_SELECT_IS_REGULAR(S) ((*(S)->select.type->is_regular)(S))
@@ -175,6 +176,7 @@ typedef struct H5S_iostats_t {
#define H5S_SELECT_SERIAL_SIZE(S) (H5S_select_serial_size(S))
#define H5S_SELECT_SERIALIZE(S,BUF) (H5S_select_serialize(S,BUF))
#define H5S_SELECT_BOUNDS(S,START,END) (H5S_get_select_bounds(S,START,END))
+#define H5S_SELECT_OFFSET(S, OFFSET) (H5S_get_select_offset(S, OFFSET))
#define H5S_SELECT_IS_CONTIGUOUS(S) (H5S_select_is_contiguous(S))
#define H5S_SELECT_IS_SINGLE(S) (H5S_select_is_single(S))
#define H5S_SELECT_IS_REGULAR(S) (H5S_select_is_regular(S))
@@ -234,6 +236,7 @@ H5_DLL herr_t H5S_select_fill(const void *fill, size_t fill_size,
H5_DLL htri_t H5S_select_valid(const H5S_t *space);
H5_DLL hssize_t H5S_get_select_npoints(const H5S_t *space);
H5_DLL herr_t H5S_get_select_bounds(const H5S_t *space, hsize_t *start, hsize_t *end);
+H5_DLL herr_t H5S_get_select_offset(const H5S_t *space, hsize_t *offset);
H5_DLL herr_t H5S_select_offset(H5S_t *space, const hssize_t *offset);
H5_DLL herr_t H5S_select_copy(H5S_t *dst, const H5S_t *src, hbool_t share_selection);
H5_DLL htri_t H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2);
diff --git a/src/H5Sselect.c b/src/H5Sselect.c
index 31fd05e..eba17a8 100644
--- a/src/H5Sselect.c
+++ b/src/H5Sselect.c
@@ -579,6 +579,46 @@ H5S_get_select_bounds(const H5S_t *space, hsize_t *start, hsize_t *end)
/*--------------------------------------------------------------------------
NAME
+ H5S_get_select_offset
+ PURPOSE
+ Gets the linear offset of the first element for the selection.
+ USAGE
+ herr_t H5S_get_select_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
+ Non-negative on success, negative on failure
+ DESCRIPTION
+ Retrieves the linear offset (in "units" of elements) of the first element
+ selected within the dataspace.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ The offset calculation _does_ include the current offset of the
+ selection within the dataspace extent.
+
+ Calling this function on a "none" selection returns fail.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5S_get_select_offset(const H5S_t *space, hsize_t *offset)
+{
+ herr_t ret_value; /* return value */
+
+ FUNC_ENTER_NOAPI_NOFUNC(H5S_get_select_offset)
+
+ /* Check args */
+ HDassert(space);
+ HDassert(offset);
+
+ ret_value = (*space->select.type->offset)(space, offset);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5S_get_select_offset() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5S_select_is_contiguous
PURPOSE
Determines if a selection is contiguous in the dataspace