summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--release_docs/RELEASE.txt4
-rw-r--r--src/H5D.c6
-rw-r--r--src/H5Dprivate.h4
-rw-r--r--src/H5Pdxpl.c85
-rw-r--r--src/H5Ppublic.h4
-rw-r--r--src/H5T.c75
-rw-r--r--src/H5Tcompound.c3
-rw-r--r--src/H5Tconv.c748
-rw-r--r--src/H5Tpkg.h3
-rw-r--r--src/H5Tprivate.h1
-rw-r--r--src/H5Tpublic.h36
-rw-r--r--test/dtypes.c128
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; elmtno<nelmts; elmtno++) {
@@ -1226,17 +1341,32 @@ H5T_conv_b_b(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
}
}
+ /* Initiate these variables */
+ except_ret = H5T_CONV_UNHANDLED;
+ reverse = TRUE;
+
/*
* Copy the significant part of the value. If the source is larger
* than the destination then invoke the overflow function or copy
* as many bits as possible. Zero extra bits in the destination.
*/
if (src->u.atomic.prec>dst->u.atomic.prec) {
- if (!H5T_overflow_g ||
- (H5T_overflow_g)(src_id, dst_id, s, d)<0) {
+ /*overflow*/
+ if(cb_struct.func) { /*If user's exception handler is present, use it*/
+ src_rev = H5T_reverse_order(s, src->size, src->u.atomic.order); /*reverse order first*/
+ except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, src_id, dst_id,
+ src_rev, d, cb_struct.user_data);
+ H5MM_free(src_rev);
+ }
+
+ if(except_ret == H5T_CONV_UNHANDLED) {
H5T_bit_copy(d, dst->u.atomic.offset,
s, src->u.atomic.offset, dst->u.atomic.prec);
- }
+ } else if(except_ret == H5T_CONV_ABORT)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception")
+ else if(except_ret == H5T_CONV_HANDLED)
+ /*Don't reverse because user handles it*/
+ reverse = FALSE;
} else {
H5T_bit_copy(d, dst->u.atomic.offset,
s, src->u.atomic.offset,
@@ -1276,7 +1406,7 @@ H5T_conv_b_b(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
* Put the destination in the correct byte order. See note at
* beginning of loop.
*/
- if (H5T_ORDER_BE==dst->u.atomic.order) {
+ if (H5T_ORDER_BE==dst->u.atomic.order && reverse) {
half_size = dst->size/2;
for (i=0; i<half_size; i++) {
uint8_t tmp = d[dst->size-(i+1)];
@@ -2092,7 +2222,10 @@ H5T_conv_enum(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
int n; /*src value cast as native int */
hsize_t i; /*counters */
H5T_enum_struct_t *priv = (H5T_enum_struct_t*)(cdata->priv);
- herr_t ret_value=SUCCEED; /* Return value */
+ H5P_genplist_t *plist; /*property list pointer */
+ H5T_conv_cb_t cb_struct; /*conversion callback structure */
+ H5T_conv_ret_t except_ret; /*return of callback function */
+ herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5T_conv_enum, FAIL);
@@ -2158,7 +2291,15 @@ H5T_conv_enum(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
s = buf + (nelmts-1) * src->size;
d = buf + (nelmts-1) * dst->size;
}
-
+
+ /* Get the plist structure */
+ if(NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find property list for ID");
+
+ /* Get conversion exception callback property */
+ if (H5P_get(plist,H5D_XFER_CONV_CB_NAME,&cb_struct)<0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get conversion exception callback");
+
for (i=0; i<nelmts; i++, s+=src_delta, d+=dst_delta) {
if (priv->length) {
/* Use O(1) lookup */
@@ -2170,11 +2311,19 @@ H5T_conv_enum(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
n = *((int*)s);
}
n -= priv->base;
+
+ except_ret = H5T_CONV_UNHANDLED;
if (n<0 || n>=priv->length || priv->src2dst[n]<0) {
- if (!H5T_overflow_g ||
- (H5T_overflow_g)(src_id, dst_id, s, d)<0) {
- HDmemset(d, 0xff, dst->size);
+ /*overflow*/
+ if(cb_struct.func) { /*If user's exception handler is present, use it*/
+ except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, src_id, dst_id,
+ s, d, cb_struct.user_data);
}
+
+ if(except_ret == H5T_CONV_UNHANDLED) {
+ HDmemset(d, 0xff, dst->size);
+ } else if(except_ret == H5T_CONV_ABORT)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception")
} else {
HDmemcpy(d,
dst->u.enumer.value+priv->src2dst[n]*dst->size,
@@ -2198,10 +2347,15 @@ H5T_conv_enum(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
}
}
if (lt>=rt) {
- if (!H5T_overflow_g ||
- (H5T_overflow_g)(src_id, dst_id, s, d)<0) {
- HDmemset(d, 0xff, dst->size);
+ if(cb_struct.func) { /*If user's exception handler is present, use it*/
+ except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, src_id, dst_id,
+ src, d, cb_struct.user_data);
}
+
+ if(except_ret == H5T_CONV_UNHANDLED) {
+ HDmemset(d, 0xff, dst->size);
+ } else if(except_ret == H5T_CONV_ABORT)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception")
} else {
HDmemcpy(d,
dst->u.enumer.value+priv->src2dst[md]*dst->size,
@@ -2721,12 +2875,17 @@ done:
* then convert one value at each memory location advancing
* BUF_STRIDE bytes each time; otherwise assume both source and
* destination values are packed.
+ *
+ * Raymond Lu
+ * Wednesday, April 21, 2004
+ * There is a new design for exception handling like overflow,
+ * which is passed in as a transfer property.
*-------------------------------------------------------------------------
*/
herr_t
H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
size_t buf_stride, size_t UNUSED bkg_stride, void *buf,
- void UNUSED *bkg, hid_t UNUSED dxpl_id)
+ void UNUSED *bkg, hid_t dxpl_id)
{
H5T_t *src = NULL; /*source data type */
H5T_t *dst = NULL; /*destination data type */
@@ -2735,10 +2894,15 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
size_t half_size; /*half the type size */
hsize_t olap; /*num overlapping elements */
uint8_t *s, *sp, *d, *dp; /*source and dest traversal ptrs*/
+ uint8_t *src_rev; /*order-reversed source buffer */
uint8_t dbuf[64]; /*temp destination buffer */
size_t first;
ssize_t sfirst; /*a signed version of `first' */
- size_t i; /* Local index variables */
+ size_t i; /*Local index variables */
+ H5P_genplist_t *plist; /*property list pointer */
+ H5T_conv_cb_t cb_struct={NULL, NULL}; /*conversion callback structure */
+ H5T_conv_ret_t except_ret; /*return of callback function */
+ hbool_t reverse; /*if reverse the order of destination */
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5T_conv_i_i, FAIL);
@@ -2793,6 +2957,14 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
direction = -1;
}
+ /* Get the plist structure */
+ if(NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find property list for ID");
+
+ /* Get conversion exception callback property */
+ if (H5P_get(plist,H5D_XFER_CONV_CB_NAME,&cb_struct)<0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get conversion exception callback");
+
/* The conversion loop */
for (elmtno=0; elmtno<nelmts; elmtno++) {
@@ -2838,6 +3010,10 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
H5T_BIT_MSB, TRUE);
first = (size_t)sfirst;
+ /* Set these variables to default */
+ except_ret = H5T_CONV_UNHANDLED;
+ reverse = TRUE;
+
if (sfirst<0) {
/*
* The source has no bits set and must therefore be zero.
@@ -2860,9 +3036,20 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
dst->u.atomic.prec-src->u.atomic.prec, FALSE);
} else if (first>=dst->u.atomic.prec) {
/*overflow*/
- if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, s, d)<0) {
- H5T_bit_set (d, dst->u.atomic.offset, dst->u.atomic.prec, TRUE);
+ if(cb_struct.func) { /*If user's exception handler is present, use it*/
+ src_rev = H5T_reverse_order(s, src->size, src->u.atomic.order); /*reverse order first*/
+ except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, src_id, dst_id,
+ src_rev, d, cb_struct.user_data);
+ H5MM_free(src_rev);
}
+
+ if(except_ret == H5T_CONV_UNHANDLED) {
+ H5T_bit_set (d, dst->u.atomic.offset, dst->u.atomic.prec, TRUE);
+ } else if(except_ret == H5T_CONV_ABORT)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception")
+ else if(except_ret == H5T_CONV_HANDLED)
+ /*Don't reverse because user handles it already*/
+ reverse = FALSE;
} else {
H5T_bit_copy (d, dst->u.atomic.offset, s, src->u.atomic.offset,
dst->u.atomic.prec);
@@ -2878,20 +3065,42 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
* (destination is set to zero).
*/
if (first+1 == src->u.atomic.prec) {
- /*overflow*/
- if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, s, d)<0) {
- H5T_bit_set (d, dst->u.atomic.offset, dst->u.atomic.prec, FALSE);
+ /*overflow - source is negative*/
+ if(cb_struct.func) { /*If user's exception handler is present, use it*/
+ src_rev = H5T_reverse_order(s, src->size, src->u.atomic.order); /*reverse order first*/
+ except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, src_id, dst_id,
+ src_rev, d, cb_struct.user_data);
+ H5MM_free(src_rev);
}
+
+ if(except_ret == H5T_CONV_UNHANDLED) {
+ H5T_bit_set (d, dst->u.atomic.offset, dst->u.atomic.prec, FALSE);
+ } else if(except_ret == H5T_CONV_ABORT)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception")
+ else if(except_ret == H5T_CONV_HANDLED)
+ /*Don't reverse because user handles it already*/
+ reverse = FALSE;
} else if (src->u.atomic.prec < dst->u.atomic.prec) {
H5T_bit_copy (d, dst->u.atomic.offset, s, src->u.atomic.offset,
src->u.atomic.prec-1);
H5T_bit_set (d, dst->u.atomic.offset+src->u.atomic.prec-1,
(dst->u.atomic.prec-src->u.atomic.prec)+1, FALSE);
} else if (first>=dst->u.atomic.prec) {
- /*overflow*/
- if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, s, d)<0) {
- H5T_bit_set (d, dst->u.atomic.offset, dst->u.atomic.prec, TRUE);
+ /*overflow - source is positive*/
+ if(cb_struct.func) { /*If user's exception handler is present, use it*/
+ src_rev = H5T_reverse_order(s, src->size, src->u.atomic.order); /*reverse order first*/
+ except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, src_id, dst_id,
+ src_rev, d, cb_struct.user_data);
+ H5MM_free(src_rev);
}
+
+ if(except_ret == H5T_CONV_UNHANDLED)
+ H5T_bit_set (d, dst->u.atomic.offset, dst->u.atomic.prec, TRUE);
+ else if(except_ret == H5T_CONV_ABORT)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception")
+ else if(except_ret == H5T_CONV_HANDLED)
+ /*Don't reverse because user handles it already*/
+ reverse = FALSE;
} else {
H5T_bit_copy (d, dst->u.atomic.offset, s, src->u.atomic.offset,
dst->u.atomic.prec);
@@ -2906,10 +3115,21 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
*/
if (first+1 >= dst->u.atomic.prec) {
/*overflow*/
- if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, s, d)<0) {
+ if(cb_struct.func) { /*If user's exception handler is present, use it*/
+ src_rev = H5T_reverse_order(s, src->size, src->u.atomic.order); /*reverse order first*/
+ except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, src_id, dst_id,
+ src_rev, d, cb_struct.user_data);
+ H5MM_free(src_rev);
+ }
+
+ if(except_ret == H5T_CONV_UNHANDLED) {
H5T_bit_set (d, dst->u.atomic.offset, dst->u.atomic.prec-1, TRUE);
H5T_bit_set (d, (dst->u.atomic.offset + dst->u.atomic.prec-1), 1, FALSE);
- }
+ } else if(except_ret == H5T_CONV_ABORT)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception")
+ else if(except_ret == H5T_CONV_HANDLED)
+ /*Don't reverse because user handles it already*/
+ reverse = FALSE;
} else if (src->u.atomic.prec<dst->u.atomic.prec) {
H5T_bit_copy (d, dst->u.atomic.offset, s, src->u.atomic.offset,
src->u.atomic.prec);
@@ -2919,7 +3139,6 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
H5T_bit_copy (d, dst->u.atomic.offset, s, src->u.atomic.offset,
dst->u.atomic.prec);
}
-
} else if (first+1 == src->u.atomic.prec) {
/*
* Both the source and the destination are signed and the
@@ -2934,10 +3153,21 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
if (sfz>=0 && fz+1>=dst->u.atomic.prec) {
/*overflow*/
- if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, s, d)<0) {
+ if(cb_struct.func) { /*If user's exception handler is present, use it*/
+ src_rev = H5T_reverse_order(s, src->size, src->u.atomic.order); /*reverse order first*/
+ except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, src_id, dst_id,
+ src_rev, d, cb_struct.user_data);
+ H5MM_free(src_rev);
+ }
+
+ if(except_ret == H5T_CONV_UNHANDLED) {
H5T_bit_set (d, dst->u.atomic.offset, dst->u.atomic.prec-1, FALSE);
H5T_bit_set (d, (dst->u.atomic.offset + dst->u.atomic.prec-1), 1, TRUE);
- }
+ } else if(except_ret == H5T_CONV_ABORT)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception")
+ else if(except_ret == H5T_CONV_HANDLED)
+ /*Don't reverse because user handles it already*/
+ reverse = FALSE;
} else if (src->u.atomic.prec<dst->u.atomic.prec) {
H5T_bit_copy (d, dst->u.atomic.offset, s, src->u.atomic.offset, src->u.atomic.prec);
H5T_bit_set (d, dst->u.atomic.offset+src->u.atomic.prec, dst->u.atomic.prec-src->u.atomic.prec, TRUE);
@@ -2954,10 +3184,21 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
*/
if (first+1>=dst->u.atomic.prec) {
/*overflow*/
- if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, s, d)<0) {
+ if(cb_struct.func) { /*If user's exception handler is present, use it*/
+ src_rev = H5T_reverse_order(s, src->size, src->u.atomic.order); /*reverse order first*/
+ except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, src_id, dst_id, src_rev, d,
+ cb_struct.user_data);
+ H5MM_free(src_rev);
+ }
+
+ if(except_ret == H5T_CONV_UNHANDLED) {
H5T_bit_set (d, dst->u.atomic.offset, dst->u.atomic.prec-1, TRUE);
H5T_bit_set (d, (dst->u.atomic.offset + dst->u.atomic.prec-1), 1, FALSE);
- }
+ } else if(except_ret == H5T_CONV_ABORT)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception")
+ else if(except_ret == H5T_CONV_HANDLED)
+ /*Don't reverse because user handles it already*/
+ reverse = FALSE;
} else if (src->u.atomic.prec<dst->u.atomic.prec) {
H5T_bit_copy (d, dst->u.atomic.offset, s, src->u.atomic.offset,
src->u.atomic.prec);
@@ -2987,7 +3228,7 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
* Put the destination in the correct byte order. See note at
* beginning of loop.
*/
- if (H5T_ORDER_BE==dst->u.atomic.order) {
+ if (H5T_ORDER_BE==dst->u.atomic.order && reverse) {
half_size = dst->size/2;
for (i=0; i<half_size; i++) {
uint8_t tmp = d[dst->size-(i+1)];
@@ -3053,19 +3294,20 @@ done:
herr_t
H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
size_t buf_stride, size_t UNUSED bkg_stride, void *buf, void UNUSED *bkg,
- hid_t UNUSED dxpl_id)
+ hid_t dxpl_id)
{
/* Traversal-related variables */
H5T_t *src_p; /*source data type */
H5T_t *dst_p; /*destination data type */
H5T_atomic_t src; /*atomic source info */
H5T_atomic_t dst; /*atomic destination info */
- int direction; /*forward or backward traversal */
+ int direction; /*forward or backward traversal */
hsize_t elmtno; /*element number */
size_t half_size; /*half the type size */
hsize_t olap; /*num overlapping elements */
ssize_t bitno; /*bit number */
uint8_t *s, *sp, *d, *dp; /*source and dest traversal ptrs*/
+ uint8_t *src_rev; /*order-reversed source buffer */
uint8_t dbuf[64]; /*temp destination buffer */
/* Conversion-related variables */
@@ -3077,8 +3319,11 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
hbool_t carry=0; /*carry after rounding mantissa */
size_t i; /*miscellaneous counters */
hsize_t implied; /*destination implied bits */
-
- herr_t ret_value=SUCCEED; /* Return value */
+ H5P_genplist_t *plist; /*property list pointer */
+ H5T_conv_cb_t cb_struct={NULL, NULL}; /*conversion callback structure */
+ H5T_conv_ret_t except_ret; /*return of callback function */
+ hbool_t reverse; /*if reverse the order of destination */
+ herr_t ret_value=SUCCEED; /*return value */
FUNC_ENTER_NOAPI(H5T_conv_f_f, FAIL);
@@ -3136,6 +3381,14 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
direction = -1;
}
+ /* Get the plist structure */
+ if(NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find property list for ID");
+
+ /* Get conversion exception callback property */
+ if (H5P_get(plist,H5D_XFER_CONV_CB_NAME,&cb_struct)<0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get conversion exception callback");
+
/* The conversion loop */
for (elmtno=0; elmtno<nelmts; elmtno++) {
/*
@@ -3263,6 +3516,10 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
*/
if (H5T_NORM_NONE==dst.u.f.norm)
mrsh++;
+
+ /* Set these variables to default */
+ except_ret = H5T_CONV_UNHANDLED;
+ reverse = TRUE;
/*
* Calculate the destination exponent by adding the destination
@@ -3296,25 +3553,24 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
* handler make sure the source buffer we hand it is in the
* original byte order.
*/
- if (H5T_overflow_g) {
- uint8_t over_src[256];
- assert(src_p->size<=sizeof over_src);
- if (H5T_ORDER_BE==src.order) {
- for (i=0; i<src_p->size; i++) {
- over_src[src_p->size-(i+1)] = s[i];
- }
- } else {
- for (i=0; i<src_p->size; i++) {
- over_src[i] = s[i];
- }
- }
- if ((H5T_overflow_g)(src_id, dst_id, over_src, d)>=0) {
- goto next;
- }
+ if(cb_struct.func) { /*If user's exception handler is present, use it*/
+ src_rev = H5T_reverse_order(s, src_p->size, src.order); /*reverse order first*/
+ except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, src_id, dst_id,
+ src_rev, d, cb_struct.user_data);
+ H5MM_free(src_rev);
+ }
+
+ if(except_ret == H5T_CONV_UNHANDLED) {
+ expo = expo_max;
+ H5T_bit_set(d, dst.u.f.mpos, dst.u.f.msize, FALSE);
+ msize = 0;
+ } else if(except_ret == H5T_CONV_ABORT)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception")
+ else if(except_ret == H5T_CONV_HANDLED) {
+ reverse = FALSE;
+ /*goto next;*/
+ goto padding;
}
- expo = expo_max;
- H5T_bit_set(d, dst.u.f.mpos, dst.u.f.msize, FALSE);
- msize = 0;
}
/*
@@ -3378,21 +3634,23 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
* calling the overflow handler make sure the source
* buffer we hand it is in the original byte order.
*/
- if (H5T_overflow_g) {
- uint8_t over_src[256];
- assert(src_p->size<=sizeof over_src);
- if (H5T_ORDER_BE==src.order) {
- for (i=0; i<src_p->size; i++)
- over_src[src_p->size-(i+1)] = s[i];
- } else {
- for (i=0; i<src_p->size; i++)
- over_src[i] = s[i];
- }
- if ((H5T_overflow_g)(src_id, dst_id, over_src, d)>=0)
- goto next;
+ if(cb_struct.func) { /*If user's exception handler is present, use it*/
+ src_rev = H5T_reverse_order(s, src_p->size, src.order); /*reverse order first*/
+ except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, src_id, dst_id,
+ src_rev, d, cb_struct.user_data);
+ H5MM_free(src_rev);
+ }
+
+ if(except_ret == H5T_CONV_UNHANDLED) {
+ expo = expo_max;
+ H5T_bit_set(d, dst.u.f.mpos, dst.u.f.msize, FALSE);
+ } else if(except_ret == H5T_CONV_ABORT)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception")
+ else if(except_ret == H5T_CONV_HANDLED) {
+ reverse = FALSE;
+ /*goto next;*/
+ goto padding;
}
- expo = expo_max;
- H5T_bit_set(d, dst.u.f.mpos, dst.u.f.msize, FALSE);
}
}
#endif /* OLD_WAY */
@@ -3423,7 +3681,7 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
* Put the destination in the correct byte order. See note at
* beginning of loop.
*/
- if (H5T_ORDER_BE==dst.order) {
+ if (H5T_ORDER_BE==dst.order && reverse) {
half_size = dst_p->size/2;
for (i=0; i<half_size; i++) {
uint8_t tmp = d[dst_p->size-(i+1)];
@@ -7966,7 +8224,7 @@ herr_t
H5T_conv_double_ullong (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
hsize_t nelmts, size_t buf_stride,
size_t UNUSED bkg_stride, void *buf, void UNUSED *bkg,
- hid_t UNUSED dxpl_id)
+ hid_t dxpl_id)
{
herr_t ret_value=SUCCEED; /* Return value */
@@ -8383,25 +8641,31 @@ done:
* Wednesday, Jan 21, 2004
*
* Modifications:
- *
+ *
+ * Raymond Lu
+ * Wednesday, April 21, 2004
+ * There is a new design for exception handling like overflow,
+ * which is passed in as a transfer property.
+ *
*-------------------------------------------------------------------------
*/
herr_t
H5T_conv_f_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
size_t buf_stride, size_t UNUSED bkg_stride, void *buf, void UNUSED *bkg,
- hid_t UNUSED dxpl_id)
+ hid_t dxpl_id)
{
/* Traversal-related variables */
H5T_t *src_p; /*source data type */
H5T_t *dst_p; /*destination data type */
H5T_atomic_t src; /*atomic source info */
H5T_atomic_t dst; /*atomic destination info */
- int direction; /*forward or backward traversal */
+ int direction; /*forward or backward traversal */
hsize_t elmtno; /*element number */
size_t half_size; /*half the type size */
ssize_t bitno; /*bit number */
hsize_t olap; /*num overlapping elements */
uint8_t *s, *sp, *d, *dp; /*source and dest traversal ptrs*/
+ uint8_t *src_rev; /*order-reversed source buffer */
uint8_t dbuf[64]; /*temp destination buffer */
/* Conversion-related variables */
@@ -8412,7 +8676,12 @@ H5T_conv_f_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
size_t i; /*miscellaneous counters */
size_t first; /*first bit(MSB) in an integer */
ssize_t sfirst; /*a signed version of `first' */
- herr_t ret_value=SUCCEED; /* Return value */
+ H5P_genplist_t *plist; /*Property list pointer */
+ H5T_conv_cb_t cb_struct={NULL, NULL}; /*conversion callback structure */
+ hbool_t truncated; /*if fraction value is dropped */
+ hbool_t reverse; /*if reverse order of destination at the end */
+ H5T_conv_ret_t except_ret; /*return of callback function */
+ herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5T_conv_f_i, FAIL);
@@ -8473,6 +8742,14 @@ H5T_conv_f_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
buf_size = (size_t)HDpow((double)2.0, (double)src.u.f.esize) / 8 + 1;
int_buf = (uint8_t*)H5MM_calloc(buf_size);
+ /* Get the plist structure. Do I need to close it? */
+ if(NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find property list for ID");
+
+ /* Get conversion exception callback property */
+ if (H5P_get(plist,H5D_XFER_CONV_CB_NAME,&cb_struct)<0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get conversion exception callback");
+
/* The conversion loop */
for (elmtno=0; elmtno<nelmts; elmtno++) {
/*
@@ -8594,10 +8871,19 @@ H5T_conv_f_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
/*
* Shift mantissa part by exponent minus mantissa size(right shift),
- * or by mantissa size minus exponent(left shift).
+ * or by mantissa size minus exponent(left shift). Example: Sequence
+ * 10...010111, expo=20, expo-msize=-3. Right-shift the sequence, we get
+ * 00010...01. The last three ones were dropped.
*/
H5T_bit_shift(int_buf, (ssize_t)(expo-src.u.f.msize), 0, buf_size*8);
+ /*
+ * If expo is less than mantissa size, the frantional value is dropped off
+ * during conversion. Set exception type to be "truncate"
+ */
+ if (expo < src.u.f.msize && cb_struct.func)
+ truncated = TRUE;
+
/* Convert to integer representation if negative.
* equivalent to ~(value - 1).
*/
@@ -8612,48 +8898,144 @@ H5T_conv_f_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
*/
sfirst = H5T_bit_find(int_buf, 0, 8*buf_size, H5T_BIT_MSB, TRUE);
first = (size_t)sfirst;
-
+
+ /* Set these variables to default */
+ except_ret = H5T_CONV_UNHANDLED;
+ truncated = FALSE;
+ reverse = TRUE;
+
if(sfirst < 0) {
/*
* The source has no bits set and must therefore be zero.
* Set the destination to zero - nothing to do.
*/
- } else if (H5T_SGN_NONE==dst.u.i.sign) {
+ } else if (H5T_SGN_NONE==dst.u.i.sign) { /*destination is unsigned*/
/*
- * Destination is unsigned. If the source value is greater
- * than the maximal destination value then it overflows, the
+ * Destination is unsigned. Library's default way: If the source value
+ * is greater than the maximal destination value then it overflows, the
* destination will be set to the maximum possible value. When the
* source is negative, underflow happens. Set the destination to be
- * zero.
+ * zero(do nothing). If user's exception handler is set, call it and
+ * let user handle it.
*/
- if(!sign) {
+ if(sign) { /*source is negative*/
+ if(cb_struct.func) { /*If user's exception handler is present, use it*/
+ src_rev = H5T_reverse_order(s, src_p->size, src.order);
+ except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW,
+ src_id, dst_id, src_rev, d, cb_struct.user_data);
+ if(except_ret == H5T_CONV_ABORT)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception")
+ else if(except_ret == H5T_CONV_HANDLED)
+ /*No need to reverse the order of destination because user handles it*/
+ reverse = FALSE;
+ H5MM_free(src_rev);
+ }
+ } else { /*source is positive*/
if (first>=dst.prec) {
/*overflow*/
- if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, s, d)<0) {
- H5T_bit_set (d, dst.offset, dst.prec, TRUE);
+ if(cb_struct.func) { /*If user's exception handler is present, use it*/
+ src_rev = H5T_reverse_order(s, src_p->size, src.order);
+ except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI,
+ src_id, dst_id, src_rev, d, cb_struct.user_data);
+ H5MM_free(src_rev);
}
+
+ if(except_ret == H5T_CONV_UNHANDLED)
+ H5T_bit_set (d, dst.offset, dst.prec, TRUE);
+ else if(except_ret == H5T_CONV_HANDLED)
+ /*No need to reverse the order of destination because user handles it*/
+ reverse = FALSE;
+ else if(except_ret == H5T_CONV_ABORT)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception")
} else if (first <dst.prec) {
- /*copy source value into it*/
- H5T_bit_copy (d, dst.offset, int_buf, 0, first+1);
+ if(truncated && cb_struct.func) { /*If user's exception handler is present, use it*/
+ src_rev = H5T_reverse_order(s, src_p->size, src.order);
+ except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_TRUNCATE,
+ src_id, dst_id, src_rev, d, cb_struct.user_data);
+ H5MM_free(src_rev);
+ }
+
+ if(except_ret == H5T_CONV_UNHANDLED)
+ /*copy source value into it if case is ignored by user handler*/
+ H5T_bit_copy (d, dst.offset, int_buf, 0, first+1);
+ else if(except_ret == H5T_CONV_HANDLED)
+ /*No need to reverse the order of destination because user handles it*/
+ reverse = FALSE;
+ else if(except_ret == H5T_CONV_ABORT)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception")
}
}
- } else if (H5T_SGN_2==dst.u.i.sign) {
- if(sign) { /*negative*/
- /* if overflows, do nothing except turn on the sign bit
- * because 0x80...00 is the biggest negative value.
- */
- if(first < dst.prec-1)
- H5T_bit_copy (d, dst.offset, int_buf, 0, first+1);
+ } else if (H5T_SGN_2==dst.u.i.sign) { /*Destination is signed*/
+ if(sign) { /*source is negative*/
+ if(first < dst.prec-1) {
+ if(truncated && cb_struct.func) { /*If user's exception handler is present, use it*/
+ src_rev = H5T_reverse_order(s, src_p->size, src.order);
+ except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_TRUNCATE,
+ src_id, dst_id, src_rev, d, cb_struct.user_data);
+ H5MM_free(src_rev);
+ }
+
+ if(except_ret == H5T_CONV_UNHANDLED) {
+ /*copy source value into it if case is ignored by user handler*/
+ H5T_bit_copy (d, dst.offset, int_buf, 0, first+1);
+ H5T_bit_set (d, (dst.offset + dst.prec-1), 1, TRUE);
+ } else if(except_ret == H5T_CONV_ABORT)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception")
+ else if(except_ret == H5T_CONV_HANDLED)
+ /*No need to reverse the order of destination because user handles it*/
+ reverse = FALSE;
+ } else {
+ /* if underflows and no callback, do nothing except turn on
+ * the sign bit because 0x80...00 is the biggest negative value.
+ */
+ if(cb_struct.func) { /*If user's exception handler is present, use it*/
+ src_rev = H5T_reverse_order(s, src_p->size, src.order);
+ except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW,
+ src_id, dst_id, src_rev, d, cb_struct.user_data);
+ H5MM_free(src_rev);
+ }
- H5T_bit_set (d, (dst.offset + dst.prec-1), 1, TRUE);
- } else { /*positive*/
+ if(except_ret == H5T_CONV_UNHANDLED)
+ H5T_bit_set (d, (dst.offset + dst.prec-1), 1, TRUE);
+ else if(except_ret == H5T_CONV_ABORT)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception")
+ else if(except_ret == H5T_CONV_HANDLED)
+ /*No need to reverse the order of destination because user handles it*/
+ reverse = FALSE;
+ }
+ } else { /*source is positive*/
if (first >= dst.prec-1) {
/*overflow*/
- if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, s, d)<0) {
- H5T_bit_set (d, dst.offset, dst.prec-1, TRUE);
+ if(cb_struct.func) { /*If user's exception handler is present, use it*/
+ src_rev = H5T_reverse_order(s, src_p->size, src.order);
+ except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI,
+ src_id, dst_id, src_rev, d, cb_struct.user_data);
+ H5MM_free(src_rev);
}
+
+ if(except_ret == H5T_CONV_UNHANDLED)
+ H5T_bit_set (d, dst.offset, dst.prec-1, TRUE);
+ else if(except_ret == H5T_CONV_ABORT)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception")
+ else if(except_ret == H5T_CONV_HANDLED)
+ /*No need to reverse the order of destination because user handles it*/
+ reverse = FALSE;
} else if(first < dst.prec-1) {
- H5T_bit_copy (d, dst.offset, int_buf, 0, first+1);
+ if(truncated && cb_struct.func) { /*If user's exception handler is present, use it*/
+ src_rev = H5T_reverse_order(s, src_p->size, src.order);
+ except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_TRUNCATE,
+ src_id, dst_id, src_rev, d, cb_struct.user_data);
+ H5MM_free(src_rev);
+ }
+
+ if(except_ret == H5T_CONV_UNHANDLED) {
+ /*copy source value into it if case is ignored by user handler*/
+ H5T_bit_copy (d, dst.offset, int_buf, 0, first+1);
+ } else if(except_ret == H5T_CONV_ABORT)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception")
+ else if(except_ret == H5T_CONV_HANDLED)
+ /*No need to reverse the order of destination because user handles it*/
+ reverse = FALSE;
}
}
}
@@ -8677,7 +9059,7 @@ H5T_conv_f_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
* Put the destination in the correct byte order. See note at
* beginning of loop.
*/
- if (H5T_ORDER_BE==dst.order) {
+ if (H5T_ORDER_BE==dst.order && reverse) {
half_size = dst_p->size/2;
for (i=0; i<half_size; i++) {
uint8_t tmp = d[dst_p->size-(i+1)];
@@ -8730,12 +9112,17 @@ done:
*
* Modifications:
*
+ * Raymond Lu
+ * Wednesday, April 21, 2004
+ * There is a new design for exception handling like overflow,
+ * which is passed in as a transfer property.
+ *
*-------------------------------------------------------------------------
*/
herr_t
H5T_conv_i_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
size_t buf_stride, size_t UNUSED bkg_stride, void *buf, void UNUSED *bkg,
- hid_t UNUSED dxpl_id)
+ hid_t dxpl_id)
{
/* Traversal-related variables */
H5T_t *src_p; /*source data type */
@@ -8747,6 +9134,7 @@ H5T_conv_i_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
size_t half_size; /*half the type size */
hsize_t olap; /*num overlapping elements */
uint8_t *s, *sp, *d, *dp; /*source and dest traversal ptrs*/
+ uint8_t *src_rev; /*order-reversed source buffer */
uint8_t dbuf[64]; /*temp destination buffer */
/* Conversion-related variables */
@@ -8760,7 +9148,11 @@ H5T_conv_i_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
size_t i; /*miscellaneous counters */
size_t first; /*first bit(MSB) in an integer */
ssize_t sfirst; /*a signed version of `first' */
- herr_t ret_value=SUCCEED; /* Return value */
+ H5P_genplist_t *plist; /*Property list pointer */
+ H5T_conv_cb_t cb_struct={NULL, NULL}; /*conversion callback structure */
+ H5T_conv_ret_t except_ret; /*return of callback function */
+ hbool_t reverse; /*if reverse the order of destination */
+ herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5T_conv_i_f, FAIL);
@@ -8821,6 +9213,14 @@ H5T_conv_i_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
buf_size = (src.prec > dst.u.f.msize ? src.prec : dst.u.f.msize)/8 + 1;
int_buf = (uint8_t*)H5MM_calloc(buf_size);
+ /* Get the plist structure */
+ if(NULL == (plist = H5P_object_verify(dxpl_id,H5P_DATASET_XFER)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find property list for ID");
+
+ /* Get conversion exception callback property */
+ if (H5P_get(plist,H5D_XFER_CONV_CB_NAME,&cb_struct)<0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get conversion exception callback");
+
/* The conversion loop */
for (elmtno=0; elmtno<nelmts; elmtno++) {
/* Make sure these variables are reset to 0. */
@@ -8902,7 +9302,7 @@ H5T_conv_i_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
H5T_bit_neg(int_buf, 0, buf_size*8);
sfirst = H5T_bit_find(int_buf, 0, src.prec-1, H5T_BIT_MSB, TRUE);
} else {
- /* If it's maximal negative number 0x80...000, treat it as if it overflows
+ /* If it's maximal negative number 0x80...000, treat it as if it overflowed
* (create a carry) to help conversion. i.e. a character type number 0x80
* is treated as 0x100.
*/
@@ -8920,7 +9320,11 @@ H5T_conv_i_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
}
first = (size_t)sfirst;
-
+
+ /* Set these variables to default */
+ except_ret = H5T_CONV_UNHANDLED;
+ reverse = TRUE;
+
/*
* Calculate the true destination exponent by adjusting according to
* the destination exponent bias.
@@ -8944,7 +9348,21 @@ H5T_conv_i_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
/* Roundup for mantissa */
if(first > dst.u.f.msize) {
- /* If the bit sequence is bigger than the mantissa part, we need to drop off the
+ /* If the bit sequence is bigger than the mantissa part, there'll be some
+ * precision loss. Let user's handler deal with the case if it's present
+ */
+ if(cb_struct.func) {
+ except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_PRECISION, src_id, dst_id,
+ s, d, cb_struct.user_data);
+ }
+
+ if(except_ret == H5T_CONV_HANDLED) {
+ reverse = FALSE;
+ goto padding;
+ } else if(except_ret == H5T_CONV_ABORT)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception")
+
+ /* If user's exception handler does deal with it, we do it by dropping off the
* extra bits at the end and do rounding. If we have .50...0(decimal) after radix
* point, we do roundup when the least significant digit before radix is odd, we do
* rounddown if it's even.
@@ -8996,15 +9414,36 @@ H5T_conv_i_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
/* Check if the exponent is too big */
- expo_max = (hsize_t)HDpow((double)2.0, (double)dst.u.f.esize) - 1;
- if(expo > expo_max)
- expo = expo_max;
+ expo_max = (hsize_t)HDpow((double)2.0, (double)dst.u.f.esize) - 1;
+
+ if(expo > expo_max) { /*overflows*/
+ if(cb_struct.func) { /*user's exception handler. Reverse back source order*/
+ src_rev = H5T_reverse_order(s, src_p->size, src.order);
+ except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, src_id, dst_id,
+ src_rev, d, cb_struct.user_data);
+ H5MM_free(src_rev);
+
+ if(except_ret == H5T_CONV_ABORT)
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception")
+ else if(except_ret == H5T_CONV_HANDLED) {
+ reverse = FALSE;
+ goto padding;
+ }
+ } else {
+ /*make destination infinity by setting exponent to maximal number and
+ *mantissa to zero.*/
+ expo = expo_max;
+ HDmemset(int_buf, 0, buf_size);
+ }
+ }
- /* Set exponent in destiny */
- H5T_bit_set_d(d, dst.u.f.epos, dst.u.f.esize, expo);
+ if(except_ret == H5T_CONV_UNHANDLED) {
+ /* Set exponent in destiny */
+ H5T_bit_set_d(d, dst.u.f.epos, dst.u.f.esize, expo);
- /* Copy mantissa into destiny */
- H5T_bit_copy(d, dst.u.f.mpos, int_buf, 0, buf_size*8 > dst.u.f.msize ? dst.u.f.msize : buf_size*8);
+ /* Copy mantissa into destiny */
+ H5T_bit_copy(d, dst.u.f.mpos, int_buf, 0, buf_size*8 > dst.u.f.msize ? dst.u.f.msize : buf_size*8);
+ }
padding:
/*
@@ -9025,7 +9464,7 @@ H5T_conv_i_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
* Put the destination in the correct byte order. See note at
* beginning of loop.
*/
- if (H5T_ORDER_BE==dst.order) {
+ if (H5T_ORDER_BE==dst.order && reverse) {
half_size = dst_p->size/2;
for (i=0; i<half_size; i++) {
uint8_t tmp = d[dst_p->size-(i+1)];
@@ -9062,3 +9501,48 @@ H5T_conv_i_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
done:
FUNC_LEAVE_NOAPI(ret_value);
}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5T_reverse_order
+ *
+ * Purpose: Internal assisting function to reverse the order of
+ * a sequence of byte when it's big endian. The byte sequence
+ * simulates the endian order.
+ *
+ * Return: Success: A pointer to the reversed byte sequence
+ *
+ * Failure: Null
+ *
+ * Programmer: Raymond Lu
+ * April 26, 2004
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+uint8_t *
+H5T_reverse_order(uint8_t *s, size_t size, H5T_order_t order)
+{
+ uint8_t *ret_value = NULL;
+ size_t i;
+
+ FUNC_ENTER_NOAPI(H5T_reverse_order, NULL);
+
+ assert(s);
+ assert(size);
+
+ ret_value = H5MM_calloc(size);
+ assert(ret_value);
+
+ if (H5T_ORDER_BE == order) {
+ for (i=0; i<size; i++)
+ ret_value[size-(i+1)] = s[i];
+ } else {
+ for (i=0; i<size; i++)
+ ret_value[i] = s[i];
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+}
diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h
index 11a00c9..d22c733 100644
--- a/src/H5Tpkg.h
+++ b/src/H5Tpkg.h
@@ -235,9 +235,6 @@ typedef enum H5T_sdir_t {
/* The native endianess of the platform */
H5_DLLVAR H5T_order_t H5T_native_order_g;
-/* The overflow handler */
-H5_DLLVAR H5T_overflow_t H5T_overflow_g;
-
/*
* Alignment information for native types. A value of N indicates that the
* data must be aligned on an address ADDR such that 0 == ADDR mod N. When
diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h
index 6013ce5..fcd2f28 100644
--- a/src/H5Tprivate.h
+++ b/src/H5Tprivate.h
@@ -86,6 +86,7 @@ H5_DLL htri_t H5T_is_sensible(const H5T_t *dt);
H5_DLL htri_t H5T_set_loc(H5T_t *dt, H5F_t *f, H5T_loc_t loc);
H5_DLL htri_t H5T_committed(H5T_t *type);
H5_DLL int H5T_link(const H5T_t *type, int adjust, hid_t dxpl_id);
+H5_DLL uint8_t * H5T_reverse_order(uint8_t *s, size_t size, H5T_order_t order);
/* Reference specific functions */
H5_DLL H5R_type_t H5T_get_ref_type(const H5T_t *dt);
diff --git a/src/H5Tpublic.h b/src/H5Tpublic.h
index 442407f..608606d 100644
--- a/src/H5Tpublic.h
+++ b/src/H5Tpublic.h
@@ -167,6 +167,21 @@ typedef enum H5T_direction_t {
H5T_DIR_DESCEND = 2 /*in descendent order */
} H5T_direction_t;
+/* The exception type passed into the conversion callback function */
+typedef enum H5T_conv_except_t {
+ H5T_CONV_EXCEPT_RANGE_HI = 0, /*source value is greater than destination's range */
+ H5T_CONV_EXCEPT_RANGE_LOW = 1, /*source value is less than destination's range */
+ H5T_CONV_EXCEPT_PRECISION = 2, /*source value loses precision in destination */
+ H5T_CONV_EXCEPT_TRUNCATE = 3 /*source value is truncated in destination */
+} H5T_conv_except_t;
+
+/* The return value from conversion callback function H5T_conv_except_func_t */
+typedef enum H5T_conv_ret_t {
+ H5T_CONV_ABORT = -1, /*abort conversion */
+ H5T_CONV_UNHANDLED = 0, /*callback function failed to handle the exception */
+ H5T_CONV_HANDLED = 1 /*callback function handled the exception successfully */
+} H5T_conv_ret_t;
+
/* Variable Length Datatype struct in memory */
/* (This is only used for VL sequences, not VL strings, which are stored in char *'s) */
typedef struct {
@@ -186,18 +201,17 @@ typedef herr_t (*H5T_conv_t) (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
hsize_t nelmts, size_t buf_stride, size_t bkg_stride, void *buf,
void *bkg, hid_t dset_xfer_plist);
-/*
- * If an error occurs during a datatype conversion then the function
- * registered with H5Tset_overflow() is called. It's arguments are the
- * source and destination datatypes, a buffer which has the source value,
- * and a buffer to receive an optional result for the overflow conversion.
- * If the overflow handler chooses a value for the result it should return
- * non-negative; otherwise the hdf5 library will choose an appropriate
- * result.
+/* Exception handler. If an exception like overflow happenes during conversion,
+ * this function is called if it's registered through H5Tset_type_conv_cb.
*/
-typedef herr_t (*H5T_overflow_t)(hid_t src_id, hid_t dst_id,
- void *src_buf, void *dst_buf);
+typedef H5T_conv_ret_t (*H5T_conv_except_func_t)(int except_type, hid_t src_id,
+ hid_t dst_id, void *src_buf, void *dst_buf, void *user_data);
+/* Structure for conversion callback property */
+typedef struct H5T_conv_cb_t {
+ H5T_conv_except_func_t func;
+ void* user_data;
+} H5T_conv_cb_t;
/* When this header is included from H5Tprivate.h, don't make calls to H5open() */
#undef H5OPEN
@@ -567,8 +581,6 @@ H5_DLL herr_t H5Tunregister(H5T_pers_t pers, const char *name, hid_t src_id,
H5_DLL H5T_conv_t H5Tfind(hid_t src_id, hid_t dst_id, H5T_cdata_t **pcdata);
H5_DLL herr_t H5Tconvert(hid_t src_id, hid_t dst_id, hsize_t nelmts,
void *buf, void *background, hid_t plist_id);
-H5_DLL H5T_overflow_t H5Tget_overflow(void);
-H5_DLL herr_t H5Tset_overflow(H5T_overflow_t func);
#ifdef __cplusplus
}
diff --git a/test/dtypes.c b/test/dtypes.c
index 17fdc33..27b4874 100644
--- a/test/dtypes.c
+++ b/test/dtypes.c
@@ -171,6 +171,46 @@ overflow_handler(hid_t UNUSED src_id, hid_t UNUSED dst_id,
/*-------------------------------------------------------------------------
+ * Function: except_func
+ *
+ * Purpose: Gets called for all data type conversion exceptions.
+ *
+ * Return: H5T_CONV_ABORT: -1
+ *
+ * H5T_CONV_UNHANDLED 0
+ *
+ * H5T_CONV_HANDLED 1
+ *
+ * Programmer: Raymond Lu
+ * April 19, 2004
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static H5T_conv_ret_t
+except_func(int except_type, hid_t src_id, hid_t dst_id, void *src_buf,
+ void *dst_buf, void *user_data)
+{
+ H5T_conv_ret_t ret = H5T_CONV_HANDLED;
+
+ if(except_type == H5T_CONV_EXCEPT_RANGE_HI)
+ /*only test integer case*/
+ *(int*)dst_buf = *(int*)user_data;
+ else if(except_type == H5T_CONV_EXCEPT_RANGE_LOW)
+ /*only test integer case*/
+ *(int*)dst_buf = *(int*)user_data;
+ else if(except_type == H5T_CONV_EXCEPT_TRUNCATE) {
+ ret = H5T_CONV_UNHANDLED;
+ } else if(except_type == H5T_CONV_EXCEPT_PRECISION) {
+ ret = H5T_CONV_UNHANDLED;
+ }
+
+ return ret;
+}
+
+
+/*-------------------------------------------------------------------------
* Function: some_dummy_func
*
* Purpose: A dummy function to help check for overflow.
@@ -3796,6 +3836,11 @@ test_conv_int_2(void)
static int
test_conv_int_float(const char *name, hid_t src, hid_t dst)
{
+ hid_t dxpl_id; /*dataset transfer property list*/
+ int fill_value=9; /*fill value for conversion exception*/
+ H5T_conv_except_func_t op; /*returned callback function for conversion exception*/
+ void *user_data; /*returned pointer to user data passed in to the callback*/
+ hbool_t except_set = FALSE; /*whether user's exception handling is set*/
const size_t ntests=NTESTS; /*number of tests */
const size_t nelmts=NTESTELEM; /*num values per test */
const size_t max_fails=40; /*max number of failures*/
@@ -3974,6 +4019,31 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst)
noverflows_g = 0;
#endif
+ /* Create a dataset transfer property list and datatype conversion
+ * exception handler function and pass in fill value. This is mainly
+ * for NetCDF compatibility, which requests fill in fill value when
+ * conversion exception happens. We only test (unsigned) int - float
+ * and float - (unsigned) int conversions, which should cover more cases.
+ */
+ if((dxpl_id = H5Pcreate(H5P_DATASET_XFER))<0)
+ goto error;
+
+ if((src_type == INT_INT && dst_type == FLT_FLOAT) ||
+ (src_type == INT_UINT && dst_type == FLT_FLOAT) ||
+ (src_type == FLT_FLOAT && dst_type == INT_UINT) ||
+ (src_type == FLT_FLOAT && dst_type == INT_INT)) {
+ if(H5Pset_type_conv_cb(dxpl_id, except_func, &fill_value)<0)
+ goto error;
+ else
+ except_set = TRUE;
+
+ if(H5Pget_type_conv_cb(dxpl_id, &op, &user_data)<0)
+ goto error;
+
+ if(op != except_func || *(int*)user_data != fill_value)
+ goto error;
+ }
+
/* The tests */
for (i=0; i<ntests; i++) {
if (ntests>1) {
@@ -3996,7 +4066,7 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst)
buf[j] = saved[j] = HDrand();
/* Perform the conversion */
- if (H5Tconvert(src, dst, (hsize_t)nelmts, buf, NULL, H5P_DEFAULT)<0)
+ if (H5Tconvert(src, dst, (hsize_t)nelmts, buf, NULL, dxpl_id)<0)
goto error;
/* Check the results from the library against hardware */
@@ -4347,10 +4417,14 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst)
for (k=0; k<dst_size; k++)
dst_bits[dst_size-(k+1)] = buf[j*dst_size+ENDIAN(dst_size, k)];
- /*
+ /* Test library's default overflow handling:
* Hardware usually doesn't handle overflows too gracefully. The
* hardware conversion result during overflows is usually garbage
* so we must handle those cases differetly when checking results.
+ *
+ * Test user's exception handler when overflows:
+ * Try to follow the except_func callback function to check if the
+ * desired value was set.
*/
if ((FLT_FLOAT==src_type || FLT_DOUBLE==src_type || FLT_LDOUBLE==src_type)
&& (INT_CHAR==dst_type || INT_SHORT==dst_type || INT_INT==dst_type
@@ -4362,9 +4436,15 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst)
* the destination. The destination should be set to the
* maximum possible value: 0x7f...f
*/
- if (0==H5T_bit_get_d(dst_bits, dst_nbits-1, 1) &&
- H5T_bit_find(dst_bits, 0, dst_nbits-1, H5T_BIT_LSB, 0)<0)
- continue; /*no error*/
+ if(!except_set) {
+ if (0==H5T_bit_get_d(dst_bits, dst_nbits-1, 1) &&
+ H5T_bit_find(dst_bits, 0, dst_nbits-1, H5T_BIT_LSB, 0)<0)
+ continue; /*no error*/
+ } else {
+ /* fill_value is small so we know only the 1st byte is set */
+ if (dst_bits[0] == fill_value)
+ continue; /*no error*/
+ }
} else if (1==H5T_bit_get_d(src_bits, src_nbits-1, 1) &&
overflows(src_bits, src_type, src_size, dst_nbits-1)) {
/*
@@ -4372,9 +4452,14 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst)
* the destination. The destination should be set to the
* smallest possible value: 0x80...0
*/
- if (1==H5T_bit_get_d(dst_bits, dst_nbits-1, 1) &&
- H5T_bit_find(dst_bits, 0, dst_nbits-1, H5T_BIT_LSB, 1)<0)
- continue; /*no error*/
+ if(!except_set) {
+ if (1==H5T_bit_get_d(dst_bits, dst_nbits-1, 1) &&
+ H5T_bit_find(dst_bits, 0, dst_nbits-1, H5T_BIT_LSB, 1)<0)
+ continue; /*no error*/
+ } else {
+ if (dst_bits[0] == fill_value)
+ continue; /*no error*/
+ }
}
}
@@ -4387,16 +4472,26 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst)
* The source is negative if the most significant bit is
* set. The destination is zero if all bits are zero.
*/
- if (H5T_bit_find(dst_bits, 0, dst_nbits, H5T_BIT_LSB, 1)<0)
- continue; /*no error*/
+ if(!except_set) {
+ if (H5T_bit_find(dst_bits, 0, dst_nbits, H5T_BIT_LSB, 1)<0)
+ continue; /*no error*/
+ } else {
+ if (dst_bits[0] == fill_value)
+ continue; /*no error*/
+ }
} else if (overflows(src_bits, src_type, src_size, dst_nbits)) {
/*
* The source is a value with a magnitude too large for
* the destination. The destination should be the
* largest possible value: 0xff...f
*/
- if (H5T_bit_find(dst_bits, 0, dst_nbits, H5T_BIT_LSB, 0)<0)
- continue; /*no error*/
+ if(!except_set) {
+ if (H5T_bit_find(dst_bits, 0, dst_nbits, H5T_BIT_LSB, 0)<0)
+ continue; /*no error*/
+ } else {
+ if (dst_bits[0] == fill_value)
+ continue; /*no error*/
+ }
}
}
@@ -4610,10 +4705,13 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst)
/*-------------------------------------------------------------------------
* Function: overflows
*
- * Purpose: return the index of the most significant digit in a bit
- * vector.
+ * Purpose: When convert from float or double to any integer type,
+ * check if overflow occurs.
+ *
+ *
+ * Return: TRUE: overflow happens
*
- * Return: index
+ * FALSE: no overflow
*
* Programmer: Raymond Lu
* Monday, Nov 17, 2003