summaryrefslogtreecommitdiffstats
path: root/src
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
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')
-rw-r--r--src/H5Fint.c127
-rw-r--r--src/H5Fprivate.h6
-rw-r--r--src/H5Olayout.c8
-rw-r--r--src/H5Pdcpl.c6
-rw-r--r--src/H5R.c4
-rw-r--r--src/H5S.c22
-rw-r--r--src/H5Sall.c11
-rw-r--r--src/H5Shyper.c465
-rw-r--r--src/H5Snone.c11
-rw-r--r--src/H5Spkg.h20
-rw-r--r--src/H5Spoint.c11
-rw-r--r--src/H5Sprivate.h12
-rw-r--r--src/H5Spublic.h2
-rw-r--r--src/H5Sselect.c48
-rw-r--r--src/H5public.h1
15 files changed, 658 insertions, 96 deletions
diff --git a/src/H5Fint.c b/src/H5Fint.c
index 31f4176..3600476 100644
--- a/src/H5Fint.c
+++ b/src/H5Fint.c
@@ -1644,6 +1644,9 @@ done:
* then increments the pointer to the first byte after the
* address. An undefined value is stored as all 1's.
*
+ * Note this function is almost identical to H5F_size_encode.
+ * Changes should be made in both places.
+ *
* Return: void
*
* Programmer: Robb Matzke
@@ -1716,6 +1719,9 @@ H5F_addr_encode(const H5F_t *f, uint8_t **pp/*in,out*/, haddr_t addr)
* If the value read is all 1's then the address is returned
* with an undefined value.
*
+ * Note this function is almost identical to H5F_size_decode.
+ * Changes should be made in both places.
+ *
* Return: void
*
* Programmer: Robb Matzke
@@ -1806,6 +1812,127 @@ H5F_addr_decode(const H5F_t *f, const uint8_t **pp/*in,out*/, haddr_t *addr_p/*o
/*-------------------------------------------------------------------------
+ * Function: H5F_size_encode
+ *
+ * Purpose: Encodes a size into the buffer pointed to by *PP and then
+ * increments the pointer to the first byte after the size.
+ * An undefined value is stored as all 1's. If size cannot
+ * be HSIZE_UNDEF, then you can use H5F_ENCODE_LENGTH
+ * instead.
+ *
+ * Note this function is almost identical to H5F_addr_encode
+ * and H5F_addr_encode_len. Changes should be made in both
+ * places.
+ *
+ * Return: void
+ *
+ * Programmer: Neil Fortner
+ * Friday, April 10, 2015
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+H5F_size_encode(const H5F_t *f, uint8_t **pp/*in,out*/, hsize_t size)
+{
+ unsigned u; /* Local index variable */
+
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ HDassert(f);
+ HDassert(pp && *pp);
+
+ if(size != HSIZE_UNDEF) {
+ for(u = 0; u < H5F_SIZEOF_SIZE(f); u++) {
+ *(*pp)++ = (uint8_t)(size & 0xff);
+ size >>= 8;
+ } /* end for */
+ HDassert("overflow" && 0 == size);
+ } /* end if */
+ else {
+ for(u = 0; u < H5F_SIZEOF_SIZE(f); u++)
+ *(*pp)++ = 0xff;
+ } /* end else */
+
+ FUNC_LEAVE_NOAPI_VOID
+} /* end H5F_size_encode() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_size_decode
+ *
+ * Purpose: Decodes a size from the buffer pointed to by *PP and
+ * updates the pointer to point to the next byte after the
+ * size.
+ *
+ * If the value read is all 1's then the size is returned
+ * with an undefined value. If size cannot be HSIZE_UNDEF,
+ * then you can use H5F_DECODE_LENGTH instead.
+ *
+ * Note this function is almost identical to H5F_addr_decode
+ * and H5F_addr_decode_len. Changes should be made in both
+ * places.
+ *
+ * Return: void
+ *
+ * Programmer: Neil Fortner
+ * Friday, April 10, 2015
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+H5F_size_decode(const H5F_t *f, const uint8_t **pp/*in,out*/,
+ hsize_t *size_p/*out*/)
+{
+ hbool_t all_zero = TRUE; /* True if address was all zeroes */
+ unsigned u; /* Local index variable */
+
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ HDassert(f);
+ HDassert(pp && *pp);
+ HDassert(size_p);
+
+ /* Reset value in destination */
+ *size_p = 0;
+
+ /* Decode bytes from size */
+ for(u = 0; u < H5F_SIZEOF_SIZE(f); u++) {
+ uint8_t c; /* Local decoded byte */
+
+ /* Get decoded byte (and advance pointer) */
+ c = *(*pp)++;
+
+ /* Check for non-undefined size byte value */
+ if(c != 0xff)
+ all_zero = FALSE;
+
+ if(u < sizeof(*size_p)) {
+ haddr_t tmp = c; /* Local copy of size, for casting */
+
+ /* Shift decoded byte to correct position */
+ tmp <<= (u * 8); /*use tmp to get casting right */
+
+ /* Merge into already decoded bytes */
+ *size_p |= tmp;
+ } /* end if */
+ else
+ if(!all_zero)
+ HDassert(0 == **pp); /*overflow */
+ } /* end for */
+
+ /* If 'all_zero' is still TRUE, the size_p was entirely composed of '0xff'
+ * bytes, which is the encoded form of 'HSIZE_UNDEF', so set the destination
+ * to that value */
+ if(all_zero)
+ *size_p = HSIZE_UNDEF;
+
+ FUNC_LEAVE_NOAPI_VOID
+} /* end H5F_size_decode() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5F_set_grp_btree_shared
*
* Purpose: Set the grp_btree_shared field with a valid ref-count pointer.
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index 4cd8c69..ab07526 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -662,6 +662,12 @@ H5_DLL void H5F_addr_encode_len(size_t addr_len, uint8_t **pp, haddr_t addr);
H5_DLL void H5F_addr_decode(const H5F_t *f, const uint8_t **pp, haddr_t *addr_p);
H5_DLL void H5F_addr_decode_len(size_t addr_len, const uint8_t **pp, haddr_t *addr_p);
+/* Size-related functions */
+H5_DLL void H5F_size_encode(const H5F_t *f, uint8_t **pp/*in,out*/,
+ hsize_t size);
+H5_DLL void H5F_size_decode(const H5F_t *f, const uint8_t **pp/*in,out*/,
+ hsize_t *size_p/*out*/);
+
/* File access property list callbacks */
H5_DLL herr_t H5P_facc_close(hid_t dxpl_id, void *close_data);
diff --git a/src/H5Olayout.c b/src/H5Olayout.c
index ac5219d..b3987e8 100644
--- a/src/H5Olayout.c
+++ b/src/H5Olayout.c
@@ -294,11 +294,11 @@ H5O_layout_decode(H5F_t *f, hid_t dxpl_id, H5O_t UNUSED *open_oh,
heap_block_p += tmp_size;
/* Source selection */
- if(H5S_SELECT_DESERIALIZE(&(mesg->storage.u.virt.list[i].source_select), &heap_block_p) < 0)
+ if(H5S_SELECT_DESERIALIZE(f, &(mesg->storage.u.virt.list[i].source_select), &heap_block_p) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "can't decode source space selection")
/* Virtual selection */
- if(H5S_SELECT_DESERIALIZE(&(mesg->storage.u.virt.list[i].virtual_select), &heap_block_p) < 0)
+ if(H5S_SELECT_DESERIALIZE(f, &(mesg->storage.u.virt.list[i].virtual_select), &heap_block_p) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "can't decode virtual space selection")
} /* end for */
@@ -510,11 +510,11 @@ H5O_layout_encode(H5F_t *f, hbool_t UNUSED disable_shared, uint8_t *p, const voi
heap_block_p += str_size[(2 * i) + 1];
/* Source selection */
- if(H5S_SELECT_SERIALIZE(mesg->storage.u.virt.list[i].source_select, &heap_block_p) < 0)
+ if(H5S_SELECT_SERIALIZE(f, mesg->storage.u.virt.list[i].source_select, &heap_block_p) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to serialize source selection")
/* Virtual selection */
- if(H5S_SELECT_SERIALIZE(mesg->storage.u.virt.list[i].virtual_select, &heap_block_p) < 0)
+ if(H5S_SELECT_SERIALIZE(f, mesg->storage.u.virt.list[i].virtual_select, &heap_block_p) < 0)
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to serialize virtual selection")
} /* end for */
diff --git a/src/H5Pdcpl.c b/src/H5Pdcpl.c
index b9b4653..60241a0 100644
--- a/src/H5Pdcpl.c
+++ b/src/H5Pdcpl.c
@@ -1833,7 +1833,11 @@ H5Pget_virtual_srcspace(hid_t dcpl_id, size_t index)
if(H5D_VIRTUAL != layout.type)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a virtual storage layout")
- /* Get the virtual space */
+ /* Attempt to open source dataset and patch extent if extent status is not
+ * H5O_VIRTUAL_STATUS_CORRECT, otherwise if status is
+ * H5O_VIRTUAL_STATUS_INVALID, patch with bounds of selection VDSINC */
+
+ /* Get the source space */
if(index >= layout.storage.u.virt.list_nused)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid index (out of range)")
HDassert(layout.storage.u.virt.list_nused <= layout.storage.u.virt.list_nalloc);
diff --git a/src/H5R.c b/src/H5R.c
index d96f5e6..aa819f2 100644
--- a/src/H5R.c
+++ b/src/H5R.c
@@ -291,7 +291,7 @@ H5R_create(void *_ref, H5G_loc_t *loc, const char *name, H5R_type_t ref_type, H5
H5F_addr_encode(loc->oloc->file, &p, obj_loc.oloc->addr);
/* Serialize the selection into heap buffer */
- if(H5S_SELECT_SERIALIZE(space, &p) < 0)
+ if(H5S_SELECT_SERIALIZE(loc->oloc->file, space, &p) < 0)
HGOTO_ERROR(H5E_REFERENCE, H5E_CANTCOPY, FAIL, "Unable to serialize selection")
/* Save the serialized buffer for later */
@@ -668,7 +668,7 @@ H5R_get_region(H5F_t *file, hid_t dxpl_id, const void *_ref)
HGOTO_ERROR(H5E_DATASPACE, H5E_NOTFOUND, NULL, "not found")
/* Unserialize the selection */
- if(H5S_SELECT_DESERIALIZE(&ret_value, &p) < 0)
+ if(H5S_SELECT_DESERIALIZE(file, &ret_value, &p) < 0)
HGOTO_ERROR(H5E_REFERENCE, H5E_CANTDECODE, NULL, "can't deserialize selection")
done:
diff --git a/src/H5S.c b/src/H5S.c
index 717374c..57e3b86 100644
--- a/src/H5S.c
+++ b/src/H5S.c
@@ -521,6 +521,12 @@ H5S_extent_copy(H5S_t *dst, const H5S_t *src)
if(H5S_select_all(dst, FALSE) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection")
+ /* If the selection is 'hyper', update the selection due to changed extent
+ */
+ if(H5S_GET_SELECT_TYPE(dst) == H5S_SEL_HYPERSLABS)
+ if(H5S__hyper_update_extent_offset(dst) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't update hyperslab")
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_extent_copy() */
@@ -1356,6 +1362,12 @@ H5S_set_extent_simple(H5S_t *space, unsigned rank, const hsize_t *dims,
if(H5S_select_all(space, FALSE) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection")
+ /* If the selection is 'hyper', update the selection due to changed
+ * extent */
+ if(H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS)
+ if(H5S__hyper_update_extent_offset(space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't update hyperslab")
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5S_set_extent_simple() */
@@ -1579,7 +1591,7 @@ H5S_encode(H5S_t *obj, unsigned char *buf, size_t *nalloc)
buf += extent_size;
/* Encode the selection part of dataspace. */
- if(H5S_SELECT_SERIALIZE(obj, &buf) < 0)
+ if(H5S_SELECT_SERIALIZE(f, obj, &buf) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTENCODE, FAIL, "can't encode select space")
} /* end else */
@@ -1698,7 +1710,7 @@ H5S_decode(const unsigned char *buf)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, NULL, "unable to set all selection")
/* Decode the select part of dataspace. I believe this part always exists. */
- if(H5S_SELECT_DESERIALIZE(&ds, &buf) < 0)
+ if(H5S_SELECT_DESERIALIZE(f, &ds, &buf) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDECODE, NULL, "can't decode space selection")
/* Set return value */
@@ -1989,6 +2001,12 @@ H5S_set_extent_real(H5S_t *space, const hsize_t *size)
if(H5S_select_all(space, FALSE) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection")
+ /* If the selection is 'hyper', update the selection due to changed
+ * extent */
+ if(H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS)
+ if(H5S__hyper_update_extent_offset(space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't update hyperslab")
+
/* Mark the dataspace as no longer shared if it was before */
if(H5O_msg_reset_share(H5O_SDSPACE_ID, space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRESET, FAIL, "can't stop sharing dataspace")
diff --git a/src/H5Sall.c b/src/H5Sall.c
index bbb2935..505e4cf 100644
--- a/src/H5Sall.c
+++ b/src/H5Sall.c
@@ -39,8 +39,10 @@ static herr_t H5S_all_get_seq_list(const H5S_t *space, unsigned flags,
static herr_t H5S_all_release(H5S_t *space);
static htri_t H5S_all_is_valid(const H5S_t *space);
static hssize_t H5S_all_serial_size(const H5S_t *space);
-static herr_t H5S_all_serialize(const H5S_t *space, uint8_t **p);
-static herr_t H5S_all_deserialize(H5S_t *space, const uint8_t **p);
+static herr_t H5S_all_serialize(const H5F_t *f, const H5S_t *space,
+ uint8_t **p);
+static herr_t H5S_all_deserialize(const H5F_t *f, H5S_t *space,
+ uint32_t version, uint8_t flags, const uint8_t **p);
static herr_t H5S_all_bounds(const H5S_t *space, hsize_t *start, hsize_t *end);
static herr_t H5S_all_offset(const H5S_t *space, hsize_t *off);
static htri_t H5S_all_is_contiguous(const H5S_t *space);
@@ -512,7 +514,7 @@ H5S_all_serial_size (const H5S_t UNUSED *space)
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_all_serialize (const H5S_t *space, uint8_t **p)
+H5S_all_serialize(const H5F_t UNUSED *f, const H5S_t *space, uint8_t **p)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
@@ -553,7 +555,8 @@ H5S_all_serialize (const H5S_t *space, uint8_t **p)
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_all_deserialize(H5S_t *space, const uint8_t UNUSED **p)
+H5S_all_deserialize(const H5F_t UNUSED *f, H5S_t *space,
+ uint32_t UNUSED version, uint8_t UNUSED flags, const uint8_t UNUSED **p)
{
herr_t ret_value = SUCCEED; /* return value */
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)
diff --git a/src/H5Snone.c b/src/H5Snone.c
index c5ec2de..28c1ffb 100644
--- a/src/H5Snone.c
+++ b/src/H5Snone.c
@@ -40,8 +40,10 @@ static herr_t H5S_none_get_seq_list(const H5S_t *space, unsigned flags,
static herr_t H5S_none_release(H5S_t *space);
static htri_t H5S_none_is_valid(const H5S_t *space);
static hssize_t H5S_none_serial_size(const H5S_t *space);
-static herr_t H5S_none_serialize(const H5S_t *space, uint8_t **p);
-static herr_t H5S_none_deserialize(H5S_t *space, const uint8_t **p);
+static herr_t H5S_none_serialize(const H5F_t *f, const H5S_t *space,
+ uint8_t **p);
+static herr_t H5S_none_deserialize(const H5F_t *f, H5S_t *space,
+ uint32_t version, uint8_t flags, const uint8_t **p);
static herr_t H5S_none_bounds(const H5S_t *space, hsize_t *start, hsize_t *end);
static herr_t H5S_none_offset(const H5S_t *space, hsize_t *off);
static htri_t H5S_none_is_contiguous(const H5S_t *space);
@@ -480,7 +482,7 @@ H5S_none_serial_size(const H5S_t UNUSED *space)
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_none_serialize(const H5S_t *space, uint8_t **p)
+H5S_none_serialize(const H5F_t UNUSED *f, const H5S_t *space, uint8_t **p)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
@@ -519,7 +521,8 @@ H5S_none_serialize(const H5S_t *space, uint8_t **p)
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_none_deserialize(H5S_t *space, const uint8_t UNUSED **p)
+H5S_none_deserialize(const H5F_t UNUSED *f, H5S_t *space,
+ uint32_t UNUSED version, uint8_t UNUSED flags, const uint8_t UNUSED **p)
{
herr_t ret_value = SUCCEED; /* return value */
diff --git a/src/H5Spkg.h b/src/H5Spkg.h
index 8613fd7..c8993dc 100644
--- a/src/H5Spkg.h
+++ b/src/H5Spkg.h
@@ -34,6 +34,10 @@
#define H5S_VALID_MAX 0x01
#define H5S_VALID_PERM 0x02
+/* Flags for serialization of selections */
+#define H5S_SELECT_FLAG_UNLIM 0x01
+#define H5S_SELECT_FLAG_BITS (H5S_SELECT_FLAG_UNLIM)
+
/* Length of stack-allocated sequences for "project intersect" routines */
#define H5S_PROJECT_INTERSECT_NSEQS 256
@@ -109,13 +113,18 @@ struct H5S_hyper_span_info_t {
typedef struct {
hbool_t diminfo_valid; /* Whether the dataset has valid diminfo */
H5S_hyper_dim_t opt_diminfo[H5S_MAX_RANK]; /* per-dim selection info */
+ H5S_hyper_dim_t opt_unlim_diminfo[H5S_MAX_RANK]; /* per-dim selections info */
H5S_hyper_dim_t app_diminfo[H5S_MAX_RANK]; /* per-dim selection info */
/* 'opt_diminfo' points to a [potentially] optimized version of the user's
* hyperslab information. 'app_diminfo' points to the actual parameters
* that the application used for setting the hyperslab selection. These
* are only used for re-gurgitating the original values used to set the
* hyperslab to the application when it queries the hyperslab selection
- * information. */
+ * information. 'opt_unlim_diminfo' is similar to opt_diminfo but
+ * contains H5S_UNLIMITED in the count or block of the unlimited
+ * dimension (if any). */
+ int unlim_dim; /* Dimension where selection is unlimited, or -1 if none */
+ hsize_t num_elem_non_unlim; /* # of elements in a "slice" excluding the unlimited dimension */
H5S_hyper_span_info_t *span_lst; /* List of hyperslab span information */
} H5S_hyper_sel_t;
@@ -133,9 +142,11 @@ typedef htri_t (*H5S_sel_is_valid_func_t)(const H5S_t *space);
/* Method to determine number of bytes required to store current selection */
typedef hssize_t (*H5S_sel_serial_size_func_t)(const H5S_t *space);
/* Method to store current selection in "serialized" form (a byte sequence suitable for storing on disk) */
-typedef herr_t (*H5S_sel_serialize_func_t)(const H5S_t *space, uint8_t **p);
-/* Method to store create selection from "serialized" form (a byte sequence suitable for storing on disk) */
-typedef herr_t (*H5S_sel_deserialize_func_t)(H5S_t *space, const uint8_t **p);
+typedef herr_t (*H5S_sel_serialize_func_t)(const H5F_t *f, const H5S_t *space,
+ uint8_t **p);
+/* Method to create selection from "serialized" form (a byte sequence suitable for storing on disk) */
+typedef herr_t (*H5S_sel_deserialize_func_t)(const H5F_t *f, H5S_t *space,
+ uint32_t version, uint8_t flags, const uint8_t **p);
/* Method to determine smallest n-D bounding box containing the current selection */
typedef herr_t (*H5S_sel_bounds_func_t)(const H5S_t *space, hsize_t *start, hsize_t *end);
/* Method to determine linear offset of initial element in selection within dataspace */
@@ -255,6 +266,7 @@ H5_DLL herr_t H5S_extent_copy_real(H5S_extent_t *dst, const H5S_extent_t *src,
H5_DLL herr_t H5S__hyper_project_intersection(const H5S_t *src_space,
const H5S_t *dst_space, const H5S_t *src_intersect_space,
H5S_t *proj_space);
+H5_DLL herr_t H5S__hyper_update_extent_offset(H5S_t *space);
/* Testing functions */
#ifdef H5S_TESTING
diff --git a/src/H5Spoint.c b/src/H5Spoint.c
index 44e0510..66fbb03 100644
--- a/src/H5Spoint.c
+++ b/src/H5Spoint.c
@@ -41,8 +41,10 @@ static herr_t H5S_point_get_seq_list(const H5S_t *space, unsigned flags,
static herr_t H5S_point_release(H5S_t *space);
static htri_t H5S_point_is_valid(const H5S_t *space);
static hssize_t H5S_point_serial_size(const H5S_t *space);
-static herr_t H5S_point_serialize(const H5S_t *space, uint8_t **p);
-static herr_t H5S_point_deserialize(H5S_t *space, const uint8_t **p);
+static herr_t H5S_point_serialize(const H5F_t *f, const H5S_t *space,
+ uint8_t **p);
+static herr_t H5S_point_deserialize(const H5F_t *f, H5S_t *space,
+ uint32_t version, uint8_t flags, const uint8_t **p);
static herr_t H5S_point_bounds(const H5S_t *space, hsize_t *start, hsize_t *end);
static herr_t H5S_point_offset(const H5S_t *space, hsize_t *off);
static htri_t H5S_point_is_contiguous(const H5S_t *space);
@@ -820,7 +822,7 @@ H5S_point_serial_size (const H5S_t *space)
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_point_serialize (const H5S_t *space, uint8_t **p)
+H5S_point_serialize(const H5F_t UNUSED *f, const H5S_t *space, uint8_t **p)
{
H5S_pnt_node_t *curr; /* Point information nodes */
uint8_t *lenp; /* pointer to length location for later storage */
@@ -889,7 +891,8 @@ H5S_point_serialize (const H5S_t *space, uint8_t **p)
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_point_deserialize (H5S_t *space, const uint8_t **p)
+H5S_point_deserialize(const H5F_t UNUSED *f, H5S_t *space,
+ uint32_t UNUSED version, uint8_t UNUSED flags, const uint8_t **p)
{
H5S_seloper_t op=H5S_SELECT_SET; /* Selection operation */
unsigned rank; /* Rank of points */
diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h
index 6ce2821..d037b03 100644
--- a/src/H5Sprivate.h
+++ b/src/H5Sprivate.h
@@ -126,7 +126,7 @@ typedef struct H5S_sel_iter_t {
#define H5S_SELECT_VALID(S) ((*(S)->select.type->is_valid)(S))
#define H5S_SELECT_RELEASE(S) ((*(S)->select.type->release)(S))
#define H5S_SELECT_SERIAL_SIZE(S) ((*(S)->select.type->serial_size)(S))
-#define H5S_SELECT_SERIALIZE(S,BUF) ((*(S)->select.type->serialize)(S,BUF))
+#define H5S_SELECT_SERIALIZE(F,S,BUF) ((*(S)->select.type->serialize)(F,S,BUF))
#define H5S_SELECT_BOUNDS(S,START,END) ((*(S)->select.type->bounds)(S,START,END))
#define H5S_SELECT_OFFSET(S, OFFSET) ((*(S)->select.type->offset)(S, OFFSET))
#define H5S_SELECT_IS_CONTIGUOUS(S) ((*(S)->select.type->is_contiguous)(S))
@@ -152,7 +152,7 @@ typedef struct H5S_sel_iter_t {
#define H5S_SELECT_VALID(S) (H5S_select_valid(S))
#define H5S_SELECT_RELEASE(S) (H5S_select_release(S))
#define H5S_SELECT_SERIAL_SIZE(S) (H5S_select_serial_size(S))
-#define H5S_SELECT_SERIALIZE(S,BUF) (H5S_select_serialize(S,BUF))
+#define H5S_SELECT_SERIALIZE(F,S,BUF) (H5S_select_serialize(F,S,BUF))
#define H5S_SELECT_BOUNDS(S,START,END) (H5S_get_select_bounds(S,START,END))
#define H5S_SELECT_OFFSET(S, OFFSET) (H5S_get_select_offset(S, OFFSET))
#define H5S_SELECT_IS_CONTIGUOUS(S) (H5S_select_is_contiguous(S))
@@ -171,7 +171,7 @@ typedef struct H5S_sel_iter_t {
#endif /* H5S_PACKAGE */
/* Handle these two callbacks in a special way, since they have prologs that need to be executed */
#define H5S_SELECT_COPY(DST,SRC,SHARE) (H5S_select_copy(DST,SRC,SHARE))
-#define H5S_SELECT_DESERIALIZE(S,BUF) (H5S_select_deserialize(S,BUF))
+#define H5S_SELECT_DESERIALIZE(F,S,BUF) (H5S_select_deserialize(F,S,BUF))
/* Operations on dataspaces */
@@ -207,7 +207,8 @@ H5_DLL htri_t H5S_extent_equal(const H5S_t *ds1, const H5S_t *ds2);
H5_DLL herr_t H5S_extent_copy(H5S_t *dst, const H5S_t *src);
/* Operations on selections */
-H5_DLL herr_t H5S_select_deserialize(H5S_t **space, const uint8_t **p);
+H5_DLL herr_t H5S_select_deserialize(const H5F_t *f, H5S_t **space,
+ const uint8_t **p);
H5_DLL H5S_sel_type H5S_get_select_type(const H5S_t *space);
H5_DLL herr_t H5S_select_iterate(void *buf, hid_t type_id, const H5S_t *space,
H5D_operator_t op, void *operator_data);
@@ -228,7 +229,8 @@ H5_DLL herr_t H5S_select_get_seq_list(const H5S_t *space, unsigned flags,
H5S_sel_iter_t *iter, size_t maxseq, size_t maxbytes,
size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len);
H5_DLL hssize_t H5S_select_serial_size(const H5S_t *space);
-H5_DLL herr_t H5S_select_serialize(const H5S_t *space, uint8_t **p);
+H5_DLL herr_t H5S_select_serialize(const H5F_t *f, const H5S_t *space,
+ uint8_t **p);
H5_DLL htri_t H5S_select_is_contiguous(const H5S_t *space);
H5_DLL htri_t H5S_select_is_single(const H5S_t *space);
H5_DLL htri_t H5S_select_is_regular(const H5S_t *space);
diff --git a/src/H5Spublic.h b/src/H5Spublic.h
index 37d3866..721c4bf 100644
--- a/src/H5Spublic.h
+++ b/src/H5Spublic.h
@@ -25,7 +25,7 @@
/* Define atomic datatypes */
#define H5S_ALL (hid_t)0
-#define H5S_UNLIMITED ((hsize_t)(hssize_t)(-1))
+#define H5S_UNLIMITED HSIZE_UNDEF
/* Define user-level maximum number of dimensions */
#define H5S_MAX_RANK 32
diff --git a/src/H5Sselect.c b/src/H5Sselect.c
index b62186b..a703cc3 100644
--- a/src/H5Sselect.c
+++ b/src/H5Sselect.c
@@ -63,7 +63,9 @@ static herr_t H5S_select_iter_next_block(H5S_sel_iter_t *iter);
herr_t
H5S_select_offset(H5S_t *space, const hssize_t *offset)
{
- FUNC_ENTER_NOAPI_NOINIT_NOERR
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
/* Check args */
HDassert(space);
@@ -76,7 +78,14 @@ H5S_select_offset(H5S_t *space, const hssize_t *offset)
/* Indicate that the offset was changed */
space->select.offset_changed = TRUE;
- FUNC_LEAVE_NOAPI(SUCCEED)
+ /* If the selection is 'hyper', update the selection due to changed offset
+ */
+ if(H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS)
+ if(H5S__hyper_update_extent_offset(space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't update hyperslab")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* H5S_select_offset() */
@@ -258,7 +267,7 @@ H5S_select_serial_size(const H5S_t *space)
REVISION LOG
--------------------------------------------------------------------------*/
herr_t
-H5S_select_serialize(const H5S_t *space, uint8_t **p)
+H5S_select_serialize(const H5F_t *f, const H5S_t *space, uint8_t **p)
{
herr_t ret_value=SUCCEED; /* Return value */
@@ -268,7 +277,7 @@ H5S_select_serialize(const H5S_t *space, uint8_t **p)
HDassert(p);
/* Call the selection type's serialize function */
- ret_value=(*space->select.type->serialize)(space,p);
+ ret_value = (*space->select.type->serialize)(f, space, p);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_select_serialize() */
@@ -450,11 +459,13 @@ H5S_select_valid(const H5S_t *space)
REVISION LOG
--------------------------------------------------------------------------*/
herr_t
-H5S_select_deserialize (H5S_t **space, const uint8_t **p)
+H5S_select_deserialize(const H5F_t *f, H5S_t **space, const uint8_t **p)
{
H5S_t *tmp_space; /* Pointer to actual dataspace to use, either
*space or a newly allocated one */
uint32_t sel_type; /* Pointer to the selection type */
+ uint32_t version; /* Version number */
+ uint8_t flags = 0; /* Flags */
herr_t ret_value=FAIL; /* return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -472,8 +483,23 @@ H5S_select_deserialize (H5S_t **space, const uint8_t **p)
/* Decode selection type */
UINT32DECODE(*p, sel_type);
- /* Skip over the remainder of the header */
- *p += 12;
+ /* Decode version */
+ UINT32DECODE(*p, version);
+
+ if(version >= (uint32_t)2) {
+ /* Decode flags */
+ flags = *(*p)++;
+
+ /* Check for unknown flags */
+ if(flags & ~H5S_SELECT_FLAG_BITS)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTLOAD, FAIL, "unknown flag for selection")
+
+ /* Skip over the remainder of the header */
+ *p += 4;
+ } /* end if */
+ else
+ /* Skip over the remainder of the header */
+ *p += 8;
/* Decode and check or patch rank for point and hyperslab selections */
if((sel_type == H5S_SEL_POINTS) || (sel_type == H5S_SEL_HYPERSLABS)) {
@@ -494,19 +520,19 @@ H5S_select_deserialize (H5S_t **space, const uint8_t **p)
/* Make routine for selection type */
switch(sel_type) {
case H5S_SEL_POINTS: /* Sequence of points selected */
- ret_value = (*H5S_sel_point->deserialize)(tmp_space, p);
+ ret_value = (*H5S_sel_point->deserialize)(f, tmp_space, version, flags, p);
break;
case H5S_SEL_HYPERSLABS: /* Hyperslab selection defined */
- ret_value = (*H5S_sel_hyper->deserialize)(tmp_space, p);
+ ret_value = (*H5S_sel_hyper->deserialize)(f, tmp_space, version, flags, p);
break;
case H5S_SEL_ALL: /* Entire extent selected */
- ret_value = (*H5S_sel_all->deserialize)(tmp_space, p);
+ ret_value = (*H5S_sel_all->deserialize)(f, tmp_space, version, flags, p);
break;
case H5S_SEL_NONE: /* Nothing selected */
- ret_value = (*H5S_sel_none->deserialize)(tmp_space, p);
+ ret_value = (*H5S_sel_none->deserialize)(f, tmp_space, version, flags, p);
break;
default:
diff --git a/src/H5public.h b/src/H5public.h
index 7bacb3d..3b89879 100644
--- a/src/H5public.h
+++ b/src/H5public.h
@@ -176,6 +176,7 @@ H5_GCC_DIAG_ON(long-long)
#else
# error "nothing appropriate for hsize_t"
#endif
+#define HSIZE_UNDEF ((hsize_t)(hssize_t)(-1))
/*
* File addresses have their own types.