summaryrefslogtreecommitdiffstats
path: root/src/H5Tconv.c
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2005-09-03 17:11:00 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2005-09-03 17:11:00 (GMT)
commit01a3d9d780f255373e5e563152ac47aed6b049bc (patch)
treecf551eaefc4f02c2cd6e9efb781160d816687ad2 /src/H5Tconv.c
parent4aa86e2297e05687820d9cd8211c217184d06ae4 (diff)
downloadhdf5-01a3d9d780f255373e5e563152ac47aed6b049bc.zip
hdf5-01a3d9d780f255373e5e563152ac47aed6b049bc.tar.gz
hdf5-01a3d9d780f255373e5e563152ac47aed6b049bc.tar.bz2
[svn-r11345] Purpose:
Bug fix & code cleanup Description: Address most of datatype conversion exception handling bug that Ed Hartnett reported. (He's reported a different problem now, but we're closer at least). Also, condense exception handling #ifdef's into one location instead of spread out in so many places. Platforms tested: FreeBSD 4.11 (sleipnir) Too minor to require h5committest
Diffstat (limited to 'src/H5Tconv.c')
-rw-r--r--src/H5Tconv.c167
1 files changed, 114 insertions, 53 deletions
diff --git a/src/H5Tconv.c b/src/H5Tconv.c
index 8745892..688eb60 100644
--- a/src/H5Tconv.c
+++ b/src/H5Tconv.c
@@ -190,7 +190,6 @@ H5FL_BLK_DEFINE_STATIC(array_seq);
* equal. In this case, do not return exception but make sure the maximum is assigned
* to the destination. SLU - 2005/06/29
*/
-#ifdef H5_WANT_DCONV_EXCEPTION
#define H5T_CONV_Xx_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \
if (*((ST*)S) > (DT)(D_MAX)) { \
if(cb_struct.func) { \
@@ -207,8 +206,6 @@ H5FL_BLK_DEFINE_STATIC(array_seq);
} \
else \
*((DT*)D) = (D_MAX); \
- } else if (*((ST*)S) == (DT)(D_MAX)) { \
- *((DT*)D) = (D_MAX); \
} else if (*((ST*)S) < (DT)(D_MIN)) { \
if(cb_struct.func) { \
H5T_conv_ret_t except_ret; /*callback return*/ \
@@ -227,13 +224,7 @@ H5FL_BLK_DEFINE_STATIC(array_seq);
} else \
*((DT*)D) = (DT)(*((ST*)S)); \
}
-#else
-#define H5T_CONV_Xx_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \
- *((DT*)D) = (DT)(*((ST*)S)); \
-}
-#endif
-#ifdef H5_WANT_DCONV_EXCEPTION
#define H5T_CONV_Ux_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \
if (*((ST*)S) > (DT)(D_MAX)) { \
if(cb_struct.func) { \
@@ -253,18 +244,12 @@ H5FL_BLK_DEFINE_STATIC(array_seq);
} else \
*((DT*)D) = (DT)(*((ST*)S)); \
}
-#else
-#define H5T_CONV_Ux_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \
- *((DT*)D) = (DT)(*((ST*)S)); \
-}
-#endif
#define H5T_CONV_sS(STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \
assert(sizeof(ST)<=sizeof(DT)); \
H5T_CONV(H5T_CONV_xX, long_long, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \
}
-#ifdef H5_WANT_DCONV_EXCEPTION
#define H5T_CONV_sU_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \
if (*((ST*)S) < 0) { \
if(cb_struct.func) { \
@@ -284,18 +269,12 @@ H5FL_BLK_DEFINE_STATIC(array_seq);
} else \
*((DT*)D) = (DT)(*((ST*)S)); \
}
-#else
-#define H5T_CONV_sU_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \
- *((DT*)D) = (DT)(*((ST*)S)); \
-}
-#endif
#define H5T_CONV_sU(STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \
assert(sizeof(ST)<=sizeof(DT)); \
H5T_CONV(H5T_CONV_sU, long_long, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \
}
-#ifdef H5_WANT_DCONV_EXCEPTION
#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(cb_struct.func) { \
@@ -315,11 +294,6 @@ H5FL_BLK_DEFINE_STATIC(array_seq);
} else \
*((DT*)D) = (DT)(*((ST*)S)); \
}
-#else
-#define H5T_CONV_uS_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \
- *((DT*)D) = (DT)(*((ST*)S)); \
-}
-#endif
#define H5T_CONV_uS(STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \
assert(sizeof(ST)<=sizeof(DT)); \
@@ -336,7 +310,6 @@ H5FL_BLK_DEFINE_STATIC(array_seq);
H5T_CONV(H5T_CONV_Xx, long_long, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \
}
-#ifdef H5_WANT_DCONV_EXCEPTION
#define H5T_CONV_Su_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \
if (*((ST*)S) < 0) { \
if(cb_struct.func) { \
@@ -371,11 +344,6 @@ H5FL_BLK_DEFINE_STATIC(array_seq);
} else \
*((DT*)D) = (DT)(*((ST*)S)); \
}
-#else
-#define H5T_CONV_Su_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \
- *((DT*)D) = (DT)(*((ST*)S)); \
-}
-#endif
#define H5T_CONV_Su(STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \
assert(sizeof(ST)>=sizeof(DT)); \
@@ -392,7 +360,6 @@ H5FL_BLK_DEFINE_STATIC(array_seq);
H5T_CONV(H5T_CONV_Ux, long_long, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \
}
-#ifdef H5_WANT_DCONV_EXCEPTION
#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) { \
@@ -413,18 +380,12 @@ H5FL_BLK_DEFINE_STATIC(array_seq);
} else \
*((DT*)D) = (DT)(*((ST*)S)); \
}
-#else
-#define H5T_CONV_su_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \
- *((DT*)D) = (DT)(*((ST*)S)); \
-}
-#endif
#define H5T_CONV_su(STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \
assert(sizeof(ST)==sizeof(DT)); \
H5T_CONV(H5T_CONV_su, long_long, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \
}
-#ifdef H5_WANT_DCONV_EXCEPTION
#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) > (DT)(D_MAX)) { \
@@ -445,11 +406,6 @@ H5FL_BLK_DEFINE_STATIC(array_seq);
} else \
*((DT*)D) = (DT)(*((ST*)S)); \
}
-#else
-#define H5T_CONV_us_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \
- *((DT*)D) = (DT)(*((ST*)S)); \
-}
-#endif
#define H5T_CONV_us(STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \
assert(sizeof(ST)==sizeof(DT)); \
@@ -464,7 +420,6 @@ H5FL_BLK_DEFINE_STATIC(array_seq);
/* Same as H5T_CONV_Xx_CORE, except that instead of using D_MAX and D_MIN
* when an overflow occurs, use the 'float' infinity values.
*/
-#ifdef H5_WANT_DCONV_EXCEPTION
#define H5T_CONV_Ff_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \
if (*((ST*)S) > (DT)(D_MAX)) { \
if(cb_struct.func) { \
@@ -499,23 +454,119 @@ H5FL_BLK_DEFINE_STATIC(array_seq);
} else \
*((DT*)D) = (DT)(*((ST*)S)); \
}
-#else
-#define H5T_CONV_Ff_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \
- *((DT*)D) = (DT)(*((ST*)S)); \
-}
-#endif
#define H5T_CONV_Ff(STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \
assert(sizeof(ST)>=sizeof(DT)); \
H5T_CONV(H5T_CONV_Ff, long double, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \
}
+/* Note: this is a relative fragile hack (to use the temporary variable of the
+ * destination type) - it may get optimized out by the compiler. QAK - 2005/08/19
+ *
+ * A better solution would be to find the bit position of the highest 1 bit
+ * in the source and the bit position of the lowest 1 bit in the source and
+ * determine if the number of bits between them is greater than the mantissa
+ * of the floating point number (including the leading "implied" 1 bit), then
+ * issue a precision exception. However, that's probably too slow, so we'll
+ * try to use this solution for now. QAK - 2005/19/08
+ */
+#define H5T_CONV_xF_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \
+ DT t_s = *((ST*)S); \
+ if (*((ST*)S) != (ST)t_s) { \
+ if(cb_struct.func) { \
+ H5T_conv_ret_t except_ret; /*callback return*/ \
+ \
+ except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_PRECISION, \
+ 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) = (DT)(*((ST*)S)); \
+ else if(except_ret == H5T_CONV_ABORT) \
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \
+ /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \
+ } \
+ else \
+ *((DT*)D) = (DT)(*((ST*)S)); \
+ } \
+ else \
+ *((DT*)D) = (DT)(*((ST*)S)); \
+}
+
#define H5T_CONV_xF(STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \
- H5T_CONV(H5T_CONV_xX, long double, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \
+ H5T_CONV(H5T_CONV_xF, long double, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \
+}
+
+/* Added a condition branch(else if (*((ST*)S) == (DT)(D_MAX))) which seems redundant.
+ * It handles a special situation when the source is "float" and assigned the value
+ * of "INT_MAX". A compiler may do roundup making this value "INT_MAX+1". However,
+ * when do comparison "if (*((ST*)S) > (DT)(D_MAX))", the compiler may consider them
+ * equal. In this case, do not return exception but make sure the maximum is assigned
+ * to the destination. SLU - 2005/06/29
+ *
+ * Modified Ray's change to just check for the source >= the DT_MAX, so that
+ * the exception handling routine gets called. QAK - 2005/08/08
+ */
+#define H5T_CONV_Fx_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \
+ if (*((ST*)S) >= (DT)(D_MAX)) { \
+ if(cb_struct.func) { \
+ H5T_conv_ret_t except_ret; /*callback return*/ \
+ \
+ 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") \
+ /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \
+ } \
+ else \
+ *((DT*)D) = (D_MAX); \
+ } else if (*((ST*)S) < (DT)(D_MIN)) { \
+ if(cb_struct.func) { \
+ H5T_conv_ret_t except_ret; /*callback return*/ \
+ \
+ 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") \
+ /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \
+ } \
+ else \
+ *((DT*)D) = (D_MIN); \
+ } else if (*((ST*)S) != (ST)((DT)(*((ST*)S)))) { \
+ if(cb_struct.func) { \
+ H5T_conv_ret_t except_ret; /*callback return*/ \
+ \
+ except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_TRUNCATE, \
+ 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) = (DT)(*((ST*)S)); \
+ else if(except_ret == H5T_CONV_ABORT) \
+ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \
+ /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \
+ } \
+ else \
+ *((DT*)D) = (DT)(*((ST*)S)); \
+ } \
+ else \
+ *((DT*)D) = (DT)(*((ST*)S)); \
}
#define H5T_CONV_Fx(STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \
- H5T_CONV(H5T_CONV_Xx, long double, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \
+ H5T_CONV(H5T_CONV_Fx, long double, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \
+}
+
+/* Since all "no exception" cores do the same thing (assign the value in the
+ * source location to the destination location, using casting), use one "core"
+ * to do them all.
+ */
+#define H5T_CONV_NO_EXCEPT_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \
+ *((DT*)D) = (DT)(*((ST*)S)); \
}
/* The main part of every integer hardware conversion macro */
@@ -686,7 +737,7 @@ H5FL_BLK_DEFINE_STATIC(array_seq);
H5_GLUE(H5T_CONV_LOOP_,PRE_DALIGN_GUTS)(DT) \
\
/* ... user-defined stuff here -- the conversion ... */ \
- H5_GLUE(GUTS,_CORE)(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) \
+ H5T_CONV_LOOP_GUTS(GUTS,S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) \
\
/* Handle source post-alignment */ \
H5_GLUE(H5T_CONV_LOOP_,POST_SALIGN_GUTS)(ST) \
@@ -699,6 +750,16 @@ H5FL_BLK_DEFINE_STATIC(array_seq);
dst += d_stride; \
}
+/* Macro to call the actual "guts" of the type conversion, or call the "no exception" guts */
+#ifdef H5_WANT_DCONV_EXCEPTION
+#define H5T_CONV_LOOP_GUTS(GUTS,S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) \
+ /* ... user-defined stuff here -- the conversion ... */ \
+ H5_GLUE(GUTS,_CORE)(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX)
+#else /* H5_WANT_DCONV_EXCEPTION */
+#define H5T_CONV_LOOP_GUTS(GUTS,S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) \
+ H5_GLUE(H5T_CONV_NO_EXCEPT,_CORE)(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX)
+#endif /* H5_WANT_DCONV_EXCEPTION */
+
#ifdef H5T_DEBUG