Merge branch 'AdvancedDecode' of https://github.com/laurencelundblade/QCBOR into AdvancedDecode
diff --git a/inc/qcbor/qcbor_decode.h b/inc/qcbor/qcbor_decode.h
index af1354e..fba80be 100644
--- a/inc/qcbor/qcbor_decode.h
+++ b/inc/qcbor/qcbor_decode.h
@@ -904,7 +904,7 @@
 
 
 /**
- Check whether all the bytes have been decoded and maps and arrays closed.
+ @brief Check whether all the bytes have been decoded and maps and arrays closed.
 
  @param[in]  pCtx  The context to check.
 
@@ -944,17 +944,58 @@
 static QCBORError QCBORDecode_GetLastError(QCBORDecodeContext *pCtx);
 
 
-void QCBORDecode_GetInt64Convert(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue);
+/**
+ @brief Decode next item as a 64-bit integer
 
+ @param[in] pCtx   The decode context
+ @param[in] uOptions The integer conversion options.
+ @param[out] pnValue  64-bit integer with item
 
+ The CBOR data item must be either a positive integer, negative integer or floating-point number.
+ \c uOptions is one of XXX and controls which conversions will be performed.
 
+ See also QCBORDecode_GetInt64ConvertAll() which will perform the same conversions
+ as this and a lot more at the cost of adding more object code to your executable.
 
-/*
- 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.
+ On error, this sets the decoder last error.  If the data item is of a type that
+ can't be decoded by this function, QCBOR_ERR_UNEXPECTED_TYPE is set. If
+ the data item can be decode, but the option requesting it is not set, then
+ QCBOR_ERR_UNEXPECTED_TYPE will be set. If the data item is too large
+ or small to be represented as a 64-bit signed integer, QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW
+ us set.
+
+ When converting floating-point values, the integer is rounded to the nearest integer using
+ llround(). By default, floating-point suport is enabled for QCBOR. If it is turned off,
+ then floating-point conversion is not available.
+ 
  */
-void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue);
+void QCBORDecode_GetInt64Convert(QCBORDecodeContext *pCtx, uint32_t uOptions, int64_t *pnValue);
+
+
+/**
+ @brief Decode next item as a 64-bit integer
+
+ @param[in] pCtx   The decode context
+ @param[in] uOptions The integer conversion options.
+ @param[out] pnValue  64-bit integer with item
+
+ This is the same as QCBORDecode_GetInt64Convert() but supports many more conversions at
+ the cost of adding more object code to your executable.
+
+ The additiona data item types that are suported are positive and negative bignums,
+ decimal fractions and big floats, including decimal fractions and big floats that use bignums.
+ Not that all these types can support numbers much larger that can be represented by
+ in a 64-bit integer, so QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will
+ often be encountered.
+ */
+void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pCtx, uint32_t uOptions, int64_t *pnValue);
+
+
+
+void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue);
+
+
+void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pValue);
 
 
 
@@ -966,6 +1007,7 @@
 
 void QCBORDecode_GetNegBignum(QCBORDecodeContext *pCtx,  UsefulBufC *pValue);
 
+void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pValue);
 
 
 
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index dc5e626..0eabfb1 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -2770,25 +2770,25 @@
 }
 
 
-#if 0
-static inline QCBORError ConvertBigNumToDouble(const UsefulBufC BigNum, uint64_t uMax, double *pResult)
-{
-   double nResult;
 
-   nResult = 0;
+static double ConvertBigNumToDouble(const UsefulBufC BigNum)
+{
+   double dResult;
+
+   dResult = 0.0;
    const uint8_t *pByte = BigNum.ptr;
    size_t uLen = BigNum.len;
    /* This will overflow and become the float value INFINITY  if the number
     is too large to fit. No error will be logged.
     TODO: should an error be logged? */
    while(uLen--) {
-      nResult = (nResult * 256) + *pByte;
+      dResult = (dResult * 256.0) + *pByte;
    }
 
-   *pResult = nResult;
-   return 0;
+   return dResult;
 }
-#endif
+
+
 
 static inline QCBORError ConvertPositiveBigNumToUnSigned(const UsefulBufC BigNum, uint64_t *pResult)
 {
@@ -2839,14 +2839,14 @@
 #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)
+static void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue, QCBORItem *pItem)
 {
    if(pMe->uLastError != QCBOR_SUCCESS) {
       return;
@@ -2866,11 +2866,17 @@
    }
 
    switch(Item.uDataType) {
-      case QCBOR_TYPE_FLOAT:
+         // TODO: float when ifdefs are set
+      case QCBOR_TYPE_DOUBLE:
          if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
             // TODO: what about under/overflow here?
             // Invokes the floating-point HW and/or compiler-added libraries
-            *pValue = (int64_t)Item.val.dfnum;
+            feclearexcept(FE_ALL_EXCEPT);
+            *pValue = llround(Item.val.dfnum);
+            if(fetestexcept(FE_INVALID)) {
+               // TODO: better error code
+               pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
+            }
          } else {
             pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
          }
@@ -2901,7 +2907,7 @@
    }
 }
 
-/* This works for signed, unsigned and float */
+/* This works for signed, unsigned and float data items */
 void QCBORDecode_GetInt64Convert(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue)
 {
    QCBORItem Item;
@@ -2933,7 +2939,7 @@
       return;
    }
 
-   if(pMe->uLastError != QCBOR_SUCCESS && pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
+   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
       // The above conversion failed in a way that code below can't correct
       return;
    }
@@ -3063,12 +3069,25 @@
       return;
    }
 
+   if(pItem) {
+      *pItem = Item;
+   }
+
    switch(Item.uDataType) {
-      case QCBOR_TYPE_FLOAT:
+         // TODO: type flaot
+      case QCBOR_TYPE_DOUBLE:
          if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
-            if(Item.val.dfnum >= 0) {
-               // TODO: over/underflow
-                *pValue = (uint64_t)Item.val.dfnum;
+            feclearexcept(FE_ALL_EXCEPT);
+            double dRounded = round(Item.val.dfnum);
+            // TODO: over/underflow
+            if(fetestexcept(FE_INVALID)) {
+               // TODO: better error code
+               pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
+            } else if(isnan(dRounded)) {
+               // TODO: better error code
+               pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
+            } else if(dRounded >= 0) {
+               *pValue = (uint64_t)dRounded;
             } else {
                pMe->uLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
             }
@@ -3126,7 +3145,13 @@
 
    QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, pValue, &Item);
 
-   if(pMe->uLastError != QCBOR_SUCCESS && pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
+   if(pMe->uLastError == QCBOR_SUCCESS) {
+      // The above conversion succeeded
+      return;
+   }
+
+   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
+      // The above conversion failed in a way that code below can't correct
       return;
    }
 
@@ -3241,149 +3266,125 @@
 
 
 
-#if 0
 /*
 
    Convert from bignums,
 
+ https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
+ 
  */
 void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pValue)
 {
    /* the same range of conversions */
 
-   /* Conversion from bignums, decimal fractions and such will be interesting */
-
    QCBORItem Item;
    QCBORError nError;
 
    nError = QCBORDecode_GetNext(pMe, &Item);
    if(nError) {
-      pMe->uLastError = nError;
+      pMe->uLastError = (uint8_t)nError;
       return;
    }
 
 
    switch(Item.uDataType) {
-         case QCBOR_TYPE_FLOAT:
-         if(uOptions & QCBOR_DECODE_TYPE_FLOAT) {
+         // TODO: type float
+      case QCBOR_TYPE_DOUBLE:
+         if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
             *pValue = Item.val.dfnum;
          } else {
-            pMe->uLastError = 99; // TODO: error code
+            pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
          }
          break;
 
-         case QCBOR_TYPE_INT64:
-         if(uOptions & QCBOR_DECODE_TYPE_INT64) {
+      case QCBOR_TYPE_INT64:
+         if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
             // TODO: how does this work?
             *pValue = (double)Item.val.int64;
          } else {
-            pMe->uLastError = 99; // TODO: error code
+            pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
          }
          break;
 
-         case QCBOR_TYPE_UINT64:
-         if(uOptions & QCBOR_DECODE_TYPE_UINT64) {
+      case QCBOR_TYPE_UINT64:
+         if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
+            // TODO: check more carefully how this cast works.
             *pValue = (double)Item.val.uint64;
          } else {
-            pMe->uLastError = 99; // TODO: error code
+            pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
+         }
+
+
+      case QCBOR_TYPE_DECIMAL_FRACTION:
+         if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+            // TODO: rounding and overflow errors
+            *pValue = (double)Item.val.expAndMantissa.Mantissa.nInt *
+                        pow(10.0, (double)Item.val.expAndMantissa.nExponent);
+         } else {
+            pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
          }
          break;
 
-         case QCBOR_TYPE_DECIMAL_FRACTION:
-         if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
-            pMe->uLastError = Exponentitate10(Item.val.expAndMantissa.Mantissa.nInt,
-                                              Item.val.expAndMantissa.nExponent,
-                                              pValue);
+      case QCBOR_TYPE_BIGFLOAT:
+         if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
+           *pValue = (double)Item.val.expAndMantissa.Mantissa.nInt *
+                                exp2((double)Item.val.expAndMantissa.nExponent);
          } else {
-            pMe->uLastError = 99; // TODO: error code
+            pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
          }
          break;
 
-         case QCBOR_TYPE_BIGFLOAT:
-         if(uOptions & QCBOR_DECODE_TYPE_BIGFLOAT) {
-            pMe->uLastError = Exponentitate2(Item.val.expAndMantissa.Mantissa.nInt,
-                                             Item.val.expAndMantissa.nExponent,
-                                             pValue);
+      case QCBOR_TYPE_POSBIGNUM:
+         if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
+            *pValue = ConvertBigNumToDouble(Item.val.bigNum);
          } else {
-            pMe->uLastError = 99; // TODO: error code
+            pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
          }
          break;
 
-         case QCBOR_TYPE_POSBIGNUM:
-         if(uOptions & QCBOR_DECODE_TYPE_BIG_NUM) {
-            pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.bigNum, pValue);
+      case QCBOR_TYPE_NEGBIGNUM:
+         if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
+            *pValue = -ConvertBigNumToDouble(Item.val.bigNum);
          } else {
-            pMe->uLastError = 99;
+            pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
          }
          break;
 
-         case QCBOR_TYPE_NEGBIGNUM:
-         if(uOptions & QCBOR_DECODE_TYPE_BIG_NUM) {
-            pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.bigNum, pValue);
+      case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
+         if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+            double dMantissa = ConvertBigNumToDouble(Item.val.expAndMantissa.Mantissa.bigNum);
+            *pValue = dMantissa * pow(10, (double)Item.val.expAndMantissa.nExponent);
          } else {
-            pMe->uLastError = 99;
+            pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
          }
          break;
 
-         case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
-         if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
-            int64_t nMantissa;
-            pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
-            if(!pMe->uLastError) {
-               pMe->uLastError = Exponentitate10(nMantissa,
-                                                 Item.val.expAndMantissa.nExponent,
-                                                 pValue);
-            }
-         } else {
-            pMe->uLastError = 99; // TODO: error code
-         }
-         break;
+      case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
+        if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+         double dMantissa = -ConvertBigNumToDouble(Item.val.expAndMantissa.Mantissa.bigNum);
+         *pValue = dMantissa * pow(10, (double)Item.val.expAndMantissa.nExponent);
+      } else {
+         pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
+      }
+      break;
 
-         case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
-         if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
-            int64_t nMantissa;
-            pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
-            if(!pMe->uLastError) {
-               pMe->uLastError = Exponentitate10(nMantissa,
-                                                 Item.val.expAndMantissa.nExponent,
-                                                 pValue);
-            }
-         } else {
-            pMe->uLastError = 99; // TODO: error code
-         }
-         break;
+      case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
+        if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
+         double dMantissa = ConvertBigNumToDouble(Item.val.expAndMantissa.Mantissa.bigNum);
+         *pValue = dMantissa * exp2((double)Item.val.expAndMantissa.nExponent);
+      } else {
+         pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
+      }
+      break;
 
-         case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
-         if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
-            int64_t nMantissa;
-            pMe->uLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
-            if(!pMe->uLastError) {
-               pMe->uLastError = Exponentitate2(nMantissa,
-                                                Item.val.expAndMantissa.nExponent,
-                                                pValue);
-            }
-         } else {
-            pMe->uLastError = 99; // TODO: error code
-         }
-         break;
-
-         case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
-         if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
-            int64_t nMantissa;
-            pMe->uLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
-            if(!pMe->uLastError) {
-               pMe->uLastError = Exponentitate2(nMantissa,
-                                                Item.val.expAndMantissa.nExponent,
-                                                pValue);
-            }
-         } else {
-            pMe->uLastError = 99; // TODO: error code
-         }
-         break;
+      case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
+        if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
+         double dMantissa = -ConvertBigNumToDouble(Item.val.expAndMantissa.Mantissa.bigNum);
+         *pValue = dMantissa * exp2((double)Item.val.expAndMantissa.nExponent);
+      } else {
+         pMe->uLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
+      }
+      break;
    }
-
-
-
 }
 
-#endif
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index 7650c59..4964c8e 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -3557,16 +3557,16 @@
 
 
 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
-/*
+/*  exponent, mantissa
   [
     4([-1, 3]),
-    4([-20, 4759477275222530853136]),
-    4([9223372036854775807, -4759477275222530853137]),
+    4([-20,                   4759477275222530853136]),
+    4([9223372036854775807,  -4759477275222530853137]),
     5([300, 100]),
-    5([-20, 4759477275222530853136]),
+    5([-20,                   4759477275222530853136]),
     5([-9223372036854775807, -4759477275222530853137])
-    5([9223372036854775806, -4759477275222530853137])
-    5([9223372036854775806, 9223372036854775806])]
+    5([ 9223372036854775806, -4759477275222530853137])
+    5([ 9223372036854775806,  9223372036854775806])]
  ]
  */
 
@@ -3584,6 +3584,8 @@
                0xC2, 0x4A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10,
    0xC5, 0x82, 0x3B, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
                0xC3, 0x4A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10,
+   0xC5, 0x82, 0x1B, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
+               0xC3, 0x4A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10,
    0xC5, 0x82, 0x1B, 0x7f, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
                0x1B, 0x7f, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE
 };
@@ -3654,33 +3656,45 @@
       return 10;
    }
 
+   // 5([-20, 4759477275222530853136]),
    nCBORError = QCBORDecode_GetNext(&DC, &item);
    if(nCBORError != QCBOR_SUCCESS) {
       return 11;
    }
-
    if(item.uDataType != QCBOR_TYPE_BIGFLOAT_POS_BIGNUM ||
       item.val.expAndMantissa.nExponent != -20 ||
       UsefulBuf_Compare(item.val.expAndMantissa.Mantissa.bigNum, BN)) {
       return 12;
    }
 
+   // 5([-9223372036854775807, -4759477275222530853137])
    nCBORError = QCBORDecode_GetNext(&DC, &item);
    if(nCBORError != QCBOR_SUCCESS) {
       return 13;
    }
-
    if(item.uDataType != QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM ||
       item.val.expAndMantissa.nExponent != -9223372036854775807 ||
       UsefulBuf_Compare(item.val.expAndMantissa.Mantissa.bigNum, BN)) {
       return 14;
    }
 
+   // 5([ 9223372036854775806, -4759477275222530853137])
+   nCBORError = QCBORDecode_GetNext(&DC, &item);
+   if(nCBORError != QCBOR_SUCCESS) {
+      return 13;
+   }
+   if(item.uDataType != QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM ||
+      item.val.expAndMantissa.nExponent != 9223372036854775806 ||
+      UsefulBuf_Compare(item.val.expAndMantissa.Mantissa.bigNum, BN)) {
+      return 14;
+   }
+
+
+   // 5([ 9223372036854775806,  9223372036854775806])]
    nCBORError = QCBORDecode_GetNext(&DC, &item);
    if(nCBORError != QCBOR_SUCCESS) {
       return 15;
    }
-
    if(item.uDataType != QCBOR_TYPE_BIGFLOAT ||
       item.val.expAndMantissa.nExponent != 9223372036854775806 ||
       item.val.expAndMantissa.Mantissa.nInt!= 9223372036854775806 ) {
@@ -3975,16 +3989,161 @@
 }
 
 
+struct NumberConversion {
+   char       *szDescription;
+   UsefulBufC  CBOR;
+   int64_t     nConvertedToInt64;
+   QCBORError  uErrorInt64;
+   uint64_t    uConvertToUInt64;
+   QCBORError  uErrorUint64;
+   double      dConvertToDouble;
+   QCBORError  uErrorDouble;
+};
+
+static struct NumberConversion NumberConversions[] = {
+   {
+      "Postive integer 0",
+      {(uint8_t[]){0x0}, 1},
+      0LL,
+      QCBOR_SUCCESS,
+      0ULL,
+      QCBOR_SUCCESS,
+      0.0,
+      QCBOR_SUCCESS
+   },
+   {
+      "-18446744073709551616",
+      {(uint8_t[]){0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, 9},
+      -9223372036854775807-1, // INT64_MIN
+      QCBOR_SUCCESS,
+      0ULL,
+      QCBOR_ERR_NUMBER_SIGN_CONVERSION,
+      -9223372036854775808.0,
+      QCBOR_SUCCESS
+   },
+   {
+      "Floating point value 100.3",
+      {(uint8_t[]){0xfb, 0x40, 0x59, 0x13, 0x33, 0x33, 0x33, 0x33, 0x33}, 9},
+      100L,
+      QCBOR_SUCCESS,
+      100ULL,
+      QCBOR_SUCCESS,
+      100.3,
+      QCBOR_SUCCESS
+   },
+   {
+      "Floating point value NaN 0xfa7fc00000",
+      {(uint8_t[]){0xfa, 0x7f, 0xc0, 0x00, 0x00}, 5},
+      0,
+      QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW,
+      0,
+      QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW,
+      NAN,
+      QCBOR_SUCCESS
+   },
+   {
+      "Floating point value -4",
+      {(uint8_t[]){0xf9, 0xc4, 0x00}, 3},
+      -4,
+      QCBOR_SUCCESS,
+      0,
+      QCBOR_ERR_NUMBER_SIGN_CONVERSION,
+      -4.0,
+      QCBOR_SUCCESS
+   },
+   {
+      "Decimal fraction 3/10",
+      {(uint8_t[]){0xC4, 0x82, 0x20, 0x03}, 4},
+      0,
+      QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW,
+      0,
+      QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW,
+      0.30000000000000004,
+      QCBOR_SUCCESS
+   }
+};
 
 
 
+
+int32_t IntegerConvertTest2()
+{
+   const size_t nNumTests = sizeof(NumberConversions)/sizeof(struct NumberConversion);
+
+   for(struct NumberConversion *pF = NumberConversions; pF < NumberConversions + nNumTests; pF++) {
+      // 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);
+      QCBORError nCBORError = QCBORDecode_SetMemPool(&DCtx, Pool, 0);
+      if(nCBORError) {
+         return -9;
+      }
+
+      int64_t nInt;
+      DCtx.uLastError = 0;
+      QCBORDecode_GetInt64ConvertAll(&DCtx, 0xffff, &nInt);
+      if(QCBORDecode_GetLastError(&DCtx) != pF->uErrorInt64) {
+         return -99;
+      }
+      if(pF->uErrorInt64 == QCBOR_SUCCESS && pF->nConvertedToInt64 != nInt) {
+         return -888;
+      }
+
+      
+      QCBORDecode_Init(&DCtx, pF->CBOR, QCBOR_DECODE_MODE_NORMAL);
+      nCBORError = QCBORDecode_SetMemPool(&DCtx, Pool, 0);
+      if(nCBORError) {
+         return -9;
+      }
+      uint64_t uInt;
+      DCtx.uLastError = 0;
+      QCBORDecode_GetUInt64ConvertAll(&DCtx, 0xffff, &uInt);
+      if(QCBORDecode_GetLastError(&DCtx) != pF->uErrorUint64) {
+         return -99;
+      }
+      if(pF->uErrorUint64 == QCBOR_SUCCESS && pF->uConvertToUInt64 != uInt) {
+         return -888;
+      }
+
+
+      QCBORDecode_Init(&DCtx, pF->CBOR, QCBOR_DECODE_MODE_NORMAL);
+      nCBORError = QCBORDecode_SetMemPool(&DCtx, Pool, 0);
+      if(nCBORError) {
+         return -9;
+      }
+      double d;
+      DCtx.uLastError = 0;
+      QCBORDecode_GetDoubleConvertAll(&DCtx, 0xffff, &d);
+      if(QCBORDecode_GetLastError(&DCtx) != pF->uErrorDouble) {
+         return -99;
+      }
+      if(pF->uErrorDouble == QCBOR_SUCCESS) {
+         if(isnan(pF->dConvertToDouble)) {
+            if(!isnan(d)) {
+               return -4;
+            }
+         } else {
+            // TODO: this comparison may need a margin of error
+            if(pF->dConvertToDouble != d) {
+               return -5;
+            }
+         }
+      }
+   }
+
+   return 0;
+}
+
 int32_t IntegerConvertTest()
 {
+   (void)IntegerConvertTest2();
 
    QCBORDecodeContext DCtx;
    QCBORError nCBORError;
 
-   /*
+   /* exponent, mantissa
     [
     4([-1, 3]),
     4([-20, 4759477275222530853136]),
@@ -3992,8 +4151,8 @@
     5([300, 100]),
     5([-20, 4759477275222530853136]),
     5([-9223372036854775807, -4759477275222530853137])
-    5([9223372036854775806, -4759477275222530853137])
-    5([9223372036854775806, 9223372036854775806])]
+    5([ 9223372036854775806, -4759477275222530853137])
+    5([ 9223372036854775806,  9223372036854775806])]
     ]
     */
 
@@ -4006,37 +4165,186 @@
    }
 
    int64_t integer;
-   QCBORDecode_GetInt64ConvertAll(&DCtx, QCBOR_CONVERT_TYPE_DECIMAL_FRACTION, &integer);
-   if(QCBORDecode_GetLastError(&DCtx) != QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW) {
-      return -2;
-   }
-
-   DCtx.uLastError = 0; // TODO: a method for this
-
+   //  4([-1, 3]),
    QCBORDecode_GetInt64ConvertAll(&DCtx, QCBOR_CONVERT_TYPE_DECIMAL_FRACTION, &integer);
    if(QCBORDecode_GetLastError(&DCtx) != QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW) {
       return -2;
    }
    DCtx.uLastError = 0; // TODO: a method for this
 
+   // 4([-20, 4759477275222530853136]),
    QCBORDecode_GetInt64ConvertAll(&DCtx, QCBOR_CONVERT_TYPE_DECIMAL_FRACTION, &integer);
    if(QCBORDecode_GetLastError(&DCtx) != QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW) {
       return -2;
    }
    DCtx.uLastError = 0; // TODO: a method for this
 
+   // 4([9223372036854775807, -4759477275222530853137]),
+   QCBORDecode_GetInt64ConvertAll(&DCtx, QCBOR_CONVERT_TYPE_DECIMAL_FRACTION, &integer);
+   if(QCBORDecode_GetLastError(&DCtx) != QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW) {
+      return -2;
+   }
+   DCtx.uLastError = 0; // TODO: a method for this
+
+   // 5([300, 100]),
    QCBORDecode_GetInt64ConvertAll(&DCtx, QCBOR_CONVERT_TYPE_DECIMAL_FRACTION|QCBOR_CONVERT_TYPE_BIGFLOAT, &integer);
    if(QCBORDecode_GetLastError(&DCtx) != QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW) {
       return -2;
    }
    DCtx.uLastError = 0; // TODO: a method for this
 
+   // 5([-20, 4759477275222530853136]),
    QCBORDecode_GetInt64ConvertAll(&DCtx, QCBOR_CONVERT_TYPE_DECIMAL_FRACTION|QCBOR_CONVERT_TYPE_BIGFLOAT, &integer);
    if(QCBORDecode_GetLastError(&DCtx) != QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW) {
       return -2;
    }
    DCtx.uLastError = 0; // TODO: a method for this
 
+   //  5([-9223372036854775807, -4759477275222530853137])
+   QCBORDecode_GetInt64ConvertAll(&DCtx, QCBOR_CONVERT_TYPE_DECIMAL_FRACTION|QCBOR_CONVERT_TYPE_BIGFLOAT, &integer);
+   if(QCBORDecode_GetLastError(&DCtx) != QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW) {
+      return -2;
+   }
+   DCtx.uLastError = 0; // TODO: a method for this
+
+   //  5([ 9223372036854775806, -4759477275222530853137])
+   QCBORDecode_GetInt64ConvertAll(&DCtx, QCBOR_CONVERT_TYPE_DECIMAL_FRACTION|QCBOR_CONVERT_TYPE_BIGFLOAT, &integer);
+   if(QCBORDecode_GetLastError(&DCtx) != QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW) {
+      return -2;
+   }
+   DCtx.uLastError = 0; // TODO: a method for this
+
+   //  5([ 9223372036854775806,  9223372036854775806])]
+   QCBORDecode_GetInt64ConvertAll(&DCtx, QCBOR_CONVERT_TYPE_DECIMAL_FRACTION|QCBOR_CONVERT_TYPE_BIGFLOAT, &integer);
+   if(QCBORDecode_GetLastError(&DCtx) != QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW) {
+      return -2;
+   }
+   DCtx.uLastError = 0; // TODO: a method for this
+   
+   
+   
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedExponentsAndMantissas), 0);
+
+   nCBORError = QCBORDecode_GetNext(&DCtx, &Item);
+   if(nCBORError) {
+      return -1;
+   }
+
+   uint64_t uinteger;
+   // 4([-1, 3]),
+   QCBORDecode_GetUInt64ConvertAll(&DCtx, QCBOR_CONVERT_TYPE_DECIMAL_FRACTION, &uinteger);
+   if(QCBORDecode_GetLastError(&DCtx) != QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW) {
+      return -2;
+   }
+   DCtx.uLastError = 0; // TODO: a method for this
+
+   // 4([-20, 4759477275222530853136]),
+   QCBORDecode_GetUInt64ConvertAll(&DCtx, QCBOR_CONVERT_TYPE_DECIMAL_FRACTION, &uinteger);
+   if(QCBORDecode_GetLastError(&DCtx) != QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW) {
+      return -2;
+   }
+   DCtx.uLastError = 0; // TODO: a method for this
+
+   // 4([9223372036854775807, -4759477275222530853137]),
+   QCBORDecode_GetUInt64ConvertAll(&DCtx, QCBOR_CONVERT_TYPE_DECIMAL_FRACTION, &uinteger);
+   if(QCBORDecode_GetLastError(&DCtx) != QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW) {
+      return -2;
+   }
+   DCtx.uLastError = 0; // TODO: a method for this
+
+   // 5([300, 100]),
+   QCBORDecode_GetUInt64ConvertAll(&DCtx, QCBOR_CONVERT_TYPE_DECIMAL_FRACTION|QCBOR_CONVERT_TYPE_BIGFLOAT, &uinteger);
+   if(QCBORDecode_GetLastError(&DCtx) != QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW) {
+      return -2;
+   }
+   DCtx.uLastError = 0; // TODO: a method for this
+
+   // 5([-20, 4759477275222530853136]),
+   QCBORDecode_GetUInt64ConvertAll(&DCtx, QCBOR_CONVERT_TYPE_DECIMAL_FRACTION|QCBOR_CONVERT_TYPE_BIGFLOAT, &uinteger);
+   if(QCBORDecode_GetLastError(&DCtx) != QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW) {
+      return -2;
+   }
+   DCtx.uLastError = 0; // TODO: a method for this
+   
+   // 5([-9223372036854775807, -4759477275222530853137])
+   QCBORDecode_GetUInt64ConvertAll(&DCtx, QCBOR_CONVERT_TYPE_DECIMAL_FRACTION|QCBOR_CONVERT_TYPE_BIGFLOAT, &uinteger);
+   if(QCBORDecode_GetLastError(&DCtx) != QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW) {
+      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_GetLastError(&DCtx) != QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW) {
+      return -2;
+   }
+   DCtx.uLastError = 0; // TODO: a method for this
+   
+   // 5([ 9223372036854775806,  9223372036854775806])]
+   QCBORDecode_GetUInt64ConvertAll(&DCtx, QCBOR_CONVERT_TYPE_DECIMAL_FRACTION|QCBOR_CONVERT_TYPE_BIGFLOAT, &uinteger);
+   if(QCBORDecode_GetLastError(&DCtx) != QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW) {
+      return -2;
+   }
+   DCtx.uLastError = 0; // TODO: a method for this
+
+
+   
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedExponentsAndMantissas), 0);
+   nCBORError = QCBORDecode_GetNext(&DCtx, &Item);
+    if(nCBORError) {
+       return -1;
+    }
+   
+   double dResult;
+   //  4([-1, 3]),
+    QCBORDecode_GetDoubleConvertAll(&DCtx, QCBOR_CONVERT_TYPE_DECIMAL_FRACTION, &dResult);
+    if(QCBORDecode_GetLastError(&DCtx) != QCBOR_SUCCESS &&
+       dResult != 0.3) {
+       return -2;
+    }
+
+   // 4([-20, 4759477275222530853136]),
+   QCBORDecode_GetDoubleConvertAll(&DCtx, QCBOR_CONVERT_TYPE_DECIMAL_FRACTION, &dResult);
+    if(QCBORDecode_GetLastError(&DCtx) != QCBOR_SUCCESS &&
+       dResult != 47.408855671161923) {
+       return -2;
+    }
+
+   // 4([9223372036854775807, -4759477275222530853137]),
+   QCBORDecode_GetDoubleConvertAll(&DCtx, QCBOR_CONVERT_TYPE_DECIMAL_FRACTION, &dResult);
+   if(QCBORDecode_GetLastError(&DCtx) != QCBOR_SUCCESS &&
+      dResult != -INFINITY) {
+      return -2;
+   }
+
+   // 5([300, 100]),
+   QCBORDecode_GetDoubleConvertAll(&DCtx, QCBOR_CONVERT_TYPE_BIGFLOAT, &dResult);
+   if(QCBORDecode_GetLastError(&DCtx) != QCBOR_SUCCESS &&
+      dResult != -INFINITY) {
+      return -2;
+   }
+
+   // 5([-20, 4759477275222530853136]),
+   QCBORDecode_GetDoubleConvertAll(&DCtx, QCBOR_CONVERT_TYPE_BIGFLOAT, &dResult);
+   if(QCBORDecode_GetLastError(&DCtx) != QCBOR_SUCCESS &&
+      dResult != 4521260802379792.0) {
+      return -2;
+   }
+
+   // 5([-9223372036854775807, -4759477275222530853137])
+   QCBORDecode_GetDoubleConvertAll(&DCtx, QCBOR_CONVERT_TYPE_BIGFLOAT, &dResult);
+   if(QCBORDecode_GetLastError(&DCtx) != QCBOR_SUCCESS &&
+      dResult != -0.0) {
+      return -2;
+   }
+
+   // 5([9223372036854775806, 9223372036854775806])]
+   QCBORDecode_GetDoubleConvertAll(&DCtx, QCBOR_CONVERT_TYPE_BIGFLOAT, &dResult);
+   if(QCBORDecode_GetLastError(&DCtx) != QCBOR_SUCCESS &&
+      dResult != INFINITY) {
+      return -2;
+   }
+
    return 0;
 }