integer conversion tests passing (but incomplete)
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index bde6785..f5995fe 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -2582,8 +2582,81 @@
}
+/**
+ @param[in] bMustBeTagged If \c true, then the data item must be tagged as either
+ a positive or negative bignum. If \c false, then it only must be a byte string and bIsNegative
+ will always be false on the asumption that it is positive, but it can be interpretted as
+ negative if the the sign is know from other context.
+ @param[out] pValue The bytes that make up the big num
+ @param[out] pbIsNegative \c true if tagged as a negative big num. \c false otherwise.
+
+ if bMustBeTagged is false, then this will succeed if the data item is a plain byte string,
+ a positive big num or a negative big num.
+
+ */
+void QCBORDecode_GetBignum(QCBORDecodeContext *pMe, bool bMustBeTagged, UsefulBufC *pValue, bool *pbIsNegative)
+{
+ if(pMe->uLastError != QCBOR_SUCCESS) {
+ // Already in error state, do nothing
+ return;
+ }
+
+ QCBORError nError;
+ QCBORItem Item;
+
+ nError = QCBORDecode_GetNext(pMe, &Item);
+ if(nError != QCBOR_SUCCESS) {
+ pMe->uLastError = (uint8_t)nError;
+ return;
+ }
+
+ *pbIsNegative = false;
+
+ switch(Item.uDataType) {
+ case QCBOR_TYPE_BYTE_STRING:
+ // TODO: check that there is no tag here?
+ if(bMustBeTagged) {
+ pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
+ } else {
+ *pValue = Item.val.string;
+ }
+ break;
+
+ case QCBOR_TYPE_POSBIGNUM:
+ *pValue = Item.val.string;
+ break;
+
+ case QCBOR_TYPE_NEGBIGNUM:
+ *pbIsNegative = true;
+ *pValue = Item.val.string;
+ break;
+
+ default:
+ pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
+ break;
+ }
+}
+
void QCBORDecode_GetPosBignum(QCBORDecodeContext *pMe, UsefulBufC *pValue)
{
+ // Has to be either a positive big num or a byte string
+ /*
+ an array of bytestrings and bignums. Tagging is necessary
+ to tell them apart
+
+ A labeled item where the label tells you it is a big
+ num and there be no tagging
+
+ An array where you expect a big num is the next thing
+ and it must be tagged so.
+
+
+ Some protocols will require it to be tagged because
+ it will be ambigous if not.
+
+
+
+ */
// TODO: do these have to be tagged?
// Probably should allow tagged or untagged, but not wrong-tagged
QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_POSBIGNUM);
@@ -2638,33 +2711,33 @@
will not fit in an int64_t and this will error out with
under or overflow
*/
-static QCBORError Exponentitate2UU(uint64_t nMantissa, int64_t nExponent, uint64_t *pnResult)
+static QCBORError Exponentitate2UU(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
{
- uint64_t nResult;
+ uint64_t uResult;
- nResult = nMantissa;
+ uResult = uMantissa;
/* This loop will run a maximum of 64 times because
* INT64_MAX < 2^31. More than that will cause
* exist with the overflow error
*/
while(nExponent > 0) {
- if(nResult > UINT64_MAX >> 1) {
+ if(uResult > UINT64_MAX >> 1) {
return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
}
- nResult = nResult << 1;
+ uResult = uResult << 1;
nExponent--;
}
while(nExponent < 0 ) {
- if(nResult == 0) {
+ if(uResult == 0) {
return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
}
- nResult = nResult >> 1;
+ uResult = uResult >> 1;
nExponent--;
}
- *pnResult = nResult;
+ *puResult = uResult;
return QCBOR_SUCCESS;
}
@@ -2718,31 +2791,6 @@
}
-// TODO: use this or get rid of it
-QCBORError ExponentitateUN(uint64_t uMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
-{
- uint64_t uResult;
-
- QCBORError uR;
-
- uR = (*pfExp)(uMantissa, nExponent, &uResult);
- if(uR) {
- return uR;
- }
-
- if(uResult > INT64_MAX) {
- return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
- }
-
- // Cast is OK because of check above
- *pnResult = (int64_t)uResult;
-
- return QCBOR_SUCCESS;
-}
-
-
-
-
#include <math.h>
/*
static inline uint8_t Exponentitate10F(uint64_t uMantissa, int64_t nExponent, double *pfResult)
@@ -2756,10 +2804,6 @@
*/
-
-
-
-
/*
A) bignum is positive
A1) output is signed INT64_MAX
@@ -2768,7 +2812,7 @@
B1) output is signed INT64_MAX
B2) output is unsigned error
*/
-static inline QCBORError ConvertBigNum(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
+static inline QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
{
uint64_t uResult;
@@ -2809,15 +2853,15 @@
static inline QCBORError ConvertPositiveBigNumToUnSigned(const UsefulBufC BigNum, uint64_t *pResult)
{
- return ConvertBigNum(BigNum, UINT64_MAX, pResult);
+ return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
}
static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
{
uint64_t uResult;
- QCBORError n = ConvertBigNum(BigNum, INT64_MAX, &uResult);
- if(n) {
- return n;
+ QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
+ if(uError) {
+ return uError;
}
/* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
*pResult = (int64_t)uResult;
@@ -2828,53 +2872,34 @@
static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
{
uint64_t uResult;
- QCBORError n = ConvertBigNum(BigNum, INT64_MAX-1, &uResult);
- if(n) {
- return n;
+ QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX-1, &uResult);
+ if(uError) {
+ return uError;
}
/* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
*pResult = -(int64_t)uResult;
- return 0;
+ return QCBOR_SUCCESS;
}
-// No function to convert a negative bignum to unsigned; it is an error
-
-
-#if 0
-static inline int ConvertXYZ(const UsefulBufC Mantissa, int64_t nExponent, int64_t *pResult)
-{
- int64_t nMantissa;
-
- int xx = ConvertPositiveBigNumToSigned(Mantissa, &nMantissa);
- if(xx) {
- return xx;
- }
-
- return ExponentiateNN(nMantissa, nExponent, pResult, &Exponentitate10UU);
-}
-
-#endif
#include "fenv.h"
-/*
- Get the next item as an int64_t. The CBOR type can be unsigned, negative, float
- a big float, a decimal fraction or a big num. Conversion will be dones as
- expected. Some cases will error out with under or over flow.
- */
-void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue, QCBORItem *pItem)
+
+void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
+ uint32_t uOptions,
+ int64_t *pValue,
+ QCBORItem *pItem)
{
if(pMe->uLastError != QCBOR_SUCCESS) {
return;
}
QCBORItem Item;
- QCBORError nError;
- nError = QCBORDecode_GetNext(pMe, &Item);
- if(nError) {
- pMe->uLastError = (uint8_t)nError;
+ QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
+ if(uError) {
+ pMe->uLastError = (uint8_t)uError;
return;
}
@@ -2925,12 +2950,9 @@
}
-
/*
- Get the next item as an int64_t. The CBOR type can be unsigned, negative, float
- a big float, a decimal fraction or a big num. Conversion will be dones as
- expected. Some cases will error out with under or over flow.
- */
+ Public function, see header qcbor/qcbor_decode.h file
+*/
void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue)
{
QCBORItem Item;
@@ -3057,18 +3079,20 @@
-void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue, QCBORItem *pItem)
+void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
+ uint32_t uOptions,
+ uint64_t *pValue,
+ QCBORItem *pItem)
{
if(pMe->uLastError != QCBOR_SUCCESS) {
return;
}
QCBORItem Item;
- QCBORError nError;
- nError = QCBORDecode_GetNext(pMe, &Item);
- if(nError) {
- pMe->uLastError = (uint8_t)nError;
+ QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
+ if(uError) {
+ pMe->uLastError = (uint8_t)uError;
return;
}
@@ -3125,7 +3149,9 @@
}
-
+/*
+ Public function, see header qcbor/qcbor_decode.h file
+*/
void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue)
{
QCBORItem Item;
@@ -3169,7 +3195,7 @@
pValue,
Exponentitate10UU);
} else {
- pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
+ pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
}
break;
@@ -3180,7 +3206,7 @@
pValue,
Exponentitate2UU);
} else {
- pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
+ pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
}
break;
@@ -3197,7 +3223,7 @@
Exponentitate10UU);
}
} else {
- pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
+ pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
}
break;
@@ -3205,7 +3231,7 @@
if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
pMe->uLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
} else {
- pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
+ pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
}
break;
@@ -3220,7 +3246,7 @@
Exponentitate2UU);
}
} else {
- pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED; // TODO: error code
+ pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
}
break;
@@ -3238,16 +3264,18 @@
}
-void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, double *pValue, QCBORItem *pItem)
+void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
+ uint32_t uOptions,
+ double *pValue,
+ QCBORItem *pItem)
{
if(pMe->uLastError != QCBOR_SUCCESS) {
return;
}
QCBORItem Item;
- QCBORError uError;
- uError = QCBORDecode_GetNext(pMe, &Item);
+ QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
if(uError) {
pMe->uLastError = (uint8_t)uError;
return;
@@ -3293,13 +3321,16 @@
/*
-
-
- https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
-
- */
+ Public function, see header qcbor/qcbor_decode.h file
+*/
void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pValue)
{
+ /*
+
+
+ https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
+
+ */
QCBORItem Item;
QCBORDecode_GetDoubleConvertInternal(pMe, uOptions, pValue, &Item);
@@ -3314,6 +3345,8 @@
return;
}
+ pMe->uLastError = QCBOR_SUCCESS;
+
switch(Item.uDataType) {
// TODO: type float
case QCBOR_TYPE_DECIMAL_FRACTION:
@@ -3386,6 +3419,9 @@
pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
}
break;
+
+ default:
+ pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
}
}
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index 17bf79d..d0589cb 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -4000,7 +4000,7 @@
QCBORError uErrorDouble;
};
-static struct NumberConversion NumberConversions[] = {
+static const struct NumberConversion NumberConversions[] = {
{
"Big float 3 * 2^^2",
{(uint8_t[]){0xC5, 0x82, 0x02, 0x03}, 4},
@@ -4107,71 +4107,71 @@
-
int32_t IntegerConvertTest2()
{
const size_t nNumTests = sizeof(NumberConversions)/sizeof(struct NumberConversion);
- for(struct NumberConversion *pF = NumberConversions; pF < NumberConversions + nNumTests; pF++) {
+ for(const struct NumberConversion *pF = NumberConversions; pF < NumberConversions + nNumTests; pF++) {
+ const size_t nIndex = (size_t)(pF - NumberConversions)/sizeof(struct NumberConversion);
+
// Set up the decoding context including a memory pool so that
// indefinite length items can be checked
QCBORDecodeContext DCtx;
- QCBORDecode_Init(&DCtx, pF->CBOR, QCBOR_DECODE_MODE_NORMAL);
UsefulBuf_MAKE_STACK_UB(Pool, 100);
+
+ /* ----- test conversion to int64_t ------ */
+ QCBORDecode_Init(&DCtx, pF->CBOR, QCBOR_DECODE_MODE_NORMAL);
QCBORError nCBORError = QCBORDecode_SetMemPool(&DCtx, Pool, 0);
if(nCBORError) {
- return -9;
+ return (int32_t)(1000+nIndex);
}
int64_t nInt;
- DCtx.uLastError = 0;
QCBORDecode_GetInt64ConvertAll(&DCtx, 0xffff, &nInt);
if(QCBORDecode_GetError(&DCtx) != pF->uErrorInt64) {
- return -99;
+ return (int32_t)(2000+nIndex);
}
if(pF->uErrorInt64 == QCBOR_SUCCESS && pF->nConvertedToInt64 != nInt) {
- return -888;
+ return (int32_t)(3000+nIndex);
}
-
+ /* ----- test conversion to uint64_t ------ */
QCBORDecode_Init(&DCtx, pF->CBOR, QCBOR_DECODE_MODE_NORMAL);
nCBORError = QCBORDecode_SetMemPool(&DCtx, Pool, 0);
if(nCBORError) {
- return -9;
+ return (int32_t)(1000+nIndex);
}
uint64_t uInt;
- DCtx.uLastError = 0;
QCBORDecode_GetUInt64ConvertAll(&DCtx, 0xffff, &uInt);
if(QCBORDecode_GetError(&DCtx) != pF->uErrorUint64) {
- return -99;
+ return (int32_t)(4000+nIndex);
}
if(pF->uErrorUint64 == QCBOR_SUCCESS && pF->uConvertToUInt64 != uInt) {
- return -888;
+ return (int32_t)(5000+nIndex);
}
-
+ /* ----- test conversion to double ------ */
QCBORDecode_Init(&DCtx, pF->CBOR, QCBOR_DECODE_MODE_NORMAL);
nCBORError = QCBORDecode_SetMemPool(&DCtx, Pool, 0);
if(nCBORError) {
- return -9;
+ return (int32_t)(1000+nIndex);
}
double d;
- DCtx.uLastError = 0;
QCBORDecode_GetDoubleConvertAll(&DCtx, 0xffff, &d);
if(QCBORDecode_GetError(&DCtx) != pF->uErrorDouble) {
- return -99;
+ return (int32_t)(6000+nIndex);
}
if(pF->uErrorDouble == QCBOR_SUCCESS) {
if(isnan(pF->dConvertToDouble)) {
// NaN's can't be compared for equality. A NaN is
// never equal to anything including another NaN
if(!isnan(d)) {
- return -4;
+ return (int32_t)(7000+nIndex);
}
} else {
// TODO: this comparison may need a margin of error
if(pF->dConvertToDouble != d) {
- return -5;
+ return (int32_t)(8000+nIndex);
}
}
}
@@ -4182,7 +4182,10 @@
int32_t IntegerConvertTest()
{
- (void)IntegerConvertTest2();
+ int32_t nReturn = IntegerConvertTest2();
+ if(nReturn) {
+ return nReturn;
+ }
QCBORDecodeContext DCtx;
QCBORError nCBORError;
@@ -4291,7 +4294,7 @@
// 4([9223372036854775807, -4759477275222530853137]),
QCBORDecode_GetUInt64ConvertAll(&DCtx, QCBOR_CONVERT_TYPE_DECIMAL_FRACTION, &uinteger);
- if(QCBORDecode_GetError(&DCtx) != QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW) {
+ if(QCBORDecode_GetError(&DCtx) != QCBOR_ERR_NUMBER_SIGN_CONVERSION) {
return -2;
}
DCtx.uLastError = 0; // TODO: a method for this
@@ -4312,14 +4315,14 @@
// 5([-9223372036854775807, -4759477275222530853137])
QCBORDecode_GetUInt64ConvertAll(&DCtx, QCBOR_CONVERT_TYPE_DECIMAL_FRACTION|QCBOR_CONVERT_TYPE_BIGFLOAT, &uinteger);
- if(QCBORDecode_GetError(&DCtx) != QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW) {
+ if(QCBORDecode_GetError(&DCtx) != QCBOR_ERR_NUMBER_SIGN_CONVERSION) {
return -2;
}
DCtx.uLastError = 0; // TODO: a method for this
// 5([ 9223372036854775806, -4759477275222530853137])
QCBORDecode_GetUInt64ConvertAll(&DCtx, QCBOR_CONVERT_TYPE_DECIMAL_FRACTION|QCBOR_CONVERT_TYPE_BIGFLOAT, &uinteger);
- if(QCBORDecode_GetError(&DCtx) != QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW) {
+ if(QCBORDecode_GetError(&DCtx) != QCBOR_ERR_NUMBER_SIGN_CONVERSION) {
return -2;
}
DCtx.uLastError = 0; // TODO: a method for this