Add compile option to disable floating point usage (#114)

This commit adds the option to disable floating point processing in
QCBOR. To disable, the USEFULBUF_DISABLE_ALL_FLOAT preprocessor macro
needs to be defined.

e.g.:

 $ make CMD_LINE="-DUSEFULBUF_DISABLE_ALL_FLOAT"

This removes the capability (and the code) of decoding floating point
types. The type is still recognised, so a meaningful
QCBOR_ERR_ALL_FLOAT_DISABLED error is returned when a floating point value
is encountered in a decoded qcbor. From the encoding interface the
floating point encoding functions are removed.

Change-Id: I371769246f7d83354607de9bce1e7998b8c536a1
Signed-off-by: Mate Toth-Pal <mate.toth-pal@arm.com>
diff --git a/README.md b/README.md
index ee78c6b..04275e1 100644
--- a/README.md
+++ b/README.md
@@ -276,6 +276,13 @@
 can be saved just by not calling any functions that
 encode floating-point numbers.
 
+### #define USEFULBUF_DISABLE_ALL_FLOAT
+
+This eliminates floating point support completely (along with related function
+headers). This is useful if the compiler options deny the usage of floating
+point operations completely, and the usage soft floating point ABI is not
+possible.
+
 ### Compiler options
 
 Compilers support a number of options that control
@@ -515,3 +522,4 @@
 ### Copyright for this README
 
 Copyright (c) 2018-2021, Laurence Lundblade. All rights reserved.
+Copyright (c) 2021, Arm Limited. All rights reserved.
diff --git a/example.c b/example.c
index 4921e13..02345ec 100644
--- a/example.c
+++ b/example.c
@@ -2,6 +2,7 @@
    example.c -- Example code for QCBOR
 
    Copyright (c) 2020-2021, Laurence Lundblade. All rights reserved.
+   Copyright (c) 2021, Arm Limited. All rights reserved.
 
    SPDX-License-Identifier: BSD-3-Clause
 
@@ -37,12 +38,16 @@
    UsefulBufC Manufacturer;
    int64_t    uDisplacement;
    int64_t    uHorsePower;
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
    double     dDesignedCompresion;
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
    int64_t    uNumCylinders;
    bool       bTurboCharged;
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
    struct {
       double dMeasuredCompression;
    } cylinders[MAX_CYLINDERS];
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 } CarEngine;
 
 
@@ -56,16 +61,20 @@
    pE->Manufacturer        = UsefulBuf_FROM_SZ_LITERAL("Porsche");
    pE->uDisplacement       = 3296;
    pE->uHorsePower         = 210;
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
    pE->dDesignedCompresion = 9.1;
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
    pE->uNumCylinders       = 6;
    pE->bTurboCharged       = false;
 
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
    pE->cylinders[0].dMeasuredCompression = 9.0;
    pE->cylinders[1].dMeasuredCompression = 9.2;
    pE->cylinders[2].dMeasuredCompression = 8.9;
    pE->cylinders[3].dMeasuredCompression = 8.9;
    pE->cylinders[4].dMeasuredCompression = 9.1;
    pE->cylinders[5].dMeasuredCompression = 9.0;
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 }
 
 
@@ -92,6 +101,7 @@
    if(pE1->uHorsePower != pE2->uHorsePower) {
       return false;
    }
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
    if(pE1->dDesignedCompresion != pE2->dDesignedCompresion) {
       return false;
    }
@@ -101,6 +111,7 @@
          return false;
       }
    }
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
    if(UsefulBuf_Compare(pE1->Manufacturer, pE2->Manufacturer)) {
       return false;
@@ -150,12 +161,16 @@
     QCBOREncode_AddInt64ToMap(&EncodeCtx, "NumCylinders", pEngine->uNumCylinders);
     QCBOREncode_AddInt64ToMap(&EncodeCtx, "Displacement", pEngine->uDisplacement);
     QCBOREncode_AddInt64ToMap(&EncodeCtx, "Horsepower", pEngine->uHorsePower);
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
     QCBOREncode_AddDoubleToMap(&EncodeCtx, "DesignedCompression", pEngine->dDesignedCompresion);
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
     QCBOREncode_OpenArrayInMap(&EncodeCtx, "Cylinders");
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
     for(int64_t i = 0 ; i < pEngine->uNumCylinders; i++) {
         QCBOREncode_AddDouble(&EncodeCtx,
                               pEngine->cylinders[i].dMeasuredCompression);
     }
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
     QCBOREncode_CloseArray(&EncodeCtx);
     QCBOREncode_AddBoolToMap(&EncodeCtx, "Turbo", pEngine->bTurboCharged);
     QCBOREncode_CloseMap(&EncodeCtx);
@@ -250,7 +265,9 @@
     QCBORDecode_GetTextStringInMapSZ(&DecodeCtx, "Manufacturer", &(pE->Manufacturer));
     QCBORDecode_GetInt64InMapSZ(&DecodeCtx, "Displacement", &(pE->uDisplacement));
     QCBORDecode_GetInt64InMapSZ(&DecodeCtx, "Horsepower", &(pE->uHorsePower));
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
     QCBORDecode_GetDoubleInMapSZ(&DecodeCtx, "DesignedCompression", &(pE->dDesignedCompresion));
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
     QCBORDecode_GetBoolInMapSZ(&DecodeCtx, "Turbo", &(pE->bTurboCharged));
 
     QCBORDecode_GetInt64InMapSZ(&DecodeCtx, "NumCylinders", &(pE->uNumCylinders));
@@ -268,10 +285,12 @@
     }
 
     QCBORDecode_EnterArrayFromMapSZ(&DecodeCtx, "Cylinders");
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
     for(int64_t i = 0; i < pE->uNumCylinders; i++) {
         QCBORDecode_GetDouble(&DecodeCtx,
                               &(pE->cylinders[i].dMeasuredCompression));
     }
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
     QCBORDecode_ExitArray(&DecodeCtx);
     QCBORDecode_ExitMap(&DecodeCtx);
 
diff --git a/inc/qcbor/UsefulBuf.h b/inc/qcbor/UsefulBuf.h
index c271a31..fb3c12b 100644
--- a/inc/qcbor/UsefulBuf.h
+++ b/inc/qcbor/UsefulBuf.h
@@ -1,6 +1,7 @@
 /*============================================================================
  Copyright (c) 2016-2018, The Linux Foundation.
  Copyright (c) 2018-2021, Laurence Lundblade.
+ Copyright (c) 2021, Arm Limited. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
@@ -138,6 +139,12 @@
  *     handle big and little-endian with system option.
  *   USEFULBUF_CONFIG_BSWAP -- With USEFULBUF_CONFIG_LITTLE_ENDIAN,
  *     use __builtin_bswapXX().
+ *
+ * It is possible to run this code in environments where using floating point is
+ * not allowed. Defining USEFULBUF_DISABLE_ALL_FLOAT will disable all the code
+ * that is related to handling floating point types, along with related
+ * interfaces. This makes it possible to compile the code with the compile
+ * option -mgeneral-regs-only.
  */
 
 #if defined(USEFULBUF_CONFIG_BIG_ENDIAN) && defined(USEFULBUF_CONFIG_LITTLE_ENDIAN)
@@ -679,6 +686,7 @@
 
 
 
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
 /**
  * @brief Copy a @c float to a @c uint32_t.
  *
@@ -733,6 +741,7 @@
  * is a crusty corner of C.
  */
 static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64);
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
 
 
@@ -1032,6 +1041,7 @@
                                              size_t uPos);
 
 
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
 /**
  * @brief Insert a @c float into the @ref UsefulOutBuf.
  *
@@ -1064,6 +1074,7 @@
 static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pUOutBuf,
                                              double d,
                                              size_t uPos);
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
 
 /**
@@ -1162,6 +1173,7 @@
                                              uint64_t uInteger64);
 
 
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
 /**
  * @brief Append a @c float to the @ref UsefulOutBuf
  *
@@ -1190,6 +1202,7 @@
  */
 static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pUOutBuf,
                                              double d);
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
 
 /**
@@ -1519,6 +1532,7 @@
 static uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pUInBuf);
 
 
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
 /**
  * @brief Get a float out of the input buffer.
  *
@@ -1547,6 +1561,7 @@
  * The input bytes are interpreted in network order (big endian).
  */
 static double UsefulInputBuf_GetDouble(UsefulInputBuf *pUInBuf);
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
 
 /**
@@ -1778,6 +1793,7 @@
 }
 
 
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
 static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
 {
    uint32_t u32;
@@ -1805,6 +1821,7 @@
    memcpy(&f, &u32, sizeof(uint32_t));
    return f;
 }
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
 
 
@@ -1984,6 +2001,7 @@
 }
 
 
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
 static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pMe,
                                             float f,
                                             size_t uPos)
@@ -1998,6 +2016,7 @@
 {
    UsefulOutBuf_InsertUint64(pMe, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
 }
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
 
 static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pMe,
@@ -2055,6 +2074,7 @@
 }
 
 
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
 static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pMe,
                                             float f)
 {
@@ -2067,6 +2087,7 @@
 {
    UsefulOutBuf_InsertDouble(pMe, d, UsefulOutBuf_GetEndPosition(pMe));
 }
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
 
 static inline int UsefulOutBuf_GetError(UsefulOutBuf *pMe)
@@ -2325,6 +2346,7 @@
 }
 
 
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
 static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *pMe)
 {
    uint32_t uResult = UsefulInputBuf_GetUint32(pMe);
@@ -2339,6 +2361,7 @@
 
    return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0;
 }
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
 
 static inline int UsefulInputBuf_GetError(UsefulInputBuf *pMe)
diff --git a/inc/qcbor/qcbor_common.h b/inc/qcbor/qcbor_common.h
index 7fc48de..e1ff43a 100644
--- a/inc/qcbor/qcbor_common.h
+++ b/inc/qcbor/qcbor_common.h
@@ -1,6 +1,7 @@
 /*==============================================================================
  Copyright (c) 2016-2018, The Linux Foundation.
  Copyright (c) 2018-2021, Laurence Lundblade.
+ Copyright (c) 2021, Arm Limited.
  All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -58,6 +59,17 @@
 #define QCBOR_DISABLE_EXP_AND_MANTISSA
 #endif
 
+/* If USEFULBUF_DISABLE_ALL_FLOATis defined then define
+ * QCBOR_DISABLE_FLOAT_HW_USE and QCBOR_DISABLE_PREFERRED_FLOAT
+ */
+#ifdef USEFULBUF_DISABLE_ALL_FLOAT
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+#define QCBOR_DISABLE_FLOAT_HW_USE
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+#define QCBOR_DISABLE_PREFERRED_FLOAT
+#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
 /* Standard CBOR Major type for positive integers of various lengths */
 #define CBOR_MAJOR_TYPE_POSITIVE_INT 0
@@ -504,7 +516,11 @@
 
    /** Trying to cancel a byte string wrapping after items have been
        added to it. */
-   QCBOR_ERR_CANNOT_CANCEL = 45
+   QCBOR_ERR_CANNOT_CANCEL = 45,
+
+   /** Floating point support is completely turned off, encoding/decoding
+       floating point numbers is not possible. */
+   QCBOR_ERR_ALL_FLOAT_DISABLED = 46
 
    /* This is stored in uint8_t; never add values > 255 */
 } QCBORError;
diff --git a/inc/qcbor/qcbor_decode.h b/inc/qcbor/qcbor_decode.h
index 1b7d148..6616033 100644
--- a/inc/qcbor/qcbor_decode.h
+++ b/inc/qcbor/qcbor_decode.h
@@ -1,6 +1,7 @@
 /*==============================================================================
  Copyright (c) 2016-2018, The Linux Foundation.
  Copyright (c) 2018-2021, Laurence Lundblade.
+ Copyright (c) 2021, Arm Limited.
  All rights reserved.
 
  Redistribution and use in source and binary forms, with or without
@@ -394,16 +395,20 @@
        *  with @c uNestLevel and @c uNextNestLevel so as to work for
        *  both definite and indefinite length maps and arrays. */
       uint16_t    uCount;
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
       /** The value for @c uDataType @ref QCBOR_TYPE_DOUBLE. */
       double      dfnum;
       /** The value for @c uDataType @ref QCBOR_TYPE_FLOAT. */
       float       fnum;
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
       /** The value for @c uDataType @ref QCBOR_TYPE_DATE_EPOCH.
        *  Floating-point dates that are NaN, +Inifinity or -Inifinity
        *  result in the @ref QCBOR_ERR_DATE_OVERFLOW error. */
       struct {
          int64_t  nSeconds;
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
          double   fSecondsFraction;
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
       } epochDate;
 
       /** The value for @c uDataType @ref QCBOR_TYPE_DAYS_EPOCH -- the
@@ -889,6 +894,7 @@
  * | @ref QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED  | Library compiled with indefinite maps and arrays  disabled and indefinite map or array encountered |
  * | @ref QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED | Library compiled with indefinite strings disabled and indefinite string encountered |
  * | @ref QCBOR_ERR_FLOAT_DATE_DISABLED        | Library compiled with floating-point disabled and floating-point date encountered |
+ * | @ref QCBOR_ERR_ALL_FLOAT_DISABLED             | Library compiled with floating-point support turned off. |
  * | __Resource exhaustion errors__  ||
  * | @ref QCBOR_ERR_STRING_ALLOCATE | The string allocator is unable to allocate more memory |
  */
diff --git a/inc/qcbor/qcbor_encode.h b/inc/qcbor/qcbor_encode.h
index 969deee..202a98f 100644
--- a/inc/qcbor/qcbor_encode.h
+++ b/inc/qcbor/qcbor_encode.h
@@ -1,6 +1,7 @@
 /*==============================================================================
  Copyright (c) 2016-2018, The Linux Foundation.
  Copyright (c) 2018-2021, Laurence Lundblade.
+ Copyright (c) 2021, Arm Limited.
  All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -341,6 +342,11 @@
  float type as 32-bits and a C double type as 64-bits. Floating-point
  epoch dates will be unsupported.
 
+ If USEFULBUF_DISABLE_ALL_FLOATis defined, then floating point support is
+ completely disabled. Decoding functions return @ref QCBOR_ERR_ALL_FLOAT_DISABLED
+ if a floating point value is encountered during decoding. Functions that are
+ encoding floating point values are not available.
+
  ## Limitations
 
  Summary Limits of this implementation:
@@ -588,6 +594,7 @@
 static void QCBOREncode_AddSZStringToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, const char *szString);
 
 
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
 /**
  @brief Add a double-precision floating-point number to the encoded output.
 
@@ -690,6 +697,7 @@
 static void QCBOREncode_AddFloatNoPreferredToMap(QCBOREncodeContext *pCtx, const char *szLabel, float fNum);
 
 static void QCBOREncode_AddFloatNoPreferredToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, float fNum);
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
 
 /**
@@ -2215,6 +2223,7 @@
 }
 
 
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
 static inline void
 QCBOREncode_AddDoubleToMap(QCBOREncodeContext *pMe, const char *szLabel, double dNum)
 {
@@ -2270,6 +2279,7 @@
    QCBOREncode_AddInt64(pMe, nLabel);
    QCBOREncode_AddFloatNoPreferred(pMe, dNum);
 }
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
 
 
diff --git a/inc/qcbor/qcbor_private.h b/inc/qcbor/qcbor_private.h
index abd6ba2..9f189e6 100644
--- a/inc/qcbor/qcbor_private.h
+++ b/inc/qcbor/qcbor_private.h
@@ -1,6 +1,7 @@
 /*==============================================================================
  Copyright (c) 2016-2018, The Linux Foundation.
  Copyright (c) 2018-2021, Laurence Lundblade.
+ Copyright (c) 2021, Arm Limited.
  All rights reserved.
 
  Redistribution and use in source and binary forms, with or without
@@ -73,6 +74,55 @@
 /* The number of tags (of any size) recorded for an individual item. */
 #define QCBOR_MAX_TAGS_PER_ITEM1 4
 
+/*
+ Convenience macro for selecting the proper return value in case floating
+ point feature(s) are disabled.
+
+ The macros:
+
+   FLOAT_ERR_CODE_NO_FLOAT(x) Can be used when disabled floating point should
+                              result error, and all other cases should return
+                              'x'.
+
+   The below macros always return QCBOR_ERR_ALL_FLOAT_DISABLED when all floating
+   point is disabled.
+
+   FLOAT_ERR_CODE_NO_HALF_PREC(x) Can be used when disabled preferred float
+                                  results in error, and all other cases should
+                                  return 'x'.
+   FLOAT_ERR_CODE_NO_FLOAT_HW(x) Can be used when disabled hardware floating
+                                 point results in error, and all other cases
+                                 should return 'x'.
+   FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(x) Can be used when either disabled
+                                              preferred float or disabling
+                                              hardware floating point results in
+                                              error, and all other cases should
+                                              return 'x'.
+ */
+#ifdef USEFULBUF_DISABLE_ALL_FLOAT
+   #define FLOAT_ERR_CODE_NO_FLOAT(x)                 QCBOR_ERR_ALL_FLOAT_DISABLED
+   #define FLOAT_ERR_CODE_NO_HALF_PREC(x)             QCBOR_ERR_ALL_FLOAT_DISABLED
+   #define FLOAT_ERR_CODE_NO_FLOAT_HW(x)              QCBOR_ERR_ALL_FLOAT_DISABLED
+   #define FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(x) QCBOR_ERR_ALL_FLOAT_DISABLED
+#else /* USEFULBUF_DISABLE_ALL_FLOAT*/
+   #define FLOAT_ERR_CODE_NO_FLOAT(x)     x
+   #ifdef QCBOR_DISABLE_PREFERRED_FLOAT
+      #define FLOAT_ERR_CODE_NO_HALF_PREC(x) QCBOR_ERR_HALF_PRECISION_DISABLED
+      #define FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(x) QCBOR_ERR_HALF_PRECISION_DISABLED
+   #else /* QCBOR_DISABLE_PREFERRED_FLOAT */
+      #define FLOAT_ERR_CODE_NO_HALF_PREC(x) x
+      #ifdef QCBOR_DISABLE_FLOAT_HW_USE
+         #define FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(x) QCBOR_ERR_HW_FLOAT_DISABLED
+      #else
+         #define FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(x) x
+      #endif
+   #endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
+   #ifdef QCBOR_DISABLE_FLOAT_HW_USE
+      #define FLOAT_ERR_CODE_NO_FLOAT_HW(x)  QCBOR_ERR_HW_FLOAT_DISABLED
+   #else /* QCBOR_DISABLE_FLOAT_HW_USE */
+      #define FLOAT_ERR_CODE_NO_FLOAT_HW(x)  x
+   #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+#endif /*USEFULBUF_DISABLE_ALL_FLOAT*/
 
 
 /*
diff --git a/inc/qcbor/qcbor_spiffy_decode.h b/inc/qcbor/qcbor_spiffy_decode.h
index dcf09a8..c924cdc 100644
--- a/inc/qcbor/qcbor_spiffy_decode.h
+++ b/inc/qcbor/qcbor_spiffy_decode.h
@@ -2,6 +2,7 @@
   qcbor_spiffy_decode.h -- higher-level easier-to-use CBOR decoding.
 
   Copyright (c) 2020-2021, Laurence Lundblade. All rights reserved.
+  Copyright (c) 2021, Arm Limited. All rights reserved.
 
   SPDX-License-Identifier: BSD-3-Clause
 
@@ -244,6 +245,9 @@
  this will set QCBOR_ERR_HALF_PRECISION_DISABLED if
  a half-precision number is encountered.
 
+ If floating-point usage is disabled this will set @ref QCBOR_ERR_ALL_FLOAT_DISABLED
+ if a floating point value is encountered.
+
  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.
@@ -352,6 +356,9 @@
  this will set QCBOR_ERR_HALF_PRECISION_DISABLED if
  a half-precision number is encountered.
 
+ If floating-point usage is disabled this will set @ref QCBOR_ERR_ALL_FLOAT_DISABLED
+ if a floating point value is encountered.
+
  See also QCBORDecode_GetUInt64Convert() and
  QCBORDecode_GetUInt64ConvertAll().
 */
@@ -455,6 +462,7 @@
 
 
 
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
 /**
  @brief Decode next item into a double floating-point value.
 
@@ -570,6 +578,7 @@
                                             const char         *szLabel,
                                             uint32_t            uConvertTypes,
                                             double             *pdValue);
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
 
 
@@ -1022,11 +1031,14 @@
 
  Floating-point dates that are plus infinity, minus infinity or NaN
  (not-a-number) will result in the @ref QCBOR_ERR_DATE_OVERFLOW
- error. If the QCBOR library is compiled with floating-point disabled,
+ error. If the QCBOR library is compiled with hardware floating-point disabled,
  @ref QCBOR_ERR_HW_FLOAT_DISABLED is set. If compiled with preferred
  float disabled, half-precision dates will result in the @ref
  QCBOR_ERR_HALF_PRECISION_DISABLED error.
 
+ If the QCBOR library is compiled with floating-point disabled,
+ @ref QCBOR_ERR_ALL_FLOAT_DISABLED is set.
+
  Please see @ref Decode-Errors-Overview "Decode Errors Overview".
 
  See @ref Tag-Usage for discussion on tag requirements.
@@ -1866,6 +1878,7 @@
 
 
 
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
 // Semi-private
 void
 QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
@@ -1954,6 +1967,7 @@
                                        QCBOR_CONVERT_TYPE_FLOAT,
                                        pdValue);
 }
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
 
 
diff --git a/src/ieee754.c b/src/ieee754.c
index 216cd00..a8079f8 100644
--- a/src/ieee754.c
+++ b/src/ieee754.c
@@ -2,6 +2,7 @@
  ieee754.c -- floating-point conversion between half, double & single-precision
 
  Copyright (c) 2018-2020, Laurence Lundblade. All rights reserved.
+ Copyright (c) 2021, Arm Limited. All rights reserved.
 
  SPDX-License-Identifier: BSD-3-Clause
 
@@ -10,6 +11,12 @@
  Created on 7/23/18
  =============================================================================*/
 
+/*
+ Include before QCBOR_DISABLE_PREFERRED_FLOAT is checked as
+ QCBOR_DISABLE_PREFERRED_FLOAT might be defined in qcbor/qcbor_common.h
+ */
+#include "qcbor/qcbor_common.h"
+
 #ifndef QCBOR_DISABLE_PREFERRED_FLOAT
 
 #include "ieee754.h"
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index 2be12d9..4a20613 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -1,6 +1,7 @@
 /*==============================================================================
  Copyright (c) 2016-2018, The Linux Foundation.
  Copyright (c) 2018-2021, Laurence Lundblade.
+ Copyright (c) 2021, Arm Limited.
  All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -839,6 +840,7 @@
  * @param[out] pDecodedItem     The filled in decoded item.
  *
  * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
+ * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
  * @retval QCBOR_ERR_BAD_TYPE_7
  */
 
@@ -867,11 +869,11 @@
           */
          pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uArgument);
          pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
-#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
-         uReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
 #endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
+         uReturn = FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS);
          break;
       case SINGLE_PREC_FLOAT: /* 26 */
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
          /* Single precision is normally returned as a double since
           * double is widely supported, there is no loss of precision,
           * it makes it easy for the caller in most cases and it can
@@ -899,11 +901,16 @@
              */
 #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
          }
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+         uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
          break;
 
       case DOUBLE_PREC_FLOAT: /* 27 */
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
          pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uArgument);
          pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+         uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
          break;
 
       case CBOR_SIMPLEV_FALSE: /* 20 */
@@ -1068,6 +1075,7 @@
  * @retval QCBOR_ERR_STRING_ALLOCATE
  * @retval QCBOR_ERR_STRING_TOO_LONG
  * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
+ * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
  * @retval QCBOR_ERR_BAD_TYPE_7
  * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
  *
@@ -1179,6 +1187,7 @@
  * @retval QCBOR_ERR_STRING_ALLOCATE
  * @retval QCBOR_ERR_STRING_TOO_LONG
  * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
+ * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
  * @retval QCBOR_ERR_BAD_TYPE_7
  * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
  * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
@@ -1412,6 +1421,7 @@
  * @retval QCBOR_ERR_STRING_ALLOCATE
  * @retval QCBOR_ERR_STRING_TOO_LONG
  * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
+ * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
  * @retval QCBOR_ERR_BAD_TYPE_7
  * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
  * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
@@ -1494,6 +1504,7 @@
  * @retval QCBOR_ERR_STRING_ALLOCATE
  * @retval QCBOR_ERR_STRING_TOO_LONG
  * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
+ * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
  * @retval QCBOR_ERR_BAD_TYPE_7
  * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
  * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
@@ -1733,6 +1744,7 @@
  * @retval QCBOR_ERR_STRING_ALLOCATE
  * @retval QCBOR_ERR_STRING_TOO_LONG
  * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
+ * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
  * @retval QCBOR_ERR_BAD_TYPE_7
  * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
  * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
@@ -1893,6 +1905,7 @@
  *
  * @retval QCBOR_ERR_DATE_OVERFLOW
  * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
+ * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
  * @retval QCBOR_ERR_BAD_TAG_CONTENT
  *
  * The epoch date tag defined in QCBOR allows for floating-point
@@ -1907,7 +1920,9 @@
 {
    QCBORError uReturn = QCBOR_SUCCESS;
 
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
    pDecodedItem->val.epochDate.fSecondsFraction = 0;
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
    switch (pDecodedItem->uDataType) {
 
@@ -1994,6 +2009,7 @@
  *
  * @retval QCBOR_ERR_DATE_OVERFLOW
  * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
+ * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
  * @retval QCBOR_ERR_BAD_TAG_CONTENT
  *
  * This is much simpler than the other epoch date format because
@@ -5051,6 +5067,7 @@
 
 
 
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
 static QCBORError ConvertDouble(const QCBORItem *pItem,
                                 uint32_t         uConvertTypes,
                                 double          *pdValue)
@@ -5373,6 +5390,7 @@
 
    pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
 }
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
 
 
diff --git a/src/qcbor_encode.c b/src/qcbor_encode.c
index 7c248ef..7f9c169 100644
--- a/src/qcbor_encode.c
+++ b/src/qcbor_encode.c
@@ -1,6 +1,7 @@
 /*==============================================================================
  Copyright (c) 2016-2018, The Linux Foundation.
  Copyright (c) 2018-2021, Laurence Lundblade.
+ Copyright (c) 2021, Arm Limited.
  All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -690,6 +691,7 @@
 }
 
 
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
 /*
  * Public functions for adding a double. See qcbor/qcbor_encode.h
  */
@@ -740,6 +742,7 @@
    QCBOREncode_AddFloatNoPreferred(me, fNum);
 #endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
 }
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
 
 #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
diff --git a/src/qcbor_err_to_str.c b/src/qcbor_err_to_str.c
index e96ed70..4879f91 100644
--- a/src/qcbor_err_to_str.c
+++ b/src/qcbor_err_to_str.c
@@ -3,6 +3,7 @@
 
  Copyright (c) 2020, Patrick Uiterwijk. All rights reserved.
  Copyright (c) 2020, Laurence Lundblade.
+ Copyright (c) 2021, Arm Limited. All rights reserved.
 
  SPDX-License-Identifier: BSD-3-Clause
 
@@ -60,6 +61,7 @@
     _ERR_TO_STR(ERR_HALF_PRECISION_DISABLED)
     _ERR_TO_STR(ERR_HW_FLOAT_DISABLED)
     _ERR_TO_STR(ERR_FLOAT_EXCEPTION)
+    _ERR_TO_STR(ERR_ALL_FLOAT_DISABLED)
 
     default:
         return "Unidentified error";
diff --git a/test/UsefulBuf_Tests.c b/test/UsefulBuf_Tests.c
index 264fbca..b6914d2 100644
--- a/test/UsefulBuf_Tests.c
+++ b/test/UsefulBuf_Tests.c
@@ -1,6 +1,7 @@
 /*==============================================================================
  Copyright (c) 2016-2018, The Linux Foundation.
  Copyright (c) 2018-2021, Laurence Lundblade.
+ Copyright (c) 2021, Arm Limited.
  All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -637,16 +638,20 @@
    const uint64_t u64 = 1984738472938472;
    const uint16_t u16 = 40000;
    const uint8_t  u8 = 9;
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
    const float    f  = (float)314.15;
    const double   d  = 2.1e10;
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
 
    UsefulOutBuf_AppendUint32(&UOB, u32); // Also tests UsefulOutBuf_InsertUint64 and UsefulOutBuf_GetEndPosition
    UsefulOutBuf_AppendUint64(&UOB, u64); // Also tests UsefulOutBuf_InsertUint32
    UsefulOutBuf_AppendUint16(&UOB, u16); // Also tests UsefulOutBuf_InsertUint16
    UsefulOutBuf_AppendByte(&UOB, u8);
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
    UsefulOutBuf_AppendFloat(&UOB, f); // Also tests UsefulOutBuf_InsertFloat
    UsefulOutBuf_AppendDouble(&UOB, d); // Also tests UsefulOutBuf_InsertDouble
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
    const UsefulBufC O = UsefulOutBuf_OutUBuf(&UOB);
    if(UsefulBuf_IsNULLC(O))
@@ -678,12 +683,14 @@
    if(UsefulInputBuf_GetByte(&UIB) != u8) {
       return "u8 out then in failed";
    }
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
    if(UsefulInputBuf_GetFloat(&UIB) != f) {
       return "float out then in failed";
    }
    if(UsefulInputBuf_GetDouble(&UIB) != d) {
       return "double out then in failed";
    }
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
    // Reset and go again for a few more tests
    UsefulInputBuf_Init(&UIB, O);
@@ -696,6 +703,7 @@
       return "Four compare failed";
    }
 
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
    if(UsefulInputBuf_BytesUnconsumed(&UIB) != 23){
       return "Wrong number of unconsumed bytes";
    }
@@ -707,6 +715,18 @@
    if(UsefulInputBuf_BytesAvailable(&UIB, 24)){
       return "Wrong number of bytes available II";
    }
+#else /* USEFULBUF_DISABLE_ALL_FLOAT */
+   if(UsefulInputBuf_BytesUnconsumed(&UIB) != 11){
+      return "Wrong number of unconsumed bytes";
+   }
+   if(!UsefulInputBuf_BytesAvailable(&UIB, 11)){
+      return "Wrong number of bytes available I";
+   }
+
+   if(UsefulInputBuf_BytesAvailable(&UIB, 12)){
+      return "Wrong number of bytes available II";
+   }
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
    UsefulInputBuf_Seek(&UIB, 0);
 
@@ -737,6 +757,7 @@
 }
 
 
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
 const char *UBUTest_CopyUtil(void)
 {
    if(UsefulBufUtil_CopyFloatToUint32(65536.0F) != 0x47800000) {
@@ -757,6 +778,7 @@
 
    return NULL;
 }
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
 
 
diff --git a/test/UsefulBuf_Tests.h b/test/UsefulBuf_Tests.h
index 976de62..0d06206 100644
--- a/test/UsefulBuf_Tests.h
+++ b/test/UsefulBuf_Tests.h
@@ -1,6 +1,7 @@
 /*==============================================================================
  Copyright (c) 2016-2018, The Linux Foundation.
  Copyright (c) 2018, Laurence Lundblade.
+ Copyright (c) 2021, Arm Limited.
  All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -45,6 +46,8 @@
 
 const char *  UIBTest_IntegerFormat(void);
 
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
 const char *  UBUTest_CopyUtil(void);
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
 #endif
diff --git a/test/float_tests.c b/test/float_tests.c
index 12f34fd..99297c0 100644
--- a/test/float_tests.c
+++ b/test/float_tests.c
@@ -2,6 +2,7 @@
  float_tests.c -- tests for float and conversion to/from half-precision
 
  Copyright (c) 2018-2020, Laurence Lundblade. All rights reserved.
+ Copyright (c) 2021, Arm Limited. All rights reserved.
 
  SPDX-License-Identifier: BSD-3-Clause
 
@@ -648,6 +649,7 @@
          0x18, 0x6A,
           0xFA, 0x00, 0x00, 0x00, 0x00};
 
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
 static const uint8_t spExpectedFloatsNoHalf[] = {
    0x8B,
       0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -749,6 +751,7 @@
       return 0;
    }
 }
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
 
 int32_t GeneralFloatDecodeTests()
@@ -766,133 +769,164 @@
       return -1;
    }
 
-#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
    uErr = QCBORDecode_GetNext(&DC, &Item);
-   if(uErr != QCBOR_SUCCESS ||
-      Item.uDataType != QCBOR_TYPE_DOUBLE ||
-      Item.val.dfnum != 0.0) {
+   if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+      || Item.uDataType != QCBOR_TYPE_DOUBLE
+      || Item.val.dfnum != 0.0
+#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
+   ) {
       return -2;
    }
-#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
-   uErr = QCBORDecode_GetNext(&DC, &Item);
-   if(uErr != QCBOR_ERR_HALF_PRECISION_DISABLED) {
-      return -3;
-   }
-#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
 
    uErr = QCBORDecode_GetNext(&DC, &Item);
-   if(uErr != QCBOR_SUCCESS ||
-      Item.uDataType != QCBOR_TYPE_DOUBLE ||
-      Item.val.dfnum != 3.14) {
+   if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+      || Item.uDataType != QCBOR_TYPE_DOUBLE
+      || Item.val.dfnum != 3.14
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+   ) {
       return -4;
    }
 
    uErr = QCBORDecode_GetNext(&DC, &Item);
-   if(uErr != QCBOR_SUCCESS ||
-      Item.uDataType != QCBOR_TYPE_DOUBLE ||
-      Item.val.dfnum != 0.0) {
+   if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+      || Item.uDataType != QCBOR_TYPE_DOUBLE
+      || Item.val.dfnum != 0.0
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+   ) {
       return -5;
    }
 
    uErr = QCBORDecode_GetNext(&DC, &Item);
-   if(uErr != QCBOR_SUCCESS ||
-      Item.uDataType != QCBOR_TYPE_DOUBLE ||
-      !isnan(Item.val.dfnum)) {
+   if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+      || Item.uDataType != QCBOR_TYPE_DOUBLE
+      || !isnan(Item.val.dfnum)
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+   ) {
       return -6;
    }
 
    uErr = QCBORDecode_GetNext(&DC, &Item);
-   if(uErr != QCBOR_SUCCESS ||
-      Item.uDataType != QCBOR_TYPE_DOUBLE ||
-      Item.val.dfnum != INFINITY) {
+   if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+      || Item.uDataType != QCBOR_TYPE_DOUBLE
+      || Item.val.dfnum != INFINITY
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+   ) {
       return -7;
    }
 
-#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
-   // Tests for normal config
+// Tests for normal config
    uErr = QCBORDecode_GetNext(&DC, &Item);
-   if(uErr != QCBOR_SUCCESS ||
-      Item.uDataType != QCBOR_TYPE_DOUBLE ||
-      Item.val.dfnum != 0.0) {
+   if(uErr != FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS)
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+      || Item.uDataType != QCBOR_TYPE_DOUBLE
+      || Item.val.dfnum != 0.0
+#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
+   ) {
       return -8;
    }
-#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
-      // Tests for preferred serialization turned off
-      uErr = QCBORDecode_GetNext(&DC, &Item);
-      if(uErr != QCBOR_ERR_HALF_PRECISION_DISABLED) {
-         return -13;
-      }
-#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
 
 #ifndef QCBOR_DISABLE_FLOAT_HW_USE
    uErr = QCBORDecode_GetNext(&DC, &Item);
-   if(uErr != QCBOR_SUCCESS ||
-      Item.uDataType != QCBOR_TYPE_DOUBLE ||
-      CHECK_EXPECTED_DOUBLE(3.14, Item.val.dfnum)) {
+   if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+      || Item.uDataType != QCBOR_TYPE_DOUBLE
+      || CHECK_EXPECTED_DOUBLE(3.14, Item.val.dfnum)
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+   ) {
       return -9;
    }
 
    uErr = QCBORDecode_GetNext(&DC, &Item);
-   if(uErr != QCBOR_SUCCESS ||
-      Item.uDataType != QCBOR_TYPE_DOUBLE ||
-      Item.val.dfnum != 0.0) {
+   if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+      || Item.uDataType != QCBOR_TYPE_DOUBLE
+      || Item.val.dfnum != 0.0
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+   ) {
       return -10;
    }
 
    uErr = QCBORDecode_GetNext(&DC, &Item);
-   if(uErr != QCBOR_SUCCESS ||
-      Item.uDataType != QCBOR_TYPE_DOUBLE ||
-      !isnan(Item.val.dfnum)) {
+   if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+      || Item.uDataType != QCBOR_TYPE_DOUBLE
+      || !isnan(Item.val.dfnum)
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+   ) {
       return -11;
    }
 
    uErr = QCBORDecode_GetNext(&DC, &Item);
-   if(uErr != QCBOR_SUCCESS ||
-      Item.uDataType != QCBOR_TYPE_DOUBLE ||
-      Item.val.dfnum != INFINITY) {
+   if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+      || Item.uDataType != QCBOR_TYPE_DOUBLE
+      || Item.val.dfnum != INFINITY
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+   ) {
       return -12;
    }
 
 #else /* QCBOR_DISABLE_FLOAT_HW_USE */
    // Tests for floating point HW use disabled
    uErr = QCBORDecode_GetNext(&DC, &Item);
-   if(uErr != QCBOR_SUCCESS ||
-      Item.uDataType != QCBOR_TYPE_FLOAT ||
-      CHECK_EXPECTED_DOUBLE(3.14, Item.val.fnum)) {
+   if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+      || Item.uDataType != QCBOR_TYPE_FLOAT
+      || CHECK_EXPECTED_DOUBLE(3.14, Item.val.fnum)
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+   ) {
       return -9;
    }
 
    uErr = QCBORDecode_GetNext(&DC, &Item);
-   if(uErr != QCBOR_SUCCESS ||
-      Item.uDataType != QCBOR_TYPE_FLOAT ||
-      Item.val.fnum != 0.0) {
+   if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+      || Item.uDataType != QCBOR_TYPE_FLOAT
+      || Item.val.fnum != 0.0
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+   ) {
       return -10;
    }
 
    uErr = QCBORDecode_GetNext(&DC, &Item);
-   if(uErr != QCBOR_SUCCESS ||
-      Item.uDataType != QCBOR_TYPE_FLOAT ||
-      !isnan(Item.val.fnum)) {
+   if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+      || Item.uDataType != QCBOR_TYPE_FLOAT
+      || !isnan(Item.val.fnum)
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+   ) {
       return -11;
    }
 
    uErr = QCBORDecode_GetNext(&DC, &Item);
-   if(uErr != QCBOR_SUCCESS ||
-      Item.uDataType != QCBOR_TYPE_FLOAT ||
-      Item.val.fnum != INFINITY) {
+   if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS)
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+      || Item.uDataType != QCBOR_TYPE_FLOAT
+      || Item.val.fnum != INFINITY
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+   ) {
       return -12;
    }
 #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
 
+
    /* Sufficent test coverage. Don't need to decode the rest */
 
 
    // Now tests for spiffy decode
    TestData = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedFloats);
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
    double d;
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
    QCBORDecode_Init(&DC, TestData, 0);
    QCBORDecode_EnterArray(&DC, NULL);
 
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
 #ifndef QCBOR_DISABLE_PREFERRED_FLOAT
 #ifndef QCBOR_DISABLE_FLOAT_HW_USE
    // Spiffy decode tests for normal full float support
@@ -1135,6 +1169,7 @@
    }
 #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
 #endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
    return 0;
 }
diff --git a/test/half_to_double_from_rfc7049.c b/test/half_to_double_from_rfc7049.c
index fce90f7..d4fded6 100644
--- a/test/half_to_double_from_rfc7049.c
+++ b/test/half_to_double_from_rfc7049.c
@@ -3,6 +3,8 @@
  Copyright (c) 2013 IETF Trust and the persons identified as the
  document authors.  All rights reserved.
 
+ Copyright (c) 2021, Arm Limited. All rights reserved.
+
  This document is subject to BCP 78 and the IETF Trust's Legal
  Provisions Relating to IETF Documents
  (http://trustee.ietf.org/license-info) in effect on the date of
@@ -33,6 +35,7 @@
 
 #include <math.h>
 
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
 double decode_half(unsigned char *halfp) {
     int half = (halfp[0] << 8) + halfp[1];
     int exp = (half >> 10) & 0x1f;
@@ -43,3 +46,4 @@
     else val = mant == 0 ? INFINITY : NAN;
     return half & 0x8000 ? -val : val;
 }
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
diff --git a/test/half_to_double_from_rfc7049.h b/test/half_to_double_from_rfc7049.h
index 4642f04..6318f80 100644
--- a/test/half_to_double_from_rfc7049.h
+++ b/test/half_to_double_from_rfc7049.h
@@ -2,6 +2,7 @@
  half_to_double_from_rfc7049.h -- interface to IETF float conversion code.
 
  Copyright (c) 2018-2020, Laurence Lundblade. All rights reserved.
+ Copyright (c) 2021, Arm Limited. All rights reserved.
 
  SPDX-License-Identifier: BSD-3-Clause
 
@@ -13,6 +14,8 @@
 #ifndef half_to_double_from_rfc7049_h
 #define half_to_double_from_rfc7049_h
 
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
 double decode_half(unsigned char *halfp);
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
 #endif /* half_to_double_from_rfc7049_h */
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index 4b20e71..aebe492 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -1,6 +1,7 @@
 /*==============================================================================
  Copyright (c) 2016-2018, The Linux Foundation.
  Copyright (c) 2018-2021, Laurence Lundblade.
+ Copyright (c) 2021, Arm Limited.
  All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -2418,8 +2419,11 @@
       return -4;
    }
    if(Item.uDataType != QCBOR_TYPE_DATE_EPOCH ||
-      Item.val.epochDate.nSeconds != 1400000000 ||
-      Item.val.epochDate.fSecondsFraction != 0 ) {
+      Item.val.epochDate.nSeconds != 1400000000
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+      || Item.val.epochDate.fSecondsFraction != 0
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+     ) {
       return -5;
    }
 
@@ -2436,7 +2440,9 @@
    }
    if(Item.uDataType != QCBOR_TYPE_DATE_EPOCH ||
       Item.val.epochDate.nSeconds != 1400000001 ||
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
       Item.val.epochDate.fSecondsFraction != 0 ||
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
       !QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_ENC_AS_B64)) {
       return -8;
    }
@@ -2446,14 +2452,18 @@
       return -9;
    }
 
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
 #ifndef QCBOR_DISABLE_FLOAT_HW_USE
    // Epoch date in float format with fractional seconds
    if((uError = QCBORDecode_GetNext(&DCtx, &Item))) {
       return -10;
    }
    if(Item.uDataType != QCBOR_TYPE_DATE_EPOCH ||
-      Item.val.epochDate.nSeconds != 1 ||
-      CHECK_EXPECTED_DOUBLE(Item.val.epochDate.fSecondsFraction, 0.1 )) {
+      Item.val.epochDate.nSeconds != 1
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+      || CHECK_EXPECTED_DOUBLE(Item.val.epochDate.fSecondsFraction, 0.1 )
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+     ) {
       return -11;
    }
 
@@ -2526,6 +2536,7 @@
 #endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
 
 #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
    return 0;
 }
@@ -2655,11 +2666,11 @@
    QCBORDecode_GetEpochDate(&DC, QCBOR_TAG_REQUIREMENT_TAG, &nEpochDateFail);
    uError = QCBORDecode_GetAndResetError(&DC);
 #ifndef QCBOR_DISABLE_FLOAT_HW_USE
-   if(uError != QCBOR_ERR_DATE_OVERFLOW) {
+   if(uError != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_ERR_DATE_OVERFLOW)) {
       return 1111;
    }
 #else
-   if(uError != QCBOR_ERR_FLOAT_DATE_DISABLED) {
+   if(uError != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_ERR_FLOAT_DATE_DISABLED)) {
       return 1112;
    }
 #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
@@ -2676,12 +2687,12 @@
    uError = QCBORDecode_GetAndResetError(&DC);
 #ifndef QCBOR_DISABLE_PREFERRED_FLOAT
 #ifndef QCBOR_DISABLE_FLOAT_HW_USE
-   const QCBORError uExpectedforHalfMinusInfinity = QCBOR_ERR_DATE_OVERFLOW;
+   const QCBORError uExpectedforHalfMinusInfinity = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_ERR_DATE_OVERFLOW);
 #else /* QCBOR_DISABLE_FLOAT_HW_USE */
-   const QCBORError uExpectedforHalfMinusInfinity = QCBOR_ERR_FLOAT_DATE_DISABLED;
+   const QCBORError uExpectedforHalfMinusInfinity = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_ERR_FLOAT_DATE_DISABLED);
 #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
 #else /* QCBOR_DISABLE_PREFERRED_FLOAT */
-   const QCBORError uExpectedforHalfMinusInfinity = QCBOR_ERR_HALF_PRECISION_DISABLED;
+   const QCBORError uExpectedforHalfMinusInfinity = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_ERR_HALF_PRECISION_DISABLED);
 #endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
    if(uError != uExpectedforHalfMinusInfinity) {
       return 2;
@@ -2715,7 +2726,7 @@
    }
 #else /* QCBOR_DISABLE_FLOAT_HW_USE */
    uError = QCBORDecode_GetAndResetError(&DC);
-   if(uError != QCBOR_ERR_FLOAT_DATE_DISABLED) {
+   if(uError != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_ERR_FLOAT_DATE_DISABLED)) {
       return 102;
    }
 #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
@@ -2729,7 +2740,7 @@
    }
 #else /* QCBOR_DISABLE_FLOAT_HW_USE */
    uError = QCBORDecode_GetAndResetError(&DC);
-   if(uError != QCBOR_ERR_FLOAT_DATE_DISABLED) {
+   if(uError != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_ERR_FLOAT_DATE_DISABLED)) {
       return 112;
    }
 #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
@@ -2743,7 +2754,7 @@
    }
 #else /* QCBOR_DISABLE_FLOAT_HW_USE */
    uError = QCBORDecode_GetAndResetError(&DC);
-   if(uError != QCBOR_ERR_FLOAT_DATE_DISABLED) {
+   if(uError != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_ERR_FLOAT_DATE_DISABLED)) {
       return 104;
    }
 #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
@@ -5483,11 +5494,11 @@
    QCBORDecode_GetEpochDateInMapN(&DCtx, 0x04, QCBOR_TAG_REQUIREMENT_TAG, &nInt);
    uErr = QCBORDecode_GetAndResetError(&DCtx);
 #ifndef QCBOR_DISABLE_FLOAT_HW_USE
-   if(uErr != QCBOR_ERR_DATE_OVERFLOW) {
+   if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_ERR_DATE_OVERFLOW)) {
       return 2024;
    }
 #else
-   if(uErr != QCBOR_ERR_FLOAT_DATE_DISABLED) {
+   if(uErr != FLOAT_ERR_CODE_NO_FLOAT(QCBOR_ERR_FLOAT_DATE_DISABLED)) {
       return 2027;
    }
 #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
@@ -5831,14 +5842,14 @@
       {(uint8_t[]){0xfb, 0x40, 0x59, 0x13, 0x33, 0x33, 0x33, 0x33, 0x33}, 9},
 #ifndef QCBOR_DISABLE_FLOAT_HW_USE
       100L,
-      QCBOR_SUCCESS,
+      FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS),
       100ULL,
-      QCBOR_SUCCESS,
+      FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS),
 #else /* QCBOR_DISABLE_FLOAT_HW_USE */
       0,
-      QCBOR_ERR_HW_FLOAT_DISABLED,
+      FLOAT_ERR_CODE_NO_FLOAT(QCBOR_ERR_HW_FLOAT_DISABLED),
       0,
-      QCBOR_ERR_HW_FLOAT_DISABLED,
+      FLOAT_ERR_CODE_NO_FLOAT(QCBOR_ERR_HW_FLOAT_DISABLED),
 #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
       100.3,
       QCBOR_SUCCESS
@@ -5846,50 +5857,32 @@
    {
       "Floating point value NaN 0xfa7fc00000",
       {(uint8_t[]){0xfa, 0x7f, 0xc0, 0x00, 0x00}, 5},
-#ifndef QCBOR_DISABLE_FLOAT_HW_USE
       0,
-      QCBOR_ERR_FLOAT_EXCEPTION,
+      FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_ERR_FLOAT_EXCEPTION),
       0,
-      QCBOR_ERR_FLOAT_EXCEPTION,
-#else /* QCBOR_DISABLE_FLOAT_HW_USE */
-      0,
-      QCBOR_ERR_HW_FLOAT_DISABLED,
-      0,
-      QCBOR_ERR_HW_FLOAT_DISABLED,
-#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+      FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_ERR_FLOAT_EXCEPTION),
       NAN,
       QCBOR_SUCCESS
    },
    {
       "half-precision Floating point value -4",
       {(uint8_t[]){0xf9, 0xc4, 0x00}, 3},
-#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
-#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
       // Normal case with all enabled.
       -4,
-      QCBOR_SUCCESS,
+      FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(QCBOR_SUCCESS),
       0,
-      QCBOR_ERR_NUMBER_SIGN_CONVERSION,
+      FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(QCBOR_ERR_NUMBER_SIGN_CONVERSION),
       -4.0,
-      QCBOR_SUCCESS
-#else /* QCBOR_DISABLE_FLOAT_HW_USE */
-      // Float HW disabled
-      -4,
-      QCBOR_ERR_HW_FLOAT_DISABLED, // Can't convert to integer
+      FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(QCBOR_SUCCESS)
+#else /* USEFULBUF_DISABLE_ALL_FLOAT */
       0,
-      QCBOR_ERR_HW_FLOAT_DISABLED, // Can't convert to integer
-      -4.0,
-      QCBOR_SUCCESS // Uses ieee754.h to conver, not HW
-#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
-#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
-      // Half-precision disabled
-      -4,
-      QCBOR_ERR_HALF_PRECISION_DISABLED,
+      QCBOR_ERR_ALL_FLOAT_DISABLED,
       0,
-      QCBOR_ERR_HALF_PRECISION_DISABLED,
-      -4.0,
-      QCBOR_ERR_HALF_PRECISION_DISABLED
-#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
+      QCBOR_ERR_ALL_FLOAT_DISABLED,
+      0,
+      QCBOR_ERR_ALL_FLOAT_DISABLED,
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
    },
    {
       "Decimal fraction 3/10",
@@ -5913,17 +5906,10 @@
    {
       "+inifinity",
       {(uint8_t[]){0xfa, 0x7f, 0x80, 0x00, 0x00}, 5},
-#ifndef QCBOR_DISABLE_FLOAT_HW_USE
       0,
-      QCBOR_ERR_FLOAT_EXCEPTION,
+      FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_ERR_FLOAT_EXCEPTION),
       0,
-      QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW,
-#else /* QCBOR_DISABLE_FLOAT_HW_USE */
-      0,
-      QCBOR_ERR_HW_FLOAT_DISABLED,
-      0,
-      QCBOR_ERR_HW_FLOAT_DISABLED,
-#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+      FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW),
       INFINITY,
       QCBOR_SUCCESS
    },
@@ -7123,6 +7109,7 @@
       return 4;
    }
 
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
    double uDouble;
    QCBORDecode_GetDoubleConvertAllInMapSZ(&DCtx,
                                           "label2",
@@ -7140,6 +7127,7 @@
       return 7;
    }
 #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
 
    QCBORDecode_ExitMap(&DCtx);
diff --git a/test/run_tests.c b/test/run_tests.c
index 53d83f6..be2582f 100644
--- a/test/run_tests.c
+++ b/test/run_tests.c
@@ -2,6 +2,7 @@
  run_tests.c -- test aggregator and results reporting
 
  Copyright (c) 2018-2021, Laurence Lundblade. All rights reserved.
+ Copyright (c) 2021, Arm Limited. All rights reserved.
 
  SPDX-License-Identifier: BSD-3-Clause
 
@@ -51,7 +52,9 @@
 
 
 static test_entry2 s_tests2[] = {
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
     TEST_ENTRY(UBUTest_CopyUtil),
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
     TEST_ENTRY(UOBTest_NonAdversarial),
     TEST_ENTRY(TestBasicSanity),
     TEST_ENTRY(UOBTest_BoundaryConditionsTest),
@@ -114,7 +117,9 @@
     TEST_ENTRY(DoubleAsSmallestTest),
     TEST_ENTRY(HalfPrecisionAgainstRFCCodeTest),
 #endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
     TEST_ENTRY(GeneralFloatEncodeTests),
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
     TEST_ENTRY(GeneralFloatDecodeTests),
     TEST_ENTRY(BstrWrapTest),
     TEST_ENTRY(BstrWrapErrorTest),