Big number code tidy and documentation update
Move the big number, big float and decimal fractions around to group them better
Clearly comment the deprecated functions
Improve documentation for big numbers, big floats and decimal fractions
Improve test coverage for big numbers a little
Optimize big number encoding
* big number and exp mantissa tidy up
* Big number documentation
* Fix commits of XCode project files
* documentation improvements
* Remove junk
---------
Co-authored-by: Laurence Lundblade <lgl@securitytheory.com>
diff --git a/src/qcbor_encode.c b/src/qcbor_encode.c
index 47208a8..a8f01fe 100644
--- a/src/qcbor_encode.c
+++ b/src/qcbor_encode.c
@@ -795,8 +795,8 @@
*
* @return If there is a carry, \c true.
*
- * If this returns @c true, then @c BigNumber - 1 is
- * one byte shorter than @c BigNumber.
+ * If this returns @c true, then @c BigNumber - 1 is one byte shorter
+ * than @c BigNumber.
**/
static bool
QCBOREncode_Private_BigNumberCarry(const UsefulBufC BigNumber)
@@ -821,7 +821,7 @@
}
-/*
+/**
* @brief Output negative bignum bytes with subtraction of 1.
*
* @param[in] pMe The decode context.
@@ -864,7 +864,7 @@
if(bCarry && BigNumber.len > 1 && UsefulBufC_NTH_BYTE(BigNumber, 0) >= 1) {
uLen--;
}
- QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_TYPE_BYTE_STRING, uLen, 0);
+ QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_TYPE_BYTE_STRING, uLen,0);
SubString = BigNumber;
bCopiedSomething = false;
@@ -887,61 +887,19 @@
/**
- * @brief Convert a negative big number to unsigned int if possible.
- *
- * @param[in] BigNumber The negative big number.
- * @param[out] puInt The converted negative big number.
- *
- * @return If conversion was possible, returns @c true.
- *
- * The parameters here are unsigned integers, but they always
- * represent negative numbers.
- *
- * Conversion is possible if the big number is greater than -(2^64).
- * Conversion include offset of 1 for encoding CBOR negative numbers.
- */
-static bool
-QCBOREncode_Private_NegativeBigNumberToUInt(const UsefulBufC BigNumber, uint64_t *puInt)
-{
- bool bIs2exp64;
-
- static const uint8_t twoExp64[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-
- bIs2exp64 = ! UsefulBuf_Compare(BigNumber, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(twoExp64));
-
- if(BigNumber.len > 8 && !bIs2exp64) {
- return false;
- }
-
- /* Must convert to CBOR type 1, a negative integer */
- if(bIs2exp64) {
- /* 2^64 is a 9 byte big number. Since negative numbers are offset
- * by one in CBOR, it can be encoded as a type 1 negative. The
- * conversion below won't work because the uInt will overflow
- * before the subtraction of 1.
- */
- *puInt = UINT64_MAX;
- } else {
- *puInt = QCBOREncode_Private_BigNumberToUInt(BigNumber);
- (*puInt)--; /* CBOR's negative offset of 1 */
- }
- return true;
-}
-
-
-/**
* @brief Remove leading zeros.
*
- * @param[in] BigNumber The negative big number.
+ * @param[in] BigNumber The big number.
*
* @return Big number with no leading zeros.
*
- * If the big number is all zeros, this returns a big number
- * that is one zero rather than the empty string.
+ * If the big number is all zeros, this returns a big number that is
+ * one zero rather than the empty string.
*
- * 3.4.3 does not explicitly decoders MUST handle the empty string,
- * but does say decoders MUST handle leading zeros. So Postel's Law
- * is applied here and 0 is not encoded as an empty string.
+ * RFC 8949 3.4.3 does not explicitly decoders MUST handle the empty
+ * string, but does say decoders MUST handle leading zeros. So
+ * Postel's Law is applied here and 0 is not encoded as an empty
+ * string.
*/
static UsefulBufC
QCBOREncode_Private_SkipLeadingZeros(const UsefulBufC BigNumber)
@@ -950,63 +908,82 @@
NLZ = UsefulBuf_SkipLeading(BigNumber, 0x00);
/* An all-zero string reduces to one 0, not an empty string. */
- if(NLZ.len == 0 && BigNumber.len > 0 && UsefulBufC_NTH_BYTE(BigNumber, 0) == 0x00) {
- NLZ.len++;
+ if(NLZ.len == 0 &&
+ BigNumber.len > 0 &&
+ UsefulBufC_NTH_BYTE(BigNumber, 0) == 0x00) {
+ NLZ.len = 1;
}
return NLZ;
}
-/*
- * Public functions for adding a big number. See qcbor/qcbor_encode.h
+/**
+ * @brief Output a big number, preferred or not, with negative offset
+ *
+ * @param[in] pMe The decode context.
+ * @param[in] uTagRequirement Either @ref QCBOR_ENCODE_AS_TAG or
+ * @ref QCBOR_ENCODE_AS_BORROWED.
+ * @param[in] bPreferred Uses preferred serialization if true
+ * @param[in] bNegative Indicates big number is negative or postive.
+ * @param[in] BigNumber The big number.
+ *
+ * Regardless of whether preferred serialization is used, if the big
+ * number is negative, one is subtracted before is output per CBOR
+ * convetion for big numbers. This requires a little big number
+ * arithmetic and adds some object code.
+ *
+ * If preferred serialization is used, then if the number is smaller
+ * than UINT64_MAX and postive it is output as type 0 and if it is
+ * equal to or smaller than UINT64_MAX it is output as a type 1
+ * integer minus one.
+ *
+ * See QCBOREncode_AddTBigNumberRaw() for simple copy through.
*/
void
-QCBOREncode_AddTBigNumber(QCBOREncodeContext *pMe,
- const uint8_t uTagRequirement,
- const bool bNegative,
- const UsefulBufC BigNumber)
+QCBOREncode_Private_AddTBigNumberMain(QCBOREncodeContext *pMe,
+ const uint8_t uTagRequirement,
+ const bool bPreferred,
+ const bool bNegative,
+ const UsefulBufC BigNumber)
{
- uint64_t uInt;
+ uint64_t uInt;
+ bool bIs2exp64;
+ uint8_t uMajorType;
+ UsefulBufC BigNumberNLZ;
- const UsefulBufC BigNumberNLZ = QCBOREncode_Private_SkipLeadingZeros(BigNumber);
+ BigNumberNLZ = QCBOREncode_Private_SkipLeadingZeros(BigNumber);
- /* Preferred serialization requires reduction to type 0 and 1 integers */
- if(bNegative) {
- if(QCBOREncode_Private_NegativeBigNumberToUInt(BigNumberNLZ, &uInt)) {
- /* Might be a 65-bit negative; use special add method for such */
- QCBOREncode_AddNegativeUInt64(pMe, uInt);
+ static const uint8_t twoExp64[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ bIs2exp64 = ! UsefulBuf_Compare(BigNumber, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(twoExp64));
+
+ if(bPreferred && (BigNumberNLZ.len <= 8 || (bNegative && bIs2exp64))) {
+ if(bIs2exp64) {
+ /* 2^64 is a 9 byte big number. Since negative numbers are offset
+ * by one in CBOR, it can be encoded as a type 1 negative. The
+ * conversion below won't work because the uInt will overflow
+ * before the subtraction of 1.
+ */
+ uInt = UINT64_MAX;
} else {
+ uInt = QCBOREncode_Private_BigNumberToUInt(BigNumberNLZ);
+ if(bNegative) {
+ uInt--;
+ }
+ }
+ uMajorType = bNegative ? CBOR_MAJOR_TYPE_NEGATIVE_INT :
+ CBOR_MAJOR_TYPE_POSITIVE_INT;
+ QCBOREncode_Private_AppendCBORHead(pMe, uMajorType, uInt, 0);
+ } else {
+ if(bNegative) {
QCBOREncode_Private_AddTNegativeBigNumber(pMe, uTagRequirement, BigNumberNLZ);
- }
-
- } else {
- if(BigNumberNLZ.len <= sizeof(uint64_t)) {
- QCBOREncode_AddUInt64(pMe, QCBOREncode_Private_BigNumberToUInt(BigNumberNLZ));
} else {
- QCBOREncode_AddTBigNumberRaw(pMe, bNegative, uTagRequirement, BigNumberNLZ);
+ QCBOREncode_AddTBigNumberRaw(pMe, false, uTagRequirement, BigNumberNLZ);
}
}
}
-/*
- * Public functions for adding a big number. See qcbor/qcbor_encode.h
- */
-void
-QCBOREncode_AddTBigNumberNoPreferred(QCBOREncodeContext *pMe,
- const uint8_t uTagRequirement,
- const bool bNegative,
- const UsefulBufC BigNumber)
-{
- const UsefulBufC BigNumberNLZ = QCBOREncode_Private_SkipLeadingZeros(BigNumber);
-
- if(bNegative) {
- QCBOREncode_Private_AddTNegativeBigNumber(pMe, uTagRequirement, BigNumberNLZ);
- } else {
- QCBOREncode_AddTBigNumberRaw(pMe, false, uTagRequirement, BigNumberNLZ);
- }
-}
#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
@@ -1078,7 +1055,7 @@
* that has no effect on the code here.
*/
if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
- QCBOREncode_AddTag(pMe, uTagNumber);
+ QCBOREncode_AddTagNumber(pMe, uTagNumber);
}
QCBOREncode_OpenArray(pMe);
QCBOREncode_AddInt64(pMe, nExponent);
@@ -1107,7 +1084,7 @@
* for CBOR negative numbers.
*/
if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
- QCBOREncode_AddTag(pMe, uTagNumber);
+ QCBOREncode_AddTagNumber(pMe, uTagNumber);
}
QCBOREncode_OpenArray(pMe);
QCBOREncode_AddInt64(pMe, nExponent);