blob: dc8450f15c7139d9448bf2d6d5c5799e401f4488 [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
Laurence Lundbladed92a6162018-11-01 11:38:35 +07002 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundbladeee851742020-01-08 08:37:05 -08003 Copyright (c) 2018-2020, Laurence Lundblade.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07004 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08005
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07006Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are
8met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15 * Neither the name of The Linux Foundation nor the names of its
16 contributors, nor the name "Laurence Lundblade" may be used to
17 endorse or promote products derived from this software without
18 specific prior written permission.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080019
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070020THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080031 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070032
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080033
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080034#include "qcbor/qcbor_decode.h"
Laurence Lundblade12d32c52018-09-19 11:25:27 -070035#include "ieee754.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070036
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070037
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053038/*
39 This casts away the const-ness of a pointer, usually so it can be
40 freed or realloced.
41 */
42#define UNCONST_POINTER(ptr) ((void *)(ptr))
43
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070044
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070045
Laurence Lundblade02625d42020-06-25 14:41:41 -070046inline static bool
47// TODO: add more tests for QCBOR_TYPE_MAP_AS_ARRAY mode in qcbor_decode_tests.c
48QCBORItem_IsMapOrArray(const QCBORItem *pMe)
49{
50 const uint8_t uDataType = pMe->uDataType;
51 return uDataType == QCBOR_TYPE_MAP ||
52 uDataType == QCBOR_TYPE_ARRAY ||
53 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
54}
55
56inline static bool
57QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem *pMe)
58{
59 if(!QCBORItem_IsMapOrArray(pMe)){
60 return false;
61 }
62
63 if(pMe->val.uCount != 0) {
64 return false;
65 }
66 return true;
67}
68
69inline static bool
70QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem *pMe)
71{
72 if(!QCBORItem_IsMapOrArray(pMe)){
73 return false;
74 }
75
76 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
77 return false;
78 }
79 return true;
80}
81
82
Laurence Lundbladeee851742020-01-08 08:37:05 -080083/*===========================================================================
Laurence Lundblade02625d42020-06-25 14:41:41 -070084 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080085
Laurence Lundblade02625d42020-06-25 14:41:41 -070086 See qcbor/qcbor_private.h for definition of the object
87 described here: QCBORDecodeNesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080088 ===========================================================================*/
89
Laurence Lundblade9c905e82020-04-25 11:31:38 -070090/*
91The main mode of decoding is a pre-order travesal of the tree of leaves (numbers, strings...)
92formed by intermediate nodes (arrays and maps). The cursor for the traversal
93 is the byte offset in the encoded input and a leaf counter for definite
94 length maps and arrays. Indefinite length maps and arrays are handled
95 by look ahead for the break.
96
97 The view presented to the caller has tags, labels and the chunks of
98 indefinite length strings aggregated into one decorated data item.
99
100The caller understands the nesting level in pre-order traversal by
101 the fact that a data item that is a map or array is presented to
102 the caller when it is first encountered in the pre-order traversal and that all data items are presented with its nesting level
103 and the nesting level of the next item.
104
105 The caller traverse maps and arrays in a special mode that often more convenient
106 that tracking by nesting level. When an array or map is expected or encountered
107 the EnterMap or EnteryArray can be called.
108
109 When entering a map or array like this, the cursor points to the first
110 item in the map or array. When exiting, it points to the item after
111 the map or array, regardless of whether the items in the map or array were
112 all traversed.
113
114 When in a map or array, the cursor functions as normal, but traversal
115 cannot go past the end of the map or array that was entered. If this
116 is attempted the QCBOR_ERR_NO_MORE_ITEMS error is returned. To
117 go past the end of the map or array ExitMap() or ExitArray() must
118 be called. It can be called any time regardless of the position
119 of the cursor.
120
121 When a map is entered, a special function allows fetching data items
122 by label. This call will traversal the whole map looking for the
123 labeled item. The whole map is traversed so as to detect duplicates.
124 This type of fetching items does not affect the normal traversal
125 cursor.
126
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700127
128When a data item is presented to the caller, the nesting level of the data
129 item is presented along with the nesting level of the item that would be
130 next consumed.
131
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700132 */
133
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700134
135inline static uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700136DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700137{
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700138 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700139 /*
140 Limit in DecodeNesting_Descend against more than
141 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
142 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700143 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700144}
145
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700146inline static uint8_t
147DecodeNesting_GetBoundedModeLevel(QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700148{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700149 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pMapsAndArrays[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700150 /*
151 Limit in DecodeNesting_Descend against more than
152 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
153 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700154 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700155}
156
Laurence Lundblade02625d42020-06-25 14:41:41 -0700157static inline size_t
158DecodeNesting_GetMapOrArrayStart(QCBORDecodeNesting *pNesting)
159{
160 return pNesting->pCurrentBounded->u.ma.uStartOffset;
161}
162
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700163inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700164DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700165{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700166 if(pNesting->pCurrent == &(pNesting->pMapsAndArrays[0])) {
167 return true;
168 } else {
169 return false;
170 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700171}
172
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700173inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700174DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700175{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700176 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
177 /* Not a map or array */
178 return false;
179 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700180 if(pNesting->pCurrent->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700181 /* Not indefinte length */
182 return false;
183 }
184 /* All checks passed; is an indefinte length map or array */
185 return true;
186}
187
188inline static bool
189DecodeNesting_IsDefiniteLength(const QCBORDecodeNesting *pNesting)
190{
191 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
192 /* Not a map or array */
193 return false;
194 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700195 if(pNesting->pCurrent->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700196 /* Is indefinite */
197 return false;
198 }
199 /* All checks passed; is a definte length map or array */
200 return true;
201}
202
Laurence Lundblade642282a2020-06-23 12:00:33 -0700203inline static bool
204DecodeNesting_IsBstrWrapped(const QCBORDecodeNesting *pNesting)
205{
206 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
207 /* is a byte string */
208 return true;
209 }
210 return false;
211}
212
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700213inline static bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700214{
215 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
216 return true;
217 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700218 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700219 return true;
220 }
221 return false;
222}
223
Laurence Lundblade02625d42020-06-25 14:41:41 -0700224inline static void DecodeNesting_SetMapOrArrayBoundedMode(const QCBORDecodeNesting *pNesting, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700225{
226 // Should be only called on maps and arrays
227 // TODO: check this cast, maybe give an error?
228 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
229}
230
231inline static void DecodeNesting_ClearBoundedMode(const QCBORDecodeNesting *pNesting)
232{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700233 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700234}
235
236inline static bool
Laurence Lundblade642282a2020-06-23 12:00:33 -0700237DecodeNesting_IsAtEndOfBoundedDefiniteLenMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700238{
239 if(pNesting->pCurrentBounded == NULL) {
240 /* No bounded map or array or... set up. */
241 return false;
242 }
243 if(pNesting->pCurrentBounded->uLevelType == QCBOR_TYPE_BYTE_STRING) {
244 /* Not a map or array */
245 return false;
246 }
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700247 if(!DecodeNesting_IsCurrentBounded(pNesting)) { // TODO: pCurrent vs pCurrentBounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700248 /* Not in bounded mode. */
249 return false;
250 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700251 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700252 /* An indefinite length map or array */
253 return false;
254 }
255 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0) {
256 /* Count is not zero, still unconsumed items. */
257 return false;
258 }
259 /* All checks passed, got to the end of a definite length map or array */
260 return true;
261}
262
263inline static bool
264DecodeNesting_IsEndOfDefiniteLengthMapOrArray(QCBORDecodeNesting *pNesting)
265{
266 /* Must only be called on map / array; TODO: add checks? */
267 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
268 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700269 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700270 return false;
271 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700272}
273
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700274inline static bool
275DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700276{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700277 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
278 return true;
279 } else {
280 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700281 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700282 /* Seems to be unnecessary TODO: if(DecodeNesting_IsAtTop(pNesting)) {
283 return false;
284 } */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700285}
286
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700287inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700288DecodeNesting_CheckBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700289{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700290 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700291 return false;
292 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700293
294 if(pNesting->pCurrentBounded->uLevelType != uType) {
295 return false;
296 }
297
298 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700299}
300
Laurence Lundblade02625d42020-06-25 14:41:41 -0700301
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700302inline static void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700303DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700304{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700305 /* Only call on array / map; TODO: add check?*/
306 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700307}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700308
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700309
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700310inline static void
311DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
312{
313 pNesting->pCurrent--;
314}
315
Laurence Lundblade02625d42020-06-25 14:41:41 -0700316
317static QCBORError
318DecodeNesting_Decsend(QCBORDecodeNesting *pNesting, uint8_t uType)
319{
320 // Error out if nesting is too deep
321 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
322 return QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
323 }
324
325 // The actual descend
326 pNesting->pCurrent++;
327
328 pNesting->pCurrent->uLevelType = uType;
329
330 return QCBOR_SUCCESS;
331}
332
333
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700334inline static void
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700335DecodeNesting_EnterBoundedMode(QCBORDecodeNesting *pNesting, size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700336{
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700337 /* Have descended into this before this is called. The job here is just to mark it in bounded mode */
338 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700339 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, uOffset);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700340}
341
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700342
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700343inline static QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700344DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700345 uint8_t uQCBORType,
346 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700347{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700348 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700349
350 if(uCount == 0) {
351 // Nothing to do for empty definite lenth arrays. They are just are
352 // effectively the same as an item that is not a map or array
353 goto Done;
354 // Empty indefinite length maps and arrays are handled elsewhere
355 }
356
357 // Error out if arrays is too long to handle
Laurence Lundblade02625d42020-06-25 14:41:41 -0700358 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
359 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
360 uError = QCBOR_ERR_ARRAY_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700361 goto Done;
362 }
363
Laurence Lundblade02625d42020-06-25 14:41:41 -0700364 uError = DecodeNesting_Decsend(pNesting, uQCBORType);
365 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700366 goto Done;
367 }
368
Laurence Lundblade02625d42020-06-25 14:41:41 -0700369 // Fill in the new map/array level. Check above makes cast OK.
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700370 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
371 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700372
373 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700374
375Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700376 return uError;;
377}
378
379
380static inline void
381DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
382{
383 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
384}
385
386
387static inline void
388DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
389{
390 while(pNesting->pCurrentBounded != &(pNesting->pMapsAndArrays[0])) {
391 pNesting->pCurrentBounded--;
392 if(DecodeNesting_IsCurrentBounded(pNesting)) {
393 break;
394 }
395 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700396}
397
398
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700399inline static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700400DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
401 size_t uEndOffset,
402 size_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700403{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700404 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700405
Laurence Lundblade02625d42020-06-25 14:41:41 -0700406 uError = DecodeNesting_Decsend(pNesting, QCBOR_TYPE_BYTE_STRING);
407 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700408 goto Done;
409 }
410
Laurence Lundblade02625d42020-06-25 14:41:41 -0700411 // Fill in the new byte string level
412 // TODO: justify cast
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700413 pNesting->pCurrent->u.bs.uPreviousEndOffset = (uint32_t)uEndOffset;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700414 pNesting->pCurrent->u.bs.uEndOfBstr = (uint32_t)uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700415
Laurence Lundblade02625d42020-06-25 14:41:41 -0700416 // Bstr wrapped levels are always bounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700417 pNesting->pCurrentBounded = pNesting->pCurrent;
418
419Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700420 return uError;;
421}
422
423
424static inline void
425DecodeNesting_ZeroDefiniteLengthCount(QCBORDecodeNesting *pNesting)
426{
427 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700428}
429
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700430
Laurence Lundbladeee851742020-01-08 08:37:05 -0800431inline static void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700432DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700433{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700434 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700435 pNesting->pMapsAndArrays[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700436 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
437}
438
439
Laurence Lundblade02625d42020-06-25 14:41:41 -0700440static void
441DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700442{
443 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700444 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700445
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700446 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700447 pNesting->pCurrent->u.ma.uCountCursor = pNesting->pCurrent->u.ma.uCountTotal;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700448 }
449}
450
Laurence Lundblade02625d42020-06-25 14:41:41 -0700451static inline void
452DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700453{
454 *pNesting = *pSave;
455}
456
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700457
Laurence Lundblade02625d42020-06-25 14:41:41 -0700458static inline uint32_t
459DecodeNesting_GetEndOfBstr(QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700460{
461 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
462}
463
464
Laurence Lundblade02625d42020-06-25 14:41:41 -0700465static inline uint32_t
466DecodeNesting_GetPreviousBoundedEnd(QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700467{
468 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
469}
470
471
Laurence Lundblade02625d42020-06-25 14:41:41 -0700472#include <stdio.h>
473void DecodeNesting_Print(QCBORDecodeNesting *pNesting, UsefulInputBuf *pBuf, const char *szName)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700474{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700475 printf("---%s--%d--%d--\narrow is current bounded level\nLevel Count Type S-Offset SaveCount Bounded E-Offset\n",
476 szName,
477 (uint32_t)pBuf->cursor,
478 (uint32_t)pBuf->UB.len);
479 for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) {
480 if(&(pNesting->pMapsAndArrays[i]) > pNesting->pCurrent) {
481 break;
482 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700483
Laurence Lundblade02625d42020-06-25 14:41:41 -0700484 // TODO: print different for BS and MA
485 printf("%2s %2d %5d %s %6u %5d %d %5d\n",
486 pNesting->pCurrentBounded == &(pNesting->pMapsAndArrays[i]) ? "->": " ",
487 i,
488 pNesting->pMapsAndArrays[i].u.ma.uCountCursor,
489 pNesting->pMapsAndArrays[i].uLevelType == QCBOR_TYPE_MAP ? "map " :
490 (pNesting->pMapsAndArrays[i].uLevelType == QCBOR_TYPE_ARRAY ? "array" :
491 (pNesting->pMapsAndArrays[i].uLevelType == QCBOR_TYPE_BYTE_STRING ? "bstr " :
492 (pNesting->pMapsAndArrays[i].uLevelType == QCBOR_TYPE_NONE ? "none " : "?????"))),
493 pNesting->pMapsAndArrays[i].u.ma.uStartOffset,
494 pNesting->pMapsAndArrays[i].u.ma.uCountTotal,
495 0, // TODO: fix this
496 pNesting->pMapsAndArrays[i].u.bs.uPreviousEndOffset
497 );
498
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700499 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700500 printf("\n");
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700501}
502
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700503
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700504
Laurence Lundbladeee851742020-01-08 08:37:05 -0800505/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800506 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
507
508 The following four functions are pretty wrappers for invocation of
509 the string allocator supplied by the caller.
510
Laurence Lundbladeee851742020-01-08 08:37:05 -0800511 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800512
Laurence Lundbladeee851742020-01-08 08:37:05 -0800513static inline void
514StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800515{
516 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
517}
518
Laurence Lundbladeee851742020-01-08 08:37:05 -0800519// StringAllocator_Reallocate called with pMem NULL is
520// equal to StringAllocator_Allocate()
521static inline UsefulBuf
522StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
523 void *pMem,
524 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800525{
526 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
527}
528
Laurence Lundbladeee851742020-01-08 08:37:05 -0800529static inline UsefulBuf
530StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800531{
532 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
533}
534
Laurence Lundbladeee851742020-01-08 08:37:05 -0800535static inline void
536StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800537{
538 if(pMe->pfAllocator) {
539 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
540 }
541}
542
543
544
Laurence Lundbladeee851742020-01-08 08:37:05 -0800545/*===========================================================================
546 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700547
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800548 See qcbor/qcbor_decode.h for definition of the object
549 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800550 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700551/*
552 Public function, see header file
553 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800554void QCBORDecode_Init(QCBORDecodeContext *me,
555 UsefulBufC EncodedCBOR,
556 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700557{
558 memset(me, 0, sizeof(QCBORDecodeContext));
559 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800560 // Don't bother with error check on decode mode. If a bad value is
561 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700562 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700563 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700564 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700565 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700566 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700567}
568
569
570/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700571 Public function, see header file
572 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800573void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
574 QCBORStringAllocate pfAllocateFunction,
575 void *pAllocateContext,
576 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700577{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800578 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
579 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
580 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700581}
582
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800583
584/*
585 Public function, see header file
586 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800587void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me,
588 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700589{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700590 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700591}
592
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700593
594/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800595 This decodes the fundamental part of a CBOR data item, the type and
596 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800597
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700598 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800599
Laurence Lundbladeee851742020-01-08 08:37:05 -0800600 This does the network->host byte order conversion. The conversion
601 here also results in the conversion for floats in addition to that
602 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800603
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700604 This returns:
605 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800606
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800607 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800608 tags and floats and length for strings and arrays
609
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800610 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800611 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800612
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800613 The int type is preferred to uint8_t for some variables as this
614 avoids integer promotions, can reduce code size and makes
615 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700616 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800617inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
618 int *pnMajorType,
619 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800620 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700621{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700622 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800623
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700624 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800625 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800626
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700627 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800628 const int nTmpMajorType = nInitialByte >> 5;
629 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800630
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800631 // Where the number or argument accumulates
632 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800633
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800634 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700635 // Need to get 1,2,4 or 8 additional argument bytes. Map
636 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800637 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800638
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800639 // Loop getting all the bytes in the argument
640 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800641 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800642 // This shift and add gives the endian conversion
643 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
644 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800645 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800646 // The reserved and thus-far unused additional info values
647 nReturn = QCBOR_ERR_UNSUPPORTED;
648 goto Done;
649 } else {
650 // Less than 24, additional info is argument or 31, an indefinite length
651 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800652 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700653 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800654
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700655 if(UsefulInputBuf_GetError(pUInBuf)) {
656 nReturn = QCBOR_ERR_HIT_END;
657 goto Done;
658 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800659
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700660 // All successful if we got here.
661 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800662 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800663 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800664 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800665
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700666Done:
667 return nReturn;
668}
669
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800670
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700671/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800672 CBOR doesn't explicitly specify two's compliment for integers but all
673 CPUs use it these days and the test vectors in the RFC are so. All
674 integers in the CBOR structure are positive and the major type
675 indicates positive or negative. CBOR can express positive integers
676 up to 2^x - 1 where x is the number of bits and negative integers
677 down to 2^x. Note that negative numbers can be one more away from
678 zero than positive. Stdint, as far as I can tell, uses two's
679 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800680
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700681 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800682 used carefully here, and in particular why it isn't used in the interface.
683 Also see
684 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
685
686 Int is used for values that need less than 16-bits and would be subject
687 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700688 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800689inline static QCBORError
690DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700691{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700692 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800693
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700694 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
695 if (uNumber <= INT64_MAX) {
696 pDecodedItem->val.int64 = (int64_t)uNumber;
697 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800698
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700699 } else {
700 pDecodedItem->val.uint64 = uNumber;
701 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800702
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700703 }
704 } else {
705 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800706 // CBOR's representation of negative numbers lines up with the
707 // two-compliment representation. A negative integer has one
708 // more in range than a positive integer. INT64_MIN is
709 // equal to (-INT64_MAX) - 1.
710 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700711 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800712
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700713 } else {
714 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000715 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700716 nReturn = QCBOR_ERR_INT_OVERFLOW;
717 }
718 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800719
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700720 return nReturn;
721}
722
723// Make sure #define value line up as DecodeSimple counts on this.
724#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
725#error QCBOR_TYPE_FALSE macro value wrong
726#endif
727
728#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
729#error QCBOR_TYPE_TRUE macro value wrong
730#endif
731
732#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
733#error QCBOR_TYPE_NULL macro value wrong
734#endif
735
736#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
737#error QCBOR_TYPE_UNDEF macro value wrong
738#endif
739
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700740#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
741#error QCBOR_TYPE_BREAK macro value wrong
742#endif
743
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700744#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
745#error QCBOR_TYPE_DOUBLE macro value wrong
746#endif
747
748#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
749#error QCBOR_TYPE_FLOAT macro value wrong
750#endif
751
752/*
753 Decode true, false, floats, break...
754 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800755inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800756DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700757{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700758 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800759
Laurence Lundbladeee851742020-01-08 08:37:05 -0800760 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800761 // above make sure uAdditionalInfo values line up with uDataType values.
762 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
763 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800764
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800765 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800766 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
767 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800768
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700769 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700770 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
771 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700772 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700773 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700774 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
775 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700776 break;
777 case DOUBLE_PREC_FLOAT:
778 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700779 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700780 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800781
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700782 case CBOR_SIMPLEV_FALSE: // 20
783 case CBOR_SIMPLEV_TRUE: // 21
784 case CBOR_SIMPLEV_NULL: // 22
785 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700786 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700787 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800788
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700789 case CBOR_SIMPLEV_ONEBYTE: // 24
790 if(uNumber <= CBOR_SIMPLE_BREAK) {
791 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700792 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700793 goto Done;
794 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800795 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700796 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800797
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700798 default: // 0-19
799 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800800 /*
801 DecodeTypeAndNumber will make uNumber equal to
802 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
803 safe because the 2, 4 and 8 byte lengths of uNumber are in
804 the double/float cases above
805 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700806 pDecodedItem->val.uSimple = (uint8_t)uNumber;
807 break;
808 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800809
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700810Done:
811 return nReturn;
812}
813
814
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700815/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530816 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700817 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800818inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
819 int nMajorType,
820 uint64_t uStrLen,
821 UsefulInputBuf *pUInBuf,
822 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700823{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700824 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800825
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800826 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
827 // This check makes the casts to size_t below safe.
828
829 // 4 bytes less than the largest sizeof() so this can be tested by
830 // putting a SIZE_MAX length in the CBOR test input (no one will
831 // care the limit on strings is 4 bytes shorter).
832 if(uStrLen > SIZE_MAX-4) {
833 nReturn = QCBOR_ERR_STRING_TOO_LONG;
834 goto Done;
835 }
836
837 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530838 if(UsefulBuf_IsNULLC(Bytes)) {
839 // Failed to get the bytes for this string item
840 nReturn = QCBOR_ERR_HIT_END;
841 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700842 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530843
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800844 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530845 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800846 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530847 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700848 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530849 goto Done;
850 }
851 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800852 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530853 } else {
854 // Normal case with no string allocator
855 pDecodedItem->val.string = Bytes;
856 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800857 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800858 // Cast because ternary operator causes promotion to integer
859 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
860 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800861
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530862Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700863 return nReturn;
864}
865
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700866
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800867
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700868
869
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700870
871
Laurence Lundbladeee851742020-01-08 08:37:05 -0800872// Make sure the constants align as this is assumed by
873// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700874#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
875#error QCBOR_TYPE_ARRAY value not lined up with major type
876#endif
877#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
878#error QCBOR_TYPE_MAP value not lined up with major type
879#endif
880
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700881/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800882 This gets a single data item and decodes it including preceding
883 optional tagging. This does not deal with arrays and maps and nesting
884 except to decode the data item introducing them. Arrays and maps are
885 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800886
Laurence Lundbladeee851742020-01-08 08:37:05 -0800887 Errors detected here include: an array that is too long to decode,
888 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700889 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800890static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
891 QCBORItem *pDecodedItem,
892 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700893{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700894 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800895
Laurence Lundbladeee851742020-01-08 08:37:05 -0800896 /*
897 Get the major type and the number. Number could be length of more
898 bytes or the value depending on the major type nAdditionalInfo is
899 an encoding of the length of the uNumber and is needed to decode
900 floats and doubles
901 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800902 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700903 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800904 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800905
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700906 memset(pDecodedItem, 0, sizeof(QCBORItem));
907
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800908 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800909
Laurence Lundbladeee851742020-01-08 08:37:05 -0800910 // Error out here if we got into trouble on the type and number. The
911 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700912 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700913 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700914 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800915
Laurence Lundbladeee851742020-01-08 08:37:05 -0800916 // At this point the major type and the value are valid. We've got
917 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800918 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700919 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
920 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800921 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700922 nReturn = QCBOR_ERR_BAD_INT;
923 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800924 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700925 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700926 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800927
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700928 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
929 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800930 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
931 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
932 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
933 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530934 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700935 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800936 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700937 }
938 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800939
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700940 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
941 case CBOR_MAJOR_TYPE_MAP: // Major type 5
942 // Record the number of items in the array or map
943 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
944 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
945 goto Done;
946 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800947 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700948 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700949 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800950 // type conversion OK because of check above
951 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700952 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800953 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800954 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
955 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700956 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800957
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700958 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800959 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700960 nReturn = QCBOR_ERR_BAD_INT;
961 } else {
962 pDecodedItem->val.uTagV = uNumber;
963 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
964 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700965 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800966
Laurence Lundbladeee851742020-01-08 08:37:05 -0800967 case CBOR_MAJOR_TYPE_SIMPLE:
968 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800969 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700970 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800971
Laurence Lundbladeee851742020-01-08 08:37:05 -0800972 default:
973 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700974 nReturn = QCBOR_ERR_UNSUPPORTED;
975 break;
976 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800977
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700978Done:
979 return nReturn;
980}
981
982
983
984/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800985 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -0800986 individual chunk items together into one QCBORItem using the string
987 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800988
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530989 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700990 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800991static inline QCBORError
992GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700993{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700994 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700995
996 // Get pointer to string allocator. First use is to pass it to
997 // GetNext_Item() when option is set to allocate for *every* string.
998 // Second use here is to allocate space to coallese indefinite
999 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001000 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
1001 &(me->StringAllocator) :
1002 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001003
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001004 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001005 nReturn = GetNext_Item(&(me->InBuf),
1006 pDecodedItem,
1007 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001008 if(nReturn) {
1009 goto Done;
1010 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001011
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001012 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301013 // code in this function from here down can be eliminated. Run tests, except
1014 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001015
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001016 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001017 const uint8_t uStringType = pDecodedItem->uDataType;
1018 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001019 goto Done; // no need to do any work here on non-string types
1020 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001021
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001022 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301023 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001024 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001025 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001026
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301027 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001028 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001029 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1030 goto Done;
1031 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001032
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001033 // Loop getting chunk of indefinite string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001034 UsefulBufC FullString = NULLUsefulBufC;
1035
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001036 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001037 // Get item for next chunk
1038 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001039 // NULL string allocator passed here. Do not need to allocate
1040 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -08001041 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001042 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001043 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001044 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001045
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301046 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001047 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001048 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001049 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301050 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001051 break;
1052 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001053
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001054 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301055 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001056 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001057 if(StringChunkItem.uDataType != uStringType ||
1058 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001059 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001060 break;
1061 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001062
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301063 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001064 // The first time throurgh FullString.ptr is NULL and this is
1065 // equivalent to StringAllocator_Allocate()
1066 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1067 UNCONST_POINTER(FullString.ptr),
1068 FullString.len + StringChunkItem.val.string.len);
1069
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001070 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301071 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001072 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001073 break;
1074 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001075
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001076 // Copy new string chunk at the end of string so far.
1077 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001078 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001079
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001080 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1081 // Getting the item failed, clean up the allocated memory
1082 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001083 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001084
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001085Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001086 return nReturn;
1087}
1088
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001089
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001090uint64_t ConvertTag(QCBORDecodeContext *me, uint16_t uTagVal) {
1091 if(uTagVal < 0xfff0) {
1092 return uTagVal;
1093 } else {
1094 // TODO constant and error check
1095 int x = uTagVal - 0xfff0;
1096 return me->auMappedTags[x];
1097 }
1098}
1099
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001100/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001101 Gets all optional tag data items preceding a data item that is not an
1102 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001103 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001104static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001105GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001106{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001107 // Stack usage: int/ptr: 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +07001108 QCBORError nReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001109
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001110 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1111 CBOR_TAG_INVALID16,
1112 CBOR_TAG_INVALID16,
1113 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001114
Laurence Lundblade59289e52019-12-30 13:44:37 -08001115 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001116 for(;;) {
1117 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001118 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001119 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001120 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001121
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001122 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
1123 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001124 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001125 break;
1126 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001127
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001128 // Is there room for the tag in the tags list?
1129 size_t uTagIndex;
1130 for(uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001131 if(auTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001132 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001133 }
1134 }
1135 if(uTagIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001136 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001137 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001138
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001139 // Is the tag > 16 bits?
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001140 if(pDecodedItem->val.uTagV > CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001141 size_t uTagMapIndex;
1142 // Is there room in the tag map?
1143 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001144 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001145 break;
1146 }
1147 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
1148 break;
1149 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001150 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001151 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1152 // No room for the tag
Laurence Lundblade02625d42020-06-25 14:41:41 -07001153 return 97; // TODO: error code
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001154 }
1155
1156 // Cover the case where tag is new and were it is already in the map
1157 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade02625d42020-06-25 14:41:41 -07001158 auTags[uTagIndex] = (uint16_t)(uTagMapIndex + 0xfff0); // TODO: proper constant and cast
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001159
1160 } else {
1161 auTags[uTagIndex] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001162 }
1163 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001164
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001165Done:
1166 return nReturn;
1167}
1168
1169
1170/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001171 This layer takes care of map entries. It combines the label and data
1172 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001173 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001174static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001175GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001176{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001177 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001178 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001179 if(nReturn)
1180 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001181
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001182 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001183 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001184 goto Done;
1185 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001186
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001187 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1188 // In a map and caller wants maps decoded, not treated as arrays
1189
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001190 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001191 // If in a map and the right decoding mode, get the label
1192
Laurence Lundbladeee851742020-01-08 08:37:05 -08001193 // Save label in pDecodedItem and get the next which will
1194 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001195 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001196 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001197 if(nReturn)
1198 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001199
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301200 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001201
1202 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1203 // strings are always good labels
1204 pDecodedItem->label.string = LabelItem.val.string;
1205 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1206 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001207 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001208 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1209 goto Done;
1210 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1211 pDecodedItem->label.int64 = LabelItem.val.int64;
1212 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1213 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1214 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1215 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1216 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1217 pDecodedItem->label.string = LabelItem.val.string;
1218 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1219 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1220 } else {
1221 // label is not an int or a string. It is an arrray
1222 // or a float or such and this implementation doesn't handle that.
1223 // Also, tags on labels are ignored.
1224 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1225 goto Done;
1226 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001227 }
1228 } else {
1229 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001230 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1231 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1232 goto Done;
1233 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001234 // Decoding a map as an array
1235 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001236 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1237 // Cast is needed because of integer promotion
1238 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001239 }
1240 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001241
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001242Done:
1243 return nReturn;
1244}
1245
1246
Laurence Lundblade02625d42020-06-25 14:41:41 -07001247/*
1248 See if next item is a CBOR break. If it is, it is consumed,
1249 if not it is not consumed.
1250*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001251static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001252NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1253{
1254 *pbNextIsBreak = false;
1255 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001256 QCBORItem Peek;
1257 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1258 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1259 if(uReturn != QCBOR_SUCCESS) {
1260 return uReturn;
1261 }
1262 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001263 // It is not a break, rewind so it can be processed normally.
1264 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001265 } else {
1266 *pbNextIsBreak = true;
1267 }
1268 }
1269
1270 return QCBOR_SUCCESS;
1271}
1272
1273
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001274/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001275 An item was just consumed, now figure out if it was the
1276 end of an array or map that can be closed out. That
1277 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001278*/
Laurence Lundblade02625d42020-06-25 14:41:41 -07001279static QCBORError NestLevelAscender(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001280{
1281 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001282
Laurence Lundblade642282a2020-06-23 12:00:33 -07001283 /* This loops ascending nesting levels as long as there is ascending to do */
1284 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1285
1286 if(DecodeNesting_IsDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001287 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001288 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1289 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001290 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001291 break;
1292 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001293 /* All of a definite length array was consumed; fall through to ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001294
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001295 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001296 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001297 bool bIsBreak = false;
1298 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1299 if(uReturn != QCBOR_SUCCESS) {
1300 goto Done;
1301 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001302
1303 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001304 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001305 break;
1306 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001307
1308 if(DecodeNesting_IsBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001309 /*
1310 Break occurred inside a bstr-wrapped CBOR or
1311 in the top level sequence. This is always an
1312 error because neither are an indefinte length
1313 map/array.
1314 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001315 uReturn = QCBOR_ERR_BAD_BREAK;
1316 goto Done;
1317 }
Laurence Lundblade02625d42020-06-25 14:41:41 -07001318 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001319 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001320
Laurence Lundblade02625d42020-06-25 14:41:41 -07001321 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001322
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001323 /* But ascent in bounded mode is only by explicit call to QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001324 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001325 /* Set the count to zero for definite length arrays to indicate cursor is at end of bounded map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001326 DecodeNesting_ZeroDefiniteLengthCount(&(pMe->nesting));
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001327 break;
1328 }
1329
1330 /* Finally, actually ascend one level. */
1331 DecodeNesting_Ascend(&(pMe->nesting));
1332 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001333
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001334 uReturn = QCBOR_SUCCESS;
1335
1336Done:
1337 return uReturn;
1338}
1339
1340
1341/*
Laurence Lundblade642282a2020-06-23 12:00:33 -07001342 This the travesal going descending into and asecnding out of maps,
1343 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1344 indefinte length maps and arrays by looking at the item count or
1345 finding CBOR breaks. It detects the ends of the top-level sequence
1346 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001347 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001348static QCBORError
1349QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001350{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001351 QCBORError uReturn;
Laurence Lundblade642282a2020-06-23 12:00:33 -07001352 /* ==== First figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001353
Laurence Lundblade642282a2020-06-23 12:00:33 -07001354 /*
1355 If out of bytes to consume, it is either the end of the top-level
1356 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001357
Laurence Lundblade642282a2020-06-23 12:00:33 -07001358 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1359 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1360 CBOR is exited, the length is set back to the top-level's length
1361 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001362
Laurence Lundblade642282a2020-06-23 12:00:33 -07001363 Only return the success error code QCBOR_ERR_NO_MORE_ITEMS here
1364 when at the top level to allow other code below to process various
1365 errors when out of bytes to decode and not at the top level. Note
1366 that QCBORDecode_Finish() still needs to be called to be sure all
1367 nesting levels were closed out.
1368 */
1369 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0 &&
1370 DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001371 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001372 goto Done;
1373 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001374
Laurence Lundblade642282a2020-06-23 12:00:33 -07001375 /*
1376 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001377 array. The check for the end of an indefinite length array is
1378 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001379 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001380 if(DecodeNesting_IsAtEndOfBoundedDefiniteLenMapOrArray(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001381 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001382 goto Done;
1383 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001384
Laurence Lundblade642282a2020-06-23 12:00:33 -07001385 /* ==== Next, not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001386 uReturn = GetNext_MapEntry(me, pDecodedItem);
1387 if(uReturn) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001388 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001389 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301390
Laurence Lundblade642282a2020-06-23 12:00:33 -07001391 /*
1392 Breaks ending arrays/maps are always processed at the end of this
1393 function. They should never show up here.
1394 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301395 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001396 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301397 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301398 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001399
Laurence Lundblade642282a2020-06-23 12:00:33 -07001400 /*
1401 Record the nesting level for this data item before processing any
1402 of decrementing and descending.
1403 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001404 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001405
Laurence Lundblade642282a2020-06-23 12:00:33 -07001406
1407 /* ==== Next, Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001408 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001409 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001410 If the new item is a map or array descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001411
Laurence Lundblade02625d42020-06-25 14:41:41 -07001412 Empty maps and arrays descended into, but then ascended out
1413 of in the next chunk of code.
1414
1415 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001416 encloses them so a decrement needs to be done for them too, but
1417 that is done only when all the items in them have been
1418 processed, not when they are opened with the exception of an
1419 empty map or array.
1420 */
1421 uReturn = DecodeNesting_DescendMapOrArray(&(me->nesting),
1422 pDecodedItem->uDataType,
1423 pDecodedItem->val.uCount);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001424 if(uReturn != QCBOR_SUCCESS) {
1425 goto Done;
1426 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001427 }
1428
Laurence Lundblade02625d42020-06-25 14:41:41 -07001429 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1430 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1431 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001432 /*
1433 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001434 - A non-aggregate like an integer or string
1435 - An empty definite length map or array
1436 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001437
1438 The Ascender does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001439 definite length map/array and break detection for an indefinite
1440 length map/array. If the end of the map/array was reached, then
1441 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001442 */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001443 uReturn = NestLevelAscender(me);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001444 if(uReturn) {
1445 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001446 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301447 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001448
Laurence Lundblade02625d42020-06-25 14:41:41 -07001449 /* ==== Last, tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001450 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001451 Tell the caller what level is next. This tells them what
1452 maps/arrays were closed out and makes it possible for them to
1453 reconstruct the tree with just the information returned in
1454 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001455 */
1456 if(DecodeNesting_IsAtEndOfBoundedDefiniteLenMapOrArray(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001457 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001458 pDecodedItem->uNextNestLevel = 0;
1459 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001460 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001461 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001462
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001463Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001464 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001465 /* This sets uDataType and uLabelType to QCBOR_TYPE_NONE */
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001466 memset(pDecodedItem, 0, sizeof(QCBORItem));
1467 }
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001468 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001469}
1470
1471
Laurence Lundblade59289e52019-12-30 13:44:37 -08001472/*
1473 Mostly just assign the right data type for the date string.
1474 */
1475inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1476{
1477 // Stack Use: UsefulBuf 1 16
1478 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1479 return QCBOR_ERR_BAD_OPT_TAG;
1480 }
1481
1482 const UsefulBufC Temp = pDecodedItem->val.string;
1483 pDecodedItem->val.dateString = Temp;
1484 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1485 return QCBOR_SUCCESS;
1486}
1487
1488
1489/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001490 The epoch formatted date. Turns lots of different forms of encoding
1491 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001492 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001493static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001494{
1495 // Stack usage: 1
1496 QCBORError nReturn = QCBOR_SUCCESS;
1497
1498 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1499
1500 switch (pDecodedItem->uDataType) {
1501
1502 case QCBOR_TYPE_INT64:
1503 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1504 break;
1505
1506 case QCBOR_TYPE_UINT64:
1507 if(pDecodedItem->val.uint64 > INT64_MAX) {
1508 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1509 goto Done;
1510 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001511 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001512 break;
1513
1514 case QCBOR_TYPE_DOUBLE:
1515 {
1516 // This comparison needs to be done as a float before
1517 // conversion to an int64_t to be able to detect doubles
1518 // that are too large to fit into an int64_t. A double
1519 // has 52 bits of preceision. An int64_t has 63. Casting
1520 // INT64_MAX to a double actually causes a round up which
1521 // is bad and wrong for the comparison because it will
1522 // allow conversion of doubles that can't fit into a
1523 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1524 // the cutoff point as if that rounds up in conversion to
1525 // double it will still be less than INT64_MAX. 0x7ff is
1526 // picked because it has 11 bits set.
1527 //
1528 // INT64_MAX seconds is on the order of 10 billion years,
1529 // and the earth is less than 5 billion years old, so for
1530 // most uses this conversion error won't occur even though
1531 // doubles can go much larger.
1532 //
1533 // Without the 0x7ff there is a ~30 minute range of time
1534 // values 10 billion years in the past and in the future
1535 // where this this code would go wrong.
1536 const double d = pDecodedItem->val.dfnum;
1537 if(d > (double)(INT64_MAX - 0x7ff)) {
1538 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1539 goto Done;
1540 }
1541 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1542 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1543 }
1544 break;
1545
1546 default:
1547 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1548 goto Done;
1549 }
1550 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1551
1552Done:
1553 return nReturn;
1554}
1555
1556
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001557/*
1558 Mostly just assign the right data type for the bignum.
1559 */
1560inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1561{
1562 // Stack Use: UsefulBuf 1 -- 16
1563 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1564 return QCBOR_ERR_BAD_OPT_TAG;
1565 }
1566 const UsefulBufC Temp = pDecodedItem->val.string;
1567 pDecodedItem->val.bigNum = Temp;
1568 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1569 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1570 : QCBOR_TYPE_NEGBIGNUM);
1571 return QCBOR_SUCCESS;
1572}
1573
1574
Laurence Lundblade59289e52019-12-30 13:44:37 -08001575#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1576/*
1577 Decode decimal fractions and big floats.
1578
1579 When called pDecodedItem must be the array that is tagged as a big
1580 float or decimal fraction, the array that has the two members, the
1581 exponent and mantissa.
1582
1583 This will fetch and decode the exponent and mantissa and put the
1584 result back into pDecodedItem.
1585 */
1586inline static QCBORError
1587QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1588{
1589 QCBORError nReturn;
1590
1591 // --- Make sure it is an array; track nesting level of members ---
1592 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1593 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1594 goto Done;
1595 }
1596
1597 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001598 // definite length arrays, but not for indefnite. Instead remember
1599 // the nesting level the two integers must be at, which is one
1600 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001601 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1602
1603 // --- Is it a decimal fraction or a bigfloat? ---
1604 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1605 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1606
1607 // --- Get the exponent ---
1608 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001609 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001610 if(nReturn != QCBOR_SUCCESS) {
1611 goto Done;
1612 }
1613 if(exponentItem.uNestingLevel != nNestLevel) {
1614 // Array is empty or a map/array encountered when expecting an int
1615 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1616 goto Done;
1617 }
1618 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1619 // Data arriving as an unsigned int < INT64_MAX has been converted
1620 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1621 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1622 // will be too large for this to handle and thus an error that will
1623 // get handled in the next else.
1624 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1625 } else {
1626 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1627 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1628 goto Done;
1629 }
1630
1631 // --- Get the mantissa ---
1632 QCBORItem mantissaItem;
1633 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1634 if(nReturn != QCBOR_SUCCESS) {
1635 goto Done;
1636 }
1637 if(mantissaItem.uNestingLevel != nNestLevel) {
1638 // Mantissa missing or map/array encountered when expecting number
1639 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1640 goto Done;
1641 }
1642 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1643 // Data arriving as an unsigned int < INT64_MAX has been converted
1644 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1645 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1646 // will be too large for this to handle and thus an error that
1647 // will get handled in an else below.
1648 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1649 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1650 // Got a good big num mantissa
1651 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1652 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001653 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1654 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1655 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001656 } else {
1657 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1658 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1659 goto Done;
1660 }
1661
1662 // --- Check that array only has the two numbers ---
1663 if(mantissaItem.uNextNestLevel == nNestLevel) {
1664 // Extra items in the decimal fraction / big num
1665 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1666 goto Done;
1667 }
1668
1669Done:
1670
1671 return nReturn;
1672}
1673#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1674
1675
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001676
1677/*
1678 */
1679inline static QCBORError DecodeURI(QCBORItem *pDecodedItem)
1680{
1681 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1682 return QCBOR_ERR_BAD_OPT_TAG;
1683 }
1684 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1685 return QCBOR_SUCCESS;
1686}
1687
1688
1689inline static QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
1690{
1691 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1692 return QCBOR_ERR_BAD_OPT_TAG;
1693 }
1694 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
1695 return QCBOR_SUCCESS;
1696}
1697
1698
1699inline static QCBORError DecodeB64(QCBORItem *pDecodedItem)
1700{
1701 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1702 return QCBOR_ERR_BAD_OPT_TAG;
1703 }
1704 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
1705 return QCBOR_SUCCESS;
1706}
1707
1708
1709inline static QCBORError DecodeRegex(QCBORItem *pDecodedItem)
1710{
1711 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1712 return QCBOR_ERR_BAD_OPT_TAG;
1713 }
1714 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
1715 return QCBOR_SUCCESS;
1716}
1717
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001718inline static QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
1719{
1720 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1721 return QCBOR_ERR_BAD_OPT_TAG;
1722 }
1723 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
1724 return QCBOR_SUCCESS;
1725}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001726
1727inline static QCBORError DecodeMIME(QCBORItem *pDecodedItem)
1728{
1729 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1730 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
1731 } else if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1732 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1733 } else {
1734 return QCBOR_ERR_BAD_OPT_TAG;
1735 }
1736 return QCBOR_SUCCESS;
1737}
1738
1739
1740/*
1741 */
1742inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1743{
1744 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1745 return QCBOR_ERR_BAD_OPT_TAG;
1746 }
1747 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
1748 return QCBOR_SUCCESS;
1749}
1750
1751
Laurence Lundblade59289e52019-12-30 13:44:37 -08001752/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001753 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001754 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001755QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001756QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001757{
1758 QCBORError nReturn;
1759
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001760 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001761 if(nReturn != QCBOR_SUCCESS) {
1762 goto Done;
1763 }
1764
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001765 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
1766 switch(pDecodedItem->uTags[i] ) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001767
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001768 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001769 nReturn = DecodeDateString(pDecodedItem);
1770 break;
1771
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001772 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001773 nReturn = DecodeDateEpoch(pDecodedItem);
1774 break;
1775
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001776 case CBOR_TAG_POS_BIGNUM:
1777 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001778 nReturn = DecodeBigNum(pDecodedItem);
1779 break;
1780
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001781 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1782 case CBOR_TAG_DECIMAL_FRACTION:
1783 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001784 // For aggregate tagged types, what goes into pTags is only collected
1785 // from the surrounding data item, not the contents, so pTags is not
1786 // passed on here.
1787
1788 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1789 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001790 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001791
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001792 case CBOR_TAG_CBOR:
1793 nReturn = DecodeWrappedCBOR(pDecodedItem);
1794 break;
1795
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001796 case CBOR_TAG_URI:
1797 nReturn = DecodeURI(pDecodedItem);
1798 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001799
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001800 case CBOR_TAG_B64URL:
1801 nReturn = DecodeB64URL(pDecodedItem);
1802 break;
1803
1804 case CBOR_TAG_B64:
1805 nReturn = DecodeB64(pDecodedItem);
1806 break;
1807
1808 case CBOR_TAG_MIME:
1809 case CBOR_TAG_BINARY_MIME:
1810 nReturn = DecodeMIME(pDecodedItem);
1811 break;
1812
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001813 case CBOR_TAG_REGEX:
1814 nReturn = DecodeRegex(pDecodedItem);
1815 break;
1816
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001817 case CBOR_TAG_BIN_UUID:
1818 nReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001819 break;
1820
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001821 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001822 // The end of the tag list or no tags
1823 // Successful exit from the loop.
1824 goto Done;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001825
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001826 default:
1827 // A tag that is not understood
1828 // A successful exit from the loop
1829 goto Done;
1830
1831 }
1832 if(nReturn != QCBOR_SUCCESS) {
1833 goto Done;
1834 }
Laurence Lundblade59289e52019-12-30 13:44:37 -08001835 }
1836
1837Done:
1838 if(nReturn != QCBOR_SUCCESS) {
1839 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1840 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1841 }
1842 return nReturn;
1843}
1844
1845
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001846QCBORError QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
1847{
1848 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
1849
1850 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
1851
1852 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
1853
1854 return uErr;
1855}
1856
1857
Laurence Lundblade59289e52019-12-30 13:44:37 -08001858/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001859 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001860 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001861QCBORError
1862QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1863 QCBORItem *pDecodedItem,
1864 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001865{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001866 QCBORError nReturn;
1867
1868 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
1869 if(nReturn != QCBOR_SUCCESS) {
1870 return nReturn;
1871 }
1872
1873 if(pTags != NULL) {
1874 pTags->uNumUsed = 0;
1875 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001876 if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001877 break;
1878 }
1879 if(pTags->uNumUsed >= pTags->uNumAllocated) {
1880 return QCBOR_ERR_TOO_MANY_TAGS;
1881 }
1882 pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]);
1883 pTags->uNumUsed++;
1884 }
1885 }
1886
1887 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001888}
1889
1890
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001891/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301892 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301893 next one down. If a layer has no work to do for a particular item
1894 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001895
Laurence Lundblade59289e52019-12-30 13:44:37 -08001896 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1897 tagged data items, turning them into the local C representation.
1898 For the most simple it is just associating a QCBOR_TYPE with the data. For
1899 the complex ones that an aggregate of data items, there is some further
1900 decoding and a little bit of recursion.
1901
1902 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301903 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301904 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001905 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001906
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301907 - GetNext_MapEntry -- This handles the combining of two
1908 items, the label and the data, that make up a map entry.
1909 It only does work on maps. It combines the label and data
1910 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001911
Laurence Lundblade59289e52019-12-30 13:44:37 -08001912 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1913 tags into bit flags associated with the data item. No actual decoding
1914 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001915
Laurence Lundblade59289e52019-12-30 13:44:37 -08001916 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301917 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301918 string allocater to create contiguous space for the item. It
1919 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001920
Laurence Lundblade59289e52019-12-30 13:44:37 -08001921 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1922 atomic data item has a "major type", an integer "argument" and optionally
1923 some content. For text and byte strings, the content is the bytes
1924 that make up the string. These are the smallest data items that are
1925 considered to be well-formed. The content may also be other data items in
1926 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001927
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001928 Roughly this takes 300 bytes of stack for vars. Need to
1929 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001930
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301931 */
1932
1933
1934/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001935 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001936 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001937int QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001938 const QCBORItem *pItem,
1939 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001940{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001941 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++ ) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001942 if(pItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001943 break;
1944 }
1945 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
1946 return 1;
1947 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001948 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001949
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001950 return 0;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001951}
1952
1953
1954/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001955 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001956 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001957QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001958{
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001959 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001960
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001961 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001962 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001963 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1964 goto Done;
1965 }
1966
1967 // Error out if not all the bytes are consumed
1968 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1969 nReturn = QCBOR_ERR_EXTRA_BYTES;
1970 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001971
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001972Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301973 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001974 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001975 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001976
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001977 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001978}
1979
1980
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001981/*
1982Public function, see header qcbor/qcbor_decode.h file
1983*/
Laurence Lundblade2b843b52020-06-16 20:51:03 -07001984uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
1985 const QCBORItem *pItem,
1986 unsigned int uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001987{
1988 if(uIndex > QCBOR_MAX_TAGS_PER_ITEM) {
1989 return CBOR_TAG_INVALID16;
1990 } else if(pItem->uTags[uIndex] <= QCBOR_LAST_UNMAPPED_TAG) {
1991 return pItem->uTags[uIndex];
1992 } else if(pItem->uTags[uIndex] < QCBOR_NUM_MAPPED_TAGS + QCBOR_LAST_UNMAPPED_TAG) {
1993 return pMe->auMappedTags[pItem->uTags[uIndex] - QCBOR_LAST_UNMAPPED_TAG];
1994 } else {
1995 return CBOR_TAG_INVALID16;
1996 }
1997}
1998
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001999
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002000/*
2001
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002002Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002003
Laurence Lundbladeee851742020-01-08 08:37:05 -08002004 - Hit end of input before it was expected while decoding type and
2005 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002006
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002007 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002008
Laurence Lundbladeee851742020-01-08 08:37:05 -08002009 - Hit end of input while decoding a text or byte string
2010 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002011
Laurence Lundbladeee851742020-01-08 08:37:05 -08002012 - Encountered conflicting tags -- e.g., an item is tagged both a date
2013 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002014
Laurence Lundbladeee851742020-01-08 08:37:05 -08002015 - Encontered an array or mapp that has too many items
2016 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002017
Laurence Lundbladeee851742020-01-08 08:37:05 -08002018 - Encountered array/map nesting that is too deep
2019 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002020
Laurence Lundbladeee851742020-01-08 08:37:05 -08002021 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2022 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002023
Laurence Lundbladeee851742020-01-08 08:37:05 -08002024 - The type of a map label is not a string or int
2025 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002026
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002027 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002028
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002029 */
2030
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002031
2032
Laurence Lundbladef6531662018-12-04 10:42:22 +09002033
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002034/* ===========================================================================
2035 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002036
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002037 This implements a simple sting allocator for indefinite length
2038 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2039 implements the function type QCBORStringAllocate and allows easy
2040 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002041
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002042 This particular allocator is built-in for convenience. The caller
2043 can implement their own. All of this following code will get
2044 dead-stripped if QCBORDecode_SetMemPool() is not called.
2045
2046 This is a very primitive memory allocator. It does not track
2047 individual allocations, only a high-water mark. A free or
2048 reallocation must be of the last chunk allocated.
2049
2050 The size of the pool and offset to free memory are packed into the
2051 first 8 bytes of the memory pool so we don't have to keep them in
2052 the decode context. Since the address of the pool may not be
2053 aligned, they have to be packed and unpacked as if they were
2054 serialized data of the wire or such.
2055
2056 The sizes packed in are uint32_t to be the same on all CPU types
2057 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002058 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002059
2060
Laurence Lundbladeee851742020-01-08 08:37:05 -08002061static inline int
2062MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002063{
2064 // Use of UsefulInputBuf is overkill, but it is convenient.
2065 UsefulInputBuf UIB;
2066
Laurence Lundbladeee851742020-01-08 08:37:05 -08002067 // Just assume the size here. It was checked during SetUp so
2068 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002069 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
2070 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2071 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2072 return UsefulInputBuf_GetError(&UIB);
2073}
2074
2075
Laurence Lundbladeee851742020-01-08 08:37:05 -08002076static inline int
2077MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002078{
2079 // Use of UsefulOutBuf is overkill, but convenient. The
2080 // length check performed here is useful.
2081 UsefulOutBuf UOB;
2082
2083 UsefulOutBuf_Init(&UOB, Pool);
2084 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2085 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2086 return UsefulOutBuf_GetError(&UOB);
2087}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002088
2089
2090/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002091 Internal function for an allocation, reallocation free and destuct.
2092
2093 Having only one function rather than one each per mode saves space in
2094 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002095
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002096 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2097 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002098static UsefulBuf
2099MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002100{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002101 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002102
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002103 uint32_t uPoolSize;
2104 uint32_t uFreeOffset;
2105
2106 if(uNewSize > UINT32_MAX) {
2107 // This allocator is only good up to 4GB. This check should
2108 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2109 goto Done;
2110 }
2111 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2112
2113 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2114 goto Done;
2115 }
2116
2117 if(uNewSize) {
2118 if(pMem) {
2119 // REALLOCATION MODE
2120 // Calculate pointer to the end of the memory pool. It is
2121 // assumed that pPool + uPoolSize won't wrap around by
2122 // assuming the caller won't pass a pool buffer in that is
2123 // not in legitimate memory space.
2124 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2125
2126 // Check that the pointer for reallocation is in the range of the
2127 // pool. This also makes sure that pointer math further down
2128 // doesn't wrap under or over.
2129 if(pMem >= pPool && pMem < pPoolEnd) {
2130 // Offset to start of chunk for reallocation. This won't
2131 // wrap under because of check that pMem >= pPool. Cast
2132 // is safe because the pool is always less than UINT32_MAX
2133 // because of check in QCBORDecode_SetMemPool().
2134 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2135
2136 // Check to see if the allocation will fit. uPoolSize -
2137 // uMemOffset will not wrap under because of check that
2138 // pMem is in the range of the uPoolSize by check above.
2139 if(uNewSize <= uPoolSize - uMemOffset) {
2140 ReturnValue.ptr = pMem;
2141 ReturnValue.len = uNewSize;
2142
2143 // Addition won't wrap around over because uNewSize was
2144 // checked to be sure it is less than the pool size.
2145 uFreeOffset = uMemOffset + uNewSize32;
2146 }
2147 }
2148 } else {
2149 // ALLOCATION MODE
2150 // uPoolSize - uFreeOffset will not underflow because this
2151 // pool implementation makes sure uFreeOffset is always
2152 // smaller than uPoolSize through this check here and
2153 // reallocation case.
2154 if(uNewSize <= uPoolSize - uFreeOffset) {
2155 ReturnValue.len = uNewSize;
2156 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002157 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002158 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002159 }
2160 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002161 if(pMem) {
2162 // FREE MODE
2163 // Cast is safe because of limit on pool size in
2164 // QCBORDecode_SetMemPool()
2165 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2166 } else {
2167 // DESTRUCT MODE
2168 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002169 }
2170 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002171
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002172 UsefulBuf Pool = {pPool, uPoolSize};
2173 MemPool_Pack(Pool, uFreeOffset);
2174
2175Done:
2176 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002177}
2178
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002179
Laurence Lundbladef6531662018-12-04 10:42:22 +09002180/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002181 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002182 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002183QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2184 UsefulBuf Pool,
2185 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002186{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002187 // The pool size and free mem offset are packed into the beginning
2188 // of the pool memory. This compile time check make sure the
2189 // constant in the header is correct. This check should optimize
2190 // down to nothing.
2191 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07002192 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002193 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002194
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002195 // The pool size and free offset packed in to the beginning of pool
2196 // memory are only 32-bits. This check will optimize out on 32-bit
2197 // machines.
2198 if(Pool.len > UINT32_MAX) {
2199 return QCBOR_ERR_BUFFER_TOO_LARGE;
2200 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002201
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002202 // This checks that the pool buffer given is big enough.
2203 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
2204 return QCBOR_ERR_BUFFER_TOO_SMALL;
2205 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002206
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002207 pMe->StringAllocator.pfAllocator = MemPool_Function;
2208 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2209 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002210
Laurence Lundblade30816f22018-11-10 13:40:22 +07002211 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002212}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002213
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002214
2215
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002216
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002217
2218
2219/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002220 Consume an entire map or array (and do next to
2221 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002222 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002223static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002224ConsumeItem(QCBORDecodeContext *pMe,
2225 const QCBORItem *pItemToConsume,
2226 uint_fast8_t *puNextNestLevel)
2227{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002228 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002229 QCBORItem Item;
2230
Laurence Lundblade02625d42020-06-25 14:41:41 -07002231 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002232
Laurence Lundblade02625d42020-06-25 14:41:41 -07002233 if(QCBORItem_IsMapOrArray(pItemToConsume)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002234 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002235
Laurence Lundblade1341c592020-04-11 14:19:05 -07002236 /* This works for definite and indefinite length
2237 * maps and arrays by using the nesting level
2238 */
2239 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002240 uReturn = QCBORDecode_GetNext(pMe, &Item);
2241 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002242 goto Done;
2243 }
2244 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002245
Laurence Lundblade1341c592020-04-11 14:19:05 -07002246 if(puNextNestLevel != NULL) {
2247 *puNextNestLevel = Item.uNextNestLevel;
2248 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002249 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002250
Laurence Lundblade1341c592020-04-11 14:19:05 -07002251 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002252 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002253 if(puNextNestLevel != NULL) {
2254 /* Just pass the nesting level through */
2255 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2256 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002257 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002258 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002259
2260Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002261 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002262}
2263
2264
Laurence Lundblade1341c592020-04-11 14:19:05 -07002265/* Return true if the labels in Item1 and Item2 are the same.
2266 Works only for integer and string labels. Returns false
2267 for any other type. */
2268static inline bool
2269MatchLabel(QCBORItem Item1, QCBORItem Item2)
2270{
2271 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2272 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2273 return true;
2274 }
2275 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002276 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002277 return true;
2278 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002279 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002280 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2281 return true;
2282 }
2283 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2284 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2285 return true;
2286 }
2287 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002288
Laurence Lundblade1341c592020-04-11 14:19:05 -07002289 /* Other label types are never matched */
2290 return false;
2291}
2292
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002293
2294/*
2295 Returns true if Item1 and Item2 are the same type
2296 or if either are of QCBOR_TYPE_ANY.
2297 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002298static inline bool
2299MatchType(QCBORItem Item1, QCBORItem Item2)
2300{
2301 if(Item1.uDataType == Item2.uDataType) {
2302 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002303 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002304 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002305 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002306 return true;
2307 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002308 return false;
2309}
2310
2311
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002312/**
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002313 \brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002314
2315 @param[in] pMe The decode context to search.
2316 @param[in,out] pItemArray The items to search for and the items found.
2317 @param[in] pCBContext Context for the not-found item call back
2318 @param[in] pfCallback Function to call on items not matched in pItemArray
2319
2320 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2321
2322 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label) were found for one of the labels being search for. This duplicate detection is only performed for items in pItemArray, not every item in the map.
2323
2324 @retval QCBOR_ERR_UNEXPECTED_TYPE The label was matched, but not the type.
2325
2326 @retval Also errors returned by QCBORDecode_GetNext().
2327
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002328 On input pItemArray contains a list of labels and data types
2329 of items to be found.
2330
2331 On output the fully retrieved items are filled in with
2332 values and such. The label was matched, so it never changes.
2333
2334 If an item was not found, its data type is set to none.
2335
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002336 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002337static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002338MapSearch(QCBORDecodeContext *pMe,
2339 QCBORItem *pItemArray,
2340 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002341 void *pCBContext,
2342 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002343{
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002344 QCBORError uReturn;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002345
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002346 QCBORDecodeNesting SaveNesting;
2347 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002348
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002349 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002350 UsefulInputBuf_Seek(&(pMe->InBuf),
2351 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002352
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002353 /*
2354 Loop over all the items in the map. They could be
2355 deeply nested and this should handle both definite
2356 and indefinite length maps and arrays, so this
2357 adds some complexity.
2358 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002359 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002360
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002361 uint_fast8_t uNextNestLevel;
2362
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002363 uint64_t uFoundItemBitMap = 0;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002364
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002365 /* Iterate over items in the map / array */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002366 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002367 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002368 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002369
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002370 /* Get the item */
2371 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002372 uReturn = QCBORDecode_GetNext(pMe, &Item);
2373 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002374 /* Got non-well-formed CBOR */
2375 goto Done;
2376 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002377
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002378 /* See if item has one of the labels that are of interest */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002379 int nIndex;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002380 QCBORItem *pIterator;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002381 for(pIterator = pItemArray, nIndex = 0; pIterator->uLabelType != 0; pIterator++, nIndex++) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002382 if(MatchLabel(Item, *pIterator)) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002383 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002384 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2385 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002386 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002387 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002388 /* Also try to match its type */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002389 if(!MatchType(Item, *pIterator)) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002390 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002391 goto Done;
2392 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002393
2394 /* Successful match. Return the item. */
2395 *pIterator = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002396 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002397 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002398 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002399 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002400 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002401 /*
2402 Call the callback on unmatched labels.
2403 (It is tempting to do duplicate detection here, but that would
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002404 require dynamic memory allocation because the number of labels
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002405 that might be encountered is unbounded.)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002406 */
2407 if(pfCallback) {
2408 uReturn = (*pfCallback)(pCBContext, &Item);
2409 if(uReturn != QCBOR_SUCCESS) {
2410 goto Done;
2411 }
2412 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002413 }
2414 }
2415
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002416 /*
2417 Consume the item whether matched or not. This
2418 does the work of traversing maps and array and
2419 everything in them. In this loop only the
2420 items at the current nesting level are examined
2421 to match the labels.
2422 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002423 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
2424 if(uReturn) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002425 goto Done;
2426 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002427
2428 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002429
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002430 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002431
2432 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002433 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2434 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002435
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002436 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002437 int i;
2438 QCBORItem *pIterator;
2439 for(pIterator = pItemArray, i = 0; pIterator->uLabelType != 0; pIterator++, i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002440 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002441 pIterator->uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002442 }
2443 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002444
2445Done:
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002446 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002447
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002448 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002449}
2450
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002451
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002452/*
2453Public function, see header qcbor/qcbor_decode.h file
2454*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002455void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2456 int64_t nLabel,
2457 uint8_t uQcborType,
2458 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002459{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002460 if(pMe->uLastError != QCBOR_SUCCESS) {
2461 return;
2462 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002463
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002464 QCBORItem OneItemSeach[2];
2465 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2466 OneItemSeach[0].label.int64 = nLabel;
2467 OneItemSeach[0].uDataType = uQcborType;
2468 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002469
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002470 QCBORError nReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002471 if(nReturn) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002472 pMe->uLastError = (uint8_t)nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002473 }
2474
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002475 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
2476 pMe->uLastError = QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002477 }
2478
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002479 *pItem = OneItemSeach[0];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002480}
2481
2482
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002483/*
2484Public function, see header qcbor/qcbor_decode.h file
2485*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002486void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2487 const char *szLabel,
2488 uint8_t uQcborType,
2489 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002490{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002491 if(pMe->uLastError != QCBOR_SUCCESS) {
2492 return;
2493 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002494
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002495 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002496 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2497 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2498 OneItemSeach[0].uDataType = uQcborType;
2499 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002500
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002501 QCBORError nReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002502 if(nReturn) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07002503 pMe->uLastError = (uint8_t)nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002504 }
2505
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002506 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07002507 pMe->uLastError = QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002508 }
2509
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002510 *pItem = OneItemSeach[0];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002511}
2512
2513
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002514/**
2515 @param[in] TagSpec Specification for matching tags.
2516 @param[in] uDataType A QCBOR data type
2517
2518 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2519 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
2520
2521 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value.
2522 */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002523static QCBORError CheckTagRequirement(const TagSpecification TagSpec, uint8_t uDataType)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002524{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002525 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG) {
2526 /* Must match the tag */
2527 if(uDataType == TagSpec.uTaggedType) {
2528 return QCBOR_SUCCESS;
2529 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002530 } else {
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002531 /* QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE or QCBOR_TAGSPEC_MATCH_EITHER */
2532 /* Must check all the possible types for the tag content */
2533 for(size_t i = 0; i < sizeof(TagSpec.uAllowedContentTypes); i++) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002534 if(uDataType == TagSpec.uAllowedContentTypes[i]) {
2535 return QCBOR_SUCCESS;
2536 }
2537 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002538 /* Didn't match any of the tag content types */
2539 /* Check the tag for the either case */
2540 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_EITHER) {
2541 if(uDataType == TagSpec.uTaggedType) {
2542 return QCBOR_SUCCESS;
2543 }
2544 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002545 }
2546
2547 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002548}
2549
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002550
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002551// Semi-private
2552// TODO: inline or collapse with QCBORDecode_GetTaggedStringInMapN?
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002553void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2554 int64_t nLabel,
2555 TagSpecification TagSpec,
2556 QCBORItem *pItem)
2557{
2558 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2559 if(pMe->uLastError != QCBOR_SUCCESS) {
2560 return;
2561 }
2562
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002563 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002564}
2565
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002566// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002567void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2568 const char *szLabel,
2569 TagSpecification TagSpec,
2570 QCBORItem *pItem)
2571{
2572 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2573 if(pMe->uLastError != QCBOR_SUCCESS) {
2574 return;
2575 }
2576
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002577 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002578}
2579
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002580// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002581void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2582 int64_t nLabel,
2583 TagSpecification TagSpec,
2584 UsefulBufC *pString)
2585{
2586 QCBORItem Item;
2587 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2588 if(pMe->uLastError == QCBOR_SUCCESS) {
2589 *pString = Item.val.string;
2590 }
2591}
2592
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002593// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002594void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2595 const char * szLabel,
2596 TagSpecification TagSpec,
2597 UsefulBufC *pString)
2598{
2599 QCBORItem Item;
2600 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2601 if(pMe->uLastError == QCBOR_SUCCESS) {
2602 *pString = Item.val.string;
2603 }
2604}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002605
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002606/*
2607Public function, see header qcbor/qcbor_decode.h file
2608*/
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002609QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2610{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002611 return MapSearch(pCtx, pItemList, NULL, NULL, NULL);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002612}
2613
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002614/*
2615Public function, see header qcbor/qcbor_decode.h file
2616*/
2617QCBORError QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pCtx,
2618 QCBORItem *pItemList,
2619 void *pCallbackCtx,
2620 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002621{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002622 return MapSearch(pCtx, pItemList, NULL, pCallbackCtx, pfCB);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002623}
2624
2625
Laurence Lundblade34691b92020-05-18 22:25:25 -07002626static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002627{
Laurence Lundblade34691b92020-05-18 22:25:25 -07002628 if(pMe->uLastError != QCBOR_SUCCESS) {
2629 // Already in error state; do nothing.
2630 return;
2631 }
2632
2633 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002634 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002635 if(pMe->uLastError != QCBOR_SUCCESS) {
2636 return;
2637 }
2638
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002639 /* Need to get the current pre-order nesting level and cursor to be
2640 at the first item in the map/array just entered.
2641
2642 Also need to current map nesting level and start cursor to
2643 be at the right place.
2644
2645 The UsefulInBuf offset could be anywhere, so no assumption is
2646 made about it.
2647
2648 No assumption is made about the pre-order nesting level either.
2649
2650 However the map mode nesting level is assumed to be one above
2651 the map level that is being entered.
2652 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002653 /* Seek to the data item that is the map or array */
2654 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002655 pMe->nesting.pCurrent = pMe->nesting.pCurrentBounded; // TODO: part of DecodeNesting
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002656
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002657 QCBORDecode_EnterBoundedMode(pMe, pSearch->uDataType);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002658}
2659
2660
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002661/*
2662Public function, see header qcbor/qcbor_decode.h file
2663*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002664void QCBORDecode_EnterMapInMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002665{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002666 QCBORItem OneItemSeach[2];
2667 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2668 OneItemSeach[0].label.int64 = nLabel;
2669 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2670 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002671
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002672 /* The map to enter was found, now finish of entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002673 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002674}
2675
2676
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002677/*
2678Public function, see header qcbor/qcbor_decode.h file
2679*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002680void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002681{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002682 QCBORItem OneItemSeach[2];
2683 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2684 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2685 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2686 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002687
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002688 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002689}
2690
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002691/*
2692Public function, see header qcbor/qcbor_decode.h file
2693*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002694void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002695{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002696 QCBORItem OneItemSeach[2];
2697 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2698 OneItemSeach[0].label.int64 = nLabel;
2699 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2700 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002701
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002702 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002703}
2704
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002705/*
2706Public function, see header qcbor/qcbor_decode.h file
2707*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002708void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2709{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002710 QCBORItem OneItemSeach[2];
2711 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2712 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2713 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2714 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002715
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002716 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002717}
2718
2719
Laurence Lundblade02625d42020-06-25 14:41:41 -07002720// Semi-private function
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002721/* Next item must be map or this generates an error */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002722void QCBORDecode_EnterBoundedMode(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002723{
Laurence Lundblade34691b92020-05-18 22:25:25 -07002724 if(pMe->uLastError != QCBOR_SUCCESS) {
2725 // Already in error state; do nothing.
2726 return;
2727 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002728
2729 /* Get the data item that is the map that is being searched */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002730 QCBORItem Item;
Laurence Lundblade986017c2020-05-23 19:25:02 -07002731 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002732 if(pMe->uLastError != QCBOR_SUCCESS) {
2733 return;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002734 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002735 if(Item.uDataType != uType) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07002736 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
2737 return;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002738 }
2739
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002740 DecodeNesting_EnterBoundedMode(&(pMe->nesting), UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002741
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002742 // TODO: restrict input to less than this or some other invalidation strategy.
Laurence Lundblade02625d42020-06-25 14:41:41 -07002743 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002744
Laurence Lundblade02625d42020-06-25 14:41:41 -07002745 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "EnterMapModeDone");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002746}
2747
Laurence Lundblade02625d42020-06-25 14:41:41 -07002748
2749/*
2750 This is for exiting a level that is a bounded map, array or bstr
2751 wrapped CBOR. It is the work common to these.
2752
2753 One chunk of work is to set up the pre-order traversal so it is at
2754 the item just after the bounded map, array or bstr that is being
2755 exited. This is somewhat complex.
2756
2757 The other work is to level-up the bounded mode to next higest bounded
2758 mode or the top level if there isn't one.
2759 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002760static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07002761ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002762{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002763 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002764
Laurence Lundblade02625d42020-06-25 14:41:41 -07002765 /*
2766 First the pre-order-traversal byte offset is positioned to the
2767 item just after the bounded mode item that was just consumed.
2768 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002769 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2770
Laurence Lundblade02625d42020-06-25 14:41:41 -07002771 /*
2772 Next, set the current nesting level to one above the bounded level
2773 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002774
Laurence Lundblade02625d42020-06-25 14:41:41 -07002775 DecodeNesting_CheckBoundedType() is always called before this and
2776 makes sure pCurrentBounded is valid.
2777 */
2778 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
2779
2780 /*
2781 This does the complex work of leveling up the pre-order traversal
2782 when the end of a map or array or another bounded level is
2783 reached. It may do nothing, or ascend all the way to the top
2784 level.
2785 */
2786 uErr = NestLevelAscender(pMe);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002787 if(uErr != QCBOR_SUCCESS) {
2788 goto Done;
2789 }
2790
Laurence Lundblade02625d42020-06-25 14:41:41 -07002791 /*
2792 This makes the next highest bounded level the current bounded
2793 level. If there is no next highest level, then no bounded mode is
2794 in effect.
2795 */
2796 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002797
Laurence Lundblade02625d42020-06-25 14:41:41 -07002798 pMe->uMapEndOffsetCache = MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002799
2800Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07002801 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "ExitBoundedLevel");
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002802 return uErr;
2803}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002804
Laurence Lundblade02625d42020-06-25 14:41:41 -07002805
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002806// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07002807void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002808{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002809 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07002810 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002811 return;
2812 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002813
Laurence Lundblade02625d42020-06-25 14:41:41 -07002814 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002815
Laurence Lundblade02625d42020-06-25 14:41:41 -07002816 if(!DecodeNesting_CheckBoundedType(&(pMe->nesting), uType)) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002817 uErr = QCBOR_ERR_CLOSE_MISMATCH;
2818 goto Done;
2819 }
2820
Laurence Lundblade02625d42020-06-25 14:41:41 -07002821 /*
2822 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002823 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07002824 from previous map search, then do a dummy search.
2825 */
2826 if(pMe->uMapEndOffsetCache == MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002827 QCBORItem Dummy;
2828 Dummy.uLabelType = QCBOR_TYPE_NONE;
2829 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
2830 if(uErr != QCBOR_SUCCESS) {
2831 goto Done;
2832 }
2833 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002834
Laurence Lundblade02625d42020-06-25 14:41:41 -07002835 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002836
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002837Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002838 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002839}
2840
2841
Laurence Lundblade1341c592020-04-11 14:19:05 -07002842void QCBORDecode_RewindMap(QCBORDecodeContext *pMe)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002843{
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002844 // TODO: check for map mode; test this
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002845 //pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->u.ma.uCountTotal;
2846 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->u.ma.uStartOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002847}
2848
2849
Laurence Lundblade1341c592020-04-11 14:19:05 -07002850
Laurence Lundblade02625d42020-06-25 14:41:41 -07002851static QCBORError InternalEnterWrappedBstr(QCBORDecodeContext *pMe,
2852 const QCBORItem *pItem,
2853 uint8_t uTagRequirement,
2854 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002855{
2856 if(pMe->uLastError != QCBOR_SUCCESS) {
2857 // Already in error state; do nothing.
2858 return pMe->uLastError;
2859 }
2860
2861 QCBORError uError = QCBOR_SUCCESS;
2862
2863 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
2864 uError = QCBOR_ERR_UNEXPECTED_TYPE;
2865 goto Done;;
2866 }
2867
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002868 // TODO: check for the other wrapped CBOR tag
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002869 const TagSpecification TagSpec = {uTagRequirement, QBCOR_TYPE_WRAPPED_CBOR, {QCBOR_TYPE_BYTE_STRING, 0,0,0,0,0}};
2870
2871 uError = CheckTagRequirement(TagSpec, pItem->uDataType);
2872 if(uError != QCBOR_SUCCESS) {
2873 goto Done;
2874 }
2875
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002876 if(DecodeNesting_IsDefiniteLength(&(pMe->nesting))) {
2877 /* Reverse the decrement done by GetNext() for the bstr as
2878 so the increment in ExitExit()->Ascender() will work right. */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002879 // TODO: method for this
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002880 pMe->nesting.pCurrent->u.ma.uCountCursor++;
2881 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002882
2883 if(pBstr) {
2884 *pBstr = pItem->val.string;
2885 }
2886
2887 const size_t uPreviousLength = UsefulInputBuf_GetLength(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002888
2889 // Need to move UIB input cursor to the right place
2890
2891 // Really this is a subtraction and an assignment; not much code
2892 // There is a range check in the seek.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002893 // The bstr was just consumed so the cursor is at the next item after it
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002894
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002895 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002896
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002897
2898 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
2899
2900 UsefulInputBuf_SetBufferLen(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002901
Laurence Lundblade02625d42020-06-25 14:41:41 -07002902 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
2903 uPreviousLength,
2904 uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002905Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -07002906 DecodeNesting_Print(&(pMe->nesting), &(pMe->InBuf), "Entered Bstr");
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002907
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002908 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002909}
2910
2911
Laurence Lundblade02625d42020-06-25 14:41:41 -07002912/*
2913 Public function, see header qcbor/qcbor_decode.h file
2914 */
2915void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
2916 uint8_t uTagRequirement,
2917 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002918{
2919 if(pMe->uLastError != QCBOR_SUCCESS) {
2920 // Already in error state; do nothing.
2921 return;
2922 }
2923
2924 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002925 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002926 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
2927 if(pMe->uLastError != QCBOR_SUCCESS) {
2928 return;
2929 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002930
Laurence Lundblade02625d42020-06-25 14:41:41 -07002931 pMe->uLastError = (uint8_t)InternalEnterWrappedBstr(pMe,
2932 &Item,
2933 uTagRequirement,
2934 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002935}
2936
2937
Laurence Lundblade02625d42020-06-25 14:41:41 -07002938/*
2939 Public function, see header qcbor/qcbor_decode.h file
2940 */
2941void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
2942 uint8_t uTagRequirement,
2943 int64_t nLabel,
2944 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002945{
2946 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002947 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002948
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002949 pMe->uLastError = (uint8_t)InternalEnterWrappedBstr(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002950}
2951
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002952
Laurence Lundblade02625d42020-06-25 14:41:41 -07002953/*
2954 Public function, see header qcbor/qcbor_decode.h file
2955 */
2956void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
2957 uint8_t uTagRequirement,
2958 const char *szLabel,
2959 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002960{
2961 QCBORItem Item;
2962 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
2963
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002964 pMe->uLastError = (uint8_t)InternalEnterWrappedBstr(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002965}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002966
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002967
Laurence Lundblade02625d42020-06-25 14:41:41 -07002968/*
2969 Public function, see header qcbor/qcbor_decode.h file
2970 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002971void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002972{
Laurence Lundblade02625d42020-06-25 14:41:41 -07002973 if(pMe->uLastError != QCBOR_SUCCESS) {
2974 // Already in error state; do nothing.
2975 return;
2976 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002977
Laurence Lundblade02625d42020-06-25 14:41:41 -07002978 if(!DecodeNesting_CheckBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
2979 pMe->uLastError = QCBOR_ERR_CLOSE_MISMATCH;
2980 return;
2981 }
2982
2983 /*
2984 Reset the length of the UsefulInputBuf to what it was before
2985 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002986 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002987 UsefulInputBuf_SetBufferLen(&(pMe->InBuf),
2988 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002989
2990
Laurence Lundblade02625d42020-06-25 14:41:41 -07002991 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002992 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002993}
2994
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002995
Laurence Lundbladee6430642020-03-14 21:15:44 -07002996
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002997
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002998
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002999
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003000
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003001
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003002static QCBORError InterpretBool(const QCBORItem *pItem, bool *pBool)
3003{
3004 switch(pItem->uDataType) {
3005 case QCBOR_TYPE_TRUE:
3006 *pBool = true;
3007 return QCBOR_SUCCESS;
3008 break;
3009
3010 case QCBOR_TYPE_FALSE:
3011 *pBool = false;
3012 return QCBOR_SUCCESS;
3013 break;
3014
3015 default:
3016 return QCBOR_ERR_UNEXPECTED_TYPE;
3017 break;
3018 }
3019}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003020
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003021/*
3022Public function, see header qcbor/qcbor_decode.h file
3023*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003024void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003025{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003026 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003027 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003028 return;
3029 }
3030
Laurence Lundbladec4537442020-04-14 18:53:22 -07003031 QCBORError nError;
3032 QCBORItem Item;
3033
3034 nError = QCBORDecode_GetNext(pMe, &Item);
3035 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003036 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003037 return;
3038 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003039 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003040}
3041
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003042/*
3043Public function, see header qcbor/qcbor_decode.h file
3044*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003045void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003046{
3047 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003048 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003049
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003050 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003051}
3052
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003053/*
3054Public function, see header qcbor/qcbor_decode.h file
3055*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003056void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3057{
3058 QCBORItem Item;
3059 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3060
3061 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
3062}
3063
3064
3065
3066void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe, TagSpecification TagSpec, UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003067{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003068 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003069 // Already in error state, do nothing
3070 return;
3071 }
3072
3073 QCBORError nError;
3074 QCBORItem Item;
3075
3076 nError = QCBORDecode_GetNext(pMe, &Item);
3077 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003078 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003079 return;
3080 }
3081
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003082 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, Item.uDataType);
3083
3084 if(pMe->uLastError == QCBOR_SUCCESS) {
3085 *pBstr = Item.val.string;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003086 }
3087}
3088
Laurence Lundbladec4537442020-04-14 18:53:22 -07003089
3090
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003091
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003092static QCBORError ConvertBigNum(uint8_t uTagRequirement, const QCBORItem *pItem, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003093{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003094 *pbIsNegative = false;
3095
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003096 bool bMustBeTagged = true; // TODO: fix this --- they have to tell us if they are expecting positive or negative
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003097
3098 switch(pItem->uDataType) {
3099 case QCBOR_TYPE_BYTE_STRING:
3100 // TODO: check that there is no tag here?
3101 if(bMustBeTagged) {
3102 return QCBOR_ERR_UNEXPECTED_TYPE;
3103 } else {
3104 *pValue = pItem->val.string;
3105 return QCBOR_SUCCESS;
3106 }
3107 break;
3108
3109 case QCBOR_TYPE_POSBIGNUM:
3110 *pValue = pItem->val.string;
3111 return QCBOR_SUCCESS;
3112 break;
3113
3114 case QCBOR_TYPE_NEGBIGNUM:
3115 *pbIsNegative = true;
3116 *pValue = pItem->val.string;
3117 return QCBOR_SUCCESS;
3118 break;
3119
3120 default:
3121 return QCBOR_ERR_UNEXPECTED_TYPE;
3122 break;
3123 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003124}
3125
3126
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003127/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003128 @param[in] bMustBeTagged If \c true, then the data item must be tagged as either
3129 a positive or negative bignum. If \c false, then it only must be a byte string and bIsNegative
3130 will always be false on the asumption that it is positive, but it can be interpretted as
3131 negative if the the sign is know from other context.
3132 @param[out] pValue The bytes that make up the big num
3133 @param[out] pbIsNegative \c true if tagged as a negative big num. \c false otherwise.
3134
3135 if bMustBeTagged is false, then this will succeed if the data item is a plain byte string,
3136 a positive big num or a negative big num.
3137
3138 */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003139void QCBORDecode_GetBignum(QCBORDecodeContext *pMe, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003140{
3141 if(pMe->uLastError != QCBOR_SUCCESS) {
3142 // Already in error state, do nothing
3143 return;
3144 }
3145
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003146 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003147 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3148 if(uError != QCBOR_SUCCESS) {
3149 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003150 return;
3151 }
3152
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003153 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003154}
3155
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003156/*
3157Public function, see header qcbor/qcbor_decode.h file
3158*/
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003159void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003160{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003161 QCBORItem Item;
3162 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003163
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003164 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003165}
3166
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003167/*
3168Public function, see header qcbor/qcbor_decode.h file
3169*/
3170void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
3171{
3172 QCBORItem Item;
3173 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3174
3175 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
3176}
3177
3178
3179
3180// Semi private
3181QCBORError FarfMIME(uint8_t uTagRequirement, const QCBORItem *pItem, UsefulBufC *pMessage, bool *pbIsNot7Bit)
3182{
3183 const TagSpecification TagSpecText = {uTagRequirement, QCBOR_TYPE_MIME, {QCBOR_TYPE_TEXT_STRING, 0,0,0,0,0}};
3184 const TagSpecification TagSpecBinary = {uTagRequirement, QCBOR_TYPE_BINARY_MIME, {QCBOR_TYPE_BYTE_STRING, 0,0,0,0,0}};
3185
3186 QCBORError uReturn;
3187
3188 if(CheckTagRequirement(TagSpecText, pItem->uDataType)) {
3189 *pMessage = pItem->val.string;
3190 if(pbIsNot7Bit != NULL) {
3191 *pbIsNot7Bit = false;
3192 }
3193 uReturn = QCBOR_SUCCESS;
3194 } else if(CheckTagRequirement(TagSpecBinary, pItem->uDataType)) {
3195 *pMessage = pItem->val.string;
3196 if(pbIsNot7Bit != NULL) {
3197 *pbIsNot7Bit = true;
3198 }
3199 uReturn = QCBOR_SUCCESS;
3200
3201 } else {
3202 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3203 }
3204
3205 return uReturn;
3206}
3207
3208
3209
3210
3211
Laurence Lundbladec4537442020-04-14 18:53:22 -07003212
3213
3214
Laurence Lundbladee6430642020-03-14 21:15:44 -07003215
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003216typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003217
3218
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003219// The main exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003220static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003221{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003222 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003223
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003224 if(uResult != 0) {
3225 /* This loop will run a maximum of 19 times because
3226 * UINT64_MAX < 10 ^^ 19. More than that will cause
3227 * exit with the overflow error
3228 */
3229 for(; nExponent > 0; nExponent--) {
3230 if(uResult > UINT64_MAX / 10) {
3231 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3232 }
3233 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003234 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003235
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003236 for(; nExponent < 0; nExponent++) {
3237 uResult = uResult / 10;
3238 if(uResult == 0) {
3239 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3240 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003241 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003242 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003243 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003244
3245 *puResult = uResult;
3246
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003247 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003248}
3249
3250
Laurence Lundbladee6430642020-03-14 21:15:44 -07003251/* Convert a decimal fraction to an int64_t without using
3252 floating point or math libraries. Most decimal fractions
3253 will not fit in an int64_t and this will error out with
3254 under or overflow
3255 */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003256static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003257{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003258 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003259
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003260 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003261
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003262 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003263 * INT64_MAX < 2^31. More than that will cause
3264 * exist with the overflow error
3265 */
3266 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003267 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003268 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003269 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003270 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003271 nExponent--;
3272 }
3273
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003274 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003275 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003276 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3277 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003278 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003279 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003280 }
3281
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003282 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003283
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003284 return QCBOR_SUCCESS;
3285}
3286
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003287/*
3288 Compute value with signed mantissa and signed result. Works with exponent of 2 or 10 based on exponentiator.
3289 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003290static inline QCBORError ExponentiateNN(int64_t nMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
3291{
3292 uint64_t uResult;
3293
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003294 // Take the absolute value of the mantissa and convert to unsigned.
3295 // TODO: this should be possible in one intruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003296 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3297
3298 // Do the exponentiation of the positive mantissa
3299 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3300 if(uReturn) {
3301 return uReturn;
3302 }
3303
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003304
Laurence Lundblade983500d2020-05-14 11:49:34 -07003305 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3306 of INT64_MIN. This assumes two's compliment representation where
3307 INT64_MIN is one increment farther from 0 than INT64_MAX.
3308 Trying to write -INT64_MIN doesn't work to get this because the
3309 compiler tries to work with an int64_t which can't represent
3310 -INT64_MIN.
3311 */
3312 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3313
3314 // Error out if too large
3315 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003316 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3317 }
3318
3319 // Casts are safe because of checks above
3320 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3321
3322 return QCBOR_SUCCESS;
3323}
3324
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003325/*
3326 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3327 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003328static inline QCBORError ExponentitateNU(int64_t nMantissa, int64_t nExponent, uint64_t *puResult, fExponentiator pfExp)
3329{
3330 if(nMantissa < 0) {
3331 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3332 }
3333
3334 // Cast to unsigned is OK because of check for negative
3335 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3336 // Exponentiation is straight forward
3337 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3338}
3339
3340
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003341#include <math.h>
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003342
3343
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003344static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003345{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003346 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003347
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003348 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003349 const uint8_t *pByte = BigNum.ptr;
3350 size_t uLen = BigNum.len;
3351 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003352 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003353 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003354 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003355 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003356 }
3357
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003358 *pResult = uResult;
3359 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003360}
3361
Laurence Lundblade887add82020-05-17 05:50:34 -07003362static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003363{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003364 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003365}
3366
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003367static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003368{
3369 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003370 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3371 if(uError) {
3372 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003373 }
3374 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3375 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003376 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003377}
3378
3379
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003380static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003381{
3382 uint64_t uResult;
Laurence Lundbladeda095972020-06-06 18:35:33 -07003383 /* negaative int furthest from zero is INT64_MIN
3384 which is expressed as -INT64_MAX-1. The value of
3385 a negative bignum is -n-1, one further from zero
3386 than the positive bignum */
3387
3388 /* say INT64_MIN is -2; then INT64_MAX is 1.
3389 Then -n-1 <= INT64_MIN.
3390 Then -n -1 <= -INT64_MAX - 1
3391 THen n <= INT64_MAX. */
3392 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003393 if(uError) {
3394 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003395 }
3396 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
Laurence Lundblade887add82020-05-17 05:50:34 -07003397 // TODO: this code is incorrect. See RFC 7049
Laurence Lundbladeda095972020-06-06 18:35:33 -07003398 uResult++; // this is the -1 in -n-1
Laurence Lundbladee6430642020-03-14 21:15:44 -07003399 *pResult = -(int64_t)uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003400 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003401}
3402
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003403#include "fenv.h"
Laurence Lundbladec4537442020-04-14 18:53:22 -07003404
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003405
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003406/*
3407Convert a integers and floats to an int64_t.
3408
3409\param[in] uOptions Bit mask list of conversion options.
3410
3411\retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
3412
3413\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3414
3415\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3416
3417*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003418static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
3419{
3420 switch(pItem->uDataType) {
3421 // TODO: float when ifdefs are set
3422 case QCBOR_TYPE_DOUBLE:
3423 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3424 // TODO: what about under/overflow here?
3425 // Invokes the floating-point HW and/or compiler-added libraries
3426 feclearexcept(FE_ALL_EXCEPT);
3427 *pnValue = llround(pItem->val.dfnum);
3428 if(fetestexcept(FE_INVALID)) {
3429 // TODO: better error code
3430 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3431 }
3432 } else {
3433 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3434 }
3435 break;
3436
3437 case QCBOR_TYPE_INT64:
3438 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
3439 *pnValue = pItem->val.int64;
3440 } else {
3441 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3442 }
3443 break;
3444
3445 case QCBOR_TYPE_UINT64:
3446 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
3447 if(pItem->val.uint64 < INT64_MAX) {
3448 *pnValue = pItem->val.int64;
3449 } else {
3450 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3451 }
3452 } else {
3453 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3454 }
3455 break;
3456
3457 default:
3458 return QCBOR_ERR_UNEXPECTED_TYPE;
3459 }
3460 return QCBOR_SUCCESS;
3461}
3462
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003463
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003464void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
3465 uint32_t uOptions,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003466 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003467 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003468{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003469 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003470 return;
3471 }
3472
Laurence Lundbladee6430642020-03-14 21:15:44 -07003473 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003474 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3475 if(uError) {
3476 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003477 return;
3478 }
3479
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003480 if(pItem) {
3481 *pItem = Item;
3482 }
3483
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003484 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003485}
3486
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003487
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003488void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3489 int64_t nLabel,
3490 uint32_t uOptions,
3491 int64_t *pnValue,
3492 QCBORItem *pItem)
3493{
3494 QCBORItem Item;
3495 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3496
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003497 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003498}
3499
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003500
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003501void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3502 const char * szLabel,
3503 uint32_t uOptions,
3504 int64_t *pnValue,
3505 QCBORItem *pItem)
3506{
3507 if(pMe->uLastError != QCBOR_SUCCESS) {
3508 return;
3509 }
3510
3511 QCBORItem Item;
3512 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3513
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003514 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003515}
3516
3517
3518
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003519/*
3520 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003521
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003522 \param[in] uOptions Bit mask list of conversion options.
3523
3524 \retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
3525
3526 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3527
3528 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3529
3530 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003531static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
3532{
3533 QCBORError uErr;
3534
3535 switch(pItem->uDataType) {
3536
3537 case QCBOR_TYPE_POSBIGNUM:
3538 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3539 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003540 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003541 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003542 }
3543 break;
3544
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003545 case QCBOR_TYPE_NEGBIGNUM:
3546 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3547 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003548 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003549 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003550 }
3551 break;
3552
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003553#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3554 case QCBOR_TYPE_DECIMAL_FRACTION:
3555 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3556 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3557 pItem->val.expAndMantissa.nExponent,
3558 pnValue,
3559 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003560 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003561 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3562 }
3563 break;
3564
3565 case QCBOR_TYPE_BIGFLOAT:
3566 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3567 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3568 pItem->val.expAndMantissa.nExponent,
3569 pnValue,
3570 Exponentitate2);
3571 } else {
3572 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3573 }
3574 break;
3575
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003576 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3577 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3578 int64_t nMantissa;
3579 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3580 if(uErr) {
3581 return uErr;
3582 }
3583 return ExponentiateNN(nMantissa,
3584 pItem->val.expAndMantissa.nExponent,
3585 pnValue,
3586 Exponentitate10);
3587 } else {
3588 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3589 }
3590 break;
3591
3592 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3593 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3594 int64_t nMantissa;
3595 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3596 if(uErr) {
3597 return uErr;
3598 }
3599 return ExponentiateNN(nMantissa,
3600 pItem->val.expAndMantissa.nExponent,
3601 pnValue,
3602 Exponentitate10);
3603 } else {
3604 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3605 }
3606 break;
3607
3608 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3609 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3610 int64_t nMantissa;
3611 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3612 if(uErr) {
3613 return uErr;
3614 }
3615 return ExponentiateNN(nMantissa,
3616 pItem->val.expAndMantissa.nExponent,
3617 pnValue,
3618 Exponentitate2);
3619 } else {
3620 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3621 }
3622 break;
3623
3624 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3625 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3626 int64_t nMantissa;
3627 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3628 if(uErr) {
3629 return uErr;
3630 }
3631 return ExponentiateNN(nMantissa,
3632 pItem->val.expAndMantissa.nExponent,
3633 pnValue,
3634 Exponentitate2);
3635 } else {
3636 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003637 }
3638 break;
3639
Laurence Lundbladec4537442020-04-14 18:53:22 -07003640 default:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003641 return QCBOR_ERR_UNEXPECTED_TYPE;
3642#endif
Laurence Lundbladec4537442020-04-14 18:53:22 -07003643 }
3644}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003645
3646
Laurence Lundbladec4537442020-04-14 18:53:22 -07003647/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003648 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003649 */
3650void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003651{
3652 QCBORItem Item;
3653
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003654 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003655
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003656 if(pMe->uLastError == QCBOR_SUCCESS) {
3657 // The above conversion succeeded
3658 return;
3659 }
3660
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003661 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003662 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07003663 return;
3664 }
3665
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003666 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003667}
3668
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003669
3670/*
3671Public function, see header qcbor/qcbor_decode.h file
3672*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003673void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int64_t *pnValue)
3674{
3675 QCBORItem Item;
3676
3677 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, pnValue, &Item);
3678
3679 if(pMe->uLastError == QCBOR_SUCCESS) {
3680 // The above conversion succeeded
3681 return;
3682 }
3683
3684 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3685 // The above conversion failed in a way that code below can't correct
3686 return;
3687 }
3688
3689 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3690}
3691
3692
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003693/*
3694Public function, see header qcbor/qcbor_decode.h file
3695*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003696void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int64_t *pnValue)
3697{
3698 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003699 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, pnValue, &Item);
3700
3701 if(pMe->uLastError == QCBOR_SUCCESS) {
3702 // The above conversion succeeded
3703 return;
3704 }
3705
3706 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3707 // The above conversion failed in a way that code below can't correct
3708 return;
3709 }
3710
3711 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3712}
3713
3714
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003715static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3716{
3717 switch(pItem->uDataType) {
3718 // TODO: type flaot
3719 case QCBOR_TYPE_DOUBLE:
3720 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3721 feclearexcept(FE_ALL_EXCEPT);
3722 double dRounded = round(pItem->val.dfnum);
3723 // TODO: over/underflow
3724 if(fetestexcept(FE_INVALID)) {
3725 // TODO: better error code
3726 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3727 } else if(isnan(dRounded)) {
3728 // TODO: better error code
3729 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3730 } else if(dRounded >= 0) {
3731 *puValue = (uint64_t)dRounded;
3732 } else {
3733 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3734 }
3735 } else {
3736 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3737 }
3738 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003739
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003740 case QCBOR_TYPE_INT64:
3741 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
3742 if(pItem->val.int64 >= 0) {
3743 *puValue = (uint64_t)pItem->val.int64;
3744 } else {
3745 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3746 }
3747 } else {
3748 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3749 }
3750 break;
3751
3752 case QCBOR_TYPE_UINT64:
3753 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
3754 *puValue = pItem->val.uint64;
3755 } else {
3756 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3757 }
3758 break;
3759
3760 default:
3761 return QCBOR_ERR_UNEXPECTED_TYPE;
3762 }
3763 return QCBOR_SUCCESS;
3764}
Laurence Lundbladec4537442020-04-14 18:53:22 -07003765
3766
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003767void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
3768 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003769 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003770 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003771{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003772 if(pMe->uLastError != QCBOR_SUCCESS) {
3773 return;
3774 }
3775
Laurence Lundbladec4537442020-04-14 18:53:22 -07003776 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003777
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003778 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3779 if(uError) {
3780 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003781 return;
3782 }
3783
Laurence Lundbladea826c502020-05-10 21:07:00 -07003784 if(pItem) {
3785 *pItem = Item;
3786 }
3787
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003788 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003789}
3790
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003791
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003792void QCBORDecode_GetInt8ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3793{
3794 int64_t uValue;
3795 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, &uValue, pItem);
3796 if(pMe->uLastError != QCBOR_SUCCESS) {
3797 return;
3798 }
3799
3800 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3801 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3802 }
3803}
3804
3805void QCBORDecode_GetInt8ConvertInternalInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3806{
3807 int64_t uValue;
3808 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, &uValue, pItem);
3809 if(pMe->uLastError != QCBOR_SUCCESS) {
3810 return;
3811 }
3812
3813 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3814 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3815 }
3816}
3817
3818void QCBORDecode_GetInt8ConvertInternalInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3819{
3820 int64_t uValue;
3821 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, &uValue, pItem);
3822 if(pMe->uLastError != QCBOR_SUCCESS) {
3823 return;
3824 }
3825
3826 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3827 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3828 }
3829}
3830
3831
3832
3833
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003834void QCBORDecode_GetUint64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3835 int64_t nLabel,
3836 uint32_t uOptions,
3837 uint64_t *puValue,
3838 QCBORItem *pItem)
3839{
3840 QCBORItem Item;
3841 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3842
3843 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
3844}
3845
3846
3847void QCBORDecode_GetUint64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3848 const char * szLabel,
3849 uint32_t uOptions,
3850 uint64_t *puValue,
3851 QCBORItem *pItem)
3852{
3853 if(pMe->uLastError != QCBOR_SUCCESS) {
3854 return;
3855 }
3856
3857 QCBORItem Item;
3858 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3859
3860 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
3861}
3862
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003863/*
3864 Public function, see header qcbor/qcbor_decode.h file
3865*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003866static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3867{
3868 QCBORError uErr;
3869
3870 switch(pItem->uDataType) {
3871
3872 case QCBOR_TYPE_POSBIGNUM:
3873 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3874 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
3875 } else {
3876 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3877 }
3878 break;
3879
3880 case QCBOR_TYPE_NEGBIGNUM:
3881 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3882 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3883 } else {
3884 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3885 }
3886 break;
3887
3888#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3889
3890 case QCBOR_TYPE_DECIMAL_FRACTION:
3891 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3892 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3893 pItem->val.expAndMantissa.nExponent,
3894 puValue,
3895 Exponentitate10);
3896 } else {
3897 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3898 }
3899 break;
3900
3901 case QCBOR_TYPE_BIGFLOAT:
3902 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3903 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3904 pItem->val.expAndMantissa.nExponent,
3905 puValue,
3906 Exponentitate2);
3907 } else {
3908 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3909 }
3910 break;
3911
3912 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3913 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3914 // TODO: Would be better to convert to unsigned
3915 int64_t nMantissa;
3916 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3917 if(uErr != QCBOR_SUCCESS) {
3918 return uErr;
3919 }
3920 return ExponentitateNU(nMantissa,
3921 pItem->val.expAndMantissa.nExponent,
3922 puValue,
3923 Exponentitate10);
3924 } else {
3925 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3926 }
3927 break;
3928
3929 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3930 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3931 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3932 } else {
3933 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3934 }
3935 break;
3936
3937 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3938 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3939 // TODO: Would be better to convert to unsigned
3940 int64_t nMantissa;
3941 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3942 if(uErr != QCBOR_SUCCESS) {
3943 return uErr;
3944 }
3945 return ExponentitateNU(nMantissa,
3946 pItem->val.expAndMantissa.nExponent,
3947 puValue,
3948 Exponentitate2);
3949 } else {
3950 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3951 }
3952 break;
3953
3954 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3955 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3956 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3957 } else {
3958 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3959 }
3960 break;
3961#endif
3962 default:
3963 return QCBOR_ERR_UNEXPECTED_TYPE;
3964 }
3965}
3966
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003967/*
3968 Public function, see header qcbor/qcbor_decode.h file
3969*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003970void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003971{
3972 QCBORItem Item;
3973
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003974 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003975
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003976 if(pMe->uLastError == QCBOR_SUCCESS) {
3977 // The above conversion succeeded
3978 return;
3979 }
3980
3981 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3982 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07003983 return;
3984 }
3985
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003986 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003987}
3988
Laurence Lundbladec4537442020-04-14 18:53:22 -07003989
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003990/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003991 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003992*/
3993void QCBORDecode_GetUint64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, uint64_t *puValue)
3994{
3995 QCBORItem Item;
3996
3997 QCBORDecode_GetUint64ConvertInternalInMapN(pMe, nLabel, uOptions, puValue, &Item);
3998
3999 if(pMe->uLastError == QCBOR_SUCCESS) {
4000 // The above conversion succeeded
4001 return;
4002 }
4003
4004 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4005 // The above conversion failed in a way that code below can't correct
4006 return;
4007 }
4008
4009 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
4010}
4011
4012
4013/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004014 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004015*/
4016void QCBORDecode_GetUint64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, uint64_t *puValue)
4017{
4018 QCBORItem Item;
4019 QCBORDecode_GetUint64ConvertInternalInMapSZ(pMe, szLabel, uOptions, puValue, &Item);
4020
4021 if(pMe->uLastError == QCBOR_SUCCESS) {
4022 // The above conversion succeeded
4023 return;
4024 }
4025
4026 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4027 // The above conversion failed in a way that code below can't correct
4028 return;
4029 }
4030
4031 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
4032}
4033
4034
4035static QCBORError ConvertDouble(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
4036{
4037 switch(pItem->uDataType) {
4038 // TODO: float when ifdefs are set
4039 case QCBOR_TYPE_DOUBLE:
4040 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
4041 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
4042 *pdValue = pItem->val.dfnum;
4043 } else {
4044 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4045 }
4046 }
4047 break;
4048
4049 case QCBOR_TYPE_INT64:
4050 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
4051 // TODO: how does this work?
4052 *pdValue = (double)pItem->val.int64;
4053
4054 } else {
4055 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4056 }
4057 break;
4058
4059 case QCBOR_TYPE_UINT64:
4060 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
4061 *pdValue = (double)pItem->val.uint64;
4062 } else {
4063 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4064 }
4065 break;
4066
4067 default:
4068 return QCBOR_ERR_UNEXPECTED_TYPE;
4069 }
4070
4071 return QCBOR_SUCCESS;
4072}
4073
4074
4075
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004076void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
4077 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004078 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004079 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004080{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004081 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004082 return;
4083 }
4084
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004085 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004086
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004087 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004088 if(uError) {
4089 pMe->uLastError = (uint8_t)uError;
4090 return;
4091 }
4092
4093 if(pItem) {
4094 *pItem = Item;
4095 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004096
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004097 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004098}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004099
Laurence Lundbladec4537442020-04-14 18:53:22 -07004100
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004101void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4102 int64_t nLabel,
4103 uint32_t uOptions,
4104 double *pdValue,
4105 QCBORItem *pItem)
4106{
4107 QCBORItem Item;
4108 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4109
4110 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
4111}
4112
4113void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4114 const char * szLabel,
4115 uint32_t uOptions,
4116 double *pdValue,
4117 QCBORItem *pItem)
4118{
4119 if(pMe->uLastError != QCBOR_SUCCESS) {
4120 return;
4121 }
4122
4123 QCBORItem Item;
4124 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4125
4126 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
4127}
4128
4129
4130
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004131static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4132{
4133 double dResult;
4134
4135 dResult = 0.0;
4136 const uint8_t *pByte = BigNum.ptr;
4137 size_t uLen = BigNum.len;
4138 /* This will overflow and become the float value INFINITY if the number
4139 is too large to fit. No error will be logged.
4140 TODO: should an error be logged? */
4141 while(uLen--) {
4142 dResult = (dResult * 256.0) + (double)*pByte++;
4143 }
4144
4145 return dResult;
4146}
4147
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004148static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004149{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004150 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004151 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4152
4153 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004154 switch(pItem->uDataType) {
4155 // TODO: type float
4156 case QCBOR_TYPE_DECIMAL_FRACTION:
4157 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4158 // TODO: rounding and overflow errors
4159 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4160 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4161 } else {
4162 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4163 }
4164 break;
4165
4166 case QCBOR_TYPE_BIGFLOAT:
4167 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
4168 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4169 exp2((double)pItem->val.expAndMantissa.nExponent);
4170 } else {
4171 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4172 }
4173 break;
4174
4175 case QCBOR_TYPE_POSBIGNUM:
4176 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
4177 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4178 } else {
4179 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4180 }
4181 break;
4182
4183 case QCBOR_TYPE_NEGBIGNUM:
4184 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004185 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004186 } else {
4187 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4188 }
4189 break;
4190
4191 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4192 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4193 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4194 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4195 } else {
4196 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4197 }
4198 break;
4199
4200 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4201 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4202 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4203 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4204 } else {
4205 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4206 }
4207 break;
4208
4209 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
4210 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
4211 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4212 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4213 } else {
4214 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4215 }
4216 break;
4217
4218 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
4219 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004220 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004221 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4222 } else {
4223 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4224 }
4225 break;
4226
4227 default:
4228 return QCBOR_ERR_UNEXPECTED_TYPE;
4229 }
4230
4231 return QCBOR_SUCCESS;
4232}
4233
4234
4235/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004236 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004237*/
4238void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pdValue)
4239{
4240
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004241 QCBORItem Item;
4242
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004243 QCBORDecode_GetDoubleConvertInternal(pMe, uOptions, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004244
4245 if(pMe->uLastError == QCBOR_SUCCESS) {
4246 // The above conversion succeeded
4247 return;
4248 }
4249
4250 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4251 // The above conversion failed in a way that code below can't correct
4252 return;
4253 }
4254
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004255 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004256}
4257
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004258
4259/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004260 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004261*/
4262void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, double *pdValue)
4263{
4264 QCBORItem Item;
4265
4266 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uOptions, pdValue, &Item);
4267
4268 if(pMe->uLastError == QCBOR_SUCCESS) {
4269 // The above conversion succeeded
4270 return;
4271 }
4272
4273 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4274 // The above conversion failed in a way that code below can't correct
4275 return;
4276 }
4277
4278 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
4279}
4280
4281
4282/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004283 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004284*/
4285void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, double *pdValue)
4286{
4287 QCBORItem Item;
4288 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uOptions, pdValue, &Item);
4289
4290 if(pMe->uLastError == QCBOR_SUCCESS) {
4291 // The above conversion succeeded
4292 return;
4293 }
4294
4295 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4296 // The above conversion failed in a way that code below can't correct
4297 return;
4298 }
4299
4300 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
4301}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004302
4303
4304void FarfDecimalFraction(QCBORDecodeContext *pMe,
4305 uint8_t uTagRequirement,
4306 QCBORItem *pItem,
4307 int64_t *pnMantissa,
4308 int64_t *pnExponent)
4309{
4310 QCBORError uErr;
4311
4312 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
4313 if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
4314 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4315 return;
4316 }
4317 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4318 if(uErr != QCBOR_SUCCESS) {
4319 pMe->uLastError = (uint8_t)uErr;
4320 return;
4321 }
4322 }
4323
4324 if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
4325 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4326 return;
4327 }
4328
4329 switch (pItem->uDataType) {
4330
4331 case QCBOR_TYPE_DECIMAL_FRACTION:
4332 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
4333 *pnExponent = pItem->val.expAndMantissa.nExponent;
4334 break;
4335
4336 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4337 *pnExponent = pItem->val.expAndMantissa.nExponent;
4338
4339 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4340 if(uErr != QCBOR_SUCCESS) {
4341 pMe->uLastError = (uint8_t)uErr;
4342 }
4343 break;
4344
4345 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4346 *pnExponent = pItem->val.expAndMantissa.nExponent;
4347
4348 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4349 if(uErr != QCBOR_SUCCESS) {
4350 pMe->uLastError = (uint8_t)uErr;
4351 }
4352 break;
4353
4354 default:
4355 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4356 }
4357}
4358
4359void QCBORDecode_GetDecimalFractionN(QCBORDecodeContext *pMe,
4360 uint8_t uTagRequirement,
4361 int64_t nLabel,
4362 int64_t *pnMantissa,
4363 int64_t *pnExponent)
4364{
4365 QCBORItem Item;
4366
4367 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4368 FarfDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
4369}
4370
4371
4372
4373void QCBORDecode_GetDecimalFractionSZ(QCBORDecodeContext *pMe,
4374 uint8_t uTagRequirement,
4375 const char *szLabel,
4376 int64_t *pnMantissa,
4377 int64_t *pnExponent)
4378{
4379 QCBORItem Item;
4380
4381 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4382
4383 FarfDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
4384}
4385
4386
4387UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4388{
4389 while(uInt & 0xff0000000000UL) {
4390 uInt = uInt << 8;
4391 };
4392
4393 UsefulOutBuf UOB;
4394
4395 UsefulOutBuf_Init(&UOB, Buffer);
4396
4397 while(uInt) {
4398 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff0000000000UL) >> 56));
4399 uInt = uInt << 8;
4400 }
4401
4402 return UsefulOutBuf_OutUBuf(&UOB);
4403}
4404
4405
4406void QCBORDecode_GetDecimalFractionBigN(QCBORDecodeContext *pMe,
4407 uint8_t uTagRequirement,
4408 int64_t nLabel,
4409 UsefulBuf pBufferForMantissa,
4410 UsefulBufC *pMantissa,
4411 bool *pbIsNegative,
4412 int64_t *pnExponent)
4413{
4414 QCBORItem Item;
4415 QCBORError uErr;
4416
4417 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4418
4419 if(Item.uDataType == QCBOR_TYPE_ARRAY) {
4420 uErr = QCBORDecode_MantissaAndExponent(pMe, &Item);
4421 if(uErr != QCBOR_SUCCESS) {
4422 pMe->uLastError = (uint8_t)uErr;
4423 return;
4424 }
4425 }
4426
4427 uint64_t uMantissa;
4428
4429 switch (Item.uDataType) {
4430
4431 case QCBOR_TYPE_DECIMAL_FRACTION:
4432 if(Item.val.expAndMantissa.Mantissa.nInt >= 0) {
4433 uMantissa = (uint64_t)Item.val.expAndMantissa.Mantissa.nInt;
4434 *pbIsNegative = false;
4435 } else {
4436 uMantissa = (uint64_t)-Item.val.expAndMantissa.Mantissa.nInt;
4437 *pbIsNegative = true;
4438 }
4439 *pMantissa = ConvertIntToBigNum(uMantissa, pBufferForMantissa);
4440 *pnExponent = Item.val.expAndMantissa.nExponent;
4441 break;
4442
4443 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4444 *pnExponent = Item.val.expAndMantissa.nExponent;
4445 *pMantissa = Item.val.expAndMantissa.Mantissa.bigNum;
4446 *pbIsNegative = false;
4447 break;
4448
4449 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4450 *pnExponent = Item.val.expAndMantissa.nExponent;
4451 *pMantissa = Item.val.expAndMantissa.Mantissa.bigNum;
4452 *pbIsNegative = true;
4453 break;
4454
4455 default:
4456 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4457 }
4458}