Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 1 | /* ========================================================================= |
| 2 | example.c -- Example code for QCBOR |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 3 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 4 | Copyright (c) 2020, Laurence Lundblade. All rights reserved. |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 5 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 6 | SPDX-License-Identifier: BSD-3-Clause |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 7 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 8 | See BSD-3-Clause license in README.md |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 9 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 10 | Created on 6/30/2020 |
| 11 | ========================================================================== */ |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 12 | |
| 13 | #include <stdio.h> |
| 14 | #include "example.h" |
| 15 | #include "qcbor/qcbor_encode.h" |
| 16 | #include "qcbor/qcbor_decode.h" |
Laurence Lundblade | 67257dc | 2020-07-27 03:33:37 -0700 | [diff] [blame] | 17 | #include "qcbor/qcbor_spiffy_decode.h" |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 18 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 19 | |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 20 | #define MAX_CYLINDERS 16 |
| 21 | |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 22 | /** |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 23 | The data structure representing a car engine that is encoded and |
| 24 | decoded in this example. |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 25 | */ |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 26 | typedef struct |
| 27 | { |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 28 | UsefulBufC Manufacturer; |
| 29 | int64_t uDisplacement; |
| 30 | int64_t uHorsePower; |
| 31 | double dDesignedCompresion; |
| 32 | int64_t uNumCylinders; |
| 33 | bool bTurboCharged; |
| 34 | struct { |
| 35 | double uMeasuredCompression; |
| 36 | } cylinders[MAX_CYLINDERS]; |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 37 | } CarEngine; |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 38 | |
| 39 | |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 40 | /** |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 41 | @brief Initialize the Engine data structure with values to encode/decode. |
| 42 | |
| 43 | @param[out] pE The Engine structure to fill in |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 44 | */ |
| 45 | void EngineInit(CarEngine *pE) |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 46 | { |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 47 | pE->Manufacturer = UsefulBuf_FROM_SZ_LITERAL("Porsche"); |
| 48 | pE->uDisplacement = 3296; |
| 49 | pE->uHorsePower = 210; |
| 50 | pE->dDesignedCompresion = 9.1; |
| 51 | pE->uNumCylinders = 6; |
| 52 | pE->bTurboCharged = false; |
| 53 | |
| 54 | pE->cylinders[0].uMeasuredCompression = 9.0; |
| 55 | pE->cylinders[1].uMeasuredCompression = 9.2; |
| 56 | pE->cylinders[2].uMeasuredCompression = 8.9; |
| 57 | pE->cylinders[3].uMeasuredCompression = 8.9; |
| 58 | pE->cylinders[4].uMeasuredCompression = 9.1; |
| 59 | pE->cylinders[5].uMeasuredCompression = 9.0; |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 60 | } |
| 61 | |
| 62 | |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 63 | /** |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 64 | @brief Compare two Engine structure for equality. |
| 65 | |
| 66 | @param[in] pE1 First Engine to compare. |
| 67 | @param[in] pE2 Second Engine to compare. |
| 68 | |
| 69 | @retval Return @c true if the two Engine data structures are exactly the |
| 70 | same. |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 71 | */ |
| 72 | bool EngineCompare(CarEngine *pE1, CarEngine *pE2) |
Laurence Lundblade | e6bbf55 | 2020-07-05 22:57:57 -0700 | [diff] [blame] | 73 | { |
| 74 | if(pE1->uNumCylinders != pE2->uNumCylinders) { |
| 75 | return false; |
| 76 | } |
| 77 | if(pE1->bTurboCharged != pE2->bTurboCharged) { |
| 78 | return false; |
| 79 | } |
| 80 | if(pE1->uDisplacement != pE2->uDisplacement) { |
| 81 | return false; |
| 82 | } |
| 83 | if(pE1->uHorsePower != pE2->uHorsePower) { |
| 84 | return false; |
| 85 | } |
| 86 | if(pE1->dDesignedCompresion != pE2->dDesignedCompresion) { |
| 87 | return false; |
| 88 | } |
| 89 | for(int64_t i = 0; i < pE2->uNumCylinders; i++) { |
| 90 | if(pE1->cylinders[i].uMeasuredCompression != |
| 91 | pE2->cylinders[i].uMeasuredCompression) { |
| 92 | return false; |
| 93 | } |
| 94 | } |
| 95 | |
| 96 | if(UsefulBuf_Compare(pE1->Manufacturer, pE2->Manufacturer)) { |
| 97 | return false; |
| 98 | } |
| 99 | |
| 100 | return true; |
| 101 | } |
| 102 | |
| 103 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 104 | #ifndef EXAMPLE_DISABLE_DEFINITE_LENGTH_ENCODE |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 105 | /** |
| 106 | @brief Encode an initialized Engine data structure in CBOR. |
| 107 | |
| 108 | @param[in] pEngine The data structure to encode. |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 109 | @param[in] Buffer Pointer and length of buffer to output to. |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 110 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 111 | @return The pointer and length of the encoded CBOR or |
| 112 | @ref NULLUsefulBufC on error. |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 113 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 114 | This is a simple CBOR encoding example. It outputs the Engine data |
| 115 | structure as a map of label-value pairs as well as an array of |
| 116 | floating point values. |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 117 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 118 | @c Buffer must be big enough to hold the output. If it is not @ref |
| 119 | NULLUsefulBufC will be returned. @ref @ref NULLUsefulBufC will be |
| 120 | returned for any other encoding errors. |
| 121 | |
| 122 | This encoding will use definite CBOR lengths. Definite lengths are |
| 123 | preferred in CBOR. See EncodeEngineIndefinteLen() that encodes using |
| 124 | indefinite lengths. |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 125 | */ |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 126 | UsefulBufC EncodeEngineDefiniteLength(const CarEngine *pEngine, UsefulBuf Buffer) |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 127 | { |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 128 | /* Initialize the encoder with the buffer big enough to hold the |
| 129 | expected output. If it is too small, QCBOREncode_Finish() will |
| 130 | return an error. */ |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 131 | QCBOREncodeContext EncodeCtx; |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 132 | QCBOREncode_Init(&EncodeCtx, Buffer); |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 133 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 134 | /* Proceed to output all the items, letting the internal error |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 135 | tracking do its work. */ |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 136 | QCBOREncode_OpenMap(&EncodeCtx); |
| 137 | QCBOREncode_AddTextToMap(&EncodeCtx, "Manufacturer", pEngine->Manufacturer); |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 138 | QCBOREncode_AddInt64ToMap(&EncodeCtx, "NumCylinders", pEngine->uNumCylinders); |
| 139 | QCBOREncode_AddInt64ToMap(&EncodeCtx, "Displacement", pEngine->uDisplacement); |
| 140 | QCBOREncode_AddInt64ToMap(&EncodeCtx, "Horsepower", pEngine->uHorsePower); |
Laurence Lundblade | e6bbf55 | 2020-07-05 22:57:57 -0700 | [diff] [blame] | 141 | QCBOREncode_AddDoubleToMap(&EncodeCtx, "DesignedCompression", pEngine->dDesignedCompresion); |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 142 | QCBOREncode_OpenArrayInMap(&EncodeCtx, "Cylinders"); |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 143 | for(int64_t i = 0 ; i < pEngine->uNumCylinders; i++) { |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 144 | QCBOREncode_AddDouble(&EncodeCtx, pEngine->cylinders[i].uMeasuredCompression); |
| 145 | } |
| 146 | QCBOREncode_CloseArray(&EncodeCtx); |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 147 | QCBOREncode_AddBoolToMap(&EncodeCtx, "Turbo", pEngine->bTurboCharged); |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 148 | QCBOREncode_CloseMap(&EncodeCtx); |
| 149 | |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 150 | /* Get the pointer and length of the encoded output. If there was |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 151 | any error it will be returned here. */ |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 152 | UsefulBufC EncodedCBOR; |
| 153 | QCBORError uErr; |
| 154 | uErr = QCBOREncode_Finish(&EncodeCtx, &EncodedCBOR); |
| 155 | if(uErr != QCBOR_SUCCESS) { |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 156 | return NULLUsefulBufC; |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 157 | } else { |
| 158 | return EncodedCBOR; |
| 159 | } |
| 160 | } |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 161 | #endif /* EXAMPLE_DISABLE_DEFINITE_LENGTH_ENCODE */ |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 162 | |
| 163 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 164 | |
| 165 | |
| 166 | #ifndef EXAMPLE_DISABLE_INDEFINITE_LENGTH_ENCODE_ENCODE |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 167 | /** |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 168 | @brief Encode an initialized Engine data structure using indefinite lengths. |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 169 | |
| 170 | @param[in] pEngine The data structure to encode. |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 171 | @param[in] Buffer Pointer and length of buffer to output to. |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 172 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 173 | @return The pointer and length of the encoded CBOR or |
| 174 | @ref NULLUsefulBufC on error. |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 175 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 176 | This is virtually the same as EncodeEngineDefiniteLength(). The |
| 177 | encoded CBOR is slightly different as the map and array use |
| 178 | indefinite lengths, rather than definite lengths. |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 179 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 180 | A definite length array is encoded as an integer indicating the |
| 181 | number of items in it. An indefinite length array is encoded as an |
| 182 | opening byte, the items in it and a "break" byte to end |
| 183 | it. Indefinite length arrays and maps are easier to encode, but |
| 184 | harder to decode. |
| 185 | |
| 186 | The advantage of this implementation is that the encoding side will |
| 187 | be a little less object code. (Eventually QCBOR will an ifdef to |
| 188 | disable definite length encoding and the object code will be even |
| 189 | smaller). However, note that the encoding implementation for a |
| 190 | protocol is just about always much smaller than the decoding |
| 191 | implementation and that code savings for use of indefinite lengths is |
| 192 | relatively small. |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 193 | */ |
| 194 | UsefulBufC EncodeEngineIndefinteLen(const CarEngine *pEngine, UsefulBuf Buffer) |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 195 | { |
| 196 | QCBOREncodeContext EncodeCtx; |
| 197 | |
| 198 | QCBOREncode_Init(&EncodeCtx, Buffer); |
| 199 | QCBOREncode_OpenMapIndefiniteLength(&EncodeCtx); |
| 200 | QCBOREncode_AddTextToMap(&EncodeCtx, "Manufacturer", pEngine->Manufacturer); |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 201 | QCBOREncode_AddInt64ToMap(&EncodeCtx, "Displacement", pEngine->uDisplacement); |
| 202 | QCBOREncode_AddInt64ToMap(&EncodeCtx, "Horsepower", pEngine->uHorsePower); |
Laurence Lundblade | e6bbf55 | 2020-07-05 22:57:57 -0700 | [diff] [blame] | 203 | QCBOREncode_AddDoubleToMap(&EncodeCtx, "DesignedCompression", pEngine->dDesignedCompresion); |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 204 | QCBOREncode_AddInt64ToMap(&EncodeCtx, "NumCylinders", pEngine->uNumCylinders); |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 205 | QCBOREncode_OpenArrayIndefiniteLengthInMap(&EncodeCtx, "Cylinders"); |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 206 | for(int64_t i = 0 ; i < pEngine->uNumCylinders; i++) { |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 207 | QCBOREncode_AddDouble(&EncodeCtx, pEngine->cylinders[i].uMeasuredCompression); |
| 208 | } |
| 209 | QCBOREncode_CloseArrayIndefiniteLength(&EncodeCtx); |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 210 | QCBOREncode_AddBoolToMap(&EncodeCtx, "Turbo", pEngine->bTurboCharged); |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 211 | QCBOREncode_CloseMapIndefiniteLength(&EncodeCtx); |
| 212 | |
| 213 | UsefulBufC EncodedCBOR; |
| 214 | QCBORError uErr; |
| 215 | uErr = QCBOREncode_Finish(&EncodeCtx, &EncodedCBOR); |
| 216 | if(uErr != QCBOR_SUCCESS) { |
| 217 | return NULLUsefulBufC; |
| 218 | } else { |
| 219 | return EncodedCBOR; |
| 220 | } |
| 221 | } |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 222 | #endif /* EXAMPLE_DISABLE_INDEFINITE_LENGTH_ENCODE */ |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 223 | |
| 224 | |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 225 | /** |
| 226 | Error results when decoding an Engine data structure. |
| 227 | */ |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 228 | typedef enum { |
| 229 | EngineSuccess, |
| 230 | CBORNotWellFormed, |
| 231 | TooManyCylinders, |
| 232 | EngineProtocolerror, |
| 233 | WrongNumberOfCylinders |
| 234 | } EngineDecodeErrors; |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 235 | |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 236 | |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 237 | /** |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 238 | Convert @ref QCBORError to @ref EngineDecodeErrors. |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 239 | */ |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 240 | EngineDecodeErrors ConvertError(QCBORError uErr) |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 241 | { |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 242 | EngineDecodeErrors uReturn; |
| 243 | |
| 244 | switch(uErr) |
| 245 | { |
| 246 | case QCBOR_SUCCESS: |
| 247 | uReturn = EngineSuccess; |
| 248 | break; |
| 249 | |
| 250 | case QCBOR_ERR_HIT_END: |
| 251 | uReturn = CBORNotWellFormed; |
| 252 | break; |
| 253 | |
| 254 | default: |
| 255 | uReturn = EngineProtocolerror; |
| 256 | break; |
| 257 | } |
| 258 | |
| 259 | return uReturn; |
| 260 | } |
| 261 | |
| 262 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 263 | #ifndef EXAMPLE_DISABLE_SPIFFY_DECODE |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 264 | /** |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 265 | @brief Simplest engine decode using spiffy decode features. |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 266 | |
| 267 | @param[in] EncodedEngine Pointer and length of CBOR-encoded engine. |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 268 | @param[out] pE The structure filled in from the decoding. |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 269 | |
| 270 | @return The decode error or success. |
| 271 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 272 | This decodes the CBOR into the engine structure. |
| 273 | |
| 274 | As QCBOR automatically supports both definite and indefinite maps and |
| 275 | arrays, this will decode either. |
| 276 | |
| 277 | This uses QCBOR's spiffy decode, so the implementation is simplest |
| 278 | and closely parallels the encode implementation in |
| 279 | EncodeEngineDefiniteLength(). |
| 280 | |
| 281 | See two other ways to implement decoding in |
| 282 | DecodeEngineSpiffyFaster() and DecodeEngineBasic(). |
| 283 | |
| 284 | This version of the decoder has the simplest implementation, but |
| 285 | pulls in more code from the QCBOR library. This version uses the |
| 286 | most CPU cycles because it scans the all the CBOR each time a data |
| 287 | item is decoded. The CPU cycles used for a data structure as small as |
| 288 | this is probably insignificant. CPU use for this style of decode is |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 289 | probably only a factor on slow CPUs with big CBOR inputs. |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 290 | */ |
Laurence Lundblade | 67257dc | 2020-07-27 03:33:37 -0700 | [diff] [blame] | 291 | EngineDecodeErrors DecodeEngineSpiffy(UsefulBufC EncodedEngine, CarEngine *pE) |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 292 | { |
| 293 | QCBORError uErr; |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 294 | QCBORDecodeContext DecodeCtx; |
| 295 | |
| 296 | QCBORDecode_Init(&DecodeCtx, EncodedEngine, QCBOR_DECODE_MODE_NORMAL); |
| 297 | QCBORDecode_EnterMap(&DecodeCtx); |
Laurence Lundblade | 323f8a9 | 2020-09-06 19:43:09 -0700 | [diff] [blame] | 298 | QCBORDecode_GetTextStringInMapSZ(&DecodeCtx, "Manufacturer", &(pE->Manufacturer)); |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 299 | QCBORDecode_GetInt64InMapSZ(&DecodeCtx, "Displacement", &(pE->uDisplacement)); |
| 300 | QCBORDecode_GetInt64InMapSZ(&DecodeCtx, "Horsepower", &(pE->uHorsePower)); |
Laurence Lundblade | e6bbf55 | 2020-07-05 22:57:57 -0700 | [diff] [blame] | 301 | QCBORDecode_GetDoubleInMapSZ(&DecodeCtx, "DesignedCompression", &(pE->dDesignedCompresion)); |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 302 | QCBORDecode_GetBoolInMapSZ(&DecodeCtx, "Turbo", &(pE->bTurboCharged)); |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 303 | |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 304 | QCBORDecode_GetInt64InMapSZ(&DecodeCtx, "NumCylinders", &(pE->uNumCylinders)); |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 305 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 306 | /* Must check error before referencing pE->uNumCylinders to be |
| 307 | sure it is valid. If any of the above errored, it won't be |
| 308 | valid. */ |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 309 | uErr = QCBORDecode_GetError(&DecodeCtx); |
| 310 | if(uErr != QCBOR_SUCCESS) { |
| 311 | goto Done; |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 312 | } |
| 313 | |
| 314 | if(pE->uNumCylinders > MAX_CYLINDERS) { |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 315 | return TooManyCylinders; |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 316 | } |
| 317 | |
| 318 | QCBORDecode_EnterArrayFromMapSZ(&DecodeCtx, "Cylinders"); |
Laurence Lundblade | e6bbf55 | 2020-07-05 22:57:57 -0700 | [diff] [blame] | 319 | for(int64_t i = 0; i < pE->uNumCylinders; i++) { |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 320 | QCBORDecode_GetDouble(&DecodeCtx, &(pE->cylinders[i].uMeasuredCompression)); |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 321 | } |
| 322 | QCBORDecode_ExitArray(&DecodeCtx); |
| 323 | QCBORDecode_ExitMap(&DecodeCtx); |
| 324 | |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 325 | /* Catch the remainder of errors here */ |
| 326 | uErr = QCBORDecode_Finish(&DecodeCtx); |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 327 | |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 328 | Done: |
| 329 | return ConvertError(uErr); |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 330 | } |
| 331 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 332 | #endif /* EXAMPLE_DISABLE_SPIFFY_DECODE */ |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 333 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 334 | |
| 335 | |
| 336 | #ifndef EXAMPLE_DISABLE_SPIFFY_DECODE_FAST |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 337 | /** |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 338 | @brief Decode an Engine structure with the faster spiffy decode features. |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 339 | |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 340 | @param[in] EncodedEngine Pointer and length of CBOR-encoded engine. |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 341 | @param[out] pE The structure filled in from the decoding. |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 342 | |
| 343 | @return The decode error or success. |
| 344 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 345 | This decodes the same as DecodeEngineSpiffy(), but uses different |
| 346 | spiffy decode features. |
| 347 | |
| 348 | This version uses QCBORDecode_GetItemsInMap() which uses less CPU |
| 349 | cycles because all the items except the array are pulled out of the |
| 350 | map in one pass, rather than having to decode the whole map for each |
| 351 | decoded item. This also pulls in less object code from the QCBOR |
| 352 | library. |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 353 | |
| 354 | See also DecodeEngineAdvanced() and DecodeEngineBasic(). |
| 355 | */ |
Laurence Lundblade | 67257dc | 2020-07-27 03:33:37 -0700 | [diff] [blame] | 356 | EngineDecodeErrors DecodeEngineSpiffyFaster(UsefulBufC EncodedEngine, CarEngine *pE) |
Laurence Lundblade | e6bbf55 | 2020-07-05 22:57:57 -0700 | [diff] [blame] | 357 | { |
| 358 | QCBORError uErr; |
| 359 | QCBORDecodeContext DecodeCtx; |
| 360 | |
| 361 | QCBORDecode_Init(&DecodeCtx, EncodedEngine, QCBOR_DECODE_MODE_NORMAL); |
| 362 | QCBORDecode_EnterMap(&DecodeCtx); |
| 363 | |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 364 | QCBORItem EngineItems[7]; |
| 365 | EngineItems[0].uLabelType = QCBOR_TYPE_TEXT_STRING; |
| 366 | EngineItems[0].label.string = UsefulBuf_FROM_SZ_LITERAL("Manufacturer"); |
| 367 | EngineItems[0].uDataType = QCBOR_TYPE_TEXT_STRING; |
Laurence Lundblade | e6bbf55 | 2020-07-05 22:57:57 -0700 | [diff] [blame] | 368 | |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 369 | EngineItems[1].uLabelType = QCBOR_TYPE_TEXT_STRING; |
| 370 | EngineItems[1].label.string = UsefulBuf_FROM_SZ_LITERAL("Displacement"); |
| 371 | EngineItems[1].uDataType = QCBOR_TYPE_INT64; |
Laurence Lundblade | e6bbf55 | 2020-07-05 22:57:57 -0700 | [diff] [blame] | 372 | |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 373 | EngineItems[2].uLabelType = QCBOR_TYPE_TEXT_STRING; |
| 374 | EngineItems[2].label.string = UsefulBuf_FROM_SZ_LITERAL("Horsepower"); |
| 375 | EngineItems[2].uDataType = QCBOR_TYPE_INT64; |
Laurence Lundblade | e6bbf55 | 2020-07-05 22:57:57 -0700 | [diff] [blame] | 376 | |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 377 | EngineItems[3].uLabelType = QCBOR_TYPE_TEXT_STRING; |
| 378 | EngineItems[3].label.string = UsefulBuf_FROM_SZ_LITERAL("DesignedCompression"); |
| 379 | EngineItems[3].uDataType = QCBOR_TYPE_DOUBLE; |
Laurence Lundblade | e6bbf55 | 2020-07-05 22:57:57 -0700 | [diff] [blame] | 380 | |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 381 | EngineItems[4].uLabelType = QCBOR_TYPE_TEXT_STRING; |
| 382 | EngineItems[4].label.string = UsefulBuf_FROM_SZ_LITERAL("Turbo"); |
| 383 | EngineItems[4].uDataType = QCBOR_TYPE_ANY; |
Laurence Lundblade | e6bbf55 | 2020-07-05 22:57:57 -0700 | [diff] [blame] | 384 | |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 385 | EngineItems[5].uLabelType = QCBOR_TYPE_TEXT_STRING; |
| 386 | EngineItems[5].label.string = UsefulBuf_FROM_SZ_LITERAL("NumCylinders"); |
| 387 | EngineItems[5].uDataType = QCBOR_TYPE_INT64; |
Laurence Lundblade | e6bbf55 | 2020-07-05 22:57:57 -0700 | [diff] [blame] | 388 | |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 389 | EngineItems[6].uLabelType = QCBOR_TYPE_NONE; |
Laurence Lundblade | e6bbf55 | 2020-07-05 22:57:57 -0700 | [diff] [blame] | 390 | |
Laurence Lundblade | 5f53f83 | 2020-09-03 12:00:14 -0700 | [diff] [blame] | 391 | QCBORDecode_GetItemsInMap(&DecodeCtx, EngineItems); |
| 392 | uErr = QCBORDecode_GetError(&DecodeCtx); |
Laurence Lundblade | e6bbf55 | 2020-07-05 22:57:57 -0700 | [diff] [blame] | 393 | if(uErr != QCBOR_SUCCESS) { |
| 394 | goto Done; |
| 395 | } |
| 396 | |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 397 | pE->Manufacturer = EngineItems[0].val.string; |
| 398 | pE->uDisplacement = EngineItems[1].val.int64; |
| 399 | pE->uHorsePower = EngineItems[2].val.int64; |
| 400 | pE->dDesignedCompresion = EngineItems[3].val.dfnum; |
| 401 | pE->uNumCylinders = EngineItems[5].val.int64; |
Laurence Lundblade | e6bbf55 | 2020-07-05 22:57:57 -0700 | [diff] [blame] | 402 | |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 403 | if(EngineItems[4].uDataType == QCBOR_TYPE_TRUE) { |
Laurence Lundblade | e6bbf55 | 2020-07-05 22:57:57 -0700 | [diff] [blame] | 404 | pE->bTurboCharged = true; |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 405 | } else if(EngineItems[4].uDataType == QCBOR_TYPE_FALSE) { |
Laurence Lundblade | e6bbf55 | 2020-07-05 22:57:57 -0700 | [diff] [blame] | 406 | pE->bTurboCharged = false; |
| 407 | } else { |
| 408 | return EngineProtocolerror; |
| 409 | } |
| 410 | |
| 411 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 412 | /* Must check error before referencing pE->uNumCylinders to be |
| 413 | sure it is valid. If any of the above errored, it won't be |
| 414 | valid. */ |
Laurence Lundblade | e6bbf55 | 2020-07-05 22:57:57 -0700 | [diff] [blame] | 415 | uErr = QCBORDecode_GetError(&DecodeCtx); |
| 416 | if(uErr != QCBOR_SUCCESS) { |
| 417 | goto Done; |
| 418 | } |
| 419 | |
| 420 | if(pE->uNumCylinders > MAX_CYLINDERS) { |
| 421 | return TooManyCylinders; |
| 422 | } |
| 423 | |
| 424 | QCBORDecode_EnterArrayFromMapSZ(&DecodeCtx, "Cylinders"); |
| 425 | for(int64_t i = 0; i < pE->uNumCylinders; i++) { |
| 426 | QCBORDecode_GetDouble(&DecodeCtx, &(pE->cylinders[i].uMeasuredCompression)); |
| 427 | } |
| 428 | QCBORDecode_ExitArray(&DecodeCtx); |
| 429 | QCBORDecode_ExitMap(&DecodeCtx); |
| 430 | |
| 431 | /* Catch the remainder of errors here */ |
| 432 | uErr = QCBORDecode_Finish(&DecodeCtx); |
| 433 | |
| 434 | Done: |
| 435 | return ConvertError(uErr); |
| 436 | } |
| 437 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 438 | #endif /* EXAMPLE_DISABLE_SPIFFY_DECODE_FAST */ |
Laurence Lundblade | e6bbf55 | 2020-07-05 22:57:57 -0700 | [diff] [blame] | 439 | |
| 440 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 441 | #ifndef EXAMPLE_DISABLE_BASIC_DECODE |
Laurence Lundblade | 1818e63 | 2020-07-26 04:14:08 -0700 | [diff] [blame] | 442 | /** |
| 443 | @brief Check the type and lable of an item. |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 444 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 445 | @param[in] szLabel The expected string label. |
| 446 | @param[in] uQCBORType The expected type or @c QCBOR_TYPE_ANY. |
| 447 | @param[in] pItem The item to check. |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 448 | |
Laurence Lundblade | a9489f8 | 2020-09-12 13:50:56 -0700 | [diff] [blame] | 449 | @retval QCBOR_ERR_LABEL_NOT_FOUND The label doesn't match. |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 450 | @retval QCBOR_ERR_UNEXPECTED_TYPE The label matches, but the type is |
| 451 | not as expected. |
| 452 | @retval QCBOR_SUCCESS Both label and type match. |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 453 | */ |
Laurence Lundblade | 1818e63 | 2020-07-26 04:14:08 -0700 | [diff] [blame] | 454 | QCBORError CheckLabelAndType(const char *szLabel, uint8_t uQCBORType, const QCBORItem *pItem) |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 455 | { |
| 456 | if(pItem->uLabelType != QCBOR_TYPE_TEXT_STRING) { |
Laurence Lundblade | a9489f8 | 2020-09-12 13:50:56 -0700 | [diff] [blame] | 457 | return QCBOR_ERR_LABEL_NOT_FOUND; |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 458 | } |
| 459 | |
| 460 | UsefulBufC Label = UsefulBuf_FromSZ(szLabel); |
| 461 | |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 462 | if(UsefulBuf_Compare(Label, pItem->label.string)) { |
Laurence Lundblade | a9489f8 | 2020-09-12 13:50:56 -0700 | [diff] [blame] | 463 | return QCBOR_ERR_LABEL_NOT_FOUND; |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 464 | } |
| 465 | |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 466 | if(pItem->uDataType != uQCBORType && uQCBORType != QCBOR_TYPE_ANY) { |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 467 | return QCBOR_ERR_UNEXPECTED_TYPE; |
| 468 | } |
| 469 | |
| 470 | return QCBOR_SUCCESS; |
| 471 | } |
| 472 | |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 473 | |
Laurence Lundblade | 1818e63 | 2020-07-26 04:14:08 -0700 | [diff] [blame] | 474 | /** |
| 475 | @brief Decode the array of engine cylinders. |
| 476 | |
| 477 | @param[in] pDecodeCtx The decode context from which to get items. |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 478 | @param[out] pE The structure filled in from the decoding. |
| 479 | @param[in] pItem The data item that is the start of the array. |
Laurence Lundblade | 1818e63 | 2020-07-26 04:14:08 -0700 | [diff] [blame] | 480 | |
| 481 | @return Either @ref EngineSuccess or an error. |
| 482 | |
| 483 | This always consumes the whole array. If it has the wrong number of |
| 484 | items in it, an error is returned. |
| 485 | */ |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 486 | EngineDecodeErrors DecodeCylinders(QCBORDecodeContext *pDecodeCtx, |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 487 | CarEngine *pE, |
| 488 | const QCBORItem *pItem) |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 489 | { |
| 490 | int i = 0; |
| 491 | QCBORItem Item; |
| 492 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 493 | /* Loop getting all the items in the array. This uses nesting |
| 494 | level to detect the end so it works for both definite and |
| 495 | indefinite length arrays. */ |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 496 | do { |
| 497 | QCBORError uErr; |
| 498 | |
| 499 | uErr = QCBORDecode_GetNext(pDecodeCtx, &Item); |
| 500 | if(uErr != QCBOR_SUCCESS) { |
| 501 | return CBORNotWellFormed; |
| 502 | } |
| 503 | if(Item.uDataType != QCBOR_TYPE_DOUBLE) { |
| 504 | return CBORNotWellFormed; |
| 505 | } |
| 506 | |
| 507 | if(i < MAX_CYLINDERS) { |
| 508 | pE->cylinders[i].uMeasuredCompression = Item.val.dfnum; |
| 509 | i++; |
| 510 | } |
| 511 | |
| 512 | } while (Item.uNextNestLevel == pItem->uNextNestLevel); |
| 513 | |
| 514 | if(i != pE->uNumCylinders) { |
| 515 | return WrongNumberOfCylinders; |
| 516 | } else { |
| 517 | return EngineSuccess; |
| 518 | } |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 519 | } |
| 520 | |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 521 | |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 522 | /** |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 523 | @brief Engine decode without spiffy decode. |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 524 | |
Laurence Lundblade | 1818e63 | 2020-07-26 04:14:08 -0700 | [diff] [blame] | 525 | @param[in] EncodedEngine Pointer and length of CBOR-encoded engine. |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 526 | @param[out] pE The structure filled in from the decoding. |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 527 | |
Laurence Lundblade | 1818e63 | 2020-07-26 04:14:08 -0700 | [diff] [blame] | 528 | @return The decode error or success. |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 529 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 530 | This is the third implementation of engine decoding, again |
| 531 | implementing the same functionality as DecodeEngineSpiffy() and |
| 532 | DecodeEngineSpiffyFaster(). |
| 533 | |
Laurence Lundblade | 1818e63 | 2020-07-26 04:14:08 -0700 | [diff] [blame] | 534 | This version of the deocde is the most complex, but uses |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 535 | significantly less code (2-3KB less on 64-bit Intel) from the QCBOR |
| 536 | library. It is also the most CPU-efficient since it does only one |
| 537 | pass through the CBOR. |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 538 | */ |
| 539 | EngineDecodeErrors DecodeEngineBasic(UsefulBufC EncodedEngine, CarEngine *pE) |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 540 | { |
| 541 | QCBORDecodeContext DecodeCtx; |
| 542 | |
Laurence Lundblade | 323f8a9 | 2020-09-06 19:43:09 -0700 | [diff] [blame] | 543 | QCBORDecode_Init(&DecodeCtx, EncodedEngine, QCBOR_DECODE_MODE_NORMAL); |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 544 | |
| 545 | QCBORItem Item; |
| 546 | QCBORError uErr; |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 547 | EngineDecodeErrors uReturn; |
| 548 | |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 549 | |
| 550 | uErr = QCBORDecode_GetNext(&DecodeCtx, &Item); |
| 551 | if(uErr != QCBOR_SUCCESS) { |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 552 | uReturn = CBORNotWellFormed; |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 553 | goto Done; |
| 554 | } |
| 555 | if(Item.uDataType != QCBOR_TYPE_MAP) { |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 556 | uReturn = CBORNotWellFormed; |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 557 | goto Done; |
| 558 | } |
| 559 | |
| 560 | while(1) { |
| 561 | uErr = QCBORDecode_GetNext(&DecodeCtx, &Item); |
| 562 | if(uErr != QCBOR_SUCCESS) { |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 563 | if(uErr == QCBOR_ERR_NO_MORE_ITEMS) { |
| 564 | break; /* Non-error exit from the loop */ |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 565 | } else { |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 566 | uReturn = CBORNotWellFormed; |
| 567 | goto Done; |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 568 | } |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 569 | } |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 570 | |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 571 | uErr = CheckLabelAndType("Manufacturer", QCBOR_TYPE_TEXT_STRING, &Item); |
| 572 | if(uErr == QCBOR_SUCCESS) { |
| 573 | pE->Manufacturer = Item.val.string; |
| 574 | continue; |
Laurence Lundblade | a9489f8 | 2020-09-12 13:50:56 -0700 | [diff] [blame] | 575 | } else if(uErr != QCBOR_ERR_LABEL_NOT_FOUND){ |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 576 | /* Maunfacturer field missing or badly formed */ |
| 577 | return EngineProtocolerror; |
| 578 | } /* continue on and try for another match */ |
| 579 | |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 580 | uErr = CheckLabelAndType("NumCylinders", QCBOR_TYPE_INT64, &Item); |
| 581 | if(uErr == QCBOR_SUCCESS) { |
| 582 | if(Item.val.int64 > MAX_CYLINDERS) { |
| 583 | return TooManyCylinders; |
| 584 | } else { |
| 585 | pE->uNumCylinders = (uint8_t)Item.val.int64; |
| 586 | continue; |
| 587 | } |
Laurence Lundblade | a9489f8 | 2020-09-12 13:50:56 -0700 | [diff] [blame] | 588 | } else if(uErr != QCBOR_ERR_LABEL_NOT_FOUND){ |
Laurence Lundblade | 1818e63 | 2020-07-26 04:14:08 -0700 | [diff] [blame] | 589 | /* NumCylinders field missing or badly formed */ |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 590 | return EngineProtocolerror; |
Laurence Lundblade | 1818e63 | 2020-07-26 04:14:08 -0700 | [diff] [blame] | 591 | } /* continue on and try for another match */ |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 592 | |
| 593 | uErr = CheckLabelAndType("Cylinders", QCBOR_TYPE_ARRAY, &Item); |
| 594 | if(uErr == QCBOR_SUCCESS) { |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 595 | DecodeCylinders(&DecodeCtx, pE, &Item); |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 596 | continue; |
Laurence Lundblade | a9489f8 | 2020-09-12 13:50:56 -0700 | [diff] [blame] | 597 | } else if(uErr != QCBOR_ERR_LABEL_NOT_FOUND){ |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 598 | return EngineProtocolerror; |
| 599 | } |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 600 | |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 601 | uErr = CheckLabelAndType("Displacement", QCBOR_TYPE_INT64, &Item); |
| 602 | if(uErr == QCBOR_SUCCESS) { |
| 603 | pE->uDisplacement = Item.val.int64; |
| 604 | continue; |
Laurence Lundblade | a9489f8 | 2020-09-12 13:50:56 -0700 | [diff] [blame] | 605 | } else if(uErr != QCBOR_ERR_LABEL_NOT_FOUND){ |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 606 | return EngineProtocolerror; |
| 607 | } |
| 608 | |
| 609 | uErr = CheckLabelAndType("Horsepower", QCBOR_TYPE_INT64, &Item); |
| 610 | if(uErr == QCBOR_SUCCESS) { |
| 611 | pE->uHorsePower = Item.val.int64; |
| 612 | continue; |
Laurence Lundblade | a9489f8 | 2020-09-12 13:50:56 -0700 | [diff] [blame] | 613 | } else if(uErr != QCBOR_ERR_LABEL_NOT_FOUND){ |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 614 | return EngineProtocolerror; |
| 615 | } |
| 616 | |
| 617 | uErr = CheckLabelAndType("DesignedCompression", QCBOR_TYPE_DOUBLE, &Item); |
| 618 | if(uErr == QCBOR_SUCCESS) { |
Laurence Lundblade | e6bbf55 | 2020-07-05 22:57:57 -0700 | [diff] [blame] | 619 | pE->dDesignedCompresion = Item.val.dfnum; |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 620 | continue; |
Laurence Lundblade | a9489f8 | 2020-09-12 13:50:56 -0700 | [diff] [blame] | 621 | } else if(uErr != QCBOR_ERR_LABEL_NOT_FOUND){ |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 622 | return EngineProtocolerror; |
| 623 | } |
| 624 | |
Laurence Lundblade | da31928 | 2020-07-06 23:04:58 -0700 | [diff] [blame] | 625 | uErr = CheckLabelAndType("Turbo", QCBOR_TYPE_ANY, &Item); |
Laurence Lundblade | 1818e63 | 2020-07-26 04:14:08 -0700 | [diff] [blame] | 626 | if(uErr == QCBOR_SUCCESS) { |
| 627 | if(Item.uDataType == QCBOR_TYPE_TRUE) { |
| 628 | pE->bTurboCharged = true; |
| 629 | } else if(Item.uDataType == QCBOR_TYPE_FALSE) { |
| 630 | pE->bTurboCharged = false; |
| 631 | } else { |
| 632 | return EngineProtocolerror; |
| 633 | } |
| 634 | continue; |
Laurence Lundblade | a9489f8 | 2020-09-12 13:50:56 -0700 | [diff] [blame] | 635 | } else if(uErr != QCBOR_ERR_LABEL_NOT_FOUND){ |
Laurence Lundblade | 1818e63 | 2020-07-26 04:14:08 -0700 | [diff] [blame] | 636 | return EngineProtocolerror; |
| 637 | } |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 638 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 639 | /* Some label data item that is not known (could just ignore |
| 640 | extras data items) */ |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 641 | return EngineProtocolerror; |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 642 | } |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 643 | uReturn = EngineSuccess; |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 644 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 645 | /* Catch the remainder of errors here */ |
| 646 | uErr = QCBORDecode_Finish(&DecodeCtx); |
| 647 | if(uErr) { |
| 648 | uReturn = ConvertError(uErr); |
| 649 | } |
| 650 | |
| 651 | |
| 652 | |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 653 | Done: |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 654 | return uReturn; |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 655 | } |
| 656 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 657 | #endif /* EXAMPLE_DISABLE_BASIC_DECODE */ |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 658 | |
| 659 | |
Laurence Lundblade | 1818e63 | 2020-07-26 04:14:08 -0700 | [diff] [blame] | 660 | int32_t RunQCborExample() |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 661 | { |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 662 | CarEngine E, DecodedEngine; |
| 663 | MakeUsefulBufOnStack( EngineBuffer, 300); |
| 664 | UsefulBufC EncodedEngine; |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 665 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 666 | MakeUsefulBufOnStack( InDefEngineBuffer, 300); |
| 667 | UsefulBufC InDefEncodedEngine; |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 668 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 669 | EngineDecodeErrors uErr; |
Laurence Lundblade | 1818e63 | 2020-07-26 04:14:08 -0700 | [diff] [blame] | 670 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 671 | EngineInit(&E); |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 672 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 673 | #ifndef EXAMPLE_DISABLE_DEFINITE_LENGTH_ENCODE |
| 674 | EncodedEngine = EncodeEngineDefiniteLength(&E, EngineBuffer); |
| 675 | printf("Definite Length Engine Encoded in %zu bytes\n", EncodedEngine.len); |
| 676 | #endif /* EXAMPLE_DISABLE_DEFINITE_LENGTH_ENCODE */ |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 677 | |
| 678 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 679 | #ifndef EXAMPLE_DISABLE_INDEFINITE_LENGTH_ENCODE_ENCODE |
| 680 | InDefEncodedEngine = EncodeEngineIndefinteLen(&E, InDefEngineBuffer); |
| 681 | printf("Indef Engine Encoded in %zu bytes\n", InDefEncodedEngine.len); |
| 682 | #endif /* EXAMPLE_DISABLE_INDEFINITE_LENGTH_ENCODE_ENCODE */ |
Laurence Lundblade | e6bbf55 | 2020-07-05 22:57:57 -0700 | [diff] [blame] | 683 | |
Laurence Lundblade | 06c8304 | 2020-07-03 23:04:53 -0700 | [diff] [blame] | 684 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 685 | #ifndef EXAMPLE_DISABLE_SPIFFY_DECODE |
| 686 | uErr = DecodeEngineSpiffy(EncodedEngine, &DecodedEngine); |
| 687 | printf("Spiffy Engine Decode Result: %d\n", uErr); |
Laurence Lundblade | e6bbf55 | 2020-07-05 22:57:57 -0700 | [diff] [blame] | 688 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 689 | if(!EngineCompare(&E, &DecodedEngine)) { |
| 690 | printf("Spiffy Engine Decode comparison fail\n"); |
| 691 | } |
| 692 | #endif /* EXAMPLE_DISABLE_SPIFFY_DECODE */ |
Laurence Lundblade | e6bbf55 | 2020-07-05 22:57:57 -0700 | [diff] [blame] | 693 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 694 | #ifndef EXAMPLE_DISABLE_SPIFFY_DECODE_FAST |
| 695 | uErr = DecodeEngineSpiffyFaster(EncodedEngine, &DecodedEngine); |
| 696 | printf("Faster Spiffy Engine Decode Result: %d\n", uErr); |
Laurence Lundblade | e6bbf55 | 2020-07-05 22:57:57 -0700 | [diff] [blame] | 697 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 698 | if(!EngineCompare(&E, &DecodedEngine)) { |
| 699 | printf("Faster Spiffy Engine Decode comparison fail\n"); |
| 700 | } |
| 701 | #endif /* EXAMPLE_DISABLE_SPIFFY_DECODE_FAST */ |
Laurence Lundblade | e6bbf55 | 2020-07-05 22:57:57 -0700 | [diff] [blame] | 702 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 703 | #ifndef EXAMPLE_DISABLE_BASIC_DECODE |
| 704 | uErr = DecodeEngineBasic(EncodedEngine, &DecodedEngine); |
| 705 | printf("Engine Basic Decode Result: %d\n", uErr); |
Laurence Lundblade | e6bbf55 | 2020-07-05 22:57:57 -0700 | [diff] [blame] | 706 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 707 | if(!EngineCompare(&E, &DecodedEngine)) { |
| 708 | printf("Engine Basic Decode comparison fail\n"); |
| 709 | } |
| 710 | #endif /* EXAMPLE_DISABLE_BASIC_DECODE */ |
Laurence Lundblade | e6bbf55 | 2020-07-05 22:57:57 -0700 | [diff] [blame] | 711 | |
Laurence Lundblade | c447417 | 2020-10-02 14:52:16 -0700 | [diff] [blame^] | 712 | printf("\n"); |
| 713 | |
| 714 | return 0; |
Laurence Lundblade | d4cd723 | 2020-07-03 19:30:48 -0700 | [diff] [blame] | 715 | } |