From f53cfbe9d66c87b414bb759b91d7c32eb28fa88f Mon Sep 17 00:00:00 2001 From: Neil Fortner Date: Thu, 16 Apr 2015 15:57:26 -0500 Subject: [svn-r26828] Implement support for unlimited selections (not supported by VDS code yet). Add tests for unlimited selections. Various other minor changes. Tested: ummon --- src/H5Fint.c | 127 +++++++++++++++ src/H5Fprivate.h | 6 + src/H5Olayout.c | 8 +- src/H5Pdcpl.c | 6 +- src/H5R.c | 4 +- src/H5S.c | 22 ++- src/H5Sall.c | 11 +- src/H5Shyper.c | 465 ++++++++++++++++++++++++++++++++++++++++++++++++------- src/H5Snone.c | 11 +- src/H5Spkg.h | 20 ++- src/H5Spoint.c | 11 +- src/H5Sprivate.h | 12 +- src/H5Spublic.h | 2 +- src/H5Sselect.c | 48 ++++-- src/H5public.h | 1 + test/tselect.c | 392 ++++++++++++++++++++++++++++++++++++++++++++++ test/vds.c | 12 +- 17 files changed, 1056 insertions(+), 102 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= 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; iselect.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; uextent.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; uextent.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; uextent.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; uextent.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; uextent.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. diff --git a/test/tselect.c b/test/tselect.c index b34d095..df67ff6 100644 --- a/test/tselect.c +++ b/test/tselect.c @@ -13230,6 +13230,395 @@ test_hyper_regular(void) /**************************************************************** ** +** test_hyper_unlim(): Tests unlimited hyperslab selections +** +****************************************************************/ +static void +test_hyper_unlim(void) +{ + hid_t sid; + hsize_t dims[3] = {4, 4, 7}; + hsize_t mdims[3] = {4, H5S_UNLIMITED, 7}; + hsize_t start[3] = {1, 2, 1}; + hsize_t stride[3] = {1, 1, 3}; + hsize_t count[3] = {1, 1, 2}; + hsize_t block[3] = {2, H5S_UNLIMITED, 2}; + hsize_t blocklist[12]; + hsize_t eblock1[6] = {1, 2, 1, 2, 3, 2}; + hsize_t eblock2[6] = {1, 2, 4, 2, 3, 5}; + hssize_t offset[3] = {0, -1, 0}; + hssize_t npoints; + hssize_t nblocks; + herr_t ret; + + /* Output message about test being performed */ + MESSAGE(6, ("Testing unlimited hyperslab selections\n")); + + /* Create dataspace */ + sid = H5Screate_simple(3, dims, mdims); + CHECK(sid, FAIL, "H5Screate_simple"); + + /* Select unlimited hyperslab */ + ret = H5Sselect_hyperslab(sid, H5S_SELECT_SET, start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* Check number of elements */ + npoints = H5Sget_select_npoints(sid); + CHECK(npoints, FAIL, "H5Sget_select_npoints"); + VERIFY(npoints, (hssize_t)16, "H5Sget_select_npoints"); + + /* Get blocklist */ + nblocks = H5Sget_select_hyper_nblocks(sid); + CHECK(nblocks, FAIL, "H5Sget_select_hyper_nblocks"); + VERIFY(nblocks, (hssize_t)2, "H5Sget_select_hyper_nblocks"); + ret = H5Sget_select_hyper_blocklist(sid, (hsize_t)0, (hsize_t)nblocks, blocklist); + CHECK(ret, FAIL, "H5Sget_select_hyper_blocklist"); + + /* Verify blocklist */ + if(HDmemcmp(blocklist, eblock1, sizeof(eblock1))) { + if(HDmemcmp(blocklist, eblock2, sizeof(eblock2))) + ERROR("H5Sget_select_hyper_blocklist"); + if(HDmemcmp(&blocklist[6], eblock1, sizeof(eblock1))) + ERROR("H5Sget_select_hyper_blocklist"); + } /* end if */ + else + if(HDmemcmp(&blocklist[6], eblock2, sizeof(eblock2))) + ERROR("H5Sget_select_hyper_blocklist"); + + /* Shrink dataspace */ + dims[1] = 3; + ret = H5Sset_extent_simple(sid, 3, dims, mdims); + CHECK(ret, FAIL, "H5Sset_extent_simple"); + + /* Check number of elements */ + npoints = H5Sget_select_npoints(sid); + CHECK(npoints, FAIL, "H5Sget_select_npoints"); + VERIFY(npoints, (hssize_t)8, "H5Sget_select_npoints"); + + /* Get blocklist */ + nblocks = H5Sget_select_hyper_nblocks(sid); + CHECK(nblocks, FAIL, "H5Sget_select_hyper_nblocks"); + VERIFY(nblocks, (hssize_t)2, "H5Sget_select_hyper_nblocks"); + ret = H5Sget_select_hyper_blocklist(sid, (hsize_t)0, (hsize_t)nblocks, blocklist); + CHECK(ret, FAIL, "H5Sget_select_hyper_blocklist"); + + /* Verify blocklist */ + eblock1[4] = 2; + eblock2[4] = 2; + if(HDmemcmp(blocklist, eblock1, sizeof(eblock1))) { + if(HDmemcmp(blocklist, eblock2, sizeof(eblock2))) + ERROR("H5Sget_select_hyper_blocklist"); + if(HDmemcmp(&blocklist[6], eblock1, sizeof(eblock1))) + ERROR("H5Sget_select_hyper_blocklist"); + } /* end if */ + else + if(HDmemcmp(&blocklist[6], eblock2, sizeof(eblock2))) + ERROR("H5Sget_select_hyper_blocklist"); + + /* Shrink dataspace */ + dims[1] = 2; + ret = H5Sset_extent_simple(sid, 3, dims, mdims); + CHECK(ret, FAIL, "H5Sset_extent_simple"); + + /* Check number of elements */ + npoints = H5Sget_select_npoints(sid); + CHECK(npoints, FAIL, "H5Sget_select_npoints"); + VERIFY(npoints, (hssize_t)0, "H5Sget_select_npoints"); + + /* Make sure there are no blocks */ + nblocks = H5Sget_select_hyper_nblocks(sid); + CHECK(nblocks, FAIL, "H5Sget_select_hyper_nblocks"); + VERIFY(nblocks, (hssize_t)0, "H5Sget_select_hyper_nblocks"); + + /* Shrink dataspace */ + dims[1] = 1; + ret = H5Sset_extent_simple(sid, 3, dims, mdims); + CHECK(ret, FAIL, "H5Sset_extent_simple"); + + /* Check number of elements */ + npoints = H5Sget_select_npoints(sid); + CHECK(npoints, FAIL, "H5Sget_select_npoints"); + VERIFY(npoints, (hssize_t)0, "H5Sget_select_npoints"); + + /* Make sure there are no blocks */ + nblocks = H5Sget_select_hyper_nblocks(sid); + CHECK(nblocks, FAIL, "H5Sget_select_hyper_nblocks"); + VERIFY(nblocks, (hssize_t)0, "H5Sget_select_hyper_nblocks"); + + /* Extend dataspace */ + dims[1] = 7; + ret = H5Sset_extent_simple(sid, 3, dims, mdims); + CHECK(ret, FAIL, "H5Sset_extent_simple"); + + /* Check number of elements */ + npoints = H5Sget_select_npoints(sid); + CHECK(npoints, FAIL, "H5Sget_select_npoints"); + VERIFY(npoints, (hssize_t)40, "H5Sget_select_npoints"); + + /* Get blocklist */ + nblocks = H5Sget_select_hyper_nblocks(sid); + CHECK(nblocks, FAIL, "H5Sget_select_hyper_nblocks"); + VERIFY(nblocks, (hssize_t)2, "H5Sget_select_hyper_nblocks"); + ret = H5Sget_select_hyper_blocklist(sid, (hsize_t)0, (hsize_t)nblocks, blocklist); + CHECK(ret, FAIL, "H5Sget_select_hyper_blocklist"); + + /* Verify blocklist */ + eblock1[4] = 6; + eblock2[4] = 6; + if(HDmemcmp(blocklist, eblock1, sizeof(eblock1))) { + if(HDmemcmp(blocklist, eblock2, sizeof(eblock2))) + ERROR("H5Sget_select_hyper_blocklist"); + if(HDmemcmp(&blocklist[6], eblock1, sizeof(eblock1))) + ERROR("H5Sget_select_hyper_blocklist"); + } /* end if */ + else + if(HDmemcmp(&blocklist[6], eblock2, sizeof(eblock2))) + ERROR("H5Sget_select_hyper_blocklist"); + +#if 0 //VDSINC + /* Set offset of selection */ + ret = H5Soffset_simple(sid, offset); + CHECK(ret, FAIL, "H5Soffset_simple"); + + /* Check number of elements */ + npoints = H5Sget_select_npoints(sid); + CHECK(npoints, FAIL, "H5Sget_select_npoints"); + VERIFY(npoints, (hssize_t)48, "H5Sget_select_npoints"); + + /* Get blocklist */ + nblocks = H5Sget_select_hyper_nblocks(sid); + CHECK(nblocks, FAIL, "H5Sget_select_hyper_nblocks"); + VERIFY(nblocks, (hssize_t)2, "H5Sget_select_hyper_nblocks"); + ret = H5Sget_select_hyper_blocklist(sid, (hsize_t)0, (hsize_t)nblocks, blocklist); + CHECK(ret, FAIL, "H5Sget_select_hyper_blocklist"); + + /* Verify blocklist */ + eblock1[1] = 1; + eblock1[4] = 6; + eblock2[1] = 1; + eblock2[4] = 6; + if(HDmemcmp(blocklist, eblock1, sizeof(eblock1))) { + if(HDmemcmp(blocklist, eblock2, sizeof(eblock2))) + ERROR("H5Sget_select_hyper_blocklist"); + if(HDmemcmp(&blocklist[6], eblock1, sizeof(eblock1))) + ERROR("H5Sget_select_hyper_blocklist"); + } /* end if */ + else + if(HDmemcmp(&blocklist[6], eblock2, sizeof(eblock2))) + ERROR("H5Sget_select_hyper_blocklist"); + + /* Reset offset of selection */ + ret = H5Soffset_simple(sid, NULL); + CHECK(ret, FAIL, "H5Soffset_simple"); +#endif + + /* + * Now try with multiple blocks in unlimited dimension + */ + stride[1] = 3; + stride[2] = 1; + count[1] = H5S_UNLIMITED; + count[2] = 1; + block[1] = 2; + + /* Select unlimited hyperslab */ + ret = H5Sselect_hyperslab(sid, H5S_SELECT_SET, start, stride, count, block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* Check number of elements */ + npoints = H5Sget_select_npoints(sid); + CHECK(npoints, FAIL, "H5Sget_select_npoints"); + VERIFY(npoints, (hssize_t)16, "H5Sget_select_npoints"); + + /* Get blocklist */ + nblocks = H5Sget_select_hyper_nblocks(sid); + CHECK(nblocks, FAIL, "H5Sget_select_hyper_nblocks"); + VERIFY(nblocks, (hssize_t)2, "H5Sget_select_hyper_nblocks"); + ret = H5Sget_select_hyper_blocklist(sid, (hsize_t)0, (hsize_t)nblocks, blocklist); + CHECK(ret, FAIL, "H5Sget_select_hyper_blocklist"); + + /* Verify blocklist */ + eblock1[1] = 2; + eblock1[4] = 3; + eblock2[1] = 5; + eblock2[2] = 1; + eblock2[4] = 6; + eblock2[5] = 2; + if(HDmemcmp(blocklist, eblock1, sizeof(eblock1))) { + if(HDmemcmp(blocklist, eblock2, sizeof(eblock2))) + ERROR("H5Sget_select_hyper_blocklist"); + if(HDmemcmp(&blocklist[6], eblock1, sizeof(eblock1))) + ERROR("H5Sget_select_hyper_blocklist"); + } /* end if */ + else + if(HDmemcmp(&blocklist[6], eblock2, sizeof(eblock2))) + ERROR("H5Sget_select_hyper_blocklist"); + +#if 0 //VDSINC + /* Shrink dataspace */ + dims[1] = 3; + ret = H5Sset_extent_simple(sid, 3, dims, mdims); + CHECK(ret, FAIL, "H5Sset_extent_simple"); + + /* Check number of elements */ + npoints = H5Sget_select_npoints(sid); + CHECK(npoints, FAIL, "H5Sget_select_npoints"); + VERIFY(npoints, (hssize_t)4, "H5Sget_select_npoints"); + + /* Get blocklist */ + nblocks = H5Sget_select_hyper_nblocks(sid); + CHECK(nblocks, FAIL, "H5Sget_select_hyper_nblocks"); + VERIFY(nblocks, (hssize_t)1, "H5Sget_select_hyper_nblocks"); + ret = H5Sget_select_hyper_blocklist(sid, (hsize_t)0, (hsize_t)nblocks, blocklist); + CHECK(ret, FAIL, "H5Sget_select_hyper_blocklist"); + + /* Verify blocklist */ + eblock1[4] = 2; + if(HDmemcmp(blocklist, eblock1, sizeof(eblock1))) + ERROR("H5Sget_select_hyper_blocklist"); +#endif //VDSINC + + /* Extend dataspace */ + dims[1] = 4; + ret = H5Sset_extent_simple(sid, 3, dims, mdims); + CHECK(ret, FAIL, "H5Sset_extent_simple"); + + /* Check number of elements */ + npoints = H5Sget_select_npoints(sid); + CHECK(npoints, FAIL, "H5Sget_select_npoints"); + VERIFY(npoints, (hssize_t)8, "H5Sget_select_npoints"); + + /* Get blocklist */ + nblocks = H5Sget_select_hyper_nblocks(sid); + CHECK(nblocks, FAIL, "H5Sget_select_hyper_nblocks"); + VERIFY(nblocks, (hssize_t)1, "H5Sget_select_hyper_nblocks"); + ret = H5Sget_select_hyper_blocklist(sid, (hsize_t)0, (hsize_t)nblocks, blocklist); + CHECK(ret, FAIL, "H5Sget_select_hyper_blocklist"); + + /* Verify blocklist */ + eblock1[4] = 3; + if(HDmemcmp(blocklist, eblock1, sizeof(eblock1))) + ERROR("H5Sget_select_hyper_blocklist"); + + /* Extend dataspace */ + dims[1] = 5; + ret = H5Sset_extent_simple(sid, 3, dims, mdims); + CHECK(ret, FAIL, "H5Sset_extent_simple"); + + /* Check number of elements */ + npoints = H5Sget_select_npoints(sid); + CHECK(npoints, FAIL, "H5Sget_select_npoints"); + VERIFY(npoints, (hssize_t)8, "H5Sget_select_npoints"); + + /* Get blocklist */ + nblocks = H5Sget_select_hyper_nblocks(sid); + CHECK(nblocks, FAIL, "H5Sget_select_hyper_nblocks"); + VERIFY(nblocks, (hssize_t)1, "H5Sget_select_hyper_nblocks"); + ret = H5Sget_select_hyper_blocklist(sid, (hsize_t)0, (hsize_t)nblocks, blocklist); + CHECK(ret, FAIL, "H5Sget_select_hyper_blocklist"); + + /* Verify blocklist */ + if(HDmemcmp(blocklist, eblock1, sizeof(eblock1))) + ERROR("H5Sget_select_hyper_blocklist"); + +#if 0 //VDSINC + /* Extend dataspace */ + dims[1] = 6; + ret = H5Sset_extent_simple(sid, 3, dims, mdims); + CHECK(ret, FAIL, "H5Sset_extent_simple"); + + /* Check number of elements */ + npoints = H5Sget_select_npoints(sid); + CHECK(npoints, FAIL, "H5Sget_select_npoints"); + VERIFY(npoints, (hssize_t)12, "H5Sget_select_npoints"); + + /* Get blocklist */ + nblocks = H5Sget_select_hyper_nblocks(sid); + CHECK(nblocks, FAIL, "H5Sget_select_hyper_nblocks"); + VERIFY(nblocks, (hssize_t)2, "H5Sget_select_hyper_nblocks"); + ret = H5Sget_select_hyper_blocklist(sid, (hsize_t)0, (hsize_t)nblocks, blocklist); + CHECK(ret, FAIL, "H5Sget_select_hyper_blocklist"); + + /* Verify blocklist */ + eblock2[4] = 5; + if(HDmemcmp(blocklist, eblock1, sizeof(eblock1))) { + if(HDmemcmp(blocklist, eblock2, sizeof(eblock2))) + ERROR("H5Sget_select_hyper_blocklist"); + if(HDmemcmp(&blocklist[6], eblock1, sizeof(eblock1))) + ERROR("H5Sget_select_hyper_blocklist"); + } /* end if */ + else + if(HDmemcmp(&blocklist[6], eblock2, sizeof(eblock2))) + ERROR("H5Sget_select_hyper_blocklist"); + + /* Set offset of selection */ + ret = H5Soffset_simple(sid, offset); + CHECK(ret, FAIL, "H5Soffset_simple"); + + /* Check number of elements */ + npoints = H5Sget_select_npoints(sid); + CHECK(npoints, FAIL, "H5Sget_select_npoints"); + VERIFY(npoints, (hssize_t)16, "H5Sget_select_npoints"); + + /* Get blocklist */ + nblocks = H5Sget_select_hyper_nblocks(sid); + CHECK(nblocks, FAIL, "H5Sget_select_hyper_nblocks"); + VERIFY(nblocks, (hssize_t)2, "H5Sget_select_hyper_nblocks"); + ret = H5Sget_select_hyper_blocklist(sid, (hsize_t)0, (hsize_t)nblocks, blocklist); + CHECK(ret, FAIL, "H5Sget_select_hyper_blocklist"); + + /* Verify blocklist */ + eblock1[1] = 1; + eblock1[4] = 2; + eblock2[1] = 4; + eblock2[4] = 5; + if(HDmemcmp(blocklist, eblock1, sizeof(eblock1))) { + if(HDmemcmp(blocklist, eblock2, sizeof(eblock2))) + ERROR("H5Sget_select_hyper_blocklist"); + if(HDmemcmp(&blocklist[6], eblock1, sizeof(eblock1))) + ERROR("H5Sget_select_hyper_blocklist"); + } /* end if */ + else + if(HDmemcmp(&blocklist[6], eblock2, sizeof(eblock2))) + ERROR("H5Sget_select_hyper_blocklist"); + + /* Set offset of selection */ + offset[1] = (hssize_t)3; + ret = H5Soffset_simple(sid, offset); + CHECK(ret, FAIL, "H5Soffset_simple"); + + /* Check number of elements */ + npoints = H5Sget_select_npoints(sid); + CHECK(npoints, FAIL, "H5Sget_select_npoints"); + VERIFY(npoints, (hssize_t)4, "H5Sget_select_npoints"); + + /* Get blocklist */ + nblocks = H5Sget_select_hyper_nblocks(sid); + CHECK(nblocks, FAIL, "H5Sget_select_hyper_nblocks"); + VERIFY(nblocks, (hssize_t)1, "H5Sget_select_hyper_nblocks"); + ret = H5Sget_select_hyper_blocklist(sid, (hsize_t)0, (hsize_t)nblocks, blocklist); + CHECK(ret, FAIL, "H5Sget_select_hyper_blocklist"); + + /* Verify blocklist */ + eblock1[1] = 5; + eblock1[4] = 5; + if(HDmemcmp(blocklist, eblock1, sizeof(eblock1))) + ERROR("H5Sget_select_hyper_blocklist"); + + /* Reset offset of selection */ + ret = H5Soffset_simple(sid, NULL); + CHECK(ret, FAIL, "H5Soffset_simple"); +#endif //VDSINC + + //VDSINC write test saving unlim selection to file as region reference + + /* Close the dataspace */ + ret = H5Sclose(sid); + CHECK(ret, FAIL, "H5Sclose"); +} /* end test_hyper_unlim() */ + +/**************************************************************** +** ** test_select(): Main H5S selection testing routine. ** ****************************************************************/ @@ -13392,6 +13781,9 @@ test_select(void) /* Test 'regular' hyperslab query routines */ test_hyper_regular(); + /* Test unlimited hyperslab selections */ + test_hyper_unlim(); + } /* test_select() */ diff --git a/test/vds.c b/test/vds.c index abb52fc..5092d1e 100644 --- a/test/vds.c +++ b/test/vds.c @@ -416,11 +416,11 @@ test_api(test_api_config_t config, hid_t fapl) const char *src_dset[4] = {"src_dset1....", "src_dset2.....", "src_dset3......", "src_dset4......."}; /* Source dataset names (different lengths) */ char tmp_filename[32]; char tmp_dsetname[32]; - hsize_t dims[4] = {10, 20, 0, 0}; /* Data space current size */ - hsize_t start[4]; /* Hyperslab start */ - hsize_t stride[4]; /* Hyperslab stride */ - hsize_t count[4]; /* Hyperslab count */ - hsize_t block[4]; /* Hyperslab block */ + hsize_t dims[2] = {10, 20}; /* Data space current size */ + hsize_t start[2]; /* Hyperslab start */ + hsize_t stride[2]; /* Hyperslab stride */ + hsize_t count[2]; /* Hyperslab count */ + hsize_t block[2]; /* Hyperslab block */ hsize_t coord[10]; /* Point selection array */ size_t size_out; unsigned i; @@ -2457,7 +2457,7 @@ test_basic_io(unsigned config, hid_t fapl) if((srcdset[0] = H5Dopen2(srcfile[0], "src_dset1", H5P_DEFAULT)) < 0) TEST_ERROR } /* end if */ -# + /* Read data directly from source dataset */ /* Select hyperslab in memory space */ start[0] = 0; -- cgit v0.12