first version of better useful buf
diff --git a/inc/UsefulBuf.h b/inc/UsefulBuf.h
index b78d0c7..aa160ba 100644
--- a/inc/UsefulBuf.h
+++ b/inc/UsefulBuf.h
@@ -60,6 +60,7 @@
#include <stddef.h> // for size_t
/**
+ @file UsefulBuf.h
The goal of this code is to make buffer and pointer manipulation
easier and safer.
@@ -109,9 +110,16 @@
gigabit-per-second IP router), it is probably better to have cleaner
code you can be most certain about the security of.
- The len field is the length of the valid data pointed to.
+ The non-const UsefulBuf is usually used to refer a buffer
+ to be filled in. The length is the size of the buffer.
- There is also a const version of it when the data is const.
+ 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.
+
+ 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 UsefulBuf is NULL, it has no value, when the ptr in it is NULL.
@@ -132,16 +140,26 @@
typedef struct {
void *ptr;
- size_t len;
+ const size_t len;
} UsefulBuf;
typedef struct {
const void *ptr;
- size_t len;
+ const size_t len;
} UsefulBufC;
+/**
+ A "NULL" UsefulBuf 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.
+ */
+#define UsefulBuf_IsNULL(UB) (!(UB).ptr)
+
+#define NULLUsefulBufC ((UsefulBufC) {NULL, 0})
+
+#define NULLUsefulBuf ((UsefulBuf) {NULL, 0})
+
/**
@@ -171,21 +189,55 @@
}
+
+
/**
- A "NULL" UsefulBuf 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.
+ Convert a literal string to a UsefulBufC.
+
+ szString must be a literal string that you can take sizeof.
+ This is better for literal strings than SZToUsefulBufC
+ 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_IsNULL(UB) (!(UB).ptr)
+#define SZLiteralToUsefulBufC(szString) \
+ ((UsefulBufC) {(szString), sizeof(szString)-1})
-#define NULLUsefulBufC ((UsefulBufC) {NULL, 0})
+#define UsefulBuf_FromSZLiteral(szString) \
+ ((UsefulBufC) {(szString), sizeof(szString)-1})
-#define NULLUsefulBuf ((UsefulBuf) {NULL, 0})
+
+/**
+ Convert a literal byte array to a UsefulBufC.
+
+ pBytes must be a literal string that you can take sizeof.
+ It will not work on non-literal strings.
+
+ */
+#define ByteArrayLiteralToUsefulBufC(pBytes) \
+ ((UsefulBufC) {(pBytes), sizeof(pBytes)})
+
+#define UsefulBuf_FromByteArrayLiteral(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
+#define MakeUsefulBufOnStack(name, size) \
+ uint8_t __pBuf##name[(size)];\
+ UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
+
+#define UsefulBuf_MakeStackUB(name, size) \
+ uint8_t __pBuf##name[(size)];\
+ UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
/*
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.
+ but that value is of zero length. It is empty when len is zero. It
+ doesn't matter what the 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
@@ -197,6 +249,9 @@
#define UsefulBuf_IsNULLOrEmpty(UB) (UsefulBuf_IsNULL(UB) || UsefulBuf_IsEmpty(UB))
+static inline int UsefulBuf_IsEmptyX(UsefulBufC UB) {
+ return !UB.len;
+}
@@ -213,28 +268,27 @@
The terminating \0 (NULL) is NOT included in the length!
*/
-static inline UsefulBufC SZToUsefulBufC(const char *szString){
- return ((UsefulBufC) {szString, strlen(szString)});
+static inline UsefulBufC UsefulBuf_FromSZ(const char *szString){
+ return ((UsefulBufC) {szString, strlen(szString)});
}
/**
@brief Copy one UsefulBuf into another
- @param[in] pDest The destination buffer to copy into
+ @param[in] Dest The destination buffer to copy into
@param[out] Src The source to copy from
- @return 0 on success, 1 on failure
+ @return filled in UsefulBufC on success, NULLUsefulBufC on failure
- This fails and returns 1 if Src.len is greater than
- pDest->len.
+ This fails if Src.len is greater than Dest.len.
Note that like memcpy, the pointers are not checked and
- this will crash, rather than return 1 if they are NULL
- or invalid.
+ this will crash, rather than return NULLUsefulBufC if
+ they are NULL or invalid.
*/
-int UsefulBuf_Copy(UsefulBuf *pDest, const UsefulBufC Src);
+UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src);
@@ -255,7 +309,7 @@
/**
@brief Copy a pointer into a UsefulBuf
- @param[in,out] pDest The destination buffer to copy into
+ @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
@@ -269,9 +323,9 @@
or invalid.
*/
-inline static int UsefulBuf_CopyPtr(UsefulBuf *pDest, const void *ptr, size_t len)
+inline static UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
{
- return UsefulBuf_Copy(pDest, (UsefulBufC){ptr, len});
+ return UsefulBuf_Copy(Dest, (UsefulBufC){ptr, len});
}
@@ -312,37 +366,6 @@
-/**
- Convert a literal string to a UsefulBufC.
-
- szString must be a literal string that you can take sizeof.
- This is better for literal strings than SZToUsefulBufC
- because it generates less code. It will not work on
- non-literal strings.
-
- The terminating \0 (NULL) is NOT included in the length!
-
- */
-#define SZLiteralToUsefulBufC(szString) \
- ((UsefulBufC) {(szString), sizeof(szString)-1})
-
-
-/**
- Convert a literal byte array to a UsefulBufC.
-
- pBytes must be a literal string that you can take sizeof.
- It will not work on non-literal strings.
-
- */
-#define ByteArrayLiteralToUsefulBufC(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
-#define MakeUsefulBufOnStack(name, size) \
- uint8_t __pBuf##name[(size)];\
- UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
@@ -415,7 +438,7 @@
typedef struct {
UsefulBuf UB;
- size_t size; // size of the buffer (not the valid data in the buffer)
+ size_t data_len; // length of the data
uint16_t magic; // Used to detect corruption and lack of initialization
uint8_t err;
} UsefulOutBuf;
@@ -425,15 +448,14 @@
@brief Initialize and supply the actual output buffer
@param[out] me The UsefulOutBuf to initialize
- @param[in] pStorage Pointer to data buffer to use
- @param[in] uStorageSize Size of buffer pStorage
+ @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, void *pStorage, size_t uStorageSize);
+void UsefulOutBuf_Init(UsefulOutBuf *me, UsefulBuf Storage);
@@ -462,7 +484,7 @@
*/
static inline void UsefulOutBuf_Reset(UsefulOutBuf *me)
{
- me->UB.len = 0;
+ me->data_len = 0;
me->err = 0;
}
@@ -484,7 +506,7 @@
*/
static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *me)
{
- return me->UB.len;
+ return me->data_len;
}
@@ -498,7 +520,7 @@
*/
static inline int UsefulOutBuf_AtStart(UsefulOutBuf *me)
{
- return 0 == me->UB.len;
+ return 0 == me->data_len;
}
@@ -875,7 +897,7 @@
static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *me)
{
- return me->size - me->UB.len;
+ return me->UB.len - me->data_len;
}
@@ -901,9 +923,8 @@
@brief Returns the resulting valid data in a UsefulBuf
@param[in] me Pointer to the UsefulOutBuf
- @param[out] O UsefuBuf structure holding pointer and length
- @return Same as UsefulOutBuf_GetError()
+ @return TODO:
If you want a pointer and length to the resulting data, dereference
O.
@@ -913,7 +934,7 @@
so you can keep adding data.
*/
-int UsefulOutBuf_OutUBuf(UsefulOutBuf *me, UsefulBuf *O);
+UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *me);
/**
@@ -1118,15 +1139,11 @@
static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *me, size_t uNum)
{
const void *pResult = UsefulInputBuf_GetBytes(me, uNum);
-
- UsefulBufC UBR = {NULL, 0};
-
- if(pResult) {
- UBR.len = uNum;
- UBR.ptr = pResult;
- }
-
- return UBR;
+ if(!pResult) {
+ return NULLUsefulBufC;
+ } else {
+ return (UsefulBufC){pResult, uNum};
+ }
}
diff --git a/inc/qcbor.h b/inc/qcbor.h
index cf34844..1036e1a 100644
--- a/inc/qcbor.h
+++ b/inc/qcbor.h
@@ -499,7 +499,7 @@
} EncodedCBORC;
typedef struct __EncodedCBOR {
- UsefulBuf Bytes;
+ UsefulBufC Bytes;
uint16_t uItems;
} EncodedCBOR;
@@ -722,7 +722,7 @@
*/
static inline EncodedCBORC EncodedCBORConst(const EncodedCBOR ECBOR)
{
- return (EncodedCBORC){UsefulBuf_Const(ECBOR.Bytes), ECBOR.uItems};
+ return (EncodedCBORC){ECBOR.Bytes, ECBOR.uItems};
}
@@ -766,7 +766,7 @@
*/
-void QCBOREncode_Init(QCBOREncodeContext *pCtx, void *pBuf, size_t uBufLen);
+void QCBOREncode_Init(QCBOREncodeContext *pCtx, UsefulBuf Storage);
@@ -1022,7 +1022,7 @@
QCBOREncode_AddText_3((pCtx), NULL, (nLabel), CBOR_TAG_NONE, (Bytes))
inline static void QCBOREncode_AddSZString_3(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, uint64_t uTag, const char *szString) {
- QCBOREncode_AddText_3(pCtx, szLabel, nLabel, uTag, SZToUsefulBufC(szString));
+ QCBOREncode_AddText_3(pCtx, szLabel, nLabel, uTag, UsefulBuf_FromSZ(szString));
}
#define QCBOREncode_AddSZString(pCtx, szString) \
diff --git a/src/UsefulBuf.c b/src/UsefulBuf.c
index a0cc9b6..d98ebd5 100644
--- a/src/UsefulBuf.c
+++ b/src/UsefulBuf.c
@@ -57,16 +57,14 @@
/*
Public function -- see UsefulBuf.h
*/
-int UsefulBuf_Copy(UsefulBuf *pDest, const UsefulBufC Src)
+UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
{
- if(Src.len > pDest->len)
- return 1;
+ if(Src.len > Dest.len)
+ return NULLUsefulBufC;
- memcpy(pDest->ptr, Src.ptr, Src.len);
-
- pDest->len = Src.len;
-
- return 0;
+ memcpy(Dest.ptr, Src.ptr, Src.len);
+
+ return((UsefulBufC){Dest.ptr, Src.len});
}
/*
@@ -121,7 +119,8 @@
THIS FUNCTION DOES POINTER MATH
*/
-void UsefulOutBuf_Init(UsefulOutBuf *me, void *pStorage, size_t uStorageSize)
+#if NODEF
+void UsefulOutBuf_InitOld(UsefulOutBuf *me, void *pStorage, size_t uStorageSize)
{
me->magic = USEFUL_OUT_BUF_MAGIC;
UsefulOutBuf_Reset(me);
@@ -141,6 +140,27 @@
me->err = 1;
#endif
}
+#endif
+
+void UsefulOutBuf_Init(UsefulOutBuf *me, UsefulBuf Storage)
+{
+ me->magic = USEFUL_OUT_BUF_MAGIC;
+ UsefulOutBuf_Reset(me);
+ me->UB = Storage;
+
+ // The following check fails on ThreadX
+#if 0
+ // Sanity check on the pointer and size to be sure we are not
+ // passed a buffer that goes off the end of the address space.
+ // Given this test, we know that all unsigned lengths less than
+ // me->size are valid and won't wrap in any pointer additions
+ // based off of pStorage in the rest of this code.
+ const uintptr_t ptrM = UINTPTR_MAX - uStorageSize;
+ if(pStorage && (uintptr_t)pStorage > ptrM) // Check #0
+ me->err = 1;
+#endif
+}
+
/*
@@ -197,7 +217,7 @@
// 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->UB.len > me->size) { // Check #1
+ if(me->data_len > me->UB.len) { // Check #1
me->err = 1;
return; // Offset of valid data is off the end of the UsefulOutBuf due to uninitialization or corruption
}
@@ -223,7 +243,7 @@
uint8_t *pSourceOfMove = ((uint8_t *)me->UB.ptr) + uInsertionPos; // PtrMath #1
size_t uNumBytesToMove = me->UB.len - uInsertionPos; // PtrMath #2
uint8_t *pDestinationOfMove = pSourceOfMove + NewData.len; // PtrMath #3
- size_t uRoomInDestination = me->size - (uInsertionPos + NewData.len); // PtrMath #4
+ size_t uRoomInDestination = me->UB.len - (uInsertionPos + NewData.len); // PtrMath #4
if(uNumBytesToMove && me->UB.ptr) {
memmove(pDestinationOfMove, pSourceOfMove, uNumBytesToMove);
@@ -231,11 +251,11 @@
/* 4. Put the new data in */
uint8_t *pInsertionPoint = ((uint8_t *)me->UB.ptr) + uInsertionPos; // PtrMath #5
- uRoomInDestination = me->size - uInsertionPos; // PtrMath #6
+ uRoomInDestination = me->UB.len - uInsertionPos; // PtrMath #6
if(me->UB.ptr) {
memmove(pInsertionPoint, NewData.ptr, NewData.len);
}
- me->UB.len += NewData.len ;
+ me->data_len += NewData.len ;
}
@@ -267,24 +287,31 @@
/*
- Public function -- see UsefulBuf.h
-
- Returns the resulting valid data in a UsefulBuf
-
+ Public function -- see UsefulBuf.h
*/
-int UsefulOutBuf_OutUBuf(UsefulOutBuf *me, UsefulBuf *O)
+UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *me)
{
if(me->err) {
- return me->err;
+ return NULLUsefulBufC;
}
if(me->magic != USEFUL_OUT_BUF_MAGIC) {
me->err = 1;
- return 1;
+ return NULLUsefulBufC;
}
-
- *O = me->UB;
- return 0;
+
+ return(UsefulBufC){me->UB.ptr,me->data_len};
+}
+
+
+UsefulBufC UsefulOutBuf_CopyOut2(UsefulOutBuf *me, UsefulBuf pDest)
+{
+ UsefulBufC Tmp = UsefulOutBuf_OutUBuf(me);
+ if(UsefulBuf_IsNULL(Tmp)) {
+ return NULLUsefulBufC;
+ }
+
+ return UsefulBuf_Copy(pDest, Tmp);
}
@@ -296,18 +323,12 @@
*/
int UsefulOutBuf_CopyOut(UsefulOutBuf *me, void *pBuf, size_t uBufSize, size_t *puCopied)
{
- UsefulBuf B;
- if(UsefulOutBuf_OutUBuf(me, &B)) {
- return 1; // was in error state or was corrupted
- }
-
- if(B.len > uBufSize) {
- return 1; // buffer was too small
- }
-
- memmove(pBuf, B.ptr, B.len);
+ UsefulBufC B = UsefulOutBuf_CopyOut2(me, (UsefulBuf){pBuf, uBufSize});
+ if(UsefulBuf_IsNULL(B)) {
+ return 1; // was in error state or was corrupted or pBuf too small
+ }
- *puCopied = me->UB.len;
+ *puCopied = B.len;
return 0;
}
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index 90d3bf3..25c62f7 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -339,9 +339,8 @@
int nReturn = QCBOR_ERR_HIT_END;
if(pBytes != NULL) {
- pDecodedItem->val.string.ptr = pBytes;
- pDecodedItem->val.string.len = uNumber;
- pDecodedItem->uDataType = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
+ pDecodedItem->val.string = (UsefulBufC){pBytes, uNumber};
+ pDecodedItem->uDataType = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
nReturn = QCBOR_SUCCESS;
}
diff --git a/src/qcbor_encode.c b/src/qcbor_encode.c
index 14e13e8..b40db6c 100644
--- a/src/qcbor_encode.c
+++ b/src/qcbor_encode.c
@@ -193,13 +193,13 @@
/*
Public function for initialization. See header qcbor.h
*/
-void QCBOREncode_Init(QCBOREncodeContext *me, void *pBuf, size_t uBufLen)
+void QCBOREncode_Init(QCBOREncodeContext *me, UsefulBuf Storage)
{
memset(me, 0, sizeof(QCBOREncodeContext));
- if(uBufLen > UINT32_MAX) {
+ if(Storage.len > UINT32_MAX) {
me->uError = QCBOR_ERR_BUFFER_TOO_LARGE;
} else {
- UsefulOutBuf_Init(&(me->OutBuf), pBuf, uBufLen);
+ UsefulOutBuf_Init(&(me->OutBuf), Storage);
Nesting_Init(&(me->nesting));
}
}
@@ -604,8 +604,9 @@
me->uError = QCBOR_ERR_BUFFER_TOO_SMALL;
goto Done;
}
-
- UsefulOutBuf_OutUBuf(&(me->OutBuf), &(pEncodedCBOR->Bytes));
+
+ pEncodedCBOR->Bytes = UsefulOutBuf_OutUBuf(&(me->OutBuf));
+
pEncodedCBOR->uItems = Nesting_GetCount(&(me->nesting));
Done:
diff --git a/test/basic_test.c b/test/basic_test.c
index f1fbce6..e5f510c 100644
--- a/test/basic_test.c
+++ b/test/basic_test.c
@@ -13,10 +13,10 @@
int basic_test_one()
{
- uint8_t buffer[512];
+ MakeUsefulBufOnStack(Storage, 512);
QCBOREncodeContext EC;
- QCBOREncode_Init(&EC, buffer, sizeof(buffer));
+ QCBOREncode_Init(&EC, Storage);
QCBOREncode_AddBool(&EC, true);
@@ -29,7 +29,7 @@
QCBORDecodeContext DC;
QCBORItem Item;
- QCBORDecode_Init(&DC, UsefulBuf_Const(Encoded.Bytes), QCBOR_DECODE_MODE_NORMAL);
+ QCBORDecode_Init(&DC, Encoded.Bytes, QCBOR_DECODE_MODE_NORMAL);
QCBORDecode_GetNext(&DC, &Item);
if(Item.uDataType != QCBOR_TYPE_TRUE) {