finish up testing and most work on integer conversion
diff --git a/inc/qcbor/qcbor_spiffy_decode.h b/inc/qcbor/qcbor_spiffy_decode.h
index 8e08cfd..21c19ea 100644
--- a/inc/qcbor/qcbor_spiffy_decode.h
+++ b/inc/qcbor/qcbor_spiffy_decode.h
@@ -171,6 +171,33 @@
*/
+
+
+/** The data item must be a tag of the expected type. It is an error
+ if it is not. For example when calling QCBORDecode_GetEpochDate(),
+ the data item must be an @ref CBOR_TAG_DATE_EPOCH tag.
+ See @ref Tag-Usage. */
+#define QCBOR_TAG_REQUIREMENT_TAG 0
+
+/** The data item must be of the type expected for content data type
+ being fetched. It is an error if it is not. For example, when
+ calling QCBORDecode_GetEpochDate() and it must not be an @ref
+ CBOR_TAG_DATE_EPOCH tag. See @ref Tag-Usage. */
+#define QCBOR_TAG_REQUIREMENT_NOT_A_TAG 1
+
+/** Either of the above two are allowed. This allows implementation of
+ being liberal in what you receive, but it is better if CBOR-based
+ protocols pick one and stick to and not required the reciever to
+ take either. See @ref Tag-Usage. */
+#define QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG 2
+
+/** Add this into the above value if other tags not processed by QCBOR
+ are to be allowed to surround the data item. See @ref Tag-Usage. */
+#define QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS 0x80
+
+
+
+
/** Conversion will proceed if the CBOR item to be decoded is an
integer or either type 0 (unsigned) or type 1 (negative). */
#define QCBOR_CONVERT_TYPE_XINT64 0x01
@@ -188,34 +215,11 @@
#define QCBOR_CONVERT_TYPE_BIGFLOAT 0x10
-/** The data item must be a tag of the expected type. It is an error
- if it is not. For example when calling QCBORDecode_GetEpochDate(),
- the data item must be an @ref CBOR_TAG_DATE_EPOCH tag.
- See @ref Tag-Usage. */
-#define QCBOR_TAG_REQUIREMENT_TAG 0
-
-/** The data item must be of the type expected for content data type
- being fetched. It is an error if it is not. For example, when
- calling QCBORDecode_GetEpochDate() and it must not be an @ref
- CBOR_TAG_DATE_EPOCH tag. See @ref Tag-Usage. */
-#define QCBOR_TAG_REQUIREMENT_NOT_A_TAG 1
-
-/** Either of the above two are allowed. This allows implementation of
- being liberal in what you receive, but it is better if CBOR-based
- protocols pick one and stick to and not required the reciever to
- take either. See @ref Tag-Usage. */
-#define QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG 2
-
-/** Add this into the above value if other tags not processed by QCBOR
- are to be allowed to surround the data item. See @ref Tag-Usage. */
-#define QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS 0x80
-
-
/**
@brief Decode next item into a signed 64-bit integer.
- @param[in] pCtx The decode context.
+ @param[in] pCtx The decode context.
@param[out] pnValue The returned 64-bit signed integer.
The CBOR data item to decode must be a positive or negative integer
@@ -310,13 +314,13 @@
See @ref Decode-Errors for discussion on how error handling works.
Note that most these types can support numbers much larger that can
- be represented by in a 64-bit integer, so @ref @ref
+ be represented by in a 64-bit integer, so @ref
QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW may often be encountered.
When converting bignums and decimal fractions @ref
QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will be set if the result is
below 1, unless the mantissa is zero, in which case the coversion is
- successful and the value of 0 is returned. TODO: is this right?
+ successful and the value of 0 is returned.
See also QCBORDecode_GetInt64ConvertAll() which does some of these
conversions, but links in much less object code. See also
@@ -402,9 +406,9 @@
/**
@brief Decode next item into an unsigned 64-bit integer with conversions
- @param[in] pCtx The decode context.
- @param[in] uConvertTypes The integer conversion options.
- @param[out] puValue The returned 64-bit unsigned integer.
+ @param[in] pCtx The decode context.
+ @param[in] uConvertTypes The integer conversion options.
+ @param[out] puValue The returned 64-bit unsigned integer.
This is the same as QCBORDecode_GetInt64ConvertAll(), but returns an
unsigned integer and thus sets @ref QCBOR_ERR_NUMBER_SIGN_CONVERSION
@@ -471,7 +475,7 @@
This will decode CBOR integer and floating-point numbers, returning
them as a double floating-point number. This function supports @ref
QCBOR_CONVERT_TYPE_XINT64 and @ref QCBOR_CONVERT_TYPE_FLOAT
- conversions. If the CBOR is not one of the requested types or a type
+ conversions. If the encoded CBOR is not one of the requested types or a type
not supported by this function, @ref QCBOR_ERR_UNEXPECTED_TYPE is
set.
@@ -484,7 +488,7 @@
a half-precision number is encountered.
Positive and negative integers can always be converted to
- floating-point, so this will never error on type 0 or 1 CBOR.
+ floating-point, so this will never error on CBOR major type 0 or 1.
Note that a large 64-bit integer can have more precision (64 bits)
than even a double floating-point (52 bits) value, so there is loss
@@ -510,9 +514,9 @@
/**
@brief Decode next item as a double floating-point value with conversion.
- @param[in] pCtx The decode context.
- @param[in] uConvertTypes The integer conversion options.
- @param[out] pdValue The returned floating-point value.
+ @param[in] pCtx The decode context.
+ @param[in] uConvertTypes The integer conversion options.
+ @param[out] pdValue The returned floating-point value.
This is the same as QCBORDecode_GetDoubleConvert() but supports many
more conversions at the cost of linking in more object code. The
@@ -523,8 +527,10 @@
Big numbers, decimal fractions and big floats that are too small or
too large to be reprented as a double floating-point number will be
- returned as plus or minus zero or infinity. There is also often loss
- of precision in the conversion.
+ returned as plus or minus zero or infinity rather than setting an
+ under or overflow error.
+
+ There is often loss of precision in the conversion.
See also QCBORDecode_GetDoubleConvert() and QCBORDecode_GetDoubleConvert().
*/
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index a7cb019..468d295 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -4771,7 +4771,7 @@
#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
case QCBOR_TYPE_DECIMAL_FRACTION:
if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
- // TODO: rounding and overflow errors
+ // Underflow gives 0, overflow gives infinity
*pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
} else {
@@ -4781,8 +4781,9 @@
case QCBOR_TYPE_BIGFLOAT:
if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
- *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
- exp2((double)pItem->val.expAndMantissa.nExponent);
+ // Underflow gives 0, overflow gives infinity
+ *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
+ exp2((double)pItem->val.expAndMantissa.nExponent);
} else {
return QCBOR_ERR_UNEXPECTED_TYPE;
}
@@ -4817,7 +4818,6 @@
case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
- // TODO: -infinity
double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
*pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
} else {
@@ -4836,7 +4836,6 @@
case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
- // TODO: -infinity
double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
*pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
} else {
@@ -4845,7 +4844,6 @@
break;
#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
-
default:
return QCBOR_ERR_UNEXPECTED_TYPE;
}
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index 19d8a78..a965606 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -5435,6 +5435,52 @@
QCBOR_ERR_HW_FLOAT_DISABLED,
#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
},
+
+ {
+ "big float underflow [9223372036854775806, -9223372036854775806]",
+ {(uint8_t[]){
+ 0xC5, 0x82,
+ 0x3B, 0x7f, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
+ 0x1B, 0x7f, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE}, 20},
+#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+ 0,
+ QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW,
+ 0,
+ QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW,
+ 0,
+ QCBOR_SUCCESS
+#else /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+ 0,
+ QCBOR_ERR_UNEXPECTED_TYPE,
+ 0,
+ QCBOR_ERR_UNEXPECTED_TYPE,
+ 0.0,
+ QCBOR_ERR_UNEXPECTED_TYPE
+#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+ },
+
+ {
+ "bigfloat that evaluates to -INFINITY",
+ {(uint8_t[]){
+ 0xC5, 0x82,
+ 0x1B, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0xC3, 0x42, 0x01, 0x01}, 15},
+#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+ 0,
+ QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW,
+ 0,
+ QCBOR_ERR_NUMBER_SIGN_CONVERSION,
+ -INFINITY,
+ QCBOR_SUCCESS
+#else /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+ 0,
+ QCBOR_ERR_UNEXPECTED_TYPE,
+ 0,
+ QCBOR_ERR_UNEXPECTED_TYPE,
+ 0.0,
+ QCBOR_ERR_UNEXPECTED_TYPE
+#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA*/
+ },
};