Do not use compound literals when QCBOR is used with C++ (#119)

This avoids use of compound literals in public header files where possible.

When not possible, the code is conditional on __cplusplus and uses initialization lists instead of compound literals


* Do not use compound literals when used with C++

* undo example.h change; tiny fixes to UsefulBuf

Co-authored-by: Laurence Lundblade <lgl@securitytheory.com>
diff --git a/inc/qcbor/UsefulBuf.h b/inc/qcbor/UsefulBuf.h
index 990191a..c271a31 100644
--- a/inc/qcbor/UsefulBuf.h
+++ b/inc/qcbor/UsefulBuf.h
@@ -41,6 +41,7 @@
 
  when         who             what, where, why
  --------     ----            --------------------------------------------------
+ 8/8/2021     dthaler/llundbla Work with C++ without compiler extensions
  5/11/2021    llundblade      Improve comments and comment formatting.
  3/6/2021     mcr/llundblade  Fix warnings related to --Wcast-qual
  2/17/2021    llundblade      Add method to go from a pointer to an offset.
@@ -276,14 +277,36 @@
  * the @c ptr field is @c NULL. It doesn't matter what @c len is.  See
  * UsefulBuf_IsEmpty() for the distinction between null and empty.
  */
-#define NULLUsefulBufC  ((UsefulBufC) {NULL, 0})
-
+/*
+ * NULLUsefulBufC and few other macros have to be
+ * definied differently in C than C++ because there
+ * is no common construct for a literal structure.
+ *
+ * In C compound literals are used.
+ *
+ * In C++ list initalization is used. This only works
+ * in C++11 and later.
+ *
+ * Note that some popular C++ compilers can handle compound
+ * literals with on-by-default extensions, however
+ * this code aims for full correctness with strict
+ * compilers so they are not used.
+ */
+#ifdef __cplusplus
+#define NULLUsefulBufC {NULL, 0}
+#else
+#define NULLUsefulBufC ((UsefulBufC) {NULL, 0})
+#endif
 
 /**
  * A null @ref UsefulBuf is one that has no memory associated the same
  * way @c NULL points to nothing. It does not matter what @c len is.
  **/
-#define NULLUsefulBuf   ((UsefulBuf) {NULL, 0})
+#ifdef __cplusplus
+#define NULLUsefulBuf  {NULL, 0}
+#else
+#define NULLUsefulBuf  ((UsefulBuf) {NULL, 0})
+#endif
 
 
 /**
@@ -395,8 +418,12 @@
  *
  * The terminating \0 (NULL) is NOT included in the length!
  */
+#ifdef __cplusplus
+#define UsefulBuf_FROM_SZ_LITERAL(szString)  {(szString), sizeof(szString)-1}
+#else
 #define UsefulBuf_FROM_SZ_LITERAL(szString) \
     ((UsefulBufC) {(szString), sizeof(szString)-1})
+#endif
 
 
 /**
@@ -405,9 +432,12 @@
  * @c pBytes must be a literal string that @c sizeof() works on.  It
  * will not work on non-literal arrays.
  */
+#ifdef __cplusplus
+#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes)  {(pBytes), sizeof(pBytes)}
+#else
 #define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \
-    ((UsefulBufC) {(pBytes), sizeof(pBytes)})
-
+   ((UsefulBufC) {(pBytes), sizeof(pBytes)})
+#endif
 
 /**
  * Make an automatic variable named @c name of type @ref UsefulBuf and
@@ -423,8 +453,12 @@
  * stack variables or static variables.  Also see @ref
  * UsefulBuf_MAKE_STACK_UB.
  */
+#ifdef __cplusplus
+#define UsefulBuf_FROM_BYTE_ARRAY(pBytes)  {(pBytes), sizeof(pBytes)}
+#else
 #define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \
-    ((UsefulBuf) {(pBytes), sizeof(pBytes)})
+   ((UsefulBuf) {(pBytes), sizeof(pBytes)})
+#endif
 
 
 /**
@@ -614,8 +648,7 @@
 
 #ifndef USEFULBUF_DISABLE_DEPRECATED
 /** Deprecated macro; use @ref UsefulBuf_FROM_SZ_LITERAL instead */
-#define SZLiteralToUsefulBufC(szString) \
-    ((UsefulBufC) {(szString), sizeof(szString)-1})
+#define SZLiteralToUsefulBufC(szString)  UsefulBuf_FROM_SZ_LITERAL(szString)
 
 /** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
 #define  MakeUsefulBufOnStack(name, size) \
@@ -624,16 +657,22 @@
 
 /** Deprecated macro; use @ref UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
 #define ByteArrayLiteralToUsefulBufC(pBytes) \
-    ((UsefulBufC) {(pBytes), sizeof(pBytes)})
+   UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes)
 
 /** Deprecated function; use UsefulBuf_Unconst() instead */
 static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
 {
+   UsefulBuf UB;
+
    // See UsefulBuf_Unconst() implementation for comment on pragmas
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wcast-qual"
-    return (UsefulBuf){(void *)UBC.ptr, UBC.len};
+   UB.ptr = (void *)UBC.ptr;
 #pragma GCC diagnostic pop
+
+   UB.len = UBC.len;
+
+   return UB;
 }
 #endif /* USEFULBUF_DISABLE_DEPRECATED */
 
@@ -1623,24 +1662,37 @@
 
 static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB)
 {
-   return (UsefulBufC){UB.ptr, UB.len};
+   UsefulBufC UBC;
+   UBC.ptr = UB.ptr;
+   UBC.len = UB.len;
+
+   return UBC;
 }
 
 static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
 {
+   UsefulBuf UB;
+
    /* -Wcast-qual is a good warning flag to use in general. This is
     * the one place in UsefulBuf where it needs to be quieted. Since
     * clang supports GCC pragmas, this works for clang too. */
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wcast-qual"
-   return (UsefulBuf){(void *)UBC.ptr, UBC.len};
+   UB.ptr = (void *)UBC.ptr;
 #pragma GCC diagnostic pop
+
+   UB.len = UBC.len;
+
+   return UB;
 }
 
 
 static inline UsefulBufC UsefulBuf_FromSZ(const char *szString)
 {
-   return ((UsefulBufC) {szString, strlen(szString)});
+   UsefulBufC UBC;
+   UBC.ptr = szString;
+   UBC.len = strlen(szString);
+   return UBC;
 }
 
 
@@ -1650,16 +1702,24 @@
 }
 
 
-static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value)
+static inline UsefulBufC UsefulBuf_Set(UsefulBuf Dest, uint8_t value)
 {
-   memset(pDest.ptr, value, pDest.len);
-   return (UsefulBufC){pDest.ptr, pDest.len};
+   memset(Dest.ptr, value, Dest.len);
+
+   UsefulBufC UBC;
+   UBC.ptr = Dest.ptr;
+   UBC.len = Dest.len;
+
+   return UBC;
 }
 
 
 static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
 {
-   return UsefulBuf_Copy(Dest, (UsefulBufC){ptr, len});
+   UsefulBufC UBC;
+   UBC.ptr = ptr;
+   UBC.len = len;
+   return UsefulBuf_Copy(Dest, UBC);
 }
 
 
@@ -1668,7 +1728,12 @@
    if(uAmount > UB.len) {
       return NULLUsefulBufC;
    }
-   return (UsefulBufC){UB.ptr, uAmount};
+   UsefulBufC UBC;
+
+   UBC.ptr = UB.ptr;
+   UBC.len = uAmount;
+
+   return UBC;
 }
 
 
@@ -1679,9 +1744,11 @@
    if(uAmount > UB.len) {
       ReturnValue = NULLUsefulBufC;
    } else if(UB.ptr == NULL) {
-      ReturnValue = (UsefulBufC){NULL, UB.len - uAmount};
+      ReturnValue.ptr = NULL;
+      ReturnValue.len = UB.len - uAmount;
    } else {
-      ReturnValue = (UsefulBufC){(const uint8_t *)UB.ptr + uAmount, UB.len - uAmount};
+      ReturnValue.ptr = (const uint8_t *)UB.ptr + uAmount;
+      ReturnValue.len = UB.len - uAmount;
    }
 
    return ReturnValue;
@@ -1775,9 +1842,11 @@
                                              const char *szString,
                                              size_t uPos)
 {
-   UsefulOutBuf_InsertUsefulBuf(pMe,
-                                (UsefulBufC){szString, strlen(szString)},
-                                uPos);
+   UsefulBufC UBC;
+   UBC.ptr = szString;
+   UBC.len = strlen(szString);
+
+   UsefulOutBuf_InsertUsefulBuf(pMe, UBC, uPos);
 }
 
 
@@ -1951,7 +2020,11 @@
 static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pMe,
                                              const char *szString)
 {
-   UsefulOutBuf_AppendUsefulBuf(pMe, (UsefulBufC){szString, strlen(szString)});
+   UsefulBufC UBC;
+   UBC.ptr = szString;
+   UBC.len = strlen(szString);
+
+   UsefulOutBuf_AppendUsefulBuf(pMe, UBC);
 }
 
 
@@ -2095,7 +2168,10 @@
    if(!pResult) {
       return NULLUsefulBufC;
    } else {
-      return (UsefulBufC){pResult, uNum};
+      UsefulBufC UBC;
+      UBC.ptr = pResult;
+      UBC.len = uNum;
+      return UBC;
    }
 }
 
diff --git a/inc/qcbor/qcbor_common.h b/inc/qcbor/qcbor_common.h
index 8ccc8b4..7fc48de 100644
--- a/inc/qcbor/qcbor_common.h
+++ b/inc/qcbor/qcbor_common.h
@@ -504,7 +504,7 @@
 
    /** Trying to cancel a byte string wrapping after items have been
        added to it. */
-   QCBOR_ERR_CANNOT_CANCEL = 45,
+   QCBOR_ERR_CANNOT_CANCEL = 45
 
    /* This is stored in uint8_t; never add values > 255 */
 } QCBORError;