summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/H5D.c72
-rw-r--r--src/H5S.c123
-rw-r--r--src/H5Sall.c755
-rw-r--r--src/H5Shyper.c5847
-rw-r--r--src/H5Spkg.h49
-rw-r--r--src/H5Spoint.c644
-rw-r--r--src/H5Sprivate.h111
-rw-r--r--src/H5Sselect.c1265
-rw-r--r--src/H5Tconv.c10
9 files changed, 2735 insertions, 6141 deletions
diff --git a/src/H5D.c b/src/H5D.c
index e3fb8e1..df68439 100644
--- a/src/H5D.c
+++ b/src/H5D.c
@@ -13,13 +13,13 @@
/* $Id$ */
#include "H5private.h" /* Generic Functions */
-#include "H5Iprivate.h" /* IDs */
#include "H5Dprivate.h" /* Dataset functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5FDprivate.h" /* File drivers */
#include "H5FLprivate.h" /* Free Lists */
#include "H5Gprivate.h" /* Group headers */
#include "H5HLprivate.h" /* Name heap */
+#include "H5Iprivate.h" /* IDs */
#include "H5MMprivate.h" /* Memory management */
#include "H5Oprivate.h" /* Object headers */
#include "H5Pprivate.h" /* Property lists */
@@ -70,11 +70,8 @@ H5FL_DEFINE_STATIC(H5D_t);
/* Declare a free list to manage blocks of type conversion data */
H5FL_BLK_DEFINE_STATIC(type_conv);
-/* Declare a free list to manage blocks of background conversion data */
-H5FL_BLK_DEFINE_STATIC(bkgr_conv);
-
-/* Declare a free list to manage blocks of fill conversion data */
-H5FL_BLK_DEFINE_STATIC(fill_conv);
+/* Declare a free list to manage blocks of single datatype element data */
+H5FL_BLK_DEFINE(type_elem);
/* Declare a free list to manage blocks of VL data */
H5FL_BLK_DEFINE_STATIC(vlen_vl_buf);
@@ -1694,6 +1691,7 @@ H5D_create(H5G_entry_t *loc, const char *name, const H5T_t *type,
H5O_reset(H5O_FILL, &fill_prop);
if(fill.buf && (NULL==H5O_copy(H5O_FILL, &fill, &fill_prop)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT,NULL,"unable to copy fill value");
+ H5O_reset(H5O_FILL_NEW, &fill);
/* Write old fill value */
if (fill_prop.buf && H5O_modify(&(new_dset->ent), H5O_FILL, 0,
H5O_FLAG_CONSTANT, &fill_prop) < 0)
@@ -2373,10 +2371,10 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space,
HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert from file to memory data space");
/*
- * If there is no type conversion then try reading directly into the
+ * If there is no type conversion then read directly into the
* application's buffer. This saves at least one mem-to-mem copy.
*/
- if (H5T_IS_NOOP(tpath) && sconv->read) {
+ if (H5T_IS_NOOP(tpath)) {
#ifdef H5S_DEBUG
H5_timer_begin(&timer);
#endif
@@ -2434,11 +2432,11 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space,
request_nelmts = target_size / MAX(src_type_size, dst_type_size);
/* Figure out the strip mine size. */
- if ((sconv->f->init)(file_space, src_type_size, &file_iter)<0)
+ if (H5S_select_iter_init(file_space, src_type_size, &file_iter)<0)
HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize file selection information");
- if ((sconv->m->init)(mem_space, dst_type_size, &mem_iter)<0)
+ if (H5S_select_iter_init(mem_space, dst_type_size, &mem_iter)<0)
HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information");
- if ((sconv->m->init)(mem_space, dst_type_size, &bkg_iter)<0)
+ if (H5S_select_iter_init(mem_space, dst_type_size, &bkg_iter)<0)
HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize background selection information");
/* Sanity check elements in temporary buffer */
@@ -2468,7 +2466,7 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space,
if (need_bkg && NULL==(bkg_buf=H5P_peek_voidp(dx_plist,H5D_XFER_BKGR_BUF_NAME))) {
/* Allocate background buffer */
H5_CHECK_OVERFLOW((request_nelmts*dst_type_size),hsize_t,size_t);
- if((bkg_buf=H5FL_BLK_ALLOC(bkgr_conv,(size_t)(request_nelmts*dst_type_size),0))==NULL)
+ if((bkg_buf=H5FL_BLK_ALLOC(type_conv,(size_t)(request_nelmts*dst_type_size),0))==NULL)
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for background conversion");
} /* end if */
@@ -2476,7 +2474,7 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space,
H5_CHECK_OVERFLOW(nelmts,hssize_t,hsize_t);
for (smine_start=0; smine_start<(hsize_t)nelmts; smine_start+=smine_nelmts) {
/* Go figure out how many elements to read from the file */
- smine_nelmts = (sconv->f->avail)(file_space,&file_iter,
+ smine_nelmts = H5S_select_favail(file_space,&file_iter,
MIN(request_nelmts, (nelmts-smine_start)));
/*
@@ -2489,7 +2487,7 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space,
#endif
/* Sanity check that space is allocated, then read data from it */
assert(dataset->layout.addr!=HADDR_UNDEF || efl.nused > 0);
- n = (sconv->f->gath)(dataset->ent.file, &(dataset->layout),
+ n = H5S_select_fgath(dataset->ent.file, &(dataset->layout),
dc_plist, src_type_size, file_space,
&file_iter, smine_nelmts, dxpl_id, tconv_buf/*out*/);
@@ -2505,8 +2503,8 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space,
#ifdef H5S_DEBUG
H5_timer_begin(&timer);
#endif
- n = (sconv->m->gath)(buf, dst_type_size, mem_space, &bkg_iter,
- smine_nelmts, bkg_buf/*out*/);
+ n = H5S_select_mgath(buf, dst_type_size, mem_space, &bkg_iter,
+ smine_nelmts, dxpl_id, bkg_buf/*out*/);
#ifdef H5S_DEBUG
H5_timer_end(&(sconv->stats[1].bkg_timer), &timer);
sconv->stats[1].bkg_nbytes += n * dst_type_size;
@@ -2528,8 +2526,8 @@ H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space,
#ifdef H5S_DEBUG
H5_timer_begin(&timer);
#endif
- status = (sconv->m->scat)(tconv_buf, dst_type_size, mem_space,
- &mem_iter, smine_nelmts, buf/*out*/);
+ status = H5S_select_mscat(tconv_buf, dst_type_size, mem_space,
+ &mem_iter, smine_nelmts, dxpl_id, buf/*out*/);
#ifdef H5S_DEBUG
H5_timer_end(&(sconv->stats[1].scat_timer), &timer);
sconv->stats[1].scat_nbytes += smine_nelmts * dst_type_size;
@@ -2566,7 +2564,7 @@ done:
if (tconv_buf && NULL==H5P_peek_voidp(dx_plist,H5D_XFER_TCONV_BUF_NAME))
H5FL_BLK_FREE(type_conv,tconv_buf);
if (bkg_buf && NULL==H5P_peek_voidp(dx_plist,H5D_XFER_BKGR_BUF_NAME))
- H5FL_BLK_FREE(bkgr_conv,bkg_buf);
+ H5FL_BLK_FREE(type_conv,bkg_buf);
if (free_this_space)
H5S_close(free_this_space);
FUNC_LEAVE(ret_value);
@@ -2803,10 +2801,10 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space,
HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert from memory to file data space");
/*
- * If there is no type conversion then try writing directly into the
+ * If there is no type conversion then write directly from the
* application's buffer. This saves at least one mem-to-mem copy.
*/
- if (H5T_IS_NOOP(tpath) && sconv->write) {
+ if (H5T_IS_NOOP(tpath)) {
#ifdef H5S_DEBUG
H5_timer_begin(&timer);
#endif
@@ -2865,11 +2863,11 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space,
HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "temporary buffer max size is too small");
/* Figure out the strip mine size. */
- if ((sconv->f->init)(file_space, dst_type_size, &file_iter)<0)
+ if (H5S_select_iter_init(file_space, dst_type_size, &file_iter)<0)
HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize file selection information");
- if ((sconv->m->init)(mem_space, src_type_size, &mem_iter)<0)
+ if (H5S_select_iter_init(mem_space, src_type_size, &mem_iter)<0)
HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize memory selection information");
- if ((sconv->f->init)(file_space, dst_type_size, &bkg_iter)<0)
+ if (H5S_select_iter_init(file_space, dst_type_size, &bkg_iter)<0)
HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize background selection information");
/*
@@ -2899,7 +2897,7 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space,
if (need_bkg && NULL==(bkg_buf=H5P_peek_voidp(dx_plist,H5D_XFER_BKGR_BUF_NAME))) {
/* Allocate background buffer */
H5_CHECK_OVERFLOW((request_nelmts*dst_type_size),hsize_t,size_t);
- if((bkg_buf=H5FL_BLK_ALLOC(bkgr_conv,(size_t)(request_nelmts*dst_type_size),1))==NULL)
+ if((bkg_buf=H5FL_BLK_ALLOC(type_conv,(size_t)(request_nelmts*dst_type_size),1))==NULL)
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for background conversion");
} /* end if */
@@ -2907,7 +2905,7 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space,
H5_CHECK_OVERFLOW(nelmts,hssize_t,hsize_t);
for (smine_start=0; smine_start<(hsize_t)nelmts; smine_start+=smine_nelmts) {
/* Go figure out how many elements to read from the file */
- smine_nelmts = (sconv->f->avail)(file_space,&file_iter,
+ smine_nelmts = H5S_select_favail(file_space,&file_iter,
MIN(request_nelmts, (nelmts-smine_start)));
/*
@@ -2918,8 +2916,8 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space,
#ifdef H5S_DEBUG
H5_timer_begin(&timer);
#endif
- n = (sconv->m->gath)(buf, src_type_size, mem_space, &mem_iter,
- smine_nelmts, tconv_buf/*out*/);
+ n = H5S_select_mgath(buf, src_type_size, mem_space, &mem_iter,
+ smine_nelmts, dxpl_id, tconv_buf/*out*/);
#ifdef H5S_DEBUG
H5_timer_end(&(sconv->stats[0].gath_timer), &timer);
sconv->stats[0].gath_nbytes += n * src_type_size;
@@ -2932,7 +2930,7 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space,
#ifdef H5S_DEBUG
H5_timer_begin(&timer);
#endif
- n = (sconv->f->gath)(dataset->ent.file, &(dataset->layout),
+ n = H5S_select_fgath(dataset->ent.file, &(dataset->layout),
dc_plist, dst_type_size, file_space,
&bkg_iter, smine_nelmts, dxpl_id,
bkg_buf/*out*/);
@@ -2958,7 +2956,7 @@ H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space,
#ifdef H5S_DEBUG
H5_timer_begin(&timer);
#endif
- status = (sconv->f->scat)(dataset->ent.file, &(dataset->layout),
+ status = H5S_select_fscat(dataset->ent.file, &(dataset->layout),
dc_plist, dst_type_size,
file_space, &file_iter, smine_nelmts,
dxpl_id, tconv_buf);
@@ -3005,7 +3003,7 @@ done:
if (tconv_buf && NULL==H5P_peek_voidp(dx_plist,H5D_XFER_TCONV_BUF_NAME))
H5FL_BLK_FREE(type_conv,tconv_buf);
if (bkg_buf && NULL==H5P_peek_voidp(dx_plist,H5D_XFER_BKGR_BUF_NAME))
- H5FL_BLK_FREE(bkgr_conv,bkg_buf);
+ H5FL_BLK_FREE(type_conv,bkg_buf);
if (free_this_space)
H5S_close(free_this_space);
@@ -3244,7 +3242,7 @@ H5D_init_storage(H5D_t *dset, const H5S_t *space)
bufsize = ptsperbuf*fill.size;
/* Allocate temporary buffer */
- if ((buf=H5FL_BLK_ALLOC(fill_conv,bufsize,0))==NULL)
+ if ((buf=H5FL_BLK_ALLOC(type_conv,bufsize,0))==NULL)
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fill buffer");
/* Fill the buffer with the fill value */
@@ -3291,7 +3289,7 @@ H5D_init_storage(H5D_t *dset, const H5S_t *space)
done:
if (buf)
- H5FL_BLK_FREE(fill_conv,buf);
+ H5FL_BLK_FREE(type_conv,buf);
FUNC_LEAVE(ret_value);
}
@@ -3765,7 +3763,7 @@ H5D_fill(const void *fill, const H5T_t *fill_type, void *buf, const H5T_t *buf_t
/* Get the maximum buffer size needed and allocate it */
buf_size=MAX(src_type_size,dst_type_size);
- if (NULL==(tconv_buf = H5MM_malloc (buf_size)) || NULL==(bkg_buf = H5MM_calloc(buf_size)))
+ if (NULL==(tconv_buf = H5FL_BLK_ALLOC(type_elem,buf_size,0)) || NULL==(bkg_buf = H5FL_BLK_ALLOC(type_elem,buf_size,1)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
/* Copy the user's data into the buffer for conversion */
@@ -3794,11 +3792,11 @@ H5D_fill(const void *fill, const H5T_t *fill_type, void *buf, const H5T_t *buf_t
done:
if (tconv_buf)
- H5MM_xfree(tconv_buf);
+ H5FL_BLK_FREE(type_elem,tconv_buf);
if (bkg_buf)
- H5MM_xfree(bkg_buf);
+ H5FL_BLK_FREE(type_elem,bkg_buf);
FUNC_LEAVE (ret_value);
-} /* H5Dfill() */
+} /* H5D_fill() */
/*--------------------------------------------------------------------------
diff --git a/src/H5S.c b/src/H5S.c
index 0aa9b18..8d5e8b9 100644
--- a/src/H5S.c
+++ b/src/H5S.c
@@ -16,12 +16,12 @@
#define _H5S_IN_H5S_C
#include "H5private.h" /* Generic Functions */
-#include "H5Iprivate.h" /* ID Functions */
#include "H5Eprivate.h" /* Error handling */
+#include "H5Iprivate.h" /* ID Functions */
#include "H5FLprivate.h" /* Free Lists */
#include "H5MMprivate.h" /* Memory Management functions */
#include "H5Oprivate.h" /* object headers */
-#include "H5Spkg.h" /* Data-space functions */
+#include "H5Spkg.h" /* Dataspace functions */
/* Local static function prototypes */
@@ -31,9 +31,12 @@
static int interface_initialize_g = 0;
static herr_t H5S_init_interface(void);
-/* Tables of file and memory conversion information */
-static const H5S_fconv_t *H5S_fconv_g[H5S_SEL_N];
-static const H5S_mconv_t *H5S_mconv_g[H5S_SEL_N];
+#ifdef H5S_DEBUG
+/* Names of the selection names, for debugging */
+static const char *H5S_sel_names[]={
+ "none", "point", "hyperslab", "all"
+};
+#endif /* H5S_DEBUG */
/* The path table, variable length */
static H5S_conv_t **H5S_conv_g = NULL;
@@ -83,14 +86,6 @@ H5S_init_interface(void)
"unable to initialize interface");
}
- /* Register space conversion functions */
- if (H5S_register(H5S_SEL_POINTS, H5S_POINT_FCONV, H5S_POINT_MCONV)<0 ||
- H5S_register(H5S_SEL_ALL, H5S_ALL_FCONV, H5S_ALL_MCONV) <0 ||
- H5S_register(H5S_SEL_HYPERSLABS, H5S_HYPER_FCONV, H5S_HYPER_MCONV) <0) {
- HRETURN_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL,
- "unable to register one or more conversion functions");
- }
-
#ifdef H5_HAVE_PARALLEL
{
/* Allow MPI buf-and-file-type optimizations? */
@@ -175,7 +170,7 @@ H5S_term_interface(void)
/* Summary */
sprintf(buf, "%s %c %s",
- path->m->name, 0==j?'>':'<', path->f->name);
+ H5S_sel_names[path->mtype], 0==j?'>':'<', H5S_sel_names[path->ftype]);
fprintf(H5DEBUG(S), " %-16s\n", buf);
/* Gather */
@@ -266,9 +261,8 @@ H5S_term_interface(void)
H5I_destroy_group(H5I_DATASPACE);
/* Clear/free conversion table */
- HDmemset(H5S_fconv_g, 0, sizeof(H5S_fconv_g));
- HDmemset(H5S_mconv_g, 0, sizeof(H5S_mconv_g));
- for (i=0; i<H5S_nconv_g; i++) H5MM_xfree(H5S_conv_g[i]);
+ for (i=0; i<H5S_nconv_g; i++)
+ H5MM_xfree(H5S_conv_g[i]);
H5S_conv_g = H5MM_xfree(H5S_conv_g);
H5S_nconv_g = H5S_aconv_g = 0;
@@ -282,46 +276,6 @@ H5S_term_interface(void)
}
-/*-------------------------------------------------------------------------
- * Function: H5S_register
- *
- * Purpose: Adds information about a data space conversion to the space
- * conversion table. A space conversion has two halves: the
- * half that copies data points between application memory and
- * the type conversion array, and the half that copies points
- * between the type conversion array and the file. Both halves
- * are required.
- *
- * Note: The conversion table will contain pointers to the file and
- * memory conversion info. The FCONV and MCONV arguments are
- * not copied.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * Tuesday, August 11, 1998
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5S_register(H5S_sel_type cls, const H5S_fconv_t *fconv,
- const H5S_mconv_t *mconv)
-{
- FUNC_ENTER_NOAPI(H5S_register, FAIL);
-
- assert(cls>=0 && cls<H5S_SEL_N);
- assert(fconv);
- assert(mconv);
-
- H5S_fconv_g[cls] = fconv;
- H5S_mconv_g[cls] = mconv;
-
- FUNC_LEAVE(SUCCEED);
-}
-
-
/*--------------------------------------------------------------------------
NAME
H5S_create
@@ -1514,7 +1468,9 @@ H5S_conv_t *
H5S_find (const H5S_t *mem_space, const H5S_t *file_space, unsigned flags)
{
H5S_conv_t *path; /* Space conversion path */
+#ifdef H5_HAVE_PARALLEL
htri_t opt; /* Flag whether a selection is optimizable */
+#endif /* H5_HAVE_PARALLEL */
size_t i; /* Index variable */
FUNC_ENTER_NOAPI(H5S_find, NULL);
@@ -1537,8 +1493,8 @@ H5S_find (const H5S_t *mem_space, const H5S_t *file_space, unsigned flags)
* If so then return a pointer to that entry.
*/
for (i=0; i<H5S_nconv_g; i++) {
- if (H5S_conv_g[i]->f->type==file_space->select.type &&
- H5S_conv_g[i]->m->type==mem_space->select.type) {
+ if (H5S_conv_g[i]->ftype==file_space->select.type &&
+ H5S_conv_g[i]->mtype==mem_space->select.type) {
#ifdef H5_HAVE_PARALLEL
/*
@@ -1555,22 +1511,8 @@ H5S_find (const H5S_t *mem_space, const H5S_t *file_space, unsigned flags)
} /* end if */
else {
#endif /* H5_HAVE_PARALLEL */
- /*
- * Check if we can set direct "all" read/write functions
- */
- opt=H5S_all_opt_possible(mem_space,file_space,flags);
- if(opt==FAIL)
- HRETURN_ERROR(H5E_DATASPACE, H5E_BADRANGE, NULL, "invalid check for contiguous dataspace ");
-
- /* Check if we can use the optimized "all" I/O routines */
- if(opt==TRUE) {
- H5S_conv_g[i]->read = H5S_all_read;
- H5S_conv_g[i]->write = H5S_all_write;
- } /* end if */
- else {
- H5S_conv_g[i]->read = NULL;
- H5S_conv_g[i]->write = NULL;
- } /* end else */
+ H5S_conv_g[i]->read = H5S_select_read;
+ H5S_conv_g[i]->write = H5S_select_write;
#ifdef H5_HAVE_PARALLEL
} /* end else */
#endif /* H5_HAVE_PARALLEL */
@@ -1580,21 +1522,14 @@ H5S_find (const H5S_t *mem_space, const H5S_t *file_space, unsigned flags)
}
/*
- * The path wasn't found. Do we have enough information to create a new
- * path?
- */
- if (NULL==H5S_fconv_g[file_space->select.type] || NULL==H5S_mconv_g[mem_space->select.type])
- HRETURN_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, NULL, "unable to convert between data space selections");
-
- /*
- * Create a new path.
+ * The path wasn't found. Create a new path.
*/
if (NULL==(path = H5MM_calloc(sizeof(*path))))
HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for data space conversion path");
/* Initialize file & memory conversion functions */
- path->f = H5S_fconv_g[file_space->select.type];
- path->m = H5S_mconv_g[mem_space->select.type];
+ path->ftype = file_space->select.type;
+ path->mtype = mem_space->select.type;
#ifdef H5_HAVE_PARALLEL
/*
@@ -1611,22 +1546,8 @@ H5S_find (const H5S_t *mem_space, const H5S_t *file_space, unsigned flags)
} /* end if */
else {
#endif /* H5_HAVE_PARALLEL */
- /*
- * Check if we can set direct "all" read/write functions
- */
- opt=H5S_all_opt_possible(mem_space,file_space,flags);
- if(opt==FAIL)
- HRETURN_ERROR(H5E_DATASPACE, H5E_BADRANGE, NULL, "invalid check for contiguous dataspace ");
-
- /* Check if we can use the optimized "all" I/O routines */
- if(opt==TRUE) {
- path->read = H5S_all_read;
- path->write = H5S_all_write;
- } /* end if */
- else {
- path->read = NULL;
- path->write = NULL;
- } /* end else */
+ path->read = H5S_select_read;
+ path->write = H5S_select_write;
#ifdef H5_HAVE_PARALLEL
} /* end else */
#endif /* H5_HAVE_PARALLEL */
diff --git a/src/H5Sall.c b/src/H5Sall.c
index 9a4d80d..6b975d9 100644
--- a/src/H5Sall.c
+++ b/src/H5Sall.c
@@ -10,56 +10,17 @@
#define H5S_PACKAGE /*suppress error about including H5Spkg */
-#include "H5private.h"
-#include "H5Dprivate.h"
-#include "H5Eprivate.h"
-#include "H5Iprivate.h"
-#include "H5Spkg.h"
-#include "H5Tprivate.h" /* Datatypes */
-#include "H5Vprivate.h"
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Iprivate.h" /* ID Functions */
+#include "H5Spkg.h" /* Dataspace functions */
+#include "H5Vprivate.h" /* Vector functions */
/* Interface initialization */
#define PABLO_MASK H5Sall_mask
#define INTERFACE_INIT NULL
static int interface_initialize_g = 0;
-static herr_t H5S_all_init (const H5S_t *space, size_t elmt_size, H5S_sel_iter_t *iter);
-static hsize_t H5S_all_favail (const H5S_t *space, const H5S_sel_iter_t *iter,
- hsize_t max);
-static hsize_t H5S_all_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*/);
-static herr_t H5S_all_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);
-static hsize_t H5S_all_mgath (const void *_buf, size_t elmt_size,
- const H5S_t *mem_space, H5S_sel_iter_t *mem_iter,
- hsize_t nelmts, void *_tconv_buf/*out*/);
-static herr_t H5S_all_mscat (const void *_tconv_buf, size_t elmt_size,
- const H5S_t *mem_space, H5S_sel_iter_t *mem_iter,
- hsize_t nelmts, void *_buf/*out*/);
-
-const H5S_fconv_t H5S_ALL_FCONV[1] = {{
- "all", /*name */
- H5S_SEL_ALL, /*selection type */
- H5S_all_init, /*initialize */
- H5S_all_favail, /*available */
- H5S_all_fgath, /*gather */
- H5S_all_fscat, /*scatter */
-}};
-
-const H5S_mconv_t H5S_ALL_MCONV[1] = {{
- "all", /*name */
- H5S_SEL_ALL, /*selection type */
- H5S_all_init, /*initialize */
- H5S_all_mgath, /*gather */
- H5S_all_mscat, /*scatter */
-}};
-
/*-------------------------------------------------------------------------
* Function: H5S_all_init
@@ -75,7 +36,7 @@ const H5S_mconv_t H5S_ALL_MCONV[1] = {{
*
*-------------------------------------------------------------------------
*/
-static herr_t
+herr_t
H5S_all_init (const H5S_t *space, size_t UNUSED elmt_size, H5S_sel_iter_t *sel_iter)
{
FUNC_ENTER_NOAPI(H5S_all_init, FAIL);
@@ -110,7 +71,7 @@ H5S_all_init (const H5S_t *space, size_t UNUSED elmt_size, H5S_sel_iter_t *sel_i
*
*-------------------------------------------------------------------------
*/
-static hsize_t
+hsize_t
H5S_all_favail (const H5S_t * UNUSED space, const H5S_sel_iter_t *sel_iter, hsize_t max)
{
FUNC_ENTER_NOAPI(H5S_all_favail, 0);
@@ -123,532 +84,6 @@ H5S_all_favail (const H5S_t * UNUSED space, const H5S_sel_iter_t *sel_iter, hsiz
} /* H5S_all_favail() */
-/*-------------------------------------------------------------------------
- * Function: H5S_all_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
- * Tuesday, June 16, 1998
- *
- * Modifications:
- * Robb Matzke, 1999-08-03
- * The data transfer properties are passed by ID since that's
- * what the virtual file layer needs.
- *-------------------------------------------------------------------------
- */
-static hsize_t
-H5S_all_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*/)
-{
- hsize_t actual_bytes; /* The actual number of bytes to read */
- hsize_t buf_off; /* Dataset offset for copying memory */
-
- FUNC_ENTER_NOAPI(H5S_all_fgath, 0);
-
- /* Check args */
- assert (f);
- assert (layout);
- assert (elmt_size>0);
- assert (file_space);
- assert (file_iter);
- assert (nelmts>0);
- assert (buf);
-
- /* Set the offset in the dataset and the number of bytes to read */
- buf_off=file_iter->all.offset*elmt_size;
- actual_bytes=elmt_size*nelmts;
-
- /*
- * Read piece from file.
- */
- H5_CHECK_OVERFLOW(actual_bytes,hsize_t,size_t);
- if (H5F_seq_read(f, dxpl_id, layout, dc_plist, file_space,
- elmt_size, (size_t)actual_bytes, buf_off, buf/*out*/)<0) {
- HRETURN_ERROR(H5E_DATASPACE, H5E_READERROR, 0, "read error");
- }
-
- /* Advance iterator */
- file_iter->all.elmt_left-=nelmts;
- file_iter->all.offset+=nelmts;
-
- FUNC_LEAVE (nelmts);
-} /* H5S_all_fgath() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5S_all_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
- * Tuesday, June 16, 1998
- *
- * Modifications:
- * Robb Matzke, 1999-08-03
- * The data transfer properties are passed by ID since that's
- * what the virtual file layer needs.
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5S_all_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)
-{
- hsize_t actual_bytes; /* The actual number of bytes to write */
- hsize_t buf_off; /* Dataset offset for copying memory */
-
- FUNC_ENTER_NOAPI(H5S_all_fscat, FAIL);
-
- /* Check args */
- assert (f);
- assert (layout);
- assert (elmt_size>0);
- assert (file_space);
- assert (file_iter);
- assert (nelmts>0);
- assert (buf);
-
- /* Set the offset in the dataset and the number of bytes to write */
- buf_off=file_iter->all.offset*elmt_size;
- actual_bytes=elmt_size*nelmts;
-
- /*
- * Write piece from file.
- */
- H5_CHECK_OVERFLOW(actual_bytes,hsize_t,size_t);
- if (H5F_seq_write(f, dxpl_id, layout, dc_plist, file_space,
- elmt_size, (size_t)actual_bytes, buf_off, buf/*out*/)<0) {
- HRETURN_ERROR(H5E_DATASPACE, H5E_WRITEERROR, 0, "write error");
- }
-
- /* Advance iterator */
- file_iter->all.elmt_left-=nelmts;
- file_iter->all.offset+=nelmts;
-
- FUNC_LEAVE (SUCCEED);
-} /* H5S_all_fscat() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5S_all_mgath
- *
- * Purpose: Gathers dataset elements from application memory BUF and
- * copies them into the data type conversion buffer TCONV_BUF.
- * Each element is ELMT_SIZE bytes and arranged in application
- * memory according to MEM_SPACE.
- * The caller is requesting that at most NELMTS be gathered.
- *
- * Return: Success: Number of elements copied.
- *
- * Failure: 0
- *
- * Programmer: Quincey Koziol
- * Tuesday, June 16, 1998
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static hsize_t
-H5S_all_mgath (const void *_buf, size_t elmt_size,
- const H5S_t UNUSED *mem_space, H5S_sel_iter_t *mem_iter,
- hsize_t nelmts, void *tconv_buf/*out*/)
-{
- const uint8_t *buf=(const uint8_t*)_buf; /* Get local copies for address arithmetic */
- hsize_t actual_bytes; /* The actual number of bytes to read */
-
- FUNC_ENTER_NOAPI(H5S_all_mgath, 0);
-
- /* Check args */
- assert (buf);
- assert (elmt_size>0);
- assert (mem_space && H5S_SEL_ALL==mem_space->select.type);
- assert (mem_iter);
- assert (nelmts>0);
- assert (tconv_buf);
-
- /* Set the offset in the dataset and the number of bytes to read */
- buf += mem_iter->all.offset*elmt_size;
- actual_bytes=elmt_size*nelmts;
-
- /* "read" in the bytes from the source (buf) to the destination (tconv_buf) */
- H5_CHECK_OVERFLOW(actual_bytes,hsize_t,size_t);
- HDmemcpy(tconv_buf,buf,(size_t)actual_bytes);
-
- /* Advance iterator */
- mem_iter->all.elmt_left-=nelmts;
- mem_iter->all.offset+=nelmts;
-
- FUNC_LEAVE (nelmts);
-} /* H5S_all_mgath() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5S_all_mscat
- *
- * Purpose: Scatters NELMTS data points from the type conversion buffer
- * TCONV_BUF to the application buffer BUF. Each element is
- * ELMT_SIZE bytes and they are organized in application memory
- * according to MEM_SPACE.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Wednesday, June 17, 1998
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5S_all_mscat (const void *tconv_buf, size_t elmt_size,
- const H5S_t UNUSED *mem_space, H5S_sel_iter_t *mem_iter,
- hsize_t nelmts, void *_buf/*out*/)
-{
- uint8_t *buf=(uint8_t *)_buf;
- hsize_t actual_bytes; /* The actual number of bytes to write */
-
- FUNC_ENTER_NOAPI(H5S_all_mscat, FAIL);
-
- /* Check args */
- assert (tconv_buf);
- assert (elmt_size>0);
- assert (mem_space && H5S_SEL_ALL==mem_space->select.type);
- assert (mem_iter);
- assert (nelmts>0);
- assert (buf);
-
- /* Set the offset in the dataset and the number of bytes to write */
- buf += mem_iter->all.offset*elmt_size;
- actual_bytes=elmt_size*nelmts;
-
- /* "write" the bytes from the source (tconv_buf) to the destination (buf) */
- H5_CHECK_OVERFLOW(actual_bytes,hsize_t,size_t);
- HDmemcpy(buf,tconv_buf,(size_t)actual_bytes);
-
- /* Advance iterator */
- mem_iter->all.elmt_left-=nelmts;
- mem_iter->all.offset+=nelmts;
-
- FUNC_LEAVE (SUCCEED);
-}
-
-
-/*-------------------------------------------------------------------------
- * Function: H5S_all_opt_possible
- *
- * Purpose: Checks if an direct I/O transfer is possible between memory and
- * the file.
- *
- * Return: Success: Non-negative: TRUE or FALSE
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * Wednesday, April 3, 2002
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-htri_t
-H5S_all_opt_possible( const H5S_t *mem_space, const H5S_t *file_space, const unsigned UNUSED flags)
-{
- htri_t c1,c2; /* Flags whether a selection is optimizable */
- htri_t ret_value=TRUE;
-
- FUNC_ENTER_NOAPI(H5S_all_opt_possible, FAIL);
-
- /* Check args */
- assert(mem_space);
- assert(file_space);
-
- /* Check whether these are both simple dataspaces */
- if (H5S_SIMPLE!=mem_space->extent.type || H5S_SIMPLE!=file_space->extent.type)
- HGOTO_DONE(FALSE);
-
- /* Check whether both selections are single blocks */
- c1=H5S_select_single(file_space);
- c2=H5S_select_single(mem_space);
- if(c1==FAIL || c2==FAIL)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "invalid check for single selection blocks");
- if(c1==FALSE || c2==FALSE)
- HGOTO_DONE(FALSE);
-
- /* Check whether the shape of each block is the same */
- c1=H5S_select_shape_same(mem_space,file_space);
- if(c1==FAIL)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "invalid check for selection blocks same");
- if(c1==FALSE)
- HGOTO_DONE(FALSE);
-
-done:
- FUNC_LEAVE(ret_value);
-} /* H5S_all_opt_possible() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5S_all_read
- *
- * Purpose: Reads directly from file into application memory if possible.
- *
- * Return: Success: Non-negative. If data was read directly then
- * MUST_CONVERT is set to zero, otherwise
- * MUST_CONVERT is set to non-zero.
- *
- * Failure: Negative. Return value of MUST_CONVERT is
- * undefined.
- *
- * Programmer: Robb Matzke
- * Thursday, April 22, 1999
- *
- * Modifications:
- * Quincey Koziol, 1999-05-25
- * Modified to allow contiguous hyperslabs to be written out.
- *
- * Robb Matzke, 1999-08-03
- * The data transfer properties are passed by ID since that's
- * what the virtual file layer needs.
- *-------------------------------------------------------------------------
- */
-herr_t
-H5S_all_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*/)
-{
- H5S_hyper_span_t *file_span=NULL,*mem_span=NULL; /* Hyperslab span node */
- char *buf=(char*)_buf; /* Get pointer to buffer */
- hsize_t file_elmts; /* Number of elements in each dimension of selection */
- hssize_t file_off,mem_off; /* Offset (in elements) of selection */
- hsize_t mem_size[H5O_LAYOUT_NDIMS]; /* Size of memory buffer */
- hsize_t size[H5O_LAYOUT_NDIMS]; /* Size of selection */
- hssize_t file_offset[H5O_LAYOUT_NDIMS]; /* Offset of selection in file */
- hssize_t mem_offset[H5O_LAYOUT_NDIMS]; /* Offset of selection in memory */
- unsigned u; /* Index variable */
- herr_t ret_value=SUCCEED;
-
- FUNC_ENTER_NOAPI(H5S_all_read, FAIL);
-
- /* Get information about memory and file */
- for (u=0; u<mem_space->extent.u.simple.rank; u++) {
- switch(mem_space->select.type) {
- case H5S_SEL_HYPERSLABS:
- /* Check for a "regular" hyperslab selection */
- if(mem_space->select.sel_info.hslab.diminfo != NULL) {
- mem_off=mem_space->select.sel_info.hslab.diminfo[u].start;
- } /* end if */
- else {
- mem_off=mem_span->low;
- mem_span=mem_span->down->head;
- } /* end else */
- mem_off+=mem_space->select.offset[u];
- break;
-
- case H5S_SEL_ALL:
- mem_off=0;
- break;
-
- case H5S_SEL_POINTS:
- mem_off=mem_space->select.sel_info.pnt_lst->head->pnt[u]
- +mem_space->select.offset[u];
- break;
-
- default:
- assert(0 && "Invalid selection type!");
- } /* end switch */
-
- switch(file_space->select.type) {
- case H5S_SEL_HYPERSLABS:
- /* Check for a "regular" hyperslab selection */
- if(file_space->select.sel_info.hslab.diminfo != NULL) {
- file_elmts=file_space->select.sel_info.hslab.diminfo[u].block;
- file_off=file_space->select.sel_info.hslab.diminfo[u].start;
- } /* end if */
- else {
- file_elmts=(file_span->high-file_span->low)+1;
- file_off=file_span->low;
- file_span=file_span->down->head;
- } /* end else */
- file_off+=file_space->select.offset[u];
- break;
-
- case H5S_SEL_ALL:
- file_elmts=file_space->extent.u.simple.size[u];
- file_off=0;
- break;
-
- case H5S_SEL_POINTS:
- file_elmts=1;
- file_off=file_space->select.sel_info.pnt_lst->head->pnt[u]
- +file_space->select.offset[u];
- break;
-
- default:
- assert(0 && "Invalid selection type!");
- } /* end switch */
-
- mem_size[u]=mem_space->extent.u.simple.size[u];
- size[u] = file_elmts;
- file_offset[u] = file_off;
- mem_offset[u] = mem_off;
- }
- mem_size[u]=elmt_size;
- size[u] = elmt_size;
- file_offset[u] = 0;
- mem_offset[u] = 0;
-
- /* Read data from the file */
- if (H5F_arr_read(f, dxpl_id, layout, dc_plist, size,
- mem_size, mem_offset, file_offset, buf/*out*/)<0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read data from the file");
-
-done:
- FUNC_LEAVE(ret_value);
-} /* end H5S_all_read() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5S_all_write
- *
- * Purpose: Writes data directly to the file if possible.
- *
- * Return: Success: Non-negative. If data was written directly
- * then MUST_CONVERT is set to zero, otherwise
- * MUST_CONVERT is set to non-zero.
- *
- * Failure: Negative. Return value of MUST_CONVERT is
- * undefined.
- *
- * Programmer: Robb Matzke
- * Wednesday, April 21, 1999
- *
- * Modifications:
- * Quincey Koziol, 1999-05-25
- * Modified to allow contiguous hyperslabs to be written out.
- *
- * Robb Matzke, 1999-08-03
- * The data transfer properties are passed by ID since that's
- * what the virtual file layer needs.
- *-------------------------------------------------------------------------
- */
-herr_t
-H5S_all_write(H5F_t *f, const struct 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)
-{
- H5S_hyper_span_t *file_span=NULL,*mem_span=NULL; /* Hyperslab span node */
- const char *buf=(const char*)_buf; /* Get pointer to buffer */
- hsize_t file_elmts; /* Number of elements in each dimension of selection */
- hssize_t file_off,mem_off; /* Offset (in elements) of selection */
- hsize_t mem_size[H5O_LAYOUT_NDIMS]; /* Size of memory buffer */
- hsize_t size[H5O_LAYOUT_NDIMS]; /* Size of selection */
- hssize_t file_offset[H5O_LAYOUT_NDIMS]; /* Offset of selection in file */
- hssize_t mem_offset[H5O_LAYOUT_NDIMS]; /* Offset of selection in memory */
- unsigned u; /* Index variable */
- herr_t ret_value=SUCCEED;
-
- FUNC_ENTER_NOAPI(H5S_all_write, FAIL);
-
- /* Get information about memory and file */
- for (u=0; u<mem_space->extent.u.simple.rank; u++) {
- switch(mem_space->select.type) {
- case H5S_SEL_HYPERSLABS:
- /* Check for a "regular" hyperslab selection */
- if(mem_space->select.sel_info.hslab.diminfo != NULL) {
- mem_off=mem_space->select.sel_info.hslab.diminfo[u].start;
- } /* end if */
- else {
- mem_off=mem_span->low;
- mem_span=mem_span->down->head;
- } /* end else */
- mem_off+=mem_space->select.offset[u];
- break;
-
- case H5S_SEL_ALL:
- mem_off=0;
- break;
-
- case H5S_SEL_POINTS:
- mem_off=mem_space->select.sel_info.pnt_lst->head->pnt[u]
- +mem_space->select.offset[u];
- break;
-
- default:
- assert(0 && "Invalid selection type!");
- } /* end switch */
-
- switch(file_space->select.type) {
- case H5S_SEL_HYPERSLABS:
- /* Check for a "regular" hyperslab selection */
- if(file_space->select.sel_info.hslab.diminfo != NULL) {
- file_elmts=file_space->select.sel_info.hslab.diminfo[u].block;
- file_off=file_space->select.sel_info.hslab.diminfo[u].start;
- } /* end if */
- else {
- file_elmts=(file_span->high-file_span->low)+1;
- file_off=file_span->low;
- file_span=file_span->down->head;
- } /* end else */
- file_off+=file_space->select.offset[u];
- break;
-
- case H5S_SEL_ALL:
- file_elmts=file_space->extent.u.simple.size[u];
- file_off=0;
- break;
-
- case H5S_SEL_POINTS:
- file_elmts=1;
- file_off=file_space->select.sel_info.pnt_lst->head->pnt[u]
- +file_space->select.offset[u];
- break;
-
- default:
- assert(0 && "Invalid selection type!");
- } /* end switch */
-
- mem_size[u]=mem_space->extent.u.simple.size[u];
- size[u] = file_elmts;
- file_offset[u] = file_off;
- mem_offset[u] = mem_off;
- }
- mem_size[u]=elmt_size;
- size[u] = elmt_size;
- file_offset[u] = 0;
- mem_offset[u] = 0;
-
- /* Write data to the file */
- if (H5F_arr_write(f, dxpl_id, layout, dc_plist, size,
- mem_size, mem_offset, file_offset, buf)<0)
- HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write data to the file");
-
-done:
- FUNC_LEAVE(ret_value);
-} /* end H5S_all_write() */
-
-
/*--------------------------------------------------------------------------
NAME
H5S_all_release
@@ -925,147 +360,81 @@ done:
/*--------------------------------------------------------------------------
NAME
- H5S_all_select_iterate
+ H5S_all_select_get_seq_list
PURPOSE
- Iterate over a "all" selection, calling a user's function for each
- element.
+ Create a list of offsets & lengths for a selection
USAGE
- herr_t H5S_all_select_iterate(buf, type_id, space, op, operator_data)
- void *buf; IN/OUT: Buffer containing elements to iterate over
- hid_t type_id; IN: Datatype ID of BUF array.
- H5S_t *space; IN: Dataspace object containing selection to iterate over
- H5D_operator_t op; IN: Function pointer to the routine to be
- called for each element in BUF iterated over.
- void *operator_data; IN/OUT: Pointer to any user-defined data
- associated with the operation.
+ herr_t H5S_all_select_get_seq_list(flags,space,iter,elem_size,maxseq,maxbytes,nseq,nbytes,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.
+ 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
+ size_t *nbytes; OUT: Actual number of bytes in sequences generated
+ hsize_t *off; OUT: Array of offsets
+ size_t *len; OUT: Array of lengths
RETURNS
- Returns the return value of the last operator if it was non-zero, or zero
- if all elements were processed. Otherwise returns a negative value.
+ Non-negative on success/Negative on failure.
DESCRIPTION
- Iterates over the selected elements in a memory buffer, calling the user's
- callback function for each element. The selection in the dataspace is
- modified so that any elements already iterated over are removed from the
- selection if the iteration is interrupted (by the H5D_operator_t function
- returning non-zero) in the "middle" of the iteration and may be re-started
- by the user where it left off.
-
- NOTE: Until "subtracting" elements from a selection is implemented,
- the selection is not modified.
+ Use the selection in the dataspace to generate a list of byte offsets and
+ lengths for the region(s) selected. Start/Restart from the position in the
+ ITER parameter. The number of sequences generated is limited by the MAXSEQ
+ parameter and the number of sequences actually generated is stored in the
+ NSEQ parameter.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
herr_t
-H5S_all_select_iterate(void *buf, hid_t type_id, H5S_t *space, H5D_operator_t op,
- void *operator_data)
+H5S_all_select_get_seq_list(unsigned UNUSED 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)
{
- hsize_t mem_size[H5O_LAYOUT_NDIMS]; /* Dataspace size */
- hsize_t mem_offset[H5O_LAYOUT_NDIMS]; /* current coordinates */
- hsize_t offset; /* offset of region in buffer */
- hsize_t nelemts; /* Number of elements to iterate through */
- void *tmp_buf; /* temporary location of the element in the buffer */
- unsigned rank; /* Dataspace rank */
- int indx; /* Index to increment */
- H5T_t *dt; /* Datatype structure */
- herr_t ret_value=0; /* return value */
+ hsize_t bytes_left; /* The number of bytes left in the selection */
+ hsize_t elem_used; /* The number of bytes used */
+ herr_t ret_value=SUCCEED; /* return value */
- FUNC_ENTER_NOAPI(H5S_all_select_iterate, 0);
+ FUNC_ENTER_NOAPI (H5S_all_select_get_seq_list, FAIL);
- assert(buf);
+ /* Check args */
assert(space);
- assert(op);
- assert(H5I_DATATYPE == H5I_get_type(type_id));
+ assert(iter);
+ assert(elem_size>0);
+ assert(maxseq>0);
+ assert(maxbytes>0);
+ assert(nseq);
+ assert(nbytes);
+ assert(off);
+ assert(len);
- /* Get the dataspace extent rank */
- rank=space->extent.u.simple.rank;
-
- /* Set up the size of the memory space */
- HDmemcpy(mem_size, space->extent.u.simple.size, rank*sizeof(hsize_t));
-
- /* Set the size of the datatype */
- if (NULL==(dt=H5I_object(type_id)))
- HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an valid base datatype");
- mem_size[rank]=H5T_get_size(dt);
+ /* Calculate the number of bytes left in the selection */
+ bytes_left=iter->all.elmt_left*elem_size;
- /* Set the coordinates to zero */
- HDmemset(mem_offset, 0, (rank+1)*sizeof(hsize_t));
+ /* "round" off the maxbytes allowed to a multiple of the element size */
+ maxbytes=(maxbytes/elem_size)*elem_size;
- /* Get the number of elements to iterate through */
- nelemts=H5S_get_simple_extent_npoints(space);
+ /* Compute the offset in the dataset */
+ off[0]=iter->all.offset*elem_size;
+ len[0]=MIN(maxbytes,bytes_left);
- /* Iterate through the entire dataset */
- while(nelemts>0 && ret_value==0) {
- /* Get the offset in the memory buffer */
- offset=H5V_array_offset(rank+1,mem_size,(const hssize_t *)mem_offset);
- tmp_buf=((char *)buf+offset);
+ /* Should only need one sequence for 'all' selections */
+ *nseq=1;
- ret_value=(*op)(tmp_buf,type_id,(hsize_t)rank,(hssize_t *)mem_offset,operator_data);
+ /* Set the number of bytes used */
+ *nbytes=len[0];
- /* Decrement the number of elements to iterate through */
- nelemts--;
-
- /* Advance the coordinate (currently in C memory order) */
- indx=rank-1; /* Leave the byte offset in the element alone */
- while(indx>=0 && ++mem_offset[indx]==mem_size[indx]) {
- mem_offset[indx]=0;
- indx--;
- } /* end while */
- } /* end while */
-
- FUNC_LEAVE (ret_value);
-} /* H5S_all_select_iterate() */
-
-
-/*--------------------------------------------------------------------------
- NAME
- H5S_all_select_fill
- PURPOSE
- Fill an "all" selection in memory with a value
- USAGE
- herr_t H5S_all_select_fill(fill,fill_size,space,buf)
- const void *fill; IN: Pointer to fill value to use
- size_t fill_size; IN: Size of elements in memory buffer & size of
- fill value
- H5S_t *space; IN: Dataspace describing memory buffer &
- containing selection to use.
- void *buf; IN/OUT: Memory buffer to fill selection in
- RETURNS
- Non-negative on success/Negative on failure.
- DESCRIPTION
- Use the selection in the dataspace to fill elements in a memory buffer.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- The memory buffer elements are assumed to have the same datatype as the
- fill value being placed into them.
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-herr_t
-H5S_all_select_fill(const void *fill, size_t fill_size, const H5S_t *space, void *buf)
-{
- hssize_t nelemts; /* Number of elements in dataspace */
- herr_t ret_value=SUCCEED; /* return value */
-
- FUNC_ENTER_NOAPI(H5S_all_select_fill, FAIL);
-
- /* Check args */
- assert(fill);
- assert(fill_size>0);
- assert(space);
- assert(buf);
-
- /* Fill the selection in the memory buffer */
-
- /* Get the number of elements to iterate through */
- if((nelemts=H5S_get_simple_extent_npoints(space))<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't get number of elements");
-
- /* Fill the elements in the buffer */
- H5_CHECK_OVERFLOW(nelemts,hssize_t,size_t);
- H5V_array_fill(buf, fill, fill_size, (size_t)nelemts);
+ /* Update the iterator */
+ elem_used=len[0]/elem_size;
+ iter->all.elmt_left-=elem_used;
+ iter->all.offset+=elem_used;
+#ifdef LATER
done:
+#endif /* LATER */
FUNC_LEAVE (ret_value);
-} /* H5S_all_select_fill() */
-
+} /* end H5S_all_select_get_seq_list() */
diff --git a/src/H5Shyper.c b/src/H5Shyper.c
index 0e30a73..04cecf6 100644
--- a/src/H5Shyper.c
+++ b/src/H5Shyper.c
@@ -10,17 +10,12 @@
#define H5S_PACKAGE /*suppress error about including H5Spkg */
-#include "H5private.h"
-#include "H5Dprivate.h"
-#include "H5Eprivate.h"
-#include "H5Fprivate.h"
-#include "H5FLprivate.h" /*Free Lists */
-#include "H5Iprivate.h"
-#include "H5MMprivate.h"
-#include "H5Pprivate.h" /* Property Lists */
-#include "H5Spkg.h"
-#include "H5Tprivate.h" /* Datatypes */
-#include "H5Vprivate.h"
+#include "H5private.h" /* Generic Functions */
+#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 H5Shyper_mask
@@ -28,58 +23,14 @@
static int interface_initialize_g = 0;
/* Local datatypes */
-/* Parameter block for H5S_hyper_select_iter_mem */
-typedef struct {
- hid_t dt;
- size_t elem_size;
- const H5S_t *space;
- H5S_sel_iter_t *iter;
- void *src;
- H5D_operator_t op;
- void * op_data;
-} H5S_hyper_iter_info_t;
/* Static function prototypes */
-static herr_t H5S_hyper_init (const H5S_t *space, size_t elmt_size, H5S_sel_iter_t *iter);
-static hsize_t H5S_hyper_favail (const H5S_t UNUSED *space,
- const H5S_sel_iter_t *sel_iter, hsize_t max);
-static hsize_t H5S_hyper_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*/);
-static herr_t H5S_hyper_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);
-static hsize_t H5S_hyper_mgath (const void *_buf, size_t elmt_size,
- const H5S_t *mem_space, H5S_sel_iter_t *mem_iter,
- hsize_t nelmts, void *_tconv_buf/*out*/);
-static herr_t H5S_hyper_mscat (const void *_tconv_buf, size_t elmt_size,
- const H5S_t *mem_space, H5S_sel_iter_t *mem_iter,
- hsize_t nelmts, void *_buf/*out*/);
static herr_t H5S_hyper_free_span_info (H5S_hyper_span_info_t *span_info);
static herr_t H5S_hyper_free_span (H5S_hyper_span_t *span);
static H5S_hyper_span_info_t *H5S_hyper_copy_span (H5S_hyper_span_info_t *spans);
static herr_t H5S_hyper_span_scratch (H5S_hyper_span_info_t *spans, void *scr_value);
static herr_t H5S_hyper_span_precompute (H5S_hyper_span_info_t *spans, size_t elmt_size);
-const H5S_fconv_t H5S_HYPER_FCONV[1] = {{
- "hslab", /*name */
- H5S_SEL_HYPERSLABS, /*selection type */
- H5S_hyper_init, /*initialize */
- H5S_hyper_favail, /*available */
- H5S_hyper_fgath, /*gather */
- H5S_hyper_fscat, /*scatter */
-}};
-
-const H5S_mconv_t H5S_HYPER_MCONV[1] = {{
- "hslab", /*name */
- H5S_SEL_HYPERSLABS, /*selection type */
- H5S_hyper_init, /*initialize */
- H5S_hyper_mgath, /*gather */
- H5S_hyper_mscat, /*scatter */
-}};
-
/* Declare a free list to manage the H5S_hyper_span_t struct */
H5FL_DEFINE_STATIC(H5S_hyper_span_t);
@@ -89,8 +40,8 @@ H5FL_ARR_DEFINE_STATIC(H5S_hyper_span_t,H5S_MAX_RANK);
/* Declare a free list to manage the H5S_hyper_span_info_t struct */
H5FL_DEFINE_STATIC(H5S_hyper_span_info_t);
-/* Declare a free list to manage arrays of size_t */
-H5FL_ARR_DEFINE_STATIC(size_t,-1);
+/* Declare external the free list for hssize_t arrays */
+H5FL_ARR_EXTERN(hssize_t);
/* Declare a free list to manage arrays of hsize_t */
H5FL_ARR_DEFINE_STATIC(hsize_t,-1);
@@ -148,11 +99,14 @@ H5S_hyper_print_spans(const struct H5S_hyper_span_info_t *span_lst)
*
*-------------------------------------------------------------------------
*/
-static herr_t
+herr_t
H5S_hyper_init (const H5S_t *space, size_t elmt_size, H5S_sel_iter_t *sel_iter)
{
+ unsigned cont_dim; /* Maximum contiguous dimension */
+ const H5S_hyper_dim_t *tdiminfo; /* Temporary pointer to diminfo information */
H5S_hyper_span_info_t *spans; /* Pointer to hyperslab span info node */
- unsigned u; /* Index variable */
+ unsigned u; /* Index variable */
+ int i; /* Index variable */
FUNC_ENTER_NOAPI(H5S_hyper_init, FAIL);
@@ -163,14 +117,87 @@ H5S_hyper_init (const H5S_t *space, size_t elmt_size, H5S_sel_iter_t *sel_iter)
/* Initialize the number of points to iterate over */
sel_iter->hyp.elmt_left=space->select.num_elem;
+ sel_iter->hyp.iter_rank=0;
+
+ /* Set the temporary pointer to the dimension information */
+ tdiminfo=space->select.sel_info.hslab.diminfo;
/* Check for the special case of just one H5Sselect_hyperslab call made */
- if(space->select.sel_info.hslab.diminfo!=NULL) {
+ if(tdiminfo!=NULL) {
/* Initialize the information needed for regular hyperslab I/O */
- /* Allocate the position & initialize to initial location */
- sel_iter->hyp.off = H5FL_ARR_ALLOC(hsize_t,space->extent.u.simple.rank,0);
- for(u=0; u<space->extent.u.simple.rank; u++)
- sel_iter->hyp.off[u]=space->select.sel_info.hslab.diminfo[u].start;
+ const hsize_t *mem_size; /* Temporary pointer to dataspace extent's dimension sizes */
+ hsize_t acc; /* Accumulator for "flattened" dimension's sizes */
+
+ /* Set the temporary pointer to the dataspace extent's dimension sizes */
+ mem_size=space->extent.u.simple.size;
+
+ /*
+ * For a regular hyperslab to be contiguous up to some dimension, it
+ * must have only one block (i.e. count==1 in all dimensions up to that
+ * dimension) and the block size must be the same as the dataspace's
+ * extent in that dimension and all dimensions up to that dimension.
+ */
+
+ /* Initialize the number of contiguous dimensions to be the same as the dataspace's rank */
+ cont_dim=space->extent.u.simple.rank;
+
+ /* Check for a "contiguous" block */
+ for(u=space->extent.u.simple.rank-1; u>0; u--) {
+ if(tdiminfo[u].count==1 && tdiminfo[u].block==mem_size[u])
+ cont_dim=u;
+ } /* end for */
+
+ /* Check if the regular selection can be "flattened" */
+ if(cont_dim<space->extent.u.simple.rank) {
+ /* Set the iterator's rank to the contiguous dimensions */
+ sel_iter->hyp.iter_rank=cont_dim;
+
+ /* Allocate the position & initialize to initial location */
+ sel_iter->hyp.off = H5FL_ARR_ALLOC(hsize_t,cont_dim,0);
+ sel_iter->hyp.diminfo = H5FL_ARR_ALLOC(H5S_hyper_dim_t,cont_dim,0);
+ sel_iter->hyp.size = H5FL_ARR_ALLOC(hsize_t,cont_dim,0);
+ sel_iter->hyp.sel_off = H5FL_ARR_ALLOC(hssize_t,cont_dim,0);
+
+ /* "Flatten" dataspace extent and selection information */
+ for(i=space->extent.u.simple.rank-1, acc=1; i>=0; i--) {
+ if(tdiminfo[i].block==mem_size[i] && i>0) {
+ assert(tdiminfo[i].start==0);
+ acc *= mem_size[i];
+ } /* end if */
+ else {
+ if((unsigned)i==(cont_dim-1)) {
+ sel_iter->hyp.diminfo[i].start = tdiminfo[i].start*acc;
+ /* Special case for stride==1 regular selections */
+ if(tdiminfo[i].stride==1)
+ sel_iter->hyp.diminfo[i].stride = 1;
+ else
+ sel_iter->hyp.diminfo[i].stride = tdiminfo[i].stride*acc;
+ sel_iter->hyp.diminfo[i].count = tdiminfo[i].count;
+ sel_iter->hyp.diminfo[i].block = tdiminfo[i].block*acc;
+ sel_iter->hyp.size[i] = mem_size[i]*acc;
+ sel_iter->hyp.sel_off[i] = space->select.offset[i]*acc;
+ } /* end if */
+ else {
+ sel_iter->hyp.diminfo[i].start = tdiminfo[i].start;
+ sel_iter->hyp.diminfo[i].stride = tdiminfo[i].stride;
+ sel_iter->hyp.diminfo[i].count = tdiminfo[i].count;
+ sel_iter->hyp.diminfo[i].block = tdiminfo[i].block;
+ sel_iter->hyp.size[i] = mem_size[i];
+ sel_iter->hyp.sel_off[i] = space->select.offset[i];
+ } /* end else */
+ } /* end if */
+ } /* end for */
+
+ /* Initialize "flattened" iterator offset to initial location and dataspace extent and selection information to correct values */
+ for(u=0; u<cont_dim; u++)
+ sel_iter->hyp.off[u]=sel_iter->hyp.diminfo[u].start;
+ } /* end if */
+ else {
+ /* Allocate the position & initialize to initial location */
+ sel_iter->hyp.off = H5FL_ARR_ALLOC(hsize_t,space->extent.u.simple.rank,0);
+ for(u=0; u<space->extent.u.simple.rank; u++)
+ sel_iter->hyp.off[u]=tdiminfo[u].start;
+ } /* end else */
} /* end if */
else {
/* Initialize the information needed for non-regular hyperslab I/O */
@@ -231,10 +258,23 @@ H5S_hyper_sel_iter_release (H5S_sel_iter_t *sel_iter)
/* Check args */
assert (sel_iter);
- /* Release the array of offsets/positions */
+ /* Release the common array of offsets/positions */
if(sel_iter->hyp.off!=NULL)
H5FL_ARR_FREE(hsize_t,sel_iter->hyp.off);
+/* Release the information needed for "flattened" regular hyperslab I/O */
+ /* Free the "flattened" dataspace extent */
+ if(sel_iter->hyp.size!=NULL)
+ H5FL_ARR_FREE(hsize_t,sel_iter->hyp.size);
+
+ /* Free the "flattened" regular hyperslab selection */
+ if(sel_iter->hyp.diminfo!=NULL)
+ H5FL_ARR_FREE(H5S_hyper_dim_t,sel_iter->hyp.diminfo);
+
+ /* Free the "flattened" selection offset */
+ if(sel_iter->hyp.sel_off!=NULL)
+ H5FL_ARR_FREE(hssize_t,sel_iter->hyp.sel_off);
+
/* Release the information needed for non-regular hyperslab I/O */
/* Free the copy of the selections span tree */
if(sel_iter->hyp.spans!=NULL)
@@ -262,7 +302,7 @@ H5S_hyper_sel_iter_release (H5S_sel_iter_t *sel_iter)
*
*-------------------------------------------------------------------------
*/
-static hsize_t
+hsize_t
H5S_hyper_favail (const H5S_t * UNUSED space,
const H5S_sel_iter_t *sel_iter, hsize_t max)
{
@@ -296,8 +336,9 @@ H5S_hyper_favail (const H5S_t * UNUSED space,
*-------------------------------------------------------------------------
*/
static int
-H5S_hyper_iter_next (const H5S_t *file_space, H5S_sel_iter_t *file_iter)
+H5S_hyper_iter_next (const H5S_t *space, H5S_sel_iter_t *iter)
{
+ const H5S_hyper_dim_t *tdiminfo; /* Temporary pointer to diminfo information */
hsize_t iter_offset[H5O_LAYOUT_NDIMS];
hsize_t iter_count[H5O_LAYOUT_NDIMS];
int fast_dim; /* Rank of the fastest changing dimension for the dataspace */
@@ -307,19 +348,33 @@ H5S_hyper_iter_next (const H5S_t *file_space, H5S_sel_iter_t *file_iter)
FUNC_ENTER_NOINIT(H5S_hyper_iter_next);
- /* Set some useful rank information */
- fast_dim=file_space->extent.u.simple.rank-1;
- ndims=file_space->extent.u.simple.rank;
+ /* Check if this is a "flattened" regular hyperslab selection */
+ if(iter->hyp.iter_rank!=0 && iter->hyp.iter_rank<space->extent.u.simple.rank) {
+ /* Set the aliases for a few important dimension ranks */
+ ndims=iter->hyp.iter_rank;
+ fast_dim=ndims-1;
+
+ /* Set the local copy of the diminfo pointer */
+ tdiminfo=iter->hyp.diminfo;
+ } /* end if */
+ else {
+ /* Set the aliases for a few important dimension ranks */
+ ndims=space->extent.u.simple.rank;
+ fast_dim=ndims-1;
+
+ /* Set the local copy of the diminfo pointer */
+ tdiminfo=space->select.sel_info.hslab.diminfo;
+ } /* end else */
/* Calculate the offset and block count for each dimension */
for(i=0; i<ndims; i++) {
- if(file_space->select.sel_info.hslab.diminfo[i].stride==1) {
- iter_offset[i]=file_iter->hyp.off[i]-file_space->select.sel_info.hslab.diminfo[i].start;
+ if(tdiminfo[i].stride==1) {
+ iter_offset[i]=iter->hyp.off[i]-tdiminfo[i].start;
iter_count[i]=0;
} /* end if */
else {
- iter_offset[i]=(file_iter->hyp.off[i]-file_space->select.sel_info.hslab.diminfo[i].start)%file_space->select.sel_info.hslab.diminfo[i].stride;
- iter_count[i]=(file_iter->hyp.off[i]-file_space->select.sel_info.hslab.diminfo[i].start)/file_space->select.sel_info.hslab.diminfo[i].stride;
+ iter_offset[i]=(iter->hyp.off[i]-tdiminfo[i].start)%tdiminfo[i].stride;
+ iter_count[i]=(iter->hyp.off[i]-tdiminfo[i].start)/tdiminfo[i].stride;
} /* end else */
} /* end for */
@@ -332,7 +387,7 @@ H5S_hyper_iter_next (const H5S_t *file_space, H5S_sel_iter_t *file_iter)
iter_count[temp_dim]++;
/* If this block is still in the range of blocks to output for the dimension, break out of loop */
- if(iter_count[temp_dim]<file_space->select.sel_info.hslab.diminfo[temp_dim].count)
+ if(iter_count[temp_dim]<tdiminfo[temp_dim].count)
break;
else
iter_count[temp_dim]=0; /* reset back to the beginning of the line */
@@ -342,7 +397,7 @@ H5S_hyper_iter_next (const H5S_t *file_space, H5S_sel_iter_t *file_iter)
iter_offset[temp_dim]++;
/* If this block is still in the range of blocks to output for the dimension, break out of loop */
- if(iter_offset[temp_dim]<file_space->select.sel_info.hslab.diminfo[temp_dim].block)
+ if(iter_offset[temp_dim]<tdiminfo[temp_dim].block)
break;
else {
/* Move to the next block in the current dimension */
@@ -350,7 +405,7 @@ H5S_hyper_iter_next (const H5S_t *file_space, H5S_sel_iter_t *file_iter)
iter_count[temp_dim]++;
/* If this block is still in the range of blocks to output for the dimension, break out of loop */
- if(iter_count[temp_dim]<file_space->select.sel_info.hslab.diminfo[temp_dim].count)
+ if(iter_count[temp_dim]<tdiminfo[temp_dim].count)
break;
else
iter_count[temp_dim]=0; /* reset back to the beginning of the line */
@@ -363,3735 +418,12 @@ H5S_hyper_iter_next (const H5S_t *file_space, H5S_sel_iter_t *file_iter)
/* Translate current iter_offset and iter_count into iterator position */
for(i=0; i<ndims; i++)
- file_iter->hyp.off[i]=file_space->select.sel_info.hslab.diminfo[i].start+(file_space->select.sel_info.hslab.diminfo[i].stride*iter_count[i])+iter_offset[i];
+ iter->hyp.off[i]=tdiminfo[i].start+(tdiminfo[i].stride*iter_count[i])+iter_offset[i];
FUNC_LEAVE (SUCCEED);
} /* H5S_hyper_iter_next() */
-/*-------------------------------------------------------------------------
- * Function: H5S_hyper_fread
- *
- * Purpose: Performs an optimized gather from the file, based on a hyperslab
- * span tree.
- *
- * Return: Success: Number of elements copied.
- * Failure: 0
- *
- * Programmer: Quincey Koziol
- * Friday, September 8, 2000
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static hsize_t
-H5S_hyper_fread (H5F_t *f, const struct H5O_layout_t *layout,
- H5P_genplist_t *dc_plist, size_t elmt_size,
- const H5S_t *space, H5S_sel_iter_t *iter,
- hsize_t nelem, hid_t dxpl_id, void *_buf/*out*/)
-{
- uint8_t *dst=(uint8_t *)_buf; /* Alias for pointer arithmetic */
- H5S_hyper_span_t **ispan; /* Iterator's hyperslab span nodes */
- H5S_hyper_span_t *curr_span; /* Current hyperslab span node */
- hsize_t slab[H5O_LAYOUT_NDIMS]; /* Cumulative size of each dimension in bytes */
- hsize_t acc; /* Accumulator for computing cumulative sizes */
- hssize_t *abs_arr; /* Absolute hyperslab span position */
- hssize_t *off_arr; /* Offset within the dataspace extent */
- int fast_dim; /* Rank of the fastest changing dimension for the dataspace */
- int curr_dim; /* Current dimension being operated on */
- int ndims; /* Number of dimensions of dataset */
- hsize_t loc_off; /* Element offset in the dataspace */
- size_t span_size=0; /* Number of bytes in current span to actually process */
- size_t io_bytes_left; /* Number of bytes left to process */
- int i; /* Index variable */
- size_t *seq_len_arr=NULL; /* Array of sequence lengths */
- hsize_t *buf_off_arr=NULL; /* Array of dataset offsets */
- size_t last_io_bytes_left=0; /* Last I/O bytes left before readv() called */
- size_t nseq=0; /* Number of sequence/offsets stored in the arrays */
- size_t vector_size; /* Value for vector size */
- H5P_genplist_t *plist; /* Property list */
- hssize_t ret_value=FAIL;
-
- FUNC_ENTER_NOINIT(H5S_hyper_fread);
-
- /* Check args */
- assert(f);
- assert(layout);
- assert(elmt_size>0);
- assert(space);
- assert(iter);
- assert(nelem>0);
- assert(dst);
-
- /* Set the rank of the fastest changing dimension */
- ndims=space->extent.u.simple.rank;
- fast_dim=(ndims-1);
-
- /* Get the pointers to the current span info and span nodes */
- curr_span=iter->hyp.span[fast_dim];
- abs_arr=iter->hyp.off;
- off_arr=space->select.offset;
- ispan=iter->hyp.span;
-
- /* Set the amount of elements to perform I/O on, etc. */
- H5_ASSIGN_OVERFLOW(io_bytes_left,(nelem*elmt_size),hsize_t,size_t);
-
- /* Compute the cumulative size of dataspace dimensions */
- for(i=fast_dim, acc=elmt_size; i>=0; i--) {
- slab[i]=acc;
- acc*=space->extent.u.simple.size[i];
- } /* end for */
-
- /* Set the offset of the first element iterated on */
- for(i=0, loc_off=0; i<ndims; i++)
- /* Compute the sequential element offset */
- loc_off+=(abs_arr[i]+space->select.offset[i])*slab[i];
-
- /* Get the hyperslab vector size */
- if(TRUE!=H5P_isa_class(dxpl_id,H5P_DATASET_XFER) || NULL == (plist = H5I_object(dxpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list");
- if (H5P_get(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((seq_len_arr = H5FL_ARR_ALLOC(size_t,vector_size,0))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate vector I/O array");
- if((buf_off_arr = H5FL_ARR_ALLOC(hsize_t,vector_size,0))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate vector I/O array");
-
- /* Range check against number of elements left in selection */
- assert(io_bytes_left<=(iter->hyp.elmt_left*elmt_size));
-
- /* Take care of any partial spans leftover from previous I/Os */
- if(abs_arr[fast_dim]!=curr_span->low) {
-
- /* Finish the span in the fastest changing dimension */
-
- /* Compute the number of bytes to attempt in this span */
- H5_ASSIGN_OVERFLOW(span_size,((curr_span->high-abs_arr[fast_dim])+1)*elmt_size,hsize_t,size_t);
-
- /* Check number of bytes against upper bounds allowed */
- if(span_size>io_bytes_left)
- span_size=io_bytes_left;
-
- if (H5F_seq_read(f, dxpl_id, layout, dc_plist, space,
- elmt_size, span_size, loc_off, dst/*out*/)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, 0, "read error");
-
- /* Increment offset in destination */
- dst+=span_size;
-
- /* Decrement I/O left to perform */
- io_bytes_left-=span_size;
-
- /* Check if we are done */
- if(io_bytes_left>0) {
- /* Move to next span in fastest changing dimension */
- curr_span=curr_span->next;
-
- if(curr_span!=NULL) {
- /* Move location offset of destination */
- loc_off+=(curr_span->low-abs_arr[fast_dim])*elmt_size;
-
- /* Move iterator for fastest changing dimension */
- abs_arr[fast_dim]=curr_span->low;
- } /* end if */
- } /* end if */
- else {
- abs_arr[fast_dim]+=span_size/elmt_size;
-
- /* Check if we are still within the span */
- if(abs_arr[fast_dim]<=curr_span->high) {
- iter->hyp.span[fast_dim]=curr_span;
-
- goto partial_done; /* finished with partial span */
- } /* end if */
- /* If we walked off that span, advance to the next span */
- else {
- /* Advance span in this dimension */
- curr_span=curr_span->next;
-
- /* Check if we have a valid span in this dimension still */
- if(curr_span!=NULL) {
- /* Reset absolute position */
- abs_arr[fast_dim]=curr_span->low;
- iter->hyp.span[fast_dim]=curr_span;
-
- goto partial_done; /* finished with partial span */
- } /* end if */
- } /* end else */
- } /* end else */
-
- /* Adjust iterator pointers */
-
- if(curr_span==NULL) {
-/* Same as code in main loop */
- /* Start at the next fastest dim */
- curr_dim=fast_dim-1;
-
- /* Work back up through the dimensions */
- while(curr_dim>=0) {
- /* Reset the current span */
- curr_span=iter->hyp.span[curr_dim];
-
- /* Increment absolute position */
- abs_arr[curr_dim]++;
-
- /* Check if we are still within the span */
- if(abs_arr[curr_dim]<=curr_span->high) {
- break;
- } /* end if */
- /* If we walked off that span, advance to the next span */
- else {
- /* Advance span in this dimension */
- curr_span=curr_span->next;
-
- /* Check if we have a valid span in this dimension still */
- if(curr_span!=NULL) {
- /* Reset absolute position */
- abs_arr[curr_dim]=curr_span->low;
-
- break;
- } /* end if */
- else {
- /* If we finished the span list in this dimension, decrement the dimension worked on and loop again */
- curr_dim--;
- } /* end else */
- } /* end else */
- } /* end while */
-
- /* Check if we are finished with the spans in the tree */
- if(curr_dim<0) {
- /* We had better be done with I/O or bad things are going to happen... */
- assert(io_bytes_left==0);
-
- goto partial_done; /* finished with partial span */
- } /* end if */
- else {
- /* Reset the span in the current dimension */
- ispan[curr_dim]=curr_span;
-
- /* Walk back down the iterator positions, reseting them */
- while(curr_dim<fast_dim) {
- assert(curr_span);
- assert(curr_span->down);
- assert(curr_span->down->head);
-
- /* Set the new span_info & span for this dimension */
- iter->hyp.span[curr_dim+1]=curr_span->down->head;
-
- /* Advance span down the tree */
- curr_span=curr_span->down->head;
-
- /* Reset the absolute offset for the dim */
- abs_arr[curr_dim+1]=curr_span->low;
-
- /* Increment current dimension */
- curr_dim++;
- } /* end while */
-
- /* Verify that the curr_span points to the fastest dim */
- assert(curr_span==iter->hyp.span[fast_dim]);
- } /* end else */
-
- /* Reset the buffer offset */
- for(i=0, loc_off=0; i<ndims; i++)
- loc_off+=(abs_arr[i]+off_arr[i])*slab[i];
- } /* end if */
- } /* end if */
-
-partial_done: /* Yes, goto's are evil, so sue me... :-) */
- /* Get the number of bytes left to process currently */
- last_io_bytes_left=io_bytes_left;
-
- /* Perform the I/O on the elements, based on the position of the iterator */
- while(io_bytes_left>0) {
- /* Adjust location offset of destination to compensate for initial increment below */
- loc_off-=curr_span->pstride;
-
- /* Loop over all the spans in the fastest changing dimension */
- while(curr_span!=NULL) {
- /* Move location offset of destination */
- loc_off+=curr_span->pstride;
-
- /* Compute the number of elements to attempt in this span */
- H5_ASSIGN_OVERFLOW(span_size,curr_span->nelem,hsize_t,size_t);
-
- /* Check number of elements against upper bounds allowed */
- if(span_size>=io_bytes_left) {
- /* Trim the number of bytes to output */
- span_size=io_bytes_left;
- io_bytes_left=0;
-
-/* COMMON */
- /* Store the I/O information for the span */
- seq_len_arr[nseq]=span_size;
- buf_off_arr[nseq]=loc_off;
-
- /* Increment the number of sequences in arrays */
- nseq++;
-
- /* If the sequence & offset arrays are full, read them in */
- if(nseq>=vector_size) {
- /* Read in the sequences */
- if (H5F_seq_readv(f, dxpl_id, layout, dc_plist, space,
- elmt_size, nseq, seq_len_arr, buf_off_arr, dst/*out*/)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, 0, "read error");
-
- /* Increment the offset of the destination buffer */
- dst+=(last_io_bytes_left-io_bytes_left);
-
- /* Keep around the current number of I/O bytes left */
- last_io_bytes_left=io_bytes_left;
- nseq=0;
- } /* end else */
-/* end COMMON */
-
- /* Break out now, we are finished with I/O */
- break;
- } /* end if */
- else {
- /* Decrement I/O left to perform */
- io_bytes_left-=span_size;
-
-/* COMMON */
- /* Store the I/O information for the span */
- seq_len_arr[nseq]=span_size;
- buf_off_arr[nseq]=loc_off;
-
- /* Increment the number of sequences in arrays */
- nseq++;
-
- /* If the sequence & offset arrays are full, read them in */
- if(nseq>=vector_size) {
- /* Read in the sequences */
- if (H5F_seq_readv(f, dxpl_id, layout, dc_plist, space,
- elmt_size, nseq, seq_len_arr, buf_off_arr, dst/*out*/)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, 0, "read error");
-
- /* Increment the offset of the destination buffer */
- dst+=(last_io_bytes_left-io_bytes_left);
-
- /* Keep around the current number of I/O bytes left */
- last_io_bytes_left=io_bytes_left;
- nseq=0;
- } /* end else */
-/* end COMMON */
- } /* end else */
-
- /* Move to next span in fastest changing dimension */
- curr_span=curr_span->next;
- } /* end while */
-
- /* Check if we are done */
- if(io_bytes_left==0) {
- abs_arr[fast_dim]=curr_span->low+(span_size/elmt_size);
-
- /* Check if we are still within the span */
- if(abs_arr[fast_dim]<=curr_span->high) {
- iter->hyp.span[fast_dim]=curr_span;
- break;
- } /* end if */
- /* If we walked off that span, advance to the next span */
- else {
- /* Advance span in this dimension */
- curr_span=curr_span->next;
-
- /* Check if we have a valid span in this dimension still */
- if(curr_span!=NULL) {
- /* Reset absolute position */
- abs_arr[fast_dim]=curr_span->low;
- iter->hyp.span[fast_dim]=curr_span;
- break;
- } /* end if */
- } /* end else */
- } /* end if */
-
- /* Adjust iterator pointers */
-
- /* Start at the next fastest dim */
- curr_dim=fast_dim-1;
-
- /* Work back up through the dimensions */
- while(curr_dim>=0) {
- /* Reset the current span */
- curr_span=iter->hyp.span[curr_dim];
-
- /* Increment absolute position */
- abs_arr[curr_dim]++;
-
- /* Check if we are still within the span */
- if(abs_arr[curr_dim]<=curr_span->high) {
- break;
- } /* end if */
- /* If we walked off that span, advance to the next span */
- else {
- /* Advance span in this dimension */
- curr_span=curr_span->next;
-
- /* Check if we have a valid span in this dimension still */
- if(curr_span!=NULL) {
- /* Reset absolute position */
- abs_arr[curr_dim]=curr_span->low;
-
- break;
- } /* end if */
- else {
- /* If we finished the span list in this dimension, decrement the dimension worked on and loop again */
- curr_dim--;
- } /* end else */
- } /* end else */
- } /* end while */
-
- /* Check if we are finished with the spans in the tree */
- if(curr_dim<0) {
- /* We had better be done with I/O or bad things are going to happen... */
- assert(io_bytes_left==0);
- break;
- } /* end if */
- else {
- /* Reset the span in the current dimension */
- ispan[curr_dim]=curr_span;
-
- /* Walk back down the iterator positions, reseting them */
- while(curr_dim<fast_dim) {
- assert(curr_span);
- assert(curr_span->down);
- assert(curr_span->down->head);
-
- /* Set the new span for the next dimension down */
- iter->hyp.span[curr_dim+1]=curr_span->down->head;
-
- /* Advance span down the tree */
- curr_span=curr_span->down->head;
-
- /* Reset the absolute offset for the dim */
- abs_arr[curr_dim+1]=curr_span->low;
-
- /* Increment current dimension */
- curr_dim++;
- } /* end while */
-
- /* Verify that the curr_span points to the fastest dim */
- assert(curr_span==iter->hyp.span[fast_dim]);
- } /* end else */
-
- /* Reset the buffer offset */
- for(i=0, loc_off=0; i<ndims; i++)
- loc_off+=(abs_arr[i]+off_arr[i])*slab[i];
- } /* end while */
-
- /* Check for any stored sequences which need to be flushed */
- if(nseq>0) {
- /* Read in the sequence */
- if (H5F_seq_readv(f, dxpl_id, layout, dc_plist, space,
- elmt_size, nseq, seq_len_arr, buf_off_arr, dst/*out*/)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, 0, "read error");
- } /* end if */
-
- /* Increment amount of I/O performed */
- iter->hyp.elmt_left-=nelem;
-
- /* Success! */
- ret_value=nelem;
-
-done:
- if(seq_len_arr!=NULL)
- H5FL_ARR_FREE(size_t,seq_len_arr);
- if(buf_off_arr!=NULL)
- H5FL_ARR_FREE(hsize_t,buf_off_arr);
-
- FUNC_LEAVE (ret_value);
-} /* H5S_hyper_fread() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5S_hyper_fread_opt
- *
- * Purpose: Performs an optimized gather from the file, based on a regular
- * hyperslab (i.e. one which was generated from just one call to
- * H5Sselect_hyperslab).
- *
- * Return: Success: Number of elements copied.
- * Failure: 0
- *
- * Programmer: Quincey Koziol
- * Friday, September 8, 2000
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static hsize_t
-H5S_hyper_fread_opt (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*/)
-{
- size_t *seq_len_arr=NULL; /* Array of sequence lengths */
- hsize_t *buf_off_arr=NULL; /* Array of dataset offsets */
- size_t nseq=0; /* Number of sequence/offsets stored in the arrays */
- size_t tot_buf_size=0; /* Total number of bytes in buffer */
-
- hssize_t offset[H5O_LAYOUT_NDIMS]; /* Offset on disk */
- hsize_t slab[H5O_LAYOUT_NDIMS]; /* Hyperslab size */
- hssize_t wrap[H5O_LAYOUT_NDIMS]; /* Bytes to wrap around at the end of a row */
- hsize_t skip[H5O_LAYOUT_NDIMS]; /* Bytes to skip between blocks */
- hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary block count */
- hsize_t tmp_block[H5O_LAYOUT_NDIMS]; /* Temporary block offset */
- uint8_t *buf=(uint8_t *)_buf; /* Alias for pointer arithmetic */
- const H5S_hyper_dim_t *tdiminfo; /* Local pointer to diminfo information */
- hssize_t fast_dim_start, /* Local copies of fastest changing dimension info */
- fast_dim_offset;
- hsize_t fast_dim_stride, /* Local copies of fastest changing dimension info */
- fast_dim_block,
- fast_dim_buf_off;
- size_t fast_dim_count;
- size_t tot_blk_count; /* Total number of blocks left to output */
- size_t act_blk_count; /* Actual number of blocks to output */
- int fast_dim; /* Rank of the fastest changing dimension for the dataspace */
- int temp_dim; /* Temporary rank holder */
- hsize_t acc; /* Accumulator */
- hsize_t buf_off; /* Current buffer offset for copying memory */
- int i; /* Counters */
- unsigned u; /* Counters */
- int ndims; /* Number of dimensions of dataset */
- size_t actual_read; /* The actual number of elements to read in */
- size_t actual_bytes; /* The actual number of bytes to copy */
- size_t io_left; /* The number of elements left in I/O operation */
- size_t tot_seq; /* The number of sequences filled */
- hsize_t *buf_off_arr_p; /* Pointer into the buffer offset array */
- size_t seq_count; /* Temporary count of sequences left to process */
-#ifndef NO_DUFFS_DEVICE
- size_t duffs_index; /* Counting index for Duff's device */
-#endif /* NO_DUFFS_DEVICE */
- size_t vector_size; /* Value for vector size */
- H5P_genplist_t *plist; /* Property list */
- hsize_t ret_value=0; /* Return value */
-
- FUNC_ENTER_NOINIT(H5S_hyper_fread_opt);
-
- /* Get the hyperslab vector size */
- if(TRUE!=H5P_isa_class(dxpl_id,H5P_DATASET_XFER) || NULL == (plist = H5I_object(dxpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a file access property list");
- if (H5P_get(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((seq_len_arr = H5FL_ARR_ALLOC(size_t,vector_size,0))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate vector I/O array");
- if((buf_off_arr = H5FL_ARR_ALLOC(hsize_t,vector_size,0))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate vector I/O array");
-
- /* Set the rank of the fastest changing dimension */
- fast_dim=file_space->extent.u.simple.rank-1;
- ndims=file_space->extent.u.simple.rank;
-
- /* initialize row sizes for each dimension */
- for(i=(ndims-1),acc=1; i>=0; i--) {
- slab[i]=acc*elmt_size;
- acc*=file_space->extent.u.simple.size[i];
- } /* end for */
-
- /* Set the number of elements left for I/O */
- H5_ASSIGN_OVERFLOW(io_left,nelmts,hsize_t,size_t);
-
- /* Check if we stopped in the middle of a sequence of elements */
- if((file_iter->hyp.off[fast_dim]-file_space->select.sel_info.hslab.diminfo[fast_dim].start)%file_space->select.sel_info.hslab.diminfo[fast_dim].stride!=0 ||
- ((file_iter->hyp.off[fast_dim]!=file_space->select.sel_info.hslab.diminfo[fast_dim].start) && file_space->select.sel_info.hslab.diminfo[fast_dim].stride==1)) {
- hsize_t leftover; /* The number of elements left over from the last sequence */
-
- /* Calculate the number of elements left in the sequence */
- if(file_space->select.sel_info.hslab.diminfo[fast_dim].stride==1)
- leftover=file_space->select.sel_info.hslab.diminfo[fast_dim].block-(file_iter->hyp.off[fast_dim]-file_space->select.sel_info.hslab.diminfo[fast_dim].start);
- else
- leftover=file_space->select.sel_info.hslab.diminfo[fast_dim].block-((file_iter->hyp.off[fast_dim]-file_space->select.sel_info.hslab.diminfo[fast_dim].start)%file_space->select.sel_info.hslab.diminfo[fast_dim].stride);
-
- /* Make certain that we don't read too many */
- H5_CHECK_OVERFLOW(leftover,hsize_t,size_t);
- actual_read=MIN((size_t)leftover,io_left);
- actual_bytes=actual_read*elmt_size;
-
- /* Copy the location of the point to get */
- HDmemcpy(offset, file_iter->hyp.off,ndims*sizeof(hssize_t));
- offset[ndims] = 0;
-
- /* Add in the selection offset */
- for(i=0; i<ndims; i++)
- offset[i] += file_space->select.offset[i];
-
- /* Compute the initial buffer offset */
- for(i=0,buf_off=0; i<ndims; i++)
- buf_off+=offset[i]*slab[i];
-
- /* Read in the rest of the sequence */
- if (H5F_seq_read(f, dxpl_id, layout, dc_plist, file_space,
- elmt_size, actual_bytes, buf_off, buf/*out*/)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, 0, "read error");
-
- /* Increment the offset of the buffer */
- buf+=actual_bytes;
-
- /* Decrement the amount left to read */
- io_left-=actual_read;
-
- /* Advance the point iterator */
- /* If we had enough buffer space to read in the rest of the sequence
- * in the fastest changing dimension, move the iterator offset to
- * the beginning of the next block to read. Otherwise, just advance
- * the iterator in the fastest changing dimension.
- */
- if(actual_read==leftover) {
- /* Move iterator offset to beginning of next sequence in the fastest changing dimension */
- H5S_hyper_iter_next(file_space,file_iter);
- } /* end if */
- else {
- file_iter->hyp.off[fast_dim]+=actual_read; /* whole sequence not read in, just advance fastest dimension offset */
- } /* end if */
- } /* end if */
-
- /* Now that we've cleared the "remainder" of the previous fastest dimension
- * sequence, we must be at the beginning of a sequence, so use the fancy
- * algorithm to compute the offsets and run through as many as possible,
- * until the buffer fills up.
- */
- if(io_left>0) { /* Just in case the "remainder" above filled the buffer */
- /* Compute the arrays to perform I/O on */
- /* Copy the location of the point to get */
- HDmemcpy(offset, file_iter->hyp.off,ndims*sizeof(hssize_t));
- offset[ndims] = 0;
-
- /* Add in the selection offset */
- for(i=0; i<ndims; i++)
- offset[i] += file_space->select.offset[i];
-
- /* Compute the current "counts" for this location */
- for(i=0; i<ndims; i++) {
- if(file_space->select.sel_info.hslab.diminfo[i].stride==1) {
- tmp_count[i] = 0;
- tmp_block[i] = file_iter->hyp.off[i]-file_space->select.sel_info.hslab.diminfo[i].start;
- } /* end if */
- else {
- tmp_count[i] = (file_iter->hyp.off[i]-file_space->select.sel_info.hslab.diminfo[i].start)/file_space->select.sel_info.hslab.diminfo[i].stride;
- tmp_block[i] = (file_iter->hyp.off[i]-file_space->select.sel_info.hslab.diminfo[i].start)%file_space->select.sel_info.hslab.diminfo[i].stride;
- } /* end else */
- } /* end for */
-
- /* Compute the initial buffer offset */
- for(i=0,buf_off=0; i<ndims; i++)
- buf_off+=offset[i]*slab[i];
-
- /* Set the number of elements to read each time */
- H5_ASSIGN_OVERFLOW(actual_read,file_space->select.sel_info.hslab.diminfo[fast_dim].block,hsize_t,size_t);
-
- /* Set the number of actual bytes */
- actual_bytes=actual_read*elmt_size;
-
- /* Set the local copy of the diminfo pointer */
- tdiminfo=file_space->select.sel_info.hslab.diminfo;
-
- /* Set local copies of information for the fastest changing dimension */
- fast_dim_start=tdiminfo[fast_dim].start;
- fast_dim_stride=tdiminfo[fast_dim].stride;
- fast_dim_block=tdiminfo[fast_dim].block;
- fast_dim_buf_off=slab[fast_dim]*fast_dim_stride;
- fast_dim_offset=fast_dim_start+file_space->select.offset[fast_dim];
-
- /* Compute the number of blocks which would fit into the buffer */
- H5_ASSIGN_OVERFLOW(tot_blk_count,(io_left/fast_dim_block),hsize_t,size_t);
-
- /* Compute the amount to wrap at the end of each row */
- for(i=0; i<ndims; i++)
- wrap[i]=(file_space->extent.u.simple.size[i]-(tdiminfo[i].stride*tdiminfo[i].count))*slab[i];
-
- /* Compute the amount to skip between blocks */
- for(i=0; i<ndims; i++)
- skip[i]=(tdiminfo[i].stride-tdiminfo[i].block)*slab[i];
-
- /* Fill the sequence length array (since they will all be the same for optimized hyperslabs) */
- for(u=0; u<vector_size; u++)
- seq_len_arr[u]=actual_bytes;
-
- /* Read in data until an entire sequence can't be read in any longer */
- while(io_left>0) {
- /* Reset copy of number of blocks in fastest dimension */
- H5_ASSIGN_OVERFLOW(fast_dim_count,tdiminfo[fast_dim].count-tmp_count[fast_dim],hsize_t,size_t);
-
- /* Check if this entire row will fit into buffer */
- if(fast_dim_count<=tot_blk_count) {
-
- /* Entire row of blocks fits into buffer */
- act_blk_count=fast_dim_count;
-
- /* Loop over all the blocks in the fastest changing dimension */
- while(fast_dim_count>0) {
- /* Gather the sequence */
-
- /* Compute the number of sequences to fill */
- tot_seq=MIN(vector_size-nseq,fast_dim_count);
-
- /* Get a copy of the number of sequences to fill */
- seq_count=tot_seq;
-
- /* Set the pointer to the correct starting array element */
- buf_off_arr_p=&buf_off_arr[nseq];
-
-#ifdef NO_DUFFS_DEVICE
- /* Fill up the buffer, or finish up the blocks in this dimension */
- while(seq_count>0) {
- /* Store of length & offset */
- /* seq_len_arr[nseq] already has the correct value */
- *buf_off_arr_p++=buf_off;
-
- /* Increment the source offset */
- buf_off+=fast_dim_buf_off;
-
- seq_count--;
- } /* end while */
-#else /* NO_DUFFS_DEVICE */
- duffs_index = (seq_count + 7) / 8;
- switch (seq_count % 8) {
- case 0:
- do
- {
- /* Store of length & offset */
- /* seq_len_arr[nseq] already has the correct value */
- *buf_off_arr_p++=buf_off;
-
- /* Increment the source offset */
- buf_off+=fast_dim_buf_off;
-
- case 7:
- /* Store of length & offset */
- /* seq_len_arr[nseq] already has the correct value */
- *buf_off_arr_p++=buf_off;
-
- /* Increment the source offset */
- buf_off+=fast_dim_buf_off;
-
- case 6:
- /* Store of length & offset */
- /* seq_len_arr[nseq] already has the correct value */
- *buf_off_arr_p++=buf_off;
-
- /* Increment the source offset */
- buf_off+=fast_dim_buf_off;
-
- case 5:
- /* Store of length & offset */
- /* seq_len_arr[nseq] already has the correct value */
- *buf_off_arr_p++=buf_off;
-
- /* Increment the source offset */
- buf_off+=fast_dim_buf_off;
-
- case 4:
- /* Store of length & offset */
- /* seq_len_arr[nseq] already has the correct value */
- *buf_off_arr_p++=buf_off;
-
- /* Increment the source offset */
- buf_off+=fast_dim_buf_off;
-
- case 3:
- /* Store of length & offset */
- /* seq_len_arr[nseq] already has the correct value */
- *buf_off_arr_p++=buf_off;
-
- /* Increment the source offset */
- buf_off+=fast_dim_buf_off;
-
- case 2:
- /* Store of length & offset */
- /* seq_len_arr[nseq] already has the correct value */
- *buf_off_arr_p++=buf_off;
-
- /* Increment the source offset */
- buf_off+=fast_dim_buf_off;
-
- case 1:
- /* Store of length & offset */
- /* seq_len_arr[nseq] already has the correct value */
- *buf_off_arr_p++=buf_off;
-
- /* Increment the source offset */
- buf_off+=fast_dim_buf_off;
-
- } while (--duffs_index > 0);
- } /* end switch */
-#endif /* NO_DUFFS_DEVICE */
-
- /* Increment number of array elements used */
- nseq+=tot_seq;
-
- /* Increment the total number of bytes contained in arrays */
- tot_buf_size += tot_seq*actual_bytes;
-
- /* Decrement number of blocks left */
- fast_dim_count -= tot_seq;
-
- /* If the sequence & offset arrays are full, read them in */
- if(nseq>=vector_size) {
- /* Read in the sequences */
- if (H5F_seq_readv(f, dxpl_id, layout, dc_plist, file_space,
- elmt_size, nseq, seq_len_arr, buf_off_arr, buf/*out*/)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, 0, "read error");
-
- /* Increment the offset of the destination buffer */
- buf+=tot_buf_size;
-
- /* Reset the number of bytes & sequences */
- tot_buf_size=0;
- nseq=0;
- } /* end else */
- } /* end while */
-
- /* Decrement number of elements left */
- io_left -= actual_read*act_blk_count;
-
- /* Decrement number of blocks left */
- tot_blk_count -= act_blk_count;
-
- /* Increment information to reflect block just processed */
- offset[fast_dim]=fast_dim_offset; /* reset the offset in the fastest dimension */
- tmp_count[fast_dim]=0;
-
- /* Increment offset in destination buffer */
- buf_off += wrap[fast_dim];
- } /* end if */
- else {
-
- /* Entire row of blocks doesn't fit into buffer */
- act_blk_count=tot_blk_count;
-
- /* Reduce number of blocks to output */
- fast_dim_count=tot_blk_count;
-
- /* Loop over all the blocks in the fastest changing dimension */
- while(fast_dim_count>0) {
- /* Gather the sequence */
-
- /* Compute the number of sequences to fill */
- tot_seq=MIN(vector_size-nseq,fast_dim_count);
-
- /* Get a copy of the number of sequences to fill */
- seq_count=tot_seq;
-
- /* Set the pointer to the correct starting array element */
- buf_off_arr_p=&buf_off_arr[nseq];
-
- /* Fill up the buffer, or finish up the blocks in this dimension */
- while(seq_count>0) {
- /* Store of length & offset */
- /* seq_len_arr[nseq] already has the correct value */
- *buf_off_arr_p++=buf_off;
-
- /* Increment the source offset */
- buf_off+=fast_dim_buf_off;
-
- seq_count--;
- } /* end while */
-
- /* Increment number of array elements used */
- nseq+=tot_seq;
-
- /* Increment the total number of bytes contained in arrays */
- tot_buf_size += tot_seq*actual_bytes;
-
- /* Decrement number of blocks left */
- fast_dim_count -= tot_seq;
-
- /* If the sequence & offset arrays are full, read them in */
- if(nseq>=vector_size) {
- /* Read in the sequences */
- if (H5F_seq_readv(f, dxpl_id, layout, dc_plist, file_space,
- elmt_size, nseq, seq_len_arr, buf_off_arr, buf/*out*/)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, 0, "read error");
-
- /* Increment the offset of the destination buffer */
- buf+=tot_buf_size;
-
- /* Reset the number of bytes & sequences */
- tot_buf_size=0;
- nseq=0;
- } /* end else */
- } /* end while */
-
- /* Decrement number of elements left */
- io_left -= actual_read*act_blk_count;
-
- /* Decrement number of blocks left */
- tot_blk_count -= act_blk_count;
-
- /* Increment information to reflect block just processed */
- offset[fast_dim]+=(fast_dim_stride*act_blk_count); /* reset the offset in the fastest dimension */
- tmp_count[fast_dim]+=act_blk_count;
-
- /* Handle any leftover, partial blocks in this row */
- if(io_left>0) {
- actual_read=io_left;
- actual_bytes=actual_read*elmt_size;
-
- /* Gather the sequence */
-
- /* Store of length & offset */
- seq_len_arr[nseq]=actual_bytes;
- buf_off_arr[nseq]=buf_off;
-
- /* Increment the total number of bytes contained in arrays */
- tot_buf_size += actual_bytes;
-
- /* Increment the number of sequences in arrays */
- nseq++;
-
- /* If the sequence & offset arrays are full, read them in */
- if(nseq>=vector_size) {
- /* Read in the sequences */
- if (H5F_seq_readv(f, dxpl_id, layout, dc_plist, file_space,
- elmt_size, nseq, seq_len_arr, buf_off_arr, buf/*out*/)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, 0, "read error");
-
- /* Increment the offset of the destination buffer */
- buf+=tot_buf_size;
-
- /* Reset the number of bytes & sequences */
- tot_buf_size=0;
- nseq=0;
- } /* end else */
-
- /* Increment the source offset */
- buf_off+=fast_dim_buf_off;
-
- /* Decrement the number of elements left */
- io_left -= actual_read;
-
- /* Increment buffer correctly */
- offset[fast_dim]+=actual_read;
- } /* end if */
-
- /* don't bother checking slower dimensions */
- assert(tot_blk_count==0);
- assert(io_left==0);
- break;
- } /* end else */
-
- /* Increment the offset and count for the other dimensions */
- temp_dim=fast_dim-1;
- while(temp_dim>=0) {
- /* Move to the next row in the curent dimension */
- offset[temp_dim]++;
- tmp_block[temp_dim]++;
-
- /* If this block is still in the range of blocks to output for the dimension, break out of loop */
- if(tmp_block[temp_dim]<tdiminfo[temp_dim].block)
- break;
- else {
- /* Move to the next block in the current dimension */
- offset[temp_dim]+=(tdiminfo[temp_dim].stride-tdiminfo[temp_dim].block);
- buf_off += skip[temp_dim];
- tmp_block[temp_dim]=0;
- tmp_count[temp_dim]++;
-
- /* If this block is still in the range of blocks to output for the dimension, break out of loop */
- if(tmp_count[temp_dim]<tdiminfo[temp_dim].count)
- break;
- else {
- offset[temp_dim]=tdiminfo[temp_dim].start+file_space->select.offset[temp_dim];
- buf_off += wrap[temp_dim];
- tmp_count[temp_dim]=0; /* reset back to the beginning of the line */
- tmp_block[temp_dim]=0;
- } /* end else */
- } /* end else */
-
- /* Decrement dimension count */
- temp_dim--;
- } /* end while */
- } /* end while */
-
- /* Check for any stored sequences which need to be flushed */
- if(nseq>0) {
- /* Read in the sequence */
- if (H5F_seq_readv(f, dxpl_id, layout, dc_plist, file_space,
- elmt_size, nseq, seq_len_arr, buf_off_arr, buf/*out*/)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, 0, "read error");
- } /* end if */
-
- /* Subtract out the selection offset */
- for(i=0; i<ndims; i++)
- offset[i] -= file_space->select.offset[i];
-
- /* Update the iterator with the location we stopped */
- HDmemcpy(file_iter->hyp.off, offset, ndims*sizeof(hssize_t));
- } /* end if */
-
- /* Decrement the number of elements left in selection */
- file_iter->hyp.elmt_left -= (nelmts-io_left);
-
- /* Set the return value */
- ret_value= (nelmts-io_left);
-
-done:
- if(seq_len_arr!=NULL)
- H5FL_ARR_FREE(size_t,seq_len_arr);
- if(buf_off_arr!=NULL)
- H5FL_ARR_FREE(hsize_t,buf_off_arr);
-
- FUNC_LEAVE (ret_value);
-} /* H5S_hyper_fread_opt() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5S_hyper_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
- * Tuesday, June 16, 1998
- *
- * Modifications:
- * Robb Matzke, 1999-08-03
- * The data transfer properties are passed by ID since that's
- * what the virtual file layer needs.
- *-------------------------------------------------------------------------
- */
-static hsize_t
-H5S_hyper_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*/)
-{
- hsize_t num_read=0; /* number of elements read into buffer */
- herr_t ret_value=SUCCEED;
-
- FUNC_ENTER_NOAPI(H5S_hyper_fgath, 0);
-
- /* Check args */
- assert (f);
- assert (layout);
- assert (elmt_size>0);
- assert (file_space);
- assert (file_iter);
- assert (nelmts>0);
- assert (_buf);
-
- /* Check for the special case of just one H5Sselect_hyperslab call made */
- if(file_space->select.sel_info.hslab.diminfo!=NULL) {
- /* Use optimized call to read in regular hyperslab */
- num_read=H5S_hyper_fread_opt(f,layout,dc_plist,elmt_size,file_space,file_iter,nelmts,dxpl_id,_buf);
- } /* end if */
- else {
- /* Perform generic hyperslab operation */
- num_read=H5S_hyper_fread(f,layout,dc_plist,elmt_size,file_space,file_iter,nelmts,dxpl_id,_buf);
- } /* end else */
-
- FUNC_LEAVE (ret_value==SUCCEED ? num_read : 0);
-} /* H5S_hyper_fgath() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5S_hyper_fwrite
- *
- * Purpose: Performs an optimized scatter to the file, based on a hyperslab
- * span selection.
- *
- * Return: Success: Number of elements copied.
- * Failure: 0
- *
- * Programmer: Quincey Koziol
- * Tuesday, September 12, 2000
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static hsize_t
-H5S_hyper_fwrite (H5F_t *f, const struct H5O_layout_t *layout,
- H5P_genplist_t *dc_plist, size_t elmt_size,
- const H5S_t *space, H5S_sel_iter_t *iter,
- hsize_t nelem, hid_t dxpl_id, const void *_buf)
-{
- const uint8_t *src=(const uint8_t *)_buf; /* Alias for pointer arithmetic */
- H5S_hyper_span_t **ispan; /* Iterator's hyperslab span nodes */
- H5S_hyper_span_t *curr_span; /* Current hyperslab span node */
- hsize_t slab[H5O_LAYOUT_NDIMS]; /* Cumulative size of each dimension in bytes */
- hsize_t acc; /* Accumulator for computing cumulative sizes */
- hssize_t *abs_arr; /* Absolute hyperslab span position */
- hssize_t *off_arr; /* Offset within the dataspace extent */
- int fast_dim; /* Rank of the fastest changing dimension for the dataspace */
- int curr_dim; /* Current dimension being operated on */
- int ndims; /* Number of dimensions of dataset */
- hsize_t loc_off; /* Element offset in the dataspace */
- size_t span_size=0; /* Number of bytes in current span to actually process */
- size_t io_bytes_left; /* Number of bytes left to process */
- int i; /* Index variable */
- size_t *seq_len_arr=NULL; /* Array of sequence lengths */
- hsize_t *buf_off_arr=NULL; /* Array of dataset offsets */
- size_t last_io_bytes_left=0; /* Last I/O bytes left before readv() called */
- size_t nseq=0; /* Number of sequence/offsets stored in the arrays */
- size_t vector_size; /* Value for vector size */
- H5P_genplist_t *plist; /* Property list */
- hssize_t ret_value=FAIL;
-
- FUNC_ENTER_NOINIT(H5S_hyper_fwrite);
-
- /* Check args */
- assert(f);
- assert(layout);
- assert(elmt_size>0);
- assert(space);
- assert(iter);
- assert(nelem>0);
- assert(src);
-
- /* Set the rank of the fastest changing dimension */
- ndims=space->extent.u.simple.rank;
- fast_dim=(ndims-1);
-
- /* Get the pointers to the current span info and span nodes */
- curr_span=iter->hyp.span[fast_dim];
- abs_arr=iter->hyp.off;
- off_arr=space->select.offset;
- ispan=iter->hyp.span;
-
- /* Set the amount of elements to perform I/O on, etc. */
- H5_ASSIGN_OVERFLOW(io_bytes_left,(nelem*elmt_size),hsize_t,size_t);
-
- /* Compute the cumulative size of dataspace dimensions */
- for(i=fast_dim, acc=elmt_size; i>=0; i--) {
- slab[i]=acc;
- acc*=space->extent.u.simple.size[i];
- } /* end for */
-
- /* Set the offset of the first element iterated on */
- for(i=0, loc_off=0; i<ndims; i++)
- /* Compute the sequential element offset */
- loc_off+=(abs_arr[i]+space->select.offset[i])*slab[i];
-
- /* Range check against number of elements left in selection */
- assert(io_bytes_left<=(iter->hyp.elmt_left*elmt_size));
-
- /* Get the hyperslab vector size */
- if(TRUE!=H5P_isa_class(dxpl_id,H5P_DATASET_XFER) || NULL == (plist = H5I_object(dxpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a file access property list");
- if (H5P_get(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((seq_len_arr = H5FL_ARR_ALLOC(size_t,vector_size,0))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate vector I/O array");
- if((buf_off_arr = H5FL_ARR_ALLOC(hsize_t,vector_size,0))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate vector I/O array");
-
- /* Take care of any partial spans leftover from previous I/Os */
- if(abs_arr[fast_dim]!=curr_span->low) {
-
- /* Finish the span in the fastest changing dimension */
-
- /* Compute the number of bytes to attempt in this span */
- H5_ASSIGN_OVERFLOW(span_size,((curr_span->high-abs_arr[fast_dim])+1)*elmt_size,hsize_t,size_t);
-
- /* Check number of bytes against upper bounds allowed */
- if(span_size>io_bytes_left)
- span_size=io_bytes_left;
-
- if (H5F_seq_write(f, dxpl_id, layout, dc_plist, space,
- elmt_size, span_size, loc_off, src)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, 0, "write error");
-
- /* Increment offset in destination */
- src+=span_size;
-
- /* Decrement I/O left to perform */
- io_bytes_left-=span_size;
-
- /* Check if we are done */
- if(io_bytes_left>0) {
- /* Move to next span in fastest changing dimension */
- curr_span=curr_span->next;
-
- if(curr_span!=NULL) {
- /* Move location offset of destination */
- loc_off+=(curr_span->low-abs_arr[fast_dim])*elmt_size;
-
- /* Move iterator for fastest changing dimension */
- abs_arr[fast_dim]=curr_span->low;
- } /* end if */
- } /* end if */
- else {
- abs_arr[fast_dim]+=span_size/elmt_size;
-
- /* Check if we are still within the span */
- if(abs_arr[fast_dim]<=curr_span->high) {
- iter->hyp.span[fast_dim]=curr_span;
-
- goto partial_done; /* finished with partial span */
- } /* end if */
- /* If we walked off that span, advance to the next span */
- else {
- /* Advance span in this dimension */
- curr_span=curr_span->next;
-
- /* Check if we have a valid span in this dimension still */
- if(curr_span!=NULL) {
- /* Reset absolute position */
- abs_arr[fast_dim]=curr_span->low;
- iter->hyp.span[fast_dim]=curr_span;
-
- goto partial_done; /* finished with partial span */
- } /* end if */
- } /* end else */
- } /* end else */
-
- /* Adjust iterator pointers */
-
- if(curr_span==NULL) {
-/* Same as code in main loop */
- /* Start at the next fastest dim */
- curr_dim=fast_dim-1;
-
- /* Work back up through the dimensions */
- while(curr_dim>=0) {
- /* Reset the current span */
- curr_span=iter->hyp.span[curr_dim];
-
- /* Increment absolute position */
- abs_arr[curr_dim]++;
-
- /* Check if we are still within the span */
- if(abs_arr[curr_dim]<=curr_span->high) {
- break;
- } /* end if */
- /* If we walked off that span, advance to the next span */
- else {
- /* Advance span in this dimension */
- curr_span=curr_span->next;
-
- /* Check if we have a valid span in this dimension still */
- if(curr_span!=NULL) {
- /* Reset absolute position */
- abs_arr[curr_dim]=curr_span->low;
-
- break;
- } /* end if */
- else {
- /* If we finished the span list in this dimension, decrement the dimension worked on and loop again */
- curr_dim--;
- } /* end else */
- } /* end else */
- } /* end while */
-
- /* Check if we are finished with the spans in the tree */
- if(curr_dim<0) {
- /* We had better be done with I/O or bad things are going to happen... */
- assert(io_bytes_left==0);
-
- goto partial_done; /* finished with partial span */
- } /* end if */
- else {
- /* Reset the span in the current dimension */
- ispan[curr_dim]=curr_span;
-
- /* Walk back down the iterator positions, reseting them */
- while(curr_dim<fast_dim) {
- assert(curr_span);
- assert(curr_span->down);
- assert(curr_span->down->head);
-
- /* Set the new span for this dimension */
- iter->hyp.span[curr_dim+1]=curr_span->down->head;
-
- /* Advance span down the tree */
- curr_span=curr_span->down->head;
-
- /* Reset the absolute offset for the dim */
- abs_arr[curr_dim+1]=curr_span->low;
-
- /* Increment current dimension */
- curr_dim++;
- } /* end while */
-
- /* Verify that the curr_span points to the fastest dim */
- assert(curr_span==iter->hyp.span[fast_dim]);
- } /* end else */
-
- /* Reset the buffer offset */
- for(i=0, loc_off=0; i<ndims; i++)
- loc_off+=(abs_arr[i]+off_arr[i])*slab[i];
- } /* end if */
- } /* end if */
-
-partial_done: /* Yes, goto's are evil, so sue me... :-) */
- /* Get the number of bytes left to process currently */
- last_io_bytes_left=io_bytes_left;
-
- /* Perform the I/O on the elements, based on the position of the iterator */
- while(io_bytes_left>0) {
- /* Adjust location offset of destination to compensate for initial increment below */
- loc_off-=curr_span->pstride;
-
- /* Loop over all the spans in the fastest changing dimension */
- while(curr_span!=NULL) {
- /* Move location offset of destination */
- loc_off+=curr_span->pstride;
-
- /* Compute the number of elements to attempt in this span */
- H5_ASSIGN_OVERFLOW(span_size,curr_span->nelem,hsize_t,size_t);
-
- /* Check number of elements against upper bounds allowed */
- if(span_size>=io_bytes_left) {
- /* Trim the number of bytes to output */
- span_size=io_bytes_left;
- io_bytes_left=0;
-
-/* COMMON */
- /* Store the I/O information for the span */
- seq_len_arr[nseq]=span_size;
- buf_off_arr[nseq]=loc_off;
-
- /* Increment the number of sequences in arrays */
- nseq++;
-
- /* If the sequence & offset arrays are full, read them in */
- if(nseq>=vector_size) {
- /* Write out the sequences */
- if (H5F_seq_writev(f, dxpl_id, layout, dc_plist, space,
- elmt_size, nseq, seq_len_arr, buf_off_arr, src)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, 0, "write error");
-
- /* Increment the offset of the destination buffer */
- src+=(last_io_bytes_left-io_bytes_left);
-
- /* Keep around the current number of I/O bytes left */
- last_io_bytes_left=io_bytes_left;
- nseq=0;
- } /* end else */
-/* end COMMON */
-
- /* Break out now, we are finished with I/O */
- break;
- } /* end if */
- else {
- /* Decrement I/O left to perform */
- io_bytes_left-=span_size;
-
-/* COMMON */
- /* Store the I/O information for the span */
- seq_len_arr[nseq]=span_size;
- buf_off_arr[nseq]=loc_off;
-
- /* Increment the number of sequences in arrays */
- nseq++;
-
- /* If the sequence & offset arrays are full, read them in */
- if(nseq>=vector_size) {
- /* Write out the sequences */
- if (H5F_seq_writev(f, dxpl_id, layout, dc_plist, space,
- elmt_size, nseq, seq_len_arr, buf_off_arr, src)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, 0, "write error");
-
- /* Increment the offset of the destination buffer */
- src+=(last_io_bytes_left-io_bytes_left);
-
- /* Keep around the current number of I/O bytes left */
- last_io_bytes_left=io_bytes_left;
- nseq=0;
- } /* end else */
-/* end COMMON */
- } /* end else */
-
- /* Move to next span in fastest changing dimension */
- curr_span=curr_span->next;
- } /* end while */
-
- /* Check if we are done */
- if(io_bytes_left==0) {
- abs_arr[fast_dim]=curr_span->low+(span_size/elmt_size);
-
- /* Check if we are still within the span */
- if(abs_arr[fast_dim]<=curr_span->high) {
- iter->hyp.span[fast_dim]=curr_span;
- break;
- } /* end if */
- /* If we walked off that span, advance to the next span */
- else {
- /* Advance span in this dimension */
- curr_span=curr_span->next;
-
- /* Check if we have a valid span in this dimension still */
- if(curr_span!=NULL) {
- /* Reset absolute position */
- abs_arr[fast_dim]=curr_span->low;
- iter->hyp.span[fast_dim]=curr_span;
- break;
- } /* end if */
- } /* end else */
- } /* end if */
-
- /* Adjust iterator pointers */
-
- /* Start at the next fastest dim */
- curr_dim=fast_dim-1;
-
- /* Work back up through the dimensions */
- while(curr_dim>=0) {
- /* Reset the current span */
- curr_span=iter->hyp.span[curr_dim];
-
- /* Increment absolute position */
- abs_arr[curr_dim]++;
-
- /* Check if we are still within the span */
- if(abs_arr[curr_dim]<=curr_span->high) {
- break;
- } /* end if */
- /* If we walked off that span, advance to the next span */
- else {
- /* Advance span in this dimension */
- curr_span=curr_span->next;
-
- /* Check if we have a valid span in this dimension still */
- if(curr_span!=NULL) {
- /* Reset absolute position */
- abs_arr[curr_dim]=curr_span->low;
-
- break;
- } /* end if */
- else {
- /* If we finished the span list in this dimension, decrement the dimension worked on and loop again */
- curr_dim--;
- } /* end else */
- } /* end else */
- } /* end while */
-
- /* Check if we are finished with the spans in the tree */
- if(curr_dim<0) {
- /* We had better be done with I/O or bad things are going to happen... */
- assert(io_bytes_left==0);
- break;
- } /* end if */
- else {
- /* Reset the span in the current dimension */
- ispan[curr_dim]=curr_span;
-
- /* Walk back down the iterator positions, reseting them */
- while(curr_dim<fast_dim) {
- assert(curr_span);
- assert(curr_span->down);
- assert(curr_span->down->head);
-
- /* Set the new span for the next dimension down */
- iter->hyp.span[curr_dim+1]=curr_span->down->head;
-
- /* Advance span down the tree */
- curr_span=curr_span->down->head;
-
- /* Reset the absolute offset for the dim */
- abs_arr[curr_dim+1]=curr_span->low;
-
- /* Increment current dimension */
- curr_dim++;
- } /* end while */
-
- /* Verify that the curr_span points to the fastest dim */
- assert(curr_span==iter->hyp.span[fast_dim]);
- } /* end else */
-
- /* Reset the buffer offset */
- for(i=0, loc_off=0; i<ndims; i++)
- loc_off+=(abs_arr[i]+off_arr[i])*slab[i];
- } /* end while */
-
- /* Check for any stored sequences which need to be flushed */
- if(nseq>0) {
- /* Write out the sequence */
- if (H5F_seq_writev(f, dxpl_id, layout, dc_plist, space,
- elmt_size, nseq, seq_len_arr, buf_off_arr, src)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, 0, "write error");
- } /* end if */
-
- /* Increment amount of I/O performed */
- iter->hyp.elmt_left-=nelem;
-
- /* Success! */
- ret_value=nelem;
-
-done:
- if(seq_len_arr!=NULL)
- H5FL_ARR_FREE(size_t,seq_len_arr);
- if(buf_off_arr!=NULL)
- H5FL_ARR_FREE(hsize_t,buf_off_arr);
-
- FUNC_LEAVE (ret_value);
-} /* H5S_hyper_fwrite() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5S_hyper_fwrite_opt
- *
- * Purpose: Performs an optimized scatter to the file, based on a regular
- * hyperslab (i.e. one which was generated from just one call to
- * H5Sselect_hyperslab).
- *
- * Return: Success: Number of elements copied.
- * Failure: 0
- *
- * Programmer: Quincey Koziol
- * Friday, July 6, 2001
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static hsize_t
-H5S_hyper_fwrite_opt (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)
-{
- size_t *seq_len_arr=NULL; /* Array of sequence lengths */
- hsize_t *buf_off_arr=NULL; /* Array of dataset offsets */
- size_t nseq=0; /* Number of sequence/offsets stored in the arrays */
- size_t tot_buf_size=0; /* Total number of bytes in buffer */
-
- hssize_t offset[H5O_LAYOUT_NDIMS]; /* Offset on disk */
- hsize_t slab[H5O_LAYOUT_NDIMS]; /* Hyperslab size */
- hssize_t wrap[H5O_LAYOUT_NDIMS]; /* Bytes to wrap around at the end of a row */
- hsize_t skip[H5O_LAYOUT_NDIMS]; /* Bytes to skip between blocks */
- hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary block count */
- hsize_t tmp_block[H5O_LAYOUT_NDIMS]; /* Temporary block offset */
- const uint8_t *buf=_buf; /* Alias for pointer arithmetic */
- const H5S_hyper_dim_t *tdiminfo; /* Local pointer to diminfo information */
- hssize_t fast_dim_start, /* Local copies of fastest changing dimension info */
- fast_dim_offset;
- hsize_t fast_dim_stride, /* Local copies of fastest changing dimension info */
- fast_dim_block,
- fast_dim_buf_off;
- size_t fast_dim_count;
- size_t tot_blk_count; /* Total number of blocks left to output */
- size_t act_blk_count; /* Actual number of blocks to output */
- int fast_dim; /* Rank of the fastest changing dimension for the dataspace */
- int temp_dim; /* Temporary rank holder */
- hsize_t acc; /* Accumulator */
- hsize_t buf_off; /* Current buffer offset for copying memory */
- int i; /* Counters */
- unsigned u; /* Counters */
- int ndims; /* Number of dimensions of dataset */
- size_t actual_write; /* The actual number of elements to write out */
- size_t actual_bytes; /* The actual number of bytes to copy */
- size_t io_left; /* The number of elements left in I/O operation */
- size_t tot_seq; /* The number of sequences filled */
- hsize_t *buf_off_arr_p; /* Pointer into the buffer offset array */
- size_t seq_count; /* Temporary count of sequences left to process */
-#ifndef NO_DUFFS_DEVICE
- size_t duffs_index; /* Counting index for Duff's device */
-#endif /* NO_DUFFS_DEVICE */
- size_t vector_size; /* Value for vector size */
- H5P_genplist_t *plist; /* Property list */
- hsize_t ret_value=0; /* Return value */
-
- FUNC_ENTER_NOINIT(H5S_hyper_fwrite_opt);
-
- /* Get the hyperslab vector size */
- if(TRUE!=H5P_isa_class(dxpl_id,H5P_DATASET_XFER) || NULL == (plist = H5I_object(dxpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a file access property list");
- if (H5P_get(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((seq_len_arr = H5FL_ARR_ALLOC(size_t,vector_size,0))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate vector I/O array");
- if((buf_off_arr = H5FL_ARR_ALLOC(hsize_t,vector_size,0))==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "can't allocate vector I/O array");
-
- /* Set the rank of the fastest changing dimension */
- fast_dim=file_space->extent.u.simple.rank-1;
- ndims=file_space->extent.u.simple.rank;
-
- /* initialize row sizes for each dimension */
- for(i=(ndims-1),acc=1; i>=0; i--) {
- slab[i]=acc*elmt_size;
- acc*=file_space->extent.u.simple.size[i];
- } /* end for */
-
- /* Set the number of elements left for I/O */
- H5_ASSIGN_OVERFLOW(io_left,nelmts,hsize_t,size_t);
-
- /* Check if we stopped in the middle of a sequence of elements */
- if((file_iter->hyp.off[fast_dim]-file_space->select.sel_info.hslab.diminfo[fast_dim].start)%file_space->select.sel_info.hslab.diminfo[fast_dim].stride!=0 ||
- ((file_iter->hyp.off[fast_dim]!=file_space->select.sel_info.hslab.diminfo[fast_dim].start) && file_space->select.sel_info.hslab.diminfo[fast_dim].stride==1)) {
- hsize_t leftover; /* The number of elements left over from the last sequence */
-
- /* Calculate the number of elements left in the sequence */
- if(file_space->select.sel_info.hslab.diminfo[fast_dim].stride==1)
- leftover=file_space->select.sel_info.hslab.diminfo[fast_dim].block-(file_iter->hyp.off[fast_dim]-file_space->select.sel_info.hslab.diminfo[fast_dim].start);
- else
- leftover=file_space->select.sel_info.hslab.diminfo[fast_dim].block-((file_iter->hyp.off[fast_dim]-file_space->select.sel_info.hslab.diminfo[fast_dim].start)%file_space->select.sel_info.hslab.diminfo[fast_dim].stride);
-
- /* Make certain that we don't write too many */
- H5_CHECK_OVERFLOW(leftover,hsize_t,size_t);
- actual_write=MIN((size_t)leftover,io_left);
- actual_bytes=actual_write*elmt_size;
-
- /* Copy the location of the point to get */
- HDmemcpy(offset, file_iter->hyp.off,ndims*sizeof(hssize_t));
- offset[ndims] = 0;
-
- /* Add in the selection offset */
- for(i=0; i<ndims; i++)
- offset[i] += file_space->select.offset[i];
-
- /* Compute the initial buffer offset */
- for(i=0,buf_off=0; i<ndims; i++)
- buf_off+=offset[i]*slab[i];
-
- /* Write out the rest of the sequence */
- if (H5F_seq_write(f, dxpl_id, layout, dc_plist, file_space,
- elmt_size, actual_bytes, buf_off, buf)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, 0, "write error");
-
- /* Increment the offset of the buffer */
- buf+=actual_bytes;
-
- /* Decrement the amount left to write */
- io_left-=actual_write;
-
- /* Advance the point iterator */
- /* If we had enough buffer space to write out the rest of the sequence
- * in the fastest changing dimension, move the iterator offset to
- * the beginning of the next block to write. Otherwise, just advance
- * the iterator in the fastest changing dimension.
- */
- if(actual_write==leftover) {
- /* Move iterator offset to beginning of next sequence in the fastest changing dimension */
- H5S_hyper_iter_next(file_space,file_iter);
- } /* end if */
- else {
- file_iter->hyp.off[fast_dim]+=actual_write; /* whole sequence not written out, just advance fastest dimension offset */
- } /* end if */
- } /* end if */
-
- /* Now that we've cleared the "remainder" of the previous fastest dimension
- * sequence, we must be at the beginning of a sequence, so use the fancy
- * algorithm to compute the offsets and run through as many as possible,
- * until the buffer runs dry.
- */
- if(io_left>0) { /* Just in case the "remainder" above emptied the buffer */
- /* Compute the arrays to perform I/O on */
- /* Copy the location of the point to get */
- HDmemcpy(offset, file_iter->hyp.off,ndims*sizeof(hssize_t));
- offset[ndims] = 0;
-
- /* Add in the selection offset */
- for(i=0; i<ndims; i++)
- offset[i] += file_space->select.offset[i];
-
- /* Compute the current "counts" for this location */
- for(i=0; i<ndims; i++) {
- if(file_space->select.sel_info.hslab.diminfo[i].stride==1) {
- tmp_count[i] = 0;
- tmp_block[i] = file_iter->hyp.off[i]-file_space->select.sel_info.hslab.diminfo[i].start;
- } /* end if */
- else {
- tmp_count[i] = (file_iter->hyp.off[i]-file_space->select.sel_info.hslab.diminfo[i].start)/file_space->select.sel_info.hslab.diminfo[i].stride;
- tmp_block[i] = (file_iter->hyp.off[i]-file_space->select.sel_info.hslab.diminfo[i].start)%file_space->select.sel_info.hslab.diminfo[i].stride;
- } /* end else */
- } /* end for */
-
- /* Compute the initial buffer offset */
- for(i=0,buf_off=0; i<ndims; i++)
- buf_off+=offset[i]*slab[i];
-
- /* Set the number of elements to write each time */
- H5_ASSIGN_OVERFLOW(actual_write,file_space->select.sel_info.hslab.diminfo[fast_dim].block,hsize_t,size_t);
-
- /* Set the number of actual bytes */
- actual_bytes=actual_write*elmt_size;
-
- /* Set the local copy of the diminfo pointer */
- tdiminfo=file_space->select.sel_info.hslab.diminfo;
-
- /* Set local copies of information for the fastest changing dimension */
- fast_dim_start=tdiminfo[fast_dim].start;
- fast_dim_stride=tdiminfo[fast_dim].stride;
- fast_dim_block=tdiminfo[fast_dim].block;
- fast_dim_buf_off=slab[fast_dim]*fast_dim_stride;
- fast_dim_offset=fast_dim_start+file_space->select.offset[fast_dim];
-
- /* Compute the number of blocks which would fit into the buffer */
- H5_ASSIGN_OVERFLOW(tot_blk_count,(io_left/fast_dim_block),hsize_t,size_t);
-
- /* Compute the amount to wrap at the end of each row */
- for(i=0; i<ndims; i++)
- wrap[i]=(file_space->extent.u.simple.size[i]-(tdiminfo[i].stride*tdiminfo[i].count))*slab[i];
-
- /* Compute the amount to skip between blocks */
- for(i=0; i<ndims; i++)
- skip[i]=(tdiminfo[i].stride-tdiminfo[i].block)*slab[i];
-
- /* Fill the sequence length array (since they will all be the same for optimized hyperslabs) */
- for(u=0; u<vector_size; u++)
- seq_len_arr[u]=actual_bytes;
-
- /* Write out data until an entire sequence can't be written any longer */
- while(io_left>0) {
- /* Reset copy of number of blocks in fastest dimension */
- H5_ASSIGN_OVERFLOW(fast_dim_count,tdiminfo[fast_dim].count-tmp_count[fast_dim],hsize_t,size_t);
-
- /* Check if this entire row will fit into buffer */
- if(fast_dim_count<=tot_blk_count) {
-
- /* Entire row of blocks fits into buffer */
- act_blk_count=fast_dim_count;
-
- /* Loop over all the blocks in the fastest changing dimension */
- while(fast_dim_count>0) {
- /* Gather the sequence */
-
- /* Compute the number of sequences to fill */
- tot_seq=MIN(vector_size-nseq,fast_dim_count);
-
- /* Get a copy of the number of sequences to fill */
- seq_count=tot_seq;
-
- /* Set the pointer to the correct starting array element */
- buf_off_arr_p=&buf_off_arr[nseq];
-
-#ifdef NO_DUFFS_DEVICE
- /* Fill up the buffer, or finish up the blocks in this dimension */
- while(seq_count>0) {
- /* Store of length & offset */
- /* seq_len_arr[nseq] already has the correct value */
- *buf_off_arr_p++=buf_off;
-
- /* Increment the source offset */
- buf_off+=fast_dim_buf_off;
-
- seq_count--;
- } /* end while */
-#else /* NO_DUFFS_DEVICE */
- duffs_index = (seq_count + 7) / 8;
- switch (seq_count % 8) {
- case 0:
- do
- {
- /* Store of length & offset */
- /* seq_len_arr[nseq] already has the correct value */
- *buf_off_arr_p++=buf_off;
-
- /* Increment the source offset */
- buf_off+=fast_dim_buf_off;
-
- case 7:
- /* Store of length & offset */
- /* seq_len_arr[nseq] already has the correct value */
- *buf_off_arr_p++=buf_off;
-
- /* Increment the source offset */
- buf_off+=fast_dim_buf_off;
-
- case 6:
- /* Store of length & offset */
- /* seq_len_arr[nseq] already has the correct value */
- *buf_off_arr_p++=buf_off;
-
- /* Increment the source offset */
- buf_off+=fast_dim_buf_off;
-
- case 5:
- /* Store of length & offset */
- /* seq_len_arr[nseq] already has the correct value */
- *buf_off_arr_p++=buf_off;
-
- /* Increment the source offset */
- buf_off+=fast_dim_buf_off;
-
- case 4:
- /* Store of length & offset */
- /* seq_len_arr[nseq] already has the correct value */
- *buf_off_arr_p++=buf_off;
-
- /* Increment the source offset */
- buf_off+=fast_dim_buf_off;
-
- case 3:
- /* Store of length & offset */
- /* seq_len_arr[nseq] already has the correct value */
- *buf_off_arr_p++=buf_off;
-
- /* Increment the source offset */
- buf_off+=fast_dim_buf_off;
-
- case 2:
- /* Store of length & offset */
- /* seq_len_arr[nseq] already has the correct value */
- *buf_off_arr_p++=buf_off;
-
- /* Increment the source offset */
- buf_off+=fast_dim_buf_off;
-
- case 1:
- /* Store of length & offset */
- /* seq_len_arr[nseq] already has the correct value */
- *buf_off_arr_p++=buf_off;
-
- /* Increment the source offset */
- buf_off+=fast_dim_buf_off;
-
- } while (--duffs_index > 0);
- } /* end switch */
-#endif /* NO_DUFFS_DEVICE */
-
- /* Increment number of array elements used */
- nseq+=tot_seq;
-
- /* Increment the total number of bytes contained in arrays */
- tot_buf_size += tot_seq*actual_bytes;
-
- /* Decrement number of blocks left */
- fast_dim_count -= tot_seq;
-
- /* If the sequence & offset arrays are full, write them out */
- if(nseq>=vector_size) {
- /* Write out the sequences */
- if (H5F_seq_writev(f, dxpl_id, layout, dc_plist, file_space,
- elmt_size, nseq, seq_len_arr, buf_off_arr, buf)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, 0, "write error");
-
- /* Increment the offset of the destination buffer */
- buf+=tot_buf_size;
-
- /* Reset the number of bytes & sequences */
- tot_buf_size=0;
- nseq=0;
- } /* end else */
- } /* end while */
-
- /* Decrement number of elements left */
- io_left -= actual_write*act_blk_count;
-
- /* Decrement number of blocks left */
- tot_blk_count -= act_blk_count;
-
- /* Increment information to reflect block just processed */
- offset[fast_dim]=fast_dim_offset; /* reset the offset in the fastest dimension */
- tmp_count[fast_dim]=0;
-
- /* Increment offset in destination buffer */
- buf_off += wrap[fast_dim];
- } /* end if */
- else {
-
- /* Entire row of blocks doesn't fit into buffer */
- act_blk_count=tot_blk_count;
-
- /* Reduce number of blocks to output */
- fast_dim_count=tot_blk_count;
-
- /* Loop over all the blocks in the fastest changing dimension */
- while(fast_dim_count>0) {
- /* Gather the sequence */
-
- /* Compute the number of sequences to fill */
- tot_seq=MIN(vector_size-nseq,fast_dim_count);
-
- /* Get a copy of the number of sequences to fill */
- seq_count=tot_seq;
-
- /* Set the pointer to the correct starting array element */
- buf_off_arr_p=&buf_off_arr[nseq];
-
- /* Fill up the buffer, or finish up the blocks in this dimension */
- while(seq_count>0) {
- /* Store of length & offset */
- /* seq_len_arr[nseq] already has the correct value */
- *buf_off_arr_p++=buf_off;
-
- /* Increment the source offset */
- buf_off+=fast_dim_buf_off;
-
- seq_count--;
- } /* end while */
-
- /* Increment number of array elements used */
- nseq+=tot_seq;
-
- /* Increment the total number of bytes contained in arrays */
- tot_buf_size += tot_seq*actual_bytes;
-
- /* Decrement number of blocks left */
- fast_dim_count -= tot_seq;
-
- /* If the sequence & offset arrays are full, write them out */
- if(nseq>=vector_size) {
- /* Write out the sequences */
- if (H5F_seq_writev(f, dxpl_id, layout, dc_plist, file_space,
- elmt_size, nseq, seq_len_arr, buf_off_arr, buf)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, 0, "write error");
-
- /* Increment the offset of the destination buffer */
- buf+=tot_buf_size;
-
- /* Reset the number of bytes & sequences */
- tot_buf_size=0;
- nseq=0;
- } /* end else */
- } /* end while */
-
- /* Decrement number of elements left */
- io_left -= actual_write*act_blk_count;
-
- /* Decrement number of blocks left */
- tot_blk_count -= act_blk_count;
-
- /* Increment information to reflect block just processed */
- offset[fast_dim]+=(fast_dim_stride*act_blk_count); /* reset the offset in the fastest dimension */
- tmp_count[fast_dim]+=act_blk_count;
-
- /* Handle any leftover, partial blocks in this row */
- if(io_left>0) {
- actual_write=io_left;
- actual_bytes=actual_write*elmt_size;
-
- /* Gather the sequence */
-
- /* Store of length & offset */
- seq_len_arr[nseq]=actual_bytes;
- buf_off_arr[nseq]=buf_off;
-
- /* Increment the total number of bytes contained in arrays */
- tot_buf_size += actual_bytes;
-
- /* Increment the number of sequences in arrays */
- nseq++;
-
- /* If the sequence & offset arrays are full, write them out */
- if(nseq>=vector_size) {
- /* Write out the sequences */
- if (H5F_seq_writev(f, dxpl_id, layout, dc_plist, file_space,
- elmt_size, nseq, seq_len_arr, buf_off_arr, buf)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, 0, "write error");
-
- /* Increment the offset of the destination buffer */
- buf+=tot_buf_size;
-
- /* Reset the number of bytes & sequences */
- tot_buf_size=0;
- nseq=0;
- } /* end else */
-
- /* Increment the source offset */
- buf_off+=fast_dim_buf_off;
-
- /* Decrement the number of elements left */
- io_left -= actual_write;
-
- /* Increment buffer correctly */
- offset[fast_dim]+=actual_write;
- } /* end if */
-
- /* don't bother checking slower dimensions */
- assert(tot_blk_count==0);
- assert(io_left==0);
- break;
- } /* end else */
-
- /* Increment the offset and count for the other dimensions */
- temp_dim=fast_dim-1;
- while(temp_dim>=0) {
- /* Move to the next row in the curent dimension */
- offset[temp_dim]++;
- tmp_block[temp_dim]++;
-
- /* If this block is still in the range of blocks to output for the dimension, break out of loop */
- if(tmp_block[temp_dim]<tdiminfo[temp_dim].block)
- break;
- else {
- /* Move to the next block in the current dimension */
- offset[temp_dim]+=(tdiminfo[temp_dim].stride-tdiminfo[temp_dim].block);
- buf_off += skip[temp_dim];
- tmp_block[temp_dim]=0;
- tmp_count[temp_dim]++;
-
- /* If this block is still in the range of blocks to output for the dimension, break out of loop */
- if(tmp_count[temp_dim]<tdiminfo[temp_dim].count)
- break;
- else {
- offset[temp_dim]=tdiminfo[temp_dim].start+file_space->select.offset[temp_dim];
- buf_off += wrap[temp_dim];
- tmp_count[temp_dim]=0; /* reset back to the beginning of the line */
- tmp_block[temp_dim]=0;
- } /* end else */
- } /* end else */
-
- /* Decrement dimension count */
- temp_dim--;
- } /* end while */
- } /* end while */
-
- /* Check for any stored sequences which need to be flushed */
- if(nseq>0) {
- /* Write out the sequence */
- if (H5F_seq_writev(f, dxpl_id, layout, dc_plist, file_space,
- elmt_size, nseq, seq_len_arr, buf_off_arr, buf)<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, 0, "write error");
- } /* end if */
-
- /* Subtract out the selection offset */
- for(i=0; i<ndims; i++)
- offset[i] -= file_space->select.offset[i];
-
- /* Update the iterator with the location we stopped */
- HDmemcpy(file_iter->hyp.off, offset, ndims*sizeof(hssize_t));
- } /* end if */
-
- /* Decrement the number of elements left in selection */
- file_iter->hyp.elmt_left -= (nelmts-io_left);
-
- ret_value= (nelmts-io_left);
-
-done:
- if(seq_len_arr!=NULL)
- H5FL_ARR_FREE(size_t,seq_len_arr);
- if(buf_off_arr!=NULL)
- H5FL_ARR_FREE(hsize_t,buf_off_arr);
-
- FUNC_LEAVE (ret_value);
-} /* H5S_hyper_fwrite_opt() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5S_hyper_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
- * Tuesday, June 16, 1998
- *
- * Modifications:
- * Robb Matzke, 1999-08-03
- * The data transfer properties are passed by ID since that's
- * what the virtual file layer needs.
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5S_hyper_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)
-{
- hsize_t num_written=0; /* number of elements read into buffer */
- herr_t ret_value=SUCCEED;
-
- FUNC_ENTER_NOAPI(H5S_hyper_fscat, 0);
-
- /* Check args */
- assert (f);
- assert (layout);
- assert (elmt_size>0);
- assert (file_space);
- assert (file_iter);
- assert (nelmts>0);
- assert (_buf);
-
- /* Check for the special case of just one H5Sselect_hyperslab call made */
- if(file_space->select.sel_info.hslab.diminfo!=NULL) {
- /* Use optimized call to write out regular hyperslab */
- num_written=H5S_hyper_fwrite_opt(f,layout,dc_plist,elmt_size,file_space,file_iter,nelmts,dxpl_id,_buf);
- } /* end if */
- else {
- /* Perform generic hyperslab operation */
- num_written=H5S_hyper_fwrite(f,layout,dc_plist,elmt_size,file_space,file_iter,nelmts,dxpl_id,_buf);
- } /* end else */
-
- FUNC_LEAVE (ret_value==FAIL ? ret_value : (num_written >0) ? SUCCEED : FAIL);
-} /* H5S_hyper_fscat() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5S_hyper_mread
- *
- * Purpose: Performs an optimized gather from a memory buffer, based on a
- * hyperslab span selection.
- *
- * Return: Success: Number of elements copied.
- * Failure: 0
- *
- * Programmer: Quincey Koziol
- * Tuesday, September 12, 2000
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static hssize_t
-H5S_hyper_mread (const void *_buf, size_t elmt_size, const H5S_t *space,
- H5S_sel_iter_t *iter, hsize_t nelem, void *_tconv_buf/*out*/)
-{
- const uint8_t *src=(const uint8_t *)_buf; /* Alias for pointer arithmetic */
- const uint8_t *tmp_src; /* Alias for pointer arithmetic */
- uint8_t *dst=(uint8_t *)_tconv_buf; /* Alias for pointer arithmetic */
- H5S_hyper_span_t **ispan; /* Iterator's hyperslab span nodes */
- H5S_hyper_span_t *curr_span; /* Current hyperslab span node */
- hsize_t slab[H5O_LAYOUT_NDIMS]; /* Cumulative size of each dimension in bytes */
- hsize_t acc; /* Accumulator for computing cumulative sizes */
- hssize_t *abs_arr; /* Absolute hyperslab span position */
- hssize_t *off_arr; /* Offset within the dataspace extent */
- int fast_dim; /* Rank of the fastest changing dimension for the dataspace */
- int curr_dim; /* Current dimension being operated on */
- int ndims; /* Number of dimensions of dataset */
- size_t span_size=0; /* Number of bytes in current span to actually process */
- size_t io_bytes_left; /* Number of bytes left to process */
- int i; /* Index variable */
- hssize_t ret_value=FAIL;
-
- FUNC_ENTER_NOINIT(H5S_hyper_mread);
-
- /* Check args */
- assert(src);
- assert(elmt_size>0);
- assert(space);
- assert(iter);
- assert(nelem>0);
- assert(dst);
-
- /* Set the rank of the fastest changing dimension */
- ndims=space->extent.u.simple.rank;
- fast_dim=(ndims-1);
-
- /* Get the pointers to the current span info and span nodes */
- curr_span=iter->hyp.span[fast_dim];
- abs_arr=iter->hyp.off;
- off_arr=space->select.offset;
- ispan=iter->hyp.span;
-
- /* Set the amount of elements to perform I/O on, etc. */
- H5_ASSIGN_OVERFLOW(io_bytes_left,nelem*elmt_size,hsize_t,size_t);
-
- /* Compute the cumulative size of dataspace dimensions */
- for(i=fast_dim, acc=elmt_size; i>=0; i--) {
- slab[i]=acc;
- acc*=space->extent.u.simple.size[i];
- } /* end for */
-
- /* Set the offset of the first element iterated on */
- for(i=0, tmp_src=src; i<ndims; i++)
- /* Compute the sequential element offset */
- tmp_src+=(abs_arr[i]+space->select.offset[i])*slab[i];
-
- /* Range check against number of elements left in selection */
- assert(io_bytes_left<=(iter->hyp.elmt_left*elmt_size));
-
- /* Take care of any partial spans leftover from previous I/Os */
- if(abs_arr[fast_dim]!=curr_span->low) {
-
- /* Finish the span in the fastest changing dimension */
-
- /* Compute the number of bytes to attempt in this span */
- H5_ASSIGN_OVERFLOW(span_size,((curr_span->high-abs_arr[fast_dim])+1)*elmt_size,hsize_t,size_t);
-
- /* Check number of elements against upper bounds allowed */
- if(span_size>io_bytes_left)
- span_size=io_bytes_left;
-
- HDmemcpy(dst,tmp_src,span_size);
-
- /* Increment offset in destination */
- dst+=span_size;
-
- /* Decrement I/O left to perform */
- io_bytes_left-=span_size;
-
- /* Check if we are done */
- if(io_bytes_left>0) {
- /* Move to next span in fastest changing dimension */
- curr_span=curr_span->next;
-
- if(curr_span!=NULL) {
- /* Move location offset of destination */
- tmp_src+=(curr_span->low-abs_arr[fast_dim])*elmt_size;
-
- /* Move iterator for fastest changing dimension */
- abs_arr[fast_dim]=curr_span->low;
- } /* end if */
- } /* end if */
- else {
- abs_arr[fast_dim]+=span_size/elmt_size;
-
- /* Check if we are still within the span */
- if(abs_arr[fast_dim]<=curr_span->high) {
- iter->hyp.span[fast_dim]=curr_span;
-
- goto partial_done; /* finished with partial span */
- } /* end if */
- /* If we walked off that span, advance to the next span */
- else {
- /* Advance span in this dimension */
- curr_span=curr_span->next;
-
- /* Check if we have a valid span in this dimension still */
- if(curr_span!=NULL) {
- /* Reset absolute position */
- abs_arr[fast_dim]=curr_span->low;
- iter->hyp.span[fast_dim]=curr_span;
-
- goto partial_done; /* finished with partial span */
- } /* end if */
- } /* end else */
- } /* end else */
-
- /* Adjust iterator pointers */
-
- if(curr_span==NULL) {
-/* Same as code in main loop */
- /* Start at the next fastest dim */
- curr_dim=fast_dim-1;
-
- /* Work back up through the dimensions */
- while(curr_dim>=0) {
- /* Reset the current span */
- curr_span=iter->hyp.span[curr_dim];
-
- /* Increment absolute position */
- abs_arr[curr_dim]++;
-
- /* Check if we are still within the span */
- if(abs_arr[curr_dim]<=curr_span->high) {
- break;
- } /* end if */
- /* If we walked off that span, advance to the next span */
- else {
- /* Advance span in this dimension */
- curr_span=curr_span->next;
-
- /* Check if we have a valid span in this dimension still */
- if(curr_span!=NULL) {
- /* Reset absolute position */
- abs_arr[curr_dim]=curr_span->low;
-
- break;
- } /* end if */
- else {
- /* If we finished the span list in this dimension, decrement the dimension worked on and loop again */
- curr_dim--;
- } /* end else */
- } /* end else */
- } /* end while */
-
- /* Check if we are finished with the spans in the tree */
- if(curr_dim<0) {
- /* We had better be done with I/O or bad things are going to happen... */
- assert(io_bytes_left==0);
-
- goto partial_done; /* finished with partial span */
- } /* end if */
- else {
- /* Reset the span in the current dimension */
- ispan[curr_dim]=curr_span;
-
- /* Walk back down the iterator positions, reseting them */
- while(curr_dim<fast_dim) {
- assert(curr_span);
- assert(curr_span->down);
- assert(curr_span->down->head);
-
- /* Set the new span for this dimension */
- iter->hyp.span[curr_dim+1]=curr_span->down->head;
-
- /* Advance span down the tree */
- curr_span=curr_span->down->head;
-
- /* Reset the absolute offset for the dim */
- abs_arr[curr_dim+1]=curr_span->low;
-
- /* Increment current dimension */
- curr_dim++;
- } /* end while */
-
- /* Verify that the curr_span points to the fastest dim */
- assert(curr_span==iter->hyp.span[fast_dim]);
- } /* end else */
-
- /* Reset the buffer offset */
- for(i=0, tmp_src=src; i<ndims; i++)
- tmp_src+=(abs_arr[i]+off_arr[i])*slab[i];
- } /* end if */
- } /* end if */
-
-partial_done: /* Yes, goto's are evil, so sue me... :-) */
-
- /* Perform the I/O on the elements, based on the position of the iterator */
- while(io_bytes_left>0) {
- /* Adjust buffer offset of source to compensate for initial increment below */
- tmp_src-=curr_span->pstride;
-
- /* Loop over all the spans in the fastest changing dimension */
- while(curr_span!=NULL) {
- /* Move buffer offset of source */
- tmp_src+=curr_span->pstride;
-
- /* Compute the number of elements to attempt in this span */
- H5_ASSIGN_OVERFLOW(span_size,curr_span->nelem,hsize_t,size_t);
-
- /* Check number of elements against upper bounds allowed */
- if(span_size>=io_bytes_left) {
- /* Trim the number of bytes to output */
- span_size=io_bytes_left;
- io_bytes_left=0;
-
-/* COMMON */
- /* "Read" the data from the source buffer */
- HDmemcpy(dst,tmp_src,span_size);
-
- /* Increment offset in destination */
- dst+=span_size;
-/* end COMMON */
-
- /* Break out now, we are finished with I/O */
- break;
- } /* end if */
- else {
- /* Decrement I/O left to perform */
- io_bytes_left-=span_size;
-
-/* COMMON */
- /* "Read" the data from the source buffer */
- HDmemcpy(dst,tmp_src,span_size);
-
- /* Increment offset in destination */
- dst+=span_size;
-/* end COMMON */
- } /* end else */
-
- /* Move to next span in fastest changing dimension */
- curr_span=curr_span->next;
- } /* end while */
-
- /* Check if we are done */
- if(io_bytes_left==0) {
- abs_arr[fast_dim]=curr_span->low+(span_size/elmt_size);
-
- /* Check if we are still within the span */
- if(abs_arr[fast_dim]<=curr_span->high) {
- iter->hyp.span[fast_dim]=curr_span;
- break;
- } /* end if */
- /* If we walked off that span, advance to the next span */
- else {
- /* Advance span in this dimension */
- curr_span=curr_span->next;
-
- /* Check if we have a valid span in this dimension still */
- if(curr_span!=NULL) {
- /* Reset absolute position */
- abs_arr[fast_dim]=curr_span->low;
- iter->hyp.span[fast_dim]=curr_span;
- break;
- } /* end if */
- } /* end else */
- } /* end if */
-
- /* Adjust iterator pointers */
-
- /* Start at the next fastest dim */
- curr_dim=fast_dim-1;
-
- /* Work back up through the dimensions */
- while(curr_dim>=0) {
- /* Reset the current span */
- curr_span=iter->hyp.span[curr_dim];
-
- /* Increment absolute position */
- abs_arr[curr_dim]++;
-
- /* Check if we are still within the span */
- if(abs_arr[curr_dim]<=curr_span->high) {
- break;
- } /* end if */
- /* If we walked off that span, advance to the next span */
- else {
- /* Advance span in this dimension */
- curr_span=curr_span->next;
-
- /* Check if we have a valid span in this dimension still */
- if(curr_span!=NULL) {
- /* Reset absolute position */
- abs_arr[curr_dim]=curr_span->low;
-
- break;
- } /* end if */
- else {
- /* If we finished the span list in this dimension, decrement the dimension worked on and loop again */
- curr_dim--;
- } /* end else */
- } /* end else */
- } /* end while */
-
- /* Check if we are finished with the spans in the tree */
- if(curr_dim<0) {
- /* We had better be done with I/O or bad things are going to happen... */
- assert(io_bytes_left==0);
- break;
- } /* end if */
- else {
- /* Reset the span in the current dimension */
- ispan[curr_dim]=curr_span;
-
- /* Walk back down the iterator positions, reseting them */
- while(curr_dim<fast_dim) {
- assert(curr_span);
- assert(curr_span->down);
- assert(curr_span->down->head);
-
- /* Set the new span for the next dimension down */
- iter->hyp.span[curr_dim+1]=curr_span->down->head;
-
- /* Advance span down the tree */
- curr_span=curr_span->down->head;
-
- /* Reset the absolute offset for the dim */
- abs_arr[curr_dim+1]=curr_span->low;
-
- /* Increment current dimension */
- curr_dim++;
- } /* end while */
-
- /* Verify that the curr_span points to the fastest dim */
- assert(curr_span==iter->hyp.span[fast_dim]);
- } /* end else */
-
- /* Reset the buffer offset */
- for(i=0, tmp_src=src; i<ndims; i++)
- tmp_src+=(abs_arr[i]+off_arr[i])*slab[i];
- } /* end while */
-
- /* Increment amount of I/O performed */
- iter->hyp.elmt_left-=nelem;
-
- /* Success! */
- ret_value=nelem;
-
-#ifdef LATER
-done:
-#endif /* LATER */
- FUNC_LEAVE (ret_value);
-} /* end H5S_hyper_mread() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5S_hyper_mread_opt
- *
- * Purpose: Performs an optimized gather from a memory buffer, based on a
- * regular hyperslab (i.e. one which was generated from just one call to
- * H5Sselect_hyperslab).
- *
- * Return: Success: Number of elements copied.
- * Failure: 0
- *
- * Programmer: Quincey Koziol
- * Tuesday, September 12, 2000
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static hsize_t
-H5S_hyper_mread_opt (const void *_buf, size_t elmt_size,
- const H5S_t *mem_space, H5S_sel_iter_t *mem_iter,
- hsize_t nelmts, void *_tconv_buf/*out*/)
-{
- hsize_t mem_size[H5O_LAYOUT_NDIMS]; /* Size of the source buffer */
- hsize_t slab[H5O_LAYOUT_NDIMS]; /* Hyperslab size */
- hssize_t wrap[H5O_LAYOUT_NDIMS]; /* Bytes to wrap around at the end of a row */
- hsize_t skip[H5O_LAYOUT_NDIMS]; /* Bytes to skip between blocks */
- hssize_t offset[H5O_LAYOUT_NDIMS]; /* Offset on disk */
- hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary block count */
- hsize_t tmp_block[H5O_LAYOUT_NDIMS]; /* Temporary block offset */
- const uint8_t *src=(const uint8_t *)_buf; /* Alias for pointer arithmetic */
- uint8_t *dst=(uint8_t *)_tconv_buf; /* Alias for pointer arithmetic */
- const H5S_hyper_dim_t *tdiminfo; /* Temporary pointer to diminfo information */
- hssize_t fast_dim_start, /* Local copies of fastest changing dimension info */
- fast_dim_offset;
- hsize_t fast_dim_stride, /* Local copies of fastest changing dimension info */
- fast_dim_block;
- size_t fast_dim_count;
- size_t tot_blk_count; /* Total number of blocks left to output */
- size_t act_blk_count; /* Actual number of blocks to output */
- size_t fast_dim_buf_off; /* Local copy of amount to move fastest dimension buffer offset */
- int fast_dim; /* Rank of the fastest changing dimension for the dataspace */
- int temp_dim; /* Temporary rank holder */
- hsize_t acc; /* Accumulator */
- int i; /* Counters */
- int ndims; /* Number of dimensions of dataset */
- size_t actual_read; /* The actual number of elements to read in */
- size_t actual_bytes; /* The actual number of bytes to copy */
- size_t io_left; /* The number of elements left in I/O operation */
-#ifndef NO_DUFFS_DEVICE
- size_t duffs_index; /* Counting index for Duff's device */
-#endif /* NO_DUFFS_DEVICE */
-
- FUNC_ENTER_NOINIT(H5S_hyper_mread_opt);
-
- /* Set the aliases for a few important dimension ranks */
- fast_dim=mem_space->extent.u.simple.rank-1;
- ndims=mem_space->extent.u.simple.rank;
-
- /* Set up the size of the memory space */
- HDmemcpy(mem_size, mem_space->extent.u.simple.size,mem_space->extent.u.simple.rank*sizeof(hsize_t));
- mem_size[mem_space->extent.u.simple.rank]=elmt_size;
-
- /* initialize row sizes for each dimension */
- for(i=(ndims-1),acc=1; i>=0; i--) {
- slab[i]=acc*elmt_size;
- acc*=mem_size[i];
- } /* end for */
-
- /* Set the number of elements left for I/O */
- H5_ASSIGN_OVERFLOW(io_left,nelmts,hsize_t,size_t);
-
- /* Check if we stopped in the middle of a sequence of elements */
- if((mem_iter->hyp.off[fast_dim]-mem_space->select.sel_info.hslab.diminfo[fast_dim].start)%mem_space->select.sel_info.hslab.diminfo[fast_dim].stride!=0 ||
- ((mem_iter->hyp.off[fast_dim]!=mem_space->select.sel_info.hslab.diminfo[fast_dim].start) && mem_space->select.sel_info.hslab.diminfo[fast_dim].stride==1)) {
- hsize_t leftover; /* The number of elements left over from the last sequence */
-
- /* Calculate the number of elements left in the sequence */
- if(mem_space->select.sel_info.hslab.diminfo[fast_dim].stride==1)
- leftover=mem_space->select.sel_info.hslab.diminfo[fast_dim].block-(mem_iter->hyp.off[fast_dim]-mem_space->select.sel_info.hslab.diminfo[fast_dim].start);
- else
- leftover=mem_space->select.sel_info.hslab.diminfo[fast_dim].block-((mem_iter->hyp.off[fast_dim]-mem_space->select.sel_info.hslab.diminfo[fast_dim].start)%mem_space->select.sel_info.hslab.diminfo[fast_dim].stride);
-
- /* Make certain that we don't write too many */
- H5_CHECK_OVERFLOW(leftover,hsize_t,size_t);
- actual_read=MIN((size_t)leftover,io_left);
- actual_bytes=actual_read*elmt_size;
-
- /* Copy the location of the point to get */
- HDmemcpy(offset, mem_iter->hyp.off,ndims*sizeof(hssize_t));
- offset[ndims] = 0;
-
- /* Add in the selection offset */
- for(i=0; i<ndims; i++)
- offset[i] += mem_space->select.offset[i];
-
- /* Compute the initial buffer offset */
- for(i=0,src=_buf; i<ndims; i++)
- src+=offset[i]*slab[i];
-
- /* Scatter out the rest of the sequence */
- HDmemcpy(dst,src,actual_bytes);
-
- /* Increment the offset of the buffer */
- dst+=actual_bytes;
-
- /* Decrement the number of elements written out */
- io_left -= actual_read;
-
- /* Advance the point iterator */
- /* If we had enough buffer space to read in the rest of the sequence
- * in the fastest changing dimension, move the iterator offset to
- * the beginning of the next block to read. Otherwise, just advance
- * the iterator in the fastest changing dimension.
- */
- if(actual_read==leftover) {
- /* Move iterator offset to beginning of next sequence in the fastest changing dimension */
- H5S_hyper_iter_next(mem_space,mem_iter);
- } /* end if */
- else {
- mem_iter->hyp.off[fast_dim]+=actual_read; /* whole sequence not written out, just advance fastest dimension offset */
- } /* end if */
- } /* end if */
-
- /* Now that we've cleared the "remainder" of the previous fastest dimension
- * sequence, we must be at the beginning of a sequence, so use the fancy
- * algorithm to compute the offsets and run through as many as possible,
- * until the buffer fills up.
- */
- if(io_left>0) { /* Just in case the "remainder" above filled the buffer */
- /* Compute the arrays to perform I/O on */
- /* Copy the location of the point to get */
- HDmemcpy(offset, mem_iter->hyp.off,ndims*sizeof(hssize_t));
- offset[ndims] = 0;
-
- /* Add in the selection offset */
- for(i=0; i<ndims; i++)
- offset[i] += mem_space->select.offset[i];
-
- /* Compute the current "counts" for this location */
- for(i=0; i<ndims; i++) {
- if(mem_space->select.sel_info.hslab.diminfo[i].stride==1) {
- tmp_count[i] = 0;
- tmp_block[i] = mem_iter->hyp.off[i]-mem_space->select.sel_info.hslab.diminfo[i].start;
- } /* end if */
- else {
- tmp_count[i] = (mem_iter->hyp.off[i]-mem_space->select.sel_info.hslab.diminfo[i].start)/mem_space->select.sel_info.hslab.diminfo[i].stride;
- tmp_block[i] = (mem_iter->hyp.off[i]-mem_space->select.sel_info.hslab.diminfo[i].start)%mem_space->select.sel_info.hslab.diminfo[i].stride;
- } /* end else */
- } /* end for */
-
- /* Compute the initial buffer offset */
- for(i=0,src=_buf; i<ndims; i++)
- src+=offset[i]*slab[i];
-
- /* Set the number of elements to write each time */
- H5_ASSIGN_OVERFLOW(actual_read,mem_space->select.sel_info.hslab.diminfo[fast_dim].block,hsize_t,size_t);
-
- /* Set the number of actual bytes */
- actual_bytes=actual_read*elmt_size;
-
- /* Set the local copy of the diminfo pointer */
- tdiminfo=mem_space->select.sel_info.hslab.diminfo;
-
- /* Set local copies of information for the fastest changing dimension */
- fast_dim_start=tdiminfo[fast_dim].start;
- fast_dim_stride=tdiminfo[fast_dim].stride;
- fast_dim_block=tdiminfo[fast_dim].block;
- H5_ASSIGN_OVERFLOW(fast_dim_buf_off,(slab[fast_dim]*fast_dim_stride),hsize_t,size_t);
- fast_dim_offset=fast_dim_start+mem_space->select.offset[fast_dim];
-
- /* Compute the number of blocks which would fit into the buffer */
- H5_ASSIGN_OVERFLOW(tot_blk_count,(io_left/fast_dim_block),hsize_t,size_t);
-
- /* Compute the amount to wrap at the end of each row */
- for(i=0; i<ndims; i++)
- wrap[i]=(mem_size[i]-(tdiminfo[i].stride*tdiminfo[i].count))*slab[i];
-
- /* Compute the amount to skip between blocks */
- for(i=0; i<ndims; i++)
- skip[i]=(tdiminfo[i].stride-tdiminfo[i].block)*slab[i];
-
- /* Read in data until an entire sequence can't be written out any longer */
- while(io_left>0) {
- /* Reset copy of number of blocks in fastest dimension */
- H5_ASSIGN_OVERFLOW(fast_dim_count,tdiminfo[fast_dim].count-tmp_count[fast_dim],hsize_t,size_t);
-
- /* Check if this entire row will fit into buffer */
- if(fast_dim_count<=tot_blk_count) {
-
- /* Entire row of blocks fits into buffer */
- act_blk_count=fast_dim_count;
-
-#ifdef NO_DUFFS_DEVICE
- /* Loop over all the blocks in the fastest changing dimension */
- while(fast_dim_count>0) {
- /* Scatter out the sequence */
- HDmemcpy(dst,src,actual_bytes);
-
- /* Increment the offset of the buffer */
- dst+=actual_bytes;
-
- /* Increment information to reflect block just processed */
- src+=fast_dim_buf_off;
-
- /* Decrement number of blocks */
- fast_dim_count--;
- } /* end while */
-#else /* NO_DUFFS_DEVICE */
- duffs_index = (fast_dim_count + 7) / 8;
- switch (fast_dim_count % 8) {
- case 0:
- do
- {
- /* Scatter out the sequence */
- HDmemcpy(dst,src,actual_bytes);
-
- /* Increment the offset of the buffer */
- dst+=actual_bytes;
-
- /* Increment information to reflect block just processed */
- src+=fast_dim_buf_off;
-
- case 7:
- /* Scatter out the sequence */
- HDmemcpy(dst,src,actual_bytes);
-
- /* Increment the offset of the buffer */
- dst+=actual_bytes;
-
- /* Increment information to reflect block just processed */
- src+=fast_dim_buf_off;
-
- case 6:
- /* Scatter out the sequence */
- HDmemcpy(dst,src,actual_bytes);
-
- /* Increment the offset of the buffer */
- dst+=actual_bytes;
-
- /* Increment information to reflect block just processed */
- src+=fast_dim_buf_off;
-
- case 5:
- /* Scatter out the sequence */
- HDmemcpy(dst,src,actual_bytes);
-
- /* Increment the offset of the buffer */
- dst+=actual_bytes;
-
- /* Increment information to reflect block just processed */
- src+=fast_dim_buf_off;
-
- case 4:
- /* Scatter out the sequence */
- HDmemcpy(dst,src,actual_bytes);
-
- /* Increment the offset of the buffer */
- dst+=actual_bytes;
-
- /* Increment information to reflect block just processed */
- src+=fast_dim_buf_off;
-
- case 3:
- /* Scatter out the sequence */
- HDmemcpy(dst,src,actual_bytes);
-
- /* Increment the offset of the buffer */
- dst+=actual_bytes;
-
- /* Increment information to reflect block just processed */
- src+=fast_dim_buf_off;
-
- case 2:
- /* Scatter out the sequence */
- HDmemcpy(dst,src,actual_bytes);
-
- /* Increment the offset of the buffer */
- dst+=actual_bytes;
-
- /* Increment information to reflect block just processed */
- src+=fast_dim_buf_off;
-
- case 1:
- /* Scatter out the sequence */
- HDmemcpy(dst,src,actual_bytes);
-
- /* Increment the offset of the buffer */
- dst+=actual_bytes;
-
- /* Increment information to reflect block just processed */
- src+=fast_dim_buf_off;
-
- } while (--duffs_index > 0);
- } /* end switch */
-#endif /* NO_DUFFS_DEVICE */
-
- /* Decrement number of elements left */
- io_left -= actual_read*act_blk_count;
-
- /* Decrement number of blocks left */
- tot_blk_count -= act_blk_count;
-
- /* Increment information to reflect block just processed */
- offset[fast_dim]=fast_dim_offset; /* reset the offset in the fastest dimension */
- tmp_count[fast_dim]=0;
-
- /* Increment offset in destination buffer */
- src += wrap[fast_dim];
- } /* end if */
- else {
-
- /* Entire row of blocks doesn't fit into buffer */
- act_blk_count=tot_blk_count;
-
- /* Reduce number of blocks to output */
- fast_dim_count=tot_blk_count;
-
- /* Loop over all the blocks in the fastest changing dimension */
- while(fast_dim_count>0) {
- /* Scatter out the sequence */
- HDmemcpy(dst,src,actual_bytes);
-
- /* Increment the offset of the buffer */
- dst+=actual_bytes;
-
- /* Increment information to reflect block just processed */
- src+=fast_dim_buf_off;
-
- /* Decrement number of blocks */
- fast_dim_count--;
- } /* end while */
-
- /* Decrement number of elements left */
- io_left -= actual_read*act_blk_count;
-
- /* Decrement number of blocks left */
- tot_blk_count -= act_blk_count;
-
- /* Increment information to reflect block just processed */
- offset[fast_dim]+=(fast_dim_stride*act_blk_count); /* reset the offset in the fastest dimension */
- tmp_count[fast_dim]+=act_blk_count;
-
- /* Handle any leftover, partial blocks in this row */
- if(io_left>0) {
- actual_read=io_left;
- actual_bytes=actual_read*elmt_size;
-
- /* Scatter out the rest of the sequence */
- HDmemcpy(dst,src,actual_bytes);
-
- /* Increment the offset of the buffer */
- dst+=actual_bytes;
-
- /* Decrement the number of elements left */
- io_left -= actual_read;
-
- /* Increment buffer correctly */
- offset[fast_dim]+=actual_read;
- } /* end if */
-
- /* don't bother checking slower dimensions */
- assert(tot_blk_count==0);
- assert(io_left==0);
- break;
- } /* end else */
-
- /* Increment the offset and count for the other dimensions */
- temp_dim=fast_dim-1;
- while(temp_dim>=0) {
- /* Move to the next row in the curent dimension */
- offset[temp_dim]++;
- tmp_block[temp_dim]++;
-
- /* If this block is still in the range of blocks to output for the dimension, break out of loop */
- if(tmp_block[temp_dim]<tdiminfo[temp_dim].block)
- break;
- else {
- /* Move to the next block in the current dimension */
- offset[temp_dim]+=(tdiminfo[temp_dim].stride-tdiminfo[temp_dim].block);
- src += skip[temp_dim];
- tmp_block[temp_dim]=0;
- tmp_count[temp_dim]++;
-
- /* If this block is still in the range of blocks to output for the dimension, break out of loop */
- if(tmp_count[temp_dim]<tdiminfo[temp_dim].count)
- break;
- else {
- offset[temp_dim]=tdiminfo[temp_dim].start+mem_space->select.offset[temp_dim];
- src += wrap[temp_dim];
- tmp_count[temp_dim]=0; /* reset back to the beginning of the line */
- tmp_block[temp_dim]=0;
- } /* end else */
- } /* end else */
-
- /* Decrement dimension count */
- temp_dim--;
- } /* end while */
- } /* end while */
-
- /* Subtract out the selection offset */
- for(i=0; i<ndims; i++)
- offset[i] -= mem_space->select.offset[i];
-
- /* Update the iterator with the location we stopped */
- HDmemcpy(mem_iter->hyp.off, offset, ndims*sizeof(hssize_t));
- } /* end if */
-
- /* Decrement the number of elements left in selection */
- mem_iter->hyp.elmt_left-=(nelmts-io_left);
-
- FUNC_LEAVE (nelmts-io_left);
-} /* end H5S_hyper_mread_opt() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5S_hyper_mgath
- *
- * Purpose: Gathers dataset elements from application memory BUF and
- * copies them into the data type conversion buffer TCONV_BUF.
- * Each element is ELMT_SIZE bytes and arranged in application
- * memory according to MEM_SPACE.
- * The caller is requesting that at most NELMTS be gathered.
- *
- * Return: Success: Number of elements copied.
- *
- * Failure: 0
- *
- * Programmer: Quincey Koziol
- * Tuesday, June 16, 1998
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static hsize_t
-H5S_hyper_mgath (const void *_buf, size_t elmt_size,
- const H5S_t *mem_space, H5S_sel_iter_t *mem_iter,
- hsize_t nelmts, void *_tconv_buf/*out*/)
-{
- hsize_t num_read; /* number of elements read into buffer */
-
- FUNC_ENTER_NOAPI(H5S_hyper_mgath, 0);
-
- /* Check args */
- assert (elmt_size>0);
- assert (mem_space);
- assert (mem_iter);
- assert (nelmts>0);
- assert (_buf);
- assert (_tconv_buf);
-
- /* Check for the special case of just one H5Sselect_hyperslab call made */
- if(mem_space->select.sel_info.hslab.diminfo!=NULL) {
- /* Use optimized call to read in regular hyperslab */
- num_read=H5S_hyper_mread_opt(_buf,elmt_size,mem_space,mem_iter,nelmts,_tconv_buf);
- } /* end if */
- else {
- /* Perform generic hyperslab operation */
- num_read=H5S_hyper_mread(_buf,elmt_size,mem_space,mem_iter,nelmts,_tconv_buf);
- } /* end else */
-
- FUNC_LEAVE (num_read);
-} /* H5S_hyper_mgath() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5S_hyper_mwrite
- *
- * Purpose: Performs an optimized gather from a memory buffer, based on a
- * hyperslab span selection.
- *
- * Return: Success: Number of elements copied.
- * Failure: 0
- *
- * Programmer: Quincey Koziol
- * Tuesday, September 12, 2000
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static hssize_t
-H5S_hyper_mwrite (const void *_tconv_buf, size_t elmt_size, const H5S_t *space,
- H5S_sel_iter_t *iter, hsize_t nelem, void *_buf/*out*/)
-{
- const uint8_t *src=(const uint8_t *)_tconv_buf; /* Alias for pointer arithmetic */
- uint8_t *dst=(uint8_t *)_buf; /* Alias for pointer arithmetic */
- uint8_t *tmp_dst; /* Alias for pointer arithmetic */
- H5S_hyper_span_t **ispan; /* Iterator's hyperslab span nodes */
- H5S_hyper_span_t *curr_span; /* Current hyperslab span node */
- hsize_t slab[H5O_LAYOUT_NDIMS]; /* Cumulative size of each dimension in bytes */
- hsize_t acc; /* Accumulator for computing cumulative sizes */
- hssize_t *abs_arr; /* Absolute hyperslab span position */
- hssize_t *off_arr; /* Offset within the dataspace extent */
- int fast_dim; /* Rank of the fastest changing dimension for the dataspace */
- int curr_dim; /* Current dimension being operated on */
- int ndims; /* Number of dimensions of dataset */
- size_t span_size=0; /* Number of bytes in current span to actually process */
- size_t io_bytes_left; /* Number of bytes left to process */
- int i; /* Index variable */
- hssize_t ret_value=FAIL;
-
- FUNC_ENTER_NOINIT(H5S_hyper_mwrite);
-
- /* Check args */
- assert(src);
- assert(elmt_size>0);
- assert(space);
- assert(iter);
- assert(nelem>0);
- assert(dst);
-
- /* Set the rank of the fastest changing dimension */
- ndims=space->extent.u.simple.rank;
- fast_dim=(ndims-1);
-
- /* Get the pointers to the current span info and span nodes */
- curr_span=iter->hyp.span[fast_dim];
- abs_arr=iter->hyp.off;
- off_arr=space->select.offset;
- ispan=iter->hyp.span;
-
- /* Set the amount of elements to perform I/O on, etc. */
- H5_ASSIGN_OVERFLOW(io_bytes_left,nelem*elmt_size,hsize_t,size_t);
-
- /* Compute the cumulative size of dataspace dimensions */
- for(i=fast_dim, acc=elmt_size; i>=0; i--) {
- slab[i]=acc;
- acc*=space->extent.u.simple.size[i];
- } /* end for */
-
- /* Set the offset of the first element iterated on */
- for(i=0, tmp_dst=dst; i<ndims; i++)
- /* Compute the sequential element offset */
- tmp_dst+=(abs_arr[i]+space->select.offset[i])*slab[i];
-
- /* Range check against number of elements left in selection */
- assert(io_bytes_left<=(iter->hyp.elmt_left*elmt_size));
-
- /* Take care of any partial spans leftover from previous I/Os */
- if(abs_arr[fast_dim]!=curr_span->low) {
-
- /* Finish the span in the fastest changing dimension */
-
- /* Compute the number of bytes to attempt in this span */
- H5_ASSIGN_OVERFLOW(span_size,((curr_span->high-abs_arr[fast_dim])+1)*elmt_size,hsize_t,size_t);
-
- /* Check number of elements against upper bounds allowed */
- if(span_size>io_bytes_left)
- span_size=io_bytes_left;
-
- HDmemcpy(tmp_dst,src,span_size);
-
- /* Increment offset in destination */
- src+=span_size;
-
- /* Decrement I/O left to perform */
- io_bytes_left-=span_size;
-
- /* Check if we are done */
- if(io_bytes_left>0) {
- /* Move to next span in fastest changing dimension */
- curr_span=curr_span->next;
-
- if(curr_span!=NULL) {
- /* Move location offset of destination */
- tmp_dst+=(curr_span->low-abs_arr[fast_dim])*elmt_size;
-
- /* Move iterator for fastest changing dimension */
- abs_arr[fast_dim]=curr_span->low;
- } /* end if */
- } /* end if */
- else {
- abs_arr[fast_dim]+=span_size/elmt_size;
-
- /* Check if we are still within the span */
- if(abs_arr[fast_dim]<=curr_span->high) {
- iter->hyp.span[fast_dim]=curr_span;
-
- goto partial_done; /* finished with partial span */
- } /* end if */
- /* If we walked off that span, advance to the next span */
- else {
- /* Advance span in this dimension */
- curr_span=curr_span->next;
-
- /* Check if we have a valid span in this dimension still */
- if(curr_span!=NULL) {
- /* Reset absolute position */
- abs_arr[fast_dim]=curr_span->low;
- iter->hyp.span[fast_dim]=curr_span;
-
- goto partial_done; /* finished with partial span */
- } /* end if */
- } /* end else */
- } /* end else */
-
- /* Adjust iterator pointers */
-
- if(curr_span==NULL) {
-/* Same as code in main loop */
- /* Start at the next fastest dim */
- curr_dim=fast_dim-1;
-
- /* Work back up through the dimensions */
- while(curr_dim>=0) {
- /* Reset the current span */
- curr_span=iter->hyp.span[curr_dim];
-
- /* Increment absolute position */
- abs_arr[curr_dim]++;
-
- /* Check if we are still within the span */
- if(abs_arr[curr_dim]<=curr_span->high) {
- break;
- } /* end if */
- /* If we walked off that span, advance to the next span */
- else {
- /* Advance span in this dimension */
- curr_span=curr_span->next;
-
- /* Check if we have a valid span in this dimension still */
- if(curr_span!=NULL) {
- /* Reset absolute position */
- abs_arr[curr_dim]=curr_span->low;
-
- break;
- } /* end if */
- else {
- /* If we finished the span list in this dimension, decrement the dimension worked on and loop again */
- curr_dim--;
- } /* end else */
- } /* end else */
- } /* end while */
-
- /* Check if we are finished with the spans in the tree */
- if(curr_dim<0) {
- /* We had better be done with I/O or bad things are going to happen... */
- assert(io_bytes_left==0);
-
- goto partial_done; /* finished with partial span */
- } /* end if */
- else {
- /* Reset the span in the current dimension */
- ispan[curr_dim]=curr_span;
-
- /* Walk back down the iterator positions, reseting them */
- while(curr_dim<fast_dim) {
- assert(curr_span);
- assert(curr_span->down);
- assert(curr_span->down->head);
-
- /* Set the new span_info & span for this dimension */
- iter->hyp.span[curr_dim+1]=curr_span->down->head;
-
- /* Advance span down the tree */
- curr_span=curr_span->down->head;
-
- /* Reset the absolute offset for the dim */
- abs_arr[curr_dim+1]=curr_span->low;
-
- /* Increment current dimension */
- curr_dim++;
- } /* end while */
-
- /* Verify that the curr_span points to the fastest dim */
- assert(curr_span==iter->hyp.span[fast_dim]);
- } /* end else */
-
- /* Reset the buffer offset */
- for(i=0, tmp_dst=dst; i<ndims; i++)
- tmp_dst+=(abs_arr[i]+off_arr[i])*slab[i];
- } /* end if */
- } /* end if */
-
-partial_done: /* Yes, goto's are evil, so sue me... :-) */
-
- /* Perform the I/O on the elements, based on the position of the iterator */
- while(io_bytes_left>0) {
- /* Adjust buffer offset of destination to compensate for initial increment below */
- tmp_dst-=(size_t)curr_span->pstride;
-
- /* Loop over all the spans in the fastest changing dimension */
- while(curr_span!=NULL) {
- /* Move buffer offset of destination */
- tmp_dst+=(size_t)curr_span->pstride;
-
- /* Compute the number of elements to attempt in this span */
- H5_ASSIGN_OVERFLOW(span_size,curr_span->nelem,hsize_t,size_t);
-
- /* Check number of elements against upper bounds allowed */
- if(span_size>=io_bytes_left) {
- /* Trim the number of bytes to output */
- span_size=io_bytes_left;
- io_bytes_left=0;
-
-/* COMMON */
- /* "Write" the data into the destination buffer */
- HDmemcpy(tmp_dst,src,span_size);
-
- /* Increment offset in destination */
- src+=span_size;
-/* end COMMON */
-
- /* Break out now, we are finished with I/O */
- break;
- } /* end if */
- else {
- /* Decrement I/O left to perform */
- io_bytes_left-=span_size;
-
-/* COMMON */
- /* "Write" the data into the destination buffer */
- HDmemcpy(tmp_dst,src,span_size);
-
- /* Increment offset in destination */
- src+=span_size;
-/* end COMMON */
- } /* end else */
-
- /* Move to next span in fastest changing dimension */
- curr_span=curr_span->next;
- } /* end while */
-
- /* Check if we are done */
- if(io_bytes_left==0) {
- abs_arr[fast_dim]=curr_span->low+(span_size/elmt_size);
-
- /* Check if we are still within the span */
- if(abs_arr[fast_dim]<=curr_span->high) {
- iter->hyp.span[fast_dim]=curr_span;
- break;
- } /* end if */
- /* If we walked off that span, advance to the next span */
- else {
- /* Advance span in this dimension */
- curr_span=curr_span->next;
-
- /* Check if we have a valid span in this dimension still */
- if(curr_span!=NULL) {
- /* Reset absolute position */
- abs_arr[fast_dim]=curr_span->low;
- iter->hyp.span[fast_dim]=curr_span;
- break;
- } /* end if */
- } /* end else */
- } /* end if */
-
- /* Adjust iterator pointers */
-
- /* Start at the next fastest dim */
- curr_dim=fast_dim-1;
-
- /* Work back up through the dimensions */
- while(curr_dim>=0) {
- /* Reset the current span */
- curr_span=iter->hyp.span[curr_dim];
-
- /* Increment absolute position */
- abs_arr[curr_dim]++;
-
- /* Check if we are still within the span */
- if(abs_arr[curr_dim]<=curr_span->high) {
- break;
- } /* end if */
- /* If we walked off that span, advance to the next span */
- else {
- /* Advance span in this dimension */
- curr_span=curr_span->next;
-
- /* Check if we have a valid span in this dimension still */
- if(curr_span!=NULL) {
- /* Reset absolute position */
- abs_arr[curr_dim]=curr_span->low;
-
- break;
- } /* end if */
- else {
- /* If we finished the span list in this dimension, decrement the dimension worked on and loop again */
- curr_dim--;
- } /* end else */
- } /* end else */
- } /* end while */
-
- /* Check if we are finished with the spans in the tree */
- if(curr_dim<0) {
- /* We had better be done with I/O or bad things are going to happen... */
- assert(io_bytes_left==0);
- break;
- } /* end if */
- else {
- /* Reset the span in the current dimension */
- ispan[curr_dim]=curr_span;
-
- /* Walk back down the iterator positions, reseting them */
- while(curr_dim<fast_dim) {
- assert(curr_span);
- assert(curr_span->down);
- assert(curr_span->down->head);
-
- /* Set the new span_info & span for the next dimension down */
- iter->hyp.span[curr_dim+1]=curr_span->down->head;
-
- /* Advance span down the tree */
- curr_span=curr_span->down->head;
-
- /* Reset the absolute offset for the dim */
- abs_arr[curr_dim+1]=curr_span->low;
-
- /* Increment current dimension */
- curr_dim++;
- } /* end while */
-
- /* Verify that the curr_span points to the fastest dim */
- assert(curr_span==iter->hyp.span[fast_dim]);
- } /* end else */
-
- /* Reset the buffer offset */
- for(i=0, tmp_dst=dst; i<ndims; i++)
- tmp_dst+=(abs_arr[i]+off_arr[i])*slab[i];
- } /* end while */
-
- /* Increment amount of I/O performed */
- iter->hyp.elmt_left-=nelem;
-
- /* Success! */
- ret_value=nelem;
-
-#ifdef LATER
-done:
-#endif /* LATER */
- FUNC_LEAVE (ret_value);
-} /* end H5S_hyper_mwrite() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5S_hyper_mwrite_opt
- *
- * Purpose: Performs an optimized scatter to a memory buffer, based on a
- * regular hyperslab (i.e. one which was generated from just one call to
- * H5Sselect_hyperslab).
- *
- * Return: Success: Number of elements copied.
- * Failure: 0
- *
- * Programmer: Quincey Koziol
- * Tuesday, September 12, 2000
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static hsize_t
-H5S_hyper_mwrite_opt (const void *_tconv_buf, size_t elmt_size,
- const H5S_t *mem_space, H5S_sel_iter_t *mem_iter,
- hsize_t nelmts, void *_buf/*out*/)
-{
- hsize_t mem_size[H5O_LAYOUT_NDIMS]; /* Size of the source buffer */
- hsize_t slab[H5O_LAYOUT_NDIMS]; /* Hyperslab size */
- hssize_t wrap[H5O_LAYOUT_NDIMS]; /* Bytes to wrap around at the end of a row */
- hsize_t skip[H5O_LAYOUT_NDIMS]; /* Bytes to skip between blocks */
- hssize_t offset[H5O_LAYOUT_NDIMS]; /* Offset on disk */
- hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary block count */
- hsize_t tmp_block[H5O_LAYOUT_NDIMS]; /* Temporary block offset */
- const uint8_t *src=(const uint8_t *)_tconv_buf; /* Alias for pointer arithmetic */
- uint8_t *dst=(uint8_t *)_buf; /* Alias for pointer arithmetic */
- const H5S_hyper_dim_t *tdiminfo; /* Temporary pointer to diminfo information */
- hssize_t fast_dim_start, /* Local copies of fastest changing dimension info */
- fast_dim_offset;
- hsize_t fast_dim_stride, /* Local copies of fastest changing dimension info */
- fast_dim_block;
- size_t fast_dim_count;
- size_t tot_blk_count; /* Total number of blocks left to output */
- size_t act_blk_count; /* Actual number of blocks to output */
- size_t fast_dim_buf_off; /* Local copy of amount to move fastest dimension buffer offset */
- int fast_dim; /* Rank of the fastest changing dimension for the dataspace */
- int temp_dim; /* Temporary rank holder */
- hsize_t acc; /* Accumulator */
- int i; /* Counters */
- int ndims; /* Number of dimensions of dataset */
- size_t actual_write; /* The actual number of elements to read in */
- size_t actual_bytes; /* The actual number of bytes to copy */
- size_t io_left; /* The number of elements left in I/O operation */
-#ifndef NO_DUFFS_DEVICE
- size_t duffs_index; /* Counting index for Duff's device */
-#endif /* NO_DUFFS_DEVICE */
-
- FUNC_ENTER_NOINIT(H5S_hyper_mwrite_opt);
-
- /* Set the aliases for a few important dimension ranks */
- fast_dim=mem_space->extent.u.simple.rank-1;
- ndims=mem_space->extent.u.simple.rank;
-
- /* Set up the size of the memory space */
- HDmemcpy(mem_size, mem_space->extent.u.simple.size,mem_space->extent.u.simple.rank*sizeof(hsize_t));
- mem_size[mem_space->extent.u.simple.rank]=elmt_size;
-
- /* initialize row sizes for each dimension */
- for(i=(ndims-1),acc=1; i>=0; i--) {
- slab[i]=acc*elmt_size;
- acc*=mem_size[i];
- } /* end for */
-
- /* Set the number of elements left for I/O */
- H5_ASSIGN_OVERFLOW(io_left,nelmts,hsize_t,size_t);
-
- /* Check if we stopped in the middle of a sequence of elements */
- if((mem_iter->hyp.off[fast_dim]-mem_space->select.sel_info.hslab.diminfo[fast_dim].start)%mem_space->select.sel_info.hslab.diminfo[fast_dim].stride!=0 ||
- ((mem_iter->hyp.off[fast_dim]!=mem_space->select.sel_info.hslab.diminfo[fast_dim].start) && mem_space->select.sel_info.hslab.diminfo[fast_dim].stride==1)) {
- hsize_t leftover; /* The number of elements left over from the last sequence */
-
- /* Calculate the number of elements left in the sequence */
- if(mem_space->select.sel_info.hslab.diminfo[fast_dim].stride==1)
- leftover=mem_space->select.sel_info.hslab.diminfo[fast_dim].block-(mem_iter->hyp.off[fast_dim]-mem_space->select.sel_info.hslab.diminfo[fast_dim].start);
- else
- leftover=mem_space->select.sel_info.hslab.diminfo[fast_dim].block-((mem_iter->hyp.off[fast_dim]-mem_space->select.sel_info.hslab.diminfo[fast_dim].start)%mem_space->select.sel_info.hslab.diminfo[fast_dim].stride);
-
- /* Make certain that we don't write too many */
- H5_CHECK_OVERFLOW(leftover,hsize_t,size_t);
- actual_write=MIN((size_t)leftover,io_left);
- actual_bytes=actual_write*elmt_size;
-
- /* Copy the location of the point to get */
- HDmemcpy(offset, mem_iter->hyp.off,ndims*sizeof(hssize_t));
- offset[ndims] = 0;
-
- /* Add in the selection offset */
- for(i=0; i<ndims; i++)
- offset[i] += mem_space->select.offset[i];
-
- /* Compute the initial buffer offset */
- for(i=0,dst=(unsigned char *)_buf; i<ndims; i++)
- dst+=offset[i]*slab[i];
-
- /* Scatter out the rest of the sequence */
- HDmemcpy(dst,src,actual_bytes);
-
- /* Increment the offset of the buffer */
- src+=actual_bytes;
-
- /* Decrement the number of elements written out */
- io_left -= actual_write;
-
- /* Advance the point iterator */
- /* If we had enough buffer space to write out the rest of the sequence
- * in the fastest changing dimension, move the iterator offset to
- * the beginning of the next block to write. Otherwise, just advance
- * the iterator in the fastest changing dimension.
- */
- if(actual_write==leftover) {
- /* Move iterator offset to beginning of next sequence in the fastest changing dimension */
- H5S_hyper_iter_next(mem_space,mem_iter);
- } /* end if */
- else {
- mem_iter->hyp.off[fast_dim]+=actual_write; /* whole sequence not written out, just advance fastest dimension offset */
- } /* end if */
- } /* end if */
-
- /* Now that we've cleared the "remainder" of the previous fastest dimension
- * sequence, we must be at the beginning of a sequence, so use the fancy
- * algorithm to compute the offsets and run through as many as possible,
- * until the buffer fills up.
- */
- if(io_left>0) { /* Just in case the "remainder" above filled the buffer */
- /* Compute the arrays to perform I/O on */
- /* Copy the location of the point to get */
- HDmemcpy(offset, mem_iter->hyp.off,ndims*sizeof(hssize_t));
- offset[ndims] = 0;
-
- /* Add in the selection offset */
- for(i=0; i<ndims; i++)
- offset[i] += mem_space->select.offset[i];
-
- /* Compute the current "counts" for this location */
- for(i=0; i<ndims; i++) {
- if(mem_space->select.sel_info.hslab.diminfo[i].stride==1) {
- tmp_count[i] = 0;
- tmp_block[i] = mem_iter->hyp.off[i]-mem_space->select.sel_info.hslab.diminfo[i].start;
- } /* end if */
- else {
- tmp_count[i] = (mem_iter->hyp.off[i]-mem_space->select.sel_info.hslab.diminfo[i].start)/mem_space->select.sel_info.hslab.diminfo[i].stride;
- tmp_block[i] = (mem_iter->hyp.off[i]-mem_space->select.sel_info.hslab.diminfo[i].start)%mem_space->select.sel_info.hslab.diminfo[i].stride;
- } /* end else */
- } /* end for */
-
- /* Compute the initial buffer offset */
- for(i=0,dst=(unsigned char *)_buf; i<ndims; i++)
- dst+=offset[i]*slab[i];
-
- /* Set the number of elements to write each time */
- H5_ASSIGN_OVERFLOW(actual_write,mem_space->select.sel_info.hslab.diminfo[fast_dim].block,hsize_t,size_t);
-
- /* Set the number of actual bytes */
- actual_bytes=actual_write*elmt_size;
-
- /* Set the local copy of the diminfo pointer */
- tdiminfo=mem_space->select.sel_info.hslab.diminfo;
-
- /* Set local copies of information for the fastest changing dimension */
- fast_dim_start=tdiminfo[fast_dim].start;
- fast_dim_stride=tdiminfo[fast_dim].stride;
- fast_dim_block=tdiminfo[fast_dim].block;
- H5_ASSIGN_OVERFLOW(fast_dim_buf_off,slab[fast_dim]*fast_dim_stride,hsize_t,size_t);
- fast_dim_offset=fast_dim_start+mem_space->select.offset[fast_dim];
-
- /* Compute the number of blocks which would fit into the buffer */
- H5_ASSIGN_OVERFLOW(tot_blk_count,(io_left/fast_dim_block),hsize_t,size_t);
-
- /* Compute the amount to wrap at the end of each row */
- for(i=0; i<ndims; i++)
- wrap[i]=(mem_size[i]-(tdiminfo[i].stride*tdiminfo[i].count))*slab[i];
-
- /* Compute the amount to skip between blocks */
- for(i=0; i<ndims; i++)
- skip[i]=(tdiminfo[i].stride-tdiminfo[i].block)*slab[i];
-
- /* Read in data until an entire sequence can't be written out any longer */
- while(io_left>0) {
- /* Reset copy of number of blocks in fastest dimension */
- H5_ASSIGN_OVERFLOW(fast_dim_count,tdiminfo[fast_dim].count-tmp_count[fast_dim],hsize_t,size_t);
-
- /* Check if this entire row will fit into buffer */
- if(fast_dim_count<=tot_blk_count) {
-
- /* Entire row of blocks fits into buffer */
- act_blk_count=fast_dim_count;
-
-#ifdef NO_DUFFS_DEVICE
- /* Loop over all the blocks in the fastest changing dimension */
- while(fast_dim_count>0) {
- /* Scatter out the sequence */
- HDmemcpy(dst,src,actual_bytes);
-
- /* Increment the offset of the buffer */
- src+=actual_bytes;
-
- /* Increment information to reflect block just processed */
- dst+=fast_dim_buf_off;
-
- /* Decrement number of blocks */
- fast_dim_count--;
- } /* end while */
-#else /* NO_DUFFS_DEVICE */
- duffs_index = (fast_dim_count + 7) / 8;
- switch (fast_dim_count % 8) {
- case 0:
- do
- {
- /* Scatter out the sequence */
- HDmemcpy(dst,src,actual_bytes);
-
- /* Increment the offset of the buffer */
- src+=actual_bytes;
-
- /* Increment information to reflect block just processed */
- dst+=fast_dim_buf_off;
-
- case 7:
- /* Scatter out the sequence */
- HDmemcpy(dst,src,actual_bytes);
-
- /* Increment the offset of the buffer */
- src+=actual_bytes;
-
- /* Increment information to reflect block just processed */
- dst+=fast_dim_buf_off;
-
- case 6:
- /* Scatter out the sequence */
- HDmemcpy(dst,src,actual_bytes);
-
- /* Increment the offset of the buffer */
- src+=actual_bytes;
-
- /* Increment information to reflect block just processed */
- dst+=fast_dim_buf_off;
-
- case 5:
- /* Scatter out the sequence */
- HDmemcpy(dst,src,actual_bytes);
-
- /* Increment the offset of the buffer */
- src+=actual_bytes;
-
- /* Increment information to reflect block just processed */
- dst+=fast_dim_buf_off;
-
- case 4:
- /* Scatter out the sequence */
- HDmemcpy(dst,src,actual_bytes);
-
- /* Increment the offset of the buffer */
- src+=actual_bytes;
-
- /* Increment information to reflect block just processed */
- dst+=fast_dim_buf_off;
-
- case 3:
- /* Scatter out the sequence */
- HDmemcpy(dst,src,actual_bytes);
-
- /* Increment the offset of the buffer */
- src+=actual_bytes;
-
- /* Increment information to reflect block just processed */
- dst+=fast_dim_buf_off;
-
- case 2:
- /* Scatter out the sequence */
- HDmemcpy(dst,src,actual_bytes);
-
- /* Increment the offset of the buffer */
- src+=actual_bytes;
-
- /* Increment information to reflect block just processed */
- dst+=fast_dim_buf_off;
-
- case 1:
- /* Scatter out the sequence */
- HDmemcpy(dst,src,actual_bytes);
-
- /* Increment the offset of the buffer */
- src+=actual_bytes;
-
- /* Increment information to reflect block just processed */
- dst+=fast_dim_buf_off;
-
- } while (--duffs_index > 0);
- } /* end switch */
-#endif /* NO_DUFFS_DEVICE */
-
- /* Decrement number of elements left */
- io_left -= actual_write*act_blk_count;
-
- /* Decrement number of blocks left */
- tot_blk_count -= act_blk_count;
-
- /* Increment information to reflect block just processed */
- offset[fast_dim]=fast_dim_offset; /* reset the offset in the fastest dimension */
- tmp_count[fast_dim]=0;
-
- /* Increment offset in destination buffer */
- dst += wrap[fast_dim];
- } /* end if */
- else {
-
- /* Entire row of blocks doesn't fit into buffer */
- act_blk_count=tot_blk_count;
-
- /* Reduce number of blocks to output */
- fast_dim_count=tot_blk_count;
-
- /* Loop over all the blocks in the fastest changing dimension */
- while(fast_dim_count>0) {
- /* Scatter out the sequence */
- HDmemcpy(dst,src,actual_bytes);
-
- /* Increment the offset of the buffer */
- src+=actual_bytes;
-
- /* Increment information to reflect block just processed */
- dst+=fast_dim_buf_off;
-
- /* Decrement number of blocks */
- fast_dim_count--;
- } /* end while */
-
- /* Decrement number of elements left */
- io_left -= actual_write*act_blk_count;
-
- /* Decrement number of blocks left */
- tot_blk_count -= act_blk_count;
-
- /* Increment information to reflect block just processed */
- offset[fast_dim]+=(fast_dim_stride*act_blk_count); /* reset the offset in the fastest dimension */
- tmp_count[fast_dim]+=act_blk_count;
-
- /* Handle any leftover, partial blocks in this row */
- if(io_left>0) {
- actual_write=io_left;
- actual_bytes=actual_write*elmt_size;
-
- /* Scatter out the rest of the sequence */
- HDmemcpy(dst,src,actual_bytes);
-
- /* Increment the offset of the buffer */
- src+=actual_bytes;
-
- /* Decrement the number of elements left */
- io_left -= actual_write;
-
- /* Increment buffer correctly */
- offset[fast_dim]+=actual_write;
- } /* end if */
-
- /* don't bother checking slower dimensions */
- assert(tot_blk_count==0);
- assert(io_left==0);
- break;
- } /* end else */
-
- /* Increment the offset and count for the other dimensions */
- temp_dim=fast_dim-1;
- while(temp_dim>=0) {
- /* Move to the next row in the curent dimension */
- offset[temp_dim]++;
- tmp_block[temp_dim]++;
-
- /* If this block is still in the range of blocks to output for the dimension, break out of loop */
- if(tmp_block[temp_dim]<tdiminfo[temp_dim].block)
- break;
- else {
- /* Move to the next block in the current dimension */
- offset[temp_dim]+=(tdiminfo[temp_dim].stride-tdiminfo[temp_dim].block);
- dst += skip[temp_dim];
- tmp_block[temp_dim]=0;
- tmp_count[temp_dim]++;
-
- /* If this block is still in the range of blocks to output for the dimension, break out of loop */
- if(tmp_count[temp_dim]<tdiminfo[temp_dim].count)
- break;
- else {
- offset[temp_dim]=tdiminfo[temp_dim].start+mem_space->select.offset[temp_dim];
- dst += wrap[temp_dim];
- tmp_count[temp_dim]=0; /* reset back to the beginning of the line */
- tmp_block[temp_dim]=0;
- } /* end else */
- } /* end else */
-
- /* Decrement dimension count */
- temp_dim--;
- } /* end while */
- } /* end while */
-
- /* Subtract out the selection offset */
- for(i=0; i<ndims; i++)
- offset[i] -= mem_space->select.offset[i];
-
- /* Update the iterator with the location we stopped */
- HDmemcpy(mem_iter->hyp.off, offset, ndims*sizeof(hssize_t));
- } /* end if */
-
- /* Decrement the number of elements left in selection */
- mem_iter->hyp.elmt_left-=(nelmts-io_left);
-
- FUNC_LEAVE (nelmts-io_left);
-} /* end H5S_hyper_mwrite_opt() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5S_hyper_mscat
- *
- * Purpose: Scatters NELMTS data points from the type conversion buffer
- * TCONV_BUF to the application buffer BUF. Each element is
- * ELMT_SIZE bytes and they are organized in application memory
- * according to MEM_SPACE.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Wednesday, June 17, 1998
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5S_hyper_mscat (const void *_tconv_buf, size_t elmt_size,
- const H5S_t *mem_space, H5S_sel_iter_t *mem_iter,
- hsize_t nelmts, void *_buf/*out*/)
-{
- hsize_t num_written; /* number of elements written into buffer */
-
- FUNC_ENTER_NOAPI(H5S_hyper_mscat, 0);
-
- /* Check args */
- assert (elmt_size>0);
- assert (mem_space);
- assert (mem_iter);
- assert (nelmts>0);
- assert (_buf);
- assert (_tconv_buf);
-
- /* Check for the special case of just one H5Sselect_hyperslab call made */
- if(mem_space->select.sel_info.hslab.diminfo!=NULL) {
- /* Use optimized call to write out regular hyperslab */
- num_written=H5S_hyper_mwrite_opt(_tconv_buf,elmt_size,mem_space,mem_iter,nelmts,_buf);
- } /* end if */
- else {
- /* Perform generic hyperslab operation */
- num_written=H5S_hyper_mwrite(_tconv_buf,elmt_size,mem_space,mem_iter,nelmts,_buf);
- } /* end else */
-
- FUNC_LEAVE (num_written>0 ? SUCCEED : FAIL);
-} /* H5S_hyper_mscat() */
-
-
/*--------------------------------------------------------------------------
NAME
H5S_hyper_npoints
@@ -4874,7 +1206,7 @@ H5S_hyper_select_valid (const H5S_t *space)
Count the number of blocks in a span tree
USAGE
hssize_t H5S_hyper_span_nblocks(spans)
- const H5S_hyper_span_info_t *spans; IN: Hyperslan span tree to count elements of
+ const H5S_hyper_span_info_t *spans; IN: Hyperslab span tree to count elements of
RETURNS
Number of blocks in span tree on success; negative on failure
DESCRIPTION
@@ -5840,475 +2172,6 @@ H5S_hyper_select_regular(const H5S_t *space)
/*--------------------------------------------------------------------------
NAME
- H5S_hyper_select_iterate_mem_gen
- PURPOSE
- Internal routine to iterate over the elements of a span tree hyperslab selection
- USAGE
- herr_t H5S_hyper_select_iterate_mem_gen(iter_info)
- H5S_hyper_iter_info_t *iter_info; IN/OUT: Block of iteration parameters to pass into recursive calls
- RETURNS
- Non-negative on success, negative on failure
- DESCRIPTION
- Iterates over the elements in a hyperslab span tree selection, calling a
- user's callback routine for each element.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-static herr_t
-H5S_hyper_select_iterate_mem_gen(H5S_hyper_iter_info_t *iter_info)
-{
- const H5S_t *space; /* Dataspace operating with */
- H5S_sel_iter_t *iter; /* Selection iterator */
- H5S_hyper_span_t *curr_span; /* Current hyperslab span node */
- hsize_t slab[H5O_LAYOUT_NDIMS]; /* Cumulative size of each dimension in bytes */
- hsize_t acc; /* Accumulator for computing cumulative sizes */
- hssize_t off_arr[H5O_LAYOUT_NDIMS]; /* Current hyperslab span position */
- hssize_t coord_arr[H5O_LAYOUT_NDIMS]; /* Current coordinate position */
- int fast_dim; /* Rank of the fastest changing dimension for the dataspace */
- int curr_dim; /* Current dimension being operated on */
- int ndims; /* Number of dimensions of dataset */
- hsize_t span_io; /* Number of elements in current span to actually process */
- herr_t user_ret=0; /* User's return value */
- uint8_t *loc; /* Current element location pointer */
- hsize_t loc_off; /* Element offset in the dataspace */
- int i; /* Index variable */
- unsigned u; /* Index variable */
- herr_t ret_value=FAIL;
-
- FUNC_ENTER_NOINIT(H5S_hyper_select_iterate_mem_gen);
-
- /* Check args */
- assert(iter_info);
-
- /* Retrieve some information from the interation info */
- space=iter_info->space;
- iter=iter_info->iter;
-
- /* Set the rank of the fastest changing dimension */
- ndims=space->extent.u.simple.rank;
- fast_dim=(ndims-1);
-
- /* Get the pointers to the current span info and span nodes */
- curr_span=iter->hyp.span[fast_dim];
-
- /* Compute the cumulative size of dataspace dimensions */
- for(i=fast_dim, acc=iter_info->elem_size; i>=0; i--) {
- slab[i]=acc;
- acc*=space->extent.u.simple.size[i];
- } /* end for */
-
- /* Set the offset of the first element iterated on */
- for(i=0, loc_off=0; i<ndims; i++) {
- /* Set the location */
- off_arr[i]=iter->hyp.span[i]->low;
- coord_arr[i]=off_arr[i]+space->select.offset[i];
-
- /* Compute the sequential element offset */
- loc_off+=coord_arr[i]*slab[i];
- } /* end for */
-
- /* Perform the I/O on the elements, based on the position of the iterator */
- user_ret=0;
- while(curr_span!=NULL && user_ret==0) {
- /* Compute the number of elements to attempt in this span */
- span_io=(curr_span->high-curr_span->low)+1;
-
- /* Iterate through all the span elements */
- for(u=0, loc=(uint8_t *)iter_info->src+loc_off; u<span_io && user_ret==0; u++) {
- /* Call the user's callback routine */
- user_ret=(*(iter_info->op))(loc,iter_info->dt,(hsize_t)ndims,coord_arr,iter_info->op_data);
-
- /* Increment the element location */
- off_arr[fast_dim]++;
- coord_arr[fast_dim]++;
-
- /* Increment the buffer offset */
- loc+=slab[fast_dim];
- } /* end for */
-
- /* Get out now for user return values not zero */
- if(user_ret!=0)
- break;
-
- /* Adjust iterator pointers */
-
- /* Advance span in fastest dimension */
- curr_span=curr_span->next;
-
- /* See if we are still in the fastest changing dimension */
- if(curr_span!=NULL) {
- /* Move the buffer offset */
- loc_off+=(span_io+(curr_span->low-off_arr[fast_dim]))*iter_info->elem_size;
-
- /* Move the element location */
- off_arr[fast_dim]=curr_span->low;
- coord_arr[fast_dim]=off_arr[fast_dim]+space->select.offset[fast_dim];
- } /* end if */
- /* We walked off the spans for the fastest dimension, work our way back up */
- else {
- /* Start at the fastest dim */
- curr_dim=fast_dim-1;
-
- /* Get the pointer to the correct dimension */
- curr_span=iter->hyp.span[curr_dim];
-
- /* Work back up through the dimensions */
- while(curr_dim>=0) {
- /* Increment position in span */
- off_arr[curr_dim]++;
- coord_arr[curr_dim]++;
-
- /* Check if we are still within the span */
- if(off_arr[curr_dim]<=curr_span->high) {
- break;
- } /* end if */
- /* If we walked off that span, advance to the next span */
- else {
- /* Advance span in this dimension */
- curr_span=curr_span->next;
-
- /* Check if we have a valid span in this dimension still */
- if(curr_span!=NULL) {
- /* Reset the offset for the dim */
- off_arr[curr_dim]=curr_span->low;
- coord_arr[curr_dim]=off_arr[curr_dim]+space->select.offset[curr_dim];
-
- break;
- } /* end if */
- else {
- /* If we finished the span list in this dimension, decrement the dimension worked on and loop again */
- curr_dim--;
-
- /* Reset the curr_span to the next dim */
- if(curr_dim>=0)
- curr_span=iter->hyp.span[curr_dim];
- } /* end else */
- } /* end else */
- } /* end while */
-
- /* Check if we are finished with the spans in the tree */
- if(curr_dim<0) {
- /* We had better be done with I/O or bad things are going to happen... */
- break;
- } /* end if */
- else {
- /* Reset the span in the current dimension */
- iter->hyp.span[curr_dim]=curr_span;
-
- /* Walk back down the iterator positions, reseting them */
- while(curr_dim<fast_dim) {
- assert(curr_span);
- assert(curr_span->down);
- assert(curr_span->down->head);
-
- /* Set the new span for this dimension */
- iter->hyp.span[curr_dim+1]=curr_span->down->head;
-
- /* Advance span down the tree */
- curr_span=curr_span->down->head;
-
- /* Reset the offset for the dim */
- off_arr[curr_dim+1]=curr_span->low;
- coord_arr[curr_dim+1]=off_arr[curr_dim+1]+space->select.offset[curr_dim+1];
-
- /* Increment current dimension */
- curr_dim++;
- } /* end while */
-
- /* Verify that the curr_span points to the fastest dim */
- assert(curr_span==iter->hyp.span[fast_dim]);
-
- /* Verify that the offset is correct for the fastest dim */
- assert(off_arr[fast_dim]==curr_span->low);
- } /* end else */
-
- /* Reset the buffer offset */
- for(i=0, loc_off=0; i<ndims; i++)
- loc_off+=coord_arr[i]*slab[i];
- } /* end else */
- } /* end while */
-
- /* Success! */
- ret_value=(user_ret==0 ? SUCCEED : user_ret);
-
-#ifdef LATER
-done:
-#endif /* LATER */
- FUNC_LEAVE (ret_value);
-} /* end H5S_hyper_select_iterate_mem_gen() */
-
-
-/*--------------------------------------------------------------------------
- NAME
- H5S_hyper_select_iterate_mem_opt
- PURPOSE
- Iterate over the data points in a regular hyperslab selection, calling a
- user's function for each element.
- USAGE
- herr_t H5S_hyper_select_iterate_mem_opt(buf, type_id, space, op, operator_data)
- H5S_sel_iter_t *iter; IN/OUT: Selection iterator
- void *buf; IN/OUT: Buffer containing elements to iterate over
- hid_t type_id; IN: Datatype ID of BUF array.
- H5S_t *space; IN: Dataspace object containing selection to iterate over
- H5D_operator_t op; IN: Function pointer to the routine to be
- called for each element in BUF iterated over.
- void *op_data; IN/OUT: Pointer to any user-defined data associated
- with the operation.
- RETURNS
- Returns the return value of the last operator if it was non-zero, or zero
- if all elements were processed. Otherwise returns a negative value.
- DESCRIPTION
- Iterates over the selected elements in a memory buffer, calling the user's
- callback function for each element. The selection in the dataspace is
- modified so that any elements already iterated over are removed from the
- selection if the iteration is interrupted (by the H5D_operator_t function
- returning non-zero) in the "middle" of the iteration and may be re-started
- by the user where it left off.
-
- NOTE: Until "subtracting" elements from a selection is implemented,
- the selection is not modified.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-static herr_t
-H5S_hyper_select_iterate_mem_opt(H5S_sel_iter_t UNUSED *iter, void *buf, hid_t type_id, H5S_t *space, H5D_operator_t op,
- void *op_data)
-{
- H5S_hyper_dim_t *diminfo; /* Alias for dataspace's diminfo information */
- hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary hyperslab counts */
- hsize_t tmp_block[H5O_LAYOUT_NDIMS]; /* Temporary hyperslab blocks */
- hssize_t offset[H5O_LAYOUT_NDIMS]; /* Offset of element in dataspace */
- hsize_t slab[H5O_LAYOUT_NDIMS]; /* Size of objects in buffer */
- size_t elem_size; /* Size of data element in buffer */
- hssize_t temp_off; /* Offset in a given dimension */
- uint8_t *loc; /* Current element location */
- int i; /* Counter */
- unsigned u; /* Counter */
- int fast_dim; /* Rank of the fastest changing dimension for the dataspace */
- int temp_dim; /* Temporary rank holder */
- unsigned ndims; /* Rank of the dataspace */
- H5T_t *dt; /* Datatype structure */
- herr_t user_ret=0; /* User's return value */
-
- FUNC_ENTER_NOINIT(H5S_hyper_select_iterate_mem_opt);
-
- /* Set some convienence values */
- ndims=space->extent.u.simple.rank;
- fast_dim=ndims-1;
- diminfo=space->select.sel_info.hslab.diminfo;
-
- /* Get the data element size */
- if (NULL==(dt=H5I_object(type_id)))
- HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an valid base datatype");
- elem_size=H5T_get_size(dt);
-
- /* Elements in the fastest dimension are 'elem_size' */
- slab[ndims-1]=elem_size;
-
- /* If we have two or more dimensions, build the other dimension's element sizes */
- if(ndims>=2) {
- /* Build the table of next-dimension down 'element' sizes */
- for(i=ndims-2; i>=0; i--)
- slab[i]=slab[i+1]*space->extent.u.simple.size[i+1];
- } /* end if */
-
- /* Build the tables of count & block sizes as well as the initial offset */
- for(u=0; u<ndims; u++) {
- tmp_count[u]=diminfo[u].count;
- tmp_block[u]=diminfo[u].block;
- offset[u]=(diminfo[u].start+space->select.offset[u]);
- } /* end for */
-
- /* Initialize the starting location */
- for(loc=buf,u=0; u<ndims; u++)
- loc+=offset[u]*slab[u];
-
- /* Go iterate over the hyperslabs */
- while(user_ret==0) {
- /* Iterate over the blocks in the fastest dimension */
- while(tmp_count[fast_dim]>0 && user_ret==0) {
-
- /* Iterate over the elements in the fastest dimension */
- while(tmp_block[fast_dim]>0 && user_ret==0) {
- user_ret=(*op)(loc,type_id,(hsize_t)ndims,offset,op_data);
-
- /* Increment the buffer location */
- loc+=slab[fast_dim];
-
- /* Increment the offset in the dataspace */
- offset[fast_dim]++;
-
- /* Decrement the sequence count */
- tmp_block[fast_dim]--;
- } /* end while */
-
- /* Reset the sequence count */
- tmp_block[fast_dim]=diminfo[fast_dim].block;
-
- /* Move the location to the next sequence to start */
- loc+=(diminfo[fast_dim].stride-diminfo[fast_dim].block)*slab[fast_dim];
-
- /* Move the offset to the next sequence to start */
- offset[fast_dim]+=(diminfo[fast_dim].stride-diminfo[fast_dim].block);
-
- /* Decrement the block count */
- tmp_count[fast_dim]--;
- } /* end while */
-
- /* Check for getting out of iterator, we're done in the 1-D case */
- if(ndims==1)
- goto done; /* Yes, an evil goto.. :-) -QAK */
-
- /* Work on other dimensions if necessary */
- if(fast_dim>0 && user_ret==0) {
- /* Reset the sequence and block counts */
- tmp_block[fast_dim]=diminfo[fast_dim].block;
- tmp_count[fast_dim]=diminfo[fast_dim].count;
-
- /* Bubble up the decrement to the slower changing dimensions */
- temp_dim=fast_dim-1;
- while(temp_dim>=0) {
- /* Decrement the sequence count in this dimension */
- tmp_block[temp_dim]--;
-
- /* Check if we are still in the sequence */
- if(tmp_block[temp_dim]>0)
- break;
-
- /* Reset the sequence count in this dimension */
- tmp_block[temp_dim]=diminfo[temp_dim].block;
-
- /* Decrement the block count */
- tmp_count[temp_dim]--;
-
- /* Check if we have more blocks left */
- if(tmp_count[temp_dim]>0)
- break;
-
- /* Check for getting out of iterator */
- if(temp_dim==0)
- goto done; /* Yes, an evil goto.. :-) -QAK */
-
- /* Reset the block count in this dimension */
- tmp_count[temp_dim]=diminfo[temp_dim].count;
-
- /* Wrapped a dimension, go up to next dimension */
- temp_dim--;
- } /* end while */
- } /* end if */
-
- /* Re-compute buffer location & offset array */
- for(loc=buf,u=0; u<ndims; u++) {
- temp_off=(diminfo[u].start+space->select.offset[u])
- +diminfo[u].stride*(diminfo[u].count-tmp_count[u])
- +(diminfo[u].block-tmp_block[u]);
- loc+=temp_off*slab[u];
- offset[u]=temp_off;
- } /* end for */
- } /* end while */
-
-done:
- FUNC_LEAVE (user_ret);
-} /* end H5S_hyper_select_iterate_mem_opt() */
-
-
-/*--------------------------------------------------------------------------
- NAME
- H5S_hyper_select_iterate
- PURPOSE
- Iterate over a hyperslab selection, calling a user's function for each
- element.
- USAGE
- herr_t H5S_hyper_select_iterate(buf, type_id, space, op, operator_data)
- void *buf; IN/OUT: Buffer containing elements to iterate over
- hid_t type_id; IN: Datatype ID of BUF array.
- H5S_t *space; IN: Dataspace object containing selection to iterate over
- H5D_operator_t op; IN: Function pointer to the routine to be
- called for each element in BUF iterated over.
- void *operator_data; IN/OUT: Pointer to any user-defined data
- associated with the operation.
- RETURNS
- Returns the return value of the last operator if it was non-zero, or zero
- if all elements were processed. Otherwise returns a negative value.
- DESCRIPTION
- Iterates over the selected elements in a memory buffer, calling the user's
- callback function for each element. The selection in the dataspace is
- modified so that any elements already iterated over are removed from the
- selection if the iteration is interrupted (by the H5D_operator_t function
- returning non-zero) in the "middle" of the iteration and may be re-started
- by the user where it left off.
-
- NOTE: Until "subtracting" elements from a selection is implemented,
- the selection is not modified.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-herr_t
-H5S_hyper_select_iterate(void *buf, hid_t type_id, H5S_t *space, H5D_operator_t op,
- void *operator_data)
-{
- H5S_hyper_iter_info_t iter_info; /* Block of parameters to pass into recursive calls */
- H5S_sel_iter_t iter; /* selection iteration info*/
- size_t elmt_size; /* Datatype size */
- H5T_t *dt; /* Datatype structure */
- herr_t ret_value=FAIL; /* return value */
-
- FUNC_ENTER_NOAPI(H5S_hyper_select_iterate, FAIL);
-
- assert(buf);
- assert(space);
- assert(op);
- assert(H5I_DATATYPE == H5I_get_type(type_id));
-
- /* Initialize iterator */
- HDmemset(&iter,0,sizeof(H5S_sel_iter_t));
-
- /* Get the datatype size */
- if (NULL==(dt=H5I_object(type_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an valid base datatype");
- elmt_size=H5T_get_size(dt);
-
- /* Construct iterator for hyperslab selection */
- if (H5S_hyper_init(space, elmt_size, &iter)<0)
- HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection information");
-
- /* Check for the special case of just one H5Sselect_hyperslab call made */
- if(space->select.sel_info.hslab.diminfo!=NULL) {
- /* Use optimized call to iterate over regular hyperslab */
- ret_value=H5S_hyper_select_iterate_mem_opt(&iter,buf,type_id,space,op,operator_data);
- }
- else {
- /* Initialize parameter block for recursive calls */
- iter_info.dt=type_id;
- iter_info.elem_size=elmt_size;
- iter_info.space=space;
- iter_info.iter=&iter;
- iter_info.src=buf;
-
- /* Copy the location of the region in the file */
- iter_info.op=op;
- iter_info.op_data=operator_data;
-
- /* Call the recursive iterator routine */
- ret_value=H5S_hyper_select_iterate_mem_gen(&iter_info);
- } /* end else */
-
- /* Release selection iterator */
- H5S_sel_iter_release(space,&iter);
-
-done:
- FUNC_LEAVE (ret_value);
-} /* H5S_hyper_select_iterate() */
-
-
-/*--------------------------------------------------------------------------
- NAME
H5S_hyper_release
PURPOSE
Release hyperslab selection information for a dataspace
@@ -6364,402 +2227,6 @@ done:
/*--------------------------------------------------------------------------
NAME
- H5S_hyper_select_fill_gen
- PURPOSE
- Fill a hyperslab selection in memory with a value
- USAGE
- herr_t H5S_hyper_select_fill_gen(fill,fill_size,space,buf)
- const void *fill; IN: Pointer to fill value to use
- size_t fill_size; IN: Size of elements in memory buffer & size of
- fill value
- H5S_t *space; IN: Dataspace describing memory buffer &
- containing selection to use.
- void *buf; IN/OUT: Memory buffer to fill selection in
- RETURNS
- Non-negative on success/Negative on failure.
- DESCRIPTION
- Use the selection in the dataspace to fill elements in a memory buffer.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- The memory buffer elements are assumed to have the same datatype as the
- fill value being placed into them.
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-static herr_t
-H5S_hyper_select_fill_gen(const void *fill, size_t fill_size, const H5S_t *space, void *buf)
-{
- H5S_hyper_span_info_t *spans=NULL; /* Pointer to copy of the span tree */
- H5S_hyper_span_info_t *tmp_spans; /* Temporary pointer to a span tree */
- H5S_hyper_span_t *span[H5O_LAYOUT_NDIMS]; /* Array of pointers to span nodes */
- H5S_hyper_span_t *curr_span; /* Current hyperslab span node */
- hsize_t slab[H5O_LAYOUT_NDIMS]; /* Cumulative size of each dimension in bytes */
- hssize_t abs_arr[H5O_LAYOUT_NDIMS]; /* Absolute hyperslab span position */
- hssize_t *off_arr; /* Offset within the dataspace extent */
- hsize_t acc; /* Accumulator for computing cumulative sizes */
- int fast_dim; /* Rank of the fastest changing dimension for the dataspace */
- int curr_dim; /* Current dimension being operated on */
- int ndims; /* Number of dimensions of dataset */
- hsize_t span_io; /* Number of elements in current span to actually process */
- hsize_t num_elem; /* Number of elements in the selection */
- uint8_t *loc; /* Current element location pointer */
- int i; /* Index variable */
- unsigned u; /* Index variable */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOINIT(H5S_hyper_select_fill_gen);
-
- /* Set the rank of the fastest changing dimension */
- ndims=space->extent.u.simple.rank;
- fast_dim=(ndims-1);
-
- /* Set the pointer to the selection offset in the dataspace */
- off_arr=space->select.offset;
-
- /* Make a copy of the span tree to iterate over */
- spans=H5S_hyper_copy_span(space->select.sel_info.hslab.span_lst);
-
- /* Set the nelem & pstride values according to the element size */
- H5S_hyper_span_precompute(spans,fill_size);
-
- /* Build arrays of span heads & offsets in each dimension */
- for(u=0, tmp_spans=spans; u<space->extent.u.simple.rank; u++) {
- /* Set the pointers to the initial span in each dimension */
- assert(tmp_spans);
- assert(tmp_spans->head);
-
- /* Set the pointer to the first span in the list for this node */
- span[u] = tmp_spans->head;
-
- /* Set the initial offset to low bound of span */
- abs_arr[u]=span[u]->low;
-
- /* Get the pointer to the next level down */
- tmp_spans=tmp_spans->head->down;
- } /* end for */
-
- /* Compute sizes of "slab" in each dimension */
- for(i=fast_dim, acc=fill_size; i>=0; i--) {
- slab[i]=acc;
- acc*=space->extent.u.simple.size[i];
- } /* end for */
-
- /* Set the offset of the first element iterated on */
- for(i=0, loc=buf; i<ndims; i++)
- /* Compute the sequential element offset */
- loc+=(abs_arr[i]+off_arr[i])*slab[i];
-
- /* Get the number of elements in selection */
- num_elem=space->select.num_elem;
-
- /* Get the pointer to the current span nodes */
- curr_span=span[fast_dim];
-
- /* Go iterate over the hyperslabs */
- while(num_elem>0) {
- /* Loop through the fastest dim's spans */
- while(curr_span!=NULL) {
- /* Compute the number of elements to attempt in this span */
- span_io=(curr_span->high-curr_span->low)+1;
-
- /* Double check that things haven't gotten out of sync */
- assert(num_elem>0);
-
- /* Fill the elements in the current block */
- H5_CHECK_OVERFLOW(span_io,hsize_t,size_t);
- H5V_array_fill(loc, fill, fill_size, (size_t)span_io);
-
- /* Increment the buffer offset */
- loc+=curr_span->pstride;
-
- /* Decrement the number of elements left */
- num_elem-=span_io;
-
- /* Advance span in fastest dimension */
- curr_span=curr_span->next;
- } /* end while */
-
- /* Check if there are more elements left */
- if(num_elem>0) {
- /* Recursively advance to next offset (not necessarily span) in next dimension up */
-
- /* Start at the fastest dim */
- curr_dim=fast_dim-1;
-
- /* Get the pointer to the correct dimension */
- curr_span=span[curr_dim];
-
- /* Work back up through the dimensions */
- while(curr_dim>=0) {
- /* Increment position in span */
- abs_arr[curr_dim]++;
-
- /* Check if we are still within the span */
- if(abs_arr[curr_dim]<=curr_span->high) {
- break;
- } /* end if */
- /* If we walked off that span, advance to the next span */
- else {
- /* Advance span in this dimension */
- curr_span=curr_span->next;
-
- /* Check if we have a valid span in this dimension still */
- if(curr_span!=NULL) {
- /* Reset the offset for the dim */
- abs_arr[curr_dim]=curr_span->low;
-
- break;
- } /* end if */
- else {
- /* If we finished the span list in this dimension, decrement the dimension worked on and loop again */
- curr_dim--;
-
- /* Reset the curr_span to the next dim */
- if(curr_dim>=0)
- curr_span=span[curr_dim];
- } /* end else */
- } /* end else */
- } /* end while */
-
- /* Reset the span in the current dimension */
- span[curr_dim]=curr_span;
-
- /* Walk back down the iterator positions, reseting them */
- while(curr_dim<fast_dim) {
- assert(curr_span);
- assert(curr_span->down);
- assert(curr_span->down->head);
-
- /* Set the new span for this dimension */
- span[curr_dim+1]=curr_span->down->head;
-
- /* Advance span down the tree */
- curr_span=curr_span->down->head;
-
- /* Reset the offset for the dim */
- abs_arr[curr_dim+1]=curr_span->low;
-
- /* Increment current dimension */
- curr_dim++;
- } /* end while */
-
- /* Verify that the curr_span points to the fastest dim */
- assert(curr_span==span[fast_dim]);
-
- /* Verify that the offset is correct for the fastest dim */
- assert(abs_arr[fast_dim]==curr_span->low);
-
- /* Recompute offset in buffer */
- for(i=0, loc=buf; i<ndims; i++)
- loc+=(abs_arr[i]+off_arr[i])*slab[i];
- } /* end if */
- } /* end while */
-
-#ifdef LATER
-done:
-#endif /* LATER */
- /* Free the copy of the selections span tree */
- if(spans!=NULL)
- H5S_hyper_free_span_info(spans);
-
- FUNC_LEAVE (ret_value);
-} /* end H5S_hyper_select_fill_gen() */
-
-
-/*--------------------------------------------------------------------------
- NAME
- H5S_hyper_select_fill_opt
- PURPOSE
- Fill a hyperslab selection in memory with a value
- USAGE
- herr_t H5S_hyper_select_fill_opt(fill,fill_size,space,buf)
- const void *fill; IN: Pointer to fill value to use
- size_t fill_size; IN: Size of elements in memory buffer & size of
- fill value
- H5S_t *space; IN: Dataspace describing memory buffer &
- containing selection to use.
- void *buf; IN/OUT: Memory buffer to fill selection in
- RETURNS
- Non-negative on success/Negative on failure.
- DESCRIPTION
- Use the selection in the dataspace to fill elements in a memory buffer.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- The memory buffer elements are assumed to have the same datatype as the
- fill value being placed into them.
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-static herr_t
-H5S_hyper_select_fill_opt(const void *fill, size_t fill_size, const H5S_t *space, void *buf)
-{
- H5S_hyper_dim_t *diminfo; /* Alias for dataspace's diminfo information */
- hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary hyperslab counts */
- hsize_t tmp_block[H5O_LAYOUT_NDIMS]; /* Temporary hyperslab blocks */
- hsize_t slab[H5O_LAYOUT_NDIMS]; /* Size of objects in buffer */
- hsize_t acc; /* Size accumulator */
- hsize_t num_elem; /* Number of elements in the selection */
- hsize_t fast_elem; /* Block size in the fastest dimension */
- hsize_t fast_stride; /* Stride in the fastest dimension */
- hssize_t temp_off; /* Offset in a given dimension */
- uint8_t *loc; /* Current element location */
- int i; /* Counter */
- unsigned u; /* Counter */
- int fast_dim; /* Rank of the fastest changing dimension for the dataspace */
- int temp_dim; /* Temporary rank holder */
- unsigned ndims; /* Rank of the dataspace */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOINIT(H5S_hyper_select_fill_opt);
-
- /* Set some convienence values */
- ndims=space->extent.u.simple.rank;
- fast_dim=ndims-1;
- diminfo=space->select.sel_info.hslab.diminfo;
-
- /* Build the table of next-dimension down 'element' sizes */
- for(i=fast_dim, acc=fill_size; i>=0; i--) {
- slab[i]=acc;
- acc*=space->extent.u.simple.size[i];
- } /* end for */
-
- /* Build the tables of count & block sizes as well as the initial starting location */
- for(u=0, loc=buf; u<ndims; u++) {
- tmp_count[u]=diminfo[u].count;
- tmp_block[u]=diminfo[u].block;
- loc+=(diminfo[u].start+space->select.offset[u])*slab[u];
- } /* end for */
-
- /* Get the number of elements in selection */
- num_elem=space->select.num_elem;
-
- /* Get the number of elements in the fastest dimension of the selection */
- fast_elem=tmp_block[fast_dim];
- fast_stride=diminfo[fast_dim].stride;
-
- /* Go iterate over the hyperslabs */
- while(num_elem>0) {
- /* Iterate over the blocks in the fastest dimension */
- while(tmp_count[fast_dim]>0) {
- /* Double check that things haven't gotten out of sync */
- assert(num_elem>0);
-
- /* Fill the elements in the current block */
- H5_CHECK_OVERFLOW(fast_elem,hsize_t,size_t);
- H5V_array_fill(loc, fill, fill_size, (size_t)fast_elem);
-
- /* Advance the pointer in the memory buffer */
- loc+=(fast_stride*fill_size);
-
- /* Decrement the block count */
- tmp_count[fast_dim]--;
-
- /* Decrement the number of elements to process */
- num_elem-=fast_elem;
- } /* end while */
-
- /* Work on other dimensions if necessary */
- if(num_elem>0) {
- /* Reset the sequence and block counts */
- tmp_count[fast_dim]=diminfo[fast_dim].count;
-
- /* Bubble up the decrement to the slower changing dimensions */
- temp_dim=fast_dim-1;
- while(temp_dim>=0) {
- /* Decrement the sequence count in this dimension */
- tmp_block[temp_dim]--;
-
- /* Check if we are still in the sequence */
- if(tmp_block[temp_dim]>0)
- break;
-
- /* Reset the sequence count in this dimension */
- tmp_block[temp_dim]=diminfo[temp_dim].block;
-
- /* Decrement the block count */
- tmp_count[temp_dim]--;
-
- /* Check if we have more blocks left */
- if(tmp_count[temp_dim]>0)
- break;
-
- /* Reset the block count in this dimension */
- tmp_count[temp_dim]=diminfo[temp_dim].count;
-
- /* Wrapped a dimension, go up to next dimension */
- temp_dim--;
- } /* end while */
-
- /* Re-compute buffer location */
- for(loc=buf,u=0; u<ndims; u++) {
- temp_off=(diminfo[u].start+space->select.offset[u])
- +diminfo[u].stride*(diminfo[u].count-tmp_count[u])
- +(diminfo[u].block-tmp_block[u]);
- loc+=temp_off*slab[u];
- } /* end for */
- } /* end if */
- } /* end while */
-
-#ifdef LATER
-done:
-#endif /* LATER */
- FUNC_LEAVE (ret_value);
-} /* end H5S_hyper_select_fill_opt() */
-
-
-/*--------------------------------------------------------------------------
- NAME
- H5S_hyper_select_fill
- PURPOSE
- Fill a hyperslab selection in memory with a value
- USAGE
- herr_t H5S_hyper_select_fill(fill,fill_size,space,buf)
- const void *fill; IN: Pointer to fill value to use
- size_t fill_size; IN: Size of elements in memory buffer & size of
- fill value
- H5S_t *space; IN: Dataspace describing memory buffer &
- containing selection to use.
- void *buf; IN/OUT: Memory buffer to fill selection in
- RETURNS
- Non-negative on success/Negative on failure.
- DESCRIPTION
- Use the selection in the dataspace to fill elements in a memory buffer.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- The memory buffer elements are assumed to have the same datatype as the
- fill value being placed into them.
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-herr_t
-H5S_hyper_select_fill(const void *fill, size_t fill_size, const H5S_t *space, void *buf)
-{
- herr_t ret_value=SUCCEED; /* return value */
-
- FUNC_ENTER_NOAPI(H5S_hyper_select_fill, FAIL);
-
- /* Check args */
- assert(fill);
- assert(fill_size>0);
- assert(space);
- assert(buf);
-
- /* Fill the selection in the memory buffer */
-
- /* Check for the special case of just one H5Sselect_hyperslab call made */
- if(space->select.sel_info.hslab.diminfo!=NULL)
- /* Use optimized call to fill regular hyperslab */
- ret_value=H5S_hyper_select_fill_opt(fill, fill_size, space, buf);
- else
- /* Call the general fill routine */
- ret_value=H5S_hyper_select_fill_gen(fill, fill_size, space, buf);
-
- FUNC_LEAVE (ret_value);
-} /* H5S_hyper_select_fill() */
-
-
-/*--------------------------------------------------------------------------
- NAME
H5S_hyper_recover_span
PURPOSE
Recover a generated span, if appropriate
@@ -9263,3 +4730,1049 @@ done:
FUNC_LEAVE (ret_value);
} /* end H5Sselect_select() */
#endif /* NEW_HYPERSLAB_API */ /* Works */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S_hyper_select_get_seq_list_gen
+ PURPOSE
+ Create a list of offsets & lengths for a selection
+ USAGE
+ herr_t H5S_hyper_select_get_file_list_gen(space,iter,maxseq,nseq,off,len)
+ 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.
+ 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
+ size_t *nbytes; OUT: Actual number of bytes in sequences generated
+ hsize_t *off; OUT: Array of offsets
+ size_t *len; OUT: Array of lengths
+ RETURNS
+ Non-negative on success/Negative on failure.
+ DESCRIPTION
+ Use the selection in the dataspace to generate a list of byte offsets and
+ lengths for the region(s) selected. Start/Restart from the position in the
+ ITER parameter. The number of sequences generated is limited by the MAXSEQ
+ parameter and the number of sequences actually generated is stored in the
+ NSEQ parameter.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static herr_t
+H5S_hyper_select_get_seq_list_gen(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)
+{
+ H5S_hyper_span_t *curr_span; /* Current hyperslab span node */
+ H5S_hyper_span_t **ispan; /* Iterator's hyperslab span nodes */
+ hsize_t slab[H5O_LAYOUT_NDIMS]; /* Cumulative size of each dimension in bytes */
+ hsize_t acc; /* Accumulator for computing cumulative sizes */
+ hsize_t loc_off; /* Element offset in the dataspace */
+ hssize_t *abs_arr; /* Absolute hyperslab span position */
+ hssize_t *off_arr; /* Offset within the dataspace extent */
+ size_t span_size=0; /* Number of bytes in current span to actually process */
+ size_t nelem; /* Number of elements left to process */
+ size_t io_bytes_left; /* Number of bytes left to process */
+ size_t start_io_bytes_left; /* Initial number of bytes left to process */
+ size_t curr_seq=0; /* Number of sequence/offsets stored in the arrays */
+ int ndims; /* Number of dimensions of dataset */
+ int fast_dim; /* Rank of the fastest changing dimension for the dataspace */
+ int curr_dim; /* Current dimension being operated on */
+ int i; /* Index variable */
+ herr_t ret_value=SUCCEED; /* return value */
+
+ FUNC_ENTER_NOINIT (H5S_hyper_select_get_seq_list_gen);
+
+ /* Check args */
+ assert(space);
+ assert(iter);
+ assert(elem_size>0);
+ assert(maxseq>0);
+ assert(maxbytes>0);
+ assert(nseq);
+ assert(nbytes);
+ assert(off);
+ assert(len);
+
+ /* "round" off the maxbytes allowed to a multiple of the element size */
+ maxbytes=(maxbytes/elem_size)*elem_size;
+
+ /* Set the rank of the fastest changing dimension */
+ ndims=space->extent.u.simple.rank;
+ fast_dim=(ndims-1);
+
+ /* Get the pointers to the current span info and span nodes */
+ curr_span=iter->hyp.span[fast_dim];
+ abs_arr=iter->hyp.off;
+ off_arr=space->select.offset;
+ ispan=iter->hyp.span;
+
+ /* Set the amount of elements to perform I/O on, etc. */
+ start_io_bytes_left=io_bytes_left=MIN(maxbytes,(iter->hyp.elmt_left*elem_size));
+ nelem=io_bytes_left/elem_size;
+
+ /* Compute the cumulative size of dataspace dimensions */
+ for(i=fast_dim, acc=elem_size; i>=0; i--) {
+ slab[i]=acc;
+ acc*=space->extent.u.simple.size[i];
+ } /* end for */
+
+ /* Set the offset of the first element iterated on */
+ for(i=0, loc_off=0; i<ndims; i++)
+ /* Compute the sequential element offset */
+ loc_off+=(abs_arr[i]+off_arr[i])*slab[i];
+
+ /* Range check against number of elements left in selection */
+ assert(io_bytes_left<=(iter->hyp.elmt_left*elem_size));
+
+ /* Take care of any partial spans leftover from previous I/Os */
+ if(abs_arr[fast_dim]!=curr_span->low) {
+
+ /* Finish the span in the fastest changing dimension */
+
+ /* Compute the number of bytes to attempt in this span */
+ H5_ASSIGN_OVERFLOW(span_size,((curr_span->high-abs_arr[fast_dim])+1)*elem_size,hsize_t,size_t);
+
+ /* Check number of bytes against upper bounds allowed */
+ if(span_size>io_bytes_left)
+ span_size=io_bytes_left;
+
+ /* Add the partial span to the list of sequences */
+ off[curr_seq]=loc_off;
+ len[curr_seq]=span_size;
+
+ /* Increment sequence count */
+ curr_seq++;
+
+ /* Decrement I/O left to perform */
+ io_bytes_left-=span_size;
+
+ /* Advance the hyperslab iterator */
+ /* Check if we are done */
+ if(io_bytes_left>0) {
+ /* Move to next span in fastest changing dimension */
+ curr_span=curr_span->next;
+
+ if(curr_span!=NULL) {
+ /* Move location offset of destination */
+ loc_off+=(curr_span->low-abs_arr[fast_dim])*elem_size;
+
+ /* Move iterator for fastest changing dimension */
+ abs_arr[fast_dim]=curr_span->low;
+ } /* end if */
+ } /* end if */
+ else {
+ abs_arr[fast_dim]+=span_size/elem_size;
+
+ /* Check if we are still within the span */
+ if(abs_arr[fast_dim]<=curr_span->high) {
+ iter->hyp.span[fast_dim]=curr_span;
+
+ goto partial_done; /* finished with partial span */
+ } /* end if */
+ /* If we walked off that span, advance to the next span */
+ else {
+ /* Advance span in this dimension */
+ curr_span=curr_span->next;
+
+ /* Check if we have a valid span in this dimension still */
+ if(curr_span!=NULL) {
+ /* Reset absolute position */
+ abs_arr[fast_dim]=curr_span->low;
+ iter->hyp.span[fast_dim]=curr_span;
+
+ goto partial_done; /* finished with partial span */
+ } /* end if */
+ } /* end else */
+ } /* end else */
+
+ /* Adjust iterator pointers */
+
+ if(curr_span==NULL) {
+/* Same as code in main loop */
+ /* Start at the next fastest dim */
+ curr_dim=fast_dim-1;
+
+ /* Work back up through the dimensions */
+ while(curr_dim>=0) {
+ /* Reset the current span */
+ curr_span=iter->hyp.span[curr_dim];
+
+ /* Increment absolute position */
+ abs_arr[curr_dim]++;
+
+ /* Check if we are still within the span */
+ if(abs_arr[curr_dim]<=curr_span->high) {
+ break;
+ } /* end if */
+ /* If we walked off that span, advance to the next span */
+ else {
+ /* Advance span in this dimension */
+ curr_span=curr_span->next;
+
+ /* Check if we have a valid span in this dimension still */
+ if(curr_span!=NULL) {
+ /* Reset the span in the current dimension */
+ ispan[curr_dim]=curr_span;
+
+ /* Reset absolute position */
+ abs_arr[curr_dim]=curr_span->low;
+
+ break;
+ } /* end if */
+ else {
+ /* If we finished the span list in this dimension, decrement the dimension worked on and loop again */
+ curr_dim--;
+ } /* end else */
+ } /* end else */
+ } /* end while */
+
+ /* Check if we are finished with the spans in the tree */
+ if(curr_dim<0) {
+ /* We had better be done with I/O or bad things are going to happen... */
+ assert(io_bytes_left==0);
+
+ goto partial_done; /* finished with partial span */
+ } /* end if */
+ else {
+ /* Walk back down the iterator positions, reseting them */
+ while(curr_dim<fast_dim) {
+ assert(curr_span);
+ assert(curr_span->down);
+ assert(curr_span->down->head);
+
+ /* Increment current dimension */
+ curr_dim++;
+
+ /* Set the new span_info & span for this dimension */
+ iter->hyp.span[curr_dim]=curr_span->down->head;
+
+ /* Advance span down the tree */
+ curr_span=curr_span->down->head;
+
+ /* Reset the absolute offset for the dim */
+ abs_arr[curr_dim]=curr_span->low;
+ } /* end while */
+
+ /* Verify that the curr_span points to the fastest dim */
+ assert(curr_span==iter->hyp.span[fast_dim]);
+ } /* end else */
+
+ /* Reset the buffer offset */
+ for(i=0, loc_off=0; i<ndims; i++)
+ loc_off+=(abs_arr[i]+off_arr[i])*slab[i];
+ } /* end if */
+ } /* end if */
+
+partial_done: /* Yes, goto's are evil, so sue me... :-) */
+
+ /* Perform the I/O on the elements, based on the position of the iterator */
+ while(io_bytes_left>0 && curr_seq<maxseq) {
+ /* Adjust location offset of destination to compensate for initial increment below */
+ loc_off-=curr_span->pstride;
+
+ /* Loop over all the spans in the fastest changing dimension */
+ while(curr_span!=NULL) {
+ /* Move location offset of destination */
+ loc_off+=curr_span->pstride;
+
+ /* Compute the number of elements to attempt in this span */
+ H5_ASSIGN_OVERFLOW(span_size,curr_span->nelem,hsize_t,size_t);
+
+ /* Check number of elements against upper bounds allowed */
+ if(span_size>=io_bytes_left) {
+ /* Trim the number of bytes to output */
+ span_size=io_bytes_left;
+ io_bytes_left=0;
+
+/* COMMON */
+ /* Store the I/O information for the span */
+ off[curr_seq]=loc_off;
+ len[curr_seq]=span_size;
+
+ /* Increment the number of sequences in arrays */
+ curr_seq++;
+
+ /* If the sequence & offset arrays are full, do what? */
+ if(curr_seq>=maxseq) {
+ /* Break out now, we are finished with sequences */
+ break;
+
+ } /* end else */
+/* end COMMON */
+
+ /* Break out now, we are finished with I/O */
+ break;
+ } /* end if */
+ else {
+ /* Decrement I/O left to perform */
+ io_bytes_left-=span_size;
+
+/* COMMON */
+ /* Store the I/O information for the span */
+ off[curr_seq]=loc_off;
+ len[curr_seq]=span_size;
+
+ /* Increment the number of sequences in arrays */
+ curr_seq++;
+
+ /* If the sequence & offset arrays are full, do what? */
+ if(curr_seq>=maxseq) {
+ /* Break out now, we are finished with sequences */
+ break;
+ } /* end else */
+/* end COMMON */
+ } /* end else */
+
+ /* Move to next span in fastest changing dimension */
+ curr_span=curr_span->next;
+ } /* end while */
+
+ /* Check if we are done */
+ if(io_bytes_left==0 || curr_seq>=maxseq) {
+ abs_arr[fast_dim]=curr_span->low+(span_size/elem_size);
+
+ /* Check if we are still within the span */
+ if(abs_arr[fast_dim]<=curr_span->high) {
+ iter->hyp.span[fast_dim]=curr_span;
+ break;
+ } /* end if */
+ /* If we walked off that span, advance to the next span */
+ else {
+ /* Advance span in this dimension */
+ curr_span=curr_span->next;
+
+ /* Check if we have a valid span in this dimension still */
+ if(curr_span!=NULL) {
+ /* Reset absolute position */
+ abs_arr[fast_dim]=curr_span->low;
+ iter->hyp.span[fast_dim]=curr_span;
+ break;
+ } /* end if */
+ } /* end else */
+ } /* end if */
+
+ /* Adjust iterator pointers */
+
+ /* Start at the next fastest dim */
+ curr_dim=fast_dim-1;
+
+ /* Work back up through the dimensions */
+ while(curr_dim>=0) {
+ /* Reset the current span */
+ curr_span=iter->hyp.span[curr_dim];
+
+ /* Increment absolute position */
+ abs_arr[curr_dim]++;
+
+ /* Check if we are still within the span */
+ if(abs_arr[curr_dim]<=curr_span->high) {
+ break;
+ } /* end if */
+ /* If we walked off that span, advance to the next span */
+ else {
+ /* Advance span in this dimension */
+ curr_span=curr_span->next;
+
+ /* Check if we have a valid span in this dimension still */
+ if(curr_span!=NULL) {
+ /* Reset the span in the current dimension */
+ ispan[curr_dim]=curr_span;
+
+ /* Reset absolute position */
+ abs_arr[curr_dim]=curr_span->low;
+
+ break;
+ } /* end if */
+ else {
+ /* If we finished the span list in this dimension, decrement the dimension worked on and loop again */
+ curr_dim--;
+ } /* end else */
+ } /* end else */
+ } /* end while */
+
+ /* Check if we are finished with the spans in the tree */
+ if(curr_dim<0) {
+ /* We had better be done with I/O or bad things are going to happen... */
+ assert(io_bytes_left==0);
+ break;
+ } /* end if */
+ else {
+ /* Walk back down the iterator positions, reseting them */
+ while(curr_dim<fast_dim) {
+ assert(curr_span);
+ assert(curr_span->down);
+ assert(curr_span->down->head);
+
+ /* Increment current dimension to the next dimension down */
+ curr_dim++;
+
+ /* Set the new span for the next dimension down */
+ iter->hyp.span[curr_dim]=curr_span->down->head;
+
+ /* Advance span down the tree */
+ curr_span=curr_span->down->head;
+
+ /* Reset the absolute offset for the dim */
+ abs_arr[curr_dim]=curr_span->low;
+ } /* end while */
+
+ /* Verify that the curr_span points to the fastest dim */
+ assert(curr_span==iter->hyp.span[fast_dim]);
+ } /* end else */
+
+ /* Reset the buffer offset */
+ for(i=0, loc_off=0; i<ndims; i++)
+ loc_off+=(abs_arr[i]+off_arr[i])*slab[i];
+ } /* end while */
+
+ /* Decrement number of elements left in iterator */
+ iter->hyp.elmt_left-=(nelem-(io_bytes_left/elem_size));
+
+ /* Set the number of sequences generated */
+ *nseq=curr_seq;
+
+ /* Set the number of bytes used */
+ *nbytes=(start_io_bytes_left-io_bytes_left);
+
+#ifdef LATER
+done:
+#endif /* LATER */
+ FUNC_LEAVE (ret_value);
+} /* end H5S_hyper_select_get_seq_list_gen() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S_hyper_select_get_seq_list_opt
+ PURPOSE
+ Create a list of offsets & lengths for a selection
+ USAGE
+ herr_t H5S_hyper_select_get_file_list_opt(space,iter,maxseq,nseq,off,len)
+ 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.
+ 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
+ size_t *nbytes; OUT: Actual number of bytes in sequences generated
+ hsize_t *off; OUT: Array of offsets
+ size_t *len; OUT: Array of lengths
+ RETURNS
+ Non-negative on success/Negative on failure.
+ DESCRIPTION
+ Use the selection in the dataspace to generate a list of byte offsets and
+ lengths for the region(s) selected. Start/Restart from the position in the
+ ITER parameter. The number of sequences generated is limited by the MAXSEQ
+ parameter and the number of sequences actually generated is stored in the
+ NSEQ parameter.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static herr_t
+H5S_hyper_select_get_seq_list_opt(const H5S_t *space,H5S_sel_iter_t *iter,
+ size_t elmt_size, size_t maxseq, size_t maxbytes, size_t *nseq, size_t *nbytes,
+ hsize_t *off, size_t *len)
+{
+ hsize_t mem_size[H5O_LAYOUT_NDIMS]; /* Size of the source buffer */
+ hsize_t slab[H5O_LAYOUT_NDIMS]; /* Hyperslab size */
+ hssize_t *sel_off; /* Selection offset in dataspace */
+ hssize_t offset[H5O_LAYOUT_NDIMS]; /* Coordinate offset in dataspace */
+ hsize_t tmp_count[H5O_LAYOUT_NDIMS];/* Temporary block count */
+ hsize_t tmp_block[H5O_LAYOUT_NDIMS];/* Temporary block offset */
+ hssize_t wrap[H5O_LAYOUT_NDIMS]; /* Bytes to wrap around at the end of a row */
+ hsize_t skip[H5O_LAYOUT_NDIMS]; /* Bytes to skip between blocks */
+ const H5S_hyper_dim_t *tdiminfo; /* Temporary pointer to diminfo information */
+ hssize_t fast_dim_start, /* Local copies of fastest changing dimension info */
+ fast_dim_offset;
+ hsize_t fast_dim_stride, /* Local copies of fastest changing dimension info */
+ fast_dim_block;
+ size_t fast_dim_buf_off; /* Local copy of amount to move fastest dimension buffer offset */
+ size_t fast_dim_count; /* Number of blocks left in fastest changing dimension */
+ size_t tot_blk_count; /* Total number of blocks left to output */
+ size_t act_blk_count; /* Actual number of blocks to output */
+ size_t total_rows; /* Total number of entire rows to output */
+ size_t curr_rows; /* Current number of entire rows to output */
+ int fast_dim; /* Rank of the fastest changing dimension for the dataspace */
+ int temp_dim; /* Temporary rank holder */
+ int ndims; /* Number of dimensions of dataset */
+ hsize_t acc; /* Accumulator */
+ hsize_t loc; /* Coordinate offset */
+ int i; /* Local index variable */
+ size_t curr_seq=0; /* Current sequence being operated on */
+ size_t actual_elem; /* The actual number of elements to count */
+ size_t actual_bytes;/* The actual number of bytes to copy */
+ size_t nelmts; /* Starting number of elements */
+ size_t io_left; /* The number of elements left in I/O operation */
+ size_t start_io_left; /* The initial number of elements left in I/O operation */
+#ifndef NO_DUFFS_DEVICE
+ size_t duffs_index; /* Counting index for Duff's device */
+#endif /* NO_DUFFS_DEVICE */
+ herr_t ret_value=SUCCEED; /* return value */
+
+ FUNC_ENTER_NOINIT (H5S_hyper_select_get_seq_list_opt);
+
+ /* Check args */
+ assert(space);
+ assert(iter);
+ assert(elmt_size>0);
+ assert(maxseq>0);
+ assert(maxbytes>0);
+ assert(nseq);
+ assert(nbytes);
+ assert(off);
+ assert(len);
+
+ /* Check if this is a "flattened" regular hyperslab selection */
+ if(iter->hyp.iter_rank!=0 && iter->hyp.iter_rank<space->extent.u.simple.rank) {
+ /* Set the aliases for a few important dimension ranks */
+ ndims=iter->hyp.iter_rank;
+ fast_dim=ndims-1;
+
+ /* Set the local copy of the diminfo pointer */
+ tdiminfo=iter->hyp.diminfo;
+
+ /* Set the local copy of the selection offset */
+ sel_off=iter->hyp.sel_off;
+
+ /* Set up the size of the memory space */
+ HDmemcpy(mem_size, iter->hyp.size, ndims*sizeof(hsize_t));
+ } /* end if */
+ else {
+ /* Set the aliases for a few important dimension ranks */
+ ndims=space->extent.u.simple.rank;
+ fast_dim=ndims-1;
+
+ /* Set the local copy of the diminfo pointer */
+ tdiminfo=space->select.sel_info.hslab.diminfo;
+
+ /* Set the local copy of the selection offset */
+ sel_off=space->select.offset;
+
+ /* Set up the size of the memory space */
+ HDmemcpy(mem_size, space->extent.u.simple.size, ndims*sizeof(hsize_t));
+ } /* end else */
+ mem_size[ndims]=elmt_size;
+
+ /* initialize row sizes for each dimension */
+ for(i=(ndims-1),acc=1; i>=0; i--) {
+ slab[i]=acc*elmt_size;
+ acc*=mem_size[i];
+ } /* end for */
+
+ /* Get the number of elements left in the selection */
+ H5_ASSIGN_OVERFLOW(io_left,iter->hyp.elmt_left,hsize_t,size_t);
+
+ /* Calculate the number of elements to sequence through */
+ start_io_left=io_left=MIN(io_left,(maxbytes/elmt_size));
+
+ /* Check if we stopped in the middle of a sequence of elements */
+ if((iter->hyp.off[fast_dim]-tdiminfo[fast_dim].start)%tdiminfo[fast_dim].stride!=0 ||
+ ((iter->hyp.off[fast_dim]!=tdiminfo[fast_dim].start) && tdiminfo[fast_dim].stride==1)) {
+ size_t leftover; /* The number of elements left over from the last sequence */
+
+ /* Calculate the number of elements left in the sequence */
+ if(tdiminfo[fast_dim].stride==1)
+ leftover=tdiminfo[fast_dim].block-(iter->hyp.off[fast_dim]-tdiminfo[fast_dim].start);
+ else
+ leftover=tdiminfo[fast_dim].block-((iter->hyp.off[fast_dim]-tdiminfo[fast_dim].start)%tdiminfo[fast_dim].stride);
+
+ /* Make certain that we don't write too many */
+ actual_elem=MIN(leftover,io_left);
+
+ /* Compute the initial buffer offset */
+ for(i=0,loc=0; i<ndims; i++)
+ loc+=(iter->hyp.off[i]+sel_off[i])*slab[i];
+
+ /* Add a new sequence */
+ off[curr_seq]=loc;
+ H5_ASSIGN_OVERFLOW(len[curr_seq],actual_elem*elmt_size,hsize_t,size_t);
+
+ /* Increment sequence count */
+ curr_seq++;
+
+ /* Decrement the number of elements left */
+ io_left -= actual_elem;
+
+ /* Advance the hyperslab iterator */
+
+ /* If we had enough room to count the rest of the sequence
+ * in the fastest changing dimension, move the iterator offset to
+ * the beginning of the next block to write. Otherwise, just advance
+ * the iterator in the fastest changing dimension.
+ */
+ if(actual_elem==leftover) {
+ /* Move iterator offset to beginning of next sequence in the fastest changing dimension */
+ H5S_hyper_iter_next(space,iter);
+ } /* end if */
+ else {
+ iter->hyp.off[fast_dim]+=actual_elem; /* whole sequence not written out, just advance fastest dimension offset */
+ } /* end else */
+
+ /* Decrement the number of elements left in selection */
+ iter->hyp.elmt_left-=actual_elem;
+ } /* end if */
+
+ /* Now that we've cleared the "remainder" of the previous fastest dimension
+ * sequence, we must be at the beginning of a sequence, so use the fancy
+ * algorithm to compute the offsets and run through as many as possible,
+ * until the buffer fills up.
+ */
+ if(io_left>0 && curr_seq<maxseq) { /* Just in case the "remainder" above filled the buffer */
+ /* Keep the number of elements we started with */
+ nelmts=io_left;
+
+ /* Compute the arrays to perform I/O on */
+ /* Copy the location of the point to get */
+ HDmemcpy(offset, iter->hyp.off,ndims*sizeof(hssize_t));
+
+ /* Add in the selection offset */
+ for(i=0; i<ndims; i++)
+ offset[i] += sel_off[i];
+
+ /* Compute the current "counts" for this location */
+ for(i=0; i<ndims; i++) {
+ if(tdiminfo[i].stride==1) {
+ tmp_count[i] = 0;
+ tmp_block[i] = iter->hyp.off[i]-tdiminfo[i].start;
+ } /* end if */
+ else {
+ tmp_count[i] = (iter->hyp.off[i]-tdiminfo[i].start)/tdiminfo[i].stride;
+ tmp_block[i] = (iter->hyp.off[i]-tdiminfo[i].start)%tdiminfo[i].stride;
+ } /* end else */
+ } /* end for */
+
+ /* Compute the initial buffer offset */
+ for(i=0,loc=0; i<ndims; i++)
+ loc+=offset[i]*slab[i];
+
+ /* Set the number of elements to write each time */
+ H5_ASSIGN_OVERFLOW(actual_elem,tdiminfo[fast_dim].block,hsize_t,size_t);
+
+ /* Set the number of actual bytes */
+ actual_bytes=actual_elem*elmt_size;
+
+ /* Set local copies of information for the fastest changing dimension */
+ fast_dim_start=tdiminfo[fast_dim].start;
+ fast_dim_stride=tdiminfo[fast_dim].stride;
+ fast_dim_block=tdiminfo[fast_dim].block;
+ H5_ASSIGN_OVERFLOW(fast_dim_buf_off,slab[fast_dim]*fast_dim_stride,hsize_t,size_t);
+ fast_dim_offset=fast_dim_start+sel_off[fast_dim];
+
+ /* Compute the number of blocks which would fit into the buffer */
+ tot_blk_count=io_left/fast_dim_block;
+
+ /* Don't go over the maximum number of sequences allowed */
+ tot_blk_count=MIN(tot_blk_count,(maxseq-curr_seq));
+
+ /* Compute the amount to wrap at the end of each row */
+ for(i=0; i<ndims; i++)
+ wrap[i]=(mem_size[i]-(tdiminfo[i].stride*tdiminfo[i].count))*slab[i];
+
+ /* Compute the amount to skip between blocks */
+ for(i=0; i<ndims; i++)
+ skip[i]=(tdiminfo[i].stride-tdiminfo[i].block)*slab[i];
+
+ /* Check if there is a partial row left (with full blocks) */
+ if(tmp_count[fast_dim]>0) {
+ /* Get number of blocks in fastest dimension */
+ H5_ASSIGN_OVERFLOW(fast_dim_count,tdiminfo[fast_dim].count-tmp_count[fast_dim],hsize_t,size_t);
+
+ /* Make certain this entire row will fit into buffer */
+ fast_dim_count=MIN(fast_dim_count,tot_blk_count);
+
+ /* Number of blocks to sequence over */
+ act_blk_count=fast_dim_count;
+
+ /* Loop over all the blocks in the fastest changing dimension */
+ while(fast_dim_count>0) {
+ /* Store the sequence information */
+ off[curr_seq]=loc;
+ len[curr_seq]=actual_bytes;
+
+ /* Increment sequence count */
+ curr_seq++;
+
+ /* Increment information to reflect block just processed */
+ loc+=fast_dim_buf_off;
+
+ /* Decrement number of blocks */
+ fast_dim_count--;
+ } /* end while */
+
+ /* Decrement number of elements left */
+ io_left -= actual_elem*act_blk_count;
+
+ /* Decrement number of blocks left */
+ tot_blk_count -= act_blk_count;
+
+ /* Increment information to reflect block just processed */
+ tmp_count[fast_dim]+=act_blk_count;
+
+ /* Check if we finished the entire row of blocks */
+ if(tmp_count[fast_dim]>=tdiminfo[fast_dim].count) {
+ /* Increment offset in destination buffer */
+ loc += wrap[fast_dim];
+
+ /* Increment information to reflect block just processed */
+ offset[fast_dim]=fast_dim_offset; /* reset the offset in the fastest dimension */
+ tmp_count[fast_dim]=0;
+
+ /* Increment the offset and count for the other dimensions */
+ temp_dim=fast_dim-1;
+ while(temp_dim>=0) {
+ /* Move to the next row in the curent dimension */
+ offset[temp_dim]++;
+ tmp_block[temp_dim]++;
+
+ /* If this block is still in the range of blocks to output for the dimension, break out of loop */
+ if(tmp_block[temp_dim]<tdiminfo[temp_dim].block)
+ break;
+ else {
+ /* Move to the next block in the current dimension */
+ offset[temp_dim]+=(tdiminfo[temp_dim].stride-tdiminfo[temp_dim].block);
+ loc += skip[temp_dim];
+ tmp_block[temp_dim]=0;
+ tmp_count[temp_dim]++;
+
+ /* If this block is still in the range of blocks to output for the dimension, break out of loop */
+ if(tmp_count[temp_dim]<tdiminfo[temp_dim].count)
+ break;
+ else {
+ offset[temp_dim]=tdiminfo[temp_dim].start+sel_off[temp_dim];
+ loc += wrap[temp_dim];
+ tmp_count[temp_dim]=0; /* reset back to the beginning of the line */
+ tmp_block[temp_dim]=0;
+ } /* end else */
+ } /* end else */
+
+ /* Decrement dimension count */
+ temp_dim--;
+ } /* end while */
+ } /* end if */
+ else {
+ /* Update the offset in the fastest dimension */
+ offset[fast_dim]+=(fast_dim_stride*act_blk_count);
+ } /* end else */
+ } /* end if */
+
+ /* Compute the number of entire rows to read in */
+ curr_rows=total_rows=tot_blk_count/tdiminfo[fast_dim].count;
+
+ /* Reset copy of number of blocks in fastest dimension */
+ H5_ASSIGN_OVERFLOW(fast_dim_count,tdiminfo[fast_dim].count,hsize_t,size_t);
+
+ /* Read in data until an entire sequence can't be written out any longer */
+ while(curr_rows>0) {
+#ifdef NO_DUFFS_DEVICE
+ /* Loop over all the blocks in the fastest changing dimension */
+ while(fast_dim_count>0) {
+ /* Store the sequence information */
+ off[curr_seq]=loc;
+ len[curr_seq]=actual_bytes;
+
+ /* Increment sequence count */
+ curr_seq++;
+
+ /* Increment information to reflect block just processed */
+ loc+=fast_dim_buf_off;
+
+ /* Decrement number of blocks */
+ fast_dim_count--;
+ } /* end while */
+#else /* NO_DUFFS_DEVICE */
+ duffs_index = (fast_dim_count + 7) / 8;
+ switch (fast_dim_count % 8) {
+ case 0:
+ do
+ {
+ /* Store the sequence information */
+ off[curr_seq]=loc;
+ len[curr_seq]=actual_bytes;
+
+ /* Increment sequence count */
+ curr_seq++;
+
+ /* Increment information to reflect block just processed */
+ loc+=fast_dim_buf_off;
+
+ case 7:
+ /* Store the sequence information */
+ off[curr_seq]=loc;
+ len[curr_seq]=actual_bytes;
+
+ /* Increment sequence count */
+ curr_seq++;
+
+ /* Increment information to reflect block just processed */
+ loc+=fast_dim_buf_off;
+
+ case 6:
+ /* Store the sequence information */
+ off[curr_seq]=loc;
+ len[curr_seq]=actual_bytes;
+
+ /* Increment sequence count */
+ curr_seq++;
+
+ /* Increment information to reflect block just processed */
+ loc+=fast_dim_buf_off;
+
+ case 5:
+ /* Store the sequence information */
+ off[curr_seq]=loc;
+ len[curr_seq]=actual_bytes;
+
+ /* Increment sequence count */
+ curr_seq++;
+
+ /* Increment information to reflect block just processed */
+ loc+=fast_dim_buf_off;
+
+ case 4:
+ /* Store the sequence information */
+ off[curr_seq]=loc;
+ len[curr_seq]=actual_bytes;
+
+ /* Increment sequence count */
+ curr_seq++;
+
+ /* Increment information to reflect block just processed */
+ loc+=fast_dim_buf_off;
+
+ case 3:
+ /* Store the sequence information */
+ off[curr_seq]=loc;
+ len[curr_seq]=actual_bytes;
+
+ /* Increment sequence count */
+ curr_seq++;
+
+ /* Increment information to reflect block just processed */
+ loc+=fast_dim_buf_off;
+
+ case 2:
+ /* Store the sequence information */
+ off[curr_seq]=loc;
+ len[curr_seq]=actual_bytes;
+
+ /* Increment sequence count */
+ curr_seq++;
+
+ /* Increment information to reflect block just processed */
+ loc+=fast_dim_buf_off;
+
+ case 1:
+ /* Store the sequence information */
+ off[curr_seq]=loc;
+ len[curr_seq]=actual_bytes;
+
+ /* Increment sequence count */
+ curr_seq++;
+
+ /* Increment information to reflect block just processed */
+ loc+=fast_dim_buf_off;
+
+ } while (--duffs_index > 0);
+ } /* end switch */
+#endif /* NO_DUFFS_DEVICE */
+
+ /* Increment offset in destination buffer */
+ loc += wrap[fast_dim];
+
+ /* Increment the offset and count for the other dimensions */
+ temp_dim=fast_dim-1;
+ while(temp_dim>=0) {
+ /* Move to the next row in the curent dimension */
+ offset[temp_dim]++;
+ tmp_block[temp_dim]++;
+
+ /* If this block is still in the range of blocks to output for the dimension, break out of loop */
+ if(tmp_block[temp_dim]<tdiminfo[temp_dim].block)
+ break;
+ else {
+ /* Move to the next block in the current dimension */
+ offset[temp_dim]+=(tdiminfo[temp_dim].stride-tdiminfo[temp_dim].block);
+ loc += skip[temp_dim];
+ tmp_block[temp_dim]=0;
+ tmp_count[temp_dim]++;
+
+ /* If this block is still in the range of blocks to output for the dimension, break out of loop */
+ if(tmp_count[temp_dim]<tdiminfo[temp_dim].count)
+ break;
+ else {
+ offset[temp_dim]=tdiminfo[temp_dim].start+sel_off[temp_dim];
+ loc += wrap[temp_dim];
+ tmp_count[temp_dim]=0; /* reset back to the beginning of the line */
+ tmp_block[temp_dim]=0;
+ } /* end else */
+ } /* end else */
+
+ /* Decrement dimension count */
+ temp_dim--;
+ } /* end while */
+
+ /* Decrement the number of rows left */
+ curr_rows--;
+ } /* end while */
+
+ /* Adjust the number of blocks & elements left to transfer */
+
+ /* Decrement number of elements left */
+ io_left -= actual_elem*(total_rows*tdiminfo[fast_dim].count);
+
+ /* Decrement number of blocks left */
+ tot_blk_count -= (total_rows*tdiminfo[fast_dim].count);
+
+ /* Read in partial row of blocks */
+ if(io_left>0 && curr_seq<maxseq) {
+ /* Get remaining number of blocks left to output */
+ fast_dim_count=tot_blk_count;
+
+ /* Loop over all the blocks in the fastest changing dimension */
+ while(fast_dim_count>0) {
+ /* Store the sequence information */
+ off[curr_seq]=loc;
+ len[curr_seq]=actual_bytes;
+
+ /* Increment sequence count */
+ curr_seq++;
+
+ /* Increment information to reflect block just processed */
+ loc+=fast_dim_buf_off;
+
+ /* Decrement number of blocks */
+ fast_dim_count--;
+ } /* end while */
+
+ /* Decrement number of elements left */
+ io_left -= actual_elem*tot_blk_count;
+
+ /* Increment information to reflect block just processed */
+ offset[fast_dim]+=(fast_dim_stride*tot_blk_count); /* move the offset in the fastest dimension */
+
+ /* Handle any leftover, partial blocks in this row */
+ if(io_left>0 && curr_seq<maxseq) {
+ actual_elem=io_left;
+ actual_bytes=actual_elem*elmt_size;
+
+ /* Store the sequence information */
+ off[curr_seq]=loc;
+ len[curr_seq]=actual_bytes;
+
+ /* Increment sequence count */
+ curr_seq++;
+
+ /* Decrement the number of elements left */
+ io_left -= actual_elem;
+
+ /* Increment buffer correctly */
+ offset[fast_dim]+=actual_elem;
+ } /* end if */
+
+ /* don't bother checking slower dimensions */
+ assert(io_left==0 || curr_seq==maxseq);
+ } /* end if */
+
+
+ /* Update the iterator */
+
+ /* Subtract out the selection offset */
+ for(i=0; i<ndims; i++)
+ offset[i] -= sel_off[i];
+
+ /* Update the iterator with the location we stopped */
+ HDmemcpy(iter->hyp.off, offset, ndims*sizeof(hssize_t));
+
+ /* Decrement the number of elements left in selection */
+ iter->hyp.elmt_left-=(nelmts-io_left);
+ } /* end if */
+
+ /* Set the number of sequences generated */
+ *nseq=curr_seq;
+
+ /* Set the number of bytes used */
+ *nbytes=(start_io_left-io_left)*elmt_size;
+
+#ifdef LATER
+done:
+#endif /* LATER */
+ FUNC_LEAVE (ret_value);
+} /* end H5S_hyper_select_get_seq_list_opt() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S_hyper_select_get_seq_list
+ PURPOSE
+ Create a list of offsets & lengths for a selection
+ USAGE
+ herr_t H5S_hyper_select_get_seq_list(flags,space,iter,elem_size,maxseq,maxbytes,nseq,nbytes,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.
+ 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
+ size_t *nbytes; OUT: Actual number of bytes in sequences generated
+ hsize_t *off; OUT: Array of offsets
+ size_t *len; OUT: Array of lengths
+ RETURNS
+ Non-negative on success/Negative on failure.
+ DESCRIPTION
+ Use the selection in the dataspace to generate a list of byte offsets and
+ lengths for the region(s) selected. Start/Restart from the position in the
+ ITER parameter. The number of sequences generated is limited by the MAXSEQ
+ parameter and the number of sequences actually generated is stored in the
+ NSEQ parameter.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5S_hyper_select_get_seq_list(unsigned UNUSED 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=FAIL; /* return value */
+
+ FUNC_ENTER_NOAPI (H5S_hyper_select_get_seq_list, FAIL);
+
+ /* Check args */
+ assert(space);
+ assert(iter);
+ assert(elem_size>0);
+ assert(maxseq>0);
+ assert(maxbytes>0);
+ assert(nseq);
+ assert(nbytes);
+ assert(off);
+ assert(len);
+
+ /* Check for the special case of just one H5Sselect_hyperslab call made */
+ if(space->select.sel_info.hslab.diminfo!=NULL)
+ /* Use optimized call to generate sequence list */
+ ret_value=H5S_hyper_select_get_seq_list_opt(space,iter,elem_size,maxseq,maxbytes,nseq,nbytes,off,len);
+ else
+ /* Call the general sequence generator routine */
+ ret_value=H5S_hyper_select_get_seq_list_gen(space,iter,elem_size,maxseq,maxbytes,nseq,nbytes,off,len);
+
+#ifdef LATER
+done:
+#endif /* LATER */
+ FUNC_LEAVE (ret_value);
+} /* end H5S_hyper_select_get_seq_list() */
+
diff --git a/src/H5Spkg.h b/src/H5Spkg.h
index 1ab7dd6..d31d894 100644
--- a/src/H5Spkg.h
+++ b/src/H5Spkg.h
@@ -72,12 +72,12 @@ struct H5S_hyper_span_info_t {
};
/* Information about one dimension in a hyperslab selection */
-typedef struct {
+struct H5S_hyper_dim_t {
hssize_t start;
hsize_t stride;
hsize_t count;
hsize_t block;
-} H5S_hyper_dim_t;
+};
/* Information about new-style hyperslab selection */
typedef struct {
@@ -117,10 +117,12 @@ struct H5S_t {
__DLL__ herr_t H5S_close_simple(H5S_simple_t *simple);
__DLL__ herr_t H5S_release_simple(H5S_simple_t *simple);
__DLL__ herr_t H5S_extent_copy(H5S_extent_t *dst, const H5S_extent_t *src);
-__DLL__ herr_t H5S_register(H5S_sel_type cls, const H5S_fconv_t *fconv,
- const H5S_mconv_t *mconv);
/* Point select functions */
+__DLL__ herr_t H5S_point_init (const H5S_t *space, size_t elmt_size,
+ H5S_sel_iter_t *iter);
+__DLL__ hsize_t H5S_point_favail (const H5S_t *space, const H5S_sel_iter_t *iter,
+ hsize_t max);
__DLL__ herr_t H5S_point_add(H5S_t *space, H5S_seloper_t op, size_t num_elem,
const hssize_t **coord);
__DLL__ herr_t H5S_point_release(H5S_t *space);
@@ -136,33 +138,29 @@ __DLL__ htri_t H5S_point_select_single(const H5S_t *space);
__DLL__ htri_t H5S_point_select_regular(const H5S_t *space);
__DLL__ herr_t H5S_select_elements (H5S_t *space, H5S_seloper_t op,
size_t num_elem, const hssize_t **coord);
-__DLL__ herr_t H5S_point_select_iterate(void *buf, hid_t type_id, H5S_t *space,
- H5D_operator_t op, void *operator_data);
-__DLL__ herr_t H5S_point_select_fill(const void *fill, size_t fill_size,
- const H5S_t *space, void *buf);
+__DLL__ herr_t H5S_point_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);
/* "All" select functions */
+__DLL__ herr_t H5S_all_init (const H5S_t *space, size_t elmt_size,
+ H5S_sel_iter_t *iter);
+__DLL__ hsize_t H5S_all_favail (const H5S_t *space, const H5S_sel_iter_t *iter,
+ hsize_t max);
__DLL__ herr_t H5S_all_release(H5S_t *space);
__DLL__ hsize_t H5S_all_npoints(const H5S_t *space);
__DLL__ herr_t H5S_all_select_serialize(const H5S_t *space, uint8_t *buf);
__DLL__ herr_t H5S_all_select_deserialize(H5S_t *space, const uint8_t *buf);
__DLL__ herr_t H5S_all_bounds(H5S_t *space, hsize_t *start, hsize_t *end);
-__DLL__ herr_t H5S_all_read(H5F_t *f, const struct 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*/);
-__DLL__ herr_t H5S_all_write(H5F_t *f, const struct 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);
-__DLL__ herr_t H5S_all_select_iterate(void *buf, hid_t type_id, H5S_t *space,
- H5D_operator_t op, void *operator_data);
-__DLL__ herr_t H5S_all_select_fill(const void *fill, size_t fill_size,
- const H5S_t *space, void *buf);
-__DLL__ htri_t H5S_all_opt_possible(const H5S_t *mem_space,
- const H5S_t *file_space, const unsigned flags);
+__DLL__ herr_t H5S_all_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);
/* Hyperslab selection functions */
+__DLL__ herr_t H5S_hyper_init (const H5S_t *space, size_t elmt_size,
+ H5S_sel_iter_t *iter);
+__DLL__ hsize_t H5S_hyper_favail (const H5S_t *space, const H5S_sel_iter_t *iter,
+ hsize_t max);
__DLL__ herr_t H5S_hyper_release(H5S_t *space);
__DLL__ herr_t H5S_hyper_sel_iter_release(H5S_sel_iter_t *sel_iter);
__DLL__ hsize_t H5S_hyper_npoints(const H5S_t *space);
@@ -177,10 +175,9 @@ __DLL__ herr_t H5S_hyper_bounds(H5S_t *space, hsize_t *start, hsize_t *end);
__DLL__ htri_t H5S_hyper_select_contiguous(const H5S_t *space);
__DLL__ htri_t H5S_hyper_select_single(const H5S_t *space);
__DLL__ htri_t H5S_hyper_select_regular(const H5S_t *space);
-__DLL__ herr_t H5S_hyper_select_iterate(void *buf, hid_t type_id, H5S_t *space,
- H5D_operator_t op, void *operator_data);
-__DLL__ herr_t H5S_hyper_select_fill(const void *fill, size_t fill_size,
- const H5S_t *space, void *buf);
+__DLL__ herr_t H5S_hyper_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);
/* "None" selection functions */
__DLL__ herr_t H5S_select_none(H5S_t *space);
diff --git a/src/H5Spoint.c b/src/H5Spoint.c
index 9dcfc4c..e7f32ef 100644
--- a/src/H5Spoint.c
+++ b/src/H5Spoint.c
@@ -10,61 +10,26 @@
#define H5S_PACKAGE /*suppress error about including H5Spkg */
-#include "H5private.h"
-#include "H5Dprivate.h"
-#include "H5Eprivate.h"
-#include "H5Iprivate.h"
-#include "H5MMprivate.h"
-#include "H5Spkg.h"
-#include "H5Tprivate.h" /* Datatypes */
-#include "H5Vprivate.h"
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5FLprivate.h" /* Free Lists */
+#include "H5Iprivate.h" /* ID Functions */
+#include "H5MMprivate.h" /* Memory Management functions */
+#include "H5Spkg.h" /* Dataspace functions */
+#include "H5Vprivate.h" /* Vector functions */
/* Interface initialization */
#define PABLO_MASK H5Spoint_mask
#define INTERFACE_INIT NULL
static int interface_initialize_g = 0;
-static herr_t H5S_point_init (const H5S_t *space, size_t elmt_size, H5S_sel_iter_t *iter);
-static hsize_t H5S_point_favail (const H5S_t *space, const H5S_sel_iter_t *iter,
- hsize_t max);
-static hsize_t H5S_point_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*/);
-static herr_t H5S_point_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);
-static hsize_t H5S_point_mgath (const void *_buf, size_t elmt_size,
- const H5S_t *mem_space,
- H5S_sel_iter_t *mem_iter, hsize_t nelmts,
- void *_tconv_buf/*out*/);
-static herr_t H5S_point_mscat (const void *_tconv_buf, size_t elmt_size,
- const H5S_t *mem_space,
- H5S_sel_iter_t *mem_iter, hsize_t nelmts,
- void *_buf/*out*/);
-
-const H5S_fconv_t H5S_POINT_FCONV[1] = {{
- "point", /*name */
- H5S_SEL_POINTS, /*selection type */
- H5S_point_init, /*initialize */
- H5S_point_favail, /*available */
- H5S_point_fgath, /*gather */
- H5S_point_fscat, /*scatter */
-}};
-
-const H5S_mconv_t H5S_POINT_MCONV[1] = {{
- "point", /*name */
- H5S_SEL_POINTS, /*selection type */
- H5S_point_init, /*initialize */
- H5S_point_mgath, /*gather */
- H5S_point_mscat, /*scatter */
-}};
-
-
+/* Declare a free list to manage the H5S_pnt_node_t struct */
+H5FL_DEFINE_STATIC(H5S_pnt_node_t);
+/* Declare a free list to manage the H5S_pnt_list_t struct */
+H5FL_DEFINE_STATIC(H5S_pnt_list_t);
+
+
/*-------------------------------------------------------------------------
* Function: H5S_point_init
*
@@ -79,7 +44,7 @@ const H5S_mconv_t H5S_POINT_MCONV[1] = {{
*
*-------------------------------------------------------------------------
*/
-static herr_t
+herr_t
H5S_point_init (const H5S_t *space, size_t UNUSED elmt_size, H5S_sel_iter_t *sel_iter)
{
FUNC_ENTER_NOAPI(H5S_point_init, FAIL);
@@ -134,7 +99,7 @@ herr_t H5S_point_add (H5S_t *space, H5S_seloper_t op, size_t num_elem, const hss
top=curr=NULL;
for(i=0; i<num_elem; i++) {
/* Allocate space for the new node */
- if((new_node = H5MM_malloc(sizeof(H5S_pnt_node_t)))==NULL)
+ if((new_node = H5FL_ALLOC(H5S_pnt_node_t,0))==NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
"can't allocate point node");
@@ -199,7 +164,7 @@ done:
*
*-------------------------------------------------------------------------
*/
-static hsize_t
+hsize_t
H5S_point_favail (const H5S_t * UNUSED space,
const H5S_sel_iter_t *sel_iter, hsize_t max)
{
@@ -211,337 +176,7 @@ H5S_point_favail (const H5S_t * UNUSED space,
FUNC_LEAVE (MIN(sel_iter->pnt.elmt_left,max));
} /* H5S_point_favail() */
-
-/*-------------------------------------------------------------------------
- * Function: H5S_point_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.
- *
- * Notes: This could be optimized by gathering selected elements near (how
- * near?) each other into one I/O request and then moving the correct
- * elements into the return buffer
- *
- * Return: Success: Number of elements copied.
- *
- * Failure: 0
- *
- * Programmer: Quincey Koziol
- * Tuesday, June 16, 1998
- *
- * Modifications:
- * Robb Matzke, 1999-08-03
- * The data transfer properties are passed by ID since that's
- * what the virtual file layer needs.
- *-------------------------------------------------------------------------
- */
-static hsize_t
-H5S_point_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*/)
-{
- hssize_t file_offset[H5O_LAYOUT_NDIMS]; /*offset of slab in file*/
- hsize_t hsize[H5O_LAYOUT_NDIMS]; /*size of hyperslab */
- hssize_t zero[H5O_LAYOUT_NDIMS]; /*zero */
- uint8_t *buf=(uint8_t *)_buf; /* Alias for pointer arithmetic */
- unsigned ndims; /* Number of dimensions of dataset */
- unsigned u; /*counters */
- hsize_t num_read; /* number of elements read into buffer */
- FUNC_ENTER_NOAPI(H5S_point_fgath, 0);
-
- /* Check args */
- assert (f);
- assert (layout);
- assert (elmt_size>0);
- assert (file_space);
- assert (file_iter);
- assert (nelmts>0);
- assert (buf);
-
- ndims=file_space->extent.u.simple.rank;
- /* initialize hyperslab size and offset in memory buffer */
- for(u=0; u<ndims+1; u++) {
- hsize[u]=1; /* hyperslab size is 1, except for last element */
- zero[u]=0; /* memory offset is 0 */
- } /* end for */
- hsize[ndims] = elmt_size;
-
- /*
- * Walk though and request each element we need and put it into the
- * buffer.
- */
- num_read=0;
- while(num_read<nelmts) {
- if(file_iter->pnt.elmt_left>0) {
- /* Copy the location of the point to get */
- HDmemcpy(file_offset, file_iter->pnt.curr->pnt, ndims*sizeof(hssize_t));
- file_offset[ndims] = 0;
-
- /* Add in the offset */
- for(u=0; u<file_space->extent.u.simple.rank; u++)
- file_offset[u] += file_space->select.offset[u];
-
- /* Go read the point */
- if (H5F_arr_read(f, dxpl_id, layout, dc_plist, hsize, hsize, zero, file_offset, buf/*out*/)<0)
- HRETURN_ERROR(H5E_DATASPACE, H5E_READERROR, 0, "read error");
-
- /* Increment the offset of the buffer */
- buf+=elmt_size;
-
- /* Increment the count read */
- num_read++;
-
- /* Advance the point iterator */
- file_iter->pnt.elmt_left--;
- file_iter->pnt.curr=file_iter->pnt.curr->next;
- } else {
- break; /* out of elements in the selection */
- } /* end else */
- } /* end while */
-
- FUNC_LEAVE (num_read);
-} /* H5S_point_fgath() */
-
-/*-------------------------------------------------------------------------
- * Function: H5S_point_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
- * Tuesday, June 16, 1998
- *
- * Modifications:
- * Robb Matzke, 1999-08-03
- * The data transfer properties are passed by ID since that's
- * what the virtual file layer needs.
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5S_point_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)
-{
- hssize_t file_offset[H5O_LAYOUT_NDIMS]; /*offset of hyperslab */
- hsize_t hsize[H5O_LAYOUT_NDIMS]; /*size of hyperslab */
- hssize_t zero[H5O_LAYOUT_NDIMS]; /*zero vector */
- const uint8_t *buf=(const uint8_t *)_buf; /* Alias for pointer arithmetic */
- unsigned ndims; /* Number of dimensions of dataset */
- unsigned u; /*counters */
- hsize_t num_written; /* number of elements written from buffer */
-
- FUNC_ENTER_NOAPI(H5S_point_fscat, FAIL);
-
- /* Check args */
- assert (f);
- assert (layout);
- assert (elmt_size>0);
- assert (file_space);
- assert (file_iter);
- assert (nelmts>0);
- assert (buf);
-
- /* Hold the number of dimensions of the dataspace */
- ndims=file_space->extent.u.simple.rank;
-
- /* initialize hyperslab size and offset in memory buffer */
- for(u=0; u<ndims+1; u++) {
- hsize[u]=1; /* hyperslab size is 1, except for last element */
- zero[u]=0; /* memory offset is 0 */
- } /* end for */
- hsize[ndims] = elmt_size;
-
- /*
- * Walk though and request each element we need and put it into the
- * buffer.
- */
- num_written=0;
- while(num_written<nelmts && file_iter->pnt.elmt_left>0) {
- /* Copy the location of the point to get */
- HDmemcpy(file_offset,file_iter->pnt.curr->pnt,ndims*sizeof(hssize_t));
- file_offset[ndims] = 0;
-
- /* Add in the offset, if there is one */
- for(u=0; u<file_space->extent.u.simple.rank; u++)
- file_offset[u] += file_space->select.offset[u];
-
- /* Go write the point */
- if (H5F_arr_write(f, dxpl_id, layout, dc_plist, hsize, hsize, zero, file_offset, buf)<0)
- HRETURN_ERROR(H5E_DATASPACE, H5E_WRITEERROR, 0, "write error");
-
- /* Increment the offset of the buffer */
- buf+=elmt_size;
-
- /* Increment the count read */
- num_written++;
-
- /* Advance the point iterator */
- file_iter->pnt.elmt_left--;
- file_iter->pnt.curr=file_iter->pnt.curr->next;
- } /* end while */
-
- FUNC_LEAVE (num_written>0 ? SUCCEED : FAIL);
-} /* H5S_point_fscat() */
-
-/*-------------------------------------------------------------------------
- * Function: H5S_point_mgath
- *
- * Purpose: Gathers dataset elements from application memory BUF and
- * copies them into the data type conversion buffer TCONV_BUF.
- * Each element is ELMT_SIZE bytes and arranged in application
- * memory according to MEM_SPACE.
- * The caller is requesting that at most NELMTS be gathered.
- *
- * Return: Success: Number of elements copied.
- *
- * Failure: 0
- *
- * Programmer: Quincey Koziol
- * Tuesday, June 16, 1998
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static hsize_t
-H5S_point_mgath (const void *_buf, size_t elmt_size,
- const H5S_t *mem_space, H5S_sel_iter_t *mem_iter,
- hsize_t nelmts, void *_tconv_buf/*out*/)
-{
- hsize_t mem_size[H5O_LAYOUT_NDIMS]; /*total size of app buf */
- const uint8_t *buf=(const uint8_t *)_buf; /* Get local copies for address arithmetic */
- uint8_t *tconv_buf=(uint8_t *)_tconv_buf;
- hsize_t acc; /* coordinate accumulator */
- hsize_t off; /* coordinate offset */
- int space_ndims; /*dimensionality of space*/
- int i; /*counters */
- hsize_t num_gath; /* number of elements gathered */
-
- FUNC_ENTER_NOAPI(H5S_point_mgath, 0);
-
- /* Check args */
- assert (buf);
- assert (elmt_size>0);
- assert (mem_space && H5S_SEL_POINTS==mem_space->select.type);
- assert (nelmts>0);
- assert (tconv_buf);
-
- /* Get the dataspace dimensions */
- if ((space_ndims=H5S_get_simple_extent_dims (mem_space, mem_size, NULL))<0)
- HRETURN_ERROR (H5E_DATASPACE, H5E_CANTINIT, 0, "unable to retrieve data space dimensions");
-
- /* Loop through all the points selected */
- for(num_gath=0; num_gath<nelmts; num_gath++) {
- if(mem_iter->pnt.elmt_left>0) {
- /* Compute the location of the point to get */
- for(i=space_ndims-1,acc=elmt_size,off=0; i>=0; i--) {
- off+=(mem_iter->pnt.curr->pnt[i]+mem_space->select.offset[i])*acc;
- acc*=mem_size[i];
- } /* end for */
-
- /* Copy the elements into the type conversion buffer */
- HDmemcpy(tconv_buf,buf+off,elmt_size);
-
- /* Increment the offset of the buffers */
- tconv_buf+=elmt_size;
-
- /* Advance the point iterator */
- mem_iter->pnt.elmt_left--;
- mem_iter->pnt.curr=mem_iter->pnt.curr->next;
- } else {
- break; /* out of elements in the selection */
- } /* end else */
- } /* end for */
-
- FUNC_LEAVE (num_gath);
-} /* H5S_point_mgath() */
-
-/*-------------------------------------------------------------------------
- * Function: H5S_point_mscat
- *
- * Purpose: Scatters NELMTS data points from the type conversion buffer
- * TCONV_BUF to the application buffer BUF. Each element is
- * ELMT_SIZE bytes and they are organized in application memory
- * according to MEM_SPACE.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Quincey Koziol
- * Wednesday, June 17, 1998
- *
- * Modifications:
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5S_point_mscat (const void *_tconv_buf, size_t elmt_size,
- const H5S_t *mem_space, H5S_sel_iter_t *mem_iter,
- hsize_t nelmts, void *_buf/*out*/)
-{
- hsize_t mem_size[H5O_LAYOUT_NDIMS]; /*total size of app buf */
- uint8_t *buf=(uint8_t *)_buf; /* Get local copies for address arithmetic */
- const uint8_t *tconv_buf=(const uint8_t *)_tconv_buf;
- hsize_t acc; /* coordinate accumulator */
- hsize_t off; /* coordinate offset */
- int space_ndims; /*dimensionality of space*/
- int i; /*counters */
- hsize_t num_scat; /* Number of elements scattered */
-
- FUNC_ENTER_NOAPI(H5S_point_mscat, FAIL);
-
- /* Check args */
- assert (tconv_buf);
- assert (elmt_size>0);
- assert (mem_space && H5S_SEL_POINTS==mem_space->select.type);
- assert (nelmts>0);
- assert (buf);
-
- /* Get the dataspace dimensions */
- if ((space_ndims=H5S_get_simple_extent_dims (mem_space, mem_size, NULL))<0)
- HRETURN_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to retrieve data space dimensions");
-
- /* Loop through all the points selected */
- for(num_scat=0; num_scat<nelmts; num_scat++) {
- if(mem_iter->pnt.elmt_left>0) {
- /* Compute the location of the point to get */
- for(i=space_ndims-1,acc=elmt_size,off=0; i>=0; i--) {
- off+=(mem_iter->pnt.curr->pnt[i]+mem_space->select.offset[i])*acc;
- acc*=mem_size[i];
- } /* end for */
-
- /* Copy the elements into the type conversion buffer */
- HDmemcpy(buf+off,tconv_buf,elmt_size);
-
- /* Increment the offset of the buffers */
- tconv_buf+=elmt_size;
-
- /* Advance the point iterator */
- mem_iter->pnt.elmt_left--;
- mem_iter->pnt.curr=mem_iter->pnt.curr->next;
- } else {
- break; /* out of elements in the selection */
- } /* end else */
- } /* end for */
-
- FUNC_LEAVE (SUCCEED);
-} /* H5S_point_mscat() */
/*--------------------------------------------------------------------------
NAME
@@ -575,12 +210,12 @@ H5S_point_release (H5S_t *space)
while(curr!=NULL) {
next=curr->next;
H5MM_xfree(curr->pnt);
- H5MM_xfree(curr);
+ H5FL_FREE(H5S_pnt_node_t,curr);
curr=next;
} /* end while */
/* Free & reset the point list header */
- H5MM_xfree(space->select.sel_info.pnt_lst);
+ H5FL_FREE(H5S_pnt_list_t,space->select.sel_info.pnt_lst);
space->select.sel_info.pnt_lst=NULL;
/* Reset the number of elements in the selection */
@@ -588,6 +223,7 @@ H5S_point_release (H5S_t *space)
FUNC_LEAVE (SUCCEED);
} /* H5S_point_release() */
+
/*--------------------------------------------------------------------------
NAME
@@ -616,6 +252,7 @@ H5S_point_npoints (const H5S_t *space)
FUNC_LEAVE (space->select.num_elem);
} /* H5S_point_npoints() */
+
/*--------------------------------------------------------------------------
NAME
@@ -648,7 +285,7 @@ H5S_point_copy (H5S_t *dst, const H5S_t *src)
assert(dst);
/* Allocate room for the head of the point list */
- if((dst->select.sel_info.pnt_lst=H5MM_malloc(sizeof(H5S_pnt_list_t)))==NULL)
+ if((dst->select.sel_info.pnt_lst=H5FL_ALLOC(H5S_pnt_list_t,0))==NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
"can't allocate point node");
@@ -656,7 +293,7 @@ H5S_point_copy (H5S_t *dst, const H5S_t *src)
new_head=NULL;
while(curr!=NULL) {
/* Create each point */
- if((new_node=H5MM_malloc(sizeof(H5S_pnt_node_t)))==NULL)
+ if((new_node=H5FL_ALLOC(H5S_pnt_node_t,0))==NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
"can't allocate point node");
if((new_node->pnt = H5MM_malloc(src->extent.u.simple.rank*sizeof(hssize_t)))==NULL)
@@ -679,6 +316,7 @@ H5S_point_copy (H5S_t *dst, const H5S_t *src)
done:
FUNC_LEAVE (ret_value);
} /* end H5S_point_copy() */
+
/*--------------------------------------------------------------------------
NAME
@@ -730,6 +368,7 @@ H5S_point_select_valid (const H5S_t *space)
FUNC_LEAVE (ret_value);
} /* end H5S_point_select_valid() */
+
/*--------------------------------------------------------------------------
NAME
@@ -776,6 +415,7 @@ H5S_point_select_serial_size (const H5S_t *space)
FUNC_LEAVE (ret_value);
} /* end H5S_point_select_serial_size() */
+
/*--------------------------------------------------------------------------
NAME
@@ -845,6 +485,7 @@ H5S_point_select_serialize (const H5S_t *space, uint8_t *buf)
FUNC_LEAVE (ret_value);
} /* H5S_point_select_serialize() */
+
/*--------------------------------------------------------------------------
NAME
@@ -909,6 +550,7 @@ done:
FUNC_LEAVE (ret_value);
} /* H5S_point_select_deserialize() */
+
/*--------------------------------------------------------------------------
NAME
@@ -1134,13 +776,13 @@ herr_t H5S_select_elements (H5S_t *space, H5S_seloper_t op, size_t num_elem,
if(op==H5S_SELECT_SET) {
if(H5S_select_release(space)<0) {
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL,
- "can't release hyperslab");
+ "can't release point selection");
} /* end if */
} /* end if */
/* Allocate space for the point selection information if necessary */
if(space->select.type!=H5S_SEL_POINTS || space->select.sel_info.pnt_lst==NULL) {
- if((space->select.sel_info.pnt_lst = H5MM_calloc(sizeof(H5S_pnt_list_t)))==NULL)
+ if((space->select.sel_info.pnt_lst = H5FL_ALLOC(H5S_pnt_list_t,1))==NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
"can't allocate element information");
} /* end if */
@@ -1222,161 +864,141 @@ done:
/*--------------------------------------------------------------------------
NAME
- H5S_point_select_iterate
+ H5S_point_select_get_seq_list
PURPOSE
- Iterate over a point selection, calling a user's function for each
- element.
+ Create a list of offsets & lengths for a selection
USAGE
- herr_t H5S_point_select_iterate(buf, type_id, space, op, operator_data)
- void *buf; IN/OUT: Buffer containing elements to iterate over
- hid_t type_id; IN: Datatype ID of BUF array.
- H5S_t *space; IN: Dataspace object containing selection to iterate over
- H5D_operator_t op; IN: Function pointer to the routine to be
- called for each element in BUF iterated over.
- void *operator_data; IN/OUT: Pointer to any user-defined data
- associated with the operation.
- RETURNS
- Returns the return value of the last operator if it was non-zero, or zero
- if all elements were processed. Otherwise returns a negative value.
- DESCRIPTION
- Iterates over the selected elements in a memory buffer, calling the user's
- callback function for each element. The selection in the dataspace is
- modified so that any elements already iterated over are removed from the
- selection if the iteration is interrupted (by the H5D_operator_t function
- returning non-zero) in the "middle" of the iteration and may be re-started
- by the user where it left off.
-
- NOTE: Until "subtracting" elements from a selection is implemented,
- the selection is not modified.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
- QAK - 2002/4/5 - Wasn't using selection offset in calculation, corrected.
---------------------------------------------------------------------------*/
-herr_t
-H5S_point_select_iterate(void *buf, hid_t type_id, H5S_t *space, H5D_operator_t op,
- void *operator_data)
-{
- hsize_t mem_size[H5O_LAYOUT_NDIMS]; /* Dataspace size */
- hssize_t mem_offset[H5O_LAYOUT_NDIMS]; /* Point offset */
- hsize_t offset; /* Offset of region in buffer */
- void *tmp_buf; /* Temporary location of the element in the buffer */
- H5S_pnt_node_t *node; /* Point node */
- unsigned rank; /* Dataspace rank */
- H5T_t *dt; /* Datatype structure */
- unsigned u; /* Local index variable */
- herr_t ret_value=0; /* return value */
-
- FUNC_ENTER_NOAPI(H5S_point_select_iterate, 0);
-
- assert(buf);
- assert(space);
- assert(op);
- assert(H5I_DATATYPE == H5I_get_type(type_id));
-
- /* Get the dataspace extent rank */
- rank=space->extent.u.simple.rank;
-
- /* Set up the size of the memory space */
- HDmemcpy(mem_size, space->extent.u.simple.size, rank*sizeof(hsize_t));
-
- /* Set the size of the datatype */
- if (NULL==(dt=H5I_object(type_id)))
- HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an valid base datatype");
- mem_size[rank]=H5T_get_size(dt);
-
- /* Iterate through the node, checking the bounds on each element */
- node=space->select.sel_info.pnt_lst->head;
- while(node!=NULL && ret_value==0) {
- /* Set up the location of the point */
- HDmemcpy(mem_offset, node->pnt, rank*sizeof(hssize_t));
- mem_offset[rank]=0;
-
- /* Add in the selection offset */
- for(u=0; u<rank; u++)
- mem_offset[u]+=space->select.offset[u];
-
- /* Get the offset in the memory buffer */
- offset=H5V_array_offset(rank+1,mem_size,(const hssize_t *)mem_offset);
- tmp_buf=((char *)buf+offset);
-
- ret_value=(*op)(tmp_buf,type_id,(hsize_t)rank,mem_offset,operator_data);
-
- node=node->next;
- } /* end while */
-
- FUNC_LEAVE (ret_value);
-} /* H5S_point_select_iterate() */
-
-
-/*--------------------------------------------------------------------------
- NAME
- H5S_point_select_fill
- PURPOSE
- Fill a point selection in memory with a value
- USAGE
- herr_t H5S_point_select_fill(fill,fill_size,space,buf)
- const void *fill; IN: Pointer to fill value to use
- size_t fill_size; IN: Size of elements in memory buffer & size of
- fill value
- H5S_t *space; IN: Dataspace describing memory buffer &
- containing selection to use.
- void *buf; IN/OUT: Memory buffer to fill selection in
+ herr_t H5S_point_select_get_seq_list(flags,space,iter,elem_size,maxseq,maxbytes,nseq,nbytes,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.
+ 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
+ size_t *nbytes; OUT: Actual number of bytes in sequences generated
+ hsize_t *off; OUT: Array of offsets
+ size_t *len; OUT: Array of lengths
RETURNS
Non-negative on success/Negative on failure.
DESCRIPTION
- Use the selection in the dataspace to fill elements in a memory buffer.
+ Use the selection in the dataspace to generate a list of byte offsets and
+ lengths for the region(s) selected. Start/Restart from the position in the
+ ITER parameter. The number of sequences generated is limited by the MAXSEQ
+ parameter and the number of sequences actually generated is stored in the
+ NSEQ parameter.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
- The memory buffer elements are assumed to have the same datatype as the
- fill value being placed into them.
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
herr_t
-H5S_point_select_fill(const void *fill, size_t fill_size, const H5S_t *space, void *_buf)
+H5S_point_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)
{
- hsize_t size[H5O_LAYOUT_NDIMS]; /* Total size of memory buf */
- uint8_t *buf=(uint8_t *)_buf; /* Alias for memory buffer */
- hsize_t acc; /* Coordinate accumulator */
- hsize_t off; /* Coordinate offset */
+ hsize_t bytes_left; /* The number of bytes left in the selection */
+ hsize_t start_bytes_left; /* The initial number of bytes left in the selection */
H5S_pnt_node_t *node; /* Point node */
+ hsize_t dims[H5O_LAYOUT_NDIMS]; /* Total size of memory buf */
int ndims; /* Dimensionality of space*/
- int i; /* Index variable */
- herr_t ret_value=SUCCEED; /* return value */
+ hsize_t acc; /* Coordinate accumulator */
+ hsize_t loc; /* Coordinate offset */
+ size_t curr_seq; /* Current sequence being operated on */
+ int i; /* Local index variable */
+ herr_t ret_value=SUCCEED; /* return value */
- FUNC_ENTER_NOAPI(H5S_point_select_fill, FAIL);
+ FUNC_ENTER_NOAPI (H5S_point_select_get_seq_list, FAIL);
/* Check args */
- assert(fill);
- assert(fill_size>0);
assert(space);
- assert(buf);
+ assert(iter);
+ assert(elem_size>0);
+ assert(maxseq>0);
+ assert(maxbytes>0);
+ assert(nseq);
+ assert(nbytes);
+ assert(off);
+ assert(len);
- /* Fill the selection in the memory buffer */
+ /* "round" off the maxbytes allowed to a multiple of the element size */
+ maxbytes=(maxbytes/elem_size)*elem_size;
+
+ /* Choose the minimum number of bytes to sequence through */
+ start_bytes_left=bytes_left=MIN(iter->pnt.elmt_left*elem_size,maxbytes);
/* Get the dataspace dimensions */
- if ((ndims=H5S_get_simple_extent_dims (space, size, NULL))<0)
+ if ((ndims=H5S_get_simple_extent_dims (space, dims, NULL))<0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to retrieve data space dimensions");
- /* Loop through all the points selected */
- node=space->select.sel_info.pnt_lst->head;
+ /* Walk through the points in the selection, starting at the current */
+ /* location in the iterator */
+ node=iter->pnt.curr;
+ curr_seq=0;
while(node!=NULL) {
/* Compute the offset of each selected point in the buffer */
- for(i=ndims-1,acc=fill_size,off=0; i>=0; i--) {
- off+=(node->pnt[i]+space->select.offset[i])*acc;
- acc*=size[i];
+ for(i=ndims-1,acc=elem_size,loc=0; i>=0; i--) {
+ loc+=(node->pnt[i]+space->select.offset[i])*acc;
+ acc*=dims[i];
} /* end for */
- /* Set the selected point to the fill value */
- HDmemcpy(buf+off,fill,fill_size);
+ /* Check if this is a later point in the selection */
+ if(curr_seq>0) {
+ /* If a sorted sequence is requested, make certain we don't go backwards in the offset */
+ if((flags&H5S_GET_SEQ_LIST_SORTED) && loc<off[curr_seq-1])
+ break;
+
+ /* Check if this point extends the previous sequence */
+ /* (Unlikely, but possible) */
+ if(loc==(off[curr_seq-1]+len[curr_seq-1])) {
+ /* Extend the previous sequence */
+ len[curr_seq-1]+=elem_size;
+ } /* end if */
+ else {
+ /* Add a new sequence */
+ off[curr_seq]=loc;
+ len[curr_seq]=elem_size;
+
+ /* Increment sequence count */
+ curr_seq++;
+ } /* end else */
+ } /* end if */
+ else {
+ /* Add a new sequence */
+ off[curr_seq]=loc;
+ len[curr_seq]=elem_size;
+
+ /* Increment sequence count */
+ curr_seq++;
+ } /* end else */
+
+ /* Decrement number of bytes left to process */
+ bytes_left-=elem_size;
+
+ /* Move the iterator */
+ iter->pnt.curr=node->next;
+ iter->pnt.elmt_left--;
+
+ /* Check if we're finished with all sequences */
+ if(curr_seq==maxseq)
+ break;
+
+ /* Check if we're finished with all the bytes available */
+ if(bytes_left==0)
+ break;
/* Advance to the next point */
node=node->next;
} /* end while */
+ /* Set the number of sequences generated */
+ *nseq=curr_seq;
+
+ /* Set the number of bytes used */
+ *nbytes=(start_bytes_left-bytes_left);
+
done:
FUNC_LEAVE (ret_value);
-} /* H5S_point_select_fill() */
-
+} /* end H5S_point_select_get_seq_list() */
diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h
index de7f838..1412ea3 100644
--- a/src/H5Sprivate.h
+++ b/src/H5Sprivate.h
@@ -40,11 +40,15 @@
#define H5S_CONV_STORAGE_CHUNKED 0x0004 /* i.e. '2' */
#define H5S_CONV_STORAGE_MASK 0x0006
+/* Flags for H5S_select_get_seq_list() */
+#define H5S_GET_SEQ_LIST_SORTED 0x0001
+
/* Forward references of common typedefs */
typedef struct H5S_t H5S_t;
typedef struct H5S_pnt_node_t H5S_pnt_node_t;
typedef struct H5S_hyper_span_t H5S_hyper_span_t;
typedef struct H5S_hyper_span_info_t H5S_hyper_span_info_t;
+typedef struct H5S_hyper_dim_t H5S_hyper_dim_t;
/* Point selection iteration container */
typedef struct {
@@ -54,10 +58,24 @@ typedef struct {
/* New Hyperslab selection iteration container */
typedef struct {
+ /* Common fields for all hyperslab selections */
hsize_t elmt_left; /* Number of elements left to iterate over */
+ hssize_t *off; /* Offset in span node (used as position for regular hyperslabs) */
+ unsigned iter_rank; /* Rank of iterator information */
+ /* (This should always be the same as the dataspace
+ * rank, except for regular hyperslab selections in
+ * which there are contiguous regions in the lower
+ * dimensions which have been "flattened" out
+ */
+
+ /* "Flattened" regular hyperslab selection fields */
+ H5S_hyper_dim_t *diminfo; /* "Flattened" regular selection information */
+ hsize_t *size; /* "Flattened" dataspace extent information */
+ hssize_t *sel_off; /* "Flattened" selection offset information */
+
+ /* Irregular hyperslab selection fields */
H5S_hyper_span_info_t *spans; /* Pointer to copy of the span tree */
- H5S_hyper_span_t **span; /* Array of pointers to span nodes */
- hssize_t *off; /* Offset in span node (position for regular hyperslabs) */
+ H5S_hyper_span_t **span;/* Array of pointers to span nodes */
} H5S_hyper_iter_t;
/* "All" selection iteration container */
@@ -73,59 +91,9 @@ typedef union {
H5S_all_iter_t all; /* "All" selection iteration information */
} H5S_sel_iter_t;
-/*
- * Data space conversions usually take place in two halves. One half
- * transfers data points between memory and a data type conversion array
- * where the points are contiguous, and the other half transfers points
- * between the type conversion array and the file.
- */
-typedef struct H5S_fconv_t {
- /* Identification */
- const char *name;
- H5S_sel_type type;
-
- /* Initialize file element numbering information */
- herr_t (*init)(const H5S_t *space, size_t elmt_size, H5S_sel_iter_t *iter);
-
- /* Determine optimal number of elements to transfer */
- hsize_t (*avail)(const H5S_t *file_space, const H5S_sel_iter_t *file_iter,
- hsize_t max);
-
- /* Gather elements from disk to type conversion buffer */
- hsize_t (*gath)(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 *tconv_buf/*out*/);
-
- /* Scatter elements from type conversion buffer to disk */
- herr_t (*scat)(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 *tconv_buf);
-} H5S_fconv_t;
-
-typedef struct H5S_mconv_t {
- /* Identification */
- const char *name;
- H5S_sel_type type;
-
- /* Initialize memory element numbering information */
- herr_t (*init)(const H5S_t *space, size_t elmt_size, H5S_sel_iter_t *iter);
-
- /* Gather elements from app buffer to type conversion buffer */
- hsize_t (*gath)(const void *buf, size_t elmt_size,
- const H5S_t *mem_space, H5S_sel_iter_t *mem_iter,
- hsize_t nelmts, void *tconv_buf/*out*/);
-
- /* Scatter elements from type conversion buffer to application buffer */
- herr_t (*scat)(const void *tconv_buf, size_t elmt_size,
- const H5S_t *mem_space, H5S_sel_iter_t *mem_iter,
- hsize_t nelmts, void *buf/*out*/);
-} H5S_mconv_t;
-
typedef struct H5S_conv_t {
- const H5S_fconv_t *f;
- const H5S_mconv_t *m;
+ H5S_sel_type ftype;
+ H5S_sel_type mtype;
/*
* If there is no data type conversion then it might be possible to
@@ -167,14 +135,6 @@ typedef struct H5S_conv_t {
#endif
} H5S_conv_t;
-/* Conversion information for the various data space selection types */
-__DLLVAR__ const H5S_fconv_t H5S_POINT_FCONV[];
-__DLLVAR__ const H5S_mconv_t H5S_POINT_MCONV[];
-__DLLVAR__ const H5S_fconv_t H5S_ALL_FCONV[];
-__DLLVAR__ const H5S_mconv_t H5S_ALL_MCONV[];
-__DLLVAR__ const H5S_fconv_t H5S_HYPER_FCONV[];
-__DLLVAR__ const H5S_mconv_t H5S_HYPER_MCONV[];
-
/* We get the declaration of H5G_entry_t from the H5Oprivate.h file */
__DLL__ H5S_t *H5S_create(H5S_class_t type);
@@ -215,10 +175,37 @@ __DLL__ htri_t H5S_select_regular(const H5S_t *space);
__DLL__ htri_t H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2);
__DLL__ herr_t H5S_select_iterate(void *buf, hid_t type_id, H5S_t *space,
H5D_operator_t op, void *operator_data);
+__DLL__ herr_t H5S_select_iter_init(const H5S_t *space, size_t elmt_size,
+ H5S_sel_iter_t *iter);
__DLL__ herr_t H5S_sel_iter_release(const H5S_t *space,
H5S_sel_iter_t *sel_iter);
__DLL__ herr_t H5S_select_fill(void *fill, size_t fill_size,
const H5S_t *space, void *buf);
+__DLL__ 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);
+__DLL__ hsize_t H5S_select_favail(const H5S_t *space, const H5S_sel_iter_t *iter,
+ hsize_t max);
+__DLL__ 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);
+__DLL__ 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);
+__DLL__ 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*/);
+__DLL__ 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*/);
+__DLL__ herr_t H5S_select_read(H5F_t *f, const struct 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*/);
+__DLL__ herr_t H5S_select_write(H5F_t *f, const struct 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*/);
/* Needed for internal use of selections in H5Fistore code */
__DLL__ herr_t H5S_select_all(H5S_t *space);
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() */
diff --git a/src/H5Tconv.c b/src/H5Tconv.c
index e61e2cb..beeb7bf 100644
--- a/src/H5Tconv.c
+++ b/src/H5Tconv.c
@@ -2372,8 +2372,11 @@ H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
} /* end if */
/* If the sequence gets shorter, pad out the original sequence with zeros */
- if(bg_seq_len<seq_len)
- HDmemset((uint8_t *)tmp_buf+dst_base_size*bg_seq_len,0,(seq_len-bg_seq_len)*dst_base_size);
+ H5_CHECK_OVERFLOW(bg_seq_len,hsize_t,hssize_t);
+ if((hssize_t)bg_seq_len<seq_len) {
+ H5_CHECK_OVERFLOW((seq_len-bg_seq_len),hsize_t,size_t);
+ HDmemset((uint8_t *)tmp_buf+dst_base_size*bg_seq_len,0,(size_t)(seq_len-bg_seq_len)*dst_base_size);
+ } /* end if */
} /* end if */
/* Convert VL sequence */
@@ -2388,7 +2391,8 @@ H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
"can't write VL data");
/* For nested VL case, free leftover heap objects from the deeper level if the length of new data elements is shorted than the old data elements.*/
- if(nested && seq_len<bg_seq_len) {
+ H5_CHECK_OVERFLOW(bg_seq_len,hsize_t,hssize_t);
+ if(nested && seq_len<(hssize_t)bg_seq_len) {
uint8_t *tmp_p=tmp_buf;
tmp_p += seq_len*dst_base_size;
for(i=0; i<(bg_seq_len-seq_len); i++) {