summaryrefslogtreecommitdiffstats
path: root/src/H5Tconv.c
diff options
context:
space:
mode:
authorRobb Matzke <matzke@llnl.gov>1998-07-07 20:13:31 (GMT)
committerRobb Matzke <matzke@llnl.gov>1998-07-07 20:13:31 (GMT)
commitbcf649388cb246fecf5bac670c54c7c4d654eb44 (patch)
treee73f696a48020d756c3eeda3c633047ef2465bfa /src/H5Tconv.c
parent63be23d70dd9bb3d79d670bb94e26c829a4abc2e (diff)
downloadhdf5-bcf649388cb246fecf5bac670c54c7c4d654eb44.zip
hdf5-bcf649388cb246fecf5bac670c54c7c4d654eb44.tar.gz
hdf5-bcf649388cb246fecf5bac670c54c7c4d654eb44.tar.bz2
[svn-r460] Changes since 19980707
---------------------- ./bin/trace ./src/H5.c ./src/H5private.h ./src/H5A.c ./src/H5D.c ./src/H5F.c ./src/H5G.c ./src/H5P.c ./src/H5Pprivate.h ./src/H5S.c ./src/H5T.c Output-only arguments have their addresses printed during tracing and added symbolic output for the H5F_driver_t arguments. That's another reason that we should be careful to add `/*out*/' after arguments that are output-only and `/*in,out*/' after arguments that are used for both input and output values. No internal function calls H5Pget_class() anymore. ./src/H5T.c ./src/H5Tconv.c ./src/H5Tpkg.h ./src/H5Tpublic.h Added H5Tget_overflow() and H5Tset_overflow() so the application can query or set a function that will be called whenever an overflow occurs. Implemented as documented in previous e-mail except the overflow handler gets two buffers: one that contains the source value and one to receive the optional destination value. ./test/dtypes.c Tests overflow handler. ./src/H5.c We have to declare fdopen() because I'm getting errors when compiling on Irix64 even though we include <stdio.h> as documented in the fdopen() man page.
Diffstat (limited to 'src/H5Tconv.c')
-rw-r--r--src/H5Tconv.c116
1 files changed, 87 insertions, 29 deletions
diff --git a/src/H5Tconv.c b/src/H5Tconv.c
index 930b330..211caf7 100644
--- a/src/H5Tconv.c
+++ b/src/H5Tconv.c
@@ -14,6 +14,7 @@
#include <H5MMprivate.h>
#include <H5Tpkg.h>
#include <math.h> /*for ceil() */
+#include <float.h> /*for FLT_MAX and HUGE_VAL */
/* Conversion data for H5T_conv_struct() */
typedef struct H5T_conv_struct_t {
@@ -551,6 +552,9 @@ H5T_conv_struct(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
*
* Modifications:
*
+ * Robb Matzke, 7 Jul 1998
+ * Added overflow handling.
+ *
*-------------------------------------------------------------------------
*/
herr_t
@@ -701,8 +705,11 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
dst->u.atomic.prec-src->u.atomic.prec, FALSE);
} else if (first>=dst->u.atomic.prec) {
/*overflow*/
- H5T_bit_set (d, dst->u.atomic.offset, dst->u.atomic.prec,
- TRUE);
+ 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);
+ }
} else {
H5T_bit_copy (d, dst->u.atomic.offset,
s, src->u.atomic.offset,
@@ -715,13 +722,16 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
* If the source is signed and the destination isn't then we
* can have overflow if the source contains more bits than
* the destination (destination is set to the maximum
- * possible value) or underflow if the source is negative
+ * possible value) or overflow if the source is negative
* (destination is set to zero).
*/
if (first+1 == src->u.atomic.prec) {
- /*underflow*/
- H5T_bit_set (d, dst->u.atomic.offset, dst->u.atomic.prec,
- FALSE);
+ /*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);
+ }
} else if (src->u.atomic.prec < dst->u.atomic.prec) {
H5T_bit_copy (d, dst->u.atomic.offset,
s, src->u.atomic.offset,
@@ -731,8 +741,11 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
FALSE);
} else if (first>=dst->u.atomic.prec) {
/*overflow*/
- H5T_bit_set (d, dst->u.atomic.offset, dst->u.atomic.prec,
- TRUE);
+ 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);
+ }
} else {
H5T_bit_copy (d, dst->u.atomic.offset,
s, src->u.atomic.offset,
@@ -748,10 +761,13 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
*/
if (first+1 >= dst->u.atomic.prec) {
/*overflow*/
- 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);
+ 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-1, TRUE);
+ H5T_bit_set (d, (dst->u.atomic.offset +
+ dst->u.atomic.prec-1), 1, FALSE);
+ }
} else if (src->u.atomic.prec<dst->u.atomic.prec) {
H5T_bit_copy (d, dst->u.atomic.offset,
s, src->u.atomic.offset,
@@ -767,7 +783,7 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
} else if (first+1 == src->u.atomic.prec) {
/*
* Both the source and the destination are signed and the
- * source value is negative. We could experience underflow
+ * source value is negative. We could experience overflow
* if the destination isn't wide enough in which case the
* destination is set to a negative number with the largest
* possible magnitude.
@@ -778,11 +794,14 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
size_t fz = (size_t)sfz;
if (sfz>=0 && fz+1>=dst->u.atomic.prec) {
- /*underflow*/
- 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);
+ /*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-1, FALSE);
+ H5T_bit_set (d, (dst->u.atomic.offset +
+ dst->u.atomic.prec-1), 1, TRUE);
+ }
} else if (src->u.atomic.prec<dst->u.atomic.prec) {
H5T_bit_copy (d, dst->u.atomic.offset,
s, src->u.atomic.offset,
@@ -804,10 +823,13 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
*/
if (first+1>=dst->u.atomic.prec) {
/*overflow*/
- 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);
+ 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-1, TRUE);
+ H5T_bit_set (d, (dst->u.atomic.offset +
+ dst->u.atomic.prec-1), 1, FALSE);
+ }
} else if (src->u.atomic.prec<dst->u.atomic.prec) {
H5T_bit_copy (d, dst->u.atomic.offset,
s, src->u.atomic.offset,
@@ -888,6 +910,9 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
*
* Modifications:
*
+ * Robb Matzke, 7 Jul 1998
+ * Added overflow handling.
+ *
*-------------------------------------------------------------------------
*/
herr_t
@@ -1143,12 +1168,30 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
/*
* The exponent is too large to fit in the available region
* or it results in the maximum possible value. Use positive
- * or negative infinity instead.
+ * or negative infinity instead unless the application
+ * specifies something else. Before calling the overflow
+ * handler make sure the source buffer we hand it is in the
+ * original byte order.
*/
+ if (H5T_overflow_g) {
+ uint8 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;
+ }
+ }
expo = expo_max;
H5T_bit_set(d, dst.u.f.mpos, dst.u.f.msize, FALSE);
msize = 0;
-
}
/*
@@ -1239,6 +1282,7 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
* If we had used a temporary buffer for the destination then we
* should copy the value to the true destination buffer.
*/
+ next:
if (d==dbuf) HDmemcpy (dp, d, dst_p->size);
sp += direction * src_p->size;
dp += direction * dst_p->size;
@@ -1324,12 +1368,14 @@ H5T_conv_float_double (hid_t __unused__ src_id, hid_t __unused__ dst_id,
*
* Modifications:
*
+ * Robb Matzke, 7 Jul 1998
+ * Added overflow handling.
+ *
*-------------------------------------------------------------------------
*/
herr_t
-H5T_conv_double_float (hid_t __unused__ src_id, hid_t __unused__ dst_id,
- H5T_cdata_t *cdata, size_t nelmts, void *buf,
- void __unused__ *bkg)
+H5T_conv_double_float (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
+ size_t nelmts, void *buf, void __unused__ *bkg)
{
size_t elmtno; /*element number */
double *s; /*source buffer */
@@ -1349,8 +1395,20 @@ H5T_conv_double_float (hid_t __unused__ src_id, hid_t __unused__ dst_id,
s = (double*)buf;
d = (float*)buf;
- for (elmtno=0; elmtno<nelmts; elmtno++) {
- *d++ = *s++;
+ for (elmtno=0; elmtno<nelmts; elmtno++, d++, s++) {
+ if (*s > FLT_MAX) {
+ if (!H5T_overflow_g ||
+ (H5T_overflow_g)(src_id, dst_id, s, d)<0) {
+ *d = HUGE_VAL;
+ }
+ } else if (*s < -FLT_MAX) {
+ if (!H5T_overflow_g ||
+ (H5T_overflow_g)(src_id, dst_id, s, d)<0) {
+ *d = -HUGE_VAL;
+ }
+ } else {
+ *d = *s;
+ }
}
break;