From 765f0159ffa71c77754583d97a2b9e494d381ebe Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Thu, 29 Nov 2007 13:44:07 -0500 Subject: [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 --- src/H5Dselect.c | 416 +++++++++++++++++++++++++++---------------------------- src/H5Sall.c | 61 ++++++-- src/H5Shyper.c | 119 +++++++++++++++- src/H5Snone.c | 41 +++++- src/H5Spkg.h | 5 +- src/H5Spoint.c | 110 ++++++++++++--- src/H5Sprivate.h | 3 + src/H5Sselect.c | 40 ++++++ test/dsets.c | 3 +- 9 files changed, 542 insertions(+), 256 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; iextent.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; iselect.sel_info.pnt_lst->head; - while(node!=NULL) { - for(i=0; iselect.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 diff --git a/test/dsets.c b/test/dsets.c index 8719441..bf58018 100644 --- a/test/dsets.c +++ b/test/dsets.c @@ -6059,7 +6059,8 @@ test_random_chunks(void) for(i = 0; i < NPOINTS; i++) if(rbuf[i] != wbuf[i]){ printf(" Line %d: Incorrect value, wbuf[%u]=%d, rbuf[%u]=%d\n",__LINE__,(unsigned)i,wbuf[i],(unsigned)i,rbuf[i]); - TEST_ERROR; + printf(" coord[%u] = {%lu, %lu}\n", (unsigned)i, (unsigned long)coord[i][0], (unsigned long)coord[i][1]); + TEST_ERROR; } /* end if */ /* Close resources */ -- cgit v0.12