diff options
author | Vailin Choi <vchoi@jam.ad.hdfgroup.org> | 2017-11-28 17:11:27 (GMT) |
---|---|---|
committer | Vailin Choi <vchoi@jam.ad.hdfgroup.org> | 2017-11-28 17:11:27 (GMT) |
commit | 3d84163ad37960ff1ecdd5782af88b442832fd99 (patch) | |
tree | 99d6ea66069bef7d37ca3abbf823e731f374b3c3 /src/H5Spoint.c | |
parent | e1dd55be8538ee0ebd1c46be3df4b306a3ac6f3f (diff) | |
download | hdf5-3d84163ad37960ff1ecdd5782af88b442832fd99.zip hdf5-3d84163ad37960ff1ecdd5782af88b442832fd99.tar.gz hdf5-3d84163ad37960ff1ecdd5782af88b442832fd99.tar.bz2 |
Fix for HDFFV-9947 H5Sencode
Modifications to fix H5Sencode bug when num points selected is > 2^32.
Diffstat (limited to 'src/H5Spoint.c')
-rw-r--r-- | src/H5Spoint.c | 179 |
1 files changed, 158 insertions, 21 deletions
diff --git a/src/H5Spoint.c b/src/H5Spoint.c index 251a063..fb0a01e 100644 --- a/src/H5Spoint.c +++ b/src/H5Spoint.c @@ -38,8 +38,8 @@ static herr_t H5S_point_get_seq_list(const H5S_t *space, unsigned flags, size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len); 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 hssize_t H5S_point_serial_size(const H5S_t *space, H5F_t *f); +static herr_t H5S_point_serialize(const H5S_t *space, uint8_t **p, H5F_t *f); static herr_t H5S_point_deserialize(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); @@ -752,6 +752,93 @@ done: FUNC_LEAVE_API(ret_value) } /* H5Sget_select_elem_npoints() */ +/*-------------------------------------------------------------------------- + NAME + H5S_point_set_version + PURPOSE + Determine the version to use for encoding points selection info + USAGE + hssize_t H5S_point_set_version(space, bounds_end, f, version) + const H5S_t *space; IN: The dataspace + hsize_t bounds_end: IN: The selection high bounds + H5F_t *f: IN: The file pointer + uint32_t *version: OUT: The version to use for encoding + RETURNS + The version to use + DESCRIPTION + Determine the version to use for encoding points selection info: + For 1.10, return 1 + + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5S_point_set_version(const H5S_t *space, hsize_t bounds_end[], H5F_t *f, uint32_t *version) +{ + hbool_t exceed = FALSE; + unsigned u; + herr_t ret_value = SUCCEED; /* return value */ + + FUNC_ENTER_NOAPI_NOINIT + + *version = H5S_POINT_VERSION_1; + + /* Determine whether the number of points or the high bounds in the selection exceed (2^32 - 1) */ + for(u = 0; u < space->extent.rank; u++) + if(bounds_end[u] > H5S_UINT32_MAX) { + exceed = TRUE; + break; + } + + if(space->select.num_elem > H5S_UINT32_MAX) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "The number of points in point selection exceeds 2^32") + else if(exceed) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "The end of bounding box in point selection exceeds 2^32") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S_point_set_version() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S_point_set_info_size + PURPOSE + Determine the size of point info to use for encoding selection info + USAGE + hssize_t H5S_point_set_info_size(space, bounds_end, version, point_size) + const H5S_t *space: IN: Dataspace ID of selection to query + hsize_t bounds_end[]: IN: The selection high bounds + uint32_t version: IN: The version used for encoding + uint8_t *point_size: OUT: The size of point info + RETURNS + The size of the points selection info + DESCRIPTION + Determine the size for encoding points selection info: + For 1.10, return 4 + + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5S_point_set_info_size(const H5S_t *space, hsize_t H5_ATTR_UNUSED bounds_end[], uint32_t H5_ATTR_UNUSED version, uint8_t H5_ATTR_UNUSED *point_size) +{ + hsize_t max_size = 0; + unsigned u; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + HDassert(version == H5S_POINT_VERSION_1); + + *point_size = H5S_INFO_SIZE_4; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5S_point_set_info_size() */ + /*-------------------------------------------------------------------------- NAME @@ -760,8 +847,9 @@ done: Determine the number of bytes needed to store the serialized point selection information. USAGE - hssize_t H5S_point_serial_size(space) + hssize_t H5S_point_serial_size(space, f) H5S_t *space; IN: Dataspace pointer to query + H5F_t *f; IN: File pointer RETURNS The number of bytes required on success, negative on an error. DESCRIPTION @@ -773,29 +861,54 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static hssize_t -H5S_point_serial_size (const H5S_t *space) +H5S_point_serial_size (const H5S_t *space, H5F_t *f) { H5S_pnt_node_t *curr; /* Point information nodes */ + hsize_t bounds_start[H5S_MAX_RANK]; + hsize_t bounds_end[H5S_MAX_RANK]; + uint32_t version; /* Version number */ + uint8_t point_size; /* Size of point info */ hssize_t ret_value = -1; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_NOAPI_NOINIT HDassert(space); - /* Basic number of bytes required to serialize point selection: + /* Get bounding box for the selection */ + HDmemset(bounds_end, 0, sizeof(bounds_end)); + if(H5S_point_bounds(space, bounds_start, bounds_end) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get selection bounds") + + /* Determine the version */ + if(H5S_point_set_version(space, bounds_end, f, &version) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't determine hyper version") + + /* Determine the size of point info */ + if(H5S_point_set_info_size(space, bounds_end, version, &point_size) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't determine hyper version") + + HDassert(version == H5S_POINT_VERSION_1); + HDassert(point_size == H5S_INFO_SIZE_4); + + /* Basic number of bytes required to serialize point selection: */ + /* * <type (4 bytes)> + <version (4 bytes)> + <padding (4 bytes)> + - * <length (4 bytes)> + <rank (4 bytes)> + <# of points (4 bytes)> = 24 bytes + * <length (4 bytes)> + <rank (4 bytes)> */ - ret_value=24; + ret_value=20; + + /* <num points (depend on point_size)> */ + ret_value += point_size; /* Count points in selection */ curr=space->select.sel_info.pnt_lst->head; while(curr!=NULL) { - /* Add 4 bytes times the rank for each element selected */ - ret_value+=4*space->extent.rank; - curr=curr->next; + /* Add <point_size> bytes times the rank for each element selected */ + ret_value += point_size * space->extent.rank; + curr = curr->next; } /* end while */ +done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5S_point_serial_size() */ @@ -806,11 +919,12 @@ H5S_point_serial_size (const H5S_t *space) PURPOSE Serialize the current selection into a user-provided buffer. USAGE - herr_t H5S_point_serialize(space, p) + herr_t H5S_point_serialize(space, p, f) const H5S_t *space; IN: Dataspace with selection to serialize uint8_t **p; OUT: Pointer to buffer to put serialized selection. Will be advanced to end of serialized selection. + H5F_t *f; IN: File pointer RETURNS Non-negative on success/Negative on failure DESCRIPTION @@ -822,41 +936,63 @@ 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 H5S_t *space, uint8_t **p, H5F_t *f) { H5S_pnt_node_t *curr; /* Point information nodes */ uint8_t *pp = (*p); /* Local pointer for decoding */ uint8_t *lenp; /* pointer to length location for later storage */ uint32_t len=0; /* number of bytes used */ unsigned u; /* local counting variable */ + uint32_t version; /* Version number */ + uint8_t point_size; /* Size of point info */ + hsize_t bounds_start[H5S_MAX_RANK]; + hsize_t bounds_end[H5S_MAX_RANK]; + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_NOAPI_NOINIT /* Check args */ HDassert(space); HDassert(p); HDassert(pp); + /* Get bounding box for the selection */ + HDmemset(bounds_end, 0, sizeof(bounds_end)); + if(H5S_point_bounds(space, bounds_start, bounds_end) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get selection bounds") + + /* Determine the version */ + if(H5S_point_set_version(space, bounds_end, f, &version) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't determine hyper version") + + /* Determine the size of point info */ + if(H5S_point_set_info_size(space, bounds_end, version, &point_size) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't determine hyper version") + + HDassert(point_size == H5S_INFO_SIZE_4); + HDassert(version == H5S_POINT_VERSION_1); + /* Store the preamble information */ UINT32ENCODE(pp, (uint32_t)H5S_GET_SELECT_TYPE(space)); /* Store the type of selection */ - UINT32ENCODE(pp, (uint32_t)1); /* Store the version number */ + UINT32ENCODE(pp, version); /* Store the version number */ + UINT32ENCODE(pp, (uint32_t)0); /* Store the un-used padding */ - lenp = pp; /* Keep the pointer to the length location for later */ - pp += 4; /* Skip over space for length */ + lenp = pp; /* Keep the pointer to the length location for later */ + pp += 4; /* Skip over space for length */ + len += 8; /* Add in advance # of bytes for num of dimensions and num elements */ /* Encode number of dimensions */ UINT32ENCODE(pp, (uint32_t)space->extent.rank); - len+=4; + /* Encode number of elements */ UINT32ENCODE(pp, (uint32_t)space->select.num_elem); - len+=4; /* Encode each point in selection */ curr=space->select.sel_info.pnt_lst->head; while(curr!=NULL) { /* Add 4 bytes times the rank for each element selected */ - len+=4*space->extent.rank; + len += 4 * space->extent.rank; /* Encode each point */ for(u=0; u<space->extent.rank; u++) @@ -871,7 +1007,8 @@ H5S_point_serialize (const H5S_t *space, uint8_t **p) /* Update encoding pointer */ *p = pp; - FUNC_LEAVE_NOAPI(SUCCEED) +done: + FUNC_LEAVE_NOAPI(ret_value) } /* H5S_point_serialize() */ |