bug fix in mantissa exponent decoding; big float and decimal fraction fixes
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index a0e39bb..e75449c 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -1691,6 +1691,7 @@
nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
goto Done;
}
+ pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel; // TODO: make sure this is right
Done:
@@ -4408,65 +4409,75 @@
#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
-static void ProcessDecimalFraction(QCBORDecodeContext *pMe,
- uint8_t uTagRequirement,
+static QCBORError FooCheck(QCBORDecodeContext *pMe, TagSpecification TagSpec, QCBORItem *pItem)
+{
+ QCBORError uErr;
+ // Loops runs at most 1.5 times. Making it a loop saves object code.
+
+ while(1) {
+ uErr = CheckTagRequirement(TagSpec, pItem->uDataType);
+ if(uErr != QCBOR_SUCCESS) {
+ goto Done;
+ }
+
+ if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
+ break; // Successful exit. Moving on to finish decoding.
+ }
+
+ // The item is an array, which means an undecoded
+ // mantissa and exponent, so decode it. It will then
+ // have a different type and exit the loop if.
+ uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
+ if(uErr != QCBOR_SUCCESS) {
+ goto Done;
+ }
+
+ // Second time around, the type must match.
+ TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_MATCH_TAG;
+ }
+Done:
+ return uErr;
+}
+
+static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
+ TagSpecification TagSpec,
QCBORItem *pItem,
int64_t *pnMantissa,
int64_t *pnExponent)
{
QCBORError uErr;
-
- if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
- if(uTagRequirement == QCBOR_TAG_REQUIREMENT_NO_TAG) {
- pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
- return;
- }
- /* The decimal fraction was untagged so it shows up as an
- array at this point. We are called to interpret it
- as a decimal fraction, so do protocol decoding. If
- it was tagged, iw would shouw up here with the
- QCBOR_TYPE_DECIMAL_FRACTION or such. */
- uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
- if(uErr != QCBOR_SUCCESS) {
- pMe->uLastError = (uint8_t)uErr;
- return;
- }
- }
-
- if(uTagRequirement == QCBOR_TAG_REQUIREMENT_NO_TAG) {
- pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
- return;
+ uErr = FooCheck(pMe, TagSpec, pItem);
+ if(uErr != QCBOR_SUCCESS) {
+ goto Done;
}
switch (pItem->uDataType) {
case QCBOR_TYPE_DECIMAL_FRACTION:
+ case QCBOR_TYPE_BIGFLOAT:
*pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
*pnExponent = pItem->val.expAndMantissa.nExponent;
break;
case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
+ case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
*pnExponent = pItem->val.expAndMantissa.nExponent;
-
uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
- if(uErr != QCBOR_SUCCESS) {
- pMe->uLastError = (uint8_t)uErr;
- }
break;
case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
+ case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
*pnExponent = pItem->val.expAndMantissa.nExponent;
-
uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
- if(uErr != QCBOR_SUCCESS) {
- pMe->uLastError = (uint8_t)uErr;
- }
break;
default:
- pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
+ uErr = QCBOR_ERR_UNEXPECTED_TYPE;
}
+
+ Done:
+ pMe->uLastError = (uint8_t)uErr;
}
@@ -4486,7 +4497,12 @@
return;
}
- ProcessDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
+ const TagSpecification TagSpec = {uTagRequirement,
+ {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
+ {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+ };
+
+ ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
}
@@ -4499,7 +4515,13 @@
QCBORItem Item;
QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
- ProcessDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
+
+ const TagSpecification TagSpec = {uTagRequirement,
+ {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
+ {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+ };
+
+ ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
}
@@ -4512,15 +4534,46 @@
QCBORItem Item;
QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
+
+ const TagSpecification TagSpec = {uTagRequirement,
+ {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
+ {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+ };
+
- ProcessDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
+ ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
}
+
+
+void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
+ uint8_t uTagRequirement,
+ int64_t *pnMantissa,
+ int64_t *pnExponent)
+{
+ if(pMe->uLastError != QCBOR_SUCCESS) {
+ return;
+ }
+
+ QCBORItem Item;
+ QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
+ if(uError) {
+ pMe->uLastError = (uint8_t)uError;
+ return;
+ }
+ const TagSpecification TagSpec = {uTagRequirement,
+ {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
+ {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+ };
+
+ ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
+}
+
#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
{
- while(uInt & 0xff0000000000UL) {
+ while((uInt & 0xff00000000000000UL) == 0) {
uInt = uInt << 8;
};
@@ -4529,8 +4582,10 @@
UsefulOutBuf_Init(&UOB, Buffer);
while(uInt) {
- UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff0000000000UL) >> 56));
+ const uint64_t xx = uInt & 0xff00000000000000UL;
+ UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
uInt = uInt << 8;
+ (void)xx;
}
return UsefulOutBuf_OutUBuf(&UOB);
@@ -4539,32 +4594,19 @@
#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
-static void ProcessDecimalFractionBig(QCBORDecodeContext *pMe,
- uint8_t uTagRequirement,
- QCBORItem *pItem,
- UsefulBuf BufferForMantissa,
- UsefulBufC *pMantissa,
- bool *pbIsNegative,
- int64_t *pnExponent)
+static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
+ TagSpecification TagSpec,
+ QCBORItem *pItem,
+ UsefulBuf BufferForMantissa,
+ UsefulBufC *pMantissa,
+ bool *pbIsNegative,
+ int64_t *pnExponent)
{
+ QCBORError uErr;
- const TagSpecification TagSpec = {uTagRequirement,
- {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
- {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
- };
-
- QCBORError uErr = CheckTagRequirement(TagSpec, pItem->uDataType);
+ uErr = FooCheck(pMe, TagSpec, pItem);
if(uErr != QCBOR_SUCCESS) {
- pMe->uLastError = (uint8_t)uErr;
- return;
- }
-
- if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
- uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
- if(uErr != QCBOR_SUCCESS) {
- pMe->uLastError = (uint8_t)uErr;
- return;
- }
+ goto Done;
}
uint64_t uMantissa;
@@ -4572,6 +4614,7 @@
switch (pItem->uDataType) {
case QCBOR_TYPE_DECIMAL_FRACTION:
+ case QCBOR_TYPE_BIGFLOAT:
if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
*pbIsNegative = false;
@@ -4584,20 +4627,25 @@
break;
case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
+ case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
*pnExponent = pItem->val.expAndMantissa.nExponent;
*pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
*pbIsNegative = false;
break;
case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
+ case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
*pnExponent = pItem->val.expAndMantissa.nExponent;
*pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
*pbIsNegative = true;
break;
default:
- pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
+ uErr = QCBOR_ERR_UNEXPECTED_TYPE;
}
+
+Done:
+ pMe->uLastError = (uint8_t)uErr;
}
@@ -4620,7 +4668,12 @@
return;
}
- ProcessDecimalFractionBig(pMe, uTagRequirement, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
+ const TagSpecification TagSpec = {uTagRequirement,
+ {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
+ {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+ };
+
+ ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
}
@@ -4639,11 +4692,92 @@
return;
}
- ProcessDecimalFractionBig(pMe, uTagRequirement, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
+ const TagSpecification TagSpec = {uTagRequirement,
+ {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
+ {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+ };
+
+ ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
}
void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
+ uint8_t uTagRequirement,
+ const char *szLabel,
+ UsefulBuf BufferForMantissa,
+ UsefulBufC *pMantissa,
+ bool *pbIsNegative,
+ int64_t *pnExponent)
+{
+ QCBORItem Item;
+
+ QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
+ if(pMe->uLastError != QCBOR_SUCCESS) {
+ return;
+ }
+
+ const TagSpecification TagSpec = {uTagRequirement,
+ {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM},
+ {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+ };
+
+ ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
+}
+
+
+void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
+ uint8_t uTagRequirement,
+ UsefulBuf MantissaBuffer,
+ UsefulBufC *pMantissa,
+ bool *pbMantissaIsNegative,
+ int64_t *pnExponent)
+{
+
+ if(pMe->uLastError != QCBOR_SUCCESS) {
+ return;
+ }
+
+ QCBORItem Item;
+ QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
+ if(uError) {
+ pMe->uLastError = (uint8_t)uError;
+ return;
+ }
+
+ const TagSpecification TagSpec = {uTagRequirement,
+ {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM , QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
+ {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+ };
+
+ ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
+
+}
+
+void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
+ uint8_t uTagRequirement,
+ int64_t nLabel,
+ UsefulBuf BufferForMantissa,
+ UsefulBufC *pMantissa,
+ bool *pbIsNegative,
+ int64_t *pnExponent)
+{
+ QCBORItem Item;
+
+ QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
+ if(pMe->uLastError != QCBOR_SUCCESS) {
+ return;
+ }
+
+ const TagSpecification TagSpec = {uTagRequirement,
+ {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM , QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
+ {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+ };
+
+ ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
+}
+
+
+void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
uint8_t uTagRequirement,
const char *szLabel,
UsefulBuf BufferForMantissa,
@@ -4658,7 +4792,12 @@
return;
}
- ProcessDecimalFractionBig(pMe, uTagRequirement, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
+ const TagSpecification TagSpec = {uTagRequirement,
+ {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM , QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM},
+ {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+ };
+
+ ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
}
#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */