new tagging encoding design complete and tested
diff --git a/README.md b/README.md
index e636ad9..34d8614 100644
--- a/README.md
+++ b/README.md
@@ -69,6 +69,9 @@
* Finish cannot be called repeatedly on a partial decode (some tests used this, but it is not really a good thing to use in the first place)
* UsefulOutBuf_OutUBuf changed to work differently
* UsefulOutBuf_Init works differently
+* The "_3" functions are replaced with "_2" functions (the macros that referenced _3, now reference _2 and work the same)
+* There is a new AddTag functon instead of the "_3" functions, making the interface simpler and saving some code
+* QCBOREncode_AddRawSimple_2 is removed (the macros that referenced still exist and work the same)
diff --git a/inc/qcbor.h b/inc/qcbor.h
index 814f129..7d8b138 100644
--- a/inc/qcbor.h
+++ b/inc/qcbor.h
@@ -450,12 +450,12 @@
buffers need only to be valid during the "Add" calls. The
data is copied into the output buf during the "Add" call.
- TODO: remote discussion of tags
- There are several "Add" functions / macros for each type. The one
- with named ending in "_2", for example QCBOREncode_AddInt64_3(),
- takes parameters for labels and tags and is the most powerful.
+ There are several "Add" functions / macros for each type. The
+ main one is named ending in "_2", for example
+ QCBOREncode_AddInt64_2().
Generally it is better to use the macros that only take the
- parameters necessary. For example, QCBOREncode_AddInt64(),
+ parameters necessary what you are adding. For example,
+ QCBOREncode_AddInt64(),
only takes the integer value to add with no labels and tags.
The simplest aggregate type is an array, which is a simple ordered
@@ -474,22 +474,13 @@
Note that when you nest arrays or maps in a map, the nested
array or map has a label.
- As mentioned callers of this API will generally not need tags
- and thus not need the "_3" functions, but they are available
- if need be. There is an IANA registry for new tags that are
+ Usually it is not necessary to add tags explcitly as most
+ tagged types have functions here, but they can be added by
+ calling QCBOREncode_AddTag(). There is an IANA registry for new tags that are
for broad use and standardization as per RFC 7049. It is also
allowed for protocols to make up new tags in the range above 256.
Note that even arrays and maps can be tagged.
- Tags in CBOR are a bit open-ended in particular allowing
- multiple tags per item, and the ability to tag deeply nested maps
- and arrays. Partly this is good as it allows them to be used
- in lots of ways, but also makes a general purpose decoder
- like this more difficult.
-
- This implementation only supports one tag per data item
- during encoding and decoding.
-
Summary Limits of this implementation:
- The entire encoded CBOR must fit into contiguous memory.
- Max size of encoded / decoded CBOR data is UINT32_MAX (4GB).
@@ -502,7 +493,6 @@
- Does not directly support labels in maps other than text strings and ints.
- Does not directly support int labels > INT64_MAX
- Epoch dates limited to INT64_MAX (+/- 292 billion years)
- - Only one tag per data item is supported for tag values > 62
- Tags on labels are ignored
This implementation is intended to run on 32 and 64-bit CPUs. It
@@ -818,7 +808,22 @@
void QCBOREncode_Init(QCBOREncodeContext *pCtx, UsefulBuf Storage);
-/* TODO: add documentation
+
+/**
+ @brief[in] Add an optional tag
+
+ @param[in] pCtx The encoding context to add the integer to.
+ @param[in] uTag The tag to add
+
+ The tag is applied to the next data item added to the encoded
+ output. That data item can be of any major CBOR type.
+
+ Any number of tags can be added to a data item.
+
+ When one of the Add functions is called with either a string or
+ integer label after a call to this function, the output will be
+ re ordered so that the tag comes after the label and tags the
+ value, not the label.
*/
void QCBOREncode_AddTag(QCBOREncodeContext *pCtx,uint64_t uTag);
@@ -930,7 +935,6 @@
@param[in] pCtx The encoding context to add the float to.
@param[in] szLabel The string map label for this integer value.
@param[in] nLabel The integer map label for this integer value.
- @param[in] uTag A CBOR type 6 tag
@param[in] fNum The float to add.
This will truncate the precision of the single precision float to half-precision.
@@ -965,7 +969,6 @@
@param[in] pCtx The encoding context to add the float to.
@param[in] szLabel The string map label for this integer value.
@param[in] nLabel The integer map label for this integer value.
- @param[in] uTag A CBOR type 6 tag
@param[in] fNum The float to add.
This will selectively encode the single-precision floating point number as either
@@ -997,13 +1000,12 @@
QCBOREncode_AddFloatAsSmallest_2((pCtx), NULL, (nLabel), (fNum))
-/*
+/**
@brief Add a dynamically sized floating point number to the encoded output
@param[in] pCtx The encoding context to add the float to.
@param[in] szLabel The string map label for this integer value.
@param[in] nLabel The integer map label for this integer value.
- @param[in] uTag A CBOR type 6 tag
@param[in] dNum The float to add.
This will selectively encode the double-precision floating point number as either
@@ -1029,7 +1031,7 @@
*/
-void QCBOREncode_AddDoubleAsSmallest_2(QCBOREncodeContext *me, const char *szLabel, int64_t nLabel, double dNum);
+void QCBOREncode_AddDoubleAsSmallest_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, double dNum);
#define QCBOREncode_AddDoubleAsSmallest(pCtx, dNum) \
QCBOREncode_AddDoubleAsSmallest_2((pCtx), NULL, QCBOR_NO_INT_LABEL, (dNum))
@@ -1089,8 +1091,15 @@
QCBOREncode_AddDateEpoch_2((pCtx), NULL, (nLabel), (date))
-// TODO: document this
-void QCBOREncode_AddBytes_2(QCBOREncodeContext *me, uint8_t uMajorType, const char *szLabel, int64_t nLabel, UsefulBufC Bytes);
+/*
+ Use QCBOREncode_AddBytes_2() or QCBOREncode_AddBText_2() or
+ QCBOREncode_AddEncoded_2() instead of this. Their inline
+ implementations call this to do their work.
+
+ The code is structured like this with the inline functions
+ to reduce object code.
+ */
+void QCBOREncode_AddBuffer_2(QCBOREncodeContext *me, uint8_t uMajorType, const char *szLabel, int64_t nLabel, UsefulBufC Bytes);
/**
@@ -1100,7 +1109,6 @@
@param[in] pCtx The context to initialize.
@param[in] szLabel The string map label for this integer value.
@param[in] nLabel The integer map label for this integer value.
- @param[in] uTag Optional CBOR data tag or CBOR_TAG_NONE.
@param[in] Bytes Pointer and length of the input data.
Simply adds the bytes to the encoded output and CBOR major type 2.
@@ -1110,21 +1118,26 @@
*/
+static inline void QCBOREncode_AddBytes_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, UsefulBufC Bytes)
+{
+ QCBOREncode_AddBuffer_2(pCtx, CBOR_MAJOR_TYPE_BYTE_STRING, szLabel, nLabel, Bytes);
+}
+
#define QCBOREncode_AddBytes(pCtx, Bytes) \
- QCBOREncode_AddBytes_2((pCtx), CBOR_MAJOR_TYPE_BYTE_STRING, NULL, QCBOR_NO_INT_LABEL, Bytes)
+ QCBOREncode_AddBytes_2((pCtx), NULL, QCBOR_NO_INT_LABEL, Bytes)
#define QCBOREncode_AddBytesToMap(pCtx, szLabel, Bytes) \
- QCBOREncode_AddBytes_2((pCtx), CBOR_MAJOR_TYPE_BYTE_STRING, (szLabel), QCBOR_NO_INT_LABEL, (Bytes))
+ QCBOREncode_AddBytes_2((pCtx), (szLabel), QCBOR_NO_INT_LABEL, (Bytes))
#define QCBOREncode_AddBytesToMapN(pCtx, nLabel, Bytes) \
- QCBOREncode_AddBytes_2((pCtx), CBOR_MAJOR_TYPE_BYTE_STRING, NULL, (nLabel), (Bytes))
+ QCBOREncode_AddBytes_2((pCtx), NULL, (nLabel), (Bytes))
static inline void QCBOREncode_AddBinaryUUID_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, UsefulBufC Bytes)
{
QCBOREncode_AddTag(pCtx, CBOR_TAG_BIN_UUID);
- QCBOREncode_AddBytes_2(pCtx, CBOR_MAJOR_TYPE_BYTE_STRING, szLabel, nLabel, Bytes);
+ QCBOREncode_AddBytes_2(pCtx, szLabel, nLabel, Bytes);
}
@@ -1141,7 +1154,7 @@
static inline void QCBOREncode_AddPositiveBignum_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, UsefulBufC Bytes)
{
QCBOREncode_AddTag(pCtx, CBOR_TAG_POS_BIGNUM);
- QCBOREncode_AddBytes_2(pCtx, CBOR_MAJOR_TYPE_BYTE_STRING, szLabel, nLabel, Bytes);
+ QCBOREncode_AddBytes_2(pCtx, szLabel, nLabel, Bytes);
}
#define QCBOREncode_AddPositiveBignum(pCtx, Bytes) \
@@ -1157,7 +1170,7 @@
static inline void QCBOREncode_AddNegativeBignum_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, UsefulBufC Bytes)
{
QCBOREncode_AddTag(pCtx, CBOR_TAG_NEG_BIGNUM);
- QCBOREncode_AddBytes_2(pCtx, CBOR_MAJOR_TYPE_BYTE_STRING, szLabel, nLabel, Bytes);
+ QCBOREncode_AddBytes_2(pCtx, szLabel, nLabel, Bytes);
}
#define QCBOREncode_AddNegativeBignum(pCtx, Bytes) \
@@ -1178,7 +1191,6 @@
@param[in] pCtx The context to initialize.
@param[in] szLabel The string map label for this integer value.
@param[in] nLabel The integer map label for this integer value.
- @param[in] uTag Optional CBOR data tag or CBOR_TAG_NONE.
@param[in] Bytes Pointer and length of text to add.
The text passed in must be unencoded UTF-8 according to RFC
@@ -1196,21 +1208,24 @@
Error handling is the same as QCBOREncode_AddInt64_2().
*/
+static inline void QCBOREncode_AddText_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, UsefulBufC Bytes)
+{
+ QCBOREncode_AddBuffer_2(pCtx, CBOR_MAJOR_TYPE_TEXT_STRING, szLabel, nLabel, Bytes);
+}
-// TODO: AddText_2?
#define QCBOREncode_AddText(pCtx, Bytes) \
- QCBOREncode_AddBytes_2((pCtx), CBOR_MAJOR_TYPE_TEXT_STRING, NULL, QCBOR_NO_INT_LABEL, (Bytes))
+ QCBOREncode_AddText_2((pCtx), NULL, QCBOR_NO_INT_LABEL, (Bytes))
#define QCBOREncode_AddTextToMap(pCtx, szLabel, Bytes) \
- QCBOREncode_AddBytes_2((pCtx), CBOR_MAJOR_TYPE_TEXT_STRING, (szLabel), QCBOR_NO_INT_LABEL, (Bytes))
+ QCBOREncode_AddText_2((pCtx), (szLabel), QCBOR_NO_INT_LABEL, (Bytes))
#define QCBOREncode_AddTextToMapN(pCtx, nLabel, Bytes) \
- QCBOREncode_AddBytes_2((pCtx), CBOR_MAJOR_TYPE_TEXT_STRING, NULL, (nLabel), (Bytes))
+ QCBOREncode_AddText_2((pCtx), NULL, (nLabel), (Bytes))
inline static void QCBOREncode_AddSZString_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, const char *szString)
{
- QCBOREncode_AddBytes_2(pCtx, CBOR_MAJOR_TYPE_TEXT_STRING, szLabel, nLabel,UsefulBuf_FromSZ(szString));
+ QCBOREncode_AddText_2(pCtx, szLabel, nLabel,UsefulBuf_FromSZ(szString));
}
#define QCBOREncode_AddSZString(pCtx, szString) \
@@ -1228,7 +1243,7 @@
static inline void QCBOREncode_AddURI_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, UsefulBufC Bytes)
{
QCBOREncode_AddTag(pCtx, CBOR_TAG_URI);
- QCBOREncode_AddBytes_2(pCtx, CBOR_MAJOR_TYPE_TEXT_STRING, szLabel, nLabel, Bytes);
+ QCBOREncode_AddText_2(pCtx, szLabel, nLabel, Bytes);
}
#define QCBOREncode_AddURI(pCtx, Bytes) \
@@ -1244,7 +1259,7 @@
static inline void QCBOREncode_AddB64Text_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, UsefulBufC Bytes)
{
QCBOREncode_AddTag(pCtx, CBOR_TAG_B64);
- QCBOREncode_AddBytes_2(pCtx, CBOR_MAJOR_TYPE_TEXT_STRING, szLabel, nLabel, Bytes);
+ QCBOREncode_AddText_2(pCtx, szLabel, nLabel, Bytes);
}
#define QCBOREncode_AddB64Text(pCtx, Bytes) \
@@ -1261,24 +1276,24 @@
static inline void QCBOREncode_AddB64URLText_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, UsefulBufC Bytes)
{
QCBOREncode_AddTag(pCtx, CBOR_TAG_B64URL);
- QCBOREncode_AddBytes_2(pCtx, CBOR_MAJOR_TYPE_TEXT_STRING, szLabel, nLabel, Bytes);
+ QCBOREncode_AddText_2(pCtx, szLabel, nLabel, Bytes);
}
#define QCBOREncode_AddB64URLText(pCtx, Bytes) \
- QCBOREncode_AddB64URLText_2((pCtx), NULL, QCBOR_NO_INT_LABEL, CBOR_TAG_B64URL, (Bytes))
+ QCBOREncode_AddB64URLText_2((pCtx), NULL, QCBOR_NO_INT_LABEL, (Bytes))
#define QCBOREncode_AddB64URLTextToMap(pCtx, szLabel, Bytes) \
- QCBOREncode_AddB64URLText_2((pCtx), (szLabel), QCBOR_NO_INT_LABEL, CBOR_TAG_B64URL, (Bytes))
+ QCBOREncode_AddB64URLText_2((pCtx), (szLabel), QCBOR_NO_INT_LABEL, (Bytes))
#define QCBOREncode_AddB64URLTextToMapN(pCtx, nLabel, Bytes) \
- QCBOREncode_AddB64URLText_2((pCtx), NULL, (nLabel), CBOR_TAG_B64URL, (Bytes))
+ QCBOREncode_AddB64URLText_2((pCtx), NULL, (nLabel), (Bytes))
static inline void QCBOREncode_AddRegex_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, UsefulBufC Bytes)
{
QCBOREncode_AddTag(pCtx, CBOR_TAG_REGEX);
- QCBOREncode_AddBytes_2(pCtx, CBOR_MAJOR_TYPE_TEXT_STRING, szLabel, nLabel, Bytes);
+ QCBOREncode_AddText_2(pCtx, szLabel, nLabel, Bytes);
}
#define QCBOREncode_AddRegex(pCtx, Bytes) \
@@ -1295,7 +1310,7 @@
static inline void QCBOREncode_AddMIMEData_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, UsefulBufC Bytes)
{
QCBOREncode_AddTag(pCtx, CBOR_TAG_MIME);
- QCBOREncode_AddBytes_2(pCtx, CBOR_MAJOR_TYPE_TEXT_STRING, szLabel, nLabel, Bytes);
+ QCBOREncode_AddText_2(pCtx, szLabel, nLabel, Bytes);
}
#define QCBOREncode_AddMIMEData(pCtx, Bytes) \
@@ -1346,6 +1361,15 @@
QCBOREncode_AddDateString_2(pCtx, NULL, (nLabel), (szDate))
+/*
+Use QCBOREncode_AddSimple_2() or QCBOREncode_AddBool_2()
+instead of this. Their inline
+implementations call this to do their work.
+
+The code is structured like this with the inline functions
+to reduce object code.
+ */
+void QCBOREncode_AddType7_2(QCBOREncodeContext *me, const char *szLabel, int64_t nLabel, size_t uSize, uint64_t uNum);
/**
@@ -1362,8 +1386,14 @@
Error handling is the same as QCBOREncode_AddInt64_2().
*/
-void QCBOREncode_AddSimple_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, uint8_t uSimple);
-
+static inline void QCBOREncode_AddSimple_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, uint8_t uSimple)
+{
+ if(uSimple < CBOR_SIMPLEV_FALSE || uSimple > CBOR_SIMPLEV_UNDEF) {
+ pCtx->uError = QCBOR_ERR_BAD_SIMPLE;
+ } else {
+ QCBOREncode_AddType7_2(pCtx, szLabel, nLabel, 0, uSimple);
+ }
+}
#define QCBOREncode_AddSimple(pCtx, uSimple) \
QCBOREncode_AddSimple_2((pCtx), NULL, QCBOR_NO_INT_LABEL, (uSimple))
@@ -1376,7 +1406,6 @@
-
/**
@brief Add a standard boolean
@@ -1389,7 +1418,6 @@
Error handling is the same as QCBOREncode_AddInt64_2().
*/
-
inline static void QCBOREncode_AddBool_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, bool b)
{
uint8_t uSimple = CBOR_SIMPLE_BREAK; // CBOR_SIMPLE_BREAK is invalid here. The point is to cause an error later
@@ -1409,8 +1437,16 @@
-// TODO: document this
-void OpenMapOrArray_2(QCBOREncodeContext *me, uint8_t uMajorType, const char *szLabel, uint64_t nLabel);
+/*
+ Call QCBOREncode_OpenArray_2(), QCBOREncode_OpenMap_2() or
+ QCBOREncode_OpenBstrWrap_2() instead of this. Their inline
+ implementations call this to do their work.
+
+ The code is structured like this with the inline functions
+ to reduce object code.
+ */
+void QCBOREncode_OpenMapOrArray_2(QCBOREncodeContext *me, uint8_t uMajorType, const char *szLabel, uint64_t nLabel);
+
/**
@@ -1459,7 +1495,7 @@
static inline void QCBOREncode_OpenArray_2(QCBOREncodeContext *pCtx, const char *szLabel, uint64_t nLabel)
{
- OpenMapOrArray_2(pCtx, CBOR_MAJOR_TYPE_ARRAY, szLabel, nLabel);
+ QCBOREncode_OpenMapOrArray_2(pCtx, CBOR_MAJOR_TYPE_ARRAY, szLabel, nLabel);
}
#define QCBOREncode_OpenArray(pCtx) \
@@ -1501,10 +1537,9 @@
static inline void QCBOREncode_OpenMap_2(QCBOREncodeContext *pCtx, const char *szLabel, uint64_t nLabel)
{
- OpenMapOrArray_2(pCtx, CBOR_MAJOR_TYPE_MAP, szLabel, nLabel);
+ QCBOREncode_OpenMapOrArray_2(pCtx, CBOR_MAJOR_TYPE_MAP, szLabel, nLabel);
}
-
#define QCBOREncode_OpenMap(pCtx) \
QCBOREncode_OpenMap_2((pCtx), NULL, QCBOR_NO_INT_LABEL)
@@ -1578,7 +1613,7 @@
*/
static inline void QCBOREncode_OpenBstrWrap_2(QCBOREncodeContext *pCtx, const char *szLabel, uint64_t nLabel)
{
- OpenMapOrArray_2(pCtx, CBOR_MAJOR_TYPE_BYTE_STRING, szLabel, nLabel);
+ QCBOREncode_OpenMapOrArray_2(pCtx, CBOR_MAJOR_TYPE_BYTE_STRING, szLabel, nLabel);
}
#define QCBOREncode_BstrWrap(pCtx) \
@@ -1617,7 +1652,7 @@
static inline void QCBOREncode_AddEncodedToMap_2(QCBOREncodeContext *pCtx, const char *szLabel, uint64_t nLabel, UsefulBufC Encoded)
{
- QCBOREncode_AddBytes_2(pCtx, CBOR_MAJOR_NONE_TYPE_RAW, szLabel, nLabel, Encoded);
+ QCBOREncode_AddBuffer_2(pCtx, CBOR_MAJOR_NONE_TYPE_RAW, szLabel, nLabel, Encoded);
}
#define QCBOREncode_AddEncodedToMapN(pCtx, nLabel, Encoded) \
@@ -1630,26 +1665,6 @@
QCBOREncode_AddEncodedToMap_2((pCtx), (szLabel), QCBOR_NO_INT_LABEL, (Encoded))
-/**
-
- @brief Add a simple value
-
- @param[in] pCtx The encoding context to add the simple value to.
- @param[in] szLabel A string label for the bytes to add. NULL if no label.
- @param[in] nLabel The integer map tag / label for this integer value.
- @param[in] uSimple One of CBOR_SIMPLEV_xxx.
-
- There should be no need to use this function directly unless some
- extensions to the CBOR standard are created and put to use. All the defined
- simple types are available via the macros for false...null
- below. Float and double are also simple types and have functions to
- add them above.
-
- Error handling is the same as QCBOREncode_AddInt64_2().
- */
-void QCBOREncode_AddRawSimple_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, uint8_t uSimple);
-
-
/**
Get the encoded CBOR and error status.
diff --git a/src/qcbor_encode.c b/src/qcbor_encode.c
index e1c6387..e8401ca 100644
--- a/src/qcbor_encode.c
+++ b/src/qcbor_encode.c
@@ -196,7 +196,7 @@
error checks in this code if you knew the caller called it
correctly. Maybe someday CDDL or some such language will be able to
generate the code to call this and the calling code would always be
- correct. This could also make automatically size some of the data
+ correct. This could also automatically size some of the data
structures like array/map nesting resulting in some good memory
savings.
*/
@@ -272,7 +272,7 @@
// always generated internally, not by the caller, b) this is for CBOR
// _generation_, not parsing c) a mistake will result in bad CBOR generation,
// not a security vulnerability.
- uMajorType <<= 5; // TODO: make this a constant
+ uMajorType <<= 5;
if(uNumber > 0xffffffff || uMinLen >= 8) {
UsefulOutBuf_InsertByte(&(me->OutBuf), uMajorType + LEN_IS_EIGHT_BYTES, uPos);
@@ -313,7 +313,6 @@
-
/*
Internal function for adding positive and negative integers of all different sizes
*/
@@ -334,29 +333,34 @@
me->uError = Nesting_Increment(&(me->nesting), 1);
}
+
/*
Does the work of adding some bytes to the CBOR output. Works for a
byte and text strings, which are the same in in CBOR though they have
different major types. This is also used to insert raw
pre-encoded CBOR.
*/
-static void AddBytesInternal2(QCBOREncodeContext *me, UsefulBufC Bytes, uint8_t uMajorType, size_t uPos)
+static void AddBufferInternal(QCBOREncodeContext *me, UsefulBufC Bytes, uint8_t uMajorType, size_t uPos)
{
if(Bytes.len >= UINT32_MAX) {
- // This implementation doesn't allow buffers larger than UINT32_MAX. This is
- // primarily because QCBORTrackNesting.pArrays[].uStart is an uint32 rather
- // than size_t to keep the stack usage down. Also it is entirely impractical
- // to create tokens bigger than 4GB in contiguous RAM
+ // This implementation doesn't allow buffers larger than UINT32_MAX.
+ // This is primarily because QCBORTrackNesting.pArrays[].uStart is
+ // an uint32 rather than size_t to keep the stack usage down. Also
+ // it is entirely impractical to create tokens bigger than 4GB in
+ // contiguous RAM
me->uError = QCBOR_ERR_BUFFER_TOO_LARGE;
} else {
if(!me->uError) {
// If it is not Raw CBOR, add the type and the length
- const size_t uPosBeforeInsert = UsefulOutBuf_GetEndPosition(&(me->OutBuf));
if(uMajorType != CBOR_MAJOR_NONE_TYPE_RAW) {
+ const size_t uPosBeforeInsert = UsefulOutBuf_GetEndPosition(&(me->OutBuf));
InsertEncodedTypeAndNumber(me, uMajorType, 0, Bytes.len, uPos);
+ // The increment in uPos is to account for bytes added for
+ // type and number so the buffer being added goes to the
+ // right place
+ uPos += UsefulOutBuf_GetEndPosition(&(me->OutBuf)) - uPosBeforeInsert;
}
- uPos += UsefulOutBuf_GetEndPosition(&(me->OutBuf)) - uPosBeforeInsert;
// Actually add the bytes
UsefulOutBuf_InsertUsefulBuf(&(me->OutBuf), Bytes, uPos);
@@ -384,7 +388,7 @@
if(szLabel) {
const UsefulBufC SZText = UsefulBuf_FromSZ(szLabel);
- AddBytesInternal2(me, SZText, CBOR_MAJOR_TYPE_TEXT_STRING, uPos);
+ AddBufferInternal(me, SZText, CBOR_MAJOR_TYPE_TEXT_STRING, uPos);
} else if (QCBOR_NO_INT_LABEL != nLabel) {
InsertInt64(me, nLabel, uPos);
}
@@ -397,10 +401,10 @@
void QCBOREncode_AddTag(QCBOREncodeContext *me, uint64_t uTag)
{
uint8_t uNestingType = Nesting_GetMajorType(&(me->nesting));
- if(uNestingType == CBOR_MAJOR_TYPE_MAP || uNestingType == CBOR_MAJOR_TYPE_ARRAY) { // TODO: really do this for arrays?
+ if(uNestingType == CBOR_MAJOR_TYPE_MAP || uNestingType == CBOR_MAJOR_TYPE_ARRAY) {
// Remember where the first tag is for this item
// So we can go back and insert the label in front of it.
- // Cast to uint32_t here is OK all sizes are limited to 4GB by other checks
+ // Cast to uint32_t here OK as all inputs are limited to 4GB
const uint32_t uPos = (uint32_t)UsefulOutBuf_GetEndPosition(&(me->OutBuf));
me->uError = Nesting_Increase(&(me->nesting), CBOR_MAJOR_NONE_TAG_LABEL_REORDER, uPos);
}
@@ -409,26 +413,26 @@
}
-
-void QCBOREncode_AddBytes_2(QCBOREncodeContext *me, uint8_t uMajorType, const char *szLabel, int64_t nLabel, UsefulBufC Bytes)
+/*
+ Semi-public interface. Called by inline functions to add text and byte strings
+ and already-encoded CBOR. They are the real public interface, even though this
+ is the main entry point. The code is structured like this to reduce code size.
+ */
+void QCBOREncode_AddBuffer_2(QCBOREncodeContext *me, uint8_t uMajorType, const char *szLabel, int64_t nLabel, UsefulBufC Bytes)
{
AddLabel(me, szLabel, nLabel);
if(!me->uError) {
- AddBytesInternal2(me, Bytes, uMajorType, UsefulOutBuf_GetEndPosition(&(me->OutBuf)));
+ AddBufferInternal(me, Bytes, uMajorType, UsefulOutBuf_GetEndPosition(&(me->OutBuf)));
}
}
-
/*
- TODO: fix docu
- Internal function common to opening an array or a map
-
- QCBOR_MAX_ARRAY_NESTING is the number of times Open can be called
- successfully. Call it one more time gives an error.
-
+ Semi-public interfaced. Called by inline functions to open arrays, maps and
+ bstr wrapped CBOR. They are the real public interface, even though this is the
+ main entry point. This code is structured like this to reduce code size.
*/
-void OpenMapOrArray_2(QCBOREncodeContext *me, uint8_t uMajorType, const char *szLabel, uint64_t nLabel)
+void QCBOREncode_OpenMapOrArray_2(QCBOREncodeContext *me, uint8_t uMajorType, const char *szLabel, uint64_t nLabel)
{
AddLabel(me, szLabel, nLabel);
@@ -448,7 +452,6 @@
/*
Public functions for closing arrays and maps. See header qcbor.h
*/
-
void QCBOREncode_Close(QCBOREncodeContext *me, uint8_t uMajorType, UsefulBufC *pWrappedCBOR)
{
if(!me->uError) {
@@ -457,22 +460,22 @@
} else if( Nesting_GetMajorType(&(me->nesting)) != uMajorType) {
me->uError = QCBOR_ERR_CLOSE_MISMATCH;
} else {
- const uint32_t uInsertPosition = Nesting_GetStartPos(&(me->nesting));
- // When the array, map or bstr wrap was started, nothing was done except
- // note the position of the start of it. This code goes back and inserts
- // the actual CBOR array, map or bstr and its length. That means all the
- // data that is in the array, map or wrapped needs to be slid to the
- // right. This is done by UsefulOutBuf's insert function that is called
- // from inside InsertEncodedTypeAndNumber()
+ // When the array, map or bstr wrap was started, nothing was done
+ // except note the position of the start of it. This code goes back
+ // and inserts the actual CBOR array, map or bstr and its length.
+ // That means all the data that is in the array, map or wrapped
+ // needs to be slid to the right. This is done by UsefulOutBuf's
+ // insert function that is called from inside
+ // InsertEncodedTypeAndNumber()
+ const size_t uInsertPosition = Nesting_GetStartPos(&(me->nesting));
+ const size_t uEndPosition = UsefulOutBuf_GetEndPosition(&(me->OutBuf));
+ // This can't go negative because the UsefulOutBuf always only grows
+ // and never shrinks. UsefulOutBut itself also has defenses such that
+ // it won't write were it should not even if given hostile input lengths
+ const size_t uLenOfEncodedMapOrArray = uEndPosition - uInsertPosition;
- // Cast from size_t to uin32_t is safe because the UsefulOutBuf
- // size is limited to UINT32_MAX in QCBOR_Init().
- // TODO: can these be size_t? Check them for over/underflow
- const uint32_t uEndPosition = (uint32_t)UsefulOutBuf_GetEndPosition(&(me->OutBuf));
- const uint32_t uLenOfEncodedMapOrArray = uEndPosition - uInsertPosition;
-
- // Length is number of bytes for a bstr and number of items for map & array
- const uint32_t uLength = uMajorType == CBOR_MAJOR_TYPE_BYTE_STRING ?
+ // Length is number of bytes for a bstr and number of items a for map & array
+ const size_t uLength = uMajorType == CBOR_MAJOR_TYPE_BYTE_STRING ?
uLenOfEncodedMapOrArray : Nesting_GetCount(&(me->nesting));
// Actually insert
@@ -489,7 +492,7 @@
// InsertEncodedTypeAndNumber() call that slides data to the right.
if(pWrappedCBOR) {
UsefulBufC PartialResult = UsefulOutBuf_OutUBuf(&(me->OutBuf));
- uint32_t uBstrLen = (uint32_t)UsefulOutBuf_GetEndPosition(&(me->OutBuf)) - uEndPosition;
+ size_t uBstrLen = UsefulOutBuf_GetEndPosition(&(me->OutBuf)) - uEndPosition;
*pWrappedCBOR = UsefulBuf_Tail(PartialResult, uInsertPosition+uBstrLen);
}
Nesting_Decrease(&(me->nesting));
@@ -498,11 +501,9 @@
}
-
/*
Public functions for adding integers. See header qcbor.h
*/
-
void QCBOREncode_AddUInt64_2(QCBOREncodeContext *me, const char *szLabel, int64_t nLabel, uint64_t uNum)
{
AddLabel(me, szLabel, nLabel);
@@ -512,18 +513,25 @@
}
}
+
+/*
+ Public functions for adding integers. See header qcbor.h
+ */
void QCBOREncode_AddInt64_2(QCBOREncodeContext *me, const char *szLabel, int64_t nLabel, int64_t nNum)
{
AddLabel(me, szLabel, nLabel);
if(!me->uError) {
+ // Cast is OK here because the output buffer is limited to 4GB in Init().
InsertInt64(me, nNum, (uint32_t)UsefulOutBuf_GetEndPosition(&(me->OutBuf)));
}
}
-
-
/*
+ Semi-public interfaced. Called by inline functions to add simple and float
+ types. They are the real public interface, even though this is the
+ main entry point. This code is structured like this to reduce code size.
+
Common code for adding floats and doubles and simple types like true and false
One way to look at simple values is that they are:
@@ -537,15 +545,18 @@
- additional integer 31 is a "break"
- additional integers 32-255 are unassigned and could be used in an update to CBOR
*/
-static void AddSimpleInternal(QCBOREncodeContext *me, const char *szLabel, int64_t nLabel, size_t uSize, uint64_t uNum)
+void QCBOREncode_AddType7_2(QCBOREncodeContext *me, const char *szLabel, int64_t nLabel, size_t uSize, uint64_t uNum)
{
AddLabel(me, szLabel, nLabel);
if(!me->uError) {
// This function call takes care of endian swapping for the float / double
InsertEncodedTypeAndNumber(me,
- CBOR_MAJOR_TYPE_SIMPLE, // The major type for floats and doubles
- uSize, // min size / tells encoder to do it right
- uNum, // Bytes of the floating point number as a uint
+ CBOR_MAJOR_TYPE_SIMPLE, // The major type for
+ // floats and doubles
+ uSize, // min size / tells
+ // encoder to do it right
+ uNum, // Bytes of the floating
+ // point number as a uint
UsefulOutBuf_GetEndPosition(&(me->OutBuf))); // end position for append
me->uError = Nesting_Increment(&(me->nesting), 1);
@@ -554,67 +565,34 @@
/*
- Public function for adding simple values. See header qcbor.h
- */
-void QCBOREncode_AddRawSimple_2(QCBOREncodeContext *me, const char *szLabel, int64_t nLabel, uint8_t uSimple)
-{
- AddSimpleInternal(me, szLabel, nLabel, 0, uSimple);
-}
-
-
-/*
- Public function for adding simple values. See header qcbor.h
- */
-void QCBOREncode_AddSimple_2(QCBOREncodeContext *me, const char *szLabel, int64_t nLabel, uint8_t uSimple)
-{
- if(uSimple < CBOR_SIMPLEV_FALSE || uSimple > CBOR_SIMPLEV_UNDEF) {
- me->uError = QCBOR_ERR_BAD_SIMPLE;
- } else {
- QCBOREncode_AddRawSimple_2(me, szLabel, nLabel, uSimple);
- }
-}
-
-
-/*
Public functions for floating point numbers. See header qcbor.h
*/
void QCBOREncode_AddFloat_2(QCBOREncodeContext *me, const char *szLabel, int64_t nLabel, float fNum)
-{
- // Convert the *type* of the data from a float to a uint so the
- // standard integer encoding can work. This takes advantage
- // of CBOR's indicator for a float being the same as for a 4
- // byte integer too.
- const float *pfNum = &fNum;
- const uint32_t uNum = *(uint32_t *)pfNum;
-
- AddSimpleInternal(me, szLabel, nLabel, sizeof(float), uNum);
+{
+ QCBOREncode_AddType7_2(me, szLabel, nLabel, sizeof(float), UsefulBufUtil_CopyFloatToUint32(fNum));
}
void QCBOREncode_AddDouble_2(QCBOREncodeContext *me, const char *szLabel, int64_t nLabel, double dNum)
{
- // see how it is done for floats above
- const double *pdNum = &dNum;
- const uint64_t uNum = *(uint64_t *)pdNum;
-
- AddSimpleInternal(me, szLabel, nLabel, sizeof(double), uNum);
+ QCBOREncode_AddType7_2(me, szLabel, nLabel, sizeof(double), UsefulBufUtil_CopyDoubleToUint64(dNum));
}
void QCBOREncode_AddFloatAsHalf_2(QCBOREncodeContext *me, const char *szLabel, int64_t nLabel, float fNum)
{
- AddSimpleInternal(me, szLabel, nLabel, sizeof(uint16_t), IEEE754_FloatToHalf(fNum));
+ QCBOREncode_AddType7_2(me, szLabel, nLabel, sizeof(uint16_t), IEEE754_FloatToHalf(fNum));
}
static void QCBOREncode_AddFUnionAsSmallest_2(QCBOREncodeContext *me, const char *szLabel, int64_t nLabel, IEEE754_union uNum)
{
switch(uNum.uTag) {
case IEEE754_UNION_IS_HALF:
- AddSimpleInternal(me, szLabel, nLabel, sizeof(uint16_t), uNum.u16);
+ QCBOREncode_AddType7_2(me, szLabel, nLabel, sizeof(uint16_t), uNum.u16);
break;
case IEEE754_UNION_IS_SINGLE:
- AddSimpleInternal(me, szLabel, nLabel, sizeof(uint32_t), uNum.u32);
+ QCBOREncode_AddType7_2(me, szLabel, nLabel, sizeof(uint32_t), uNum.u32);
break;
case IEEE754_UNION_IS_DOUBLE:
- AddSimpleInternal(me, szLabel, nLabel, sizeof(uint64_t), uNum.u64);
+ QCBOREncode_AddType7_2(me, szLabel, nLabel, sizeof(uint64_t), uNum.u64);
break;
}
}
@@ -631,6 +609,7 @@
+
/*
Public functions to finish and get the encoded result. See header qcbor.h
*/
@@ -646,10 +625,11 @@
if(UsefulOutBuf_GetError(&(me->OutBuf))) {
// Stuff didn't fit in the buffer.
- // This check catches this condition for all the appends and inserts so checks aren't needed
- // when the appends and inserts are performed. And of course UsefulBuf will never
- // overrun the input buffer given to it. No complex analysis of the error handling
- // in this file is needed to know that is true. Just read the UsefulBuf code.
+ // This check catches this condition for all the appends and inserts
+ // so checks aren't needed when the appends and inserts are performed.
+ // And of course UsefulBuf will never overrun the input buffer given
+ // to it. No complex analysis of the error handling in this file is
+ // needed to know that is true. Just read the UsefulBuf code.
me->uError = QCBOR_ERR_BUFFER_TOO_SMALL;
goto Done;
}
diff --git a/test/qcbor_encode_tests.c b/test/qcbor_encode_tests.c
index 77a8a6e..598e775 100644
--- a/test/qcbor_encode_tests.c
+++ b/test/qcbor_encode_tests.c
@@ -550,7 +550,7 @@
// binary blobs in maps
QCBOREncode_OpenMap(&ECtx);
QCBOREncode_AddTag(&ECtx, 100000);
- QCBOREncode_AddBytes_2(&ECtx, CBOR_MAJOR_TYPE_BYTE_STRING, "binbin", QCBOR_NO_INT_LABEL, ((UsefulBufC) {(uint8_t []){0x00}, 1}));
+ QCBOREncode_AddBytes_2(&ECtx, "binbin", QCBOR_NO_INT_LABEL, ((UsefulBufC) {(uint8_t []){0x00}, 1}));
QCBOREncode_AddBytesToMap(&ECtx, "blabel", ((UsefulBufC){(uint8_t []){0x01, 0x02, 0x03}, 3}));
QCBOREncode_AddBytesToMapN(&ECtx, 0, ((UsefulBufC){(uint8_t []){0x04, 0x02, 0x03, 0xfe}, 4}));
QCBOREncode_CloseMap(&ECtx);
@@ -627,14 +627,14 @@
// Extended simple values (these are not standard...)
QCBOREncode_OpenMap(&ECtx);
QCBOREncode_AddTag(&ECtx, 88);
- QCBOREncode_AddRawSimple_2(&ECtx, "s1", QCBOR_NO_INT_LABEL, 255);
- QCBOREncode_AddRawSimple_2(&ECtx, "s2", QCBOR_NO_INT_LABEL, 0);
+ QCBOREncode_AddType7_2(&ECtx, "s1", QCBOR_NO_INT_LABEL, 0, 255);
+ QCBOREncode_AddType7_2(&ECtx, "s2", QCBOR_NO_INT_LABEL, 0, 0);
QCBOREncode_AddTag(&ECtx, 88);
- QCBOREncode_AddRawSimple_2(&ECtx, "s3", QCBOR_NO_INT_LABEL, 33);
+ QCBOREncode_AddType7_2(&ECtx, "s3", QCBOR_NO_INT_LABEL, 0, 33);
QCBOREncode_AddTag(&ECtx, 88);
- QCBOREncode_AddRawSimple_2(&ECtx, NULL, 88378374, 255);
+ QCBOREncode_AddType7_2(&ECtx, NULL, 88378374, 0, 255);
QCBOREncode_AddTag(&ECtx, 88);
- QCBOREncode_AddRawSimple_2(&ECtx, NULL, 89, 19);
+ QCBOREncode_AddType7_2(&ECtx, NULL, 89, 0, 19);
QCBOREncode_CloseMap(&ECtx);