blob: c489ad61e61eba7ba20f67d5077ad91c3fbb871b [file] [log] [blame]
Laurence Lundbladec4474172020-10-02 14:52:16 -07001/* =========================================================================
2 example.c -- Example code for QCBOR
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07003
Laurence Lundblade5c91eb32021-04-03 23:56:54 -07004 Copyright (c) 2020-2021, Laurence Lundblade. All rights reserved.
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02005 Copyright (c) 2021, Arm Limited. All rights reserved.
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006
Laurence Lundbladec4474172020-10-02 14:52:16 -07007 SPDX-License-Identifier: BSD-3-Clause
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07008
Laurence Lundbladee8f58162024-08-22 10:30:08 -07009 See BSD-3-Clause license in file named "LICENSE"
Laurence Lundbladed4cd7232020-07-03 19:30:48 -070010
Laurence Lundbladec4474172020-10-02 14:52:16 -070011 Created on 6/30/2020
12 ========================================================================== */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -070013
14#include <stdio.h>
15#include "example.h"
16#include "qcbor/qcbor_encode.h"
17#include "qcbor/qcbor_decode.h"
Laurence Lundblade67257dc2020-07-27 03:33:37 -070018#include "qcbor/qcbor_spiffy_decode.h"
Laurence Lundbladed4cd7232020-07-03 19:30:48 -070019
Laurence Lundbladec4474172020-10-02 14:52:16 -070020
Laurence Lundblade5c91eb32021-04-03 23:56:54 -070021/**
22 * This is a simple example of encoding and decoding some CBOR from
23 * and to a C structure.
24 *
25 * This also includes a comparison between the original structure
26 * and the one decoded from the CBOR to confirm correctness.
27 */
28
29
Laurence Lundbladed4cd7232020-07-03 19:30:48 -070030#define MAX_CYLINDERS 16
31
Laurence Lundbladeda319282020-07-06 23:04:58 -070032/**
Laurence Lundblade5c91eb32021-04-03 23:56:54 -070033 * The data structure representing a car engine that is encoded and
34 * decoded in this example.
Laurence Lundbladeda319282020-07-06 23:04:58 -070035 */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -070036typedef struct
37{
Laurence Lundbladec4474172020-10-02 14:52:16 -070038 UsefulBufC Manufacturer;
39 int64_t uDisplacement;
40 int64_t uHorsePower;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +020041#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundbladec4474172020-10-02 14:52:16 -070042 double dDesignedCompresion;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +020043#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundbladec4474172020-10-02 14:52:16 -070044 int64_t uNumCylinders;
45 bool bTurboCharged;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +020046#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundbladec4474172020-10-02 14:52:16 -070047 struct {
Laurence Lundblade5c91eb32021-04-03 23:56:54 -070048 double dMeasuredCompression;
Laurence Lundbladec4474172020-10-02 14:52:16 -070049 } cylinders[MAX_CYLINDERS];
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +020050#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundbladeda319282020-07-06 23:04:58 -070051} CarEngine;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -070052
53
Laurence Lundbladeda319282020-07-06 23:04:58 -070054/**
Laurence Lundblade5c91eb32021-04-03 23:56:54 -070055 * @brief Initialize the Engine data structure with values to encode.
56 *
57 * @param[out] pE The Engine structure to fill in
Laurence Lundbladeda319282020-07-06 23:04:58 -070058 */
59void EngineInit(CarEngine *pE)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -070060{
Laurence Lundbladec4474172020-10-02 14:52:16 -070061 pE->Manufacturer = UsefulBuf_FROM_SZ_LITERAL("Porsche");
62 pE->uDisplacement = 3296;
63 pE->uHorsePower = 210;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +020064#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundbladec4474172020-10-02 14:52:16 -070065 pE->dDesignedCompresion = 9.1;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +020066#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundbladec4474172020-10-02 14:52:16 -070067 pE->uNumCylinders = 6;
68 pE->bTurboCharged = false;
69
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +020070#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade5c91eb32021-04-03 23:56:54 -070071 pE->cylinders[0].dMeasuredCompression = 9.0;
72 pE->cylinders[1].dMeasuredCompression = 9.2;
73 pE->cylinders[2].dMeasuredCompression = 8.9;
74 pE->cylinders[3].dMeasuredCompression = 8.9;
75 pE->cylinders[4].dMeasuredCompression = 9.1;
76 pE->cylinders[5].dMeasuredCompression = 9.0;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +020077#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -070078}
79
80
Laurence Lundbladeda319282020-07-06 23:04:58 -070081/**
Laurence Lundblade5c91eb32021-04-03 23:56:54 -070082 * @brief Compare two Engine structure for equality.
83 *
84 * @param[in] pE1 First Engine to compare.
85 * @param[in] pE2 Second Engine to compare.
86 *
87 * @retval Return @c true if the two Engine data structures are exactly the
88 * same.
Laurence Lundbladeda319282020-07-06 23:04:58 -070089 */
Laurence Lundblade5c91eb32021-04-03 23:56:54 -070090static bool EngineCompare(const CarEngine *pE1, const CarEngine *pE2)
Laurence Lundbladee6bbf552020-07-05 22:57:57 -070091{
Laurence Lundblade5c91eb32021-04-03 23:56:54 -070092 if(pE1->uNumCylinders != pE2->uNumCylinders) {
93 return false;
94 }
95 if(pE1->bTurboCharged != pE2->bTurboCharged) {
96 return false;
97 }
98 if(pE1->uDisplacement != pE2->uDisplacement) {
99 return false;
100 }
101 if(pE1->uHorsePower != pE2->uHorsePower) {
102 return false;
103 }
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200104#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700105 if(pE1->dDesignedCompresion != pE2->dDesignedCompresion) {
106 return false;
107 }
108 for(int64_t i = 0; i < pE2->uNumCylinders; i++) {
109 if(pE1->cylinders[i].dMeasuredCompression !=
110 pE2->cylinders[i].dMeasuredCompression) {
111 return false;
112 }
113 }
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200114#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundbladee6bbf552020-07-05 22:57:57 -0700115
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700116 if(UsefulBuf_Compare(pE1->Manufacturer, pE2->Manufacturer)) {
117 return false;
118 }
Laurence Lundbladee6bbf552020-07-05 22:57:57 -0700119
120 return true;
121}
122
123
Laurence Lundbladeda319282020-07-06 23:04:58 -0700124/**
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700125 * @brief Encode an initialized CarEngine data structure in CBOR.
126 *
127 * @param[in] pEngine The data structure to encode.
128 * @param[in] Buffer Pointer and length of buffer to output to.
129 *
130 * @return The pointer and length of the encoded CBOR or
131 * @ref NULLUsefulBufC on error.
132 *
Laurence Lundblade88ba5662024-11-03 02:10:24 -0800133 * This encodes the input structure @c pEngine as a CBOR map of
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700134 * label-value pairs. An array of float is one of the items in the
135 * map.
136 *
137 * This uses the UsefulBuf convention of passing in a non-const empty
138 * buffer to be filled in and returning a filled in const buffer. The
139 * buffer to write into is given as a pointer and length in a
140 * UsefulBuf. The buffer returned with the encoded CBOR is a
141 * UsefulBufC also a pointer and length. In this implementation the
142 * pointer to the returned data is exactly the same as that of the
143 * empty buffer. The returned length will be smaller than or equal to
144 * that of the empty buffer. This gives correct const-ness for the
145 * buffer passed in and the data returned.
146 *
147 * @c Buffer must be big enough to hold the output. If it is not @ref
148 * NULLUsefulBufC will be returned. @ref NULLUsefulBufC will be
149 * returned for any other encoding errors.
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700150 *
151 * This can be called with @c Buffer set to @ref SizeCalculateUsefulBuf
152 * in which case the size of the encoded engine will be calculated,
153 * but no actual encoded CBOR will be output. The calculated size is
154 * in @c .len of the returned @ref UsefulBufC.
Laurence Lundbladeda319282020-07-06 23:04:58 -0700155 */
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700156UsefulBufC EncodeEngine(const CarEngine *pEngine, UsefulBuf Buffer)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700157{
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700158 /* Set up the encoding context with the output buffer */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700159 QCBOREncodeContext EncodeCtx;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700160 QCBOREncode_Init(&EncodeCtx, Buffer);
Laurence Lundblade06c83042020-07-03 23:04:53 -0700161
Laurence Lundbladec4474172020-10-02 14:52:16 -0700162 /* Proceed to output all the items, letting the internal error
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700163 * tracking do its work */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700164 QCBOREncode_OpenMap(&EncodeCtx);
Laurence Lundblade0f143652024-10-06 11:06:19 -0700165 QCBOREncode_AddTextToMapSZ(&EncodeCtx, "Manufacturer", pEngine->Manufacturer);
166 QCBOREncode_AddInt64ToMapSZ(&EncodeCtx, "NumCylinders", pEngine->uNumCylinders);
167 QCBOREncode_AddInt64ToMapSZ(&EncodeCtx, "Displacement", pEngine->uDisplacement);
168 QCBOREncode_AddInt64ToMapSZ(&EncodeCtx, "Horsepower", pEngine->uHorsePower);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200169#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade0f143652024-10-06 11:06:19 -0700170 QCBOREncode_AddDoubleToMapSZ(&EncodeCtx, "DesignedCompression", pEngine->dDesignedCompresion);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200171#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade0f143652024-10-06 11:06:19 -0700172 QCBOREncode_OpenArrayInMapSZ(&EncodeCtx, "Cylinders");
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200173#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade06c83042020-07-03 23:04:53 -0700174 for(int64_t i = 0 ; i < pEngine->uNumCylinders; i++) {
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700175 QCBOREncode_AddDouble(&EncodeCtx,
176 pEngine->cylinders[i].dMeasuredCompression);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700177 }
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200178#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700179 QCBOREncode_CloseArray(&EncodeCtx);
Laurence Lundblade0f143652024-10-06 11:06:19 -0700180 QCBOREncode_AddBoolToMapSZ(&EncodeCtx, "Turbo", pEngine->bTurboCharged);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700181 QCBOREncode_CloseMap(&EncodeCtx);
182
Laurence Lundblade06c83042020-07-03 23:04:53 -0700183 /* Get the pointer and length of the encoded output. If there was
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700184 * any encoding error, it will be returned here */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700185 UsefulBufC EncodedCBOR;
186 QCBORError uErr;
187 uErr = QCBOREncode_Finish(&EncodeCtx, &EncodedCBOR);
188 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladec4474172020-10-02 14:52:16 -0700189 return NULLUsefulBufC;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700190 } else {
191 return EncodedCBOR;
192 }
193}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700194
195
Laurence Lundbladeda319282020-07-06 23:04:58 -0700196/**
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700197 * Error results when decoding an Engine data structure.
Laurence Lundbladeda319282020-07-06 23:04:58 -0700198 */
Laurence Lundblade06c83042020-07-03 23:04:53 -0700199typedef enum {
200 EngineSuccess,
201 CBORNotWellFormed,
202 TooManyCylinders,
203 EngineProtocolerror,
204 WrongNumberOfCylinders
205} EngineDecodeErrors;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700206
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700207
Laurence Lundbladeda319282020-07-06 23:04:58 -0700208/**
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700209 * Convert @ref QCBORError to @ref EngineDecodeErrors.
Laurence Lundbladeda319282020-07-06 23:04:58 -0700210 */
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700211static EngineDecodeErrors ConvertError(QCBORError uErr)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700212{
Laurence Lundblade06c83042020-07-03 23:04:53 -0700213 EngineDecodeErrors uReturn;
214
215 switch(uErr)
216 {
217 case QCBOR_SUCCESS:
218 uReturn = EngineSuccess;
219 break;
220
221 case QCBOR_ERR_HIT_END:
222 uReturn = CBORNotWellFormed;
223 break;
224
225 default:
226 uReturn = EngineProtocolerror;
227 break;
228 }
229
230 return uReturn;
231}
232
233
Laurence Lundbladeda319282020-07-06 23:04:58 -0700234/**
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700235 * @brief Simplest engine decode using spiffy decode features.
236 *
237 * @param[in] EncodedEngine Pointer and length of CBOR-encoded engine.
238 * @param[out] pE The structure filled in from the decoding.
239 *
240 * @return The decode error or success.
241 *
242 * This decodes the CBOR into the engine structure.
243 *
244 * As QCBOR automatically supports both definite and indefinite maps
245 * and arrays, this will decode either.
246 *
247 * This uses QCBOR's spiffy decode functions, so the implementation is
248 * simple and closely parallels the encode implementation in
249 * EncodeEngineDefiniteLength().
250 *
251 * Another way to decode without using spiffy decode functions is to
252 * use QCBORDecode_GetNext() to traverse the whole tree. This
253 * requires a more complex implementation, but is faster and will pull
254 * in less code from the CBOR library. The speed advantage is likely
255 * of consequence when decoding much much larger CBOR on slow small
256 * CPUs.
257 *
258 * A middle way is to use the spiffy decode
259 * QCBORDecode_GetItemsInMap(). The implementation has middle
260 * complexity and uses less CPU.
Laurence Lundblade06c83042020-07-03 23:04:53 -0700261 */
Laurence Lundblade67257dc2020-07-27 03:33:37 -0700262EngineDecodeErrors DecodeEngineSpiffy(UsefulBufC EncodedEngine, CarEngine *pE)
Laurence Lundblade06c83042020-07-03 23:04:53 -0700263{
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700264 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700265 QCBORDecodeContext DecodeCtx;
266
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700267 /* Let QCBORDecode internal error tracking do its work. */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700268 QCBORDecode_Init(&DecodeCtx, EncodedEngine, QCBOR_DECODE_MODE_NORMAL);
Laurence Lundblade6545d1b2020-10-14 11:13:13 -0700269 QCBORDecode_EnterMap(&DecodeCtx, NULL);
Laurence Lundblade323f8a92020-09-06 19:43:09 -0700270 QCBORDecode_GetTextStringInMapSZ(&DecodeCtx, "Manufacturer", &(pE->Manufacturer));
Laurence Lundblade06c83042020-07-03 23:04:53 -0700271 QCBORDecode_GetInt64InMapSZ(&DecodeCtx, "Displacement", &(pE->uDisplacement));
272 QCBORDecode_GetInt64InMapSZ(&DecodeCtx, "Horsepower", &(pE->uHorsePower));
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200273#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundbladee6bbf552020-07-05 22:57:57 -0700274 QCBORDecode_GetDoubleInMapSZ(&DecodeCtx, "DesignedCompression", &(pE->dDesignedCompresion));
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200275#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundbladeda319282020-07-06 23:04:58 -0700276 QCBORDecode_GetBoolInMapSZ(&DecodeCtx, "Turbo", &(pE->bTurboCharged));
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700277
Laurence Lundblade06c83042020-07-03 23:04:53 -0700278 QCBORDecode_GetInt64InMapSZ(&DecodeCtx, "NumCylinders", &(pE->uNumCylinders));
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700279
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700280 /* Check the internal tracked error now before going on to
281 * reference any of the decoded data, particularly
282 * pE->uNumCylinders */
Laurence Lundblade06c83042020-07-03 23:04:53 -0700283 uErr = QCBORDecode_GetError(&DecodeCtx);
284 if(uErr != QCBOR_SUCCESS) {
285 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700286 }
287
288 if(pE->uNumCylinders > MAX_CYLINDERS) {
Laurence Lundblade06c83042020-07-03 23:04:53 -0700289 return TooManyCylinders;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700290 }
291
292 QCBORDecode_EnterArrayFromMapSZ(&DecodeCtx, "Cylinders");
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200293#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundbladee6bbf552020-07-05 22:57:57 -0700294 for(int64_t i = 0; i < pE->uNumCylinders; i++) {
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700295 QCBORDecode_GetDouble(&DecodeCtx,
296 &(pE->cylinders[i].dMeasuredCompression));
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700297 }
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200298#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700299 QCBORDecode_ExitArray(&DecodeCtx);
300 QCBORDecode_ExitMap(&DecodeCtx);
301
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700302 /* Catch further decoding error here */
Laurence Lundblade06c83042020-07-03 23:04:53 -0700303 uErr = QCBORDecode_Finish(&DecodeCtx);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700304
Laurence Lundblade06c83042020-07-03 23:04:53 -0700305Done:
306 return ConvertError(uErr);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700307}
308
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700309
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300310int32_t RunQCborExample(void)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700311{
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700312 CarEngine InitialEngine;
313 CarEngine DecodedEngine;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700314
Laurence Lundblade8510f8c2020-12-01 11:31:16 -0800315 /* For every buffer used by QCBOR a pointer and a length are always
316 * carried in a UsefulBuf. This is a secure coding and hygene
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700317 * practice to help make sure code never runs off the end of a
318 * buffer.
Laurence Lundblade8510f8c2020-12-01 11:31:16 -0800319 *
320 * UsefulBuf structures are passed as a stack parameter to make the
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700321 * code prettier. The object code generated isn't much different
322 * from passing a pointer parameter and a length parameter.
Laurence Lundblade8510f8c2020-12-01 11:31:16 -0800323 *
324 * This macro is equivalent to:
325 * uint8_t __pBufEngineBuffer[300];
326 * UsefulBuf EngineBuffer = {__pBufEngineBuffer, 300};
327 */
328 UsefulBuf_MAKE_STACK_UB( EngineBuffer, 300);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700329
Laurence Lundblade8510f8c2020-12-01 11:31:16 -0800330 /* The pointer in UsefulBuf is not const and used for representing
331 * a buffer to be written to. For UsefulbufC, the pointer is const
332 * and is used to represent a buffer that has been written to.
333 */
334 UsefulBufC EncodedEngine;
Laurence Lundblade8510f8c2020-12-01 11:31:16 -0800335 EngineDecodeErrors uErr;
Laurence Lundblade1818e632020-07-26 04:14:08 -0700336
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700337 /* Initialize the structure with some values. */
338 EngineInit(&InitialEngine);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700339
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700340 /* Encode the engine structure. */
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700341 EncodedEngine = EncodeEngine(&InitialEngine, EngineBuffer);
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700342 if(UsefulBuf_IsNULLC(EncodedEngine)) {
343 printf("Engine encode failed\n");
344 goto Done;
345 }
346 printf("Example: Definite Length Engine Encoded in %zu bytes\n",
347 EncodedEngine.len);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700348
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700349 /* Decode the CBOR */
Laurence Lundbladec4474172020-10-02 14:52:16 -0700350 uErr = DecodeEngineSpiffy(EncodedEngine, &DecodedEngine);
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700351 printf("Example: Spiffy Engine Decode Result: %d\n", uErr);
352 if(uErr) {
353 goto Done;
Laurence Lundbladec4474172020-10-02 14:52:16 -0700354 }
Laurence Lundbladee6bbf552020-07-05 22:57:57 -0700355
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700356 /* Check the results */
357 if(!EngineCompare(&InitialEngine, &DecodedEngine)) {
358 printf("Example: Spiffy Engine Decode comparison fail\n");
Laurence Lundbladec4474172020-10-02 14:52:16 -0700359 }
Laurence Lundbladee6bbf552020-07-05 22:57:57 -0700360
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700361
362 /* Further example of how to calculate the encoded size, then allocate */
363 UsefulBufC EncodedEngineSize;
364 EncodedEngineSize = EncodeEngine(&InitialEngine, SizeCalculateUsefulBuf);
365 if(UsefulBuf_IsNULLC(EncodedEngine)) {
366 printf("Engine encode size calculation failed\n");
367 goto Done;
368 }
369 (void)EncodedEngineSize; /* Supress unsed variable warning */
370 /* Here malloc could be called to allocate a buffer. Then
371 * EncodeEngine() can be called a second time to actually
372 * encode. (The actual code is not live here to avoid a
373 * dependency on malloc()).
374 * UsefulBuf MallocedBuffer;
375 * MallocedBuffer.len = EncodedEngineSize.len;
376 * MallocedBuffer.ptr = malloc(EncodedEngineSize.len);
377 * EncodedEngine = EncodeEngine(&InitialEngine, MallocedBuffer);
378 */
379
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700380Done:
Laurence Lundbladec4474172020-10-02 14:52:16 -0700381 printf("\n");
382
383 return 0;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700384}