diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/H5Dmpio.c | 3 | ||||
-rw-r--r-- | src/H5Dvirtual.c | 4 | ||||
-rw-r--r-- | src/H5P.c | 19 | ||||
-rw-r--r-- | src/H5Pdeprec.c | 48 | ||||
-rw-r--r-- | src/H5Ppublic.h | 3 | ||||
-rw-r--r-- | src/H5Rint.c | 3 | ||||
-rw-r--r-- | src/H5S.c | 22 | ||||
-rw-r--r-- | src/H5Sall.c | 2 | ||||
-rw-r--r-- | src/H5Sdeprec.c | 121 | ||||
-rw-r--r-- | src/H5Shyper.c | 880 | ||||
-rw-r--r-- | src/H5Snone.c | 2 | ||||
-rw-r--r-- | src/H5Spkg.h | 31 | ||||
-rw-r--r-- | src/H5Spoint.c | 334 | ||||
-rw-r--r-- | src/H5Spublic.h | 12 | ||||
-rw-r--r-- | src/H5vers.txt | 2 | ||||
-rw-r--r-- | src/Makefile.am | 2 |
16 files changed, 1215 insertions, 273 deletions
diff --git a/src/H5Dmpio.c b/src/H5Dmpio.c index d23cb63..7019362 100644 --- a/src/H5Dmpio.c +++ b/src/H5Dmpio.c @@ -2742,6 +2742,9 @@ H5D__chunk_redistribute_shared_chunks(const H5D_io_info_t *io_info, const H5D_ty if ((mpi_size = H5F_mpi_get_size(io_info->dset->oloc.file)) < 0) HGOTO_ERROR(H5E_IO, H5E_MPI, FAIL, "unable to obtain mpi size") + /* Set to latest format for encoding dataspace */ + H5CX_set_libver_bounds(NULL); + if (*local_chunk_array_num_entries) if (NULL == (send_requests = (MPI_Request *) H5MM_malloc(*local_chunk_array_num_entries * sizeof(MPI_Request)))) HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "couldn't allocate send requests buffer") diff --git a/src/H5Dvirtual.c b/src/H5Dvirtual.c index 6c0cfba..d38df1b 100644 --- a/src/H5Dvirtual.c +++ b/src/H5Dvirtual.c @@ -430,6 +430,10 @@ H5D__virtual_store_layout(H5F_t *f, H5O_layout_t *layout) /* Create block if # of used entries > 0 */ if(layout->storage.u.virt.list_nused > 0) { + + /* Set the low/high bounds according to 'f' for the API context */ + H5CX_set_libver_bounds(f); + /* Allocate array for caching results of strlen */ if(NULL == (str_size = (size_t *)H5MM_malloc(2 * layout->storage.u.virt.list_nused * sizeof(size_t)))) HGOTO_ERROR(H5E_OHDR, H5E_RESOURCE, FAIL, "unable to allocate string length array") @@ -817,14 +817,17 @@ done: /*-------------------------------------------------------------------------- NAME - H5Pencode + H5Pencode2 PURPOSE - Routine to convert the property values in a property list into a binary buffer + Routine to convert the property values in a property list into a binary buffer. + The encoding of property values will be done according to the file format + setting in fapl_id. USAGE - herr_t H5Pencode(plist_id, buf, nalloc) + herr_t H5Pencode(plist_id, buf, nalloc, fapl_id) hid_t plist_id; IN: Identifier to property list to encode void *buf: OUT: buffer to gold the encoded plist size_t *nalloc; IN/OUT: size of buffer needed to encode plist + hid_t fapl_id; IN: File access property list ID RETURNS Returns non-negative on success, negative on failure. DESCRIPTION @@ -837,25 +840,29 @@ done: REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5Pencode(hid_t plist_id, void *buf, size_t *nalloc) +H5Pencode2(hid_t plist_id, void *buf, size_t *nalloc, hid_t fapl_id) { H5P_genplist_t *plist; /* Property list to query */ herr_t ret_value = SUCCEED; /* return value */ FUNC_ENTER_API(FAIL) - H5TRACE3("e", "i*x*z", plist_id, buf, nalloc); + H5TRACE4("e", "i*x*zi", plist_id, buf, nalloc, fapl_id); /* Check arguments. */ if(NULL == (plist = (H5P_genplist_t *)H5I_object_verify(plist_id, H5I_GENPROP_LST))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list"); + /* Verify access property list and set up collective metadata if appropriate */ + if(H5CX_set_apl(&fapl_id, H5P_CLS_FACC, H5I_INVALID_HID, TRUE) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info") + /* Call the internal encode routine */ if((ret_value = H5P__encode(plist, TRUE, buf, nalloc)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTENCODE, FAIL, "unable to encode property list"); done: FUNC_LEAVE_API(ret_value) -} /* H5Pencode() */ +} /* H5Pencode2() */ /*-------------------------------------------------------------------------- diff --git a/src/H5Pdeprec.c b/src/H5Pdeprec.c index 4a63b36..f6c2a3c 100644 --- a/src/H5Pdeprec.c +++ b/src/H5Pdeprec.c @@ -486,6 +486,54 @@ done: FUNC_LEAVE_API(ret_value) } /* end H5Pget_version() */ + +/*-------------------------------------------------------------------------- + NAME + H5Pencode1 + PURPOSE + Routine to convert the property values in a property list into a binary buffer + USAGE + herr_t H5Pencode1(plist_id, buf, nalloc) + hid_t plist_id; IN: Identifier to property list to encode + void *buf: OUT: buffer to gold the encoded plist + size_t *nalloc; IN/OUT: size of buffer needed to encode plist + RETURNS + Returns non-negative on success, negative on failure. + DESCRIPTION + Encodes a property list into a binary buffer. If the buffer is NULL, then + the call will set the size needed to encode the plist in nalloc. Otherwise + the routine will encode the plist in buf. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5Pencode1(hid_t plist_id, void *buf, size_t *nalloc) +{ + H5P_genplist_t *plist; /* Property list to query */ + hid_t temp_fapl_id = H5P_DEFAULT; + herr_t ret_value = SUCCEED; /* return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "i*x*z", plist_id, buf, nalloc); + + /* Check arguments. */ + if(NULL == (plist = (H5P_genplist_t *)H5I_object_verify(plist_id, H5I_GENPROP_LST))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list"); + + /* Verify access property list and set up collective metadata if appropriate */ + if(H5CX_set_apl(&temp_fapl_id, H5P_CLS_FACC, H5I_INVALID_HID, TRUE) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info") + + /* Call the internal encode routine */ + if((ret_value = H5P__encode(plist, TRUE, buf, nalloc)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTENCODE, FAIL, "unable to encode property list"); + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Pencode1() */ + /*------------------------------------------------------------------------- * Function: H5Pset_file_space * diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h index 078fe74..90e6618 100644 --- a/src/H5Ppublic.h +++ b/src/H5Ppublic.h @@ -236,7 +236,7 @@ H5_DLL herr_t H5Pinsert2(hid_t plist_id, const char *name, size_t size, H5P_prp_compare_func_t prp_cmp, H5P_prp_close_func_t prp_close); H5_DLL herr_t H5Pset(hid_t plist_id, const char *name, const void *value); H5_DLL htri_t H5Pexist(hid_t plist_id, const char *name); -H5_DLL herr_t H5Pencode(hid_t plist_id, void *buf, size_t *nalloc); +H5_DLL herr_t H5Pencode2(hid_t plist_id, void *buf, size_t *nalloc, hid_t fapl_id); H5_DLL hid_t H5Pdecode(const void *buf); H5_DLL herr_t H5Pget_size(hid_t id, const char *name, size_t *size); H5_DLL herr_t H5Pget_nprops(hid_t id, size_t *nprops); @@ -536,6 +536,7 @@ H5_DLL herr_t H5Pinsert1(hid_t plist_id, const char *name, size_t size, void *value, H5P_prp_set_func_t prp_set, H5P_prp_get_func_t prp_get, H5P_prp_delete_func_t prp_delete, H5P_prp_copy_func_t prp_copy, H5P_prp_close_func_t prp_close); +H5_DLL herr_t H5Pencode1(hid_t plist_id, void *buf, size_t *nalloc); H5_DLL H5Z_filter_t H5Pget_filter1(hid_t plist_id, unsigned filter, unsigned int *flags/*out*/, size_t *cd_nelmts/*out*/, unsigned cd_values[]/*out*/, size_t namelen, char name[]); diff --git a/src/H5Rint.c b/src/H5Rint.c index a4f76ce..9098a03 100644 --- a/src/H5Rint.c +++ b/src/H5Rint.c @@ -215,6 +215,9 @@ H5R__create(void *_ref, H5G_loc_t *loc, const char *name, H5R_type_t ref_type, H obj_loc.path = &path; H5G_loc_reset(&obj_loc); + /* Set the FAPL for the API context */ + H5CX_set_libver_bounds(loc->oloc->file); + /* Find the object */ if(H5G_loc_find(loc, name, &obj_loc) < 0) HGOTO_ERROR(H5E_REFERENCE, H5E_NOTFOUND, FAIL, "object not found") @@ -23,6 +23,7 @@ /***********/ #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ +#include "H5CXprivate.h" /* API Contexts */ #include "H5Fprivate.h" /* Files */ #include "H5FLprivate.h" /* Free lists */ #include "H5Iprivate.h" /* IDs */ @@ -1487,13 +1488,15 @@ done: /*------------------------------------------------------------------------- - * Function: H5Sencode + * Function: H5Sencode2 * * Purpose: Given a dataspace ID, converts the object description * (including selection) into binary in a buffer. + * The selection will be encoded according to the file + * format setting in fapl. * * Return: Success: non-negative - * Failure: negative + * Failure: negative * * Programmer: Raymond Lu * slu@ncsa.uiuc.edu @@ -1502,24 +1505,29 @@ done: *------------------------------------------------------------------------- */ herr_t -H5Sencode(hid_t obj_id, void *buf, size_t *nalloc) +H5Sencode2(hid_t obj_id, void *buf, size_t *nalloc, hid_t fapl_id) { H5S_t *dspace; herr_t ret_value=SUCCEED; FUNC_ENTER_API(FAIL) - H5TRACE3("e", "i*x*z", obj_id, buf, nalloc); + H5TRACE4("e", "i*x*zi", obj_id, buf, nalloc, fapl_id); /* Check argument and retrieve object */ if(NULL == (dspace = (H5S_t *)H5I_object_verify(obj_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") + + /* Verify access property list and set up collective metadata if appropriate */ + if(H5CX_set_apl(&fapl_id, H5P_CLS_FACC, H5I_INVALID_HID, TRUE) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info") + if(H5S_encode(dspace, (unsigned char **)&buf, nalloc) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTENCODE, FAIL, "can't encode dataspace") + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTENCODE, FAIL, "can't encode dataspace") done: FUNC_LEAVE_API(ret_value) -} /* end H5Sencode() */ +} /* H5Sencode2() */ /*------------------------------------------------------------------------- diff --git a/src/H5Sall.c b/src/H5Sall.c index 9823d36..7aa9644 100644 --- a/src/H5Sall.c +++ b/src/H5Sall.c @@ -629,7 +629,7 @@ H5S__all_serialize(const H5S_t *space, uint8_t **p) /* 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, (uint32_t)H5S_ALL_VERSION_1); /* Store the version number */ UINT32ENCODE(pp, (uint32_t)0); /* Store the un-used padding */ UINT32ENCODE(pp, (uint32_t)0); /* Store the additional information length */ diff --git a/src/H5Sdeprec.c b/src/H5Sdeprec.c new file mode 100644 index 0000000..e4ec1b0 --- /dev/null +++ b/src/H5Sdeprec.c @@ -0,0 +1,121 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5Sdeprec.c + * + * Purpose: Deprecated functions from the H5S interface. These + * functions are here for compatibility purposes and may be + * removed in the future. Applications should switch to the + * newer APIs. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#include "H5Smodule.h" /* This source code file is part of the H5S module */ + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5CXprivate.h" /* API Contexts */ +#include "H5Spkg.h" /* Dataspaces */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Iprivate.h" /* IDs */ + + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + +#ifndef H5_NO_DEPRECATED_SYMBOLS + +/*------------------------------------------------------------------------- + * Function: H5Sencode1 + * + * Purpose: Given a dataspace ID, converts the object description + * (including selection) into binary in a buffer. + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Raymond Lu + * slu@ncsa.uiuc.edu + * July 14, 2004 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Sencode1(hid_t obj_id, void *buf, size_t *nalloc) +{ + H5S_t *dspace; + hid_t temp_fapl_id = H5P_DEFAULT; + herr_t ret_value=SUCCEED; + + FUNC_ENTER_API(FAIL) + H5TRACE3("e", "i*x*z", obj_id, buf, nalloc); + + /* Check argument and retrieve object */ + if (NULL == (dspace = (H5S_t *)H5I_object_verify(obj_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") + + /* Verify access property list and set up collective metadata if appropriate */ + if(H5CX_set_apl(&temp_fapl_id, H5P_CLS_FACC, H5I_INVALID_HID, TRUE) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info") + + /* Use (earliest, latest) i.e. not latest format */ + if(H5S_encode(dspace, (unsigned char **)&buf, nalloc)<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTENCODE, FAIL, "can't encode dataspace") + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Sencode1() */ +#endif /* H5_NO_DEPRECATED_SYMBOLS */ + diff --git a/src/H5Shyper.c b/src/H5Shyper.c index 6d42ec1..a6494d9 100644 --- a/src/H5Shyper.c +++ b/src/H5Shyper.c @@ -28,13 +28,14 @@ /***********/ /* Headers */ /***********/ -#include "H5private.h" /* Generic Functions */ +#include "H5private.h" /* Generic Functions */ +#include "H5CXprivate.h" /* API Contexts */ #include "H5Eprivate.h" /* Error handling */ #include "H5FLprivate.h" /* Free Lists */ #include "H5Iprivate.h" /* ID Functions */ -#include "H5MMprivate.h" /* Memory management */ -#include "H5Spkg.h" /* Dataspace functions */ -#include "H5VMprivate.h" /* Vector functions */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Spkg.h" /* Dataspace functions */ +#include "H5VMprivate.h" /* Vector functions */ /****************/ @@ -157,6 +158,13 @@ const H5S_select_class_t H5S_sel_hyper[1] = {{ H5S__hyper_iter_init, }}; +/* Format version bounds for dataspace hyperslab selection */ +const unsigned H5O_sds_hyper_ver_bounds[] = { + H5S_HYPER_VERSION_1, /* H5F_LIBVER_EARLIEST */ + H5S_HYPER_VERSION_1, /* H5F_LIBVER_V18 */ + H5S_HYPER_VERSION_2, /* H5F_LIBVER_V110 */ + H5S_HYPER_VERSION_3 /* H5F_LIBVER_LATEST */ +}; /*******************/ /* Local Variables */ @@ -3204,8 +3212,9 @@ H5S__hyper_span_nblocks(const H5S_hyper_span_info_t *spans) PURPOSE Get the number of hyperslab blocks in current hyperslab selection USAGE - hsize_t H5S__get_select_hyper_nblocks(space) + hsize_t H5S__get_select_hyper_nblocks(space, app_ref) H5S_t *space; IN: Dataspace ptr of selection to query + hbool_t app_ref; IN: Whether this is an appl. ref. call RETURNS The number of hyperslab blocks in selection on success, negative on failure DESCRIPTION @@ -3216,7 +3225,7 @@ H5S__hyper_span_nblocks(const H5S_hyper_span_info_t *spans) REVISION LOG --------------------------------------------------------------------------*/ static hsize_t -H5S__get_select_hyper_nblocks(const H5S_t *space) +H5S__get_select_hyper_nblocks(const H5S_t *space, hbool_t app_ref) { hsize_t ret_value = 0; /* Return value */ @@ -3231,7 +3240,8 @@ H5S__get_select_hyper_nblocks(const H5S_t *space) /* 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; + ret_value *= (app_ref ? space->select.sel_info.hslab->app_diminfo[u].count : + space->select.sel_info.hslab->opt_diminfo[u].count); } /* end if */ else ret_value = H5S__hyper_span_nblocks(space->select.sel_info.hslab->span_lst); @@ -3274,7 +3284,7 @@ H5Sget_select_hyper_nblocks(hid_t spaceid) if(space->select.sel_info.hslab->unlim_dim >= 0) HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot get number of blocks for unlimited selection") - ret_value = (hssize_t)H5S__get_select_hyper_nblocks(space); + ret_value = (hssize_t)H5S__get_select_hyper_nblocks(space, TRUE); done: FUNC_LEAVE_API(ret_value) @@ -3283,6 +3293,210 @@ done: /*-------------------------------------------------------------------------- NAME + H5S__hyper_get_enc_size_real + PURPOSE + Determine the size to encode the hyperslab selection info + USAGE + hssize_t H5S__hyper_get_enc_size_real(max_size, enc_size) + hsize_t max_size: IN: The maximum size of the hyperslab selection info + unint8_t *enc_size: OUT:The encoding size + RETURNS + The size to encode hyperslab selection info + DESCRIPTION + Determine the size by comparing "max_size" with (2^32 - 1) and (2^16 - 1). + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static uint8_t +H5S__hyper_get_enc_size_real(hsize_t max_size) +{ + uint8_t ret_value = H5S_SELECT_INFO_ENC_SIZE_2; + + FUNC_ENTER_STATIC_NOERR + + if(max_size > H5S_UINT32_MAX) + ret_value = H5S_SELECT_INFO_ENC_SIZE_8; + else if(max_size > H5S_UINT16_MAX) + ret_value = H5S_SELECT_INFO_ENC_SIZE_4; + else + ret_value = H5S_SELECT_INFO_ENC_SIZE_2; + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S__hyper_get_enc_size_real() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S__hyper_get_version_enc_size + PURPOSE + Determine the version and encoded size to use for encoding hyperslab selection info + USAGE + hssize_t H5S__hyper_get_version_enc_size(space, block_count, version, enc_size) + const H5S_t *space: IN: The dataspace + hsize_t block_count: IN: The number of blocks in the selection + uint32_t *version: OUT: The version to use for encoding + uint8_t *enc_size: OUT: The encoded size to use + + RETURNS + The version and the size to encode hyperslab selection info + DESCRIPTION + Determine the version to use for encoding hyperslab selection info based + on the following: + (1) the file format setting in fapl + (2) whether the number of blocks or selection high bounds exceeds H5S_UINT32_MAX or not + + Determine the encoded size based on version: + For version 3, the encoded size is determined according to: + (a) regular hyperslab + (1) The maximum needed to store start/stride/count/block + (2) Special handling for count/block: need to provide room for H5S_UNLIMITED + (b) irregular hyperslab + The maximum size needed to store: + (1) the number of blocks + (2) the selection high bounds + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5S__hyper_get_version_enc_size(const H5S_t *space, hsize_t block_count, uint32_t *version, uint8_t *enc_size) +{ + hsize_t bounds_start[H5S_MAX_RANK]; /* Starting coordinate of bounding box */ + hsize_t bounds_end[H5S_MAX_RANK]; /* Opposite coordinate of bounding box */ + hbool_t count_up_version = FALSE; /* Whether number of blocks exceed H5S_UINT32_MAX */ + hbool_t bound_up_version = FALSE; /* Whether high bounds exceed H5S_UINT32_MAX */ + H5F_libver_t low_bound; /* The 'low' bound of library format versions */ + H5F_libver_t high_bound; /* The 'high' bound of library format versions */ + htri_t is_regular; /* A regular hyperslab or not */ + uint32_t tmp_version; /* Local temporay version */ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Get bounding box for the selection */ + HDmemset(bounds_end, 0, sizeof(bounds_end)); + + if(space->select.sel_info.hslab->unlim_dim < 0) { /* ! H5S_UNLIMITED */ + /* Get bounding box for the selection */ + if(H5S__hyper_bounds(space, bounds_start, bounds_end) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get selection bounds") + } + + /* Determine whether the number of blocks or the high bounds in the selection exceed (2^32 - 1) */ + if(block_count > H5S_UINT32_MAX) + count_up_version = TRUE; + else { + for(u = 0; u < space->extent.rank; u++) + if(bounds_end[u] > H5S_UINT32_MAX) { + bound_up_version = TRUE; + break; + } + } + + /* Get the file's low_bound and high_bound */ + if(H5CX_get_libver_bounds(&low_bound, &high_bound) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get low/high bounds from API context") + + /* Determine regular hyperslab */ + is_regular = H5S__hyper_is_regular(space); + + if(low_bound >= H5F_LIBVER_V112 || space->select.sel_info.hslab->unlim_dim >= 0) + tmp_version = MAX(H5S_HYPER_VERSION_2, H5O_sds_hyper_ver_bounds[low_bound]); + + else { + if(count_up_version || bound_up_version) + tmp_version = is_regular ? H5S_HYPER_VERSION_2 : H5S_HYPER_VERSION_3; + else + tmp_version = (is_regular && block_count >= 4) ? H5O_sds_hyper_ver_bounds[low_bound] : H5S_HYPER_VERSION_1; + + } + + /* Version bounds check */ + if(tmp_version > H5O_sds_hyper_ver_bounds[high_bound]) { + /* Fail for irregular hyperslab if exceeds 32 bits */ + if(count_up_version) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "The number of blocks in hyperslab selection exceeds 2^32") + else if(bound_up_version) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "The end of bounding box in hyperslab selection exceeds 2^32") + else + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "Dataspace hyperslab selection version out of bounds") + } + + /* Set the message version */ + *version = tmp_version; + + /* Determine the encoded size based on version */ + switch(tmp_version) { + case H5S_HYPER_VERSION_1: + *enc_size = H5S_SELECT_INFO_ENC_SIZE_4; + break; + + case H5S_HYPER_VERSION_2: + *enc_size = H5S_SELECT_INFO_ENC_SIZE_8; + break; + + case H5S_HYPER_VERSION_3: + if(is_regular) { + uint8_t enc1, enc2; + hsize_t max1 = 0; + hsize_t max2 = 0; + + /* Find max for count[] and block[] */ + for(u = 0; u < space->extent.rank; u++) { + if(space->select.sel_info.hslab->opt_diminfo[u].count != H5S_UNLIMITED && + space->select.sel_info.hslab->opt_diminfo[u].count > max1) + max1 = space->select.sel_info.hslab->opt_diminfo[u].count; + if(space->select.sel_info.hslab->opt_diminfo[u].block != H5S_UNLIMITED && + space->select.sel_info.hslab->opt_diminfo[u].block > max1) + max1 = space->select.sel_info.hslab->opt_diminfo[u].block; + } + + /* +1 to provide room for H5S_UNLIMITED */ + enc1 = H5S__hyper_get_enc_size_real(++max1); + + /* Find max for start[] and stride[] */ + for(u = 0; u < space->extent.rank; u++) { + if(space->select.sel_info.hslab->opt_diminfo[u].start > max2) + max2 = space->select.sel_info.hslab->opt_diminfo[u].start; + if(space->select.sel_info.hslab->opt_diminfo[u].stride > max2) + max2 = space->select.sel_info.hslab->opt_diminfo[u].stride; + } + + /* Determine the encoding size */ + enc2 = H5S__hyper_get_enc_size_real(max2); + + *enc_size = MAX(enc1, enc2); + } else { + hsize_t max_size = block_count; + HDassert(space->select.sel_info.hslab->unlim_dim < 0); + + /* Find max for block_count and bounds_end[] */ + for(u = 0; u < space->extent.rank; u++) + if(bounds_end[u] > max_size) + max_size = bounds_end[u]; + + /* Determine the encoding size */ + *enc_size = H5S__hyper_get_enc_size_real(max_size); + } + break; + + default: + HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown hyperslab selection version") + break; + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S__hyper_get_version_enc_size() */ + + + +/*-------------------------------------------------------------------------- + NAME H5S__hyper_serial_size PURPOSE Determine the number of bytes needed to store the serialized hyperslab @@ -3303,49 +3517,73 @@ done: static hssize_t H5S__hyper_serial_size(const H5S_t *space) { - hsize_t block_count; /* block counter for regular hyperslabs */ - unsigned u; /* Counter */ - hssize_t ret_value = -1; /* return value */ + hsize_t block_count = 0; /* block counter for regular hyperslabs */ + uint32_t version; /* Version number */ + uint8_t enc_size; /* Encoded size of hyerslab selection info */ + hssize_t ret_value = -1; /* return value */ - FUNC_ENTER_STATIC_NOERR + FUNC_ENTER_STATIC HDassert(space); - /* Check for version (right now, an unlimited dimension is the only thing - * that would bump the version) */ - if(space->select.sel_info.hslab->unlim_dim >= 0) + if(space->select.sel_info.hslab->unlim_dim < 0) /* ! H5S_UNLIMITED */ + block_count = H5S__get_select_hyper_nblocks(space, FALSE); + + /* Determine the version and the encoded size */ + if(H5S__hyper_get_version_enc_size(space, block_count, &version, &enc_size) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't determine hyper version & enc_size") + + if(version == H5S_HYPER_VERSION_3) { + /* Version 3: regular */ + /* Size required is always: + * <type (4 bytes)> + <version (4 bytes)> + <flags (1 byte)> + + * <size of offset info (1 byte)> + <rank (4 bytes)> + + * (4 (start/stride/count/block) * <enc_size> * <rank>) = + * 14 + (4 * enc_size * rank) bytes + */ + if(H5S__hyper_is_regular(space)) + ret_value = (hssize_t)14 + + ((hssize_t)4 * (hssize_t)enc_size * (hssize_t)space->extent.rank); + else { + /* Version 3: irregular */ + /* Size required is always: + * <type (4 bytes)> + <version (4 bytes)> + <flags (1 byte)> + + * <size of offset info (1 byte)> + <rank (4 bytes)> + + * < # of blocks (depend on enc_size) > + + * (2 (starting/ending offset) * <rank> * <enc_size> * <# of blocks) = + * = 14 bytes + enc_size (block_count) + (2 * enc_size * rank * block_count) bytes + */ + ret_value = 14 + enc_size; + H5_CHECK_OVERFLOW(((unsigned)2 * enc_size * space->extent.rank * block_count), hsize_t, hssize_t); + ret_value += (hssize_t)((unsigned)2 * enc_size * space->extent.rank * block_count); + } + } else if(version == H5S_HYPER_VERSION_2) { /* Version 2 */ /* Size required is always: * <type (4 bytes)> + <version (4 bytes)> + <flags (1 byte)> + * <length (4 bytes)> + <rank (4 bytes)> + - * (4 (start/stride/count/block) * <rank> * <value (8 bytes)>) = - * 17 + (4 * rank * 8) bytes + * (4 (start/stride/count/block) * <enc_size (8 bytes)> * <rank>) = + * 17 + (4 * 8 * rank) bytes */ - ret_value = (hssize_t)17 + ((hssize_t)4 * (hssize_t)space->extent.rank - * (hssize_t)8); - else { + HDassert(enc_size == 8); + ret_value = (hssize_t)17 + ((hssize_t)4 * (hssize_t)8 * (hssize_t)space->extent.rank); + } else { + HDassert(version == H5S_HYPER_VERSION_1); + HDassert(enc_size == 4); /* Version 1 */ /* Basic number of bytes required to serialize hyperslab selection: * <type (4 bytes)> + <version (4 bytes)> + <padding (4 bytes)> + - * <length (4 bytes)> + <rank (4 bytes)> + <# of blocks (4 bytes)> - * = 24 bytes + * <length (4 bytes)> + <rank (4 bytes)> + <# of blocks (4 bytes)> + + * (2 (starting/ending offset) * <enc_size (4 bytes)> * <rank> * <# of blocks) = + * = 24 bytes + (2 * 4 * rank * block_count) */ ret_value = 24; - - /* Check for a "regular" hyperslab selection */ - if(space->select.sel_info.hslab->diminfo_valid) { - /* Check each dimension */ - for(block_count = 1, u = 0; u < space->extent.rank; u++) - block_count *= space->select.sel_info.hslab->opt_diminfo[u].count; - } /* end if */ - else - /* Spin through hyperslab spans, adding 8 * rank bytes for each block */ - block_count = H5S__hyper_span_nblocks(space->select.sel_info.hslab->span_lst); - H5_CHECK_OVERFLOW((8 * space->extent.rank * block_count), hsize_t, hssize_t); - ret_value += (hssize_t)(8 * block_count * space->extent.rank); + ret_value += (hssize_t)(8 * space->extent.rank * block_count); } /* end else */ +done: + FUNC_LEAVE_NOAPI(ret_value) } /* end H5S__hyper_serial_size() */ @@ -3356,12 +3594,13 @@ H5S__hyper_serial_size(const H5S_t *space) PURPOSE Serialize the current selection into a user-provided buffer. USAGE - void H5S__hyper_serialize_helper(spans, start, end, rank, buf) + void H5S__hyper_serialize_helper(spans, start, end, rank, enc_size, buf) H5S_hyper_span_info_t *spans; IN: Hyperslab span tree to serialize hssize_t start[]; IN/OUT: Accumulated start points hssize_t end[]; IN/OUT: Accumulated end points hsize_t rank; IN: Current rank looking at - uint8 *buf; OUT: Buffer to put serialized selection into + uint8_t enc_size IN: Encoded size of hyperslab selection info + uint8_t *buf; OUT: Buffer to put serialized selection into RETURNS None DESCRIPTION @@ -3374,7 +3613,7 @@ H5S__hyper_serial_size(const H5S_t *space) --------------------------------------------------------------------------*/ static void H5S__hyper_serialize_helper(const H5S_hyper_span_info_t *spans, - hsize_t *start, hsize_t *end, hsize_t rank, uint8_t **p) + hsize_t *start, hsize_t *end, hsize_t rank, uint8_t enc_size, uint8_t **p) { H5S_hyper_span_t *curr; /* Pointer to current hyperslab span */ uint8_t *pp = (*p); /* Local pointer for decoding */ @@ -3398,26 +3637,65 @@ H5S__hyper_serialize_helper(const H5S_hyper_span_info_t *spans, end[rank] = curr->high; /* Recurse down to the next dimension */ - H5S__hyper_serialize_helper(curr->down, start, end, rank + 1, &pp); + H5S__hyper_serialize_helper(curr->down, start, end, rank + 1, enc_size, &pp); } /* end if */ else { hsize_t u; /* Index variable */ /* Encode all the previous dimensions starting & ending points */ + switch(enc_size) { + case H5S_SELECT_INFO_ENC_SIZE_2: + /* Encode previous starting points */ + for(u=0; u<rank; u++) + UINT16ENCODE(pp, (uint16_t)start[u]); + + /* Encode starting point for this span */ + UINT16ENCODE(pp, (uint16_t)curr->low); + + /* Encode previous ending points */ + for(u=0; u<rank; u++) + UINT16ENCODE(pp, (uint16_t)end[u]); + + /* Encode starting point for this span */ + UINT16ENCODE(pp, (uint16_t)curr->high); + break; - /* Encode previous starting points */ - for(u = 0; u < rank; u++) - UINT32ENCODE(pp, (uint32_t)start[u]); + case H5S_SELECT_INFO_ENC_SIZE_4: + /* Encode previous starting points */ + for(u=0; u<rank; u++) + UINT32ENCODE(pp, (uint32_t)start[u]); - /* Encode starting point for this span */ - UINT32ENCODE(pp, (uint32_t)curr->low); + /* Encode starting point for this span */ + UINT32ENCODE(pp, (uint32_t)curr->low); - /* Encode previous ending points */ - for(u = 0; u < rank; u++) - UINT32ENCODE(pp, (uint32_t)end[u]); + /* Encode previous ending points */ + for(u=0; u<rank; u++) + UINT32ENCODE(pp, (uint32_t)end[u]); + + /* Encode starting point for this span */ + UINT32ENCODE(pp, (uint32_t)curr->high); + break; + + case H5S_SELECT_INFO_ENC_SIZE_8: + /* Encode previous starting points */ + for(u=0; u<rank; u++) + UINT64ENCODE(pp, (uint64_t)start[u]); + + /* Encode starting point for this span */ + UINT64ENCODE(pp, (uint64_t)curr->low); + + /* Encode previous ending points */ + for(u=0; u<rank; u++) + UINT64ENCODE(pp, (uint64_t)end[u]); + + /* Encode starting point for this span */ + UINT64ENCODE(pp, (uint64_t)curr->high); + break; + + default: + HDassert(0 && "Unknown enc size?!?"); - /* Encode starting point for this span */ - UINT32ENCODE(pp, (uint32_t)curr->high); + } /* end switch */ } /* end else */ /* Advance to next node */ @@ -3455,14 +3733,26 @@ H5S__hyper_serialize_helper(const H5S_hyper_span_info_t *spans, static herr_t H5S__hyper_serialize(const H5S_t *space, uint8_t **p) { - uint8_t *pp; /* Local pointer for encoding */ - uint8_t *lenp; /* Pointer to length location for later storage */ - uint32_t len = 0; /* Number of bytes used */ + const H5S_hyper_dim_t *diminfo; /* Alias for dataspace's diminfo information */ + hsize_t tmp_count[H5S_MAX_RANK]; /* Temporary hyperslab counts */ + hsize_t offset[H5S_MAX_RANK]; /* Offset of element in dataspace */ + hsize_t start[H5S_MAX_RANK]; /* Location of start of hyperslab */ + hsize_t end[H5S_MAX_RANK]; /* Location of end of hyperslab */ + uint8_t *pp; /* Local pointer for decoding */ + uint8_t *lenp = NULL; /* 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 */ + hsize_t block_count = 0; /* block counter for regular hyperslabs */ + unsigned fast_dim; /* Rank of the fastest changing dimension for the dataspace */ + unsigned ndims; /* Rank of the dataspace */ + unsigned i, u; /* Local counting variable */ + hbool_t complete = FALSE; /* Whether we are done with the iteration */ + hbool_t is_regular; /* Whether selection is regular */ + uint8_t enc_size; + herr_t ret_value = SUCCEED; /* return value */ - FUNC_ENTER_STATIC_NOERR + FUNC_ENTER_STATIC /* Sanity checks */ HDassert(space); @@ -3470,163 +3760,243 @@ H5S__hyper_serialize(const H5S_t *space, uint8_t **p) pp = (*p); HDassert(pp); - /* Calculate version */ - if(space->select.sel_info.hslab->unlim_dim >= 0) { - version = 2; - flags |= H5S_SELECT_FLAG_UNLIM; - } /* end if */ - else - version = 1; + /* Set some convienence values */ + ndims = space->extent.rank; + diminfo = space->select.sel_info.hslab->opt_diminfo; + + if(space->select.sel_info.hslab->unlim_dim < 0) /* ! H5S_UNLIMITED */ + block_count = H5S__get_select_hyper_nblocks(space, FALSE); + + /* Determine the version and the encoded size */ + if(H5S__hyper_get_version_enc_size(space, block_count, &version, &enc_size) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't determine hyper version & enc_size") + + is_regular = H5S__hyper_is_regular(space); + if(is_regular && + (version == H5S_HYPER_VERSION_2 || version == H5S_HYPER_VERSION_3)) + flags |= H5S_HYPER_REGULAR; /* Store the preamble information */ UINT32ENCODE(pp, (uint32_t)H5S_GET_SELECT_TYPE(space)); /* Store the type of selection */ UINT32ENCODE(pp, version); /* Store the version number */ - if(version >= 2) - *(pp)++ = flags; /* Store the flags */ - else - 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 */ + + if(version >= 3) { + *(pp)++ = flags; /* Store the flags */ + *(pp)++ = enc_size; /* Store size of offset info */ + + } else { + if(version == 2) + *(pp)++ = flags; /* Store the flags */ + else + 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 */ + + len += 4; /* ndims */ + } /* Encode number of dimensions */ - UINT32ENCODE(pp, (uint32_t)space->extent.rank); - len += 4; + UINT32ENCODE(pp, (uint32_t)ndims); - /* If there is an unlimited dimension, only encode opt_unlim_diminfo */ - if(flags & H5S_SELECT_FLAG_UNLIM) { - unsigned i; + if(is_regular) { - HDassert(H5S_UNLIMITED == HSIZE_UNDEF); + if(version >= H5S_HYPER_VERSION_2) { + + HDassert(H5S_UNLIMITED == HSIZE_UNDEF); - /* Iterate over dimensions */ - for(i = 0; i < space->extent.rank; i++) { + /* Iterate over dimensions */ /* Encode start/stride/block/count */ - UINT64ENCODE(pp, space->select.sel_info.hslab->opt_diminfo[i].start); - UINT64ENCODE(pp, space->select.sel_info.hslab->opt_diminfo[i].stride); - UINT64ENCODE(pp, space->select.sel_info.hslab->opt_diminfo[i].count); - UINT64ENCODE(pp, space->select.sel_info.hslab->opt_diminfo[i].block); - } /* end for */ - len += (4 * space->extent.rank * 8); - } /* end if */ - /* Check for a "regular" hyperslab selection */ - else if(space->select.sel_info.hslab->diminfo_valid) { - const H5S_hyper_dim_t *diminfo; /* Alias for dataspace's diminfo information */ - hsize_t offset[H5S_MAX_RANK]; /* Offset of element in dataspace */ - hsize_t tmp_count[H5S_MAX_RANK]; /* Temporary hyperslab counts */ - unsigned fast_dim; /* Rank of the fastest changing dimension for the dataspace */ - unsigned ndims; /* Rank of the dataspace */ - unsigned u; /* Local counting variable */ - hbool_t done; /* Whether we are done with the iteration */ + switch(enc_size) { + case H5S_SELECT_INFO_ENC_SIZE_2: + HDassert(version == H5S_HYPER_VERSION_3); + for(i = 0; i < space->extent.rank; i++) { + UINT16ENCODE(pp, diminfo[i].start); + UINT16ENCODE(pp, diminfo[i].stride); + if(diminfo[i].count == H5S_UNLIMITED) { + UINT16ENCODE(pp, H5S_UINT16_MAX); + } else { + UINT16ENCODE(pp, diminfo[i].count); + } + + if(diminfo[i].block == H5S_UNLIMITED) { + UINT16ENCODE(pp, H5S_UINT16_MAX); + } else { + UINT16ENCODE(pp, diminfo[i].block); + } + } /* end for */ + break; - /* Set some convenience values */ - ndims = space->extent.rank; - fast_dim = ndims - 1; - diminfo = space->select.sel_info.hslab->opt_diminfo; + case H5S_SELECT_INFO_ENC_SIZE_4: + HDassert(version == H5S_HYPER_VERSION_3); + for(i = 0; i < space->extent.rank; i++) { + UINT32ENCODE(pp, diminfo[i].start); + UINT32ENCODE(pp, diminfo[i].stride); + if(diminfo[i].count == H5S_UNLIMITED) { + UINT32ENCODE(pp, H5S_UINT32_MAX); + } else { + UINT32ENCODE(pp, diminfo[i].count); + } + if(diminfo[i].block == H5S_UNLIMITED) { + UINT32ENCODE(pp, H5S_UINT32_MAX); + } else { + UINT32ENCODE(pp, diminfo[i].block); + } + } /* end for */ + break; - /* Check each dimension */ - for(block_count = 1, u = 0; u < ndims; u++) - block_count *= diminfo[u].count; + case H5S_SELECT_INFO_ENC_SIZE_8: + HDassert(version == H5S_HYPER_VERSION_2 || version == H5S_HYPER_VERSION_3); + for(i = 0; i < space->extent.rank; i++) { + UINT64ENCODE(pp, diminfo[i].start); + UINT64ENCODE(pp, diminfo[i].stride); + if(diminfo[i].count == H5S_UNLIMITED) { + UINT64ENCODE(pp, H5S_UINT64_MAX); + } else { + UINT64ENCODE(pp, diminfo[i].count); + } + if(diminfo[i].block == H5S_UNLIMITED) { + UINT64ENCODE(pp, H5S_UINT64_MAX); + } else { + UINT64ENCODE(pp, diminfo[i].block); + } + } /* end for */ + if(version == H5S_HYPER_VERSION_2) + len += (4 * space->extent.rank * 8); + break; + default: + HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown offset info size for hyperslab") + break; + } /* end switch */ - /* Encode number of hyperslabs */ - H5_CHECK_OVERFLOW(block_count, hsize_t, uint32_t); - UINT32ENCODE(pp, (uint32_t)block_count); - len += 4; + } else { - /* Now serialize the information for the regular hyperslab */ + HDassert(version == H5S_HYPER_VERSION_1); + + /* Set some convienence values */ + fast_dim = ndims - 1; - /* Build the tables of count sizes as well as the initial offset */ - for(u = 0; u < ndims; u++) { - tmp_count[u] = diminfo[u].count; - offset[u] = diminfo[u].start; - } /* end for */ + /* Encode number of hyperslabs */ + H5_CHECK_OVERFLOW(block_count, hsize_t, uint32_t); + UINT32ENCODE(pp, (uint32_t)block_count); + len += 4; - /* We're not done with the iteration */ - done = FALSE; + /* Now serialize the information for the regular hyperslab */ - /* Go iterate over the hyperslabs */ - while(done == FALSE) { - /* Iterate over the blocks in the fastest dimension */ - while(tmp_count[fast_dim] > 0) { - /* Add 8 bytes times the rank for each hyperslab selected */ - len += 8 * ndims; + /* Build the tables of count sizes as well as the initial offset */ + for(u = 0; u < ndims; u++) { + tmp_count[u] = diminfo[u].count; + offset[u] = diminfo[u].start; + } /* end for */ - /* Encode hyperslab starting location */ - for(u = 0; u < ndims; u++) - UINT32ENCODE(pp, (uint32_t)offset[u]); + /* Go iterate over the hyperslabs */ + while(complete == FALSE) { + /* Iterate over the blocks in the fastest dimension */ + while(tmp_count[fast_dim] > 0) { + /* Add 8 bytes times the rank for each hyperslab selected */ + len += 8 * ndims; - /* Encode hyperslab ending location */ - for(u = 0; u < ndims; u++) - UINT32ENCODE(pp, (uint32_t)(offset[u] + (diminfo[u].block - 1))); + /* Encode hyperslab starting location */ + for(u = 0; u < ndims; u++) + UINT32ENCODE(pp, (uint32_t)offset[u]); - /* Move the offset to the next sequence to start */ - offset[fast_dim]+=diminfo[fast_dim].stride; + /* Encode hyperslab ending location */ + for(u = 0; u < ndims; u++) + UINT32ENCODE(pp, (uint32_t)(offset[u] + (diminfo[u].block - 1))); - /* Decrement the block count */ - tmp_count[fast_dim]--; - } /* end while */ + /* Move the offset to the next sequence to start */ + offset[fast_dim]+=diminfo[fast_dim].stride; + + /* Decrement the block count */ + tmp_count[fast_dim]--; + } /* end while */ - /* Work on other dimensions if necessary */ - if(fast_dim > 0) { - int temp_dim; /* Temporary rank holder */ + /* Work on other dimensions if necessary */ + if(fast_dim > 0) { + int temp_dim; /* Temporary rank holder */ - /* Reset the block counts */ - tmp_count[fast_dim] = diminfo[fast_dim].count; + /* Reset the block counts */ + tmp_count[fast_dim] = diminfo[fast_dim].count; - /* Bubble up the decrement to the slower changing dimensions */ - temp_dim = (int)fast_dim - 1; - while(temp_dim >= 0 && done == FALSE) { - /* Decrement the block count */ - tmp_count[temp_dim]--; + /* Bubble up the decrement to the slower changing dimensions */ + temp_dim = (int)fast_dim - 1; + while(temp_dim >= 0 && complete == FALSE) { + /* Decrement the block count */ + tmp_count[temp_dim]--; - /* Check if we have more blocks left */ - if(tmp_count[temp_dim] > 0) - break; + /* Check if we have more blocks left */ + if(tmp_count[temp_dim] > 0) + break; - /* Check for getting out of iterator */ - if(temp_dim == 0) - done = TRUE; + /* Check for getting out of iterator */ + if(temp_dim == 0) + complete = TRUE; - /* Reset the block count in this dimension */ - tmp_count[temp_dim] = diminfo[temp_dim].count; + /* Reset the block count in this dimension */ + tmp_count[temp_dim] = diminfo[temp_dim].count; - /* Wrapped a dimension, go up to next dimension */ - temp_dim--; - } /* end while */ - } /* end if */ - else - break; /* Break out now, for 1-D selections */ + /* Wrapped a dimension, go up to next dimension */ + temp_dim--; + } /* end while */ + } /* end if */ + else + break; /* Break out now, for 1-D selections */ - /* Re-compute offset array */ - for(u = 0; u < ndims; u++) - offset[u] = diminfo[u].start + diminfo[u].stride * (diminfo[u].count - tmp_count[u]); - } /* end while */ - } /* end if */ - else { - hsize_t start[H5S_MAX_RANK]; /* Location of start of hyperslab */ - hsize_t end[H5S_MAX_RANK]; /* Location of end of hyperslab */ + /* Re-compute offset array */ + for(u = 0; u < ndims; u++) + offset[u] = diminfo[u].start + diminfo[u].stride * (diminfo[u].count - tmp_count[u]); + } /* end while */ + + } /* end else */ + + } else { /* irregular */ /* Encode number of hyperslabs */ - block_count = H5S__hyper_span_nblocks(space->select.sel_info.hslab->span_lst); - H5_CHECK_OVERFLOW(block_count, hsize_t, uint32_t); - UINT32ENCODE(pp, (uint32_t)block_count); - len += 4; + switch(enc_size) { + case H5S_SELECT_INFO_ENC_SIZE_2: + HDassert(version == H5S_HYPER_VERSION_3); + H5_CHECK_OVERFLOW(block_count, hsize_t, uint16_t); + UINT16ENCODE(pp, (uint16_t)block_count); + break; - /* Add 8 bytes times the rank for each hyperslab selected */ - H5_CHECK_OVERFLOW((8 * space->extent.rank * block_count), hsize_t, size_t); - len += (uint32_t)(8 * space->extent.rank * block_count); + case H5S_SELECT_INFO_ENC_SIZE_4: + HDassert(version == H5S_HYPER_VERSION_1 || version == H5S_HYPER_VERSION_3); + H5_CHECK_OVERFLOW(block_count, hsize_t, uint32_t); + UINT32ENCODE(pp, (uint32_t)block_count); + break; - /* Encode each hyperslab in selection */ - H5S__hyper_serialize_helper(space->select.sel_info.hslab->span_lst, start, end, (hsize_t)0, &pp); - } /* end else */ + case H5S_SELECT_INFO_ENC_SIZE_8: + HDassert(version == H5S_HYPER_VERSION_3); + UINT64ENCODE(pp, block_count); + break; + + default: + HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown offset info size for hyperslab") + break; + } /* end switch */ + + if(version == H5S_HYPER_VERSION_1) { + len+=4; /* block_count */ + + /* Add 8 bytes times the rank for each hyperslab selected */ + H5_CHECK_OVERFLOW((8 * ndims * block_count), hsize_t, size_t); + len += (uint32_t)(8 * ndims * block_count); + } + + H5S__hyper_serialize_helper(space->select.sel_info.hslab->span_lst, start, end, (hsize_t)0, enc_size, &pp); + + } /* Encode length */ - UINT32ENCODE(lenp, (uint32_t)len); /* Store the length of the extra information */ + if(version <= H5S_HYPER_VERSION_2) + UINT32ENCODE(lenp, (uint32_t)len); /* Store the length of the extra information */ /* Update encoding pointer */ *p = pp; - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5S__hyper_serialize() */ +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S__hyper_serialize() */ + /*-------------------------------------------------------------------------- @@ -3657,14 +4027,15 @@ H5S__hyper_deserialize(H5S_t **space, const uint8_t **p) H5S_t *tmp_space = NULL; /* Pointer to actual dataspace to use, either *space or a newly allocated one */ hsize_t dims[H5S_MAX_RANK]; /* Dimenion sizes */ - hsize_t start[H5S_MAX_RANK]; /* Hyperslab start information */ - hsize_t block[H5S_MAX_RANK]; /* Hyperslab block information */ + hsize_t start[H5S_MAX_RANK]; /* hyperslab start information */ + hsize_t block[H5S_MAX_RANK]; /* hyperslab block information */ uint32_t version; /* Version number */ uint8_t flags = 0; /* Flags */ - unsigned rank; /* Rank of points */ + uint8_t enc_size = 0; /* Encoded size of selection info */ + unsigned rank; /* rank of points */ const uint8_t *pp; /* Local pointer for decoding */ - unsigned u; /* Local counting variable */ - herr_t ret_value = FAIL; /* Return value */ + unsigned u; /* Local counting variable */ + herr_t ret_value=FAIL; /* return value */ FUNC_ENTER_STATIC @@ -3688,15 +4059,31 @@ H5S__hyper_deserialize(H5S_t **space, const uint8_t **p) /* Decode version */ UINT32DECODE(pp, version); - if(version >= (uint32_t)2) { + if(version >= (uint32_t)H5S_HYPER_VERSION_2) { /* Decode flags */ flags = *(pp)++; - /* Skip over the remainder of the header */ - pp += 4; - } else + if(version >= (uint32_t)H5S_HYPER_VERSION_3) + /* decode size of offset info */ + enc_size = *(pp)++; + else { + /* Skip over the remainder of the header */ + pp += 4; + enc_size = H5S_SELECT_INFO_ENC_SIZE_8; + } + + /* Check for unknown flags */ + if(flags & ~H5S_SELECT_FLAG_BITS) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTLOAD, FAIL, "unknown flag for selection") + } else { /* Skip over the remainder of the header */ pp += 8; + enc_size = H5S_SELECT_INFO_ENC_SIZE_4; + } + + /* Check encoded */ + if(enc_size & ~H5S_SELECT_INFO_ENC_SIZE_BITS) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTLOAD, FAIL, "unknown size of point/offset info for selection") /* Decode the rank of the point selection */ UINT32DECODE(pp,rank); @@ -3712,24 +4099,66 @@ H5S__hyper_deserialize(H5S_t **space, const uint8_t **p) if(rank != tmp_space->extent.rank) HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "rank of serialized selection does not match dataspace") - /* If there is an unlimited dimension, only encode opt_unlim_diminfo */ - if(flags & H5S_SELECT_FLAG_UNLIM) { + if(flags & H5S_HYPER_REGULAR) { hsize_t stride[H5S_MAX_RANK]; /* Hyperslab stride information */ - hsize_t count[H5S_MAX_RANK]; /* Hyperslab count information */ + hsize_t count[H5S_MAX_RANK]; /* Hyperslab count information */ /* Sanity checks */ HDassert(H5S_UNLIMITED == HSIZE_UNDEF); HDassert(version >= 2); - /* Iterate over dimensions */ - for(u = 0; u < rank; u++) { - /* Decode start/stride/block/count */ - UINT64DECODE(pp, start[u]); - UINT64DECODE(pp, stride[u]); - UINT64DECODE(pp, count[u]); - UINT64DECODE(pp, block[u]); - } /* end for */ + /* Decode start/stride/block/count */ + switch(enc_size) { + case H5S_SELECT_INFO_ENC_SIZE_2: + for(u = 0; u < tmp_space->extent.rank; u++) { + UINT16DECODE(pp, start[u]); + UINT16DECODE(pp, stride[u]); + + UINT16DECODE(pp, count[u]); + if((uint16_t)count[u] == H5S_UINT16_MAX) + count[u] = H5S_UNLIMITED; + + UINT16DECODE(pp, block[u]); + if((uint16_t)block[u] == H5S_UINT16_MAX) + block[u] = H5S_UNLIMITED; + } /* end for */ + break; + + case H5S_SELECT_INFO_ENC_SIZE_4: + for(u = 0; u < tmp_space->extent.rank; u++) { + UINT32DECODE(pp, start[u]); + UINT32DECODE(pp, stride[u]); + + UINT32DECODE(pp, count[u]); + if((uint32_t)count[u] == H5S_UINT32_MAX) + count[u] = H5S_UNLIMITED; + + UINT32DECODE(pp, block[u]); + if((uint32_t)block[u] == H5S_UINT32_MAX) + block[u] = H5S_UNLIMITED; + } /* end for */ + break; + case H5S_SELECT_INFO_ENC_SIZE_8: + for(u = 0; u < tmp_space->extent.rank; u++) { + UINT64DECODE(pp, start[u]); + UINT64DECODE(pp, stride[u]); + + UINT64DECODE(pp, count[u]); + if((uint64_t)count[u] == H5S_UINT64_MAX) + count[u] = H5S_UNLIMITED; + + UINT64DECODE(pp, block[u]); + if((uint64_t)block[u] == H5S_UINT64_MAX) + block[u] = H5S_UNLIMITED; + } /* end for */ + break; + + default: + HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown offset info size for hyperslab") + break; + } /* end switch */ + /* Select the hyperslab to the current selection */ if((ret_value = H5S_select_hyperslab(tmp_space, H5S_SELECT_SET, start, stride, count, block)) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't change selection") @@ -3737,28 +4166,65 @@ H5S__hyper_deserialize(H5S_t **space, const uint8_t **p) else { const hsize_t *stride; /* Hyperslab stride information */ const hsize_t *count; /* Hyperslab count information */ - hsize_t end[H5S_MAX_RANK]; /* Hyperslab end information */ - hsize_t *tstart; /* Temporary hyperslab pointers */ - hsize_t *tend; /* Temporary hyperslab pointers */ - hsize_t *tblock; /* Temporary hyperslab pointers */ - size_t block_count; /* Number of blocks in selection */ - unsigned v; /* Local counting variable */ + hsize_t end[H5S_MAX_RANK]; /* Hyperslab end information */ + hsize_t *tstart; /* Temporary hyperslab pointers */ + hsize_t *tend; /* Temporary hyperslab pointers */ + hsize_t *tblock; /* Temporary hyperslab pointers */ + size_t num_elem; /* Number of elements in selection */ + unsigned v; /* Local counting variable */ + + /* decode the number of blocks */ + switch(enc_size) { + case H5S_SELECT_INFO_ENC_SIZE_2: + UINT16DECODE(pp, num_elem); + break; + + case H5S_SELECT_INFO_ENC_SIZE_4: + UINT32DECODE(pp, num_elem); + break; + + case H5S_SELECT_INFO_ENC_SIZE_8: + UINT64DECODE(pp, num_elem); + break; - /* Decode the number of blocks */ - UINT32DECODE(pp, block_count); + default: + HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown offset info size for hyperslab") + break; + } /* Set the count & stride for all blocks */ stride = count = H5S_hyper_ones_g; /* Retrieve the coordinates from the buffer */ - for(u = 0; u < block_count; u++) { - /* Decode the starting points */ - for(tstart = start, v = 0; v < rank; v++, tstart++) - UINT32DECODE(pp, *tstart); - - /* Decode the ending points */ - for(tend = end, v = 0; v < rank; v++, tend++) - UINT32DECODE(pp, *tend); + for(u = 0; u < num_elem; u++) { + + /* Decode the starting and ending points */ + switch(enc_size) { + case H5S_SELECT_INFO_ENC_SIZE_2: + for(tstart = start, v = 0; v < rank; v++, tstart++) + UINT16DECODE(pp, *tstart); + for(tend = end, v = 0; v < rank; v++, tend++) + UINT16DECODE(pp, *tend); + break; + + case H5S_SELECT_INFO_ENC_SIZE_4: + for(tstart = start,v = 0; v < rank; v++, tstart++) + UINT32DECODE(pp, *tstart); + for(tend = end, v = 0; v < rank; v++, tend++) + UINT32DECODE(pp, *tend); + break; + + case H5S_SELECT_INFO_ENC_SIZE_8: + for(tstart = start, v = 0; v < rank; v++, tstart++) + UINT64DECODE(pp, *tstart); + for(tend = end, v = 0; v < rank; v++, tend++) + UINT64DECODE(pp, *tend); + break; + + default: + HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown offset info size for hyperslab") + break; + } /* Change the ending points into blocks */ for(tblock = block, tstart = start, tend = end, v = 0; v < rank; v++, tstart++, tend++, tblock++) diff --git a/src/H5Snone.c b/src/H5Snone.c index cae9a67..6219bb1 100644 --- a/src/H5Snone.c +++ b/src/H5Snone.c @@ -583,7 +583,7 @@ H5S__none_serialize(const H5S_t *space, uint8_t **p) /* 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, (uint32_t)H5S_NONE_VERSION_1); /* Store the version number */ UINT32ENCODE(pp, (uint32_t)0); /* Store the un-used padding */ UINT32ENCODE(pp, (uint32_t)0); /* Store the additional information length */ diff --git a/src/H5Spkg.h b/src/H5Spkg.h index 2918648..56b1f30 100644 --- a/src/H5Spkg.h +++ b/src/H5Spkg.h @@ -37,8 +37,35 @@ #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) +#define H5S_HYPER_REGULAR 0x01 +#define H5S_SELECT_FLAG_BITS (H5S_HYPER_REGULAR) + +/* Versions for H5S_SEL_HYPER selection info */ +#define H5S_HYPER_VERSION_1 1 +#define H5S_HYPER_VERSION_2 2 +#define H5S_HYPER_VERSION_3 3 + +/* Versions for H5S_SEL_POINTS selection info */ +#define H5S_POINT_VERSION_1 1 +#define H5S_POINT_VERSION_2 2 + +/* Versions for H5S_SEL_NONE selection info */ +#define H5S_NONE_VERSION_1 1 + +/* Versions for H5S_SEL_ALL selection info */ +#define H5S_ALL_VERSION_1 1 + +/* Encoded size of selection info for H5S_SEL_POINTS/H5S_SEL_HYPER */ +#define H5S_SELECT_INFO_ENC_SIZE_2 0x02 /* 2 bytes: 16 bits */ +#define H5S_SELECT_INFO_ENC_SIZE_4 0x04 /* 4 bytes: 32 bits */ +#define H5S_SELECT_INFO_ENC_SIZE_8 0x08 /* 8 bytes: 64 bits */ +#define H5S_SELECT_INFO_ENC_SIZE_BITS ( H5S_SELECT_INFO_ENC_SIZE_2 | \ + H5S_SELECT_INFO_ENC_SIZE_4 | \ + H5S_SELECT_INFO_ENC_SIZE_8 ) + +#define H5S_UINT16_MAX 0x0000FFFF /* 2^16 - 1 = 65,535 */ +#define H5S_UINT32_MAX 0xFFFFFFFF /* 2^32 - 1 = 4,294,967,295 */ +#define H5S_UINT64_MAX ((hsize_t)(-1L)) /* 2^64 - 1 = 18,446,744,073,709,551,615 */ /* Length of stack-allocated sequences for "project intersect" routines */ #define H5S_PROJECT_INTERSECT_NSEQS 256 diff --git a/src/H5Spoint.c b/src/H5Spoint.c index ac9c983..a3f7df2 100644 --- a/src/H5Spoint.c +++ b/src/H5Spoint.c @@ -28,13 +28,14 @@ /***********/ /* Headers */ /***********/ -#include "H5private.h" /* Generic Functions */ +#include "H5private.h" /* Generic Functions */ +#include "H5CXprivate.h" /* API Contexts */ #include "H5Eprivate.h" /* Error handling */ #include "H5FLprivate.h" /* Free Lists */ -#include "H5Iprivate.h" /* ID Functions */ -#include "H5MMprivate.h" /* Memory management */ -#include "H5Spkg.h" /* Dataspace functions */ -#include "H5VMprivate.h" /* Vector functions */ +#include "H5Iprivate.h" /* ID Functions */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Spkg.h" /* Dataspace functions */ +#include "H5VMprivate.h" /* Vector functions */ /****************/ @@ -72,6 +73,8 @@ static herr_t H5S__point_project_scalar(const H5S_t *space, hsize_t *offset); static herr_t H5S__point_project_simple(const H5S_t *space, H5S_t *new_space, hsize_t *offset); static herr_t H5S__point_iter_init(H5S_sel_iter_t *iter, const H5S_t *space); +static herr_t + H5S__point_get_version_enc_size(const H5S_t *space, uint32_t *version, uint8_t *enc_size); /* Selection iteration callbacks */ static herr_t H5S__point_iter_coords(const H5S_sel_iter_t *iter, hsize_t *coords); @@ -118,6 +121,13 @@ const H5S_select_class_t H5S_sel_point[1] = {{ H5S__point_iter_init, }}; +/* Format version bounds for dataspace hyperslab selection */ +const unsigned H5O_sds_point_ver_bounds[] = { + H5S_POINT_VERSION_1, /* H5F_LIBVER_EARLIEST */ + H5S_POINT_VERSION_1, /* H5F_LIBVER_V18 */ + H5S_POINT_VERSION_1, /* H5F_LIBVER_V110 */ + H5S_POINT_VERSION_2 /* H5F_LIBVER_LATEST */ +}; /*******************/ /* Local Variables */ @@ -919,6 +929,124 @@ done: FUNC_LEAVE_API(ret_value) } /* end H5Sget_select_elem_npoints() */ +/*-------------------------------------------------------------------------- + NAME + H5S__point_get_version_enc_size + PURPOSE + Determine the version and the size (2, 4 or 8 bytes) to encode point selection info + USAGE + hssize_t H5S__point_set_enc_size(space, version, enc_size) + const H5S_t *space: IN: Dataspace ID of selection to query + uint32_t *version: OUT: The version to use for encoding + uint8_t *enc_size: OUT: The size to use for encoding + RETURNS + The version and the size to encode point selection info + DESCRIPTION + Determine the version to use for encoding points selection info based + on the following: + (1) the low/high bounds setting in fapl + (2) whether the number of points or selection high bounds exceeds H5S_UINT32_MAX or not + + Determine the encoded size based on version: + --For version 2, the encoded size of point selection info is determined + by the maximum size for: + (a) storing the number of points + (b) storing the selection high bounds + + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5S__point_get_version_enc_size(const H5S_t *space, uint32_t *version, uint8_t *enc_size) +{ + hbool_t count_up_version = FALSE; /* Whether number of points exceed H5S_UINT32_MAX */ + hbool_t bound_up_version = FALSE; /* Whether high bounds exceed H5S_UINT32_MAX */ + H5F_libver_t low_bound; /* The 'low' bound of library format versions */ + H5F_libver_t high_bound; /* The 'high' bound of library format versions */ + uint32_t tmp_version; /* Local temporary version */ + hsize_t bounds_start[H5S_MAX_RANK]; /* Starting coordinate of bounding box */ + hsize_t bounds_end[H5S_MAX_RANK]; /* Opposite coordinate of bounding box */ + hsize_t max_size = 0; /* Maximum selection size */ + unsigned u; /* Local index veriable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* 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 whether number of points or high bounds exceeds (2^32 - 1) */ + if(space->select.num_elem > H5S_UINT32_MAX) + count_up_version = TRUE; + else { + for(u = 0; u < space->extent.rank; u++) + if(bounds_end[u] > H5S_UINT32_MAX) { + bound_up_version = TRUE; + break; + } + } + + /* If exceed (2^32 -1) */ + if(count_up_version || bound_up_version) + tmp_version = H5S_POINT_VERSION_2; + else + tmp_version = H5S_POINT_VERSION_1; + + /* Get the file's low/high bounds */ + if(H5CX_get_libver_bounds(&low_bound, &high_bound) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get low/high bounds from API context") + + /* Upgrade to the version indicated by the file's low bound if higher */ + tmp_version = MAX(tmp_version, H5O_sds_point_ver_bounds[low_bound]); + + /* Version bounds check */ + if(tmp_version > H5O_sds_point_ver_bounds[high_bound]) { + if(count_up_version) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "The number of points in point selection exceeds 2^32") + else if(bound_up_version) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "The end of bounding box in point selection exceeds 2^32") + else + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "Dataspace point selection version out of bounds") + } + + /* Set the version to return */ + *version = tmp_version; + + /* Get the encoded size use based on version */ + switch(tmp_version) { + case H5S_POINT_VERSION_1: + *enc_size = H5S_SELECT_INFO_ENC_SIZE_4; + break; + + case H5S_POINT_VERSION_2: + /* Find max for num_elem and bounds_end[] */ + max_size = space->select.num_elem; + for(u = 0; u < space->extent.rank; u++) + if(bounds_end[u] > max_size) + max_size = bounds_end[u]; + + /* Determine the encoding size */ + if(max_size > H5S_UINT32_MAX) + *enc_size = H5S_SELECT_INFO_ENC_SIZE_8; + else if(max_size > H5S_UINT16_MAX) + *enc_size = H5S_SELECT_INFO_ENC_SIZE_4; + else + *enc_size = H5S_SELECT_INFO_ENC_SIZE_2; + break; + + default: + HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown point info size") + break; + } /* end switch */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S__point_get_version_enc_size() */ + /*-------------------------------------------------------------------------- NAME @@ -942,22 +1070,39 @@ done: static hssize_t H5S__point_serial_size(const H5S_t *space) { + uint32_t version; /* Version number */ + uint8_t enc_size; /* Encoded size of point selection info */ hssize_t ret_value = -1; /* Return value */ - FUNC_ENTER_STATIC_NOERR + FUNC_ENTER_STATIC HDassert(space); - /* 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 - */ - ret_value = 24; + /* Determine the version and encoded size for point selection */ + if(H5S__point_get_version_enc_size(space, &version, &enc_size) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't determine hyper version") + + /* Basic number of bytes required to serialize point selection: */ + if(version >= H5S_POINT_VERSION_2) + /* + * <type (4 bytes)> + <version (4 bytes)> + + * <size of point info (1 byte)> + rank (4 bytes)> + */ + ret_value=13; + else + /* + * <type (4 bytes)> + <version (4 bytes)> + <padding (4 bytes)> + + * <length (4 bytes)> + <rank (4 bytes)> + */ + ret_value = 20; + + /* <num points (depend on enc_size)> */ + ret_value += enc_size; /* Count points in selection */ - /* (Add 4 bytes times the rank for each element selected) */ - ret_value += (4 * space->extent.rank) * (hssize_t)H5S_GET_SELECT_NPOINTS(space); + ret_value += (hssize_t) (enc_size * space->extent.rank * space->select.num_elem); +done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5S__point_serial_size() */ @@ -987,12 +1132,15 @@ static herr_t H5S__point_serialize(const H5S_t *space, uint8_t **p) { H5S_pnt_node_t *curr; /* Point information nodes */ - uint8_t *pp; /* Local pointer for encoding */ - uint8_t *lenp; /* Pointer to length location for later storage */ - uint32_t len = 0; /* Number of bytes used */ - unsigned u; /* Local counting variable */ + uint8_t *pp; /* Local pointer for decoding */ + uint8_t *lenp = NULL; /* 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 enc_size; /* Encoded size of point selection info */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_STATIC_NOERR + FUNC_ENTER_STATIC /* Check args */ HDassert(space); @@ -1000,42 +1148,96 @@ H5S__point_serialize(const H5S_t *space, uint8_t **p) pp = (*p); HDassert(pp); + /* Determine the version and encoded size for point selection info */ + if(H5S__point_get_version_enc_size(space, &version, &enc_size) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't determine hyper version") + /* 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, (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 */ + + UINT32ENCODE(pp, version); /* Store the version number */ + if(version >= 2) { + *(pp)++ = enc_size; /* Store size of point info */ + } else { + HDassert(version == H5S_POINT_VERSION_1); + 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 */ + 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; + switch(enc_size) { + case H5S_SELECT_INFO_ENC_SIZE_2: + HDassert(version == H5S_POINT_VERSION_2); + + /* Encode number of elements */ + UINT16ENCODE(pp, (uint16_t)space->select.num_elem); + + /* Encode each point in selection */ + curr=space->select.sel_info.pnt_lst->head; + while(curr!=NULL) { + /* Encode each point */ + for(u=0; u<space->extent.rank; u++) + UINT16ENCODE(pp, (uint16_t)curr->pnt[u]); + curr=curr->next; + } /* end while */ + break; - /* 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; + case H5S_SELECT_INFO_ENC_SIZE_4: + HDassert(version == H5S_POINT_VERSION_1 || version == H5S_POINT_VERSION_2); - /* Encode each point */ - for(u = 0; u < space->extent.rank; u++) - UINT32ENCODE(pp, (uint32_t)curr->pnt[u]); + /* Encode number of elements */ + UINT32ENCODE(pp, (uint32_t)space->select.num_elem); - curr = curr->next; - } /* end while */ + /* Encode each point in selection */ + curr=space->select.sel_info.pnt_lst->head; + while(curr!=NULL) { + /* Encode each point */ + for(u=0; u<space->extent.rank; u++) + UINT32ENCODE(pp, (uint32_t)curr->pnt[u]); + curr=curr->next; + } /* end while */ + + /* Add 4 bytes times the rank for each element selected */ + if(version == H5S_POINT_VERSION_1) + len += (uint32_t)space->select.num_elem * 4 * space->extent.rank; + break; + + case H5S_SELECT_INFO_ENC_SIZE_8: + HDassert(version == H5S_POINT_VERSION_2); + + /* Encode number of elements */ + UINT64ENCODE(pp, space->select.num_elem); + + /* Encode each point in selection */ + curr=space->select.sel_info.pnt_lst->head; + while(curr!=NULL) { + /* Encode each point */ + for(u=0; u<space->extent.rank; u++) + UINT64ENCODE(pp, curr->pnt[u]); + curr=curr->next; + } /* end while */ + break; - /* Encode length */ - UINT32ENCODE(lenp, (uint32_t)len); /* Store the length of the extra information */ + default: + HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown point info size") + break; + + } /* end switch */ + + if(version == H5S_POINT_VERSION_1) + UINT32ENCODE(lenp, (uint32_t)len); /* Store the length of the extra information */ /* Update encoding pointer */ *p = pp; - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5S__point_serialize() */ +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S__point_serialize() */ + /*-------------------------------------------------------------------------- @@ -1067,9 +1269,10 @@ H5S__point_deserialize(H5S_t **space, const uint8_t **p) either *space or a newly allocated one */ hsize_t dims[H5S_MAX_RANK]; /* Dimension sizes */ uint32_t version; /* Version number */ + uint8_t enc_size = 0; /* Encoded size of selection info */ hsize_t *coord = NULL, *tcoord; /* Pointer to array of elements */ const uint8_t *pp; /* Local pointer for decoding */ - size_t num_elem = 0; /* Number of elements in selection */ + hsize_t num_elem = 0; /* Number of elements in selection */ unsigned rank; /* Rank of points */ unsigned i, j; /* local counting variables */ herr_t ret_value = SUCCEED; /* Return value */ @@ -1096,8 +1299,18 @@ H5S__point_deserialize(H5S_t **space, const uint8_t **p) /* Decode version */ UINT32DECODE(pp, version); - /* Skip over the remainder of the header */ - pp += 8; + if(version >= (uint32_t)H5S_POINT_VERSION_2) + /* Decode size of point info */ + enc_size = *(pp)++; + else { + /* Skip over the remainder of the header */ + pp += 8; + enc_size = H5S_SELECT_INFO_ENC_SIZE_4; + } + + /* Check encoded size */ + if(enc_size & ~H5S_SELECT_INFO_ENC_SIZE_BITS) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTLOAD, FAIL, "unknown size of point/offset info for selection") /* Decode the rank of the point selection */ UINT32DECODE(pp,rank); @@ -1113,8 +1326,22 @@ H5S__point_deserialize(H5S_t **space, const uint8_t **p) if(rank != tmp_space->extent.rank) HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "rank of serialized selection does not match dataspace") - /* Deserialize points to select */ - UINT32DECODE(pp, num_elem); /* decode the number of points */ + /* decode the number of points */ + switch(enc_size) { + case H5S_SELECT_INFO_ENC_SIZE_2: + UINT16DECODE(pp, num_elem); + break; + case H5S_SELECT_INFO_ENC_SIZE_4: + UINT32DECODE(pp, num_elem); + break; + case H5S_SELECT_INFO_ENC_SIZE_8: + UINT64DECODE(pp, num_elem); + break; + default: + HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown point info size") + break; + } /* end switch */ + /* Allocate space for the coordinates */ if(NULL == (coord = (hsize_t *)H5MM_malloc(num_elem * rank * sizeof(hsize_t)))) @@ -1123,7 +1350,22 @@ H5S__point_deserialize(H5S_t **space, const uint8_t **p) /* Retrieve the coordinates from the buffer */ for(tcoord = coord, i = 0; i < num_elem; i++) for(j = 0; j < (unsigned)rank; j++, tcoord++) - UINT32DECODE(pp, *tcoord); + switch(enc_size) { + case H5S_SELECT_INFO_ENC_SIZE_2: + UINT16DECODE(pp, *tcoord); + break; + + case H5S_SELECT_INFO_ENC_SIZE_4: + UINT32DECODE(pp, *tcoord); + break; + + case H5S_SELECT_INFO_ENC_SIZE_8: + UINT64DECODE(pp, *tcoord); + break; + default: + HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unknown point info size") + break; + } /* end switch */ /* Select points */ if(H5S_select_elements(tmp_space, H5S_SELECT_SET, num_elem, (const hsize_t *)coord) < 0) diff --git a/src/H5Spublic.h b/src/H5Spublic.h index 561875a..c01beca 100644 --- a/src/H5Spublic.h +++ b/src/H5Spublic.h @@ -97,7 +97,7 @@ H5_DLL herr_t H5Sset_extent_simple(hid_t space_id, int rank, const hsize_t dims[], const hsize_t max[]); H5_DLL hid_t H5Scopy(hid_t space_id); H5_DLL herr_t H5Sclose(hid_t space_id); -H5_DLL herr_t H5Sencode(hid_t obj_id, void *buf, size_t *nalloc); +H5_DLL herr_t H5Sencode2(hid_t obj_id, void *buf, size_t *nalloc, hid_t fapl); H5_DLL hid_t H5Sdecode(const void *buf); H5_DLL hssize_t H5Sget_simple_extent_npoints(hid_t space_id); H5_DLL int H5Sget_simple_extent_ndims(hid_t space_id); @@ -134,6 +134,16 @@ H5_DLL hssize_t H5Sget_select_hyper_nblocks(hid_t spaceid); H5_DLL herr_t H5Sget_select_hyper_blocklist(hid_t spaceid, hsize_t startblock, hsize_t numblocks, hsize_t buf[/*numblocks*/]); +/* Symbols defined for compatibility with previous versions of the HDF5 API. + * + * Use of these symbols is deprecated. + */ +#ifndef H5_NO_DEPRECATED_SYMBOLS +/* Function prototypes */ +H5_DLL herr_t H5Sencode1(hid_t obj_id, void *buf, size_t *nalloc); + +#endif /* H5_NO_DEPRECATED_SYMBOLS */ + #ifdef __cplusplus } #endif diff --git a/src/H5vers.txt b/src/H5vers.txt index 914c30e..22117c3 100644 --- a/src/H5vers.txt +++ b/src/H5vers.txt @@ -61,12 +61,14 @@ FUNCTION: H5Oget_info_by_name; ; v18, v112 FUNCTION: H5Oget_info_by_idx; ; v18, v112 FUNCTION: H5Ovisit; ; v18, v112 FUNCTION: H5Ovisit_by_name; ; v18, v112 +FUNCTION: H5Pencode; ; v110, v112 FUNCTION: H5Pget_filter; ; v10, v18 FUNCTION: H5Pget_filter_by_id; ; v16, v18 FUNCTION: H5Pinsert; ; v14, v18 FUNCTION: H5Pregister; ; v14, v18 FUNCTION: H5Rdereference; ; v10, v110 FUNCTION: H5Rget_obj_type; ; v16, v18 +FUNCTION: H5Sencode; ; v18, v112 FUNCTION: H5Tarray_create; ; v14, v18 FUNCTION: H5Tcommit; ; v10, v18 FUNCTION: H5Tget_array_dims; ; v14, v18 diff --git a/src/Makefile.am b/src/Makefile.am index 5532655..378e390 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -102,7 +102,7 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \ H5R.c H5Rint.c H5Rdeprec.c \ H5UC.c \ H5RS.c \ - H5S.c H5Sall.c H5Sdbg.c H5Shyper.c H5Snone.c H5Spoint.c \ + H5S.c H5Sall.c H5Sdbg.c H5Sdeprec.c H5Shyper.c H5Snone.c H5Spoint.c \ H5Sselect.c H5Stest.c \ H5SL.c \ H5SM.c H5SMbtree2.c H5SMcache.c H5SMmessage.c H5SMtest.c \ |