summaryrefslogtreecommitdiffstats
path: root/src/H5Shyper.c
diff options
context:
space:
mode:
authorNeil Fortner <nfortne2@hdfgroup.org>2015-04-16 20:57:26 (GMT)
committerNeil Fortner <nfortne2@hdfgroup.org>2015-04-16 20:57:26 (GMT)
commitf53cfbe9d66c87b414bb759b91d7c32eb28fa88f (patch)
tree7dc8c3b5a717b8cf03304614efaf1944cd9ffb00 /src/H5Shyper.c
parent11efaf4ff7d49c9242f832db4394376ba2541ab0 (diff)
downloadhdf5-f53cfbe9d66c87b414bb759b91d7c32eb28fa88f.zip
hdf5-f53cfbe9d66c87b414bb759b91d7c32eb28fa88f.tar.gz
hdf5-f53cfbe9d66c87b414bb759b91d7c32eb28fa88f.tar.bz2
[svn-r26828] Implement support for unlimited selections (not supported by VDS code yet).
Add tests for unlimited selections. Various other minor changes. Tested: ummon
Diffstat (limited to 'src/H5Shyper.c')
-rw-r--r--src/H5Shyper.c465
1 files changed, 411 insertions, 54 deletions
diff --git a/src/H5Shyper.c b/src/H5Shyper.c
index 51194f9..32b6fe9 100644
--- a/src/H5Shyper.c
+++ b/src/H5Shyper.c
@@ -54,8 +54,10 @@ static herr_t H5S_hyper_get_seq_list(const H5S_t *space, unsigned flags,
static herr_t H5S_hyper_release(H5S_t *space);
static htri_t H5S_hyper_is_valid(const H5S_t *space);
static hssize_t H5S_hyper_serial_size(const H5S_t *space);
-static herr_t H5S_hyper_serialize(const H5S_t *space, uint8_t **p);
-static herr_t H5S_hyper_deserialize(H5S_t *space, const uint8_t **p);
+static herr_t H5S_hyper_serialize(const H5F_t *f, const H5S_t *space,
+ uint8_t **p);
+static herr_t H5S_hyper_deserialize(const H5F_t *f, H5S_t *space,
+ uint32_t version, uint8_t flags, const uint8_t **p);
static herr_t H5S_hyper_bounds(const H5S_t *space, hsize_t *start, hsize_t *end);
static herr_t H5S_hyper_offset(const H5S_t *space, hsize_t *offset);
static htri_t H5S_hyper_is_contiguous(const H5S_t *space);
@@ -1644,6 +1646,16 @@ H5S_hyper_copy (H5S_t *dst, const H5S_t *src, hbool_t share_selection)
dst_hslab->app_diminfo[u]=src_hslab->app_diminfo[u];
} /* end for */
} /* end if */
+ dst_hslab->unlim_dim = src_hslab->unlim_dim;
+ if(src_hslab->unlim_dim >= 0) {
+ size_t u; /* Local index variable */
+
+ for(u = 0; u < src->extent.rank; u++) {
+ dst_hslab->opt_unlim_diminfo[u] = src_hslab->opt_unlim_diminfo[u];
+ dst_hslab->app_diminfo[u] = src_hslab->app_diminfo[u];
+ } /* end for */
+ } /* end for */
+ dst_hslab->num_elem_non_unlim = src_hslab->num_elem_non_unlim;
dst->select.sel_info.hslab->span_lst=src->select.sel_info.hslab->span_lst;
/* Check if there is hyperslab span information to copy */
@@ -1658,6 +1670,21 @@ H5S_hyper_copy (H5S_t *dst, const H5S_t *src, hbool_t share_selection)
dst->select.sel_info.hslab->span_lst = H5S_hyper_copy_span(src->select.sel_info.hslab->span_lst);
} /* end if */
+ /* If there is an unlimited dimension, we must update the selection if the
+ * extent changed */
+ if(dst_hslab->unlim_dim >= 0) {
+ htri_t extent_equal;
+
+ /* Check if the extent changed */
+ if((extent_equal = H5S_extent_equal(src, dst)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "dataspace comparison failed")
+
+ if(!extent_equal)
+ /* Update selection due to changed extent */
+ if(H5S__hyper_update_extent_offset(dst) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't update hyperslab")
+ } /* end if */
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_hyper_copy() */
@@ -1866,15 +1893,26 @@ H5S_get_select_hyper_nblocks(H5S_t *space)
/* Check for a "regular" hyperslab selection */
if(space->select.sel_info.hslab->diminfo_valid) {
+ const H5S_hyper_dim_t *diminfo; /* Alias for dataspace's diminfo information */
unsigned u; /* Local index variable */
+ /* Set diminfo based on whether this is an unlimited selection */
+ if(space->select.sel_info.hslab->unlim_dim >= 0)
+ diminfo = space->select.sel_info.hslab->opt_diminfo;
+ else
+ diminfo = space->select.sel_info.hslab->app_diminfo;
+
/* Check each dimension */
- for(ret_value = 1, u = 0; u < space->extent.rank; u++)
- ret_value *= space->select.sel_info.hslab->app_diminfo[u].count;
+ for(ret_value = 1, u = 0; u < space->extent.rank; u++) {
+ if(diminfo[u].block == (hsize_t)0)
+ HGOTO_DONE((hsize_t)0)
+ ret_value *= diminfo[u].count;;
+ } /* end for */
} /* end if */
else
ret_value = H5S_hyper_span_nblocks(space->select.sel_info.hslab->span_lst);
+done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5S_get_select_hyper_nblocks() */
@@ -2071,7 +2109,7 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_hyper_serialize (const H5S_t *space, uint8_t **p)
+H5S_hyper_serialize(const H5F_t *f, const H5S_t *space, uint8_t **p)
{
const H5S_hyper_dim_t *diminfo; /* Alias for dataspace's diminfo information */
hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary hyperslab counts */
@@ -2081,6 +2119,8 @@ H5S_hyper_serialize (const H5S_t *space, uint8_t **p)
hsize_t temp_off; /* Offset in a given dimension */
uint8_t *lenp; /* pointer to length location for later storage */
uint32_t len = 0; /* number of bytes used */
+ uint32_t version; /* Version number */
+ uint8_t flags = 0; /* Flags for message */
hsize_t block_count; /* block counter for regular hyperslabs */
unsigned fast_dim; /* Rank of the fastest changing dimension for the dataspace */
unsigned ndims; /* Rank of the dataspace */
@@ -2090,10 +2130,21 @@ H5S_hyper_serialize (const H5S_t *space, uint8_t **p)
HDassert(space);
+ /* Calculate version */
+ if(space->select.sel_info.hslab->unlim_dim >= 0) {
+ version = 2;
+ flags |= H5S_SELECT_FLAG_UNLIM;
+ } /* end if */
+ else
+ version = 1;
+
/* Store the preamble information */
- UINT32ENCODE(*p, (uint32_t)H5S_GET_SELECT_TYPE(space)); /* Store the type of selection */
- UINT32ENCODE(*p, (uint32_t)1); /* Store the version number */
- UINT32ENCODE(*p, (uint32_t)0); /* Store the un-used padding */
+ UINT32ENCODE(*p, (uint32_t)H5S_GET_SELECT_TYPE(space)); /* Store the type of selection */
+ UINT32ENCODE(*p, version); /* Store the version number */
+ if(version >= 2)
+ *(*p)++ = flags; /* Store the flags */
+ else
+ UINT32ENCODE(*p, (uint32_t)0); /* Store the un-used padding */
lenp = *p; /* keep the pointer to the length location for later */
*p += 4; /* skip over space for length */
@@ -2101,8 +2152,23 @@ H5S_hyper_serialize (const H5S_t *space, uint8_t **p)
UINT32ENCODE(*p, (uint32_t)space->extent.rank);
len += 4;
+ /* If there is an unlimited dimension, only encode opt_unlim_diminfo */
+ if(flags & H5S_SELECT_FLAG_UNLIM) {
+ unsigned i;
+
+ HDassert(H5S_UNLIMITED == HSIZE_UNDEF);
+
+ /* Iterate over dimensions */
+ for(i = 0; i < space->extent.rank; i++) {
+ /* Encode start/stride/block/count */
+ H5F_size_encode(f, p, space->select.sel_info.hslab->opt_unlim_diminfo[i].start);
+ H5F_size_encode(f, p, space->select.sel_info.hslab->opt_unlim_diminfo[i].stride);
+ H5F_size_encode(f, p, space->select.sel_info.hslab->opt_unlim_diminfo[i].count);
+ H5F_size_encode(f, p, space->select.sel_info.hslab->opt_unlim_diminfo[i].block);
+ } /* end for */
+ } /* end if */
/* Check for a "regular" hyperslab selection */
- if(space->select.sel_info.hslab->diminfo_valid) {
+ else if(space->select.sel_info.hslab->diminfo_valid) {
unsigned u; /* Local counting variable */
/* Set some convienence values */
@@ -2154,7 +2220,8 @@ H5S_hyper_serialize (const H5S_t *space, uint8_t **p)
/* Work on other dimensions if necessary */
if(fast_dim > 0) {
- int temp_dim; /* Temporary rank holder */
+ int
+ temp_dim; /* Temporary rank holder */
/* Reset the block counts */
tmp_count[fast_dim]=diminfo[fast_dim].count;
@@ -2235,7 +2302,8 @@ H5S_hyper_serialize (const H5S_t *space, uint8_t **p)
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_hyper_deserialize (H5S_t *space, const uint8_t **p)
+H5S_hyper_deserialize(const H5F_t *f, H5S_t *space, uint32_t UNUSED version,
+ uint8_t flags, const uint8_t **p)
{
unsigned rank; /* rank of points */
size_t num_elem=0; /* number of elements in selection */
@@ -2262,32 +2330,68 @@ H5S_hyper_deserialize (H5S_t *space, const uint8_t **p)
/* Deserialize slabs to select */
/* (The header and rank have already beed decoded) */
rank = space->extent.rank; /* Retrieve rank from space */
- UINT32DECODE(*p,num_elem); /* decode the number of points */
- /* Set the count & stride for all blocks */
- for(tcount=count,tstride=stride,j=0; j<rank; j++,tstride++,tcount++) {
- *tcount=1;
- *tstride=1;
- } /* end for */
+ /* If there is an unlimited dimension, only encode opt_unlim_diminfo */
+ if(flags & H5S_SELECT_FLAG_UNLIM) {
+ HDassert(H5S_UNLIMITED == HSIZE_UNDEF);
+ HDassert(version >= 2);
+
+ /* Iterate over dimensions */
+ for(i = 0; i < space->extent.rank; i++) {
+ /* Decode start/stride/block/count */
+ H5F_size_decode(f, p, &space->select.sel_info.hslab->opt_unlim_diminfo[i].start);
+ H5F_size_decode(f, p, &space->select.sel_info.hslab->opt_unlim_diminfo[i].stride);
+ H5F_size_decode(f, p, &space->select.sel_info.hslab->opt_unlim_diminfo[i].count);
+ if(space->select.sel_info.hslab->opt_unlim_diminfo[i].count == H5S_UNLIMITED) {
+ if(space->select.sel_info.hslab->unlim_dim >= 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot have more than one unlimited dimension in selection")
+ space->select.sel_info.hslab->unlim_dim = (int)i;
+ } /* end if */
+ H5F_size_decode(f, p, &space->select.sel_info.hslab->opt_unlim_diminfo[i].block);
+ if(space->select.sel_info.hslab->opt_unlim_diminfo[i].block == H5S_UNLIMITED) {
+ if(space->select.sel_info.hslab->unlim_dim >= 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot have more than one unlimited dimension in selection")
+ space->select.sel_info.hslab->unlim_dim = (int)i;
+ } /* end if */
+ } /* end for */
+
+ /* Copy opt_unlim_diminfo to app_diminfo */
+ HDassert(sizeof(space->select.sel_info.hslab->app_diminfo) == sizeof(space->select.sel_info.hslab->opt_unlim_diminfo));
+ HDmemcpy(space->select.sel_info.hslab->app_diminfo, space->select.sel_info.hslab->opt_unlim_diminfo, sizeof(space->select.sel_info.hslab->app_diminfo));
- /* Retrieve the coordinates from the buffer */
- for(i=0; i<num_elem; i++) {
- /* Decode the starting points */
- for(tstart=start,j=0; j<rank; j++,tstart++)
- UINT32DECODE(*p, *tstart);
+ /* Update selection due to match current extent */
+ if(H5S__hyper_update_extent_offset(space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't update hyperslab")
+ } /* end if */
+ else {
+ /* decode the number of points */
+ UINT32DECODE(*p,num_elem);
- /* Decode the ending points */
- for(tend=end,j=0; j<rank; j++,tend++)
- UINT32DECODE(*p, *tend);
+ /* Set the count & stride for all blocks */
+ for(tcount=count,tstride=stride,j=0; j<rank; j++,tstride++,tcount++) {
+ *tcount=1;
+ *tstride=1;
+ } /* end for */
- /* Change the ending points into blocks */
- for(tblock=block,tstart=start,tend=end,j=0; j<rank; j++,tstart++,tend++,tblock++)
- *tblock=(*tend-*tstart)+1;
+ /* Retrieve the coordinates from the buffer */
+ for(i=0; i<num_elem; i++) {
+ /* Decode the starting points */
+ for(tstart=start,j=0; j<rank; j++,tstart++)
+ UINT32DECODE(*p, *tstart);
- /* Select or add the hyperslab to the current selection */
- if((ret_value=H5S_select_hyperslab(space,(i==0 ? H5S_SELECT_SET : H5S_SELECT_OR),start,stride,count,block))<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection")
- } /* end for */
+ /* Decode the ending points */
+ for(tend=end,j=0; j<rank; j++,tend++)
+ UINT32DECODE(*p, *tend);
+
+ /* Change the ending points into blocks */
+ for(tblock=block,tstart=start,tend=end,j=0; j<rank; j++,tstart++,tend++,tblock++)
+ *tblock=(*tend-*tstart)+1;
+
+ /* Select or add the hyperslab to the current selection */
+ if((ret_value=H5S_select_hyperslab(space,(i==0 ? H5S_SELECT_SET : H5S_SELECT_OR),start,stride,count,block))<0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection")
+ } /* end for */
+ } /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -2460,11 +2564,19 @@ H5S_get_select_hyper_blocklist(H5S_t *space, hbool_t internal, hsize_t startbloc
*/
diminfo = space->select.sel_info.hslab->opt_diminfo;
else
- /*
- * Use the "application dimension information" to pass back to the user
- * the blocks they set, not the optimized, internal information.
- */
- diminfo = space->select.sel_info.hslab->app_diminfo;
+ if(space->select.sel_info.hslab->unlim_dim >= 0)
+ /*
+ * There is an unlimited dimension so we must use opt_diminfo as
+ * it has been "clipped" to the current extent.
+ */
+ diminfo = space->select.sel_info.hslab->opt_diminfo;
+ else
+ /*
+ * Use the "application dimension information" to pass back to
+ * the user the blocks they set, not the optimized, internal
+ * information.
+ */
+ diminfo = space->select.sel_info.hslab->app_diminfo;
/* Build the tables of count sizes as well as the initial offset */
for(u = 0; u < ndims; u++) {
@@ -3148,7 +3260,8 @@ H5S_hyper_is_regular(const H5S_t *space)
HDassert(space);
/* Only simple check for regular hyperslabs for now... */
- if(space->select.sel_info.hslab->diminfo_valid)
+ if(space->select.sel_info.hslab->diminfo_valid
+ || (space->select.sel_info.hslab->unlim_dim >= 0))
ret_value=TRUE;
else
ret_value=FALSE;
@@ -6031,6 +6144,12 @@ H5S_hyper_generate_spans(H5S_t *space)
/* Get the diminfo */
for(u=0; u<space->extent.rank; u++) {
+ /* Check for unlimited dimension and return error */
+ if(space->select.sel_info.hslab->opt_diminfo[u].count == H5S_UNLIMITED)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "can't generate spans with unlimited count (only H5S_SELECT_SET supported)")
+ if(space->select.sel_info.hslab->opt_diminfo[u].block == H5S_UNLIMITED)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "can't generate spans with unlimited block (only H5S_SELECT_SET supported)")
+
tmp_start[u]=space->select.sel_info.hslab->opt_diminfo[u].start;
tmp_stride[u]=space->select.sel_info.hslab->opt_diminfo[u].stride;
tmp_count[u]=space->select.sel_info.hslab->opt_diminfo[u].count;
@@ -6318,6 +6437,7 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
const hsize_t *opt_count; /* Optimized count information */
const hsize_t *opt_block; /* Optimized block information */
unsigned u; /* Counters */
+ int unlim_dim = -1; /* Unlimited dimension in selection, of -1 if none */
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -6336,6 +6456,20 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
if(block==NULL)
block = _ones;
+ /* Check for unlimited dimension */
+ for(u = 0; u<space->extent.rank; u++)
+ if((count[u] == H5S_UNLIMITED) || (block[u] == H5S_UNLIMITED)) {
+ if(unlim_dim >= 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot have more than one unlimited dimension in selection")
+ else {
+ if(op != H5S_SELECT_SET)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot use unlimited selection to modify existing selection")
+ if(count[u] == block[u] /* == H5S_UNLIMITED */)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "count and block cannot both be unlimited")
+ unlim_dim = (int)u;
+ } /* end else */
+ } /* end if */
+
/*
* Check new selection.
*/
@@ -6385,12 +6519,26 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
for(u=0; u<space->extent.rank; u++) {
/* contiguous hyperslabs have the block size equal to the stride */
if(stride[u]==block[u]) {
- int_count[u]=1;
- int_stride[u]=1;
- if(block[u]==1)
- int_block[u]=count[u];
- else
- int_block[u]=block[u]*count[u];
+ if(count[u] == H5S_UNLIMITED) {
+ if(block[u] == 1) {
+ int_block[u] = H5S_UNLIMITED;
+ int_count[u] = 1;
+ int_stride[u] = 1;
+ } /* end if */
+ else {
+ int_block[u] = block[u];
+ int_count[u] = H5S_UNLIMITED;
+ int_stride[u] = stride[u];
+ } /* end else */
+ } /* end if */
+ else {
+ int_count[u]=1;
+ int_stride[u]=1;
+ if(block[u]==1)
+ int_block[u]=count[u];
+ else
+ int_block[u]=block[u]*count[u];
+ } /* end else */
} /* end if */
else {
if(count[u]==1)
@@ -6524,16 +6672,41 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
space->select.num_elem *= (opt_count[u] * opt_block[u]);
} /* end for */
+ /* Save unlim_dim */
+ space->select.sel_info.hslab->unlim_dim = unlim_dim;
+
/* Indicate that the dimension information is valid */
space->select.sel_info.hslab->diminfo_valid = TRUE;
/* Indicate that there's no slab information */
space->select.sel_info.hslab->span_lst = NULL;
+
+ /* Handle unlimited selections */
+ if(unlim_dim >= 0) {
+ space->select.sel_info.hslab->num_elem_non_unlim = (hsize_t)1;
+ for(u = 0; u < space->extent.rank; u++) {
+ space->select.sel_info.hslab->opt_unlim_diminfo[u].start = start[u];
+ space->select.sel_info.hslab->opt_unlim_diminfo[u].stride = opt_stride[u];
+ space->select.sel_info.hslab->opt_unlim_diminfo[u].count = opt_count[u];
+ space->select.sel_info.hslab->opt_unlim_diminfo[u].block = opt_block[u];
+
+ if((int)u != unlim_dim)
+ space->select.sel_info.hslab->num_elem_non_unlim *= (opt_count[u] * opt_block[u]);
+ } /* end for */
+
+ /* Set opt_diminfo or span tree based on extent */
+ if(H5S__hyper_update_extent_offset(space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't set selection based on extent")
+ } /* end if */
} /* end if */
else if(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA) {
/* Sanity check */
HDassert(H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS);
+ /* Cannot modify unlimited selections */
+ if(space->select.sel_info.hslab->unlim_dim >= 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot modify unlimited selection")
+
/* Check if there's no hyperslab span information currently */
if(NULL == space->select.sel_info.hslab->span_lst)
if(H5S_hyper_generate_spans(space) < 0)
@@ -6927,6 +7100,7 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
const hsize_t *opt_count; /* Optimized count information */
const hsize_t *opt_block; /* Optimized block information */
unsigned u; /* Counters */
+ int unlim_dim = -1; /* Unlimited dimension in selection, of -1 if none */
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -6945,6 +7119,20 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
if(block==NULL)
block = _ones;
+ /* Check for unlimited dimension */
+ for(u = 0; u<space->extent.rank; u++)
+ if((count[u] == H5S_UNLIMITED) || (block[u] == H5S_UNLIMITED)) {
+ if(unlim_dim >= 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot have more than one unlimited dimension in selection")
+ else {
+ if(op != H5S_SELECT_SET)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot use unlimited selection to modify existing selection")
+ if(count[u] == block[u] /* == H5S_UNLIMITED */)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "count and block cannot both be unlimited")
+ unlim_dim = (int)u;
+ } /* end else */
+ } /* end if */
+
/*
* Check new selection.
*/
@@ -6990,12 +7178,26 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
for(u=0; u<space->extent.rank; u++) {
/* contiguous hyperslabs have the block size equal to the stride */
if(stride[u]==block[u]) {
- int_count[u]=1;
- int_stride[u]=1;
- if(block[u]==1)
- int_block[u]=count[u];
- else
- int_block[u]=block[u]*count[u];
+ if(count[u] == H5S_UNLIMITED) {
+ if(block[u] == 1) {
+ int_block[u] = H5S_UNLIMITED;
+ int_count[u] = 1;
+ int_stride[u] = 1;
+ } /* end if */
+ else {
+ int_block[u] = block[u];
+ int_count[u] = H5S_UNLIMITED;
+ int_stride[u] = stride[u];
+ } /* end else */
+ } /* end if */
+ else {
+ int_count[u]=1;
+ int_stride[u]=1;
+ if(block[u]==1)
+ int_block[u]=count[u];
+ else
+ int_block[u]=block[u]*count[u];
+ } /* end else */
} /* end if */
else {
if(count[u]==1)
@@ -7120,16 +7322,41 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
space->select.num_elem*=(opt_count[u]*opt_block[u]);
} /* end for */
+ /* Save unlim_dim */
+ space->select.sel_info.hslab->unlim_dim = unlim_dim;
+
/* Indicate that the dimension information is valid */
space->select.sel_info.hslab->diminfo_valid=TRUE;
/* Indicate that there's no slab information */
space->select.sel_info.hslab->span_lst=NULL;
+
+ /* Handle unlimited selections */
+ if(unlim_dim >= 0) {
+ space->select.sel_info.hslab->num_elem_non_unlim = (hsize_t)1;
+ for(u = 0; u < space->extent.rank; u++) {
+ space->select.sel_info.hslab->opt_unlim_diminfo[u].start = start[u];
+ space->select.sel_info.hslab->opt_unlim_diminfo[u].stride = opt_stride[u];
+ space->select.sel_info.hslab->opt_unlim_diminfo[u].count = opt_count[u];
+ space->select.sel_info.hslab->opt_unlim_diminfo[u].block = opt_block[u];
+
+ if((int)u != unlim_dim)
+ space->select.sel_info.hslab->num_elem_non_unlim *= (opt_count[u] * opt_block[u]);
+ } /* end for */
+
+ /* Set opt_diminfo or span tree based on extent */
+ if(H5S__hyper_update_extent_offset(space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't set selection based on extent")
+ } /* end if */
} /* end if */
else if(op>=H5S_SELECT_OR && op<=H5S_SELECT_NOTA) {
/* Sanity check */
HDassert(H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS);
+ /* Cannot modify unlimited selections */
+ if(space->select.sel_info.hslab->unlim_dim >= 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot modify unlimited selection")
+
/* Check if there's no hyperslab span information currently */
if(space->select.sel_info.hslab->span_lst==NULL)
if(H5S_hyper_generate_spans(space)<0)
@@ -9254,6 +9481,127 @@ done:
/*--------------------------------------------------------------------------
NAME
+ H5S__hyper_update_extent_offset
+ PURPOSE
+ Updates the hyperslab selection after a change to the dataspace extent
+ or offset
+ USAGE
+ VDSINC
+ RETURNS
+ Non-negative on success/Negative on failure.
+ DESCRIPTION
+ since unlimited selections are internally described as limited
+ selections with maximal size, these internal selections need to be
+ updated whenever the maximum size changes. This function
+ recaluculates the unlimited dimension (if any) of the hyperslab
+ selection when the extent or offset is changed.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5S__hyper_update_extent_offset(H5S_t *space)
+{
+ H5S_hyper_sel_t *hslab; /* Convenience pointer to hyperslab info */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE
+
+ /* Check parameters */
+ HDassert(space);
+ hslab = space->select.sel_info.hslab;
+ HDassert(hslab);
+
+ /* Check for unlimited dimension */
+ if(hslab->unlim_dim < 0)
+ HGOTO_DONE(SUCCEED)
+
+ /* Free previous spans, if any */
+ if(hslab->span_lst != NULL) {
+ if(H5S_hyper_free_span_info(hslab->span_lst) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release hyperslab spans")
+ hslab->span_lst = NULL;
+ } /* end if */
+
+ /* Initialize opt_diminfo wit opt_unlim_diminfo */
+ hslab->opt_diminfo[hslab->unlim_dim] = hslab->opt_unlim_diminfo[hslab->unlim_dim];
+
+ /* Check for selection outside extent */
+ if((hsize_t)((hssize_t)hslab->opt_diminfo[hslab->unlim_dim].start
+ + space->select.offset[hslab->unlim_dim])
+ >= space->extent.size[hslab->unlim_dim]) {
+ if(hslab->opt_diminfo[hslab->unlim_dim].block == H5S_UNLIMITED)
+ hslab->opt_diminfo[hslab->unlim_dim].block = 0;
+ else
+ hslab->opt_diminfo[hslab->unlim_dim].count = 0;
+
+ space->select.num_elem = (hsize_t)0;
+
+ /* Mark that opt_diminfo is valid */
+ hslab->diminfo_valid = TRUE;
+
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+
+ /* Check for single block in unlimited dimension */
+ if(hslab->opt_diminfo[hslab->unlim_dim].count == (hsize_t)1) {
+ HDassert(hslab->opt_diminfo[hslab->unlim_dim].block = H5S_UNLIMITED);
+
+ /* Calculate actual block size for this extent */
+ hslab->opt_diminfo[hslab->unlim_dim].block =
+ (hsize_t)((hssize_t)space->extent.size[hslab->unlim_dim]
+ - ((hssize_t)hslab->opt_diminfo[hslab->unlim_dim].start
+ + space->select.offset[hslab->unlim_dim]));
+
+ /* Calculate number of elements */
+ space->select.num_elem = hslab->opt_diminfo[hslab->unlim_dim].block
+ * hslab->num_elem_non_unlim;
+
+ /* Mark that opt_diminfo is valid */
+ hslab->diminfo_valid = TRUE;
+ } /* end if */
+ else {
+ HDassert(hslab->opt_diminfo[hslab->unlim_dim].count == H5S_UNLIMITED);
+ HDassert(hslab->opt_diminfo[hslab->unlim_dim].block != H5S_UNLIMITED);
+
+ /* Calculate initial count (last block may be partial) */
+ hslab->opt_diminfo[hslab->unlim_dim].count =
+ ((hsize_t)((hssize_t)space->extent.size[hslab->unlim_dim]
+ - ((hssize_t)hslab->opt_diminfo[hslab->unlim_dim].start
+ + space->select.offset[hslab->unlim_dim])
+ + (hssize_t)hslab->opt_diminfo[hslab->unlim_dim].stride
+ - (hssize_t)1)
+ / hslab->opt_diminfo[hslab->unlim_dim].stride);
+ HDassert(hslab->opt_diminfo[hslab->unlim_dim].count > (hsize_t)0);
+
+ /* Calculate number of elements */
+ space->select.num_elem = hslab->opt_diminfo[hslab->unlim_dim].count
+ * hslab->opt_diminfo[hslab->unlim_dim].block
+ * hslab->num_elem_non_unlim;
+
+ /* Check if last block is partial */
+ if(((hslab->opt_diminfo[hslab->unlim_dim].stride
+ * (hslab->opt_diminfo[hslab->unlim_dim].count - (hsize_t)1))
+ + hslab->opt_diminfo[hslab->unlim_dim].block - (hsize_t)1)
+ > ((hsize_t)((hssize_t)space->extent.size[hslab->unlim_dim]
+ - (hssize_t)hslab->opt_diminfo[hslab->unlim_dim].start
+ + space->select.offset[hslab->unlim_dim]))) {
+ /* Last block is partial, need to construct compound selection */
+ HDassert(0 && "Not yet implemented...");//VDSINC
+ } /* end if */
+ else
+ /* Last block is complete, simply mark that opt_diminfo is valid */
+ hslab->diminfo_valid = TRUE;
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S__hyper_update_extent_offset() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5Sis_regular_hyperslab
PURPOSE
Determine if a hyperslab selection is regular
@@ -9325,6 +9673,7 @@ H5Sget_regular_hyperslab(hid_t spaceid, hsize_t start[], hsize_t stride[],
hsize_t count[], hsize_t block[])
{
H5S_t *space; /* Dataspace to query */
+ H5S_hyper_dim_t *diminfo; /* Pointer to diminfo to return */
unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
@@ -9339,19 +9688,27 @@ H5Sget_regular_hyperslab(hid_t spaceid, hsize_t start[], hsize_t stride[],
if(TRUE != H5S_hyper_is_regular(space))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a regular hyperslab selection")
+ /* Determine which diminfo to return */
+ if(space->select.sel_info.hslab->diminfo_valid)
+ diminfo = space->select.sel_info.hslab->app_diminfo;
+ else {
+ HDassert(space->select.sel_info.hslab->unlim_dim >= 0);
+ diminfo = space->select.sel_info.hslab->opt_unlim_diminfo;
+ } /* end else */
+
/* Retrieve hyperslab parameters */
if(start)
for(u = 0; u < space->extent.rank; u++)
- start[u] = space->select.sel_info.hslab->app_diminfo[u].start;
+ start[u] = diminfo[u].start;
if(stride)
for(u = 0; u < space->extent.rank; u++)
- stride[u] = space->select.sel_info.hslab->app_diminfo[u].stride;
+ stride[u] = diminfo[u].stride;
if(count)
for(u = 0; u < space->extent.rank; u++)
- count[u] = space->select.sel_info.hslab->app_diminfo[u].count;
+ count[u] = diminfo[u].count;
if(block)
for(u = 0; u < space->extent.rank; u++)
- block[u] = space->select.sel_info.hslab->app_diminfo[u].block;
+ block[u] = diminfo[u].block;
done:
FUNC_LEAVE_API(ret_value)