Big simplification and cleanup of example (#94)
Removed the decoding example that are not spiffy decode so the whole example is much cleaner and easier to look at
diff --git a/example.c b/example.c
index 5ec3f2f..4921e13 100644
--- a/example.c
+++ b/example.c
@@ -1,7 +1,7 @@
/* =========================================================================
example.c -- Example code for QCBOR
- Copyright (c) 2020, Laurence Lundblade. All rights reserved.
+ Copyright (c) 2020-2021, Laurence Lundblade. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
@@ -17,11 +17,20 @@
#include "qcbor/qcbor_spiffy_decode.h"
+/**
+ * This is a simple example of encoding and decoding some CBOR from
+ * and to a C structure.
+ *
+ * This also includes a comparison between the original structure
+ * and the one decoded from the CBOR to confirm correctness.
+ */
+
+
#define MAX_CYLINDERS 16
/**
- The data structure representing a car engine that is encoded and
- decoded in this example.
+ * The data structure representing a car engine that is encoded and
+ * decoded in this example.
*/
typedef struct
{
@@ -32,15 +41,15 @@
int64_t uNumCylinders;
bool bTurboCharged;
struct {
- double uMeasuredCompression;
+ double dMeasuredCompression;
} cylinders[MAX_CYLINDERS];
} CarEngine;
/**
- @brief Initialize the Engine data structure with values to encode/decode.
-
- @param[out] pE The Engine structure to fill in
+ * @brief Initialize the Engine data structure with values to encode.
+ *
+ * @param[out] pE The Engine structure to fill in
*/
void EngineInit(CarEngine *pE)
{
@@ -51,88 +60,91 @@
pE->uNumCylinders = 6;
pE->bTurboCharged = false;
- pE->cylinders[0].uMeasuredCompression = 9.0;
- pE->cylinders[1].uMeasuredCompression = 9.2;
- pE->cylinders[2].uMeasuredCompression = 8.9;
- pE->cylinders[3].uMeasuredCompression = 8.9;
- pE->cylinders[4].uMeasuredCompression = 9.1;
- pE->cylinders[5].uMeasuredCompression = 9.0;
+ pE->cylinders[0].dMeasuredCompression = 9.0;
+ pE->cylinders[1].dMeasuredCompression = 9.2;
+ pE->cylinders[2].dMeasuredCompression = 8.9;
+ pE->cylinders[3].dMeasuredCompression = 8.9;
+ pE->cylinders[4].dMeasuredCompression = 9.1;
+ pE->cylinders[5].dMeasuredCompression = 9.0;
}
/**
- @brief Compare two Engine structure for equality.
-
- @param[in] pE1 First Engine to compare.
- @param[in] pE2 Second Engine to compare.
-
- @retval Return @c true if the two Engine data structures are exactly the
- same.
+ * @brief Compare two Engine structure for equality.
+ *
+ * @param[in] pE1 First Engine to compare.
+ * @param[in] pE2 Second Engine to compare.
+ *
+ * @retval Return @c true if the two Engine data structures are exactly the
+ * same.
*/
-bool EngineCompare(CarEngine *pE1, CarEngine *pE2)
+static bool EngineCompare(const CarEngine *pE1, const CarEngine *pE2)
{
- if(pE1->uNumCylinders != pE2->uNumCylinders) {
- return false;
- }
- if(pE1->bTurboCharged != pE2->bTurboCharged) {
- return false;
- }
- if(pE1->uDisplacement != pE2->uDisplacement) {
- return false;
- }
- if(pE1->uHorsePower != pE2->uHorsePower) {
- return false;
- }
- if(pE1->dDesignedCompresion != pE2->dDesignedCompresion) {
- return false;
- }
- for(int64_t i = 0; i < pE2->uNumCylinders; i++) {
- if(pE1->cylinders[i].uMeasuredCompression !=
- pE2->cylinders[i].uMeasuredCompression) {
- return false;
- }
- }
+ if(pE1->uNumCylinders != pE2->uNumCylinders) {
+ return false;
+ }
+ if(pE1->bTurboCharged != pE2->bTurboCharged) {
+ return false;
+ }
+ if(pE1->uDisplacement != pE2->uDisplacement) {
+ return false;
+ }
+ if(pE1->uHorsePower != pE2->uHorsePower) {
+ return false;
+ }
+ if(pE1->dDesignedCompresion != pE2->dDesignedCompresion) {
+ return false;
+ }
+ for(int64_t i = 0; i < pE2->uNumCylinders; i++) {
+ if(pE1->cylinders[i].dMeasuredCompression !=
+ pE2->cylinders[i].dMeasuredCompression) {
+ return false;
+ }
+ }
- if(UsefulBuf_Compare(pE1->Manufacturer, pE2->Manufacturer)) {
- return false;
- }
+ if(UsefulBuf_Compare(pE1->Manufacturer, pE2->Manufacturer)) {
+ return false;
+ }
return true;
}
-#ifndef EXAMPLE_DISABLE_DEFINITE_LENGTH_ENCODE
/**
- @brief Encode an initialized Engine data structure in CBOR.
-
- @param[in] pEngine The data structure to encode.
- @param[in] Buffer Pointer and length of buffer to output to.
-
- @return The pointer and length of the encoded CBOR or
- @ref NULLUsefulBufC on error.
-
- This is a simple CBOR encoding example. It outputs the Engine data
- structure as a map of label-value pairs as well as an array of
- floating point values.
-
- @c Buffer must be big enough to hold the output. If it is not @ref
- NULLUsefulBufC will be returned. @ref @ref NULLUsefulBufC will be
- returned for any other encoding errors.
-
- This encoding will use definite CBOR lengths. Definite lengths are
- preferred in CBOR. See EncodeEngineIndefinteLen() that encodes using
- indefinite lengths.
+ * @brief Encode an initialized CarEngine data structure in CBOR.
+ *
+ * @param[in] pEngine The data structure to encode.
+ * @param[in] Buffer Pointer and length of buffer to output to.
+ *
+ * @return The pointer and length of the encoded CBOR or
+ * @ref NULLUsefulBufC on error.
+ *
+ * This encodes the input structure \c pEngine as a CBOR map of
+ * label-value pairs. An array of float is one of the items in the
+ * map.
+ *
+ * This uses the UsefulBuf convention of passing in a non-const empty
+ * buffer to be filled in and returning a filled in const buffer. The
+ * buffer to write into is given as a pointer and length in a
+ * UsefulBuf. The buffer returned with the encoded CBOR is a
+ * UsefulBufC also a pointer and length. In this implementation the
+ * pointer to the returned data is exactly the same as that of the
+ * empty buffer. The returned length will be smaller than or equal to
+ * that of the empty buffer. This gives correct const-ness for the
+ * buffer passed in and the data returned.
+ *
+ * @c Buffer must be big enough to hold the output. If it is not @ref
+ * NULLUsefulBufC will be returned. @ref NULLUsefulBufC will be
+ * returned for any other encoding errors.
*/
UsefulBufC EncodeEngineDefiniteLength(const CarEngine *pEngine, UsefulBuf Buffer)
{
- /* Initialize the encoder with the buffer big enough to hold the
- expected output. If it is too small, QCBOREncode_Finish() will
- return an error. */
+ /* Set up the encoding context with the output buffer */
QCBOREncodeContext EncodeCtx;
QCBOREncode_Init(&EncodeCtx, Buffer);
/* Proceed to output all the items, letting the internal error
- tracking do its work. */
+ * tracking do its work */
QCBOREncode_OpenMap(&EncodeCtx);
QCBOREncode_AddTextToMap(&EncodeCtx, "Manufacturer", pEngine->Manufacturer);
QCBOREncode_AddInt64ToMap(&EncodeCtx, "NumCylinders", pEngine->uNumCylinders);
@@ -141,14 +153,15 @@
QCBOREncode_AddDoubleToMap(&EncodeCtx, "DesignedCompression", pEngine->dDesignedCompresion);
QCBOREncode_OpenArrayInMap(&EncodeCtx, "Cylinders");
for(int64_t i = 0 ; i < pEngine->uNumCylinders; i++) {
- QCBOREncode_AddDouble(&EncodeCtx, pEngine->cylinders[i].uMeasuredCompression);
+ QCBOREncode_AddDouble(&EncodeCtx,
+ pEngine->cylinders[i].dMeasuredCompression);
}
QCBOREncode_CloseArray(&EncodeCtx);
QCBOREncode_AddBoolToMap(&EncodeCtx, "Turbo", pEngine->bTurboCharged);
QCBOREncode_CloseMap(&EncodeCtx);
/* Get the pointer and length of the encoded output. If there was
- any error it will be returned here. */
+ * any encoding error, it will be returned here */
UsefulBufC EncodedCBOR;
QCBORError uErr;
uErr = QCBOREncode_Finish(&EncodeCtx, &EncodedCBOR);
@@ -158,72 +171,10 @@
return EncodedCBOR;
}
}
-#endif /* EXAMPLE_DISABLE_DEFINITE_LENGTH_ENCODE */
-
-
-
-
-#ifndef EXAMPLE_DISABLE_INDEFINITE_LENGTH_ENCODE_ENCODE
-/**
- @brief Encode an initialized Engine data structure using indefinite lengths.
-
- @param[in] pEngine The data structure to encode.
- @param[in] Buffer Pointer and length of buffer to output to.
-
- @return The pointer and length of the encoded CBOR or
- @ref NULLUsefulBufC on error.
-
- This is virtually the same as EncodeEngineDefiniteLength(). The
- encoded CBOR is slightly different as the map and array use
- indefinite lengths, rather than definite lengths.
-
- A definite length array is encoded as an integer indicating the
- number of items in it. An indefinite length array is encoded as an
- opening byte, the items in it and a "break" byte to end
- it. Indefinite length arrays and maps are easier to encode, but
- harder to decode.
-
- The advantage of this implementation is that the encoding side will
- be a little less object code. (Eventually QCBOR will an ifdef to
- disable definite length encoding and the object code will be even
- smaller). However, note that the encoding implementation for a
- protocol is just about always much smaller than the decoding
- implementation and that code savings for use of indefinite lengths is
- relatively small.
- */
-UsefulBufC EncodeEngineIndefinteLen(const CarEngine *pEngine, UsefulBuf Buffer)
-{
- QCBOREncodeContext EncodeCtx;
-
- QCBOREncode_Init(&EncodeCtx, Buffer);
- QCBOREncode_OpenMapIndefiniteLength(&EncodeCtx);
- QCBOREncode_AddTextToMap(&EncodeCtx, "Manufacturer", pEngine->Manufacturer);
- QCBOREncode_AddInt64ToMap(&EncodeCtx, "Displacement", pEngine->uDisplacement);
- QCBOREncode_AddInt64ToMap(&EncodeCtx, "Horsepower", pEngine->uHorsePower);
- QCBOREncode_AddDoubleToMap(&EncodeCtx, "DesignedCompression", pEngine->dDesignedCompresion);
- QCBOREncode_AddInt64ToMap(&EncodeCtx, "NumCylinders", pEngine->uNumCylinders);
- QCBOREncode_OpenArrayIndefiniteLengthInMap(&EncodeCtx, "Cylinders");
- for(int64_t i = 0 ; i < pEngine->uNumCylinders; i++) {
- QCBOREncode_AddDouble(&EncodeCtx, pEngine->cylinders[i].uMeasuredCompression);
- }
- QCBOREncode_CloseArrayIndefiniteLength(&EncodeCtx);
- QCBOREncode_AddBoolToMap(&EncodeCtx, "Turbo", pEngine->bTurboCharged);
- QCBOREncode_CloseMapIndefiniteLength(&EncodeCtx);
-
- UsefulBufC EncodedCBOR;
- QCBORError uErr;
- uErr = QCBOREncode_Finish(&EncodeCtx, &EncodedCBOR);
- if(uErr != QCBOR_SUCCESS) {
- return NULLUsefulBufC;
- } else {
- return EncodedCBOR;
- }
-}
-#endif /* EXAMPLE_DISABLE_INDEFINITE_LENGTH_ENCODE */
/**
- Error results when decoding an Engine data structure.
+ * Error results when decoding an Engine data structure.
*/
typedef enum {
EngineSuccess,
@@ -235,9 +186,9 @@
/**
- Convert @ref QCBORError to @ref EngineDecodeErrors.
+ * Convert @ref QCBORError to @ref EngineDecodeErrors.
*/
-EngineDecodeErrors ConvertError(QCBORError uErr)
+static EngineDecodeErrors ConvertError(QCBORError uErr)
{
EngineDecodeErrors uReturn;
@@ -260,39 +211,40 @@
}
-#ifndef EXAMPLE_DISABLE_SPIFFY_DECODE
/**
- @brief Simplest engine decode using spiffy decode features.
-
- @param[in] EncodedEngine Pointer and length of CBOR-encoded engine.
- @param[out] pE The structure filled in from the decoding.
-
- @return The decode error or success.
-
- This decodes the CBOR into the engine structure.
-
- As QCBOR automatically supports both definite and indefinite maps and
- arrays, this will decode either.
-
- This uses QCBOR's spiffy decode, so the implementation is simplest
- and closely parallels the encode implementation in
- EncodeEngineDefiniteLength().
-
- See two other ways to implement decoding in
- DecodeEngineSpiffyFaster() and DecodeEngineBasic().
-
- This version of the decoder has the simplest implementation, but
- pulls in more code from the QCBOR library. This version uses the
- most CPU cycles because it scans the all the CBOR each time a data
- item is decoded. The CPU cycles used for a data structure as small as
- this is probably insignificant. CPU use for this style of decode is
- probably only a factor on slow CPUs with big CBOR inputs.
+ * @brief Simplest engine decode using spiffy decode features.
+ *
+ * @param[in] EncodedEngine Pointer and length of CBOR-encoded engine.
+ * @param[out] pE The structure filled in from the decoding.
+ *
+ * @return The decode error or success.
+ *
+ * This decodes the CBOR into the engine structure.
+ *
+ * As QCBOR automatically supports both definite and indefinite maps
+ * and arrays, this will decode either.
+ *
+ * This uses QCBOR's spiffy decode functions, so the implementation is
+ * simple and closely parallels the encode implementation in
+ * EncodeEngineDefiniteLength().
+ *
+ * Another way to decode without using spiffy decode functions is to
+ * use QCBORDecode_GetNext() to traverse the whole tree. This
+ * requires a more complex implementation, but is faster and will pull
+ * in less code from the CBOR library. The speed advantage is likely
+ * of consequence when decoding much much larger CBOR on slow small
+ * CPUs.
+ *
+ * A middle way is to use the spiffy decode
+ * QCBORDecode_GetItemsInMap(). The implementation has middle
+ * complexity and uses less CPU.
*/
EngineDecodeErrors DecodeEngineSpiffy(UsefulBufC EncodedEngine, CarEngine *pE)
{
- QCBORError uErr;
+ QCBORError uErr;
QCBORDecodeContext DecodeCtx;
+ /* Let QCBORDecode internal error tracking do its work. */
QCBORDecode_Init(&DecodeCtx, EncodedEngine, QCBOR_DECODE_MODE_NORMAL);
QCBORDecode_EnterMap(&DecodeCtx, NULL);
QCBORDecode_GetTextStringInMapSZ(&DecodeCtx, "Manufacturer", &(pE->Manufacturer));
@@ -303,9 +255,9 @@
QCBORDecode_GetInt64InMapSZ(&DecodeCtx, "NumCylinders", &(pE->uNumCylinders));
- /* Must check error before referencing pE->uNumCylinders to be
- sure it is valid. If any of the above errored, it won't be
- valid. */
+ /* Check the internal tracked error now before going on to
+ * reference any of the decoded data, particularly
+ * pE->uNumCylinders */
uErr = QCBORDecode_GetError(&DecodeCtx);
if(uErr != QCBOR_SUCCESS) {
goto Done;
@@ -317,357 +269,33 @@
QCBORDecode_EnterArrayFromMapSZ(&DecodeCtx, "Cylinders");
for(int64_t i = 0; i < pE->uNumCylinders; i++) {
- QCBORDecode_GetDouble(&DecodeCtx, &(pE->cylinders[i].uMeasuredCompression));
+ QCBORDecode_GetDouble(&DecodeCtx,
+ &(pE->cylinders[i].dMeasuredCompression));
}
QCBORDecode_ExitArray(&DecodeCtx);
QCBORDecode_ExitMap(&DecodeCtx);
- /* Catch the remainder of errors here */
+ /* Catch further decoding error here */
uErr = QCBORDecode_Finish(&DecodeCtx);
Done:
return ConvertError(uErr);
}
-#endif /* EXAMPLE_DISABLE_SPIFFY_DECODE */
-
-
-
-#ifndef EXAMPLE_DISABLE_SPIFFY_DECODE_FAST
-/**
- @brief Decode an Engine structure with the faster spiffy decode features.
-
- @param[in] EncodedEngine Pointer and length of CBOR-encoded engine.
- @param[out] pE The structure filled in from the decoding.
-
- @return The decode error or success.
-
- This decodes the same as DecodeEngineSpiffy(), but uses different
- spiffy decode features.
-
- This version uses QCBORDecode_GetItemsInMap() which uses less CPU
- cycles because all the items except the array are pulled out of the
- map in one pass, rather than having to decode the whole map for each
- decoded item. This also pulls in less object code from the QCBOR
- library.
-
- See also DecodeEngineAdvanced() and DecodeEngineBasic().
-*/
-EngineDecodeErrors DecodeEngineSpiffyFaster(UsefulBufC EncodedEngine, CarEngine *pE)
-{
- QCBORError uErr;
- QCBORDecodeContext DecodeCtx;
-
- QCBORDecode_Init(&DecodeCtx, EncodedEngine, QCBOR_DECODE_MODE_NORMAL);
- QCBORDecode_EnterMap(&DecodeCtx, NULL);
-
- QCBORItem EngineItems[7];
- EngineItems[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
- EngineItems[0].label.string = UsefulBuf_FROM_SZ_LITERAL("Manufacturer");
- EngineItems[0].uDataType = QCBOR_TYPE_TEXT_STRING;
-
- EngineItems[1].uLabelType = QCBOR_TYPE_TEXT_STRING;
- EngineItems[1].label.string = UsefulBuf_FROM_SZ_LITERAL("Displacement");
- EngineItems[1].uDataType = QCBOR_TYPE_INT64;
-
- EngineItems[2].uLabelType = QCBOR_TYPE_TEXT_STRING;
- EngineItems[2].label.string = UsefulBuf_FROM_SZ_LITERAL("Horsepower");
- EngineItems[2].uDataType = QCBOR_TYPE_INT64;
-
- EngineItems[3].uLabelType = QCBOR_TYPE_TEXT_STRING;
- EngineItems[3].label.string = UsefulBuf_FROM_SZ_LITERAL("DesignedCompression");
- EngineItems[3].uDataType = QCBOR_TYPE_DOUBLE;
-
- EngineItems[4].uLabelType = QCBOR_TYPE_TEXT_STRING;
- EngineItems[4].label.string = UsefulBuf_FROM_SZ_LITERAL("Turbo");
- EngineItems[4].uDataType = QCBOR_TYPE_ANY;
-
- EngineItems[5].uLabelType = QCBOR_TYPE_TEXT_STRING;
- EngineItems[5].label.string = UsefulBuf_FROM_SZ_LITERAL("NumCylinders");
- EngineItems[5].uDataType = QCBOR_TYPE_INT64;
-
- EngineItems[6].uLabelType = QCBOR_TYPE_NONE;
-
- QCBORDecode_GetItemsInMap(&DecodeCtx, EngineItems);
- uErr = QCBORDecode_GetError(&DecodeCtx);
- if(uErr != QCBOR_SUCCESS) {
- goto Done;
- }
-
- pE->Manufacturer = EngineItems[0].val.string;
- pE->uDisplacement = EngineItems[1].val.int64;
- pE->uHorsePower = EngineItems[2].val.int64;
- pE->dDesignedCompresion = EngineItems[3].val.dfnum;
- pE->uNumCylinders = EngineItems[5].val.int64;
-
- if(EngineItems[4].uDataType == QCBOR_TYPE_TRUE) {
- pE->bTurboCharged = true;
- } else if(EngineItems[4].uDataType == QCBOR_TYPE_FALSE) {
- pE->bTurboCharged = false;
- } else {
- return EngineProtocolerror;
- }
-
-
- /* Must check error before referencing pE->uNumCylinders to be
- sure it is valid. If any of the above errored, it won't be
- valid. */
- uErr = QCBORDecode_GetError(&DecodeCtx);
- if(uErr != QCBOR_SUCCESS) {
- goto Done;
- }
-
- if(pE->uNumCylinders > MAX_CYLINDERS) {
- return TooManyCylinders;
- }
-
- QCBORDecode_EnterArrayFromMapSZ(&DecodeCtx, "Cylinders");
- for(int64_t i = 0; i < pE->uNumCylinders; i++) {
- QCBORDecode_GetDouble(&DecodeCtx, &(pE->cylinders[i].uMeasuredCompression));
- }
- QCBORDecode_ExitArray(&DecodeCtx);
- QCBORDecode_ExitMap(&DecodeCtx);
-
- /* Catch the remainder of errors here */
- uErr = QCBORDecode_Finish(&DecodeCtx);
-
-Done:
- return ConvertError(uErr);
-}
-
-#endif /* EXAMPLE_DISABLE_SPIFFY_DECODE_FAST */
-
-
-#ifndef EXAMPLE_DISABLE_BASIC_DECODE
-/**
- @brief Check the type and lable of an item.
-
- @param[in] szLabel The expected string label.
- @param[in] uQCBORType The expected type or @c QCBOR_TYPE_ANY.
- @param[in] pItem The item to check.
-
- @retval QCBOR_ERR_LABEL_NOT_FOUND The label doesn't match.
- @retval QCBOR_ERR_UNEXPECTED_TYPE The label matches, but the type is
- not as expected.
- @retval QCBOR_SUCCESS Both label and type match.
- */
-QCBORError CheckLabelAndType(const char *szLabel, uint8_t uQCBORType, const QCBORItem *pItem)
-{
- if(pItem->uLabelType != QCBOR_TYPE_TEXT_STRING) {
- return QCBOR_ERR_LABEL_NOT_FOUND;
- }
-
- UsefulBufC Label = UsefulBuf_FromSZ(szLabel);
-
- if(UsefulBuf_Compare(Label, pItem->label.string)) {
- return QCBOR_ERR_LABEL_NOT_FOUND;
- }
-
- if(pItem->uDataType != uQCBORType && uQCBORType != QCBOR_TYPE_ANY) {
- return QCBOR_ERR_UNEXPECTED_TYPE;
- }
-
- return QCBOR_SUCCESS;
-}
-
-
-/**
- @brief Decode the array of engine cylinders.
-
- @param[in] pDecodeCtx The decode context from which to get items.
- @param[out] pE The structure filled in from the decoding.
- @param[in] pItem The data item that is the start of the array.
-
- @return Either @ref EngineSuccess or an error.
-
- This always consumes the whole array. If it has the wrong number of
- items in it, an error is returned.
- */
-EngineDecodeErrors DecodeCylinders(QCBORDecodeContext *pDecodeCtx,
- CarEngine *pE,
- const QCBORItem *pItem)
-{
- int i = 0;
- QCBORItem Item;
-
- /* Loop getting all the items in the array. This uses nesting
- level to detect the end so it works for both definite and
- indefinite length arrays. */
- do {
- QCBORError uErr;
-
- uErr = QCBORDecode_GetNext(pDecodeCtx, &Item);
- if(uErr != QCBOR_SUCCESS) {
- return CBORNotWellFormed;
- }
- if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
- return CBORNotWellFormed;
- }
-
- if(i < MAX_CYLINDERS) {
- pE->cylinders[i].uMeasuredCompression = Item.val.dfnum;
- i++;
- }
-
- } while (Item.uNextNestLevel == pItem->uNextNestLevel);
-
- if(i != pE->uNumCylinders) {
- return WrongNumberOfCylinders;
- } else {
- return EngineSuccess;
- }
-}
-
-
-/**
- @brief Engine decode without spiffy decode.
-
- @param[in] EncodedEngine Pointer and length of CBOR-encoded engine.
- @param[out] pE The structure filled in from the decoding.
-
- @return The decode error or success.
-
- This is the third implementation of engine decoding, again
- implementing the same functionality as DecodeEngineSpiffy() and
- DecodeEngineSpiffyFaster().
-
- This version of the deocde is the most complex, but uses
- significantly less code (2-3KB less on 64-bit Intel) from the QCBOR
- library. It is also the most CPU-efficient since it does only one
- pass through the CBOR.
-*/
-EngineDecodeErrors DecodeEngineBasic(UsefulBufC EncodedEngine, CarEngine *pE)
-{
- QCBORDecodeContext DecodeCtx;
-
- QCBORDecode_Init(&DecodeCtx, EncodedEngine, QCBOR_DECODE_MODE_NORMAL);
-
- QCBORItem Item;
- QCBORError uErr;
- EngineDecodeErrors uReturn;
-
-
- uErr = QCBORDecode_GetNext(&DecodeCtx, &Item);
- if(uErr != QCBOR_SUCCESS) {
- uReturn = CBORNotWellFormed;
- goto Done;
- }
- if(Item.uDataType != QCBOR_TYPE_MAP) {
- uReturn = CBORNotWellFormed;
- goto Done;
- }
-
- while(1) {
- uErr = QCBORDecode_GetNext(&DecodeCtx, &Item);
- if(uErr != QCBOR_SUCCESS) {
- if(uErr == QCBOR_ERR_NO_MORE_ITEMS) {
- break; /* Non-error exit from the loop */
- } else {
- uReturn = CBORNotWellFormed;
- goto Done;
- }
- }
-
- uErr = CheckLabelAndType("Manufacturer", QCBOR_TYPE_TEXT_STRING, &Item);
- if(uErr == QCBOR_SUCCESS) {
- pE->Manufacturer = Item.val.string;
- continue;
- } else if(uErr != QCBOR_ERR_LABEL_NOT_FOUND){
- /* Maunfacturer field missing or badly formed */
- return EngineProtocolerror;
- } /* continue on and try for another match */
-
- uErr = CheckLabelAndType("NumCylinders", QCBOR_TYPE_INT64, &Item);
- if(uErr == QCBOR_SUCCESS) {
- if(Item.val.int64 > MAX_CYLINDERS) {
- return TooManyCylinders;
- } else {
- pE->uNumCylinders = (uint8_t)Item.val.int64;
- continue;
- }
- } else if(uErr != QCBOR_ERR_LABEL_NOT_FOUND){
- /* NumCylinders field missing or badly formed */
- return EngineProtocolerror;
- } /* continue on and try for another match */
-
- uErr = CheckLabelAndType("Cylinders", QCBOR_TYPE_ARRAY, &Item);
- if(uErr == QCBOR_SUCCESS) {
- DecodeCylinders(&DecodeCtx, pE, &Item);
- continue;
- } else if(uErr != QCBOR_ERR_LABEL_NOT_FOUND){
- return EngineProtocolerror;
- }
-
- uErr = CheckLabelAndType("Displacement", QCBOR_TYPE_INT64, &Item);
- if(uErr == QCBOR_SUCCESS) {
- pE->uDisplacement = Item.val.int64;
- continue;
- } else if(uErr != QCBOR_ERR_LABEL_NOT_FOUND){
- return EngineProtocolerror;
- }
-
- uErr = CheckLabelAndType("Horsepower", QCBOR_TYPE_INT64, &Item);
- if(uErr == QCBOR_SUCCESS) {
- pE->uHorsePower = Item.val.int64;
- continue;
- } else if(uErr != QCBOR_ERR_LABEL_NOT_FOUND){
- return EngineProtocolerror;
- }
-
- uErr = CheckLabelAndType("DesignedCompression", QCBOR_TYPE_DOUBLE, &Item);
- if(uErr == QCBOR_SUCCESS) {
- pE->dDesignedCompresion = Item.val.dfnum;
- continue;
- } else if(uErr != QCBOR_ERR_LABEL_NOT_FOUND){
- return EngineProtocolerror;
- }
-
- uErr = CheckLabelAndType("Turbo", QCBOR_TYPE_ANY, &Item);
- if(uErr == QCBOR_SUCCESS) {
- if(Item.uDataType == QCBOR_TYPE_TRUE) {
- pE->bTurboCharged = true;
- } else if(Item.uDataType == QCBOR_TYPE_FALSE) {
- pE->bTurboCharged = false;
- } else {
- return EngineProtocolerror;
- }
- continue;
- } else if(uErr != QCBOR_ERR_LABEL_NOT_FOUND){
- return EngineProtocolerror;
- }
-
- /* Some label data item that is not known (could just ignore
- extras data items) */
- return EngineProtocolerror;
- }
- uReturn = EngineSuccess;
-
- /* Catch the remainder of errors here */
- uErr = QCBORDecode_Finish(&DecodeCtx);
- if(uErr) {
- uReturn = ConvertError(uErr);
- }
-
-
-
-Done:
- return uReturn;
-}
-
-#endif /* EXAMPLE_DISABLE_BASIC_DECODE */
-
int32_t RunQCborExample()
{
- CarEngine E, DecodedEngine;
+ CarEngine InitialEngine;
+ CarEngine DecodedEngine;
/* For every buffer used by QCBOR a pointer and a length are always
* carried in a UsefulBuf. This is a secure coding and hygene
- * practice to help make sure code never runs off the end of a buffer.
+ * practice to help make sure code never runs off the end of a
+ * buffer.
*
* UsefulBuf structures are passed as a stack parameter to make the
- * code prettier. The object code generated isn't much different from
- * passing a pointer parameter and a length parameter.
+ * code prettier. The object code generated isn't much different
+ * from passing a pointer parameter and a length parameter.
*
* This macro is equivalent to:
* uint8_t __pBufEngineBuffer[300];
@@ -680,53 +308,33 @@
* and is used to represent a buffer that has been written to.
*/
UsefulBufC EncodedEngine;
-
- UsefulBuf_MAKE_STACK_UB( InDefEngineBuffer, 300);
- UsefulBufC InDefEncodedEngine;
-
EngineDecodeErrors uErr;
- EngineInit(&E);
+ /* Initialize the structure with some values. */
+ EngineInit(&InitialEngine);
-#ifndef EXAMPLE_DISABLE_DEFINITE_LENGTH_ENCODE
- EncodedEngine = EncodeEngineDefiniteLength(&E, EngineBuffer);
- printf("Definite Length Engine Encoded in %zu bytes\n", EncodedEngine.len);
-#endif /* EXAMPLE_DISABLE_DEFINITE_LENGTH_ENCODE */
+ /* Encode the engine structure. */
+ EncodedEngine = EncodeEngineDefiniteLength(&InitialEngine, EngineBuffer);
+ if(UsefulBuf_IsNULLC(EncodedEngine)) {
+ printf("Engine encode failed\n");
+ goto Done;
+ }
+ printf("Example: Definite Length Engine Encoded in %zu bytes\n",
+ EncodedEngine.len);
-
-#ifndef EXAMPLE_DISABLE_INDEFINITE_LENGTH_ENCODE_ENCODE
- InDefEncodedEngine = EncodeEngineIndefinteLen(&E, InDefEngineBuffer);
- printf("Indef Engine Encoded in %zu bytes\n", InDefEncodedEngine.len);
-#endif /* EXAMPLE_DISABLE_INDEFINITE_LENGTH_ENCODE_ENCODE */
-
-
-#ifndef EXAMPLE_DISABLE_SPIFFY_DECODE
+ /* Decode the CBOR */
uErr = DecodeEngineSpiffy(EncodedEngine, &DecodedEngine);
- printf("Spiffy Engine Decode Result: %d\n", uErr);
-
- if(!EngineCompare(&E, &DecodedEngine)) {
- printf("Spiffy Engine Decode comparison fail\n");
+ printf("Example: Spiffy Engine Decode Result: %d\n", uErr);
+ if(uErr) {
+ goto Done;
}
-#endif /* EXAMPLE_DISABLE_SPIFFY_DECODE */
-#ifndef EXAMPLE_DISABLE_SPIFFY_DECODE_FAST
- uErr = DecodeEngineSpiffyFaster(EncodedEngine, &DecodedEngine);
- printf("Faster Spiffy Engine Decode Result: %d\n", uErr);
-
- if(!EngineCompare(&E, &DecodedEngine)) {
- printf("Faster Spiffy Engine Decode comparison fail\n");
+ /* Check the results */
+ if(!EngineCompare(&InitialEngine, &DecodedEngine)) {
+ printf("Example: Spiffy Engine Decode comparison fail\n");
}
-#endif /* EXAMPLE_DISABLE_SPIFFY_DECODE_FAST */
-#ifndef EXAMPLE_DISABLE_BASIC_DECODE
- uErr = DecodeEngineBasic(EncodedEngine, &DecodedEngine);
- printf("Engine Basic Decode Result: %d\n", uErr);
-
- if(!EngineCompare(&E, &DecodedEngine)) {
- printf("Engine Basic Decode comparison fail\n");
- }
-#endif /* EXAMPLE_DISABLE_BASIC_DECODE */
-
+Done:
printf("\n");
return 0;