bug fix; function documentation completed; tests
diff --git a/inc/qcbor/qcbor_encode.h b/inc/qcbor/qcbor_encode.h
index 8dfc2da..e6a9a4c 100644
--- a/inc/qcbor/qcbor_encode.h
+++ b/inc/qcbor/qcbor_encode.h
@@ -621,24 +621,30 @@
@param[in] pCtx The encoding context to add the double to.
@param[in] dNum The double-precision number to add.
- This outputs a floating-point number with CBOR major type 7.
+ This encodes and outputs a floating-point number. CBOR major type 7
+ is used.
- This will selectively encode the double-precision floating-point
- number as either double-precision, single-precision or
- half-precision. It will always encode infinity, NaN and 0 has half
- precision. If no precision will be lost in the conversion to
- half-precision, then it will be converted and encoded. If not and no
- precision will be lost in conversion to single-precision, then it
- will be converted and encoded. If not, then no conversion is
- performed, and it encoded as a double.
+ This implements preferred serialization, selectively encoding the
+ double-precision floating-point number as either double-precision,
+ single-precision or half-precision. Infinity, NaN and 0 are always
+ encoded as half-precision. If no precision will be lost in the
+ conversion to half-precision, then it will be converted and
+ encoded. If not and no precision will be lost in conversion to
+ single-precision, then it will be converted and encoded. If not, then
+ no conversion is performed, and it encoded as a double-precision.
Half-precision floating-point numbers take up 2 bytes, half that of
single-precision, one quarter of double-precision
- This automatically reduces the size of encoded messages a lot, maybe
- even by four if most of values are 0, infinity or NaN.
+ This automatically reduces the size of encoded CBOR, maybe even by
+ four if most of values are 0, infinity or NaN.
- QCBOR usually returns all decoded floats as a double.
+ When decoded, QCBOR will usually return these values as
+ double-precision.
+
+ It is possible to disable this preferred serialization when compiling
+ QCBOR. In that case, this functions the same as
+ QCBOREncode_AddDoubleNoPreferred().
Error handling is the same as QCBOREncode_AddInt64().
@@ -658,7 +664,7 @@
@param[in] pCtx The encoding context to add the double to.
@param[in] fNum The single-precision number to add.
- This is identical to QCBOREncode_AddDouble() execpt the input is
+ This is identical to QCBOREncode_AddDouble() except the input is
single-precision.
See also QCBOREncode_AddDouble(), QCBOREncode_AddDoubleNoPreferred(),
@@ -677,13 +683,13 @@
@param[in] pCtx The encoding context to add the double to.
@param[in] dNum The double-precision number to add.
- This always outputs the value as a 64-bit double-precision.
- Preffered encoding is not used.
+ This always outputs the number as a 64-bit double-precision.
+ Preferred serialization is not used.
-Error handling is the same as QCBOREncode_AddInt64().
+ Error handling is the same as QCBOREncode_AddInt64().
- See also QCBOREncode_AddDouble(), QCBOREncode_AddFloat(),
- and QCBOREncode_AddFloatNoPreferred() and @ref Floating-Point.
+ See also QCBOREncode_AddDouble(), QCBOREncode_AddFloat(), and
+ QCBOREncode_AddFloatNoPreferred() and @ref Floating-Point.
*/
void QCBOREncode_AddDoubleNoPreferred(QCBOREncodeContext *pCtx, double dNum);
@@ -698,13 +704,13 @@
@param[in] pCtx The encoding context to add the double to.
@param[in] fNum The single-precision number to add.
- This always outputs the value as a 32-bit single-precision.
- Preffered encoding is not used.
+ This always outputs the number as a 32-bit single-precision.
+ Preferred serialization is not used.
Error handling is the same as QCBOREncode_AddInt64().
- See also QCBOREncode_AddDouble(), QCBOREncode_AddFloat(),
- and QCBOREncode_AddDoubleNoPreferred() and @ref Floating-Point.
+ See also QCBOREncode_AddDouble(), QCBOREncode_AddFloat(), and
+ QCBOREncode_AddDoubleNoPreferred() and @ref Floating-Point.
*/
void QCBOREncode_AddFloatNoPreferred(QCBOREncodeContext *pCtx, float fNum);
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index 3c11a64..5684d76 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -571,7 +571,7 @@
case HALF_PREC_FLOAT:
#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
- // The caast to uint16_t is safe because the encoded value
+ // The cast to uint16_t is safe because the encoded value
// was 16 bits. It was widened to 64 bits to be passed in here.
pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
@@ -581,9 +581,10 @@
break;
case SINGLE_PREC_FLOAT:
#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
- // The caast to uint32_t is safe because the encoded value
+ // The cast to uint32_t is safe because the encoded value
// was 32 bits. It was widened to 64 bits to be passed in here.
pDecodedItem->val.dfnum = IEEE754_FloatToDouble((uint32_t)uNumber);
+ pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
#else
pDecodedItem->val.fnum = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
@@ -1230,7 +1231,9 @@
// values 10 billion years in the past and in the future
// where this this code would go wrong and some compilers
// will generate warnings or errors.
- const double d = pDecodedItem->val.dfnum;
+ const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
+ pDecodedItem->val.dfnum :
+ (double)pDecodedItem->val.fnum;
if(d > (double)(INT64_MAX - 0x7ff)) {
nReturn = QCBOR_ERR_DATE_OVERFLOW;
goto Done;
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index 9cfbb2d..2c95a00 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -2060,7 +2060,7 @@
0x1b, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // Too large integer
0xc1, // tag for epoch date
- 0xfa, 0x3f, 0x8c, 0xcc, 0xcd, // double with value 1.1
+ 0xfa, 0x3f, 0x8c, 0xcc, 0xcd, // single with value 1.1
0xc1, // tag for epoch date
0xfa, 0x7f, 0x7f, 0xff, 0xff, // 3.4028234663852886e+38 too large
@@ -2142,10 +2142,6 @@
CHECK_EXPECTED_DOUBLE(Item.val.epochDate.fSecondsFraction, 0.1 )) {
return -9;
}
-#else
- if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_FLOAT_DATE_UNSUPPORTED)
- return -80;
-#endif
// Epoch date float that is too large for our representation
if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_DATE_OVERFLOW) {
@@ -2158,12 +2154,28 @@
}
// Largest double epoch date supported
- if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_SUCCESS ||
- Item.uDataType != QCBOR_TYPE_DATE_EPOCH ||
- Item.val.epochDate.nSeconds != 9223372036854773760 ||
- Item.val.epochDate.nSeconds == 0) {
- return -12;
+ if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_SUCCESS ||
+ Item.uDataType != QCBOR_TYPE_DATE_EPOCH ||
+ Item.val.epochDate.nSeconds != 9223372036854773760 ||
+ Item.val.epochDate.nSeconds == 0) {
+ return -12;
+ }
+#else
+ if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_FLOAT_DATE_UNSUPPORTED) {
+ return -80;
}
+ if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_FLOAT_DATE_UNSUPPORTED) {
+ return -80;
+ }
+ if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_FLOAT_DATE_UNSUPPORTED) {
+ return -80;
+ }
+ if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_FLOAT_DATE_UNSUPPORTED) {
+ return -80;
+ }
+#endif
+
+
// TODO: could use a few more tests with float, double, and half precsion
// and negative (but coverage is still pretty good)