first check-in of UsefulBuf example
diff --git a/Makefile b/Makefile
index fd5ee92..a4fe2b5 100644
--- a/Makefile
+++ b/Makefile
@@ -28,7 +28,7 @@
 
 TEST_OBJ=test/UsefulBuf_Tests.o test/qcbor_encode_tests.o \
     test/qcbor_decode_tests.o test/run_tests.o \
-    test/float_tests.o test/half_to_double_from_rfc7049.o example.o
+    test/float_tests.o test/half_to_double_from_rfc7049.o example.o ub-example.o
 
 .PHONY: all so install uninstall clean
 
@@ -58,6 +58,7 @@
 src/qcbor_err_to_str.o: inc/qcbor/qcbor_common.h
 
 example.o:	$(PUBLIC_INTERFACE)
+ub-example.o:	$(PUBLIC_INTERFACE)
 
 test/run_tests.o: test/UsefulBuf_Tests.h test/float_tests.h test/run_tests.h test/qcbor_encode_tests.h test/qcbor_decode_tests.h inc/qcbor/qcbor_private.h
 test/UsefulBuf_Tests.o: test/UsefulBuf_Tests.h inc/qcbor/UsefulBuf.h
diff --git a/QCBOR.xcodeproj/project.pbxproj b/QCBOR.xcodeproj/project.pbxproj
index 727464e..625e7af 100644
--- a/QCBOR.xcodeproj/project.pbxproj
+++ b/QCBOR.xcodeproj/project.pbxproj
@@ -56,6 +56,7 @@
 		E776E091214AE07500E67947 /* qcbor_decode.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E08E214AE07500E67947 /* qcbor_decode.c */; };
 		E776E097214AE0C700E67947 /* cmd_line_main.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E096214AE0C700E67947 /* cmd_line_main.c */; };
 		E7864766252CE63100A0C11B /* qcbor_err_to_str.c in Sources */ = {isa = PBXBuildFile; fileRef = E7864765252CE63100A0C11B /* qcbor_err_to_str.c */; };
+		E7C960B92800A09E00FB537C /* ub-example.c in Sources */ = {isa = PBXBuildFile; fileRef = E7C960B82800A09E00FB537C /* ub-example.c */; };
 		E7FDBF04256C969D007138A8 /* qcbor_encode.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E08C214AE07400E67947 /* qcbor_encode.c */; };
 		E7FDBF05256C969D007138A8 /* ieee754.c in Sources */ = {isa = PBXBuildFile; fileRef = E73B57582161CA690080D658 /* ieee754.c */; };
 		E7FDBF06256C969D007138A8 /* qcbor_err_to_str.c in Sources */ = {isa = PBXBuildFile; fileRef = E7864765252CE63100A0C11B /* qcbor_err_to_str.c */; };
@@ -170,13 +171,15 @@
 		E776E08D214AE07500E67947 /* UsefulBuf.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.c; name = UsefulBuf.c; path = src/UsefulBuf.c; sourceTree = "<group>"; tabWidth = 3; };
 		E776E08E214AE07500E67947 /* qcbor_decode.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.c; name = qcbor_decode.c; path = src/qcbor_decode.c; sourceTree = "<group>"; tabWidth = 3; };
 		E776E094214AE09700E67947 /* UsefulBuf.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.h; name = UsefulBuf.h; path = inc/UsefulBuf.h; sourceTree = "<group>"; tabWidth = 3; };
-		E776E096214AE0C700E67947 /* cmd_line_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmd_line_main.c; sourceTree = "<group>"; };
+		E776E096214AE0C700E67947 /* cmd_line_main.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.c; path = cmd_line_main.c; sourceTree = "<group>"; tabWidth = 3; };
 		E776E161214EE19C00E67947 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
 		E7864765252CE63100A0C11B /* qcbor_err_to_str.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = qcbor_err_to_str.c; path = src/qcbor_err_to_str.c; sourceTree = "<group>"; };
 		E78C91DE240C90C100F4CECE /* qcbor_decode.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.h; name = qcbor_decode.h; path = inc/qcbor/qcbor_decode.h; sourceTree = "<group>"; tabWidth = 3; };
 		E78C91DF240C90C100F4CECE /* qcbor_common.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.h; name = qcbor_common.h; path = inc/qcbor/qcbor_common.h; sourceTree = "<group>"; tabWidth = 3; };
 		E78C91E0240C90C100F4CECE /* qcbor_private.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.h; name = qcbor_private.h; path = inc/qcbor/qcbor_private.h; sourceTree = "<group>"; tabWidth = 3; };
 		E78C91E1240C90C100F4CECE /* qcbor_encode.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.h; name = qcbor_encode.h; path = inc/qcbor/qcbor_encode.h; sourceTree = "<group>"; tabWidth = 3; };
+		E7C960B72800A09E00FB537C /* ub-example.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ub-example.h"; sourceTree = "<group>"; };
+		E7C960B82800A09E00FB537C /* ub-example.c */ = {isa = PBXFileReference; indentWidth = 3; lastKnownFileType = sourcecode.c.c; path = "ub-example.c"; sourceTree = "<group>"; tabWidth = 3; };
 		E7FDBF16256C969D007138A8 /* QCBOR_Disable_Indef */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = QCBOR_Disable_Indef; sourceTree = BUILT_PRODUCTS_DIR; };
 		E7FDBF2C257A6C1F007138A8 /* QCBOR_Disable_Indef_array */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = QCBOR_Disable_Indef_array; sourceTree = BUILT_PRODUCTS_DIR; };
 /* End PBXFileReference section */
@@ -231,6 +234,8 @@
 			isa = PBXGroup;
 			children = (
 				E743D0E124AC516D0017899F /* example.c */,
+				E7C960B72800A09E00FB537C /* ub-example.h */,
+				E7C960B82800A09E00FB537C /* ub-example.c */,
 				E743D0F224AC54600017899F /* example.h */,
 			);
 			name = example;
@@ -525,6 +530,7 @@
 				E776E090214AE07500E67947 /* UsefulBuf.c in Sources */,
 				0FA9BEBA216DC7AD00BA646B /* qcbor_encode_tests.c in Sources */,
 				E776E097214AE0C700E67947 /* cmd_line_main.c in Sources */,
+				E7C960B92800A09E00FB537C /* ub-example.c in Sources */,
 				E743D0F324AD08020017899F /* example.c in Sources */,
 				0FA9BEBD216DE31700BA646B /* UsefulBuf_Tests.c in Sources */,
 			);
diff --git a/cmd_line_main.c b/cmd_line_main.c
index ef59e43..59ceb3a 100644
--- a/cmd_line_main.c
+++ b/cmd_line_main.c
@@ -13,6 +13,7 @@
 #include <stdio.h>
 #include "run_tests.h"
 #include "example.h"
+#include "ub-example.h"
 
 
 /*
@@ -33,6 +34,7 @@
    (void)argc; // Avoid unused parameter error
 
    RunQCborExample();
+   RunUsefulBufExample();
 
 
    // This call prints out sizes of data structures to remind us
diff --git a/ub-example.c b/ub-example.c
new file mode 100644
index 0000000..71bb26b
--- /dev/null
+++ b/ub-example.c
@@ -0,0 +1,258 @@
+//
+//  ub-example.c
+//  QCBOR
+//
+//  Created by Laurence Lundblade on 4/8/22.
+//  Copyright © 2022 Laurence Lundblade. All rights reserved.
+//
+
+#include "ub-example.h"
+
+#include "UsefulBuf.h"
+
+
+/*
+ A large number of the security issues with C code come from mistakes
+ made with a pointer and length for a buffer or some binary data.
+ UsefulBuf adopts a convention that a pointer and length *always*
+ go together to migitigate this.  With UsefulBuf there are never
+ pointers without lengths so you always know how big the buffer
+ or the data is.
+
+ C99 allows passing structures so a structure is used. Compilers
+ are smart these days so the object code produced is no different
+ than passing two separate parameters. Passing structures also
+ makes the interfaces prettier. Assignments of structures also
+ can make code prettier.
+
+ There are a bunch of (tested!) functions to manipulate UsefulBuf's so
+ code using it may have no pointer manipulation at all!
+
+ In this example the buffers that are filled in with data
+ are const and the ones that are to-be-filled in are not
+ const. Keeping const distinct from non-const is helpful
+ when reading the code and helps avoid some coding mistakes.
+ See this:
+ https://stackoverflow.com/questions/117293/use-of-const-for-function-parameters
+
+ This contrived example copies data from input to output
+ expanding bytes with the value 'x' to 'xx'.
+
+ Input -- This is the pointer and length of the input, the
+ bytes to copy. Note that UsefulBufC.ptr is a const void *
+ indicates that input data won't be changed by this function.
+ There is a "C" in UsefulBufC to indicate the value is const.
+ The length here is the length of the valid input data. Note
+ also that the parameter Input is const, so this is fully
+ const and clearly an [in] parameter.
+
+ Output -- This is a pointer and length of
+ the memory to used to store the output. The correct length
+ here is critical for code security. Note that  UsefulBuf.ptr
+ is void *, it is not const indicating data can be written to
+ it. Note that the parameter itself *is* const indicating
+ that the code below will not point this to some other buffer
+ or change the length and clearly marked as an [in] parameter.
+
+ Output -- This is the interesting and unusual one. To stay
+ consistent with always paring and a length and for
+ a pointer to valid data to always be const, this is returned as
+ a UsefulBufC. Note that the parameter is a pointer to a
+ UsefulBufC, a *place* to return a UsefulBufC.
+
+ In this case and most cases the pointer in Output->ptr
+ will be the same as OutputBuffer.ptr. This may seem
+ redundant, but there's a few reasons for it. First,
+ is the goal of always pairing a pointer and a length.
+ Second is being more strict with constness. Third
+ is the code hygene and clarity of having
+ variables for to-be-filled buffers be distinct from those
+ containing valid data. Fourth, there are no [in,out]
+ parameters, only [in] parameters and [out] parameters
+ (the to-be-filled-in buffer is considered an [in]
+ parameter).
+
+ Note that the compiler will be smart about all
+ this and should generate pretty much the same code
+ as for a traditional interface with the
+ length parameter. On x86 with gcc-11 and no stack guards,
+ the UB code is 81 bytes and the traditional code is 77 bytes.
+
+ This supports computing of the would-be output
+ without actually doing any outputing by making
+ the OutputBuffer have a NULL pointer and a very
+ large length, e.g., {NULL, SIZE_MAX}.
+
+ */
+int
+ExpandUB(const UsefulBufC   Input,
+         const UsefulBuf    OutputBuffer,
+         UsefulBufC        *Output)
+{
+    size_t nInputPosition;
+    size_t nOutputPosition;
+
+    nOutputPosition = 0;
+
+    /* Loop over all the bytes in Input */
+    for(nInputPosition = 0; nInputPosition < Input.len; nInputPosition++) {
+        const uint8_t nInputByte = ((uint8_t*)Input.ptr)[nInputPosition];
+
+        /* Copy every byte */
+        if(OutputBuffer.ptr != NULL) {
+            ((uint8_t *)OutputBuffer.ptr)[nOutputPosition] = nInputByte;
+        }
+        nOutputPosition++;
+        if(nOutputPosition >= OutputBuffer.len) {
+            return -1l;
+        }
+
+        /* Double output 'x' because that is what this contrived example does */
+        if(nInputByte== 'x') {
+            if(OutputBuffer.ptr != NULL) {
+                ((uint8_t *)OutputBuffer.ptr)[nOutputPosition] = 'x';
+            }
+            nOutputPosition++;
+            if(nOutputPosition >= OutputBuffer.len) {
+                return -1l;
+            }
+        }
+    }
+
+    *Output = (UsefulBufC){OutputBuffer.ptr, nOutputPosition};
+
+    return 0; /* success */
+}
+
+
+/* This is the more tradional way to implement this. */
+int ExpandTraditional(const uint8_t  *pInputPointer,
+                       const size_t    uInputLength,
+                       uint8_t        *pOutputBuffer,
+                       const size_t    uOutputBufferLength,
+                       size_t         *puOutputLength)
+{
+    size_t nInputPosition;
+    size_t nOutputPosition;
+
+    nOutputPosition = 0;
+
+    /* Loop over all the bytes in Input */
+    for(nInputPosition = 0; nInputPosition < uInputLength; nInputPosition++) {
+        const uint8_t nInputByte = ((uint8_t*)pInputPointer)[nInputPosition];
+
+        /* Copy every byte */
+        if(pOutputBuffer != NULL) {
+            ((uint8_t *)pOutputBuffer)[nOutputPosition] = nInputByte;
+        }
+        nOutputPosition++;
+        if(nOutputPosition >= uOutputBufferLength) {
+            return -1l;
+        }
+
+        /* Double output 'x' because that is what this contrived example does */
+        if(nInputByte== 'x') {
+            if(pOutputBuffer != NULL) {
+                ((uint8_t *)pOutputBuffer)[nOutputPosition] = 'x';
+            }
+            nOutputPosition++;
+            if(nOutputPosition >= uOutputBufferLength) {
+                return -1l;
+            }
+        }
+    }
+
+   *puOutputLength = nOutputPosition;
+
+    return 0; /* success */
+}
+
+
+/*
+ Here's an example of going from a traditional interface
+ interface to a UsefulBuf interface.
+ */
+int ExpandTraditionalAdapted(const uint8_t  *pInputPointer,
+                             size_t          uInputLength,
+                             uint8_t        *pOutputBuffer,
+                             size_t          uOutputBufferLength,
+                             size_t         *puOutputLength)
+{
+    UsefulBufC  Input;
+    UsefulBuf   OutputBuffer;
+    UsefulBufC  Output;
+    int         nReturn;
+
+    Input = (UsefulBufC){pInputPointer, uInputLength};
+    OutputBuffer = (UsefulBuf){pOutputBuffer, uOutputBufferLength};
+
+    nReturn = ExpandUB(Input, OutputBuffer, &Output);
+
+    *puOutputLength = Output.len;
+
+    return nReturn;
+}
+
+
+/* Here's an example for going from a UsefulBuf interface
+ to a traditional interface. */
+int
+ExpandUBAdapted(const UsefulBufC   Input,
+                const UsefulBuf    OutputBuffer,
+                UsefulBufC        *Output)
+{
+    Output->ptr = OutputBuffer.ptr;
+
+    return ExpandTraditional(Input.ptr, Input.len,
+                                OutputBuffer.ptr, OutputBuffer.len,
+                               &(Output->len));
+}
+
+
+
+#define INPUT "xyz123xyz"
+
+int32_t RunUsefulBufExample()
+{
+   /* ------------ UsefulBuf examples ------------- */
+   UsefulBufC Input = UsefulBuf_FROM_SZ_LITERAL(INPUT);
+
+   /* This macros makes a 20 byte buffer on the stack. It also makes
+    * a UsefulBuf on the stack. It sets up the UsefulBuf to point to
+    * the 20 byte buffer and sets it's length to 20 bytes. This
+    * is the empty, to-be-filled in memory for the output. It is not
+    * const. */
+   MakeUsefulBufOnStack(OutBuf, sizeof(INPUT) * 2);
+
+   /* This is were the pointer and the length of the completed output
+    * will be placed. Output.ptr is a pointer to const bytes. */
+   UsefulBufC           Output;
+
+   ExpandUB(Input, OutBuf, &Output);
+
+   ExpandUBAdapted(Input, OutBuf, &Output);
+
+
+
+   /* ------ Get Size example  -------- */
+   ExpandUB(Input, (UsefulBuf){NULL, SIZE_MAX}, &Output);
+
+   /* Size is in Output.len */
+
+
+
+   /* ---------- Traditional examples (for comparison) --------- */
+   uint8_t puBuffer[sizeof(INPUT) * 2];
+   size_t  uOutputSize;
+
+   ExpandTraditional((const uint8_t *)INPUT, sizeof(INPUT),
+                     puBuffer, sizeof(puBuffer),
+                     &uOutputSize);
+
+
+   ExpandTraditionalAdapted((const uint8_t *)INPUT, sizeof(INPUT),
+                            puBuffer, sizeof(puBuffer),
+                           &uOutputSize);
+
+   return 0;
+}
diff --git a/ub-example.h b/ub-example.h
new file mode 100644
index 0000000..6ed3626
--- /dev/null
+++ b/ub-example.h
@@ -0,0 +1,16 @@
+//
+//  ub-example.h
+//  QCBOR
+//
+//  Created by Laurence Lundblade on 4/8/22.
+//  Copyright © 2022 Laurence Lundblade. All rights reserved.
+//
+
+#ifndef ub_example_h
+#define ub_example_h
+
+#include <stdint.h>
+
+int32_t RunUsefulBufExample(void);
+
+#endif /* ub_example_h */