blob: 473e989c8a5ea209096a6176b196a7653900c655 [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 Lundblade33ed26f2024-11-24 10:26:43 -080019#include "qcbor/qcbor_number_decode.h"
Laurence Lundbladed4cd7232020-07-03 19:30:48 -070020
Laurence Lundbladec4474172020-10-02 14:52:16 -070021
Laurence Lundblade5c91eb32021-04-03 23:56:54 -070022/**
23 * This is a simple example of encoding and decoding some CBOR from
24 * and to a C structure.
25 *
26 * This also includes a comparison between the original structure
27 * and the one decoded from the CBOR to confirm correctness.
28 */
29
30
Laurence Lundbladed4cd7232020-07-03 19:30:48 -070031#define MAX_CYLINDERS 16
32
Laurence Lundbladeda319282020-07-06 23:04:58 -070033/**
Laurence Lundblade5c91eb32021-04-03 23:56:54 -070034 * The data structure representing a car engine that is encoded and
35 * decoded in this example.
Laurence Lundbladeda319282020-07-06 23:04:58 -070036 */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -070037typedef struct
38{
Laurence Lundbladec4474172020-10-02 14:52:16 -070039 UsefulBufC Manufacturer;
40 int64_t uDisplacement;
41 int64_t uHorsePower;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +020042#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundbladec4474172020-10-02 14:52:16 -070043 double dDesignedCompresion;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +020044#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundbladec4474172020-10-02 14:52:16 -070045 int64_t uNumCylinders;
46 bool bTurboCharged;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +020047#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundbladec4474172020-10-02 14:52:16 -070048 struct {
Laurence Lundblade5c91eb32021-04-03 23:56:54 -070049 double dMeasuredCompression;
Laurence Lundbladec4474172020-10-02 14:52:16 -070050 } cylinders[MAX_CYLINDERS];
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +020051#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundbladeda319282020-07-06 23:04:58 -070052} CarEngine;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -070053
54
Laurence Lundbladeda319282020-07-06 23:04:58 -070055/**
Laurence Lundblade5c91eb32021-04-03 23:56:54 -070056 * @brief Initialize the Engine data structure with values to encode.
57 *
58 * @param[out] pE The Engine structure to fill in
Laurence Lundbladeda319282020-07-06 23:04:58 -070059 */
60void EngineInit(CarEngine *pE)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -070061{
Laurence Lundbladec4474172020-10-02 14:52:16 -070062 pE->Manufacturer = UsefulBuf_FROM_SZ_LITERAL("Porsche");
63 pE->uDisplacement = 3296;
64 pE->uHorsePower = 210;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +020065#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundbladec4474172020-10-02 14:52:16 -070066 pE->dDesignedCompresion = 9.1;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +020067#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundbladec4474172020-10-02 14:52:16 -070068 pE->uNumCylinders = 6;
69 pE->bTurboCharged = false;
70
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +020071#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade5c91eb32021-04-03 23:56:54 -070072 pE->cylinders[0].dMeasuredCompression = 9.0;
73 pE->cylinders[1].dMeasuredCompression = 9.2;
74 pE->cylinders[2].dMeasuredCompression = 8.9;
75 pE->cylinders[3].dMeasuredCompression = 8.9;
76 pE->cylinders[4].dMeasuredCompression = 9.1;
77 pE->cylinders[5].dMeasuredCompression = 9.0;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +020078#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -070079}
80
81
Laurence Lundbladeda319282020-07-06 23:04:58 -070082/**
Laurence Lundblade5c91eb32021-04-03 23:56:54 -070083 * @brief Compare two Engine structure for equality.
84 *
85 * @param[in] pE1 First Engine to compare.
86 * @param[in] pE2 Second Engine to compare.
87 *
88 * @retval Return @c true if the two Engine data structures are exactly the
89 * same.
Laurence Lundbladeda319282020-07-06 23:04:58 -070090 */
Laurence Lundblade5c91eb32021-04-03 23:56:54 -070091static bool EngineCompare(const CarEngine *pE1, const CarEngine *pE2)
Laurence Lundbladee6bbf552020-07-05 22:57:57 -070092{
Laurence Lundblade5c91eb32021-04-03 23:56:54 -070093 if(pE1->uNumCylinders != pE2->uNumCylinders) {
94 return false;
95 }
96 if(pE1->bTurboCharged != pE2->bTurboCharged) {
97 return false;
98 }
99 if(pE1->uDisplacement != pE2->uDisplacement) {
100 return false;
101 }
102 if(pE1->uHorsePower != pE2->uHorsePower) {
103 return false;
104 }
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200105#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700106 if(pE1->dDesignedCompresion != pE2->dDesignedCompresion) {
107 return false;
108 }
109 for(int64_t i = 0; i < pE2->uNumCylinders; i++) {
110 if(pE1->cylinders[i].dMeasuredCompression !=
111 pE2->cylinders[i].dMeasuredCompression) {
112 return false;
113 }
114 }
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200115#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundbladee6bbf552020-07-05 22:57:57 -0700116
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700117 if(UsefulBuf_Compare(pE1->Manufacturer, pE2->Manufacturer)) {
118 return false;
119 }
Laurence Lundbladee6bbf552020-07-05 22:57:57 -0700120
121 return true;
122}
123
124
Laurence Lundbladeda319282020-07-06 23:04:58 -0700125/**
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700126 * @brief Encode an initialized CarEngine data structure in CBOR.
127 *
128 * @param[in] pEngine The data structure to encode.
129 * @param[in] Buffer Pointer and length of buffer to output to.
130 *
131 * @return The pointer and length of the encoded CBOR or
132 * @ref NULLUsefulBufC on error.
133 *
Laurence Lundblade88ba5662024-11-03 02:10:24 -0800134 * This encodes the input structure @c pEngine as a CBOR map of
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700135 * label-value pairs. An array of float is one of the items in the
136 * map.
137 *
138 * This uses the UsefulBuf convention of passing in a non-const empty
139 * buffer to be filled in and returning a filled in const buffer. The
140 * buffer to write into is given as a pointer and length in a
141 * UsefulBuf. The buffer returned with the encoded CBOR is a
142 * UsefulBufC also a pointer and length. In this implementation the
143 * pointer to the returned data is exactly the same as that of the
144 * empty buffer. The returned length will be smaller than or equal to
145 * that of the empty buffer. This gives correct const-ness for the
146 * buffer passed in and the data returned.
147 *
148 * @c Buffer must be big enough to hold the output. If it is not @ref
149 * NULLUsefulBufC will be returned. @ref NULLUsefulBufC will be
150 * returned for any other encoding errors.
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700151 *
152 * This can be called with @c Buffer set to @ref SizeCalculateUsefulBuf
153 * in which case the size of the encoded engine will be calculated,
154 * but no actual encoded CBOR will be output. The calculated size is
155 * in @c .len of the returned @ref UsefulBufC.
Laurence Lundbladeda319282020-07-06 23:04:58 -0700156 */
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700157UsefulBufC EncodeEngine(const CarEngine *pEngine, UsefulBuf Buffer)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700158{
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700159 /* Set up the encoding context with the output buffer */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700160 QCBOREncodeContext EncodeCtx;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700161 QCBOREncode_Init(&EncodeCtx, Buffer);
Laurence Lundblade06c83042020-07-03 23:04:53 -0700162
Laurence Lundbladec4474172020-10-02 14:52:16 -0700163 /* Proceed to output all the items, letting the internal error
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700164 * tracking do its work */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700165 QCBOREncode_OpenMap(&EncodeCtx);
Laurence Lundblade0f143652024-10-06 11:06:19 -0700166 QCBOREncode_AddTextToMapSZ(&EncodeCtx, "Manufacturer", pEngine->Manufacturer);
167 QCBOREncode_AddInt64ToMapSZ(&EncodeCtx, "NumCylinders", pEngine->uNumCylinders);
168 QCBOREncode_AddInt64ToMapSZ(&EncodeCtx, "Displacement", pEngine->uDisplacement);
169 QCBOREncode_AddInt64ToMapSZ(&EncodeCtx, "Horsepower", pEngine->uHorsePower);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200170#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade0f143652024-10-06 11:06:19 -0700171 QCBOREncode_AddDoubleToMapSZ(&EncodeCtx, "DesignedCompression", pEngine->dDesignedCompresion);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200172#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade0f143652024-10-06 11:06:19 -0700173 QCBOREncode_OpenArrayInMapSZ(&EncodeCtx, "Cylinders");
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200174#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade06c83042020-07-03 23:04:53 -0700175 for(int64_t i = 0 ; i < pEngine->uNumCylinders; i++) {
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700176 QCBOREncode_AddDouble(&EncodeCtx,
177 pEngine->cylinders[i].dMeasuredCompression);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700178 }
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200179#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700180 QCBOREncode_CloseArray(&EncodeCtx);
Laurence Lundblade0f143652024-10-06 11:06:19 -0700181 QCBOREncode_AddBoolToMapSZ(&EncodeCtx, "Turbo", pEngine->bTurboCharged);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700182 QCBOREncode_CloseMap(&EncodeCtx);
183
Laurence Lundblade06c83042020-07-03 23:04:53 -0700184 /* Get the pointer and length of the encoded output. If there was
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700185 * any encoding error, it will be returned here */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700186 UsefulBufC EncodedCBOR;
187 QCBORError uErr;
188 uErr = QCBOREncode_Finish(&EncodeCtx, &EncodedCBOR);
189 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladec4474172020-10-02 14:52:16 -0700190 return NULLUsefulBufC;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700191 } else {
192 return EncodedCBOR;
193 }
194}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700195
196
Laurence Lundbladeda319282020-07-06 23:04:58 -0700197/**
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700198 * Error results when decoding an Engine data structure.
Laurence Lundbladeda319282020-07-06 23:04:58 -0700199 */
Laurence Lundblade06c83042020-07-03 23:04:53 -0700200typedef enum {
201 EngineSuccess,
202 CBORNotWellFormed,
203 TooManyCylinders,
204 EngineProtocolerror,
205 WrongNumberOfCylinders
206} EngineDecodeErrors;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700207
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700208
Laurence Lundbladeda319282020-07-06 23:04:58 -0700209/**
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700210 * Convert @ref QCBORError to @ref EngineDecodeErrors.
Laurence Lundbladeda319282020-07-06 23:04:58 -0700211 */
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700212static EngineDecodeErrors ConvertError(QCBORError uErr)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700213{
Laurence Lundblade06c83042020-07-03 23:04:53 -0700214 EngineDecodeErrors uReturn;
215
216 switch(uErr)
217 {
218 case QCBOR_SUCCESS:
219 uReturn = EngineSuccess;
220 break;
221
222 case QCBOR_ERR_HIT_END:
223 uReturn = CBORNotWellFormed;
224 break;
225
226 default:
227 uReturn = EngineProtocolerror;
228 break;
229 }
230
231 return uReturn;
232}
233
234
Laurence Lundbladeda319282020-07-06 23:04:58 -0700235/**
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700236 * @brief Simplest engine decode using spiffy decode features.
237 *
238 * @param[in] EncodedEngine Pointer and length of CBOR-encoded engine.
239 * @param[out] pE The structure filled in from the decoding.
240 *
241 * @return The decode error or success.
242 *
243 * This decodes the CBOR into the engine structure.
244 *
245 * As QCBOR automatically supports both definite and indefinite maps
246 * and arrays, this will decode either.
247 *
248 * This uses QCBOR's spiffy decode functions, so the implementation is
249 * simple and closely parallels the encode implementation in
250 * EncodeEngineDefiniteLength().
251 *
252 * Another way to decode without using spiffy decode functions is to
253 * use QCBORDecode_GetNext() to traverse the whole tree. This
254 * requires a more complex implementation, but is faster and will pull
255 * in less code from the CBOR library. The speed advantage is likely
256 * of consequence when decoding much much larger CBOR on slow small
257 * CPUs.
258 *
259 * A middle way is to use the spiffy decode
260 * QCBORDecode_GetItemsInMap(). The implementation has middle
261 * complexity and uses less CPU.
Laurence Lundblade06c83042020-07-03 23:04:53 -0700262 */
Laurence Lundblade67257dc2020-07-27 03:33:37 -0700263EngineDecodeErrors DecodeEngineSpiffy(UsefulBufC EncodedEngine, CarEngine *pE)
Laurence Lundblade06c83042020-07-03 23:04:53 -0700264{
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700265 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700266 QCBORDecodeContext DecodeCtx;
267
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700268 /* Let QCBORDecode internal error tracking do its work. */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700269 QCBORDecode_Init(&DecodeCtx, EncodedEngine, QCBOR_DECODE_MODE_NORMAL);
Laurence Lundblade6545d1b2020-10-14 11:13:13 -0700270 QCBORDecode_EnterMap(&DecodeCtx, NULL);
Laurence Lundblade323f8a92020-09-06 19:43:09 -0700271 QCBORDecode_GetTextStringInMapSZ(&DecodeCtx, "Manufacturer", &(pE->Manufacturer));
Laurence Lundblade06c83042020-07-03 23:04:53 -0700272 QCBORDecode_GetInt64InMapSZ(&DecodeCtx, "Displacement", &(pE->uDisplacement));
273 QCBORDecode_GetInt64InMapSZ(&DecodeCtx, "Horsepower", &(pE->uHorsePower));
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200274#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundbladee6bbf552020-07-05 22:57:57 -0700275 QCBORDecode_GetDoubleInMapSZ(&DecodeCtx, "DesignedCompression", &(pE->dDesignedCompresion));
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200276#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundbladeda319282020-07-06 23:04:58 -0700277 QCBORDecode_GetBoolInMapSZ(&DecodeCtx, "Turbo", &(pE->bTurboCharged));
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700278
Laurence Lundblade06c83042020-07-03 23:04:53 -0700279 QCBORDecode_GetInt64InMapSZ(&DecodeCtx, "NumCylinders", &(pE->uNumCylinders));
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700280
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700281 /* Check the internal tracked error now before going on to
282 * reference any of the decoded data, particularly
283 * pE->uNumCylinders */
Laurence Lundblade06c83042020-07-03 23:04:53 -0700284 uErr = QCBORDecode_GetError(&DecodeCtx);
285 if(uErr != QCBOR_SUCCESS) {
286 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700287 }
288
289 if(pE->uNumCylinders > MAX_CYLINDERS) {
Laurence Lundblade06c83042020-07-03 23:04:53 -0700290 return TooManyCylinders;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700291 }
292
293 QCBORDecode_EnterArrayFromMapSZ(&DecodeCtx, "Cylinders");
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200294#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundbladee6bbf552020-07-05 22:57:57 -0700295 for(int64_t i = 0; i < pE->uNumCylinders; i++) {
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700296 QCBORDecode_GetDouble(&DecodeCtx,
297 &(pE->cylinders[i].dMeasuredCompression));
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700298 }
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200299#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700300 QCBORDecode_ExitArray(&DecodeCtx);
301 QCBORDecode_ExitMap(&DecodeCtx);
302
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700303 /* Catch further decoding error here */
Laurence Lundblade06c83042020-07-03 23:04:53 -0700304 uErr = QCBORDecode_Finish(&DecodeCtx);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700305
Laurence Lundblade06c83042020-07-03 23:04:53 -0700306Done:
307 return ConvertError(uErr);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700308}
309
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700310
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300311int32_t RunQCborExample(void)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700312{
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700313 CarEngine InitialEngine;
314 CarEngine DecodedEngine;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700315
Laurence Lundblade8510f8c2020-12-01 11:31:16 -0800316 /* For every buffer used by QCBOR a pointer and a length are always
317 * carried in a UsefulBuf. This is a secure coding and hygene
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700318 * practice to help make sure code never runs off the end of a
319 * buffer.
Laurence Lundblade8510f8c2020-12-01 11:31:16 -0800320 *
321 * UsefulBuf structures are passed as a stack parameter to make the
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700322 * code prettier. The object code generated isn't much different
323 * from passing a pointer parameter and a length parameter.
Laurence Lundblade8510f8c2020-12-01 11:31:16 -0800324 *
325 * This macro is equivalent to:
326 * uint8_t __pBufEngineBuffer[300];
327 * UsefulBuf EngineBuffer = {__pBufEngineBuffer, 300};
328 */
329 UsefulBuf_MAKE_STACK_UB( EngineBuffer, 300);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700330
Laurence Lundblade8510f8c2020-12-01 11:31:16 -0800331 /* The pointer in UsefulBuf is not const and used for representing
332 * a buffer to be written to. For UsefulbufC, the pointer is const
333 * and is used to represent a buffer that has been written to.
334 */
335 UsefulBufC EncodedEngine;
Laurence Lundblade8510f8c2020-12-01 11:31:16 -0800336 EngineDecodeErrors uErr;
Laurence Lundblade1818e632020-07-26 04:14:08 -0700337
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700338 /* Initialize the structure with some values. */
339 EngineInit(&InitialEngine);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700340
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700341 /* Encode the engine structure. */
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700342 EncodedEngine = EncodeEngine(&InitialEngine, EngineBuffer);
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700343 if(UsefulBuf_IsNULLC(EncodedEngine)) {
344 printf("Engine encode failed\n");
345 goto Done;
346 }
347 printf("Example: Definite Length Engine Encoded in %zu bytes\n",
348 EncodedEngine.len);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700349
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700350 /* Decode the CBOR */
Laurence Lundbladec4474172020-10-02 14:52:16 -0700351 uErr = DecodeEngineSpiffy(EncodedEngine, &DecodedEngine);
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700352 printf("Example: Spiffy Engine Decode Result: %d\n", uErr);
353 if(uErr) {
354 goto Done;
Laurence Lundbladec4474172020-10-02 14:52:16 -0700355 }
Laurence Lundbladee6bbf552020-07-05 22:57:57 -0700356
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700357 /* Check the results */
358 if(!EngineCompare(&InitialEngine, &DecodedEngine)) {
359 printf("Example: Spiffy Engine Decode comparison fail\n");
Laurence Lundbladec4474172020-10-02 14:52:16 -0700360 }
Laurence Lundbladee6bbf552020-07-05 22:57:57 -0700361
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700362
363 /* Further example of how to calculate the encoded size, then allocate */
364 UsefulBufC EncodedEngineSize;
365 EncodedEngineSize = EncodeEngine(&InitialEngine, SizeCalculateUsefulBuf);
366 if(UsefulBuf_IsNULLC(EncodedEngine)) {
367 printf("Engine encode size calculation failed\n");
368 goto Done;
369 }
370 (void)EncodedEngineSize; /* Supress unsed variable warning */
371 /* Here malloc could be called to allocate a buffer. Then
372 * EncodeEngine() can be called a second time to actually
373 * encode. (The actual code is not live here to avoid a
374 * dependency on malloc()).
375 * UsefulBuf MallocedBuffer;
376 * MallocedBuffer.len = EncodedEngineSize.len;
377 * MallocedBuffer.ptr = malloc(EncodedEngineSize.len);
378 * EncodedEngine = EncodeEngine(&InitialEngine, MallocedBuffer);
379 */
380
Laurence Lundblade5c91eb32021-04-03 23:56:54 -0700381Done:
Laurence Lundbladec4474172020-10-02 14:52:16 -0700382 printf("\n");
383
384 return 0;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -0700385}