diff options
author | Raymond Lu <songyulu@hdfgroup.org> | 2004-04-27 19:16:54 (GMT) |
---|---|---|
committer | Raymond Lu <songyulu@hdfgroup.org> | 2004-04-27 19:16:54 (GMT) |
commit | b3d2f04490363a24f1d43581116a61356ca89f77 (patch) | |
tree | 71b91e09d8fe1e0475e2da5fe39f487c9db5eba9 /src/H5Tconv.c | |
parent | 85b599e9332c1d7d6f454425b66ad43e78954814 (diff) | |
download | hdf5-b3d2f04490363a24f1d43581116a61356ca89f77.zip hdf5-b3d2f04490363a24f1d43581116a61356ca89f77.tar.gz hdf5-b3d2f04490363a24f1d43581116a61356ca89f77.tar.bz2 |
[svn-r8424] *** empty log message ***
Diffstat (limited to 'src/H5Tconv.c')
-rw-r--r-- | src/H5Tconv.c | 748 |
1 files changed, 616 insertions, 132 deletions
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); +} |