UsefulBuf documentation and coding style improvements
* No semantic changes
* Move all inline functions to the end
* Full spelling and grammar check
diff --git a/inc/UsefulBuf.h b/inc/UsefulBuf.h
index 682646e..80d33ac 100644
--- a/inc/UsefulBuf.h
+++ b/inc/UsefulBuf.h
@@ -1,4 +1,4 @@
-/*==============================================================================
+/*============================================================================
Copyright (c) 2016-2018, The Linux Foundation.
Copyright (c) 2018-2019, Laurence Lundblade.
@@ -27,9 +27,9 @@
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- ==============================================================================*/
+ =============================================================================*/
-/*===================================================================================
+/*============================================================================
FILE: UsefulBuf.h
DESCRIPTION: General purpose input and output buffers
@@ -39,24 +39,26 @@
This section contains comments describing changes made to the module.
Notice that changes are listed in reverse chronological order.
- when who what, where, why
- -------- ---- ---------------------------------------------------
- 3/6/2019 llundblade Add UsefulBuf_IsValue()
- 12/17/2018 llundblade Remove const from UsefulBuf and UsefulBufC .len
- 12/13/2018 llundblade Documentation improvements
- 09/18/2018 llundblade Cleaner distinction between UsefulBuf and UsefulBufC
- 02/02/18 llundbla Full support for integers in and out; fix pointer
- alignment bug. Incompatible change: integers in/out
- are now in network byte order.
- 08/12/17 llundbla Added UsefulOutBuf_AtStart and UsefulBuf_Find
- 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected comparison
- for < or > for unequal length buffers. Added
- UsefulBuf_Set() function.
- 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
- 11/13/16 llundbla Initial Version.
+ when who what, where, why
+ -------- ---- --------------------------------------------------
+ 3/23/2019 llundblade Big documentation & style update. No interface
+ change.
+ 3/6/2019 llundblade Add UsefulBuf_IsValue()
+ 12/17/2018 llundblade Remove const from UsefulBuf and UsefulBufC .len
+ 12/13/2018 llundblade Documentation improvements
+ 09/18/2018 llundblade Cleaner distinction between UsefulBuf and
+ UsefulBufC.
+ 02/02/18 llundbla Full support for integers in and out; fix pointer
+ alignment bug. Incompatible change: integers
+ in/out are now in network byte order.
+ 08/12/17 llundbla Added UsefulOutBuf_AtStart and UsefulBuf_Find
+ 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected
+ comparison for < or > for unequal length buffers.
+ Added UsefulBuf_Set() function.
+ 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
+ 11/13/16 llundbla Initial Version.
-
- =====================================================================================*/
+ =============================================================================*/
#ifndef _UsefulBuf_h
#define _UsefulBuf_h
@@ -76,79 +78,84 @@
The goal of this code is to make buffer and pointer manipulation
easier and safer when working with binary data.
- You use the UsefulBuf, UsefulOutBuf and UsefulInputBuf
- structures to represent buffers rather than ad hoc pointers and lengths.
+ The \ref UsefulBuf, \ref UsefulOutBuf and \ref UsefulInputBuf
+ structures are used to represent buffers rather than ad hoc pointers and
+ lengths.
- With these it will often be possible to write code that does little or no
- direct pointer manipulation for copying and formatting data. For example
- the QCBOR encoder was rewritten using these and has no direct pointer
- manipulation.
+ With these it will often be possible to write code that does little
+ or no direct pointer manipulation for copying and formatting
+ data. For example, the QCBOR encoder was written using these and
+ has no less pointer manipulation.
- While it is true that object code using these functions will be a little
- larger and slower than a white-knuckle clever use of pointers might be, but
- not by that much or enough to have an affect for most use cases. For
- security-oriented code this is highly worthwhile. Clarity, simplicity,
- reviewability and are more important.
+ While it is true that object code using these functions will be a
+ little larger and slower than a white-knuckle clever use of pointers
+ might be, but not by that much or enough to have an effect for most
+ use cases. For security-oriented code this is highly
+ worthwhile. Clarity, simplicity, reviewability and are more
+ important.
- There are some extra sanity and double checks in this code to help catch
- coding errors and simple memory corruption. They are helpful, but not a
- substitute for proper code review, input validation and such.
+ There are some extra sanity and double checks in this code to help
+ catch coding errors and simple memory corruption. They are helpful,
+ but not a substitute for proper code review, input validation and
+ such.
- This code consists of a lot of inline functions and a few that are not.
- It should not generate very much object code, especially with the
- optimizer turned up to -Os or -O3. The idea is that the inline
- functions are easier to review and understand and the optimizer does
- the work of making the code small.
+ This code consists of a lot of inline functions and a few that are
+ not. It should not generate very much object code, especially with
+ the optimizer turned up to \c -Os or \c -O3.
*/
-/*...... This is a ruler that is 80 characters long...........................*/
-
/**
- UsefulBufC and UsefulBuf are simple data structures to hold a pointer and
- length for a binary data. In C99 this data structure can be passed on the
- stack making a lot of code cleaner than carrying around a pointer and
- length as two parameters.
+ \ref UsefulBufC and \ref UsefulBuf are simple data structures to hold
+ a pointer and length for binary data. In C99 this data structure can
+ be passed on the stack making a lot of code cleaner than carrying
+ around a pointer and length as two parameters.
- This is also conducive to secure code practice as the lengths are
+ This is also conducive to secure coding practice as the length is
always carried with the pointer and the convention for handling a
pointer and a length is clear.
While it might be possible to write buffer and pointer code more
efficiently in some use cases, the thought is that unless there is an
- extreme need for performance (e.g., you are building a gigabit-per-second
- IP router), it is probably better to have cleaner code you can be most
- certain about the security of.
+ extreme need for performance (e.g., you are building a
+ gigabit-per-second IP router), it is probably better to have cleaner
+ code you can be most certain about the security of.
- The non-const UsefulBuf is usually used to refer a buffer to be filled in.
- The length is the size of the buffer.
+ The non-const \ref UsefulBuf is usually used to refer a buffer to be
+ filled in. The length is the size of the buffer.
- The const UsefulBufC is usually used to refer to some data that has been
- filled in. The length is amount of valid data pointed to.
+ The const \ref UsefulBufC is usually used to refer to some data that
+ has been filled in. The length is amount of valid data pointed to.
- A common use is to pass a UsefulBuf to a function, the function fills it
- in, the function returns a UsefulBufC. The pointer is the same in both.
+ A common use is to pass a \ref UsefulBuf to a function, the function
+ fills it in, the function returns a \ref UsefulBufC. The pointer is
+ the same in both.
- A UsefulBuf is NULL, it has no value, when the ptr in it is NULL.
+ A \ref UsefulBuf is null, it has no value, when \c ptr in it is \c NULL.
There are utility functions for the following:
- - Checking for UsefulBufs that are NULL, empty or both
+ - Initializing
+ - Create initialized const \ref UsefulBufC from compiler literals
+ - Create initialized const \ref UsefulBufC from NULL-terminated string
+ - Make an empty \ref UsefulBuf on the stack
+ - Checking whether a \ref UsefulBuf is null, empty or both
- Copying, copying with offset, copying head or tail
- Comparing and finding substrings
- - Initializating
- - Create initialized const UsefulBufC from compiler literals
- - Create initialized const UsefulBufC from NULL-terminated string
- - Make an empty UsefulBuf on the stack
- See also UsefulOutBuf. It is a richer structure that has both the size of
- the valid data and the size of the buffer.
+ See also \ref UsefulOutBuf. It is a richer structure that has both
+ the size of the valid data and the size of the buffer.
- UsefulBuf is only 16 or 8 bytes on a 64- or 32-bit machine so it can go
- on the stack and be a function parameter or return value.
+ \ref UsefulBuf is only 16 or 8 bytes on a 64- or 32-bit machine so it
+ can go on the stack and be a function parameter or return value.
- UsefulBuf is kind of like the Useful Pot Pooh gave Eeyore on his birthday.
- Eeyore's balloon fits beautifully, "it goes in and out like anything".
+ Another way to look at it is this. C has the NULL-terminated string
+ as a means for handling text strings, but no means or convention for
+ binary strings. Other languages do have such means, Rust, an
+ efficient compiled language, for example.
+ \ref UsefulBuf is kind of like the Useful Pot Pooh gave Eeyore on his
+ birthday. Eeyore's balloon fits beautifully, "it goes in and out
+ like anything".
*/
typedef struct q_useful_buf_c {
const void *ptr;
@@ -157,8 +164,8 @@
/**
- The non-const UsefulBuf typically used for some allocated memory
- that is to be filled in. The len is the amount of memory,
+ This non-const \ref UsefulBuf is typically used for some allocated
+ memory that is to be filled in. The \c len is the amount of memory,
not the length of the valid data in the buffer.
*/
typedef struct q_useful_buf {
@@ -168,156 +175,137 @@
/**
- A "NULL" UsefulBufC is one that has no value in the same way a NULL pointer has no value.
- A UsefulBuf is NULL when the ptr field is NULL. It doesn't matter what len is.
- See UsefulBuf_IsEmpty() for the distinction between NULL and empty.
+ A null \ref UsefulBufC is one that has no value in the same way a \c
+ NULL pointer has no value. A \ref UsefulBufC is \c NULL when 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})
-/** A NULL UsefulBuf is one that has no memory associated the say way
- NULL points to nothing. It does not matter what len is.
+
+/**
+ 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})
/**
- @brief Check if a UsefulBuf is NULL or not
+ @brief Check if a \ref UsefulBuf is \ref NULLUsefulBuf or not.
- @param[in] UB The UsefulBuf to check
+ @param[in] UB The UsefulBuf to check.
- @return 1 if it is NULL, 0 if not.
+ @return 1 if it is \ref NULLUsefulBuf, 0 if not.
*/
-static inline int UsefulBuf_IsNULL(UsefulBuf UB) {
- return !UB.ptr;
-}
+static inline int UsefulBuf_IsNULL(UsefulBuf UB);
/**
- @brief Check if a UsefulBufC is NULL or not
+ @brief Check if a \ref UsefulBufC is \ref NULLUsefulBufC or not.
- @param[in] UB The UsefulBufC to check
+ @param[in] UB The \ref UsefulBufC to check.
- @return 1 if it is NULL, 0 if not.
+ @return 1 if it is \c NULLUsefulBufC, 0 if not.
*/
-static inline int UsefulBuf_IsNULLC(UsefulBufC UB) {
- return !UB.ptr;
-}
+static inline int UsefulBuf_IsNULLC(UsefulBufC UB);
/**
- @brief Check if a UsefulBuf is empty or not
+ @brief Check if a \ref UsefulBuf is empty or not.
- @param[in] UB The UsefulBuf to check
+ @param[in] UB The \ref UsefulBuf to check.
@return 1 if it is empty, 0 if not.
- An "Empty" UsefulBuf is one that has a value and can be considered to be set,
- but that value is of zero length. It is empty when len is zero. It
- doesn't matter what the ptr is.
+ An "empty" \ref UsefulBuf is one that has a value and can be
+ considered to be set, but that value is of zero length. It is empty
+ when \c len is zero. It doesn't matter what the \c ptr is.
- A lot of uses will not need to clearly distinguish a NULL UsefulBuf
- from an empty one and can have the ptr NULL and the len 0. However
- if a use of UsefulBuf needs to make a distinction then ptr should
- not be NULL when the UsefulBuf is considered empty, but not NULL.
-
+ A lot of uses will not need to clearly distinguish a \c NULL \ref
+ UsefulBuf from an empty one and can have the \c ptr \c NULL and the
+ \c len 0. However if a use of \ref UsefulBuf needs to make a
+ distinction then \c ptr should not be \c NULL when the \ref UsefulBuf
+ is considered empty, but not \c NULL.
*/
-static inline int UsefulBuf_IsEmpty(UsefulBuf UB) {
- return !UB.len;
-}
+static inline int UsefulBuf_IsEmpty(UsefulBuf UB);
/**
- @brief Check if a UsefulBufC is empty or not
+ @brief Check if a \ref UsefulBufC is empty or not.
- @param[in] UB The UsefulBufC to check
+ @param[in] UB The \ref UsefulBufC to check.
@return 1 if it is empty, 0 if not.
*/
-static inline int UsefulBuf_IsEmptyC(UsefulBufC UB) {
- return !UB.len;
-}
+static inline int UsefulBuf_IsEmptyC(UsefulBufC UB);
/**
- @brief Check if a UsefulBuf is NULL or empty
+ @brief Check if a \ref UsefulBuf is \ref NULLUsefulBuf or empty.
- @param[in] UB The UsefulBuf to check
+ @param[in] UB The \ref UsefulBuf to check.
- @return 1 if it is either NULL or empty, 0 if not.
+ @return 1 if it is either \ref NULLUsefulBuf or empty, 0 if not.
*/
-static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB) {
- return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB);
-}
+static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB);
/**
- @brief Check if a UsefulBufC is NULL or empty
+ @brief Check if a \ref UsefulBufC is \ref NULLUsefulBufC or empty.
- @param[in] UB The UsefulBufC to check
+ @param[in] UB The \ref UsefulBufC to check.
- @return 1 if it is either NULL or empty, 0 if not.
+ @return 1 if it is either \ref NULLUsefulBufC or empty, 0 if not.
*/
-static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB) {
- return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB);
-}
+static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB);
/**
- @brief Convert a non const UsefulBuf to a const UsefulBufC
+ @brief Convert a non-const \ref UsefulBuf to a const \ref UsefulBufC.
- @param[in] UB The UsefulBuf to convert
+ @param[in] UB The \ref UsefulBuf to convert.
- Returns: a UsefulBufC struct
+ @return A \ref UsefulBufC struct.
*/
-
-static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB)
-{
- return (UsefulBufC){UB.ptr, UB.len};
-}
+static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB);
/**
- @brief Convert a const UsefulBufC to a non-const UsefulBuf
+ @brief Convert a const \ref UsefulBufC to a non-const \ref UsefulBuf.
- @param[in] UBC The UsefulBuf to convert
+ @param[in] UBC The \ref UsefulBuf to convert.
- Returns: a non const UsefulBuf struct
+ @return A non-const \ref UsefulBuf struct.
*/
-static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
-{
- return (UsefulBuf){(void *)UBC.ptr, UBC.len};
-}
+static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC);
/**
- Convert a literal string to a UsefulBufC.
+ Convert a literal string to a \ref UsefulBufC.
- szString must be a literal string that you can take sizeof.
- This is better for literal strings than UsefulBuf_FromSZ()
- because it generates less code. It will not work on
- non-literal strings.
+ \c szString must be a literal string that \c sizeof() works on. This
+ is better for literal strings than UsefulBuf_FromSZ() because it
+ generates less code. It will not work on non-literal strings.
The terminating \0 (NULL) is NOT included in the length!
-
*/
#define UsefulBuf_FROM_SZ_LITERAL(szString) \
((UsefulBufC) {(szString), sizeof(szString)-1})
/**
- Convert a literal byte array to a UsefulBufC.
+ Convert a literal byte array to a \ref UsefulBufC.
- pBytes must be a literal string that you can take sizeof.
- It will not work on non-literal arrays.
-
+ \c pBytes must be a literal string that \c sizeof() works on. It
+ will not work on non-literal arrays.
*/
#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \
((UsefulBufC) {(pBytes), sizeof(pBytes)})
/**
- Make an automatic variable with name of type UsefulBuf and point it to a stack
- variable of the give size
+ Make an automatic variable named \c name of type \ref UsefulBuf and
+ point it to a stack variable of the given \c size.
*/
#define UsefulBuf_MAKE_STACK_UB(name, size) \
uint8_t __pBuf##name[(size)];\
@@ -325,83 +313,1142 @@
/**
- Make a byte array in to a UsefulBuf
+ Make a byte array in to a \ref UsefulBuf. This is usually used on
+ stack variables or static variables. Also see \ref
+ UsefulBuf_MAKE_STACK_UB.
*/
#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \
((UsefulBuf) {(pBytes), sizeof(pBytes)})
+
/**
- @brief Convert a NULL terminated string to a UsefulBufC.
+ @brief Convert a NULL-terminated string to a \ref UsefulBufC.
- @param[in] szString The string to convert
+ @param[in] szString The string to convert.
- @return a UsefulBufC struct
+ @return A \ref UsefulBufC struct.
- UsefulBufC.ptr points to the string so it's lifetime
- must be maintained.
+ \c UsefulBufC.ptr points to the string so its lifetime must be
+ maintained.
- The terminating \0 (NULL) is NOT included in the length!
-
+ The terminating \0 (NULL) is NOT included in the length.
*/
-static inline UsefulBufC UsefulBuf_FromSZ(const char *szString){
- return ((UsefulBufC) {szString, strlen(szString)});
-}
+static inline UsefulBufC UsefulBuf_FromSZ(const char *szString);
/**
- @brief Copy one UsefulBuf into another at an offset
+ @brief Copy one \ref UsefulBuf into another at an offset.
- @param[in] Dest Destiation buffer to copy into
- @param[in] uOffset The byte offset in Dest at which to copy to
- @param[in] Src The bytes to copy
+ @param[in] Dest Destination buffer to copy into.
+ @param[in] uOffset The byte offset in \c Dest at which to copy to.
+ @param[in] Src The bytes to copy.
- @return Pointer and length of the copy
+ @return Pointer and length of the copy or \ref NULLUsefulBufC.
- This fails and returns NULLUsefulBufC Src.len + uOffset > Dest.len.
+ This fails and returns \ref NULLUsefulBufC if \c offset is beyond the
+ size of \c Dest.
- Like memcpy, there is no check for NULL. If NULL is passed
- this will crash.
+ This fails and returns \ref NULLUsefulBufC if the \c Src length plus
+ \c uOffset is greater than the length of \c Dest.
- There is an assumption that there is valid data in Dest up to
- uOffset as the resulting UsefulBufC returned starts
- at the beginning of Dest and goes to Src.len + uOffset.
+ The results are undefined if \c Dest and \c Src overlap.
+ This assumes that there is valid data in \c Dest up to \c
+ uOffset. The \ref UsefulBufC returned starts at the beginning of \c
+ Dest and goes to \c Src.len \c + \c uOffset.
*/
UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src);
/**
- @brief Copy one UsefulBuf into another
+ @brief Copy one \ref UsefulBuf into another.
- @param[in] Dest The destination buffer to copy into
- @param[out] Src The source to copy from
+ @param[in] Dest The destination buffer to copy into.
+ @param[out] Src The source to copy from.
- @return filled in UsefulBufC on success, NULLUsefulBufC on failure
+ @return Filled in \ref UsefulBufC on success, \ref NULLUsefulBufC
+ on failure.
- This fails if Src.len is greater than Dest.len.
+ This fails if \c Src.len is greater than \c Dest.len.
- Note that like memcpy, the pointers are not checked and
- this will crash, rather than return NULLUsefulBufC if
- they are NULL or invalid.
+ Note that like \c memcpy(), the pointers are not checked and this
+ will crash rather than return \ref NULLUsefulBufC if they are \c
+ NULL or invalid.
- Results are undefined if Dest and Src overlap.
-
+ The results are undefined if \c Dest and \c Src overlap.
*/
-static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src) {
+static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src);
+
+
+/**
+ @brief Set all bytes in a \ref UsefulBuf to a value, for example to 0.
+
+ @param[in] pDest The destination buffer to copy into.
+ @param[in] value The value to set the bytes to.
+
+ Note that like \c memset(), the pointer in \c pDest is not checked
+ and this will crash if \c NULL or invalid.
+ */
+static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value);
+
+
+/**
+ @brief Copy a pointer into a \ref UsefulBuf.
+
+ @param[in,out] Dest The destination buffer to copy into.
+ @param[in] ptr The source to copy from.
+ @param[in] uLen Length of the source; amount to copy.
+
+ @return 0 on success, 1 on failure.
+
+ This fails and returns \ref NULLUsefulBufC if \c uLen is greater than
+ \c pDest->len.
+
+ Note that like \c memcpy(), the pointers are not checked and this
+ will crash, rather than return 1 if they are \c NULL or invalid.
+ */
+static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest,
+ const void *ptr,
+ size_t uLen);
+
+
+/**
+ @brief Returns a truncation of a \ref UsefulBufC.
+
+ @param[in] UB The buffer to get the head of.
+ @param[in] uAmount The number of bytes in the head.
+
+ @return A \ref UsefulBufC that is the head of UB.
+ */
+static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount);
+
+
+/**
+ @brief Returns bytes from the end of a \ref UsefulBufC.
+
+ @param[in] UB The buffer to get the tail of.
+ @param[in] uAmount The offset from the start where the tail is to begin.
+
+ @return A \ref UsefulBufC that is the tail of \c UB or \ref NULLUsefulBufC
+ if \c uAmount is greater than the length of the \ref UsefulBufC.
+
+ If \c UB.ptr is \c NULL, but \c UB.len is not zero, then the result will
+ be a \ref UsefulBufC with a \c NULL \c ptr and \c len with the length
+ of the tail.
+ */
+static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount);
+
+
+/**
+ @brief Compare one \ref UsefulBufC to another.
+
+ @param[in] UB1 The first buffer to compare.
+ @param[in] UB2 The second buffer to compare.
+
+ @return 0, positive or negative value.
+
+ Returns a negative value if \c UB1 if is less than \c UB2. \c UB1 is
+ less than \c UB2 if it is shorter or the first byte that is not the
+ same is less.
+
+ Returns 0 if the inputs are the same.
+
+ Returns a positive value if \c UB2 is less than \c UB1.
+
+ All that is of significance is that the result is positive, negative
+ or 0. (This doesn't return the difference between the first
+ non-matching byte like \c memcmp() ).
+ */
+int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2);
+
+
+/**
+ @brief Find first byte that is not a particular byte value.
+
+ @param[in] UB The destination buffer for byte comparison.
+ @param[in] uValue The byte value to compare to.
+
+ @return Offset of first byte that isn't \c uValue or
+ \c SIZE_MAX if all bytes are \c uValue.
+
+ Note that unlike most comparison functions, 0
+ does not indicate a successful comparison, so the
+ test for match is:
+
+ UsefulBuf_IsValue(...) == SIZE_MAX
+
+ If \c UB is null or empty, there is no match
+ and 0 is returned.
+ */
+size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue);
+
+
+/**
+ @brief Find one \ref UsefulBufC in another.
+
+ @param[in] BytesToSearch Buffer to search through.
+ @param[in] BytesToFind Buffer with bytes to be found.
+
+ @return Position of found bytes or \c SIZE_MAX if not found.
+ */
+size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
+
+
+#if 1 // NOT_DEPRECATED
+/** Deprecated macro; use \ref UsefulBuf_FROM_SZ_LITERAL instead */
+#define SZLiteralToUsefulBufC(szString) \
+ ((UsefulBufC) {(szString), sizeof(szString)-1})
+
+/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
+#define MakeUsefulBufOnStack(name, size) \
+ uint8_t __pBuf##name[(size)];\
+ UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
+
+/** Deprecated macro; use \ref UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
+#define ByteArrayLiteralToUsefulBufC(pBytes) \
+ ((UsefulBufC) {(pBytes), sizeof(pBytes)})
+
+/** Deprecated function; use UsefulBuf_Unconst() instead */
+static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
+{
+ return (UsefulBuf){(void *)UBC.ptr, UBC.len};
+}
+#endif
+
+
+
+
+/**
+ @brief Copy a \c float to a \c uint32_t.
+
+ @param[in] f Float value to copy.
+
+ @return A \c uint32_t with the float bits.
+
+ Convenience function to avoid type punning, compiler warnings and
+ such. The optimizer usually reduces this to a simple assignment. This
+ is a crusty corner of C.
+ */
+static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f);
+
+
+/**
+ @brief Copy a \c double to a \c uint64_t.
+
+ @param[in] d Double value to copy.
+
+ @return A \c uint64_t with the double bits.
+
+ Convenience function to avoid type punning, compiler warnings and
+ such. The optimizer usually reduces this to a simple assignment. This
+ is a crusty corner of C.
+ */
+static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d);
+
+
+/**
+ @brief Copy a \c uint32_t to a \c float.
+
+ @param[in] u32 Integer value to copy.
+
+ @return The value as a \c float.
+
+ Convenience function to avoid type punning, compiler warnings and
+ such. The optimizer usually reduces this to a simple assignment. This
+ is a crusty corner of C.
+ */
+static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32);
+
+
+/**
+ @brief Copy a \c uint64_t to a \c double.
+
+ @param[in] u64 Integer value to copy.
+
+ @return The value as a \c double.
+
+ Convenience function to avoid type punning, compiler warnings and
+ such. The optimizer usually reduces this to a simple assignment. This
+ is a crusty corner of C.
+ */
+static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64);
+
+
+
+
+/**
+ UsefulOutBuf is a structure and functions (an object) for serializing
+ data into a buffer when encoding a network protocol or writing data
+ to file.
+
+ The main idea is that all the pointer manipulation is performed by
+ \ref UsefulOutBuf functions so the caller doesn't have to do any
+ pointer manipulation. The pointer manipulation is centralized. This
+ code will have been reviewed and written carefully so it spares the
+ caller of much of this work and results in safer code with less work.
+
+ The \ref UsefulOutBuf methods that add data to the output buffer
+ always check the length and will never write off the end of the
+ output buffer. If an attempt to add data that will not fit is made,
+ an internal error flag will be set and further attempts to add data
+ will not do anything.
+
+ There is no way to ever write off the end of that buffer when calling
+ the \c UsefulOutBuf_AddXxx() and \c UsefulOutBuf_InsertXxx()
+ functions.
+
+ The functions to add data do not return an error. The working model
+ is that all calls to add data are made without an error check. Errors
+ are just checked for once after all the data has been added before the
+ and before serialized data is to be used. This makes the calling code
+ cleaner.
+
+ There is a utility function to get the error status anytime along the
+ way for a special circumstance. There are functions to see how much
+ room is left and see if some data will fit too, but their use is
+ generally not necessary.
+
+ The general call flow is:
+
+ - Initialize by calling \ref UsefulOutBuf_Init(). The output
+ buffer given to it can be from the heap, stack or
+ otherwise. \ref UsefulOutBuf_MakeOnStack is a convenience macro
+ that makes a buffer on the stack and initializes it.
+
+ - Call methods like UsefulOutBuf_InsertString(),
+ UsefulOutBuf_AppendUint32() and UsefulOutBuf_InsertUsefulBuf()
+ to output data. The append calls add data to the end of the
+ valid data. The insert calls take a position argument.
+
+ - Call UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to see
+ there were no errors and to get the serialized output bytes.
+
+ \ref UsefulOutBuf can be used in a size calculation mode to calculate
+ the size of output that would be generated. This is useful to
+ calculate the size of a buffer that is to be allocated to hold the
+ output. To use \ref UsefulOutBuf in this mode, call
+ UsefulOutBuf_Init() with the \c Storage \ref UsefulBuf as
+ \c (UsefulBuf){NULL,MAX_UINT32}. Then call all the Insert and Add
+ functions. No attempt will made to actually copy data, so only the
+ lengths have to be valid for these calls.
+
+ Methods like UsefulOutBuf_InsertUint64() always output in network
+ bytes order (big endian).
+
+ The possible errors are:
+ - The \ref UsefulOutBuf was not initialized or was corrupted.
+
+ - An attempt was made to add data that will not fit.
+
+ - An attempt was made to insert data at a position beyond the end of
+ the buffer.
+
+ - An attempt was made to insert data at a position beyond the valid
+ data in the buffer.
+
+ Some inexpensive simple sanity checks are performed before every data
+ addition to guard against use of an uninitialized or corrupted
+ UsefulOutBuf.
+
+ This has been used to create a CBOR encoder. The CBOR encoder has
+ almost no pointer manipulation in it, is easier to read, and easier
+ to review.
+
+ A \ref UsefulOutBuf is small and can go on the stack:
+ - 32 bytes (27 bytes plus alignment padding) on a 64-bit machine
+ - 16 bytes (15 bytes plus alignment padding) on a 32-bit machines
+ */
+typedef struct useful_out_buf {
+ // PRIVATE DATA STRUCTURE
+ UsefulBuf UB; // Memory that is being output to
+ size_t data_len; // length of the data
+ uint16_t magic; // Used to detect corruption and lack of initialization
+ uint8_t err;
+} UsefulOutBuf;
+
+
+/**
+ @brief Initialize and supply the actual output buffer.
+
+ @param[out] pUOutBuf The \ref UsefulOutBuf to initialize.
+ @param[in] Storage Buffer to output into.
+
+ Initializes the \ref UsefulOutBuf with storage. Sets the current
+ position to the beginning of the buffer clears the error.
+
+ This must be called before the \ref UsefulOutBuf is used.
+ */
+void UsefulOutBuf_Init(UsefulOutBuf *pUOutBuf, UsefulBuf Storage);
+
+
+/**
+ Convenience macro to make a \ref UsefulOutBuf on the stack and
+ initialize it with a stack buffer of the given size. The variable
+ will be named \c name.
+ */
+#define UsefulOutBuf_MakeOnStack(name, size) \
+ uint8_t __pBuf##name[(size)];\
+ UsefulOutBuf name;\
+ UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)});
+
+
+/**
+ @brief Reset a \ref UsefulOutBuf for re use
+
+ @param[in] pUOutBuf Pointer to the \ref UsefulOutBuf
+
+ This sets the amount of data in the output buffer to none and clears
+ the error state.
+
+ The output buffer is still the same one and size as from the
+ UsefulOutBuf_Init() call.
+
+ This doesn't zero the data, just resets to 0 bytes of valid data.
+ */
+static inline void UsefulOutBuf_Reset(UsefulOutBuf *pUOutBuf);
+
+
+/**
+ @brief Returns position of end of data in the \ref UsefulOutBuf.
+
+ @param[in] pUOutBuf Pointer to the \ref UsefulOutBuf.
+
+ @return position of end of data.
+
+ On a freshly initialized \ref UsefulOutBuf with no data added, this
+ will return 0. After 10 bytes have been added, it will return 10 and
+ so on.
+
+ Generally callers will not need this function for most uses of \ref
+ UsefulOutBuf.
+ */
+static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pUOutBuf);
+
+
+/**
+ @brief Returns whether any data has been added to the \ref UsefulOutBuf.
+
+ @param[in] pUOutBuf Pointer to the \ref UsefulOutBuf.
+
+ @return 1 if output position is at start.
+ */
+static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pUOutBuf);
+
+
+/**
+ @brief Inserts bytes into the \ref UsefulOutBuf.
+
+ @param[in] pUOutBuf Pointer to the \ref UsefulOutBuf.
+ @param[in] NewData The bytes to insert.
+ @param[in] uPos Index in output buffer at which to insert.
+
+ \c NewData is the pointer and length for the bytes to be added to the
+ output buffer. There must be room in the output buffer for all of \c
+ NewData or an error will occur.
+
+ The insertion point must be between 0 and the current valid data. If
+ not, an error will occur. Appending data to the output buffer is
+ achieved by inserting at the end of the valid data. This can be
+ retrieved by calling UsefulOutBuf_GetEndPosition().
+
+ When insertion is performed, the bytes between the insertion point
+ and the end of data previously added to the output buffer are slid to
+ the right to make room for the new data.
+
+ Overlapping buffers are OK. \c NewData can point to data in the
+ output buffer.
+
+ If an error occurs an error state is set in the \ref UsefulOutBuf. No
+ error is returned. All subsequent attempts to add data will do
+ nothing.
+
+ The intended use is that all additions are made without checking for
+ an error. The error will be taken into account when
+ UsefulOutBuf_OutUBuf() returns \c NullUsefulBufC.
+ UsefulOutBuf_GetError() can also be called to check for an error.
+ */
+void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pUOutBuf,
+ UsefulBufC NewData,
+ size_t uPos);
+
+
+/**
+ @brief Insert a data buffer into the \ref UsefulOutBuf.
+
+ @param[in] pUOutBuf Pointer to the \ref UsefulOutBuf.
+ @param[in] pBytes Pointer to the bytes to insert
+ @param[in] uLen Length of the bytes to insert
+ @param[in] uPos Index in output buffer at which to insert
+
+ See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
+ the difference being a pointer and length is passed in rather than an
+ \ref UsefulBufC.
+ */
+static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pUOutBuf,
+ const void *pBytes,
+ size_t uLen,
+ size_t uPos);
+
+
+/**
+ @brief Insert a NULL-terminated string into the UsefulOutBuf.
+
+ @param[in] pUOutBuf Pointer to the \ref UsefulOutBuf.
+ @param[in] szString NULL-terminated string to insert.
+ @param[in] uPos Index in output buffer at which to insert.
+ */
+static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pUOutBuf,
+ const char *szString,
+ size_t uPos);
+
+
+/**
+ @brief Insert a byte into the \ref UsefulOutBuf.
+
+ @param[in] pUOutBuf Pointer to the UsefulOutBuf.
+ @param[in] byte Bytes to insert.
+ @param[in] uPos Index in output buffer at which to insert.
+
+ See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
+ the difference being a single byte is to be inserted.
+ */
+static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *pUOutBuf,
+ uint8_t byte,
+ size_t uPos);
+
+
+/**
+ @brief Insert a 16-bit integer into the \ref UsefulOutBuf.
+
+ @param[in] pUOutBuf Pointer to the \ref UsefulOutBuf.
+ @param[in] uInteger16 Integer to insert.
+ @param[in] uPos Index in output buffer at which to insert.
+
+ See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
+ the difference being a two-byte integer is to be inserted.
+
+ The integer will be inserted in network byte order (big endian).
+ */
+static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *pUOutBuf,
+ uint16_t uInteger16,
+ size_t uPos);
+
+
+/**
+ @brief Insert a 32-bit integer into the \ref UsefulOutBuf.
+
+ @param[in] pUOutBuf Pointer to the \ref UsefulOutBuf.
+ @param[in] uInteger32 Integer to insert.
+ @param[in] uPos Index in output buffer at which to insert.
+
+ See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
+ the difference being a four-byte integer is to be inserted.
+
+ The integer will be inserted in network byte order (big endian).
+ */
+static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pUOutBuf,
+ uint32_t uInteger32,
+ size_t uPos);
+
+
+/**
+ @brief Insert a 64-bit integer into the \ref UsefulOutBuf.
+
+ @param[in] pUOutBuf Pointer to the \ref UsefulOutBuf.
+ @param[in] uInteger64 Integer to insert.
+ @param[in] uPos Index in output buffer at which to insert.
+
+ See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
+ the difference being an eight-byte integer is to be inserted.
+
+ The integer will be inserted in network byte order (big endian).
+ */
+static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pUOutBuf,
+ uint64_t uInteger64,
+ size_t uPos);
+
+
+/**
+ @brief Insert a \c float into the \ref UsefulOutBuf.
+
+ @param[in] pUOutBuf Pointer to the \ref UsefulOutBuf.
+ @param[in] f \c float to insert.
+ @param[in] uPos Index in output buffer at which to insert.
+
+ See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
+ the difference being a \c float is to be inserted.
+
+ The \c float will be inserted in network byte order (big endian).
+ */
+static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pUOutBuf,
+ float f,
+ size_t uPos);
+
+
+/**
+ @brief Insert a \c double into the \ref UsefulOutBuf.
+
+ @param[in] pUOutBuf Pointer to the \ref UsefulOutBuf.
+ @param[in] d \c double to insert.
+ @param[in] uPos Index in output buffer at which to insert.
+
+ See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
+ the difference being a \c double is to be inserted.
+
+ The \c double will be inserted in network byte order (big endian).
+ */
+static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pUOutBuf,
+ double d,
+ size_t uPos);
+
+
+/**
+ @brief Append a \ref UsefulBuf into the \ref UsefulOutBuf.
+
+ @param[in] pUOutBuf Pointer to the \ref UsefulOutBuf.
+ @param[in] NewData The \ref UsefulBuf with the bytes to append.
+
+ See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
+ with the insertion point at the end of the valid data.
+*/
+static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pUOutBuf,
+ UsefulBufC NewData);
+
+
+/**
+ @brief Append bytes to the \ref UsefulOutBuf.
+
+ @param[in] pUOutBuf Pointer to the \ref UsefulOutBuf.
+ @param[in] pBytes Pointer to bytes to append.
+ @param[in] uLen Length of \c pBytes to append.
+
+ See UsefulOutBuf_InsertData() for details. This does the same
+ with the insertion point at the end of the valid data.
+ */
+static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pUOutBuf,
+ const void *pBytes,
+ size_t uLen);
+
+
+/**
+ @brief Append a NULL-terminated string to the \ref UsefulOutBuf
+
+ @param[in] pUOutBuf Pointer to the \ref UsefulOutBuf.
+ @param[in] szString NULL-terminated string to append.
+ */
+static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pUOutBuf,
+ const char *szString);
+
+
+/**
+ @brief Append a byte to the \ref UsefulOutBuf
+
+ @param[in] pUOutBuf Pointer to the \ref UsefulOutBuf.
+ @param[in] byte Bytes to append.
+
+ See UsefulOutBuf_InsertByte() for details. This does the same
+ with the insertion point at the end of the valid data.
+ */
+static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pUOutBuf,
+ uint8_t byte);
+
+
+/**
+ @brief Append an integer to the \ref UsefulOutBuf
+
+ @param[in] pUOutBuf Pointer to the \ref UsefulOutBuf.
+ @param[in] uInteger16 Integer to append.
+
+ See UsefulOutBuf_InsertUint16() for details. This does the same
+ with the insertion point at the end of the valid data.
+
+ The integer will be appended in network byte order (big endian).
+ */
+static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pUOutBuf,
+ uint16_t uInteger16);
+
+
+/**
+ @brief Append an integer to the \ref UsefulOutBuf
+
+ @param[in] pUOutBuf Pointer to the \ref UsefulOutBuf.
+ @param[in] uInteger32 Integer to append.
+
+ See UsefulOutBuf_InsertUint32() for details. This does the same
+ with the insertion point at the end of the valid data.
+
+ The integer will be appended in network byte order (big endian).
+ */
+static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pUOutBuf,
+ uint32_t uInteger32);
+
+
+/**
+ @brief Append an integer to the \ref UsefulOutBuf
+
+ @param[in] pUOutBuf Pointer to the \ref UsefulOutBuf.
+ @param[in] uInteger64 Integer to append.
+
+ See UsefulOutBuf_InsertUint64() for details. This does the same
+ with the insertion point at the end of the valid data.
+
+ The integer will be appended in network byte order (big endian).
+ */
+static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pUOutBuf,
+ uint64_t uInteger64);
+
+
+/**
+ @brief Append a \c float to the \ref UsefulOutBuf
+
+ @param[in] pUOutBuf Pointer to the \ref UsefulOutBuf.
+ @param[in] f \c float to append.
+
+ See UsefulOutBuf_InsertFloat() for details. This does the same
+ with the insertion point at the end of the valid data.
+
+ The float will be appended in network byte order (big endian).
+ */
+static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pUOutBuf,
+ float f);
+
+
+/**
+ @brief Append a \c double to the \ref UsefulOutBuf
+
+ @param[in] pUOutBuf Pointer to the \ref UsefulOutBuf.
+ @param[in] d \c double to append.
+
+ See UsefulOutBuf_InsertDouble() for details. This does the same
+ with the insertion point at the end of the valid data.
+
+ The double will be appended in network byte order (big endian).
+ */
+static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pUOutBuf,
+ double d);
+
+
+/**
+ @brief Returns the current error status.
+
+ @param[in] pUOutBuf Pointer to the \ref UsefulOutBuf.
+
+ @return 0 if all OK, 1 on error.
+
+ This is the error status since the call to either
+ UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once it goes into error
+ state it will stay until one of those functions is called.
+
+ Possible error conditions are:
+ - bytes to be inserted will not fit
+ - insertion point is out of buffer or past valid data
+ - current position is off end of buffer (probably corrupted or uninitialized)
+ - detect corruption / uninitialized by bad magic number
+ */
+static inline int UsefulOutBuf_GetError(UsefulOutBuf *pUOutBuf);
+
+
+/**
+ @brief Returns number of bytes unused used in the output buffer.
+
+ @param[in] pUOutBuf Pointer to the \ref UsefulOutBuf.
+
+ @return Number of unused bytes or zero.
+
+ Because of the error handling strategy and checks in
+ UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
+ this.
+ */
+static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pUOutBuf);
+
+
+/**
+ @brief Returns 1 if some number of bytes will fit in the \ref UsefulOutBuf.
+
+ @param[in] pUOutBuf Pointer to the \ref UsefulOutBuf
+ @param[in] uLen Number of bytes for which to check
+
+ @return 1 if \c uLen bytes will fit, 0 if not.
+
+ Because of the error handling strategy and checks in
+ UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
+ this.
+ */
+static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pUOutBuf, size_t uLen);
+
+
+/**
+ @brief Returns the resulting valid data in a UsefulOutBuf
+
+ @param[in] pUOutBuf Pointer to the \ref UsefulOutBuf.
+
+ @return The valid data in \ref UsefulOutBuf or
+ \ref NULLUsefulBufC if there was an error adding data.
+
+ The storage for the returned data is the \c Storage parameter passed
+ to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut().
+
+ This can be called anytime and many times to get intermediate
+ results. It doesn't change the data or reset the current position
+ so you can keep adding data.
+ */
+UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pUOutBuf);
+
+
+/**
+ @brief Copies the valid data into a supplied buffer
+
+ @param[in] pUOutBuf Pointer to the \ref UsefulOutBuf.
+ @param[out] Dest The destination buffer to copy into.
+
+ @return Pointer and length of copied data or \c NULLUsefulBufC
+ if it will not fit in the \c Dest buffer.
+
+ This is the same as UsefulOutBuf_OutUBuf() except it copies the data
+ to \c Dest.
+*/
+UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pUOutBuf, UsefulBuf Dest);
+
+
+
+
+/**
+ \ref UsefulInputBuf is the counterpart to \ref UsefulOutBuf and is
+ for parsing data read or received. Initialize it with the data from
+ the network. Then use the functions here to get data chunks of
+ various types. A position cursor is maintained internally.
+
+ As long as the functions here are used, there will never be a
+ reference off the end of the given buffer. This is true even if they
+ care called incorrectly, an attempt is made to seek of the end of the
+ buffer, etc. This makes it easier to write safe and correct code.
+ For example, the QCBOR decoder implementation is safer and easier to
+ review through its use of \ref UsefulInputBuf.
+
+ \ref UsefulInputBuf maintains an internal error state. The
+ intended use is that data chunks can be fetched without error
+ checking until the end. Once data has been requested off the end of
+ the buffer, the error state is entered. In the error state the
+ \c UsefulInputBuf_GetXxxx() functions return 0, or \c NULL or
+ \ref NULLUsefulBufC. As long as null are not dereferenced, the
+ error check can be put off until the end, simplifying the calling
+ code.
+
+ The integer and float parsing expects network byte order (big
+ endian). Network byte order is what is used by TCP/IP, CBOR and most
+ internet protocols.
+
+ Lots of inline functions are used to keep code size down. The code
+ optimizer, particularly with the \c -Os or \c -O3, also reduces code
+ size a lot. The only non-inline code is UsefulInputBuf_GetBytes()
+ which is less than 100 bytes so use of \ref UsefulInputBuf doesn't
+ add much code for all the messy hard-to-get right issues with parsing
+ in C that is solves.
+
+ The parse context size is:
+ - 64-bit machine: 16 + 8 + 2 + 1 (5 bytes padding to align) = 32 bytes
+ - 32-bit machine: 8 + 4 + 2 + 1 (1 byte padding to align) = 16 bytes
+ */
+typedef struct useful_input_buf {
+ // PRIVATE DATA STRUCTURE
+ UsefulBufC UB; // Data being parsed
+ size_t cursor; // Current offset in data being parse
+ uint16_t magic; // Check for corrupted or uninitialized UsefulInputBuf
+ uint8_t err; // Set request goes off end or magic number is bad
+} UsefulInputBuf;
+
+#define UIB_MAGIC (0xB00F)
+
+
+/**
+ @brief Initialize the UsefulInputBuf structure before use.
+
+ @param[in] pUInBuf Pointer to the UsefulInputBuf instance.
+ @param[in] UB The data to parse.
+ */
+static inline void UsefulInputBuf_Init(UsefulInputBuf *pUInBuf, UsefulBufC UB);
+
+
+/**
+ @brief Returns current position in input buffer.
+
+ @param[in] pUInBuf Pointer to the UsefulInputBuf.
+
+ @return Integer position of the cursor.
+
+ The position that the next bytes will be returned from.
+ */
+static size_t UsefulInputBuf_Tell(UsefulInputBuf *pUInBuf);
+
+
+/**
+ @brief Sets the current position in input buffer.
+
+ @param[in] pUInBuf Pointer to the UsefulInputBuf.
+ @param[in] uPos Position to set to.
+
+ If the position is off the end of the input buffer, the error state
+ is entered, and all functions will do nothing.
+
+ Seeking to a valid position in the buffer will not reset the error
+ state. Only re initialization will do that.
+ */
+static void UsefulInputBuf_Seek(UsefulInputBuf *pUInBuf, size_t uPos);
+
+
+/**
+ @brief Returns the number of bytes from the cursor to the end of the buffer,
+ the unconsumed bytes.
+
+ @param[in] pUInBuf Pointer to the UsefulInputBuf.
+
+ @return Number of bytes unconsumed or 0 on error.
+
+ This is a critical function for input length validation.
+
+ Returns 0 if the cursor it invalid or corruption of the structure is
+ detected.
+ */
+static size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pUInBuf);
+
+
+/**
+ @brief Check if there are any unconsumed bytes.
+
+ @param[in] pUInBuf Pointer to the UsefulInputBuf.
+ @param[in] uLen Number of bytes to check availability for.
+
+ @return 1 if \c uLen bytes are available after the cursor, and 0 if not.
+ */
+static int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pUInBuf, size_t uLen);
+
+
+/**
+ @brief Get pointer to bytes out of the input buffer.
+
+ @param[in] pUInBuf Pointer to the UsefulInputBuf.
+ @param[in] uNum Number of bytes to get.
+
+ @return Pointer to bytes.
+
+ This consumes \c uNum bytes from the input buffer. It returns a
+ pointer to the start of the \c uNum bytes.
+
+ If there are not \c uNum bytes in the input buffer, \c NULL will be
+ returned and an error will be set.
+
+ It advances the current position by \c uNum bytes.
+ */
+const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pUInBuf, size_t uNum);
+
+
+/**
+ @brief Get \ref UsefulBuf out of the input buffer.
+
+ @param[in] pUInBuf Pointer to the UsefulInputBuf.
+ @param[in] uNum Number of bytes to get.
+
+ @return A \ref UsefulBufC with ptr and length of bytes consumed.
+
+ This consumes \c uNum bytes from the input buffer and returns the
+ pointer and length for them as a \ref UsefulBufC. The length returned
+ will always be \c uNum.
+
+ If there are not \c uNum bytes in the input buffer, \ref NULLUsefulBufC
+ will be returned and the error state is set.
+
+ It advances the current position by \c uNum bytes.
+ */
+static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pUInBuf, size_t uNum);
+
+
+/**
+ @brief Get a byte out of the input buffer.
+
+ @param[in] pUInBuf Pointer to the \ref UsefulInputBuf.
+
+ @return The byte.
+
+ This consumes 1 byte from the input buffer. It returns the byte.
+
+ If there is not 1 byte in the buffer, 0 will be returned for the byte
+ and an error set internally. You must check the error at some point
+ to know whether the 0 was the real value or just returned in error,
+ but you may not have to do that right away. Check the error state
+ with UsefulInputBuf_GetError(). You can also know you are in the
+ error state if UsefulInputBuf_GetBytes() returns \c NULL or the \c
+ ptr from UsefulInputBuf_GetUsefulBuf() is \c NULL.
+
+ It advances the current position by 1 byte.
+ */
+static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pUInBuf);
+
+
+/**
+ @brief Get a \c uint16_t out of the input buffer.
+
+ @param[in] pUInBuf Pointer to the UsefulInputBuf.
+
+ @return The \c uint16_t.
+
+ See UsefulInputBuf_GetByte(). This works the same, except it returns
+ a \c uint16_t and two bytes are consumed.
+
+ The input bytes must be in network order (big endian).
+ */
+static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pUInBuf);
+
+
+/**
+ @brief Get a uint32_t out of the input buffer.
+
+ @param[in] pUInBuf Pointer to the UsefulInputBuf.
+
+ @return The \c uint32_t.
+
+ See UsefulInputBuf_GetByte(). This works the same, except it returns
+ a \c uint32_t and four bytes are consumed.
+
+ The input bytes must be in network order (big endian).
+ */
+static uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pUInBuf);
+
+
+/**
+ @brief Get a uint64_t out of the input buffer.
+
+ @param[in] pUInBuf Pointer to the UsefulInputBuf.
+
+ @return The uint64_t.
+
+ See UsefulInputBuf_GetByte(). This works the same, except it returns
+ a \c uint64_t and eight bytes are consumed.
+
+ The input bytes must be in network order (big endian).
+ */
+static uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pUInBuf);
+
+
+/**
+ @brief Get a float out of the input buffer.
+
+ @param[in] pUInBuf Pointer to the UsefulInputBuf.
+
+ @return The float.
+
+ See UsefulInputBuf_GetByte(). This works the same, except it returns
+ a float and four bytes are consumed.
+
+ The input bytes must be in network order (big endian).
+ */
+static float UsefulInputBuf_GetFloat(UsefulInputBuf *pUInBuf);
+
+
+/**
+ @brief Get a double out of the input buffer.
+
+ @param[in] pUInBuf Pointer to the UsefulInputBuf.
+
+ @return The double.
+
+ See UsefulInputBuf_GetByte(). This works the same, except it returns
+ a double and eight bytes are consumed.
+
+ The input bytes must be in network order (big endian).
+ */
+static double UsefulInputBuf_GetDouble(UsefulInputBuf *pUInBuf);
+
+
+/**
+ @brief Get the error status.
+
+ @param[in] pUInBuf Pointer to the \ref UsefulInputBuf.
+
+ @return 0 if there is no error, 1 if there is.
+
+ The error state is entered for one of these reasons:
+ - Attempt to fetch data past the end of the buffer
+ - Attempt to seek to a position past the end of the buffer
+ - Attempt to get data from an uninitialized or corrupt instance
+ of \ref UsefulInputBuf
+
+ Once in the error state, it can only be cleared by calling
+ UsefulInputBuf_Init().
+
+ You may be able to only check the error state at the end after all
+ the UsefulInputBuf_GetXxxx() calls have been made, but if what you
+ get later depends on what you get sooner you cannot. For example,
+ if you get a length or count of following items you will have to
+ check the error.
+ */
+static int UsefulInputBuf_GetError(UsefulInputBuf *pUInBuf);
+
+
+
+
+/*----------------------------------------------------------
+ Inline implementations.
+ */
+static inline int UsefulBuf_IsNULL(UsefulBuf UB)
+{
+ return !UB.ptr;
+}
+
+
+static inline int UsefulBuf_IsNULLC(UsefulBufC UB)
+{
+ return !UB.ptr;
+}
+
+
+static inline int UsefulBuf_IsEmpty(UsefulBuf UB)
+{
+ return !UB.len;
+}
+
+
+static inline int UsefulBuf_IsEmptyC(UsefulBufC UB)
+{
+ return !UB.len;
+}
+
+
+static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB)
+{
+ return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB);
+}
+
+
+static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB)
+{
+ return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB);
+}
+
+
+static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB)
+{
+ return (UsefulBufC){UB.ptr, UB.len};
+}
+
+
+static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
+{
+ return (UsefulBuf){(void *)UBC.ptr, UBC.len};
+}
+
+
+static inline UsefulBufC UsefulBuf_FromSZ(const char *szString)
+{
+ return ((UsefulBufC) {szString, strlen(szString)});
+}
+
+
+static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
+{
return UsefulBuf_CopyOffset(Dest, 0, Src);
}
-/**
- @brief Set all bytes in a UsefulBuf to a value, for example 0
-
- @param[in] pDest The destination buffer to copy into
- @param[in] value The value to set the bytes to
-
- Note that like memset, the pointer in pDest is not checked and
- this will crash if NULL or invalid.
-
- */
static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value)
{
memset(pDest.ptr, value, pDest.len);
@@ -409,38 +1456,12 @@
}
-/**
- @brief Copy a pointer into a UsefulBuf
-
- @param[in,out] Dest The destination buffer to copy into
- @param[in] ptr The source to copy from
- @param[in] len Length of the source; amoutn to copy
-
- @return 0 on success, 1 on failure
-
- This fails and returns NULLUsefulBufC if len is greater than
- pDest->len.
-
- Note that like memcpy, the pointers are not checked and
- this will crash, rather than return 1 if they are NULL
- or invalid.
-
- */
-inline static UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
+static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
{
return UsefulBuf_Copy(Dest, (UsefulBufC){ptr, len});
}
-/**
- @brief Returns a truncation of a UsefulBufC
-
- @param[in] UB The buffer to get the head of
- @param[in] uAmount The number of bytes in the head
-
- @return A UsefulBufC that is the head of UB
-
- */
static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount)
{
if(uAmount > UB.len) {
@@ -450,19 +1471,6 @@
}
-/**
- @brief Returns bytes from the end of a UsefulBufC
-
- @param[in] UB The buffer to get the tail of
- @param[in] uAmount The offset from the start where the tail is to begin
-
- @return A UsefulBufC that is the tail of UB or NULLUsefulBufC if
- uAmount is greater than the length of the UsefulBufC
-
- If the input UsefulBufC is NULL, but the len is not, then the
- length of the tail will be calculated and returned along
- with a NULL ptr.
- */
static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount)
{
UsefulBufC ReturnValue;
@@ -479,376 +1487,88 @@
}
-/**
- @brief Compare two UsefulBufCs.
- @param[in] UB1 First UsefulBufC to compare.
- @param[in] UB2 Second UsefulBufC to compare.
-
- @return 0 if equal...
-
- Returns a negative value if UB1 if is less than UB2. UB1 is
- less than UB2 if it is shorter or the first byte that is not
- the same is less.
-
- Returns 0 if the UsefulBufs are the same.
-
- Returns a positive value if UB2 is less than UB1.
-
- All that is of significance is that the result is positive,
- negative or 0. (This doesn't return the difference between
- the first non-matching byte like memcmp).
-
- */
-int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2);
-
-
-/**
- @brief Find first byte that is not a particular byte value.
-
- @param[in] UB The destination buffer for byte comparison.
- @param[in] uValue The byte value to compare to.
-
- @return Offset of first byte that isn't \c uValue or
- SIZE_MAX if all bytes are \c uValue.
-
- Note that unlike most comparison functions, 0
- does not indicate a successful comparison, so the
- test for match is:
-
- UsefulBuf_IsValue(...) == SIZE_MAX
-
- If \c UB is NULL or empty, there is no match
- and 0 is returned.
- */
-size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue);
-
-
-/**
- @brief Find one UsefulBuf in another
-
- @param[in] BytesToSearch UsefulBuf to search through
- @param[in] BytesToFind UsefulBuf with bytes to be found
-
- @return position of found bytes or SIZE_MAX if not found.
-
- */
-size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
-
-
-
-
-#if 0 // NOT_DEPRECATED
-/** Deprecated macro; use UsefulBuf_FROM_SZ_LITERAL instead */
-#define SZLiteralToUsefulBufC(szString) \
- ((UsefulBufC) {(szString), sizeof(szString)-1})
-
-/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
-#define MakeUsefulBufOnStack(name, size) \
- uint8_t __pBuf##name[(size)];\
- UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
-
-/** Deprecated macro; use UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
-#define ByteArrayLiteralToUsefulBufC(pBytes) \
- ((UsefulBufC) {(pBytes), sizeof(pBytes)})
-
-/** Deprecated function; use UsefulBuf_Unconst() instead */
-static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
-{
- return (UsefulBuf){(void *)UBC.ptr, UBC.len};
-}
-#endif
-
-
-
-/*
- Convenient functions to avoid type punning, compiler warnings and such
- The optimizer reduces them to a simple assignment
- This is a crusty corner of C. It shouldn't be this hard.
- */
static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
{
- uint32_t u32;
- memcpy(&u32, &f, sizeof(uint32_t));
- return u32;
+ uint32_t u32;
+ memcpy(&u32, &f, sizeof(uint32_t));
+ return u32;
}
static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d)
{
- uint64_t u64;
- memcpy(&u64, &d, sizeof(uint64_t));
- return u64;
+ uint64_t u64;
+ memcpy(&u64, &d, sizeof(uint64_t));
+ return u64;
}
static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64)
{
- double d;
- memcpy(&d, &u64, sizeof(uint64_t));
- return d;
+ double d;
+ memcpy(&d, &u64, sizeof(uint64_t));
+ return d;
}
static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32)
{
- float f;
- memcpy(&f, &u32, sizeof(uint32_t));
- return f;
+ float f;
+ memcpy(&f, &u32, sizeof(uint32_t));
+ return f;
}
-
-/**
- UsefulOutBuf is a structure and functions (an object) that are good
- for serializing data into a buffer such as is often done with network
- protocols or data written to files.
-
- The main idea is that all the pointer manipulation for adding data is
- done by UsefulOutBuf functions so the caller doesn't have to do any.
- All the pointer manipulation is centralized here. This code will
- have been reviewed and written carefully so it spares the caller of
- much of this work and results in much safer code with much less work.
-
- The functions to add data to the output buffer always check the
- length and will never write off the end of the output buffer. If an
- attempt to add data that will not fit is made, an internal error flag
- will be set and further attempts to add data will not do anything.
-
- Basically, if you initialized with the correct buffer, there is no
- way to ever write off the end of that buffer when calling the Add
- and Insert functions here.
-
- The functions to add data do not return an error. The working model
- is that the caller just makes all the calls to add data without any
- error checking on each one. The error is instead checked after all the
- data is added when the result is to be used. This makes the caller's
- code cleaner.
-
- There is a utility function to get the error status anytime along the
- way if the caller wants. There are functions to see how much room is
- left and see if some data will fit too, but their use is generally
- not necessary.
-
- The general call flow is like this:
-
- - Initialize the UsefulOutBuf with the buffer that is to have the
- data added. The caller allocates the buffer. It can be heap
- or stack or shared memory (or other).
-
- - Make calls to add data to the output buffer. Insert and append
- are both supported. The append and insert calls will never write
- off the end of the buffer.
-
- - When all data is added, check the error status to make sure
- everything fit.
-
- - Get the resulting serialized data either as a UsefulBuf (a
- pointer and length) or have it copied to another buffer.
-
- UsefulOutBuf can be initialized with just a buffer length by passing
- NULL as the pointer to the output buffer. This is useful if you want
- to go through the whole serialization process to either see if it
- will fit into a given buffer or compute the size of the buffer
- needed. Pass a very large buffer size when calling Init, if you want
- just to compute the size.
-
- Some inexpensive simple sanity checks are performed before every data
- addition to guard against use of an uninitialized or corrupted
- UsefulOutBuf.
-
- This has been used to create a CBOR encoder. The CBOR encoder has
- almost no pointer manipulation in it, is much easier to read, and
- easier to review.
-
- A UsefulOutBuf is 27 bytes or 15 bytes on 64- or 32-bit machines so it
- can go on the stack or be a C99 function parameter.
- */
-
-typedef struct useful_out_buf {
- UsefulBuf UB; // Memory that is being output to
- size_t data_len; // length of the data
- uint16_t magic; // Used to detect corruption and lack of initialization
- uint8_t err;
-} UsefulOutBuf;
-
-
-/**
- @brief Initialize and supply the actual output buffer
-
- @param[out] me The UsefulOutBuf to initialize
- @param[in] Storage Buffer to output into
-
- Intializes the UsefulOutBuf with storage. Sets the current position
- to the beginning of the buffer clears the error.
-
- This must be called before the UsefulOutBuf is used.
- */
-void UsefulOutBuf_Init(UsefulOutBuf *me, UsefulBuf Storage);
-
-
-
-
-/** Convenience marco to make a UsefulOutBuf on the stack and
- initialize it with stack buffer
- */
-#define UsefulOutBuf_MakeOnStack(name, size) \
- uint8_t __pBuf##name[(size)];\
- UsefulOutBuf name;\
- UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)});
-
-
-
-/**
- @brief Reset a UsefulOutBuf for re use
-
- @param[in] me Pointer to the UsefulOutBuf
-
- This sets the amount of data in the output buffer to none and
- clears the error state.
-
- The output buffer is still the same one and size as from the
- UsefulOutBuf_Init() call.
-
- It doesn't zero the data, just resets to 0 bytes of valid data.
- */
-static inline void UsefulOutBuf_Reset(UsefulOutBuf *me)
+static inline void UsefulOutBuf_Reset(UsefulOutBuf *pMe)
{
- me->data_len = 0;
- me->err = 0;
+ pMe->data_len = 0;
+ pMe->err = 0;
}
-/**
- @brief Returns position of end of data in the UsefulOutBuf
-
- @param[in] me Pointer to the UsefulOutBuf
-
- @return position of end of data
-
- On a freshly initialized UsefulOutBuf with no data added, this will
- return 0. After ten bytes have been added, it will return 10 and so
- on.
-
- Generally callers will not need this function for most uses of
- UsefulOutBuf.
-
- */
-static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *me)
+static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pMe)
{
- return me->data_len;
+ return pMe->data_len;
}
-/**
- @brief Returns whether any data has been added to the UsefulOutBuf
-
- @param[in] me Pointer to the UsefulOutBuf
-
- @return 1 if output position is at start
-
- */
-static inline int UsefulOutBuf_AtStart(UsefulOutBuf *me)
+static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pMe)
{
- return 0 == me->data_len;
+ return 0 == pMe->data_len;
}
-/**
- @brief Inserts bytes into the UsefulOutBuf
-
- @param[in] me Pointer to the UsefulOutBuf
- @param[in] NewData UsefulBuf with the bytes to insert
- @param[in] uPos Index in output buffer at which to insert
-
- NewData is the pointer and length for the bytes to be added to the
- output buffer. There must be room in the output buffer for all of
- NewData or an error will occur.
-
- The insertion point must be between 0 and the current valid data. If
- not an error will occur. Appending data to the output buffer is
- achieved by inserting at the end of the valid data. This can be
- retrieved by calling UsefulOutBuf_GetEndPosition().
-
- When insertion is performed, the bytes between the insertion point and
- the end of data previously added to the output buffer is slid to the
- right to make room for the new data.
-
- Overlapping buffers are OK. NewData can point to data in the output
- buffer.
-
- If an error occurs an error state is set in the UsefulOutBuf. No
- error is returned. All subsequent attempts to add data will do
- nothing.
-
- Call UsefulOutBuf_GetError() to find out if there is an error. This
- is usually not needed until all additions of data are complete.
-
- */
-void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *me, UsefulBufC NewData, size_t uPos);
-
-
-/**
- @brief Insert a data buffer into the UsefulOutBuf
-
- @param[in] me Pointer to the UsefulOutBul
- @param[in] pBytes Pointer to the bytes to insert
- @param[in] uLen Length of the bytes to insert
- @param[in] uPos Index in output buffer at which to insert
-
- See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
- the difference being a pointer and length is passed in rather than an
- UsefulBuf.
-
- */
-static inline void UsefulOutBuf_InsertData(UsefulOutBuf *me, const void *pBytes, size_t uLen, size_t uPos)
+static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pMe,
+ const void *pBytes,
+ size_t uLen,
+ size_t uPos)
{
UsefulBufC Data = {pBytes, uLen};
- UsefulOutBuf_InsertUsefulBuf(me, Data, uPos);
+ UsefulOutBuf_InsertUsefulBuf(pMe, Data, uPos);
}
-/**
- @brief Insert a NULL-terminated string into the UsefulOutBuf
-
- @param[in] me Pointer to the UsefulOutBuf
- @param[in] szString string to append
-
- */
-static inline void UsefulOutBuf_InsertString(UsefulOutBuf *me, const char *szString, size_t uPos)
+static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pMe,
+ const char *szString,
+ size_t uPos)
{
- UsefulOutBuf_InsertUsefulBuf(me, (UsefulBufC){szString, strlen(szString)}, uPos);
+ UsefulOutBuf_InsertUsefulBuf(pMe,
+ (UsefulBufC){szString, strlen(szString)},
+ uPos);
}
-/**
- @brief Insert a byte into the UsefulOutBuf
-
- @param[in] me Pointer to the UsefulOutBul
- @param[in] byte Bytes to insert
- @param[in] uPos Index in output buffer at which to insert
-
- See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
- the difference being a single byte is to be inserted.
- */
-static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me, uint8_t byte, size_t uPos)
+static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me,
+ uint8_t byte,
+ size_t uPos)
{
UsefulOutBuf_InsertData(me, &byte, 1, uPos);
}
-/**
- @brief Insert a 16-bit integer into the UsefulOutBuf
-
- @param[in] me Pointer to the UsefulOutBul
- @param[in] uInteger16 Integer to insert
- @param[in] uPos Index in output buffer at which to insert
-
- See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
- the difference being a single byte is to be inserted.
-
- The integer will be inserted in network byte order (big endian)
- */
-static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me, uint16_t uInteger16, size_t uPos)
+static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me,
+ uint16_t uInteger16,
+ size_t uPos)
{
// Converts native integer format to network byte order (big endian)
uint8_t tmp[2];
@@ -858,19 +1578,9 @@
}
-/**
- @brief Insert a 32-bit integer into the UsefulOutBuf
-
- @param[in] me Pointer to the UsefulOutBul
- @param[in] uInteger32 Integer to insert
- @param[in] uPos Index in output buffer at which to insert
-
- See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
- the difference being a single byte is to be inserted.
-
- The integer will be inserted in network byte order (big endian)
- */
-static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *me, uint32_t uInteger32, size_t uPos)
+static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pMe,
+ uint32_t uInteger32,
+ size_t uPos)
{
// Converts native integer format to network byte order (big endian)
uint8_t tmp[4];
@@ -878,23 +1588,13 @@
tmp[1] = (uInteger32 & 0xff0000) >> 16;
tmp[2] = (uInteger32 & 0xff00) >> 8;
tmp[3] = (uInteger32 & 0xff);
- UsefulOutBuf_InsertData(me, tmp, 4, uPos);
+ UsefulOutBuf_InsertData(pMe, tmp, 4, uPos);
}
-/**
- @brief Insert a 64-bit integer into the UsefulOutBuf
-
- @param[in] me Pointer to the UsefulOutBul
- @param[in] uInteger64 Integer to insert
- @param[in] uPos Index in output buffer at which to insert
-
- See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
- the difference being a single byte is to be inserted.
-
- The integer will be inserted in network byte order (big endian)
- */
-static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *me, uint64_t uInteger64, size_t uPos)
+static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pMe,
+ uint64_t uInteger64,
+ size_t uPos)
{
// Converts native integer format to network byte order (big endian)
uint8_t tmp[8];
@@ -906,478 +1606,168 @@
tmp[5] = (uInteger64 & 0xff0000) >> 16;
tmp[6] = (uInteger64 & 0xff00) >> 8;
tmp[7] = (uInteger64 & 0xff);
- UsefulOutBuf_InsertData(me, tmp, 8, uPos);
+ UsefulOutBuf_InsertData(pMe, tmp, 8, uPos);
}
-/**
- @brief Insert a float into the UsefulOutBuf
-
- @param[in] me Pointer to the UsefulOutBul
- @param[in] f Integer to insert
- @param[in] uPos Index in output buffer at which to insert
-
- See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
- the difference being a single byte is to be inserted.
-
- The float will be inserted in network byte order (big endian)
- */
-static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *me, float f, size_t uPos)
+static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pMe,
+ float f,
+ size_t uPos)
{
- UsefulOutBuf_InsertUint32(me, UsefulBufUtil_CopyFloatToUint32(f), uPos);
+ UsefulOutBuf_InsertUint32(pMe, UsefulBufUtil_CopyFloatToUint32(f), uPos);
}
-/**
- @brief Insert a double into the UsefulOutBuf
-
- @param[in] me Pointer to the UsefulOutBul
- @param[in] d Integer to insert
- @param[in] uPos Index in output buffer at which to insert
-
- See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
- the difference being a single byte is to be inserted.
-
- The double will be inserted in network byte order (big endian)
- */
-static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *me, double d, size_t uPos)
+static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pMe,
+ double d,
+ size_t uPos)
{
- UsefulOutBuf_InsertUint64(me, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
+ UsefulOutBuf_InsertUint64(pMe, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
}
-
-/**
- Append a UsefulBuf into the UsefulOutBuf
-
- @param[in] me Pointer to the UsefulOutBuf
- @param[in] NewData UsefulBuf with the bytes to append
-
- See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
- with the insertion point at the end of the valid data.
-
-*/
-static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *me, UsefulBufC NewData)
+static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pMe,
+ UsefulBufC NewData)
{
// An append is just a insert at the end
- UsefulOutBuf_InsertUsefulBuf(me, NewData, UsefulOutBuf_GetEndPosition(me));
+ UsefulOutBuf_InsertUsefulBuf(pMe, NewData, UsefulOutBuf_GetEndPosition(pMe));
}
-/**
- Append bytes to the UsefulOutBuf
-
- @param[in] me Pointer to the UsefulOutBuf
- @param[in] pBytes Pointer to bytes to append
- @param[in] uLen Index in output buffer at which to append
-
- See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
- with the insertion point at the end of the valid data.
- */
-
-static inline void UsefulOutBuf_AppendData(UsefulOutBuf *me, const void *pBytes, size_t uLen)
+static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pMe,
+ const void *pBytes,
+ size_t uLen)
{
UsefulBufC Data = {pBytes, uLen};
- UsefulOutBuf_AppendUsefulBuf(me, Data);
+ UsefulOutBuf_AppendUsefulBuf(pMe, Data);
}
-/**
- Append a NULL-terminated string to the UsefulOutBuf
-
- @param[in] me Pointer to the UsefulOutBuf
- @param[in] szString string to append
-
- */
-static inline void UsefulOutBuf_AppendString(UsefulOutBuf *me, const char *szString)
+static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pMe,
+ const char *szString)
{
- UsefulOutBuf_AppendUsefulBuf(me, (UsefulBufC){szString, strlen(szString)});
+ UsefulOutBuf_AppendUsefulBuf(pMe, (UsefulBufC){szString, strlen(szString)});
}
-/**
- @brief Append a byte to the UsefulOutBuf
-
- @param[in] me Pointer to the UsefulOutBuf
- @param[in] byte Bytes to append
-
- See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
- with the insertion point at the end of the valid data.
- */
-static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *me, uint8_t byte)
+static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pMe,
+ uint8_t byte)
{
- UsefulOutBuf_AppendData(me, &byte, 1);
-}
-
-/**
- @brief Append an integer to the UsefulOutBuf
-
- @param[in] me Pointer to the UsefulOutBuf
- @param[in] uInteger16 Integer to append
-
- See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
- with the insertion point at the end of the valid data.
-
- The integer will be appended in network byte order (big endian).
- */
-static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *me, uint16_t uInteger16){
- UsefulOutBuf_InsertUint16(me, uInteger16, UsefulOutBuf_GetEndPosition(me));
-}
-
-/**
- @brief Append an integer to the UsefulOutBuf
-
- @param[in] me Pointer to the UsefulOutBuf
- @param[in] uInteger32 Integer to append
-
- See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
- with the insertion point at the end of the valid data.
-
- The integer will be appended in network byte order (big endian).
- */
-static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *me, uint32_t uInteger32){
- UsefulOutBuf_InsertUint32(me, uInteger32, UsefulOutBuf_GetEndPosition(me));
-}
-
-/**
- @brief Append an integer to the UsefulOutBuf
-
- @param[in] me Pointer to the UsefulOutBuf
- @param[in] uInteger64 Integer to append
-
- See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
- with the insertion point at the end of the valid data.
-
- The integer will be appended in network byte order (big endian).
- */
-static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *me, uint64_t uInteger64){
- UsefulOutBuf_InsertUint64(me, uInteger64, UsefulOutBuf_GetEndPosition(me));
+ UsefulOutBuf_AppendData(pMe, &byte, 1);
}
-/**
- @brief Append a float to the UsefulOutBuf
-
- @param[in] me Pointer to the UsefulOutBuf
- @param[in] f Float to append
-
- See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
- with the insertion point at the end of the valid data.
-
- The float will be appended in network byte order (big endian).
- */
-static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *me, float f){
- UsefulOutBuf_InsertFloat(me, f, UsefulOutBuf_GetEndPosition(me));
-}
-
-/**
- @brief Append a float to the UsefulOutBuf
-
- @param[in] me Pointer to the UsefulOutBuf
- @param[in] d Double to append
-
- See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
- with the insertion point at the end of the valid data.
-
- The double will be appended in network byte order (big endian).
- */
-static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *me, double d){
- UsefulOutBuf_InsertDouble(me, d, UsefulOutBuf_GetEndPosition(me));
-}
-
-/**
- @brief Returns the current error status
-
- @param[in] me Pointer to the UsefulOutBuf
-
- @return 0 if all OK, 1 on error
-
- This is the error status since the call to either
- UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once it goes into error
- state it will stay until one of those functions is called.
-
- Possible error conditions are:
- - bytes to be inserted will not fit
- - insertion point is out of buffer or past valid data
- - current position is off end of buffer (probably corruption or uninitialized)
- - detect corruption / uninitialized by bad magic number
- */
-
-static inline int UsefulOutBuf_GetError(UsefulOutBuf *me)
+static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pMe,
+ uint16_t uInteger16)
{
- return me->err;
+ UsefulOutBuf_InsertUint16(pMe, uInteger16, UsefulOutBuf_GetEndPosition(pMe));
+}
+
+static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pMe,
+ uint32_t uInteger32)
+{
+ UsefulOutBuf_InsertUint32(pMe, uInteger32, UsefulOutBuf_GetEndPosition(pMe));
}
-/**
- @brief Returns number of bytes unused used in the output buffer
-
- @param[in] me Pointer to the UsefulOutBuf
-
- @return Number of unused bytes or zero
-
- Because of the error handling strategy and checks in UsefulOutBuf_InsertUsefulBuf()
- it is usually not necessary to use this.
- */
-
-static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *me)
+static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pMe,
+ uint64_t uInteger64)
{
- return me->UB.len - me->data_len;
+ UsefulOutBuf_InsertUint64(pMe, uInteger64, UsefulOutBuf_GetEndPosition(pMe));
}
-/**
- @brief Returns true / false if some number of bytes will fit in the UsefulOutBuf
-
- @param[in] me Pointer to the UsefulOutBuf
- @param[in] uLen Number of bytes for which to check
-
- @return 1 or 0 if nLen bytes would fit
-
- Because of the error handling strategy and checks in UsefulOutBuf_InsertUsefulBuf()
- it is usually not necessary to use this.
- */
-
-static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *me, size_t uLen)
+static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pMe,
+ float f)
{
- return uLen <= UsefulOutBuf_RoomLeft(me);
+ UsefulOutBuf_InsertFloat(pMe, f, UsefulOutBuf_GetEndPosition(pMe));
}
-/**
- @brief Returns the resulting valid data in a UsefulOutBuf
-
- @param[in] me Pointer to the UsefulOutBuf.
-
- @return The valid data in UsefulOutBuf.
-
- The storage for the returned data is Storage parameter passed
- to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut().
-
- This can be called anytime and many times to get intermediate
- results. It doesn't change the data or reset the current position
- so you can keep adding data.
- */
-
-UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *me);
-
-
-/**
- @brief Copies the valid data out into a supplied buffer
-
- @param[in] me Pointer to the UsefulOutBuf
- @param[out] Dest The destination buffer to copy into
-
- @return Pointer and length of copied data.
-
- This is the same as UsefulOutBuf_OutUBuf() except it copies the data.
-*/
-
-UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *me, UsefulBuf Dest);
-
-
-
-
-
-
-
-
-
-
-
-
-
-/**
- UsefulInputBuf is the counterpart to UsefulOutBuf and is for parsing
- data read or received. Initialize it with the data
- from the network and its length. Then use the functions
- here to get the various data types out of it. It maintains a position
- for getting the next item. This means you don't have to track a
- pointer as you get each object. UsefulInputBuf does that for you and
- makes sure it never goes off the end of the buffer. The QCBOR
- implementation parser makes use of this for all its pointer math and
- length checking.
-
- UsefulInputBuf also maintains an internal error state so you do not have
- to. Once data has been requested off the end of the buffer, it goes
- into an error state. You can keep calling functions to get more data
- but they will either return 0 or NULL. As long as you don't
- dereference the NULL, you can wait until all data items have been
- fetched before checking for the error and this can simplify your
- code.
-
- The integer and float parsing expects network byte order (big endian).
- Network byte order is what is used by TCP/IP, CBOR and most internet
- protocols.
-
- Lots of inlining is used to keep code size down. The code optimizer,
- particularly with the -Os, also reduces code size a lot. The only
- non-inline code is UsefulInputBuf_GetBytes() which is less than 100
- bytes so use of UsefulInputBuf doesn't add much code for all the messy
- hard-to-get right issues with parsing in C that is solves.
-
- The parse context size is:
- 64-bit machine: 16 + 8 + 2 + 1 (5 bytes padding to align) = 32 bytes
- 32-bit machine: 8 + 4 + 2 + 1 (1 byte padding to align) = 16 bytes
-
- */
-
-#define UIB_MAGIC (0xB00F)
-
-typedef struct useful_input_buf {
- // Private data structure
- UsefulBufC UB; // Data being parsed
- size_t cursor; // Current offset in data being parse
- uint16_t magic; // Check for corrupted or uninitialized UsefulInputBuf
- uint8_t err; // Set request goes off end or magic number is bad
-} UsefulInputBuf;
-
-
-
-/**
- @brief Initialize the UsefulInputBuf structure before use.
-
- @param[in] me Pointer to the UsefulInputBuf instance.
- @param[in] UB Pointer to the data to parse.
-
- */
-static inline void UsefulInputBuf_Init(UsefulInputBuf *me, UsefulBufC UB)
+static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pMe,
+ double d)
{
- me->cursor = 0;
- me->err = 0;
- me->magic = UIB_MAGIC;
- me->UB = UB;
+ UsefulOutBuf_InsertDouble(pMe, d, UsefulOutBuf_GetEndPosition(pMe));
}
-/**
- @brief Returns current position in input buffer
-
- @param[in] me Pointer to the UsefulInputBuf.
-
- @return Integer position of the cursor
-
- The position that the next bytes will be returned from.
-
- */
-static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *me)
+static inline int UsefulOutBuf_GetError(UsefulOutBuf *pMe)
{
- return me->cursor;
+ return pMe->err;
}
-/**
- @brief Sets current position in input buffer
-
- @param[in] me Pointer to the UsefulInputBuf.
- @param[in] uPos Position to set to
-
- If the position is off the end of the input buffer, the error state
- is entered and all functions will do nothing.
-
- Seeking to a valid position in the buffer will not reset the error
- state. Only re initialization will do that.
-
- */
-static inline void UsefulInputBuf_Seek(UsefulInputBuf *me, size_t uPos)
+static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pMe)
{
- if(uPos > me->UB.len) {
- me->err = 1;
+ return pMe->UB.len - pMe->data_len;
+}
+
+
+static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pMe, size_t uLen)
+{
+ return uLen <= UsefulOutBuf_RoomLeft(pMe);
+}
+
+
+
+
+static inline void UsefulInputBuf_Init(UsefulInputBuf *pMe, UsefulBufC UB)
+{
+ pMe->cursor = 0;
+ pMe->err = 0;
+ pMe->magic = UIB_MAGIC;
+ pMe->UB = UB;
+}
+
+static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *pMe)
+{
+ return pMe->cursor;
+}
+
+
+static inline void UsefulInputBuf_Seek(UsefulInputBuf *pMe, size_t uPos)
+{
+ if(uPos > pMe->UB.len) {
+ pMe->err = 1;
} else {
- me->cursor = uPos;
+ pMe->cursor = uPos;
}
}
-/**
- @brief Returns the number of bytes from the cursor to the end of the buffer,
- the uncomsummed bytes.
-
- @param[in] me Pointer to the UsefulInputBuf.
-
- @return number of bytes unconsumed or 0 on error.
-
- This is a critical function for input length validation. This does
- some pointer / offset math.
-
- Returns 0 if the cursor it invalid or corruption of the structure is
- detected.
-
- Code Reviewers: THIS FUNCTION DOES POINTER MATH
- */
-static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *me)
+static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pMe)
{
+ // Code Reviewers: THIS FUNCTION DOES POINTER MATH
+
// Magic number is messed up. Either the structure got overwritten
// or was never initialized.
- if(me->magic != UIB_MAGIC) {
+ if(pMe->magic != UIB_MAGIC) {
return 0;
}
- // The cursor is off the end of the input buffer given
+ // The cursor is off the end of the input buffer given.
// Presuming there are no bugs in this code, this should never happen.
// If it so, the struct was corrupted. The check is retained as
- // as a defense in case there is a bug in this code or the struct is corrupted.
- if(me->cursor > me->UB.len) {
+ // as a defense in case there is a bug in this code or the struct is
+ // corrupted.
+ if(pMe->cursor > pMe->UB.len) {
return 0;
}
// subtraction can't go neative because of check above
- return me->UB.len - me->cursor;
+ return pMe->UB.len - pMe->cursor;
}
-/**
- @brief Check if there are any unconsumed bytes
-
- @param[in] me Pointer to the UsefulInputBuf.
-
- @return 1 if len bytes are available after the cursor, and 0 if not
-
- */
-static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *me, size_t uLen)
+static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pMe, size_t uLen)
{
- return UsefulInputBuf_BytesUnconsumed(me) >= uLen ? 1 : 0;
+ return UsefulInputBuf_BytesUnconsumed(pMe) >= uLen ? 1 : 0;
}
-/**
- @brief Get pointer to bytes out of the input buffer
-
- @param[in] me Pointer to the UsefulInputBuf.
- @param[in] uNum Number of bytes to get
-
- @return Pointer to bytes.
-
- This consumes n bytes from the input buffer. It returns a pointer to
- the start of the n bytes.
-
- If there are not n bytes in the input buffer, NULL will be returned
- and an error will be set.
-
- It advances the current position by n bytes.
- */
-const void * UsefulInputBuf_GetBytes(UsefulInputBuf *me, size_t uNum);
-
-
-/**
- @brief Get UsefulBuf out of the input buffer
-
- @param[in] me Pointer to the UsefulInputBuf.
- @param[in] uNum Number of bytes to get
-
- @return UsefulBufC with ptr and length for bytes consumed.
-
- This consumes n bytes from the input buffer and returns the pointer
- and len to them as a UsefulBufC. The len returned will always be n.
-
- If there are not n bytes in the input buffer, UsefulBufC.ptr will be
- NULL and UsefulBufC.len will be 0. An error will be set.
-
- It advances the current position by n bytes.
- */
-static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *me, size_t uNum)
+static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pMe, size_t uNum)
{
- const void *pResult = UsefulInputBuf_GetBytes(me, uNum);
+ const void *pResult = UsefulInputBuf_GetBytes(pMe, uNum);
if(!pResult) {
return NULLUsefulBufC;
} else {
@@ -1386,48 +1776,16 @@
}
-/**
- @brief Get a byte out of the input buffer.
-
- @param[in] me Pointer to the UsefulInputBuf.
-
- @return The byte
-
- This consumes 1 byte from the input buffer. It returns the byte.
-
- If there is not 1 byte in the buffer, 0 will be returned for the byte
- and an error set internally. You must check the error at some point
- to know whether the 0 was the real value or just returned in error,
- but you may not have to do that right away. Check the error state
- with UsefulInputBuf_GetError(). You can also know you are in the
- error state if UsefulInputBuf_GetBytes() returns NULL or the ptr from
- UsefulInputBuf_GetUsefulBuf() is NULL.
-
- It advances the current position by 1 byte.
- */
-static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *me)
+static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pMe)
{
- const void *pResult = UsefulInputBuf_GetBytes(me, sizeof(uint8_t));
+ const void *pResult = UsefulInputBuf_GetBytes(pMe, sizeof(uint8_t));
return pResult ? *(uint8_t *)pResult : 0;
}
-
-/**
- @brief Get a uint16_t out of the input buffer
-
- @param[in] me Pointer to the UsefulInputBuf.
-
- @return The uint16_t
-
- See UsefulInputBuf_GetByte(). This works the same, except it returns
- a uint16_t and two bytes are consumed.
-
- The input bytes must be in network order (big endian).
- */
-static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *me)
+static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pMe)
{
- const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(me, sizeof(uint16_t));
+ const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint16_t));
if(!pResult) {
return 0;
@@ -1437,125 +1795,61 @@
}
-/**
- @brief Get a uint32_t out of the input buffer
-
- @param[in] me Pointer to the UsefulInputBuf.
-
- @return The uint32_t
-
- See UsefulInputBuf_GetByte(). This works the same, except it returns
- a uint32_t and four bytes are consumed.
-
- The input bytes must be in network order (big endian).
- */
-static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *me)
+static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pMe)
{
- const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(me, sizeof(uint32_t));
+ const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint32_t));
if(!pResult) {
return 0;
}
return ((uint32_t)pResult[0]<<24) +
- ((uint32_t)pResult[1]<<16) +
- ((uint32_t)pResult[2]<<8) +
- (uint32_t)pResult[3];
+ ((uint32_t)pResult[1]<<16) +
+ ((uint32_t)pResult[2]<<8) +
+ (uint32_t)pResult[3];
}
-/**
- @brief Get a uint64_t out of the input buffer
-
- @param[in] me Pointer to the UsefulInputBuf.
-
- @return The uint64_t
-
- See UsefulInputBuf_GetByte(). This works the same, except it returns
- a uint64_t and eight bytes are consumed.
-
- The input bytes must be in network order (big endian).
- */
-static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *me)
+static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pMe)
{
- const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(me, sizeof(uint64_t));
+ const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint64_t));
if(!pResult) {
return 0;
}
return ((uint64_t)pResult[0]<<56) +
- ((uint64_t)pResult[1]<<48) +
- ((uint64_t)pResult[2]<<40) +
- ((uint64_t)pResult[3]<<32) +
- ((uint64_t)pResult[4]<<24) +
- ((uint64_t)pResult[5]<<16) +
- ((uint64_t)pResult[6]<<8) +
- (uint64_t)pResult[7];
+ ((uint64_t)pResult[1]<<48) +
+ ((uint64_t)pResult[2]<<40) +
+ ((uint64_t)pResult[3]<<32) +
+ ((uint64_t)pResult[4]<<24) +
+ ((uint64_t)pResult[5]<<16) +
+ ((uint64_t)pResult[6]<<8) +
+ (uint64_t)pResult[7];
}
-/**
- @brief Get a float out of the input buffer
-
- @param[in] me Pointer to the UsefulInputBuf.
-
- @return The float
-
- See UsefulInputBuf_GetByte(). This works the same, except it returns
- a float and four bytes are consumed.
-
- The input bytes must be in network order (big endian).
- */
-static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *me)
+static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *pMe)
{
- uint32_t uResult = UsefulInputBuf_GetUint32(me);
+ uint32_t uResult = UsefulInputBuf_GetUint32(pMe);
return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0;
}
-/**
- @brief Get a double out of the input buffer
- @param[in] me Pointer to the UsefulInputBuf.
-
- @return The double
-
- See UsefulInputBuf_GetByte(). This works the same, except it returns
- a double and eight bytes are consumed.
-
- The input bytes must be in network order (big endian).
- */
-static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *me)
+static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *pMe)
{
- uint64_t uResult = UsefulInputBuf_GetUint64(me);
+ uint64_t uResult = UsefulInputBuf_GetUint64(pMe);
return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0;
}
-/**
- @brief Get the error status
-
- @param[in] me Pointer to the UsefulInputBuf.
-
- @return The error.
-
- Zero is success, non-zero is error. Once in the error state, the only
- way to clear it is to call Init again.
-
- You may be able to only check the error state at the end after all
- the Get()'s have been done, but if what you get later depends on what
- you get sooner you cannot. For example if you get a length or count
- of following items you will have to check the error.
-
- */
-static inline int UsefulInputBuf_GetError(UsefulInputBuf *me)
+static inline int UsefulInputBuf_GetError(UsefulInputBuf *pMe)
{
- return me->err;
+ return pMe->err;
}
-
#ifdef __cplusplus
}
#endif
diff --git a/src/UsefulBuf.c b/src/UsefulBuf.c
index d27c146..f13dad2 100644
--- a/src/UsefulBuf.c
+++ b/src/UsefulBuf.c
@@ -138,11 +138,11 @@
Code Reviewers: THIS FUNCTION DOES POINTER MATH
*/
-void UsefulOutBuf_Init(UsefulOutBuf *me, UsefulBuf Storage)
+void UsefulOutBuf_Init(UsefulOutBuf *pMe, UsefulBuf Storage)
{
- me->magic = USEFUL_OUT_BUF_MAGIC;
- UsefulOutBuf_Reset(me);
- me->UB = Storage;
+ pMe->magic = USEFUL_OUT_BUF_MAGIC;
+ UsefulOutBuf_Reset(pMe);
+ pMe->UB = Storage;
#if 0
// This check is off by default.
@@ -196,9 +196,9 @@
4. Put the new data in at the insertion position.
*/
-void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *me, UsefulBufC NewData, size_t uInsertionPos)
+void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pMe, UsefulBufC NewData, size_t uInsertionPos)
{
- if(me->err) {
+ if(pMe->err) {
// Already in error state.
return;
}
@@ -208,53 +208,53 @@
// probably means me was not initialized or it was corrupted. Attackers
// can defeat this, but it is a hurdle and does good with very
// little code.
- if(me->magic != USEFUL_OUT_BUF_MAGIC) {
- me->err = 1;
+ if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
+ pMe->err = 1;
return; // Magic number is wrong due to uninitalization or corrption
}
// Make sure valid data is less than buffer size. This would only occur
// if there was corruption of me, but it is also part of the checks to
// be sure there is no pointer arithmatic under/overflow.
- if(me->data_len > me->UB.len) { // Check #1
- me->err = 1;
+ if(pMe->data_len > pMe->UB.len) { // Check #1
+ pMe->err = 1;
return; // Offset of valid data is off the end of the UsefulOutBuf due to uninitialization or corruption
}
/* 1. Will it fit? */
// WillItFit() is the same as: NewData.len <= (me->size - me->data_len)
// Check #1 makes sure subtraction in RoomLeft will not wrap around
- if(! UsefulOutBuf_WillItFit(me, NewData.len)) { // Check #2
+ if(! UsefulOutBuf_WillItFit(pMe, NewData.len)) { // Check #2
// The new data will not fit into the the buffer.
- me->err = 1;
+ pMe->err = 1;
return;
}
/* 2. Check the Insertion Position */
// This, with Check #1, also confirms that uInsertionPos <= me->data_len
- if(uInsertionPos > me->data_len) { // Check #3
+ if(uInsertionPos > pMe->data_len) { // Check #3
// Off the end of the valid data in the buffer.
- me->err = 1;
+ pMe->err = 1;
return;
}
/* 3. Slide existing data to the right */
- uint8_t *pSourceOfMove = ((uint8_t *)me->UB.ptr) + uInsertionPos; // PtrMath #1
- size_t uNumBytesToMove = me->data_len - uInsertionPos; // PtrMath #2
+ uint8_t *pSourceOfMove = ((uint8_t *)pMe->UB.ptr) + uInsertionPos; // PtrMath #1
+ size_t uNumBytesToMove = pMe->data_len - uInsertionPos; // PtrMath #2
uint8_t *pDestinationOfMove = pSourceOfMove + NewData.len; // PtrMath #3
- if(uNumBytesToMove && me->UB.ptr) {
+ if(uNumBytesToMove && pMe->UB.ptr) {
// To know memmove won't go off end of destination, see PtrMath #4
memmove(pDestinationOfMove, pSourceOfMove, uNumBytesToMove);
}
/* 4. Put the new data in */
- uint8_t *pInsertionPoint = ((uint8_t *)me->UB.ptr) + uInsertionPos; // PtrMath #5
- if(me->UB.ptr) {
+ uint8_t *pInsertionPoint = ((uint8_t *)pMe->UB.ptr) + uInsertionPos; // PtrMath #5
+ if(pMe->UB.ptr) {
// To know memmove won't go off end of destination, see PtrMath #6
memmove(pInsertionPoint, NewData.ptr, NewData.len);
}
- me->data_len += NewData.len ;
+ pMe->data_len += NewData.len ;
}
@@ -291,18 +291,18 @@
/*
Public function -- see UsefulBuf.h
*/
-UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *me)
+UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pMe)
{
- if(me->err) {
+ if(pMe->err) {
return NULLUsefulBufC;
}
- if(me->magic != USEFUL_OUT_BUF_MAGIC) {
- me->err = 1;
+ if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
+ pMe->err = 1;
return NULLUsefulBufC;
}
- return (UsefulBufC){me->UB.ptr,me->data_len};
+ return (UsefulBufC){pMe->UB.ptr, pMe->data_len};
}
@@ -311,9 +311,9 @@
Copy out the data accumulated in to the output buffer.
*/
-UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *me, UsefulBuf pDest)
+UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pMe, UsefulBuf pDest)
{
- const UsefulBufC Tmp = UsefulOutBuf_OutUBuf(me);
+ const UsefulBufC Tmp = UsefulOutBuf_OutUBuf(pMe);
if(UsefulBuf_IsNULLC(Tmp)) {
return NULLUsefulBufC;
}
@@ -330,22 +330,22 @@
Code Reviewers: THIS FUNCTION DOES POINTER MATH
*/
-const void * UsefulInputBuf_GetBytes(UsefulInputBuf *me, size_t uAmount)
+const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pMe, size_t uAmount)
{
// Already in error state. Do nothing.
- if(me->err) {
+ if(pMe->err) {
return NULL;
}
- if(!UsefulInputBuf_BytesAvailable(me, uAmount)) {
+ if(!UsefulInputBuf_BytesAvailable(pMe, uAmount)) {
// The number of bytes asked for at current position are more than available
- me->err = 1;
+ pMe->err = 1;
return NULL;
}
// This is going to succeed
- const void * const result = ((uint8_t *)me->UB.ptr) + me->cursor;
- me->cursor += uAmount; // this will not overflow because of check using UsefulInputBuf_BytesAvailable()
+ const void * const result = ((uint8_t *)pMe->UB.ptr) + pMe->cursor;
+ pMe->cursor += uAmount; // this will not overflow because of check using UsefulInputBuf_BytesAvailable()
return result;
}