added general float test; some bug fixes
diff --git a/QCBOR.xcodeproj/project.pbxproj b/QCBOR.xcodeproj/project.pbxproj
index baed191..5aa9a7a 100644
--- a/QCBOR.xcodeproj/project.pbxproj
+++ b/QCBOR.xcodeproj/project.pbxproj
@@ -62,7 +62,7 @@
0FA9BEBC216DE31700BA646B /* UsefulBuf_Tests.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.c; name = UsefulBuf_Tests.c; path = test/UsefulBuf_Tests.c; sourceTree = "<group>"; tabWidth = 3; };
E73B57572161CA680080D658 /* ieee754.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ieee754.h; path = src/ieee754.h; sourceTree = "<group>"; };
E73B57582161CA690080D658 /* ieee754.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ieee754.c; path = src/ieee754.c; sourceTree = "<group>"; };
- E73B575A2161CA7C0080D658 /* float_tests.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = float_tests.c; path = test/float_tests.c; sourceTree = "<group>"; };
+ E73B575A2161CA7C0080D658 /* float_tests.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.c; name = float_tests.c; path = test/float_tests.c; sourceTree = "<group>"; tabWidth = 3; };
E73B575B2161CA7C0080D658 /* half_to_double_from_rfc7049.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = half_to_double_from_rfc7049.h; path = test/half_to_double_from_rfc7049.h; sourceTree = "<group>"; };
E73B575C2161CA7C0080D658 /* float_tests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = float_tests.h; path = test/float_tests.h; sourceTree = "<group>"; };
E73B575D2161CA7C0080D658 /* half_to_double_from_rfc7049.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = half_to_double_from_rfc7049.c; path = test/half_to_double_from_rfc7049.c; sourceTree = "<group>"; };
diff --git a/inc/qcbor/qcbor_decode.h b/inc/qcbor/qcbor_decode.h
index be03b01..ac6a423 100644
--- a/inc/qcbor/qcbor_decode.h
+++ b/inc/qcbor/qcbor_decode.h
@@ -207,6 +207,8 @@
uint16_t uCount;
/** The value for @c uDataType @ref QCBOR_TYPE_DOUBLE. */
double dfnum;
+ /** The value for @c uDataType @ref QCBOR_TYPE_FLOAT. */
+ float fnum;
/** The value for @c uDataType @ref QCBOR_TYPE_DATE_EPOCH. */
struct {
int64_t nSeconds;
diff --git a/inc/qcbor/qcbor_encode.h b/inc/qcbor/qcbor_encode.h
index 8975f04..8dfc2da 100644
--- a/inc/qcbor/qcbor_encode.h
+++ b/inc/qcbor/qcbor_encode.h
@@ -253,6 +253,7 @@
TODO: -----
+ @anchor Floating-Point
By default QCBOR fully supports IEEE 754 floating-point:
* Encode/decode of double, single and half-precision
* CBOR preferred serialization of floating-point
@@ -615,7 +616,7 @@
/**
- @brief Add a floating-point number to the encoded output.
+ @brief Add a double-precision floating-point number to the encoded output.
@param[in] pCtx The encoding context to add the double to.
@param[in] dNum The double-precision number to add.
@@ -637,9 +638,12 @@
This automatically reduces the size of encoded messages a lot, maybe
even by four if most of values are 0, infinity or NaN.
- On decode, these will always be returned as a double.
+ QCBOR usually returns all decoded floats as a double.
Error handling is the same as QCBOREncode_AddInt64().
+
+ See also QCBOREncode_AddDoubleNoPreferred(), QCBOREncode_AddFloat()
+ and QCBOREncode_AddFloatNoPreferred() and @ref Floating-Point.
*/
void QCBOREncode_AddDouble(QCBOREncodeContext *pCtx, double dNum);
@@ -647,13 +651,66 @@
static void QCBOREncode_AddDoubleToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, double dNum);
-void QCBOREncode_AddFloat(QCBOREncodeContext *pCtx, float dNum);
+
+/**
+ @brief Add a single-precision floating-point number to the encoded output.
+
+ @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
+ single-precision.
+
+ See also QCBOREncode_AddDouble(), QCBOREncode_AddDoubleNoPreferred(),
+ and QCBOREncode_AddFloatNoPreferred() and @ref Floating-Point.
+*/
+void QCBOREncode_AddFloat(QCBOREncodeContext *pCtx, float fNum);
+
+static void QCBOREncode_AddFloatToMap(QCBOREncodeContext *pCtx, const char *szLabel, float fNum);
+
+static void QCBOREncode_AddFloatToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, float dNum);
+/**
+ @brief Add a double-precision floating-point number without preferred encoding.
+ @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.
+
+Error handling is the same as QCBOREncode_AddInt64().
+
+ See also QCBOREncode_AddDouble(), QCBOREncode_AddFloat(),
+ and QCBOREncode_AddFloatNoPreferred() and @ref Floating-Point.
+*/
void QCBOREncode_AddDoubleNoPreferred(QCBOREncodeContext *pCtx, double dNum);
-void QCBOREncode_AddFloatNoPreferred(QCBOREncodeContext *pCtx, float dNum);
+static void QCBOREncode_AddDoubleNoPreferredToMap(QCBOREncodeContext *pCtx, const char *szLabel, double dNum);
+
+static void QCBOREncode_AddDoubleNoPreferredToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, double dNum);
+
+
+/**
+ @brief Add a single-precision floating-point number without preferred encoding.
+
+ @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.
+
+ Error handling is the same as QCBOREncode_AddInt64().
+
+ See also QCBOREncode_AddDouble(), QCBOREncode_AddFloat(),
+ and QCBOREncode_AddDoubleNoPreferred() and @ref Floating-Point.
+*/
+void QCBOREncode_AddFloatNoPreferred(QCBOREncodeContext *pCtx, float fNum);
+
+static void QCBOREncode_AddFloatNoPreferredToMap(QCBOREncodeContext *pCtx, const char *szLabel, float fNum);
+
+static void QCBOREncode_AddFloatNoPreferredToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, float fNum);
@@ -1774,6 +1831,30 @@
QCBOREncode_AddFloat(pCtx, fNum);
}
+static inline void QCBOREncode_AddDoubleNoPreferredToMap(QCBOREncodeContext *pCtx, const char *szLabel, double dNum)
+{
+ QCBOREncode_AddSZString(pCtx, szLabel);
+ QCBOREncode_AddDoubleNoPreferred(pCtx, dNum);
+}
+
+static inline void QCBOREncode_AddDoubleNoPreferredToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, double dNum)
+{
+ QCBOREncode_AddInt64(pCtx, nLabel);
+ QCBOREncode_AddDoubleNoPreferred(pCtx, dNum);
+}
+
+static inline void QCBOREncode_AddFloatNoPreferredToMap(QCBOREncodeContext *pCtx, const char *szLabel, float dNum)
+{
+ QCBOREncode_AddSZString(pCtx, szLabel);
+ QCBOREncode_AddFloatNoPreferred(pCtx, dNum);
+}
+
+static inline void QCBOREncode_AddFloatNoPreferredToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, float dNum)
+{
+ QCBOREncode_AddInt64(pCtx, nLabel);
+ QCBOREncode_AddFloatNoPreferred(pCtx, dNum);
+}
+
static inline void QCBOREncode_AddDateEpoch(QCBOREncodeContext *pCtx, int64_t date)
{
diff --git a/src/qcbor_encode.c b/src/qcbor_encode.c
index c3f2dca..fbad5a9 100644
--- a/src/qcbor_encode.c
+++ b/src/qcbor_encode.c
@@ -575,11 +575,15 @@
}
+/*
+ Public functions for adding a double. See qcbor/qcbor_encode.h
+*/
void QCBOREncode_AddDoubleNoPreferred(QCBOREncodeContext *me, double dNum)
{
QCBOREncode_AddType7(me, sizeof(uint64_t), UsefulBufUtil_CopyDoubleToUint64(dNum));
}
+
/*
Public functions for adding a double. See qcbor/qcbor_encode.h
*/
@@ -595,6 +599,9 @@
}
+/*
+ Public functions for adding a float. See qcbor/qcbor_encode.h
+*/
void QCBOREncode_AddFloatNoPreferred(QCBOREncodeContext *me, float fNum)
{
QCBOREncode_AddType7(me, sizeof(uint32_t), UsefulBufUtil_CopyFloatToUint32(fNum));
@@ -602,7 +609,7 @@
/*
- Public functions for closing arrays and maps. See qcbor.h
+ Public functions for adding a float. See qcbor/qcbor_encode.h
*/
void QCBOREncode_AddFloat(QCBOREncodeContext *me, float fNum)
{
diff --git a/test/float_tests.c b/test/float_tests.c
index dd6b755..d43039d 100644
--- a/test/float_tests.c
+++ b/test/float_tests.c
@@ -450,6 +450,90 @@
}
+/*
+[0.0, 3.14, 0.0, NaN, Infinity, 0.0, 3.140000104904175, 0.0, NaN, Infinity,
+ {100: 0.0, 101: 3.1415926, "euler": 2.718281828459045, 105: 0.0,
+ 102: 0.0, 103: 3.141592502593994, "euler2": 2.7182817459106445, 106: 0.0}]
+ */
+static const uint8_t spExpectedFloats[] = {
+ 0x8B,
+ 0xF9, 0x00, 0x00,
+ 0xFB, 0x40, 0x09, 0x1E, 0xB8, 0x51, 0xEB, 0x85, 0x1F,
+ 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFB, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xF9, 0x00, 0x00,
+ 0xFA, 0x40, 0x48, 0xF5, 0xC3,
+ 0xFA, 0x00, 0x00, 0x00, 0x00,
+ 0xFA, 0x7F, 0xC0, 0x00, 0x00,
+ 0xFA, 0x7F, 0x80, 0x00, 0x00,
+ 0xA8,
+ 0x18, 0x64,
+ 0xF9, 0x00, 0x00,
+ 0x18, 0x65,
+ 0xFB, 0x40, 0x09, 0x21, 0xFB, 0x4D, 0x12, 0xD8, 0x4A,
+ 0x65, 0x65, 0x75, 0x6C, 0x65, 0x72,
+ 0xFB, 0x40, 0x05, 0xBF, 0x0A, 0x8B, 0x14, 0x57, 0x69,
+ 0x18, 0x69,
+ 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x66,
+ 0xF9, 0x00, 0x00,
+ 0x18, 0x67,
+ 0xFA, 0x40, 0x49, 0x0F, 0xDA,
+ 0x66, 0x65, 0x75, 0x6C, 0x65, 0x72, 0x32,
+ 0xFA, 0x40, 0x2D, 0xF8, 0x54,
+ 0x18, 0x6A,
+ 0xFA, 0x00, 0x00, 0x00, 0x00};
+
+int32_t GeneralFloatEncodeTests()
+{
+ UsefulBuf_MAKE_STACK_UB(OutBuffer, sizeof(spExpectedFloats));
+
+ QCBOREncodeContext EC;
+ QCBOREncode_Init(&EC, OutBuffer);
+ QCBOREncode_OpenArray(&EC);
+
+ QCBOREncode_AddDouble(&EC, 0.0);
+ QCBOREncode_AddDouble(&EC, 3.14);
+ QCBOREncode_AddDoubleNoPreferred(&EC, 0.0);
+ QCBOREncode_AddDoubleNoPreferred(&EC, NAN);
+ QCBOREncode_AddDoubleNoPreferred(&EC, INFINITY);
+
+ QCBOREncode_AddFloat(&EC, 0.0);
+ QCBOREncode_AddFloat(&EC, 3.14f);
+ QCBOREncode_AddFloatNoPreferred(&EC, 0.0f);
+ QCBOREncode_AddFloatNoPreferred(&EC, NAN);
+ QCBOREncode_AddFloatNoPreferred(&EC, INFINITY);
+
+ QCBOREncode_OpenMap(&EC);
+
+ QCBOREncode_AddDoubleToMapN(&EC, 100, 0.0);
+ QCBOREncode_AddDoubleToMapN(&EC, 101, 3.1415926);
+ QCBOREncode_AddDoubleToMap(&EC, "euler", 2.71828182845904523536);
+ QCBOREncode_AddDoubleNoPreferredToMapN(&EC, 105, 0.0);
+
+ QCBOREncode_AddFloatToMapN(&EC, 102, 0.0f);
+ QCBOREncode_AddFloatToMapN(&EC, 103, 3.1415926f);
+ QCBOREncode_AddFloatToMap(&EC, "euler2", 2.71828182845904523536f);
+ QCBOREncode_AddFloatNoPreferredToMapN(&EC, 106, 0.0f);
+
+ QCBOREncode_CloseMap(&EC);
+ QCBOREncode_CloseArray(&EC);
+
+ UsefulBufC Encoded;
+ QCBORError uErr = QCBOREncode_Finish(&EC, &Encoded);
+ if(uErr) {
+ return -1;
+ }
+
+ if(UsefulBuf_Compare(Encoded, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats))) {
+ return -3;
+ }
+
+ return 0;
+}
+
+
#ifdef NAN_EXPERIMENT
/*
diff --git a/test/float_tests.h b/test/float_tests.h
index 2b997f7..0e889ea 100644
--- a/test/float_tests.h
+++ b/test/float_tests.h
@@ -23,6 +23,9 @@
int32_t HalfPrecisionAgainstRFCCodeTest(void);
+int32_t GeneralFloatEncodeTests(void);
+
+
#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
diff --git a/test/run_tests.c b/test/run_tests.c
index 0f40e93..f0440bb 100644
--- a/test/run_tests.c
+++ b/test/run_tests.c
@@ -95,6 +95,7 @@
TEST_ENTRY(HalfPrecisionDecodeBasicTests),
TEST_ENTRY(DoubleAsSmallestTest),
TEST_ENTRY(HalfPrecisionAgainstRFCCodeTest),
+ TEST_ENTRY(GeneralFloatEncodeTests),
#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
TEST_ENTRY(BstrWrapTest),
TEST_ENTRY(BstrWrapErrorTest),