diff options
-rw-r--r-- | release_docs/RELEASE.txt | 4 | ||||
-rw-r--r-- | src/H5D.c | 6 | ||||
-rw-r--r-- | src/H5Dprivate.h | 4 | ||||
-rw-r--r-- | src/H5Pdxpl.c | 85 | ||||
-rw-r--r-- | src/H5Ppublic.h | 4 | ||||
-rw-r--r-- | src/H5T.c | 75 | ||||
-rw-r--r-- | src/H5Tcompound.c | 3 | ||||
-rw-r--r-- | src/H5Tconv.c | 748 | ||||
-rw-r--r-- | src/H5Tpkg.h | 3 | ||||
-rw-r--r-- | src/H5Tprivate.h | 1 | ||||
-rw-r--r-- | src/H5Tpublic.h | 36 | ||||
-rw-r--r-- | test/dtypes.c | 128 |
12 files changed, 858 insertions, 239 deletions
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 045e5db..3ece36e 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -42,6 +42,10 @@ New Features Library: -------- + - New exception handler for datatype conversion is put in to + replace the old overflow callback function. This exception + handler is set through H5Pset_type_conv_cb function. + SLU - 2004/4/27 - Added option that if $HDF5_DISABLE_VERSION_CHECK is set to 2, will suppress all library version mismatch warning messages. AKC - 2004/4/14 @@ -145,6 +145,7 @@ H5D_init_interface(void) * - Default value for I/O transfer mode * - Default value for EDC property * - Default value for filter callback + * - Default value for datatype conversion callback */ H5P_genclass_t *xfer_pclass; size_t def_max_temp_buf = H5D_XFER_MAX_TEMP_BUF_DEF; @@ -164,6 +165,7 @@ H5D_init_interface(void) #endif /* H5_HAVE_PARALLEL */ H5Z_EDC_t enable_edc = H5D_XFER_EDC_DEF; H5Z_cb_t filter_cb = H5D_XFER_FILTER_CB_DEF; + H5T_conv_cb_t conv_cb = H5D_XFER_CONV_CB_DEF; /* Dataset creation property class variables. In sequence, they are, * - Creation property list class to modify @@ -269,6 +271,10 @@ H5D_init_interface(void) /* Register the filter callback property */ if(H5P_register(xfer_pclass,H5D_XFER_FILTER_CB_NAME,H5D_XFER_FILTER_CB_SIZE,&filter_cb,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0) HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") + + /* Register the type conversion callback property */ + if(H5P_register(xfer_pclass,H5D_XFER_CONV_CB_NAME,H5D_XFER_CONV_CB_SIZE,&conv_cb,NULL,NULL,NULL,NULL,NULL,NULL,NULL)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class") } /* end if */ /* Only register the default property list if it hasn't been created yet */ diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h index bef1936..b828c8b 100644 --- a/src/H5Dprivate.h +++ b/src/H5Dprivate.h @@ -137,6 +137,10 @@ #define H5D_XFER_FILTER_CB_NAME "filter_cb" #define H5D_XFER_FILTER_CB_SIZE sizeof(H5Z_cb_t) #define H5D_XFER_FILTER_CB_DEF {NULL,NULL} +/* Definitions for type conversion callback function property */ +#define H5D_XFER_CONV_CB_NAME "type_conv_cb" +#define H5D_XFER_CONV_CB_SIZE sizeof(H5T_conv_cb_t) +#define H5D_XFER_CONV_CB_DEF {NULL,NULL} /****************************/ /* Library Private Typedefs */ diff --git a/src/H5Pdxpl.c b/src/H5Pdxpl.c index 3805c68..e5bd817 100644 --- a/src/H5Pdxpl.c +++ b/src/H5Pdxpl.c @@ -348,6 +348,91 @@ done: /*------------------------------------------------------------------------- + * Function: H5Pset_type_conv_cb + * + * Purpose: Sets user's callback function for dataset transfer property + * list. This callback function defines what user wants to do + * if there's exception during datatype conversion. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Raymond Lu + * April 15, 2004 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pset_type_conv_cb(hid_t plist_id, H5T_conv_except_func_t *op, void *operate_data) +{ + H5P_genplist_t *plist; /* Property list pointer */ + herr_t ret_value=SUCCEED; /* return value */ + H5T_conv_cb_t cb_struct; + + FUNC_ENTER_API(H5Pset_type_conv_cb, FAIL); + H5TRACE3("e","ixx",plist_id,op,operate_data); + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(plist_id,H5P_DATASET_XFER))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + + /* Update property list */ + cb_struct.func = op; + cb_struct.user_data = operate_data; + + if (H5P_set(plist,H5D_XFER_CONV_CB_NAME,&cb_struct)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set value"); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5Pget_type_conv_cb + * + * Purpose: Gets callback function for dataset transfer property + * list. This callback function defines what user wants to do + * if there's exception during datatype conversion. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Raymond Lu + * April 15, 2004 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Pget_type_conv_cb(hid_t plist_id, H5T_conv_except_func_t **op, void **operate_data) +{ + H5P_genplist_t *plist; /* Property list pointer */ + H5T_conv_cb_t cb_struct; + herr_t ret_value=SUCCEED; /* return value */ + + FUNC_ENTER_API(H5Pget_type_conv_cb, FAIL); + H5TRACE3("e","ixx",plist_id,op,operate_data); + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(plist_id,H5P_DATASET_XFER))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); + + /* Get property */ + if (H5P_get(plist,H5D_XFER_CONV_CB_NAME,&cb_struct)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set value"); + + /* Assign return value */ + *op = cb_struct.func; + *operate_data = cb_struct.user_data; + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- * Function: H5Pget_btree_ratios * * Purpose: Queries B-tree split ratios. See H5Pset_btree_ratios(). diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h index 9644b11..0b37e45 100644 --- a/src/H5Ppublic.h +++ b/src/H5Ppublic.h @@ -27,6 +27,7 @@ #include "H5Ipublic.h" #include "H5Dpublic.h" #include "H5Fpublic.h" +#include "H5Tpublic.h" #include "H5FDpublic.h" #include "H5MMpublic.h" #include "H5Zpublic.h" @@ -300,7 +301,8 @@ H5_DLL herr_t H5Pget_hyper_vector_size(hid_t fapl_id, size_t *size/*out*/); H5_DLL herr_t H5Pset_small_data_block_size(hid_t fapl_id, hsize_t size); H5_DLL herr_t H5Pget_small_data_block_size(hid_t fapl_id, hsize_t *size/*out*/); H5_DLL herr_t H5Premove_filter(hid_t plist_id, H5Z_filter_t filter); - +H5_DLL herr_t H5Pset_type_conv_cb(hid_t dxpl_id, H5T_conv_except_func_t *op, void* operate_data); +H5_DLL herr_t H5Pget_type_conv_cb(hid_t dxpl_id, H5T_conv_except_func_t **op, void** operate_data); #ifdef __cplusplus } @@ -244,9 +244,6 @@ static struct { /* The native endianess of the platform */ H5T_order_t H5T_native_order_g = H5T_ORDER_ERROR; -/* The overflow handler */ -H5T_overflow_t H5T_overflow_g = NULL; - /* Declare the free list for H5T_t's */ H5FL_DEFINE(H5T_t); @@ -2548,78 +2545,6 @@ done: FUNC_LEAVE_API(ret_value); } - -/*------------------------------------------------------------------------- - * Function: H5Tget_overflow - * - * Purpose: Returns a pointer to the current global overflow function. - * This is an application-defined function that is called - * whenever a data type conversion causes an overflow. - * - * Return: Success: Ptr to an application-defined function. - * - * Failure: NULL (this can happen if no overflow handling - * function is registered). - * - * Programmer: Robb Matzke - * Tuesday, July 7, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -H5T_overflow_t -H5Tget_overflow(void) -{ - H5T_overflow_t ret_value; /* Return value */ - - FUNC_ENTER_API(H5Tget_overflow, NULL); - H5TRACE0("x",""); - - if (NULL==H5T_overflow_g) - HGOTO_ERROR(H5E_DATATYPE, H5E_UNINITIALIZED, NULL, "no overflow handling function is registered"); - - /* Set return value */ - ret_value=H5T_overflow_g; - -done: - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5Tset_overflow - * - * Purpose: Sets the overflow handler to be the specified function. FUNC - * will be called for all data type conversions that result in - * an overflow. See the definition of `H5T_overflow_t' for - * documentation of arguments and return values. The NULL - * pointer may be passed to remove the overflow handler. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Tuesday, July 7, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5Tset_overflow(H5T_overflow_t func) -{ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_API(H5Tset_overflow, FAIL); - H5TRACE1("e","x",func); - - H5T_overflow_g = func; - -done: - FUNC_LEAVE_API(ret_value); -} - - /*------------------------------------------------------------------------- * API functions are above; library-private functions are below... *------------------------------------------------------------------------- diff --git a/src/H5Tcompound.c b/src/H5Tcompound.c index 3a1c64f..f62f794 100644 --- a/src/H5Tcompound.c +++ b/src/H5Tcompound.c @@ -253,7 +253,8 @@ H5Tget_member_type(hid_t type_id, unsigned membno) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable register datatype atom") done: - if(ret_value<0) { + if(ret_value<0) +{ if(memb_dt!=NULL) if(H5T_close(memb_dt)<0) HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "can't close datatype") diff --git a/src/H5Tconv.c b/src/H5Tconv.c index 83f001c..78744d5 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -24,10 +24,11 @@ #include "H5private.h" /*generic functions */ #include "H5Eprivate.h" /*error handling */ -#include "H5FLprivate.h" /*Free Lists */ +#include "H5FLprivate.h" /*Free Lists */ #include "H5Iprivate.h" /*ID functions */ #include "H5MMprivate.h" /*memory management */ #include "H5Pprivate.h" /* Property Lists */ +#include "H5Dprivate.h" /* Dataset */ #include "H5Tpkg.h" /*data-type functions */ /* Conversion data for H5T_conv_struct() */ @@ -191,19 +192,43 @@ H5FL_BLK_DEFINE_STATIC(array_seq); #define H5T_CONV_Xx_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ if (*((ST*)S) > (DT)(D_MAX)) { \ - if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, S, D)<0) \ + if(cb_struct.func) { /*If user's exception handler is present, use it*/ \ + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, \ + src_id, dst_id, S, D, cb_struct.user_data); \ + } \ + \ + if(except_ret == H5T_CONV_UNHANDLED) { \ + /*let compiler convert if case is ignored by user handler*/ \ *((DT*)D) = (D_MAX); \ + } else if(except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ } else if (*((ST*)S) < (D_MIN)) { \ - if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, S, D)<0) \ + if(cb_struct.func) { /*If user's exception handler is present, use it*/ \ + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, \ + src_id, dst_id, S, D, cb_struct.user_data); \ + } \ + \ + if(except_ret == H5T_CONV_UNHANDLED) { \ + /*let compiler convert if case is ignored by user handler*/ \ *((DT*)D) = (D_MIN); \ + } else if(except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ } else \ *((DT*)D) = (DT)(*((ST*)S)); \ -} +} #define H5T_CONV_Ux_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ if (*((ST*)S) > (D_MAX)) { \ - if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, S, D)<0) \ + if(cb_struct.func) { /*If user's exception handler is present, use it*/ \ + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, \ + src_id, dst_id, S, D, cb_struct.user_data); \ + } \ + \ + if(except_ret == H5T_CONV_UNHANDLED) { \ + /*let compiler convert if case is ignored by user handler*/ \ *((DT*)D) = (D_MAX); \ + } else if(except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ } else \ *((DT*)D) = (DT)(*((ST*)S)); \ } @@ -215,8 +240,16 @@ H5FL_BLK_DEFINE_STATIC(array_seq); #define H5T_CONV_sU_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ if (*((ST*)S)<0) { \ - if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, S, D)<0) \ - *((DT*)D) = 0; \ + if(cb_struct.func) { /*If user's exception handler is present, use it*/ \ + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, \ + src_id, dst_id, S, D, cb_struct.user_data); \ + } \ + \ + if(except_ret == H5T_CONV_UNHANDLED) { \ + /*let compiler convert if case is ignored by user handler*/ \ + *((DT*)D) = 0; \ + } else if(except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ } else \ *((DT*)D) = (DT)(*((ST*)S)); \ } @@ -227,9 +260,17 @@ H5FL_BLK_DEFINE_STATIC(array_seq); } #define H5T_CONV_uS_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ - if (sizeof(ST)==sizeof(DT) && *((ST*)S) > (D_MAX)) { \ - if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, S, D)<0) \ + if (sizeof(ST)==sizeof(DT) && *((ST*)S) > (D_MAX)) { \ + if(cb_struct.func) { /*If user's exception handler is present, use it*/ \ + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, \ + src_id, dst_id, S, D, cb_struct.user_data); \ + } \ + \ + if(except_ret == H5T_CONV_UNHANDLED) { \ + /*let compiler convert if case is ignored by user handler*/ \ *((DT*)D) = (D_MAX); \ + } else if(except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ } else \ *((DT*)D) = (DT)(*((ST*)S)); \ } @@ -251,12 +292,28 @@ H5FL_BLK_DEFINE_STATIC(array_seq); #define H5T_CONV_Su_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ if (*((ST*)S) < 0) { \ - if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, S, D)<0) \ - *((DT*)D) = 0; \ + if(cb_struct.func) { /*If user's exception handler is present, use it*/ \ + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, \ + src_id, dst_id, S, D, cb_struct.user_data); \ + } \ + \ + if(except_ret == H5T_CONV_UNHANDLED) { \ + /*let compiler convert if case is ignored by user handler*/ \ + *((DT*)D) = 0; \ + } else if(except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ } else if (sizeof(ST)>sizeof(DT) && *((ST*)S)>(ST)(D_MAX)) { \ /*sign vs. unsign ok in previous line*/ \ - if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, S, D)<0) \ + if(cb_struct.func) { /*If user's exception handler is present, use it*/ \ + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, \ + src_id, dst_id, S, D, cb_struct.user_data); \ + } \ + \ + if(except_ret == H5T_CONV_UNHANDLED) { \ + /*let compiler convert if case is ignored by user handler*/ \ *((DT*)D) = (D_MAX); \ + } else if(except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ } else \ *((DT*)D) = (DT)(*((ST*)S)); \ } @@ -279,8 +336,16 @@ H5FL_BLK_DEFINE_STATIC(array_seq); #define H5T_CONV_su_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ /* Assumes memory format of unsigned & signed integers is same */ \ if (*((ST*)S)<0) { \ - if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, S, D)<0) \ - *((DT*)D) = 0; \ + if(cb_struct.func) { /*If user's exception handler is present, use it*/ \ + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, \ + src_id, dst_id, S, D, cb_struct.user_data); \ + } \ + \ + if(except_ret == H5T_CONV_UNHANDLED) { \ + /*let compiler convert if case is ignored by user handler*/ \ + *((DT*)D) = 0; \ + } else if(except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ } \ } @@ -292,8 +357,16 @@ H5FL_BLK_DEFINE_STATIC(array_seq); #define H5T_CONV_us_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ /* Assumes memory format of unsigned & signed integers is same */ \ if (*((ST*)S) > (D_MAX)) { \ - if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, S, D)<0) \ + if(cb_struct.func) { /*If user's exception handler is present, use it*/ \ + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, \ + src_id, dst_id, S, D, cb_struct.user_data); \ + } \ + \ + if(except_ret == H5T_CONV_UNHANDLED) { \ + /*let compiler convert if case is ignored by user handler*/ \ *((DT*)D) = (D_MAX); \ + } else if(except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ } \ } @@ -312,11 +385,27 @@ H5FL_BLK_DEFINE_STATIC(array_seq); */ #define H5T_CONV_Ff_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ if (*((ST*)S) > (DT)(D_MAX)) { \ - if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, S, D)<0) \ + if(cb_struct.func) { /*If user's exception handler is present, use it*/ \ + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, \ + src_id, dst_id, S, D, cb_struct.user_data); \ + } \ + \ + if(except_ret == H5T_CONV_UNHANDLED) { \ + /*let compiler convert if case is ignored by user handler*/ \ *((DT*)D) = (H5T_NATIVE_FLOAT_POS_INF_g); \ + } else if(except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ } else if (*((ST*)S) < (D_MIN)) { \ - if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, S, D)<0) \ + if(cb_struct.func) { /*If user's exception handler is present, use it*/ \ + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, \ + src_id, dst_id, S, D, cb_struct.user_data); \ + } \ + \ + if(except_ret == H5T_CONV_UNHANDLED) { \ + /*let compiler convert if case is ignored by user handler*/ \ *((DT*)D) = (H5T_NATIVE_FLOAT_NEG_INF_g); \ + } else if(except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ } else \ *((DT*)D) = (DT)(*((ST*)S)); \ } @@ -343,8 +432,11 @@ H5FL_BLK_DEFINE_STATIC(array_seq); ATYPE aligned; /*aligned type */ \ hbool_t s_mv, d_mv; /*move data to align it? */ \ ssize_t s_stride, d_stride; /*src and dst strides */ \ - size_t safe; /* How many elements are safe to process in each pass */ \ - \ + size_t safe; /*how many elements are safe to process in each pass */ \ + H5P_genplist_t *plist; /*Property list pointer */ \ + H5T_conv_cb_t cb_struct; /*conversion callback structure */ \ + H5T_conv_ret_t except_ret; /*callback return*/ \ + \ switch (cdata->command) { \ case H5T_CONV_INIT: \ /* Sanity check and initialize statistics */ \ @@ -386,7 +478,15 @@ H5FL_BLK_DEFINE_STATIC(array_seq); d_stride%H5T_NATIVE_##DTYPE##_ALIGN_g); \ CI_INC_SRC(s_mv) \ CI_INC_DST(d_mv) \ - \ + \ + /* Get the plist structure */ \ + if(NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER))) \ + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find property list for ID"); \ + \ + /* Get conversion exception callback property */ \ + if (H5P_get(plist,H5D_XFER_CONV_CB_NAME,&cb_struct)<0) \ + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get conversion exception callback"); \ + \ /* The outer loop of the type conversion macro, controlling which */ \ /* direction the buffer is walked */ \ while (nelmts>0) { \ @@ -417,7 +517,9 @@ H5FL_BLK_DEFINE_STATIC(array_seq); src = dst = buf; \ safe=nelmts; \ } /* end else */ \ - \ + \ + except_ret = H5T_CONV_UNHANDLED; \ + \ /* Perform loop over elements to convert */ \ if (s_mv && d_mv) { \ /* Alignment is required for both source and dest */ \ @@ -1122,7 +1224,7 @@ done: herr_t H5T_conv_b_b(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, size_t buf_stride, size_t UNUSED bkg_stride, void *_buf, - void UNUSED *background, hid_t UNUSED dxpl_id) + void UNUSED *background, hid_t dxpl_id) { uint8_t *buf = (uint8_t*)_buf; H5T_t *src=NULL, *dst=NULL; /*source and dest data types */ @@ -1134,7 +1236,12 @@ H5T_conv_b_b(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, uint8_t dbuf[256]; /*temp destination buffer */ size_t msb_pad_offset; /*offset for dest MSB padding */ size_t i; - herr_t ret_value=SUCCEED; /* Return value */ + uint8_t *src_rev; /*order-reversed source buffer */ + H5P_genplist_t *plist; /*property list pointer */ + H5T_conv_cb_t cb_struct={NULL, NULL}; /*conversion callback structure */ + H5T_conv_ret_t except_ret; /*return of callback function */ + hbool_t reverse; /*if reverse the order of destination */ + herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5T_conv_b_b, FAIL); @@ -1187,6 +1294,14 @@ H5T_conv_b_b(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, direction = -1; } + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find property list for ID"); + + /* Get conversion exception callback property */ + if (H5P_get(plist,H5D_XFER_CONV_CB_NAME,&cb_struct)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get conversion exception callback"); + /* The conversion loop */ for (elmtno=0; elmtno<nelmts; elmtno++) { @@ -1226,17 +1341,32 @@ H5T_conv_b_b(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, } } + /* Initiate these variables */ + except_ret = H5T_CONV_UNHANDLED; + reverse = TRUE; + /* * Copy the significant part of the value. If the source is larger * than the destination then invoke the overflow function or copy * as many bits as possible. Zero extra bits in the destination. */ if (src->u.atomic.prec>dst->u.atomic.prec) { - if (!H5T_overflow_g || - (H5T_overflow_g)(src_id, dst_id, s, d)<0) { + /*overflow*/ + if(cb_struct.func) { /*If user's exception handler is present, use it*/ + src_rev = H5T_reverse_order(s, src->size, src->u.atomic.order); /*reverse order first*/ + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, src_id, dst_id, + src_rev, d, cb_struct.user_data); + H5MM_free(src_rev); + } + + if(except_ret == H5T_CONV_UNHANDLED) { H5T_bit_copy(d, dst->u.atomic.offset, s, src->u.atomic.offset, dst->u.atomic.prec); - } + } else if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") + else if(except_ret == H5T_CONV_HANDLED) + /*Don't reverse because user handles it*/ + reverse = FALSE; } else { H5T_bit_copy(d, dst->u.atomic.offset, s, src->u.atomic.offset, @@ -1276,7 +1406,7 @@ H5T_conv_b_b(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, * Put the destination in the correct byte order. See note at * beginning of loop. */ - if (H5T_ORDER_BE==dst->u.atomic.order) { + if (H5T_ORDER_BE==dst->u.atomic.order && reverse) { half_size = dst->size/2; for (i=0; i<half_size; i++) { uint8_t tmp = d[dst->size-(i+1)]; @@ -2092,7 +2222,10 @@ H5T_conv_enum(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, int n; /*src value cast as native int */ hsize_t i; /*counters */ H5T_enum_struct_t *priv = (H5T_enum_struct_t*)(cdata->priv); - herr_t ret_value=SUCCEED; /* Return value */ + H5P_genplist_t *plist; /*property list pointer */ + H5T_conv_cb_t cb_struct; /*conversion callback structure */ + H5T_conv_ret_t except_ret; /*return of callback function */ + herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5T_conv_enum, FAIL); @@ -2158,7 +2291,15 @@ H5T_conv_enum(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, s = buf + (nelmts-1) * src->size; d = buf + (nelmts-1) * dst->size; } - + + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find property list for ID"); + + /* Get conversion exception callback property */ + if (H5P_get(plist,H5D_XFER_CONV_CB_NAME,&cb_struct)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get conversion exception callback"); + for (i=0; i<nelmts; i++, s+=src_delta, d+=dst_delta) { if (priv->length) { /* Use O(1) lookup */ @@ -2170,11 +2311,19 @@ H5T_conv_enum(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, n = *((int*)s); } n -= priv->base; + + except_ret = H5T_CONV_UNHANDLED; if (n<0 || n>=priv->length || priv->src2dst[n]<0) { - if (!H5T_overflow_g || - (H5T_overflow_g)(src_id, dst_id, s, d)<0) { - HDmemset(d, 0xff, dst->size); + /*overflow*/ + if(cb_struct.func) { /*If user's exception handler is present, use it*/ + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, src_id, dst_id, + s, d, cb_struct.user_data); } + + if(except_ret == H5T_CONV_UNHANDLED) { + HDmemset(d, 0xff, dst->size); + } else if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") } else { HDmemcpy(d, dst->u.enumer.value+priv->src2dst[n]*dst->size, @@ -2198,10 +2347,15 @@ H5T_conv_enum(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, } } if (lt>=rt) { - if (!H5T_overflow_g || - (H5T_overflow_g)(src_id, dst_id, s, d)<0) { - HDmemset(d, 0xff, dst->size); + if(cb_struct.func) { /*If user's exception handler is present, use it*/ + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, src_id, dst_id, + src, d, cb_struct.user_data); } + + if(except_ret == H5T_CONV_UNHANDLED) { + HDmemset(d, 0xff, dst->size); + } else if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") } else { HDmemcpy(d, dst->u.enumer.value+priv->src2dst[md]*dst->size, @@ -2721,12 +2875,17 @@ done: * then convert one value at each memory location advancing * BUF_STRIDE bytes each time; otherwise assume both source and * destination values are packed. + * + * Raymond Lu + * Wednesday, April 21, 2004 + * There is a new design for exception handling like overflow, + * which is passed in as a transfer property. *------------------------------------------------------------------------- */ herr_t H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, size_t buf_stride, size_t UNUSED bkg_stride, void *buf, - void UNUSED *bkg, hid_t UNUSED dxpl_id) + void UNUSED *bkg, hid_t dxpl_id) { H5T_t *src = NULL; /*source data type */ H5T_t *dst = NULL; /*destination data type */ @@ -2735,10 +2894,15 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, size_t half_size; /*half the type size */ hsize_t olap; /*num overlapping elements */ uint8_t *s, *sp, *d, *dp; /*source and dest traversal ptrs*/ + uint8_t *src_rev; /*order-reversed source buffer */ uint8_t dbuf[64]; /*temp destination buffer */ size_t first; ssize_t sfirst; /*a signed version of `first' */ - size_t i; /* Local index variables */ + size_t i; /*Local index variables */ + H5P_genplist_t *plist; /*property list pointer */ + H5T_conv_cb_t cb_struct={NULL, NULL}; /*conversion callback structure */ + H5T_conv_ret_t except_ret; /*return of callback function */ + hbool_t reverse; /*if reverse the order of destination */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5T_conv_i_i, FAIL); @@ -2793,6 +2957,14 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, direction = -1; } + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find property list for ID"); + + /* Get conversion exception callback property */ + if (H5P_get(plist,H5D_XFER_CONV_CB_NAME,&cb_struct)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get conversion exception callback"); + /* The conversion loop */ for (elmtno=0; elmtno<nelmts; elmtno++) { @@ -2838,6 +3010,10 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, H5T_BIT_MSB, TRUE); first = (size_t)sfirst; + /* Set these variables to default */ + except_ret = H5T_CONV_UNHANDLED; + reverse = TRUE; + if (sfirst<0) { /* * The source has no bits set and must therefore be zero. @@ -2860,9 +3036,20 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, dst->u.atomic.prec-src->u.atomic.prec, FALSE); } else if (first>=dst->u.atomic.prec) { /*overflow*/ - if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, s, d)<0) { - H5T_bit_set (d, dst->u.atomic.offset, dst->u.atomic.prec, TRUE); + if(cb_struct.func) { /*If user's exception handler is present, use it*/ + src_rev = H5T_reverse_order(s, src->size, src->u.atomic.order); /*reverse order first*/ + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, src_id, dst_id, + src_rev, d, cb_struct.user_data); + H5MM_free(src_rev); } + + if(except_ret == H5T_CONV_UNHANDLED) { + H5T_bit_set (d, dst->u.atomic.offset, dst->u.atomic.prec, TRUE); + } else if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") + else if(except_ret == H5T_CONV_HANDLED) + /*Don't reverse because user handles it already*/ + reverse = FALSE; } else { H5T_bit_copy (d, dst->u.atomic.offset, s, src->u.atomic.offset, dst->u.atomic.prec); @@ -2878,20 +3065,42 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, * (destination is set to zero). */ if (first+1 == src->u.atomic.prec) { - /*overflow*/ - if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, s, d)<0) { - H5T_bit_set (d, dst->u.atomic.offset, dst->u.atomic.prec, FALSE); + /*overflow - source is negative*/ + if(cb_struct.func) { /*If user's exception handler is present, use it*/ + src_rev = H5T_reverse_order(s, src->size, src->u.atomic.order); /*reverse order first*/ + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, src_id, dst_id, + src_rev, d, cb_struct.user_data); + H5MM_free(src_rev); } + + if(except_ret == H5T_CONV_UNHANDLED) { + H5T_bit_set (d, dst->u.atomic.offset, dst->u.atomic.prec, FALSE); + } else if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") + else if(except_ret == H5T_CONV_HANDLED) + /*Don't reverse because user handles it already*/ + reverse = FALSE; } else if (src->u.atomic.prec < dst->u.atomic.prec) { H5T_bit_copy (d, dst->u.atomic.offset, s, src->u.atomic.offset, src->u.atomic.prec-1); H5T_bit_set (d, dst->u.atomic.offset+src->u.atomic.prec-1, (dst->u.atomic.prec-src->u.atomic.prec)+1, FALSE); } else if (first>=dst->u.atomic.prec) { - /*overflow*/ - if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, s, d)<0) { - H5T_bit_set (d, dst->u.atomic.offset, dst->u.atomic.prec, TRUE); + /*overflow - source is positive*/ + if(cb_struct.func) { /*If user's exception handler is present, use it*/ + src_rev = H5T_reverse_order(s, src->size, src->u.atomic.order); /*reverse order first*/ + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, src_id, dst_id, + src_rev, d, cb_struct.user_data); + H5MM_free(src_rev); } + + if(except_ret == H5T_CONV_UNHANDLED) + H5T_bit_set (d, dst->u.atomic.offset, dst->u.atomic.prec, TRUE); + else if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") + else if(except_ret == H5T_CONV_HANDLED) + /*Don't reverse because user handles it already*/ + reverse = FALSE; } else { H5T_bit_copy (d, dst->u.atomic.offset, s, src->u.atomic.offset, dst->u.atomic.prec); @@ -2906,10 +3115,21 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, */ if (first+1 >= dst->u.atomic.prec) { /*overflow*/ - if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, s, d)<0) { + if(cb_struct.func) { /*If user's exception handler is present, use it*/ + src_rev = H5T_reverse_order(s, src->size, src->u.atomic.order); /*reverse order first*/ + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, src_id, dst_id, + src_rev, d, cb_struct.user_data); + H5MM_free(src_rev); + } + + if(except_ret == H5T_CONV_UNHANDLED) { H5T_bit_set (d, dst->u.atomic.offset, dst->u.atomic.prec-1, TRUE); H5T_bit_set (d, (dst->u.atomic.offset + dst->u.atomic.prec-1), 1, FALSE); - } + } else if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") + else if(except_ret == H5T_CONV_HANDLED) + /*Don't reverse because user handles it already*/ + reverse = FALSE; } else if (src->u.atomic.prec<dst->u.atomic.prec) { H5T_bit_copy (d, dst->u.atomic.offset, s, src->u.atomic.offset, src->u.atomic.prec); @@ -2919,7 +3139,6 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, H5T_bit_copy (d, dst->u.atomic.offset, s, src->u.atomic.offset, dst->u.atomic.prec); } - } else if (first+1 == src->u.atomic.prec) { /* * Both the source and the destination are signed and the @@ -2934,10 +3153,21 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, if (sfz>=0 && fz+1>=dst->u.atomic.prec) { /*overflow*/ - if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, s, d)<0) { + if(cb_struct.func) { /*If user's exception handler is present, use it*/ + src_rev = H5T_reverse_order(s, src->size, src->u.atomic.order); /*reverse order first*/ + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, src_id, dst_id, + src_rev, d, cb_struct.user_data); + H5MM_free(src_rev); + } + + if(except_ret == H5T_CONV_UNHANDLED) { H5T_bit_set (d, dst->u.atomic.offset, dst->u.atomic.prec-1, FALSE); H5T_bit_set (d, (dst->u.atomic.offset + dst->u.atomic.prec-1), 1, TRUE); - } + } else if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") + else if(except_ret == H5T_CONV_HANDLED) + /*Don't reverse because user handles it already*/ + reverse = FALSE; } else if (src->u.atomic.prec<dst->u.atomic.prec) { H5T_bit_copy (d, dst->u.atomic.offset, s, src->u.atomic.offset, src->u.atomic.prec); H5T_bit_set (d, dst->u.atomic.offset+src->u.atomic.prec, dst->u.atomic.prec-src->u.atomic.prec, TRUE); @@ -2954,10 +3184,21 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, */ if (first+1>=dst->u.atomic.prec) { /*overflow*/ - if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, s, d)<0) { + if(cb_struct.func) { /*If user's exception handler is present, use it*/ + src_rev = H5T_reverse_order(s, src->size, src->u.atomic.order); /*reverse order first*/ + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, src_id, dst_id, src_rev, d, + cb_struct.user_data); + H5MM_free(src_rev); + } + + if(except_ret == H5T_CONV_UNHANDLED) { H5T_bit_set (d, dst->u.atomic.offset, dst->u.atomic.prec-1, TRUE); H5T_bit_set (d, (dst->u.atomic.offset + dst->u.atomic.prec-1), 1, FALSE); - } + } else if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") + else if(except_ret == H5T_CONV_HANDLED) + /*Don't reverse because user handles it already*/ + reverse = FALSE; } else if (src->u.atomic.prec<dst->u.atomic.prec) { H5T_bit_copy (d, dst->u.atomic.offset, s, src->u.atomic.offset, src->u.atomic.prec); @@ -2987,7 +3228,7 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, * Put the destination in the correct byte order. See note at * beginning of loop. */ - if (H5T_ORDER_BE==dst->u.atomic.order) { + if (H5T_ORDER_BE==dst->u.atomic.order && reverse) { half_size = dst->size/2; for (i=0; i<half_size; i++) { uint8_t tmp = d[dst->size-(i+1)]; @@ -3053,19 +3294,20 @@ done: herr_t H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, size_t buf_stride, size_t UNUSED bkg_stride, void *buf, void UNUSED *bkg, - hid_t UNUSED dxpl_id) + hid_t dxpl_id) { /* Traversal-related variables */ H5T_t *src_p; /*source data type */ H5T_t *dst_p; /*destination data type */ H5T_atomic_t src; /*atomic source info */ H5T_atomic_t dst; /*atomic destination info */ - int direction; /*forward or backward traversal */ + int direction; /*forward or backward traversal */ hsize_t elmtno; /*element number */ size_t half_size; /*half the type size */ hsize_t olap; /*num overlapping elements */ ssize_t bitno; /*bit number */ uint8_t *s, *sp, *d, *dp; /*source and dest traversal ptrs*/ + uint8_t *src_rev; /*order-reversed source buffer */ uint8_t dbuf[64]; /*temp destination buffer */ /* Conversion-related variables */ @@ -3077,8 +3319,11 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, hbool_t carry=0; /*carry after rounding mantissa */ size_t i; /*miscellaneous counters */ hsize_t implied; /*destination implied bits */ - - herr_t ret_value=SUCCEED; /* Return value */ + H5P_genplist_t *plist; /*property list pointer */ + H5T_conv_cb_t cb_struct={NULL, NULL}; /*conversion callback structure */ + H5T_conv_ret_t except_ret; /*return of callback function */ + hbool_t reverse; /*if reverse the order of destination */ + herr_t ret_value=SUCCEED; /*return value */ FUNC_ENTER_NOAPI(H5T_conv_f_f, FAIL); @@ -3136,6 +3381,14 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, direction = -1; } + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find property list for ID"); + + /* Get conversion exception callback property */ + if (H5P_get(plist,H5D_XFER_CONV_CB_NAME,&cb_struct)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get conversion exception callback"); + /* The conversion loop */ for (elmtno=0; elmtno<nelmts; elmtno++) { /* @@ -3263,6 +3516,10 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, */ if (H5T_NORM_NONE==dst.u.f.norm) mrsh++; + + /* Set these variables to default */ + except_ret = H5T_CONV_UNHANDLED; + reverse = TRUE; /* * Calculate the destination exponent by adding the destination @@ -3296,25 +3553,24 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, * handler make sure the source buffer we hand it is in the * original byte order. */ - if (H5T_overflow_g) { - uint8_t over_src[256]; - assert(src_p->size<=sizeof over_src); - if (H5T_ORDER_BE==src.order) { - for (i=0; i<src_p->size; i++) { - over_src[src_p->size-(i+1)] = s[i]; - } - } else { - for (i=0; i<src_p->size; i++) { - over_src[i] = s[i]; - } - } - if ((H5T_overflow_g)(src_id, dst_id, over_src, d)>=0) { - goto next; - } + if(cb_struct.func) { /*If user's exception handler is present, use it*/ + src_rev = H5T_reverse_order(s, src_p->size, src.order); /*reverse order first*/ + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, src_id, dst_id, + src_rev, d, cb_struct.user_data); + H5MM_free(src_rev); + } + + if(except_ret == H5T_CONV_UNHANDLED) { + expo = expo_max; + H5T_bit_set(d, dst.u.f.mpos, dst.u.f.msize, FALSE); + msize = 0; + } else if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") + else if(except_ret == H5T_CONV_HANDLED) { + reverse = FALSE; + /*goto next;*/ + goto padding; } - expo = expo_max; - H5T_bit_set(d, dst.u.f.mpos, dst.u.f.msize, FALSE); - msize = 0; } /* @@ -3378,21 +3634,23 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, * calling the overflow handler make sure the source * buffer we hand it is in the original byte order. */ - if (H5T_overflow_g) { - uint8_t over_src[256]; - assert(src_p->size<=sizeof over_src); - if (H5T_ORDER_BE==src.order) { - for (i=0; i<src_p->size; i++) - over_src[src_p->size-(i+1)] = s[i]; - } else { - for (i=0; i<src_p->size; i++) - over_src[i] = s[i]; - } - if ((H5T_overflow_g)(src_id, dst_id, over_src, d)>=0) - goto next; + if(cb_struct.func) { /*If user's exception handler is present, use it*/ + src_rev = H5T_reverse_order(s, src_p->size, src.order); /*reverse order first*/ + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, src_id, dst_id, + src_rev, d, cb_struct.user_data); + H5MM_free(src_rev); + } + + if(except_ret == H5T_CONV_UNHANDLED) { + expo = expo_max; + H5T_bit_set(d, dst.u.f.mpos, dst.u.f.msize, FALSE); + } else if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") + else if(except_ret == H5T_CONV_HANDLED) { + reverse = FALSE; + /*goto next;*/ + goto padding; } - expo = expo_max; - H5T_bit_set(d, dst.u.f.mpos, dst.u.f.msize, FALSE); } } #endif /* OLD_WAY */ @@ -3423,7 +3681,7 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, * Put the destination in the correct byte order. See note at * beginning of loop. */ - if (H5T_ORDER_BE==dst.order) { + if (H5T_ORDER_BE==dst.order && reverse) { half_size = dst_p->size/2; for (i=0; i<half_size; i++) { uint8_t tmp = d[dst_p->size-(i+1)]; @@ -7966,7 +8224,7 @@ herr_t H5T_conv_double_ullong (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, size_t buf_stride, size_t UNUSED bkg_stride, void *buf, void UNUSED *bkg, - hid_t UNUSED dxpl_id) + hid_t dxpl_id) { herr_t ret_value=SUCCEED; /* Return value */ @@ -8383,25 +8641,31 @@ done: * Wednesday, Jan 21, 2004 * * Modifications: - * + * + * Raymond Lu + * Wednesday, April 21, 2004 + * There is a new design for exception handling like overflow, + * which is passed in as a transfer property. + * *------------------------------------------------------------------------- */ herr_t H5T_conv_f_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, size_t buf_stride, size_t UNUSED bkg_stride, void *buf, void UNUSED *bkg, - hid_t UNUSED dxpl_id) + hid_t dxpl_id) { /* Traversal-related variables */ H5T_t *src_p; /*source data type */ H5T_t *dst_p; /*destination data type */ H5T_atomic_t src; /*atomic source info */ H5T_atomic_t dst; /*atomic destination info */ - int direction; /*forward or backward traversal */ + int direction; /*forward or backward traversal */ hsize_t elmtno; /*element number */ size_t half_size; /*half the type size */ ssize_t bitno; /*bit number */ hsize_t olap; /*num overlapping elements */ uint8_t *s, *sp, *d, *dp; /*source and dest traversal ptrs*/ + uint8_t *src_rev; /*order-reversed source buffer */ uint8_t dbuf[64]; /*temp destination buffer */ /* Conversion-related variables */ @@ -8412,7 +8676,12 @@ H5T_conv_f_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, size_t i; /*miscellaneous counters */ size_t first; /*first bit(MSB) in an integer */ ssize_t sfirst; /*a signed version of `first' */ - herr_t ret_value=SUCCEED; /* Return value */ + H5P_genplist_t *plist; /*Property list pointer */ + H5T_conv_cb_t cb_struct={NULL, NULL}; /*conversion callback structure */ + hbool_t truncated; /*if fraction value is dropped */ + hbool_t reverse; /*if reverse order of destination at the end */ + H5T_conv_ret_t except_ret; /*return of callback function */ + herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5T_conv_f_i, FAIL); @@ -8473,6 +8742,14 @@ H5T_conv_f_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, buf_size = (size_t)HDpow((double)2.0, (double)src.u.f.esize) / 8 + 1; int_buf = (uint8_t*)H5MM_calloc(buf_size); + /* Get the plist structure. Do I need to close it? */ + if(NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find property list for ID"); + + /* Get conversion exception callback property */ + if (H5P_get(plist,H5D_XFER_CONV_CB_NAME,&cb_struct)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get conversion exception callback"); + /* The conversion loop */ for (elmtno=0; elmtno<nelmts; elmtno++) { /* @@ -8594,10 +8871,19 @@ H5T_conv_f_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, /* * Shift mantissa part by exponent minus mantissa size(right shift), - * or by mantissa size minus exponent(left shift). + * or by mantissa size minus exponent(left shift). Example: Sequence + * 10...010111, expo=20, expo-msize=-3. Right-shift the sequence, we get + * 00010...01. The last three ones were dropped. */ H5T_bit_shift(int_buf, (ssize_t)(expo-src.u.f.msize), 0, buf_size*8); + /* + * If expo is less than mantissa size, the frantional value is dropped off + * during conversion. Set exception type to be "truncate" + */ + if (expo < src.u.f.msize && cb_struct.func) + truncated = TRUE; + /* Convert to integer representation if negative. * equivalent to ~(value - 1). */ @@ -8612,48 +8898,144 @@ H5T_conv_f_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, */ sfirst = H5T_bit_find(int_buf, 0, 8*buf_size, H5T_BIT_MSB, TRUE); first = (size_t)sfirst; - + + /* Set these variables to default */ + except_ret = H5T_CONV_UNHANDLED; + truncated = FALSE; + reverse = TRUE; + if(sfirst < 0) { /* * The source has no bits set and must therefore be zero. * Set the destination to zero - nothing to do. */ - } else if (H5T_SGN_NONE==dst.u.i.sign) { + } else if (H5T_SGN_NONE==dst.u.i.sign) { /*destination is unsigned*/ /* - * Destination is unsigned. If the source value is greater - * than the maximal destination value then it overflows, the + * Destination is unsigned. Library's default way: If the source value + * is greater than the maximal destination value then it overflows, the * destination will be set to the maximum possible value. When the * source is negative, underflow happens. Set the destination to be - * zero. + * zero(do nothing). If user's exception handler is set, call it and + * let user handle it. */ - if(!sign) { + if(sign) { /*source is negative*/ + if(cb_struct.func) { /*If user's exception handler is present, use it*/ + src_rev = H5T_reverse_order(s, src_p->size, src.order); + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, + src_id, dst_id, src_rev, d, cb_struct.user_data); + if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") + else if(except_ret == H5T_CONV_HANDLED) + /*No need to reverse the order of destination because user handles it*/ + reverse = FALSE; + H5MM_free(src_rev); + } + } else { /*source is positive*/ if (first>=dst.prec) { /*overflow*/ - if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, s, d)<0) { - H5T_bit_set (d, dst.offset, dst.prec, TRUE); + if(cb_struct.func) { /*If user's exception handler is present, use it*/ + src_rev = H5T_reverse_order(s, src_p->size, src.order); + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, + src_id, dst_id, src_rev, d, cb_struct.user_data); + H5MM_free(src_rev); } + + if(except_ret == H5T_CONV_UNHANDLED) + H5T_bit_set (d, dst.offset, dst.prec, TRUE); + else if(except_ret == H5T_CONV_HANDLED) + /*No need to reverse the order of destination because user handles it*/ + reverse = FALSE; + else if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") } else if (first <dst.prec) { - /*copy source value into it*/ - H5T_bit_copy (d, dst.offset, int_buf, 0, first+1); + if(truncated && cb_struct.func) { /*If user's exception handler is present, use it*/ + src_rev = H5T_reverse_order(s, src_p->size, src.order); + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_TRUNCATE, + src_id, dst_id, src_rev, d, cb_struct.user_data); + H5MM_free(src_rev); + } + + if(except_ret == H5T_CONV_UNHANDLED) + /*copy source value into it if case is ignored by user handler*/ + H5T_bit_copy (d, dst.offset, int_buf, 0, first+1); + else if(except_ret == H5T_CONV_HANDLED) + /*No need to reverse the order of destination because user handles it*/ + reverse = FALSE; + else if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") } } - } else if (H5T_SGN_2==dst.u.i.sign) { - if(sign) { /*negative*/ - /* if overflows, do nothing except turn on the sign bit - * because 0x80...00 is the biggest negative value. - */ - if(first < dst.prec-1) - H5T_bit_copy (d, dst.offset, int_buf, 0, first+1); + } else if (H5T_SGN_2==dst.u.i.sign) { /*Destination is signed*/ + if(sign) { /*source is negative*/ + if(first < dst.prec-1) { + if(truncated && cb_struct.func) { /*If user's exception handler is present, use it*/ + src_rev = H5T_reverse_order(s, src_p->size, src.order); + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_TRUNCATE, + src_id, dst_id, src_rev, d, cb_struct.user_data); + H5MM_free(src_rev); + } + + if(except_ret == H5T_CONV_UNHANDLED) { + /*copy source value into it if case is ignored by user handler*/ + H5T_bit_copy (d, dst.offset, int_buf, 0, first+1); + H5T_bit_set (d, (dst.offset + dst.prec-1), 1, TRUE); + } else if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") + else if(except_ret == H5T_CONV_HANDLED) + /*No need to reverse the order of destination because user handles it*/ + reverse = FALSE; + } else { + /* if underflows and no callback, do nothing except turn on + * the sign bit because 0x80...00 is the biggest negative value. + */ + if(cb_struct.func) { /*If user's exception handler is present, use it*/ + src_rev = H5T_reverse_order(s, src_p->size, src.order); + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, + src_id, dst_id, src_rev, d, cb_struct.user_data); + H5MM_free(src_rev); + } - H5T_bit_set (d, (dst.offset + dst.prec-1), 1, TRUE); - } else { /*positive*/ + if(except_ret == H5T_CONV_UNHANDLED) + H5T_bit_set (d, (dst.offset + dst.prec-1), 1, TRUE); + else if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") + else if(except_ret == H5T_CONV_HANDLED) + /*No need to reverse the order of destination because user handles it*/ + reverse = FALSE; + } + } else { /*source is positive*/ if (first >= dst.prec-1) { /*overflow*/ - if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, s, d)<0) { - H5T_bit_set (d, dst.offset, dst.prec-1, TRUE); + if(cb_struct.func) { /*If user's exception handler is present, use it*/ + src_rev = H5T_reverse_order(s, src_p->size, src.order); + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, + src_id, dst_id, src_rev, d, cb_struct.user_data); + H5MM_free(src_rev); } + + if(except_ret == H5T_CONV_UNHANDLED) + H5T_bit_set (d, dst.offset, dst.prec-1, TRUE); + else if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") + else if(except_ret == H5T_CONV_HANDLED) + /*No need to reverse the order of destination because user handles it*/ + reverse = FALSE; } else if(first < dst.prec-1) { - H5T_bit_copy (d, dst.offset, int_buf, 0, first+1); + if(truncated && cb_struct.func) { /*If user's exception handler is present, use it*/ + src_rev = H5T_reverse_order(s, src_p->size, src.order); + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_TRUNCATE, + src_id, dst_id, src_rev, d, cb_struct.user_data); + H5MM_free(src_rev); + } + + if(except_ret == H5T_CONV_UNHANDLED) { + /*copy source value into it if case is ignored by user handler*/ + H5T_bit_copy (d, dst.offset, int_buf, 0, first+1); + } else if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") + else if(except_ret == H5T_CONV_HANDLED) + /*No need to reverse the order of destination because user handles it*/ + reverse = FALSE; } } } @@ -8677,7 +9059,7 @@ H5T_conv_f_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, * Put the destination in the correct byte order. See note at * beginning of loop. */ - if (H5T_ORDER_BE==dst.order) { + if (H5T_ORDER_BE==dst.order && reverse) { half_size = dst_p->size/2; for (i=0; i<half_size; i++) { uint8_t tmp = d[dst_p->size-(i+1)]; @@ -8730,12 +9112,17 @@ done: * * Modifications: * + * Raymond Lu + * Wednesday, April 21, 2004 + * There is a new design for exception handling like overflow, + * which is passed in as a transfer property. + * *------------------------------------------------------------------------- */ herr_t H5T_conv_i_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, size_t buf_stride, size_t UNUSED bkg_stride, void *buf, void UNUSED *bkg, - hid_t UNUSED dxpl_id) + hid_t dxpl_id) { /* Traversal-related variables */ H5T_t *src_p; /*source data type */ @@ -8747,6 +9134,7 @@ H5T_conv_i_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, size_t half_size; /*half the type size */ hsize_t olap; /*num overlapping elements */ uint8_t *s, *sp, *d, *dp; /*source and dest traversal ptrs*/ + uint8_t *src_rev; /*order-reversed source buffer */ uint8_t dbuf[64]; /*temp destination buffer */ /* Conversion-related variables */ @@ -8760,7 +9148,11 @@ H5T_conv_i_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, size_t i; /*miscellaneous counters */ size_t first; /*first bit(MSB) in an integer */ ssize_t sfirst; /*a signed version of `first' */ - herr_t ret_value=SUCCEED; /* Return value */ + H5P_genplist_t *plist; /*Property list pointer */ + H5T_conv_cb_t cb_struct={NULL, NULL}; /*conversion callback structure */ + H5T_conv_ret_t except_ret; /*return of callback function */ + hbool_t reverse; /*if reverse the order of destination */ + herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5T_conv_i_f, FAIL); @@ -8821,6 +9213,14 @@ H5T_conv_i_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, buf_size = (src.prec > dst.u.f.msize ? src.prec : dst.u.f.msize)/8 + 1; int_buf = (uint8_t*)H5MM_calloc(buf_size); + /* Get the plist structure */ + if(NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER))) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find property list for ID"); + + /* Get conversion exception callback property */ + if (H5P_get(plist,H5D_XFER_CONV_CB_NAME,&cb_struct)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get conversion exception callback"); + /* The conversion loop */ for (elmtno=0; elmtno<nelmts; elmtno++) { /* Make sure these variables are reset to 0. */ @@ -8902,7 +9302,7 @@ H5T_conv_i_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, H5T_bit_neg(int_buf, 0, buf_size*8); sfirst = H5T_bit_find(int_buf, 0, src.prec-1, H5T_BIT_MSB, TRUE); } else { - /* If it's maximal negative number 0x80...000, treat it as if it overflows + /* If it's maximal negative number 0x80...000, treat it as if it overflowed * (create a carry) to help conversion. i.e. a character type number 0x80 * is treated as 0x100. */ @@ -8920,7 +9320,11 @@ H5T_conv_i_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, } first = (size_t)sfirst; - + + /* Set these variables to default */ + except_ret = H5T_CONV_UNHANDLED; + reverse = TRUE; + /* * Calculate the true destination exponent by adjusting according to * the destination exponent bias. @@ -8944,7 +9348,21 @@ H5T_conv_i_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, /* Roundup for mantissa */ if(first > dst.u.f.msize) { - /* If the bit sequence is bigger than the mantissa part, we need to drop off the + /* If the bit sequence is bigger than the mantissa part, there'll be some + * precision loss. Let user's handler deal with the case if it's present + */ + if(cb_struct.func) { + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_PRECISION, src_id, dst_id, + s, d, cb_struct.user_data); + } + + if(except_ret == H5T_CONV_HANDLED) { + reverse = FALSE; + goto padding; + } else if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") + + /* If user's exception handler does deal with it, we do it by dropping off the * extra bits at the end and do rounding. If we have .50...0(decimal) after radix * point, we do roundup when the least significant digit before radix is odd, we do * rounddown if it's even. @@ -8996,15 +9414,36 @@ H5T_conv_i_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, /* Check if the exponent is too big */ - expo_max = (hsize_t)HDpow((double)2.0, (double)dst.u.f.esize) - 1; - if(expo > expo_max) - expo = expo_max; + expo_max = (hsize_t)HDpow((double)2.0, (double)dst.u.f.esize) - 1; + + if(expo > expo_max) { /*overflows*/ + if(cb_struct.func) { /*user's exception handler. Reverse back source order*/ + src_rev = H5T_reverse_order(s, src_p->size, src.order); + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, src_id, dst_id, + src_rev, d, cb_struct.user_data); + H5MM_free(src_rev); + + if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") + else if(except_ret == H5T_CONV_HANDLED) { + reverse = FALSE; + goto padding; + } + } else { + /*make destination infinity by setting exponent to maximal number and + *mantissa to zero.*/ + expo = expo_max; + HDmemset(int_buf, 0, buf_size); + } + } - /* Set exponent in destiny */ - H5T_bit_set_d(d, dst.u.f.epos, dst.u.f.esize, expo); + if(except_ret == H5T_CONV_UNHANDLED) { + /* Set exponent in destiny */ + H5T_bit_set_d(d, dst.u.f.epos, dst.u.f.esize, expo); - /* Copy mantissa into destiny */ - H5T_bit_copy(d, dst.u.f.mpos, int_buf, 0, buf_size*8 > dst.u.f.msize ? dst.u.f.msize : buf_size*8); + /* Copy mantissa into destiny */ + H5T_bit_copy(d, dst.u.f.mpos, int_buf, 0, buf_size*8 > dst.u.f.msize ? dst.u.f.msize : buf_size*8); + } padding: /* @@ -9025,7 +9464,7 @@ H5T_conv_i_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, * Put the destination in the correct byte order. See note at * beginning of loop. */ - if (H5T_ORDER_BE==dst.order) { + if (H5T_ORDER_BE==dst.order && reverse) { half_size = dst_p->size/2; for (i=0; i<half_size; i++) { uint8_t tmp = d[dst_p->size-(i+1)]; @@ -9062,3 +9501,48 @@ H5T_conv_i_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, done: FUNC_LEAVE_NOAPI(ret_value); } + + +/*------------------------------------------------------------------------- + * Function: H5T_reverse_order + * + * Purpose: Internal assisting function to reverse the order of + * a sequence of byte when it's big endian. The byte sequence + * simulates the endian order. + * + * Return: Success: A pointer to the reversed byte sequence + * + * Failure: Null + * + * Programmer: Raymond Lu + * April 26, 2004 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +uint8_t * +H5T_reverse_order(uint8_t *s, size_t size, H5T_order_t order) +{ + uint8_t *ret_value = NULL; + size_t i; + + FUNC_ENTER_NOAPI(H5T_reverse_order, NULL); + + assert(s); + assert(size); + + ret_value = H5MM_calloc(size); + assert(ret_value); + + if (H5T_ORDER_BE == order) { + for (i=0; i<size; i++) + ret_value[size-(i+1)] = s[i]; + } else { + for (i=0; i<size; i++) + ret_value[i] = s[i]; + } + +done: + FUNC_LEAVE_NOAPI(ret_value); +} diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h index 11a00c9..d22c733 100644 --- a/src/H5Tpkg.h +++ b/src/H5Tpkg.h @@ -235,9 +235,6 @@ typedef enum H5T_sdir_t { /* The native endianess of the platform */ H5_DLLVAR H5T_order_t H5T_native_order_g; -/* The overflow handler */ -H5_DLLVAR H5T_overflow_t H5T_overflow_g; - /* * Alignment information for native types. A value of N indicates that the * data must be aligned on an address ADDR such that 0 == ADDR mod N. When diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h index 6013ce5..fcd2f28 100644 --- a/src/H5Tprivate.h +++ b/src/H5Tprivate.h @@ -86,6 +86,7 @@ H5_DLL htri_t H5T_is_sensible(const H5T_t *dt); H5_DLL htri_t H5T_set_loc(H5T_t *dt, H5F_t *f, H5T_loc_t loc); H5_DLL htri_t H5T_committed(H5T_t *type); H5_DLL int H5T_link(const H5T_t *type, int adjust, hid_t dxpl_id); +H5_DLL uint8_t * H5T_reverse_order(uint8_t *s, size_t size, H5T_order_t order); /* Reference specific functions */ H5_DLL H5R_type_t H5T_get_ref_type(const H5T_t *dt); diff --git a/src/H5Tpublic.h b/src/H5Tpublic.h index 442407f..608606d 100644 --- a/src/H5Tpublic.h +++ b/src/H5Tpublic.h @@ -167,6 +167,21 @@ typedef enum H5T_direction_t { H5T_DIR_DESCEND = 2 /*in descendent order */ } H5T_direction_t; +/* The exception type passed into the conversion callback function */ +typedef enum H5T_conv_except_t { + H5T_CONV_EXCEPT_RANGE_HI = 0, /*source value is greater than destination's range */ + H5T_CONV_EXCEPT_RANGE_LOW = 1, /*source value is less than destination's range */ + H5T_CONV_EXCEPT_PRECISION = 2, /*source value loses precision in destination */ + H5T_CONV_EXCEPT_TRUNCATE = 3 /*source value is truncated in destination */ +} H5T_conv_except_t; + +/* The return value from conversion callback function H5T_conv_except_func_t */ +typedef enum H5T_conv_ret_t { + H5T_CONV_ABORT = -1, /*abort conversion */ + H5T_CONV_UNHANDLED = 0, /*callback function failed to handle the exception */ + H5T_CONV_HANDLED = 1 /*callback function handled the exception successfully */ +} H5T_conv_ret_t; + /* Variable Length Datatype struct in memory */ /* (This is only used for VL sequences, not VL strings, which are stored in char *'s) */ typedef struct { @@ -186,18 +201,17 @@ typedef herr_t (*H5T_conv_t) (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, size_t buf_stride, size_t bkg_stride, void *buf, void *bkg, hid_t dset_xfer_plist); -/* - * If an error occurs during a datatype conversion then the function - * registered with H5Tset_overflow() is called. It's arguments are the - * source and destination datatypes, a buffer which has the source value, - * and a buffer to receive an optional result for the overflow conversion. - * If the overflow handler chooses a value for the result it should return - * non-negative; otherwise the hdf5 library will choose an appropriate - * result. +/* Exception handler. If an exception like overflow happenes during conversion, + * this function is called if it's registered through H5Tset_type_conv_cb. */ -typedef herr_t (*H5T_overflow_t)(hid_t src_id, hid_t dst_id, - void *src_buf, void *dst_buf); +typedef H5T_conv_ret_t (*H5T_conv_except_func_t)(int except_type, hid_t src_id, + hid_t dst_id, void *src_buf, void *dst_buf, void *user_data); +/* Structure for conversion callback property */ +typedef struct H5T_conv_cb_t { + H5T_conv_except_func_t func; + void* user_data; +} H5T_conv_cb_t; /* When this header is included from H5Tprivate.h, don't make calls to H5open() */ #undef H5OPEN @@ -567,8 +581,6 @@ H5_DLL herr_t H5Tunregister(H5T_pers_t pers, const char *name, hid_t src_id, H5_DLL H5T_conv_t H5Tfind(hid_t src_id, hid_t dst_id, H5T_cdata_t **pcdata); H5_DLL herr_t H5Tconvert(hid_t src_id, hid_t dst_id, hsize_t nelmts, void *buf, void *background, hid_t plist_id); -H5_DLL H5T_overflow_t H5Tget_overflow(void); -H5_DLL herr_t H5Tset_overflow(H5T_overflow_t func); #ifdef __cplusplus } diff --git a/test/dtypes.c b/test/dtypes.c index 17fdc33..27b4874 100644 --- a/test/dtypes.c +++ b/test/dtypes.c @@ -171,6 +171,46 @@ overflow_handler(hid_t UNUSED src_id, hid_t UNUSED dst_id, /*------------------------------------------------------------------------- + * Function: except_func + * + * Purpose: Gets called for all data type conversion exceptions. + * + * Return: H5T_CONV_ABORT: -1 + * + * H5T_CONV_UNHANDLED 0 + * + * H5T_CONV_HANDLED 1 + * + * Programmer: Raymond Lu + * April 19, 2004 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static H5T_conv_ret_t +except_func(int except_type, hid_t src_id, hid_t dst_id, void *src_buf, + void *dst_buf, void *user_data) +{ + H5T_conv_ret_t ret = H5T_CONV_HANDLED; + + if(except_type == H5T_CONV_EXCEPT_RANGE_HI) + /*only test integer case*/ + *(int*)dst_buf = *(int*)user_data; + else if(except_type == H5T_CONV_EXCEPT_RANGE_LOW) + /*only test integer case*/ + *(int*)dst_buf = *(int*)user_data; + else if(except_type == H5T_CONV_EXCEPT_TRUNCATE) { + ret = H5T_CONV_UNHANDLED; + } else if(except_type == H5T_CONV_EXCEPT_PRECISION) { + ret = H5T_CONV_UNHANDLED; + } + + return ret; +} + + +/*------------------------------------------------------------------------- * Function: some_dummy_func * * Purpose: A dummy function to help check for overflow. @@ -3796,6 +3836,11 @@ test_conv_int_2(void) static int test_conv_int_float(const char *name, hid_t src, hid_t dst) { + hid_t dxpl_id; /*dataset transfer property list*/ + int fill_value=9; /*fill value for conversion exception*/ + H5T_conv_except_func_t op; /*returned callback function for conversion exception*/ + void *user_data; /*returned pointer to user data passed in to the callback*/ + hbool_t except_set = FALSE; /*whether user's exception handling is set*/ const size_t ntests=NTESTS; /*number of tests */ const size_t nelmts=NTESTELEM; /*num values per test */ const size_t max_fails=40; /*max number of failures*/ @@ -3974,6 +4019,31 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst) noverflows_g = 0; #endif + /* Create a dataset transfer property list and datatype conversion + * exception handler function and pass in fill value. This is mainly + * for NetCDF compatibility, which requests fill in fill value when + * conversion exception happens. We only test (unsigned) int - float + * and float - (unsigned) int conversions, which should cover more cases. + */ + if((dxpl_id = H5Pcreate(H5P_DATASET_XFER))<0) + goto error; + + if((src_type == INT_INT && dst_type == FLT_FLOAT) || + (src_type == INT_UINT && dst_type == FLT_FLOAT) || + (src_type == FLT_FLOAT && dst_type == INT_UINT) || + (src_type == FLT_FLOAT && dst_type == INT_INT)) { + if(H5Pset_type_conv_cb(dxpl_id, except_func, &fill_value)<0) + goto error; + else + except_set = TRUE; + + if(H5Pget_type_conv_cb(dxpl_id, &op, &user_data)<0) + goto error; + + if(op != except_func || *(int*)user_data != fill_value) + goto error; + } + /* The tests */ for (i=0; i<ntests; i++) { if (ntests>1) { @@ -3996,7 +4066,7 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst) buf[j] = saved[j] = HDrand(); /* Perform the conversion */ - if (H5Tconvert(src, dst, (hsize_t)nelmts, buf, NULL, H5P_DEFAULT)<0) + if (H5Tconvert(src, dst, (hsize_t)nelmts, buf, NULL, dxpl_id)<0) goto error; /* Check the results from the library against hardware */ @@ -4347,10 +4417,14 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst) for (k=0; k<dst_size; k++) dst_bits[dst_size-(k+1)] = buf[j*dst_size+ENDIAN(dst_size, k)]; - /* + /* Test library's default overflow handling: * Hardware usually doesn't handle overflows too gracefully. The * hardware conversion result during overflows is usually garbage * so we must handle those cases differetly when checking results. + * + * Test user's exception handler when overflows: + * Try to follow the except_func callback function to check if the + * desired value was set. */ if ((FLT_FLOAT==src_type || FLT_DOUBLE==src_type || FLT_LDOUBLE==src_type) && (INT_CHAR==dst_type || INT_SHORT==dst_type || INT_INT==dst_type @@ -4362,9 +4436,15 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst) * the destination. The destination should be set to the * maximum possible value: 0x7f...f */ - if (0==H5T_bit_get_d(dst_bits, dst_nbits-1, 1) && - H5T_bit_find(dst_bits, 0, dst_nbits-1, H5T_BIT_LSB, 0)<0) - continue; /*no error*/ + if(!except_set) { + if (0==H5T_bit_get_d(dst_bits, dst_nbits-1, 1) && + H5T_bit_find(dst_bits, 0, dst_nbits-1, H5T_BIT_LSB, 0)<0) + continue; /*no error*/ + } else { + /* fill_value is small so we know only the 1st byte is set */ + if (dst_bits[0] == fill_value) + continue; /*no error*/ + } } else if (1==H5T_bit_get_d(src_bits, src_nbits-1, 1) && overflows(src_bits, src_type, src_size, dst_nbits-1)) { /* @@ -4372,9 +4452,14 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst) * the destination. The destination should be set to the * smallest possible value: 0x80...0 */ - if (1==H5T_bit_get_d(dst_bits, dst_nbits-1, 1) && - H5T_bit_find(dst_bits, 0, dst_nbits-1, H5T_BIT_LSB, 1)<0) - continue; /*no error*/ + if(!except_set) { + if (1==H5T_bit_get_d(dst_bits, dst_nbits-1, 1) && + H5T_bit_find(dst_bits, 0, dst_nbits-1, H5T_BIT_LSB, 1)<0) + continue; /*no error*/ + } else { + if (dst_bits[0] == fill_value) + continue; /*no error*/ + } } } @@ -4387,16 +4472,26 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst) * The source is negative if the most significant bit is * set. The destination is zero if all bits are zero. */ - if (H5T_bit_find(dst_bits, 0, dst_nbits, H5T_BIT_LSB, 1)<0) - continue; /*no error*/ + if(!except_set) { + if (H5T_bit_find(dst_bits, 0, dst_nbits, H5T_BIT_LSB, 1)<0) + continue; /*no error*/ + } else { + if (dst_bits[0] == fill_value) + continue; /*no error*/ + } } else if (overflows(src_bits, src_type, src_size, dst_nbits)) { /* * The source is a value with a magnitude too large for * the destination. The destination should be the * largest possible value: 0xff...f */ - if (H5T_bit_find(dst_bits, 0, dst_nbits, H5T_BIT_LSB, 0)<0) - continue; /*no error*/ + if(!except_set) { + if (H5T_bit_find(dst_bits, 0, dst_nbits, H5T_BIT_LSB, 0)<0) + continue; /*no error*/ + } else { + if (dst_bits[0] == fill_value) + continue; /*no error*/ + } } } @@ -4610,10 +4705,13 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst) /*------------------------------------------------------------------------- * Function: overflows * - * Purpose: return the index of the most significant digit in a bit - * vector. + * Purpose: When convert from float or double to any integer type, + * check if overflow occurs. + * + * + * Return: TRUE: overflow happens * - * Return: index + * FALSE: no overflow * * Programmer: Raymond Lu * Monday, Nov 17, 2003 |