From b3d2f04490363a24f1d43581116a61356ca89f77 Mon Sep 17 00:00:00 2001 From: Raymond Lu Date: Tue, 27 Apr 2004 14:16:54 -0500 Subject: [svn-r8424] *** empty log message *** --- release_docs/RELEASE.txt | 4 + src/H5D.c | 6 + src/H5Dprivate.h | 4 + src/H5Pdxpl.c | 85 ++++++ src/H5Ppublic.h | 4 +- src/H5T.c | 75 ----- src/H5Tcompound.c | 3 +- src/H5Tconv.c | 748 ++++++++++++++++++++++++++++++++++++++--------- src/H5Tpkg.h | 3 - src/H5Tprivate.h | 1 + src/H5Tpublic.h | 36 ++- 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 diff --git a/src/H5D.c b/src/H5D.c index f350867..2fb268f 100644 --- a/src/H5D.c +++ b/src/H5D.c @@ -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 } diff --git a/src/H5T.c b/src/H5T.c index fa73518..174d1c1 100644 --- a/src/H5T.c +++ b/src/H5T.c @@ -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; elmtnou.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; isize-(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; ilength) { /* 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; elmtnou.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.precu.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.precu.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.precu.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; isize-(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; elmtnosize<=sizeof over_src); - if (H5T_ORDER_BE==src.order) { - for (i=0; isize; i++) { - over_src[src_p->size-(i+1)] = s[i]; - } - } else { - for (i=0; isize; 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; isize; i++) - over_src[src_p->size-(i+1)] = s[i]; - } else { - for (i=0; isize; 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; isize-(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; elmtnosize, 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 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; isize-(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 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; isize-(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; i1) { @@ -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