New clever type and argument decoder saves 250 bytes of object code
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index 8d216c7..6df81fc 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -42,6 +42,7 @@
 
  when               who             what, where, why
  --------           ----            ---------------------------------------------------
+ 01/10/19           llundblade      Clever type and argument decoder is 250 bytes smaller
  11/9/18            llundblade      Error codes are now enums.
  11/2/18            llundblade      Simplify float decoding and align with preferred
                                     float encoding
@@ -353,71 +354,59 @@
    puAdditionalInfo -- Pass this along to know what kind of float or if length is indefinite
 
  */
-inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf, int *pnMajorType, uint64_t *puNumber, uint8_t *puAdditionalInfo)
+inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
+                                              int *pnMajorType,
+                                              uint64_t *puArgument,
+                                              uint8_t *puAdditionalInfo)
 {
-   // Stack usage: int/ptr 5 -- 40
    QCBORError nReturn;
-
+   
    // Get the initial byte that every CBOR data item has
-   const uint8_t InitialByte = UsefulInputBuf_GetByte(pUInBuf);
-
+   const uint8_t uInitialByte = UsefulInputBuf_GetByte(pUInBuf);
+   
    // Break down the initial byte
-   const uint8_t uTmpMajorType   = InitialByte >> 5;
-   const uint8_t uAdditionalInfo = InitialByte & 0x1f;
+   const uint8_t uTmpMajorType   = uInitialByte >> 5;
+   const uint8_t uAdditionalInfo = uInitialByte & 0x1f;
+   
+   // Where the number or argument accumulates
+   uint64_t uArgument;
 
-   // Get the integer that follows the major type. Do not know if this is a length, value, float or tag at this point
-   // Also convert from network byte order.
-   uint64_t uTmpValue;
-   switch(uAdditionalInfo) {
+   if(uAdditionalInfo >= LEN_IS_ONE_BYTE && uAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
+      // Need to get 1,2,4 or 8 additional argument bytes
+      // Map LEN_IS_ONE_BYTE.. LEN_IS_EIGHT_BYTES to actual length
+      static const uint8_t aIterate[] = {1,2,4,8};
 
-      case LEN_IS_ONE_BYTE:
-         uTmpValue = UsefulInputBuf_GetByte(pUInBuf);
-         break;
-
-      case LEN_IS_TWO_BYTES:
-         uTmpValue = UsefulInputBuf_GetUint16(pUInBuf);
-         break;
-
-      case LEN_IS_FOUR_BYTES:
-         uTmpValue = UsefulInputBuf_GetUint32(pUInBuf);
-         break;
-
-      case LEN_IS_EIGHT_BYTES:
-         uTmpValue = UsefulInputBuf_GetUint64(pUInBuf);
-         break;
-
-      case ADDINFO_RESERVED1: // reserved by CBOR spec
-      case ADDINFO_RESERVED2: // reserved by CBOR spec
-      case ADDINFO_RESERVED3: // reserved by CBOR spec
-         nReturn = QCBOR_ERR_UNSUPPORTED;
-         goto Done;
-
-      default:
-         // This is when the "number" is in the additional info
-         uTmpValue = uAdditionalInfo;
-         break;
+      // Loop getting all the bytes in the argument
+      uArgument = 0;
+      for(int i = aIterate[uAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
+         // This shift and add gives the endian conversion
+         uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
+      }
+   } else if(uAdditionalInfo >= ADDINFO_RESERVED1 && uAdditionalInfo <= ADDINFO_RESERVED3) {
+      // The reserved and thus-far unused additional info values
+      nReturn = QCBOR_ERR_UNSUPPORTED;
+      goto Done;
+   } else {
+      // Less than 24, additional info is argument or 31, an indefinite length
+      // No more bytes to get
+      uArgument = uAdditionalInfo;
    }
-
-   // If any of the UsefulInputBuf_Get calls fail we will get here with uTmpValue as 0.
-   // There is no harm in this. This following check takes care of catching all of
-   // these errors.
-
+   
    if(UsefulInputBuf_GetError(pUInBuf)) {
       nReturn = QCBOR_ERR_HIT_END;
       goto Done;
    }
-
+   
    // All successful if we got here.
    nReturn           = QCBOR_SUCCESS;
    *pnMajorType      = uTmpMajorType;
-   *puNumber         = uTmpValue;
+   *puArgument       = uArgument;
    *puAdditionalInfo = uAdditionalInfo;
-
+   
 Done:
    return nReturn;
 }
 
-
 /*
  CBOR doesn't explicitly specify two's compliment for integers but all CPUs
  use it these days and the test vectors in the RFC are so. All integers in the CBOR