blob: 945eadd048054ca9ad5a6c08ff8ba84e25ef794a [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 Lundbladeee851742020-01-08 08:37:05 -080046/*===========================================================================
47 DecodeNesting -- Functions for tracking array/map nesting when decoding
48
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080049 See qcbor/qcbor_decode.h for definition of the object
50 used here: QCBORDecodeNesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080051 ===========================================================================*/
52
Laurence Lundblade9c905e82020-04-25 11:31:38 -070053
54
55/*
56The main mode of decoding is a pre-order travesal of the tree of leaves (numbers, strings...)
57formed by intermediate nodes (arrays and maps). The cursor for the traversal
58 is the byte offset in the encoded input and a leaf counter for definite
59 length maps and arrays. Indefinite length maps and arrays are handled
60 by look ahead for the break.
61
62 The view presented to the caller has tags, labels and the chunks of
63 indefinite length strings aggregated into one decorated data item.
64
65The caller understands the nesting level in pre-order traversal by
66 the fact that a data item that is a map or array is presented to
67 the caller when it is first encountered in the pre-order traversal and that all data items are presented with its nesting level
68 and the nesting level of the next item.
69
70 The caller traverse maps and arrays in a special mode that often more convenient
71 that tracking by nesting level. When an array or map is expected or encountered
72 the EnterMap or EnteryArray can be called.
73
74 When entering a map or array like this, the cursor points to the first
75 item in the map or array. When exiting, it points to the item after
76 the map or array, regardless of whether the items in the map or array were
77 all traversed.
78
79 When in a map or array, the cursor functions as normal, but traversal
80 cannot go past the end of the map or array that was entered. If this
81 is attempted the QCBOR_ERR_NO_MORE_ITEMS error is returned. To
82 go past the end of the map or array ExitMap() or ExitArray() must
83 be called. It can be called any time regardless of the position
84 of the cursor.
85
86 When a map is entered, a special function allows fetching data items
87 by label. This call will traversal the whole map looking for the
88 labeled item. The whole map is traversed so as to detect duplicates.
89 This type of fetching items does not affect the normal traversal
90 cursor.
91
92
93
94
95
96
97
98
99
100
101When a data item is presented to the caller, the nesting level of the data
102 item is presented along with the nesting level of the item that would be
103 next consumed.
104
105
106
107
108
109
110
111
112
113 */
114
Laurence Lundblade6b249302020-04-30 12:38:12 -0700115inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700116// TODO: add more tests for QCBOR_TYPE_MAP_AS_ARRAY mode in qcbor_decode_tests.c
Laurence Lundbladeee851742020-01-08 08:37:05 -0800117IsMapOrArray(uint8_t uDataType)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700118{
Laurence Lundblade6b249302020-04-30 12:38:12 -0700119 return uDataType == QCBOR_TYPE_MAP ||
120 uDataType == QCBOR_TYPE_ARRAY ||
121 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700122}
123
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700124
125inline static uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700126DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700127{
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700128 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700129 // Check in DecodeNesting_Descend and never having
130 // QCBOR_MAX_ARRAY_NESTING > 255 gaurantees cast is safe
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700131 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700132}
133
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700134inline static uint8_t
135DecodeNesting_GetBoundedModeLevel(QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700136{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700137 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pMapsAndArrays[0]);
138
139 // Check in DecodeNesting_Descend and never having
140 // QCBOR_MAX_ARRAY_NESTING > 255 gaurantees cast is safe
141 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700142}
143
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700144inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700145DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700146{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700147 if(pNesting->pCurrent == &(pNesting->pMapsAndArrays[0])) {
148 return true;
149 } else {
150 return false;
151 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700152}
153
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700154inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700155DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700156{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700157 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
158 /* Not a map or array */
159 return false;
160 }
161 if(pNesting->pCurrent->u.ma.uCountCursor != UINT16_MAX) {
162 /* Not indefinte length */
163 return false;
164 }
165 /* All checks passed; is an indefinte length map or array */
166 return true;
167}
168
169inline static bool
170DecodeNesting_IsDefiniteLength(const QCBORDecodeNesting *pNesting)
171{
172 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
173 /* Not a map or array */
174 return false;
175 }
176 if(pNesting->pCurrent->u.ma.uCountCursor == UINT16_MAX) {
177 /* Is indefinite */
178 return false;
179 }
180 /* All checks passed; is a definte length map or array */
181 return true;
182}
183
Laurence Lundblade642282a2020-06-23 12:00:33 -0700184inline static bool
185DecodeNesting_IsBstrWrapped(const QCBORDecodeNesting *pNesting)
186{
187 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
188 /* is a byte string */
189 return true;
190 }
191 return false;
192}
193
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700194inline static bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700195{
196 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
197 return true;
198 }
199 if(pNesting->pCurrent->u.ma.uStartOffset != UINT32_MAX) {
200 return true;
201 }
202 return false;
203}
204
205inline static void DecodeNesting_SetBoundedMode(const QCBORDecodeNesting *pNesting, size_t uStart)
206{
207 // Should be only called on maps and arrays
208 // TODO: check this cast, maybe give an error?
209 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
210}
211
212inline static void DecodeNesting_ClearBoundedMode(const QCBORDecodeNesting *pNesting)
213{
214 pNesting->pCurrent->u.ma.uStartOffset = UINT32_MAX;
215}
216
217inline static bool
Laurence Lundblade642282a2020-06-23 12:00:33 -0700218DecodeNesting_IsAtEndOfBoundedDefiniteLenMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700219{
220 if(pNesting->pCurrentBounded == NULL) {
221 /* No bounded map or array or... set up. */
222 return false;
223 }
224 if(pNesting->pCurrentBounded->uLevelType == QCBOR_TYPE_BYTE_STRING) {
225 /* Not a map or array */
226 return false;
227 }
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700228 if(!DecodeNesting_IsCurrentBounded(pNesting)) { // TODO: pCurrent vs pCurrentBounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700229 /* Not in bounded mode. */
230 return false;
231 }
232 if(pNesting->pCurrentBounded->u.ma.uCountCursor == UINT16_MAX) {
233 /* An indefinite length map or array */
234 return false;
235 }
236 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0) {
237 /* Count is not zero, still unconsumed items. */
238 return false;
239 }
240 /* All checks passed, got to the end of a definite length map or array */
241 return true;
242}
243
244inline static bool
245DecodeNesting_IsEndOfDefiniteLengthMapOrArray(QCBORDecodeNesting *pNesting)
246{
247 /* Must only be called on map / array; TODO: add checks? */
248 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
249 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700250 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700251 return false;
252 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700253}
254
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700255inline static bool
256DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700257{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700258 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
259 return true;
260 } else {
261 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700262 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700263 /* Seems to be unnecessary TODO: if(DecodeNesting_IsAtTop(pNesting)) {
264 return false;
265 } */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700266}
267
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700268inline static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700269DecodeNesting_CheckBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700270{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700271 if(pNesting->pCurrentBounded->uLevelType == uType) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700272 return true;
273 } else {
274 return false;
275 }
276}
277
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700278inline static void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700279DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700280{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700281 /* Only call on array / map; TODO: add check?*/
282 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700283}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700284
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700285
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700286inline static void
287DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
288{
289 pNesting->pCurrent--;
290}
291
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700292inline static void
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700293DecodeNesting_EnterBoundedMode(QCBORDecodeNesting *pNesting, size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700294{
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700295 /* Have descended into this before this is called. The job here is just to mark it in bounded mode */
296 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700297 DecodeNesting_SetBoundedMode(pNesting, uOffset);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700298}
299
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700300
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700301
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700302
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700303inline static QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700304DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade642282a2020-06-23 12:00:33 -0700305 uint8_t uQCBORType,
306 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700307{
308 QCBORError nReturn = QCBOR_SUCCESS;
309
310 if(uCount == 0) {
311 // Nothing to do for empty definite lenth arrays. They are just are
312 // effectively the same as an item that is not a map or array
313 goto Done;
314 // Empty indefinite length maps and arrays are handled elsewhere
315 }
316
317 // Error out if arrays is too long to handle
318 if(uCount != UINT16_MAX && uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
319 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
320 goto Done;
321 }
322
323 // Error out if nesting is too deep
324 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
325 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
326 goto Done;
327 }
328
329 // The actual descend
330 pNesting->pCurrent++;
331
332 // Fill in the new level fully
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700333 pNesting->pCurrent->uLevelType = uQCBORType;
334 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
335 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700336
337 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700338
339Done:
340 return nReturn;;
341}
342
343
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700344inline static QCBORError
345DecodeNesting_DescendWrappedBstr(QCBORDecodeNesting *pNesting,
346 size_t uEndOffset,
347 size_t uEndOfBstr)
348{
349 QCBORError nReturn = QCBOR_SUCCESS;
350
351 // Error out if nesting is too deep
352 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
353 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
354 goto Done;
355 }
356
357 // The actual descend
358 pNesting->pCurrent++;
359
360 // Fill in the new level fully
361 pNesting->pCurrent->uLevelType = QCBOR_TYPE_BYTE_STRING;
362 pNesting->pCurrent->u.bs.uPreviousEndOffset = (uint32_t)uEndOffset;
363 pNesting->pCurrent->u.bs.uEndOfBstr = (uint32_t)uEndOfBstr;
364
365 pNesting->pCurrentBounded = pNesting->pCurrent;
366
367Done:
368 return nReturn;;
369}
370
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700371
Laurence Lundbladeee851742020-01-08 08:37:05 -0800372inline static void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700373DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700374{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700375 pNesting->pMapsAndArrays[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700376 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
377}
378
379
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700380static void DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
381{
382 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700383 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700384
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700385 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700386 pNesting->pCurrent->u.ma.uCountCursor = pNesting->pCurrent->u.ma.uCountTotal;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700387 }
388}
389
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700390static inline void DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700391{
392 *pNesting = *pSave;
393}
394
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700395
396static inline uint32_t DecodeNesting_GetEndOfBstr(QCBORDecodeNesting *pMe)
397{
398 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
399}
400
401
402static inline uint32_t DecodeNesting_GetPreviousBoundedEnd(QCBORDecodeNesting *pMe)
403{
404 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
405}
406
407
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700408QCBORError DecodeNesting_EnterBstr(QCBORDecodeNesting *pNesting, uint32_t uEndOffset)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700409{
410 QCBORError uReturn ;
411
412 // Error out if nesting is too deep
413 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
414 uReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
415 goto Done;
416 }
417
418 // The actual descend
419 pNesting->pCurrent++;
420
421 // Record a few details for this nesting level
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700422 pNesting->pCurrent->uLevelType = QCBOR_TYPE_BYTE_STRING; // TODO the right value for a bstr
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700423
424 uReturn = QCBOR_SUCCESS;
425
426Done:
427 return uReturn;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700428}
429
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700430
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700431
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700432
Laurence Lundbladeee851742020-01-08 08:37:05 -0800433/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800434 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
435
436 The following four functions are pretty wrappers for invocation of
437 the string allocator supplied by the caller.
438
Laurence Lundbladeee851742020-01-08 08:37:05 -0800439 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800440
Laurence Lundbladeee851742020-01-08 08:37:05 -0800441static inline void
442StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800443{
444 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
445}
446
Laurence Lundbladeee851742020-01-08 08:37:05 -0800447// StringAllocator_Reallocate called with pMem NULL is
448// equal to StringAllocator_Allocate()
449static inline UsefulBuf
450StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
451 void *pMem,
452 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800453{
454 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
455}
456
Laurence Lundbladeee851742020-01-08 08:37:05 -0800457static inline UsefulBuf
458StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800459{
460 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
461}
462
Laurence Lundbladeee851742020-01-08 08:37:05 -0800463static inline void
464StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800465{
466 if(pMe->pfAllocator) {
467 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
468 }
469}
470
471
472
Laurence Lundbladeee851742020-01-08 08:37:05 -0800473/*===========================================================================
474 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700475
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800476 See qcbor/qcbor_decode.h for definition of the object
477 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800478 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700479/*
480 Public function, see header file
481 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800482void QCBORDecode_Init(QCBORDecodeContext *me,
483 UsefulBufC EncodedCBOR,
484 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700485{
486 memset(me, 0, sizeof(QCBORDecodeContext));
487 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800488 // Don't bother with error check on decode mode. If a bad value is
489 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700490 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700491 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700492 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700493 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700494 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700495}
496
497
498/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700499 Public function, see header file
500 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800501void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
502 QCBORStringAllocate pfAllocateFunction,
503 void *pAllocateContext,
504 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700505{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800506 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
507 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
508 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700509}
510
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800511
512/*
513 Public function, see header file
514 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800515void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me,
516 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700517{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700518 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700519}
520
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700521
522/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800523 This decodes the fundamental part of a CBOR data item, the type and
524 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800525
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700526 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800527
Laurence Lundbladeee851742020-01-08 08:37:05 -0800528 This does the network->host byte order conversion. The conversion
529 here also results in the conversion for floats in addition to that
530 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800531
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700532 This returns:
533 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800534
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800535 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800536 tags and floats and length for strings and arrays
537
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800538 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800539 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800540
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800541 The int type is preferred to uint8_t for some variables as this
542 avoids integer promotions, can reduce code size and makes
543 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700544 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800545inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
546 int *pnMajorType,
547 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800548 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700549{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700550 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800551
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700552 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800553 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800554
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700555 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800556 const int nTmpMajorType = nInitialByte >> 5;
557 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800558
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800559 // Where the number or argument accumulates
560 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800561
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800562 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700563 // Need to get 1,2,4 or 8 additional argument bytes. Map
564 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800565 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800566
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800567 // Loop getting all the bytes in the argument
568 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800569 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800570 // This shift and add gives the endian conversion
571 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
572 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800573 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800574 // The reserved and thus-far unused additional info values
575 nReturn = QCBOR_ERR_UNSUPPORTED;
576 goto Done;
577 } else {
578 // Less than 24, additional info is argument or 31, an indefinite length
579 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800580 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700581 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800582
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700583 if(UsefulInputBuf_GetError(pUInBuf)) {
584 nReturn = QCBOR_ERR_HIT_END;
585 goto Done;
586 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800587
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700588 // All successful if we got here.
589 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800590 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800591 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800592 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800593
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700594Done:
595 return nReturn;
596}
597
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800598
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700599/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800600 CBOR doesn't explicitly specify two's compliment for integers but all
601 CPUs use it these days and the test vectors in the RFC are so. All
602 integers in the CBOR structure are positive and the major type
603 indicates positive or negative. CBOR can express positive integers
604 up to 2^x - 1 where x is the number of bits and negative integers
605 down to 2^x. Note that negative numbers can be one more away from
606 zero than positive. Stdint, as far as I can tell, uses two's
607 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800608
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700609 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800610 used carefully here, and in particular why it isn't used in the interface.
611 Also see
612 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
613
614 Int is used for values that need less than 16-bits and would be subject
615 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700616 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800617inline static QCBORError
618DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700619{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700620 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800621
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700622 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
623 if (uNumber <= INT64_MAX) {
624 pDecodedItem->val.int64 = (int64_t)uNumber;
625 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800626
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700627 } else {
628 pDecodedItem->val.uint64 = uNumber;
629 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800630
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700631 }
632 } else {
633 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800634 // CBOR's representation of negative numbers lines up with the
635 // two-compliment representation. A negative integer has one
636 // more in range than a positive integer. INT64_MIN is
637 // equal to (-INT64_MAX) - 1.
638 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700639 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800640
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700641 } else {
642 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000643 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700644 nReturn = QCBOR_ERR_INT_OVERFLOW;
645 }
646 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800647
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700648 return nReturn;
649}
650
651// Make sure #define value line up as DecodeSimple counts on this.
652#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
653#error QCBOR_TYPE_FALSE macro value wrong
654#endif
655
656#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
657#error QCBOR_TYPE_TRUE macro value wrong
658#endif
659
660#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
661#error QCBOR_TYPE_NULL macro value wrong
662#endif
663
664#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
665#error QCBOR_TYPE_UNDEF macro value wrong
666#endif
667
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700668#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
669#error QCBOR_TYPE_BREAK macro value wrong
670#endif
671
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700672#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
673#error QCBOR_TYPE_DOUBLE macro value wrong
674#endif
675
676#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
677#error QCBOR_TYPE_FLOAT macro value wrong
678#endif
679
680/*
681 Decode true, false, floats, break...
682 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800683inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800684DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700685{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700686 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800687
Laurence Lundbladeee851742020-01-08 08:37:05 -0800688 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800689 // above make sure uAdditionalInfo values line up with uDataType values.
690 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
691 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800692
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800693 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800694 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
695 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800696
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700697 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700698 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
699 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700700 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700701 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700702 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
703 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700704 break;
705 case DOUBLE_PREC_FLOAT:
706 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700707 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700708 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800709
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700710 case CBOR_SIMPLEV_FALSE: // 20
711 case CBOR_SIMPLEV_TRUE: // 21
712 case CBOR_SIMPLEV_NULL: // 22
713 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700714 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700715 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800716
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700717 case CBOR_SIMPLEV_ONEBYTE: // 24
718 if(uNumber <= CBOR_SIMPLE_BREAK) {
719 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700720 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700721 goto Done;
722 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800723 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700724 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800725
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700726 default: // 0-19
727 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800728 /*
729 DecodeTypeAndNumber will make uNumber equal to
730 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
731 safe because the 2, 4 and 8 byte lengths of uNumber are in
732 the double/float cases above
733 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700734 pDecodedItem->val.uSimple = (uint8_t)uNumber;
735 break;
736 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800737
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700738Done:
739 return nReturn;
740}
741
742
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700743/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530744 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700745 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800746inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
747 int nMajorType,
748 uint64_t uStrLen,
749 UsefulInputBuf *pUInBuf,
750 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700751{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700752 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800753
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800754 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
755 // This check makes the casts to size_t below safe.
756
757 // 4 bytes less than the largest sizeof() so this can be tested by
758 // putting a SIZE_MAX length in the CBOR test input (no one will
759 // care the limit on strings is 4 bytes shorter).
760 if(uStrLen > SIZE_MAX-4) {
761 nReturn = QCBOR_ERR_STRING_TOO_LONG;
762 goto Done;
763 }
764
765 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530766 if(UsefulBuf_IsNULLC(Bytes)) {
767 // Failed to get the bytes for this string item
768 nReturn = QCBOR_ERR_HIT_END;
769 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700770 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530771
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800772 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530773 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800774 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530775 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700776 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530777 goto Done;
778 }
779 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800780 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530781 } else {
782 // Normal case with no string allocator
783 pDecodedItem->val.string = Bytes;
784 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800785 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800786 // Cast because ternary operator causes promotion to integer
787 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
788 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800789
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530790Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700791 return nReturn;
792}
793
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700794
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800795
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700796
797
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700798
799
Laurence Lundbladeee851742020-01-08 08:37:05 -0800800// Make sure the constants align as this is assumed by
801// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700802#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
803#error QCBOR_TYPE_ARRAY value not lined up with major type
804#endif
805#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
806#error QCBOR_TYPE_MAP value not lined up with major type
807#endif
808
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700809/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800810 This gets a single data item and decodes it including preceding
811 optional tagging. This does not deal with arrays and maps and nesting
812 except to decode the data item introducing them. Arrays and maps are
813 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800814
Laurence Lundbladeee851742020-01-08 08:37:05 -0800815 Errors detected here include: an array that is too long to decode,
816 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700817 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800818static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
819 QCBORItem *pDecodedItem,
820 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700821{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700822 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800823
Laurence Lundbladeee851742020-01-08 08:37:05 -0800824 /*
825 Get the major type and the number. Number could be length of more
826 bytes or the value depending on the major type nAdditionalInfo is
827 an encoding of the length of the uNumber and is needed to decode
828 floats and doubles
829 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800830 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700831 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800832 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800833
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700834 memset(pDecodedItem, 0, sizeof(QCBORItem));
835
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800836 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800837
Laurence Lundbladeee851742020-01-08 08:37:05 -0800838 // Error out here if we got into trouble on the type and number. The
839 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700840 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700841 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700842 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800843
Laurence Lundbladeee851742020-01-08 08:37:05 -0800844 // At this point the major type and the value are valid. We've got
845 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800846 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700847 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
848 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800849 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700850 nReturn = QCBOR_ERR_BAD_INT;
851 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800852 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700853 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700854 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800855
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700856 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
857 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800858 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
859 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
860 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
861 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530862 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700863 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800864 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700865 }
866 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800867
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700868 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
869 case CBOR_MAJOR_TYPE_MAP: // Major type 5
870 // Record the number of items in the array or map
871 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
872 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
873 goto Done;
874 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800875 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530876 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700877 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800878 // type conversion OK because of check above
879 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700880 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800881 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800882 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
883 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700884 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800885
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700886 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800887 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700888 nReturn = QCBOR_ERR_BAD_INT;
889 } else {
890 pDecodedItem->val.uTagV = uNumber;
891 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
892 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700893 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800894
Laurence Lundbladeee851742020-01-08 08:37:05 -0800895 case CBOR_MAJOR_TYPE_SIMPLE:
896 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800897 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700898 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800899
Laurence Lundbladeee851742020-01-08 08:37:05 -0800900 default:
901 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700902 nReturn = QCBOR_ERR_UNSUPPORTED;
903 break;
904 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800905
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700906Done:
907 return nReturn;
908}
909
910
911
912/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800913 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -0800914 individual chunk items together into one QCBORItem using the string
915 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800916
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530917 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700918 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800919static inline QCBORError
920GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700921{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700922 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700923
924 // Get pointer to string allocator. First use is to pass it to
925 // GetNext_Item() when option is set to allocate for *every* string.
926 // Second use here is to allocate space to coallese indefinite
927 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800928 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
929 &(me->StringAllocator) :
930 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800931
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700932 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800933 nReturn = GetNext_Item(&(me->InBuf),
934 pDecodedItem,
935 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700936 if(nReturn) {
937 goto Done;
938 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800939
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700940 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530941 // code in this function from here down can be eliminated. Run tests, except
942 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800943
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800944 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700945 const uint8_t uStringType = pDecodedItem->uDataType;
946 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700947 goto Done; // no need to do any work here on non-string types
948 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800949
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800950 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530951 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800952 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700953 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800954
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530955 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800956 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700957 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
958 goto Done;
959 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800960
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700961 // Loop getting chunk of indefinite string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700962 UsefulBufC FullString = NULLUsefulBufC;
963
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700964 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700965 // Get item for next chunk
966 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700967 // NULL string allocator passed here. Do not need to allocate
968 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -0800969 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700970 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700971 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700972 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800973
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530974 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700975 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800976 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700977 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530978 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700979 break;
980 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800981
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700982 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530983 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700984 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800985 if(StringChunkItem.uDataType != uStringType ||
986 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700987 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700988 break;
989 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800990
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530991 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800992 // The first time throurgh FullString.ptr is NULL and this is
993 // equivalent to StringAllocator_Allocate()
994 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
995 UNCONST_POINTER(FullString.ptr),
996 FullString.len + StringChunkItem.val.string.len);
997
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700998 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530999 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001000 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001001 break;
1002 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001003
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001004 // Copy new string chunk at the end of string so far.
1005 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001006 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001007
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001008 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1009 // Getting the item failed, clean up the allocated memory
1010 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001011 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001012
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001013Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001014 return nReturn;
1015}
1016
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001017
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001018uint64_t ConvertTag(QCBORDecodeContext *me, uint16_t uTagVal) {
1019 if(uTagVal < 0xfff0) {
1020 return uTagVal;
1021 } else {
1022 // TODO constant and error check
1023 int x = uTagVal - 0xfff0;
1024 return me->auMappedTags[x];
1025 }
1026}
1027
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001028/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001029 Gets all optional tag data items preceding a data item that is not an
1030 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001031 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001032static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001033GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001034{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001035 // Stack usage: int/ptr: 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +07001036 QCBORError nReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001037
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001038 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1039 CBOR_TAG_INVALID16,
1040 CBOR_TAG_INVALID16,
1041 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001042
Laurence Lundblade59289e52019-12-30 13:44:37 -08001043 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001044 for(;;) {
1045 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001046 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001047 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001048 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001049
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001050 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
1051 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001052 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001053 break;
1054 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001055
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001056 // Is there room for the tag in the tags list?
1057 size_t uTagIndex;
1058 for(uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001059 if(auTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001060 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001061 }
1062 }
1063 if(uTagIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001064 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001065 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001066
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001067 // Is the tag > 16 bits?
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001068 if(pDecodedItem->val.uTagV > CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001069 size_t uTagMapIndex;
1070 // Is there room in the tag map?
1071 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001072 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001073 break;
1074 }
1075 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
1076 break;
1077 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001078 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001079 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1080 // No room for the tag
1081 return 97; // TODO error code
1082 }
1083
1084 // Cover the case where tag is new and were it is already in the map
1085 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
1086 auTags[uTagIndex] = (uint16_t)(uTagMapIndex + 0xfff0); // TODO proper constant and cast
1087
1088 } else {
1089 auTags[uTagIndex] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001090 }
1091 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001092
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001093Done:
1094 return nReturn;
1095}
1096
1097
1098/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001099 This layer takes care of map entries. It combines the label and data
1100 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001101 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001102static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001103GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001104{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001105 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001106 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001107 if(nReturn)
1108 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001109
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001110 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001111 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001112 goto Done;
1113 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001114
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001115 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1116 // In a map and caller wants maps decoded, not treated as arrays
1117
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001118 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001119 // If in a map and the right decoding mode, get the label
1120
Laurence Lundbladeee851742020-01-08 08:37:05 -08001121 // Save label in pDecodedItem and get the next which will
1122 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001123 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001124 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001125 if(nReturn)
1126 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001127
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301128 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001129
1130 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1131 // strings are always good labels
1132 pDecodedItem->label.string = LabelItem.val.string;
1133 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1134 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001135 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001136 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1137 goto Done;
1138 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1139 pDecodedItem->label.int64 = LabelItem.val.int64;
1140 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1141 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1142 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1143 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1144 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1145 pDecodedItem->label.string = LabelItem.val.string;
1146 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1147 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1148 } else {
1149 // label is not an int or a string. It is an arrray
1150 // or a float or such and this implementation doesn't handle that.
1151 // Also, tags on labels are ignored.
1152 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1153 goto Done;
1154 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001155 }
1156 } else {
1157 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001158 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1159 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1160 goto Done;
1161 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001162 // Decoding a map as an array
1163 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001164 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1165 // Cast is needed because of integer promotion
1166 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001167 }
1168 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001169
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001170Done:
1171 return nReturn;
1172}
1173
1174
Laurence Lundblade642282a2020-06-23 12:00:33 -07001175static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001176NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1177{
1178 *pbNextIsBreak = false;
1179 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
1180 // TODO: use the Peek method?
1181 QCBORItem Peek;
1182 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1183 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1184 if(uReturn != QCBOR_SUCCESS) {
1185 return uReturn;
1186 }
1187 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
1188 // It is not a break, rewind so it can be processed normally.
1189 UsefulInputBuf_Seek(pUIB, uPeek);
1190 } else {
1191 *pbNextIsBreak = true;
1192 }
1193 }
1194
1195 return QCBOR_SUCCESS;
1196}
1197
1198
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001199/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001200 An item was just consumed, now figure out if it was the
1201 end of an array or map that can be closed out. That
1202 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001203*/
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001204static QCBORError Ascender(QCBORDecodeContext *pMe)
1205{
1206 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001207
Laurence Lundblade642282a2020-06-23 12:00:33 -07001208 /* This loops ascending nesting levels as long as there is ascending to do */
1209 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1210
1211 if(DecodeNesting_IsDefiniteLength(&(pMe->nesting))) {
1212 /* Definite Length Maps and Arrays */
1213 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1214 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
1215 /* Didn't close out map or array; all work here is done */
1216 break;
1217 }
1218 /* fall through to an actual ascend at the end of loop */
1219
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001220 } else {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001221 /* If not definite length, have to check for a CBOR break. */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001222 bool bIsBreak = false;
1223 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1224 if(uReturn != QCBOR_SUCCESS) {
1225 goto Done;
1226 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001227
1228 if(!bIsBreak) {
1229 /* It's not a break; nothing closes out; all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001230 break;
1231 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001232
1233 if(DecodeNesting_IsBstrWrapped(&(pMe->nesting))) {
1234 /* Break occurred inside a wrapped bstr or
1235 at the top level sequence. This is always an
1236 error because it is not in an indefinte length. */
1237 uReturn = QCBOR_ERR_BAD_BREAK;
1238 goto Done;
1239 }
1240 /* fall through to an actual ascend at the end of loop */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001241 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001242
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001243 /* All items in the level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001244
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001245 /* But ascent in bounded mode is only by explicit call to QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001246 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001247 /* Set the count to zero for definite length arrays to indicate cursor is at end of bounded map / array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001248 pMe->nesting.pCurrent->u.ma.uCountCursor = 0;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001249 break;
1250 }
1251
1252 /* Finally, actually ascend one level. */
1253 DecodeNesting_Ascend(&(pMe->nesting));
1254 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001255
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001256 uReturn = QCBOR_SUCCESS;
1257
1258Done:
1259 return uReturn;
1260}
1261
1262
1263/*
Laurence Lundblade642282a2020-06-23 12:00:33 -07001264 This the travesal going descending into and asecnding out of maps,
1265 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1266 indefinte length maps and arrays by looking at the item count or
1267 finding CBOR breaks. It detects the ends of the top-level sequence
1268 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001269 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001270static QCBORError
1271QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001272{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001273 QCBORError uReturn;
Laurence Lundblade642282a2020-06-23 12:00:33 -07001274 /* ==== First figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001275
Laurence Lundblade642282a2020-06-23 12:00:33 -07001276 /*
1277 If out of bytes to consume, it is either the end of the top-level
1278 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001279
Laurence Lundblade642282a2020-06-23 12:00:33 -07001280 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1281 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1282 CBOR is exited, the length is set back to the top-level's length
1283 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001284
Laurence Lundblade642282a2020-06-23 12:00:33 -07001285 Only return the success error code QCBOR_ERR_NO_MORE_ITEMS here
1286 when at the top level to allow other code below to process various
1287 errors when out of bytes to decode and not at the top level. Note
1288 that QCBORDecode_Finish() still needs to be called to be sure all
1289 nesting levels were closed out.
1290 */
1291 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0 &&
1292 DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001293 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001294 goto Done;
1295 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001296
Laurence Lundblade642282a2020-06-23 12:00:33 -07001297 /*
1298 Check to see if at the end of a bounded definite length map or
1299 array. The check for the end of an indefnite length array is
1300 later. (TODO: test that).
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001301 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001302 if(DecodeNesting_IsAtEndOfBoundedDefiniteLenMapOrArray(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001303 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001304 goto Done;
1305 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001306
Laurence Lundblade642282a2020-06-23 12:00:33 -07001307 /* ==== Next, not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001308 uReturn = GetNext_MapEntry(me, pDecodedItem);
1309 if(uReturn) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001310 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001311 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301312
Laurence Lundblade642282a2020-06-23 12:00:33 -07001313 /*
1314 Breaks ending arrays/maps are always processed at the end of this
1315 function. They should never show up here.
1316 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301317 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001318 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301319 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301320 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001321
Laurence Lundblade642282a2020-06-23 12:00:33 -07001322 /*
1323 Record the nesting level for this data item before processing any
1324 of decrementing and descending.
1325 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001326 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001327
Laurence Lundblade642282a2020-06-23 12:00:33 -07001328
1329 /* ==== Next, Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001330 if(IsMapOrArray(pDecodedItem->uDataType) && pDecodedItem->val.uCount != 0) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001331 /*
1332 If the new item is a map or array descend. Empty definite
1333 length maps and arrays are not handled here as they can be
1334 treated as a non-aggreate type. Empty indefinite length maps
1335 and arrays are handled here.
1336
1337 Maps and arrays do count in as items in the map/array that
1338 encloses them so a decrement needs to be done for them too, but
1339 that is done only when all the items in them have been
1340 processed, not when they are opened with the exception of an
1341 empty map or array.
1342 */
1343 uReturn = DecodeNesting_DescendMapOrArray(&(me->nesting),
1344 pDecodedItem->uDataType,
1345 pDecodedItem->val.uCount);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001346 if(uReturn != QCBOR_SUCCESS) {
1347 goto Done;
1348 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001349 }
1350
Laurence Lundblade642282a2020-06-23 12:00:33 -07001351 // TODO: not sure the if-then-else logic is right here
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001352 if(!IsMapOrArray(pDecodedItem->uDataType) ||
Laurence Lundblade642282a2020-06-23 12:00:33 -07001353 pDecodedItem->val.uCount == 0 ||
1354 pDecodedItem->val.uCount == UINT16_MAX) {
1355 /*
1356 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001357 - A non-aggregate like an integer or string
1358 - An empty definite length map or array
1359 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001360
1361 The Ascender does the work of decrementing the count for an
1362 definite length array and break detection for an indefinite
1363 length array. If the end of the map or array was reached, then
1364 it ascends nesting levels, possibly all the way to the top.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001365 */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001366 uReturn = Ascender(me);
1367 if(uReturn) {
1368 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001369 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301370 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001371
Laurence Lundblade642282a2020-06-23 12:00:33 -07001372 /* ==== Last, Tell the caller the nest level of the next item ==== */
1373 /*
1374 Tell the caller what level is next. This tells them what
1375 maps/arrays were closed out and makes it possible for them to
1376 reconstruct the tree with just the information returned by
1377 GetNext
1378 */
1379 if(DecodeNesting_IsAtEndOfBoundedDefiniteLenMapOrArray(&(me->nesting))) {
1380 /* At end of a bounded map / array; next nest is 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001381 pDecodedItem->uNextNestLevel = 0;
1382 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001383 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001384 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001385
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001386Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001387 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001388 /* This sets uDataType and uLabelType to QCBOR_TYPE_NONE */
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001389 memset(pDecodedItem, 0, sizeof(QCBORItem));
1390 }
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001391 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001392}
1393
1394
Laurence Lundblade59289e52019-12-30 13:44:37 -08001395/*
1396 Mostly just assign the right data type for the date string.
1397 */
1398inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1399{
1400 // Stack Use: UsefulBuf 1 16
1401 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1402 return QCBOR_ERR_BAD_OPT_TAG;
1403 }
1404
1405 const UsefulBufC Temp = pDecodedItem->val.string;
1406 pDecodedItem->val.dateString = Temp;
1407 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1408 return QCBOR_SUCCESS;
1409}
1410
1411
1412/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001413 The epoch formatted date. Turns lots of different forms of encoding
1414 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001415 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001416static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001417{
1418 // Stack usage: 1
1419 QCBORError nReturn = QCBOR_SUCCESS;
1420
1421 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1422
1423 switch (pDecodedItem->uDataType) {
1424
1425 case QCBOR_TYPE_INT64:
1426 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1427 break;
1428
1429 case QCBOR_TYPE_UINT64:
1430 if(pDecodedItem->val.uint64 > INT64_MAX) {
1431 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1432 goto Done;
1433 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001434 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001435 break;
1436
1437 case QCBOR_TYPE_DOUBLE:
1438 {
1439 // This comparison needs to be done as a float before
1440 // conversion to an int64_t to be able to detect doubles
1441 // that are too large to fit into an int64_t. A double
1442 // has 52 bits of preceision. An int64_t has 63. Casting
1443 // INT64_MAX to a double actually causes a round up which
1444 // is bad and wrong for the comparison because it will
1445 // allow conversion of doubles that can't fit into a
1446 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1447 // the cutoff point as if that rounds up in conversion to
1448 // double it will still be less than INT64_MAX. 0x7ff is
1449 // picked because it has 11 bits set.
1450 //
1451 // INT64_MAX seconds is on the order of 10 billion years,
1452 // and the earth is less than 5 billion years old, so for
1453 // most uses this conversion error won't occur even though
1454 // doubles can go much larger.
1455 //
1456 // Without the 0x7ff there is a ~30 minute range of time
1457 // values 10 billion years in the past and in the future
1458 // where this this code would go wrong.
1459 const double d = pDecodedItem->val.dfnum;
1460 if(d > (double)(INT64_MAX - 0x7ff)) {
1461 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1462 goto Done;
1463 }
1464 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1465 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1466 }
1467 break;
1468
1469 default:
1470 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1471 goto Done;
1472 }
1473 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1474
1475Done:
1476 return nReturn;
1477}
1478
1479
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001480/*
1481 Mostly just assign the right data type for the bignum.
1482 */
1483inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1484{
1485 // Stack Use: UsefulBuf 1 -- 16
1486 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1487 return QCBOR_ERR_BAD_OPT_TAG;
1488 }
1489 const UsefulBufC Temp = pDecodedItem->val.string;
1490 pDecodedItem->val.bigNum = Temp;
1491 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1492 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1493 : QCBOR_TYPE_NEGBIGNUM);
1494 return QCBOR_SUCCESS;
1495}
1496
1497
Laurence Lundblade59289e52019-12-30 13:44:37 -08001498#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1499/*
1500 Decode decimal fractions and big floats.
1501
1502 When called pDecodedItem must be the array that is tagged as a big
1503 float or decimal fraction, the array that has the two members, the
1504 exponent and mantissa.
1505
1506 This will fetch and decode the exponent and mantissa and put the
1507 result back into pDecodedItem.
1508 */
1509inline static QCBORError
1510QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1511{
1512 QCBORError nReturn;
1513
1514 // --- Make sure it is an array; track nesting level of members ---
1515 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1516 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1517 goto Done;
1518 }
1519
1520 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001521 // definite length arrays, but not for indefnite. Instead remember
1522 // the nesting level the two integers must be at, which is one
1523 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001524 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1525
1526 // --- Is it a decimal fraction or a bigfloat? ---
1527 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1528 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1529
1530 // --- Get the exponent ---
1531 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001532 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001533 if(nReturn != QCBOR_SUCCESS) {
1534 goto Done;
1535 }
1536 if(exponentItem.uNestingLevel != nNestLevel) {
1537 // Array is empty or a map/array encountered when expecting an int
1538 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1539 goto Done;
1540 }
1541 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1542 // Data arriving as an unsigned int < INT64_MAX has been converted
1543 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1544 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1545 // will be too large for this to handle and thus an error that will
1546 // get handled in the next else.
1547 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1548 } else {
1549 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1550 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1551 goto Done;
1552 }
1553
1554 // --- Get the mantissa ---
1555 QCBORItem mantissaItem;
1556 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1557 if(nReturn != QCBOR_SUCCESS) {
1558 goto Done;
1559 }
1560 if(mantissaItem.uNestingLevel != nNestLevel) {
1561 // Mantissa missing or map/array encountered when expecting number
1562 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1563 goto Done;
1564 }
1565 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1566 // Data arriving as an unsigned int < INT64_MAX has been converted
1567 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1568 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1569 // will be too large for this to handle and thus an error that
1570 // will get handled in an else below.
1571 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1572 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1573 // Got a good big num mantissa
1574 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1575 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001576 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1577 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1578 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001579 } else {
1580 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1581 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1582 goto Done;
1583 }
1584
1585 // --- Check that array only has the two numbers ---
1586 if(mantissaItem.uNextNestLevel == nNestLevel) {
1587 // Extra items in the decimal fraction / big num
1588 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1589 goto Done;
1590 }
1591
1592Done:
1593
1594 return nReturn;
1595}
1596#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1597
1598
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001599
1600/*
1601 */
1602inline static QCBORError DecodeURI(QCBORItem *pDecodedItem)
1603{
1604 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1605 return QCBOR_ERR_BAD_OPT_TAG;
1606 }
1607 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1608 return QCBOR_SUCCESS;
1609}
1610
1611
1612inline static QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
1613{
1614 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1615 return QCBOR_ERR_BAD_OPT_TAG;
1616 }
1617 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
1618 return QCBOR_SUCCESS;
1619}
1620
1621
1622inline static QCBORError DecodeB64(QCBORItem *pDecodedItem)
1623{
1624 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1625 return QCBOR_ERR_BAD_OPT_TAG;
1626 }
1627 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
1628 return QCBOR_SUCCESS;
1629}
1630
1631
1632inline static QCBORError DecodeRegex(QCBORItem *pDecodedItem)
1633{
1634 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1635 return QCBOR_ERR_BAD_OPT_TAG;
1636 }
1637 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
1638 return QCBOR_SUCCESS;
1639}
1640
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001641inline static QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
1642{
1643 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1644 return QCBOR_ERR_BAD_OPT_TAG;
1645 }
1646 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
1647 return QCBOR_SUCCESS;
1648}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001649
1650inline static QCBORError DecodeMIME(QCBORItem *pDecodedItem)
1651{
1652 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1653 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
1654 } else if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1655 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1656 } else {
1657 return QCBOR_ERR_BAD_OPT_TAG;
1658 }
1659 return QCBOR_SUCCESS;
1660}
1661
1662
1663/*
1664 */
1665inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1666{
1667 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1668 return QCBOR_ERR_BAD_OPT_TAG;
1669 }
1670 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
1671 return QCBOR_SUCCESS;
1672}
1673
1674
Laurence Lundblade59289e52019-12-30 13:44:37 -08001675/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001676 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001677 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001678QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001679QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001680{
1681 QCBORError nReturn;
1682
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001683 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001684 if(nReturn != QCBOR_SUCCESS) {
1685 goto Done;
1686 }
1687
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001688 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
1689 switch(pDecodedItem->uTags[i] ) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001690
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001691 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001692 nReturn = DecodeDateString(pDecodedItem);
1693 break;
1694
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001695 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001696 nReturn = DecodeDateEpoch(pDecodedItem);
1697 break;
1698
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001699 case CBOR_TAG_POS_BIGNUM:
1700 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001701 nReturn = DecodeBigNum(pDecodedItem);
1702 break;
1703
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001704 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1705 case CBOR_TAG_DECIMAL_FRACTION:
1706 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001707 // For aggregate tagged types, what goes into pTags is only collected
1708 // from the surrounding data item, not the contents, so pTags is not
1709 // passed on here.
1710
1711 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1712 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001713 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001714
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001715 case CBOR_TAG_CBOR:
1716 nReturn = DecodeWrappedCBOR(pDecodedItem);
1717 break;
1718
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001719 case CBOR_TAG_URI:
1720 nReturn = DecodeURI(pDecodedItem);
1721 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001722
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001723 case CBOR_TAG_B64URL:
1724 nReturn = DecodeB64URL(pDecodedItem);
1725 break;
1726
1727 case CBOR_TAG_B64:
1728 nReturn = DecodeB64(pDecodedItem);
1729 break;
1730
1731 case CBOR_TAG_MIME:
1732 case CBOR_TAG_BINARY_MIME:
1733 nReturn = DecodeMIME(pDecodedItem);
1734 break;
1735
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001736 case CBOR_TAG_REGEX:
1737 nReturn = DecodeRegex(pDecodedItem);
1738 break;
1739
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001740 case CBOR_TAG_BIN_UUID:
1741 nReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001742 break;
1743
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001744 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001745 // The end of the tag list or no tags
1746 // Successful exit from the loop.
1747 goto Done;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001748
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001749 default:
1750 // A tag that is not understood
1751 // A successful exit from the loop
1752 goto Done;
1753
1754 }
1755 if(nReturn != QCBOR_SUCCESS) {
1756 goto Done;
1757 }
Laurence Lundblade59289e52019-12-30 13:44:37 -08001758 }
1759
1760Done:
1761 if(nReturn != QCBOR_SUCCESS) {
1762 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1763 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1764 }
1765 return nReturn;
1766}
1767
1768
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001769QCBORError QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
1770{
1771 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
1772
1773 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
1774
1775 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
1776
1777 return uErr;
1778}
1779
1780
Laurence Lundblade59289e52019-12-30 13:44:37 -08001781/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001782 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001783 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001784QCBORError
1785QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1786 QCBORItem *pDecodedItem,
1787 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001788{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001789 QCBORError nReturn;
1790
1791 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
1792 if(nReturn != QCBOR_SUCCESS) {
1793 return nReturn;
1794 }
1795
1796 if(pTags != NULL) {
1797 pTags->uNumUsed = 0;
1798 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001799 if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001800 break;
1801 }
1802 if(pTags->uNumUsed >= pTags->uNumAllocated) {
1803 return QCBOR_ERR_TOO_MANY_TAGS;
1804 }
1805 pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]);
1806 pTags->uNumUsed++;
1807 }
1808 }
1809
1810 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001811}
1812
1813
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001814/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301815 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301816 next one down. If a layer has no work to do for a particular item
1817 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001818
Laurence Lundblade59289e52019-12-30 13:44:37 -08001819 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1820 tagged data items, turning them into the local C representation.
1821 For the most simple it is just associating a QCBOR_TYPE with the data. For
1822 the complex ones that an aggregate of data items, there is some further
1823 decoding and a little bit of recursion.
1824
1825 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301826 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301827 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001828 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001829
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301830 - GetNext_MapEntry -- This handles the combining of two
1831 items, the label and the data, that make up a map entry.
1832 It only does work on maps. It combines the label and data
1833 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001834
Laurence Lundblade59289e52019-12-30 13:44:37 -08001835 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1836 tags into bit flags associated with the data item. No actual decoding
1837 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001838
Laurence Lundblade59289e52019-12-30 13:44:37 -08001839 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301840 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301841 string allocater to create contiguous space for the item. It
1842 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001843
Laurence Lundblade59289e52019-12-30 13:44:37 -08001844 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1845 atomic data item has a "major type", an integer "argument" and optionally
1846 some content. For text and byte strings, the content is the bytes
1847 that make up the string. These are the smallest data items that are
1848 considered to be well-formed. The content may also be other data items in
1849 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001850
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001851 Roughly this takes 300 bytes of stack for vars. Need to
1852 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001853
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301854 */
1855
1856
1857/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001858 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001859 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001860int QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001861 const QCBORItem *pItem,
1862 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001863{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001864 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++ ) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001865 if(pItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001866 break;
1867 }
1868 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
1869 return 1;
1870 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001871 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001872
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001873 return 0;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001874}
1875
1876
1877/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001878 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001879 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001880QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001881{
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001882 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001883
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001884 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001885 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001886 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1887 goto Done;
1888 }
1889
1890 // Error out if not all the bytes are consumed
1891 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1892 nReturn = QCBOR_ERR_EXTRA_BYTES;
1893 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001894
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001895Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301896 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001897 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001898 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001899
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001900 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001901}
1902
1903
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001904/*
1905Public function, see header qcbor/qcbor_decode.h file
1906*/
Laurence Lundblade2b843b52020-06-16 20:51:03 -07001907uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
1908 const QCBORItem *pItem,
1909 unsigned int uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001910{
1911 if(uIndex > QCBOR_MAX_TAGS_PER_ITEM) {
1912 return CBOR_TAG_INVALID16;
1913 } else if(pItem->uTags[uIndex] <= QCBOR_LAST_UNMAPPED_TAG) {
1914 return pItem->uTags[uIndex];
1915 } else if(pItem->uTags[uIndex] < QCBOR_NUM_MAPPED_TAGS + QCBOR_LAST_UNMAPPED_TAG) {
1916 return pMe->auMappedTags[pItem->uTags[uIndex] - QCBOR_LAST_UNMAPPED_TAG];
1917 } else {
1918 return CBOR_TAG_INVALID16;
1919 }
1920}
1921
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001922
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001923/*
1924
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001925Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001926
Laurence Lundbladeee851742020-01-08 08:37:05 -08001927 - Hit end of input before it was expected while decoding type and
1928 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001929
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001930 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001931
Laurence Lundbladeee851742020-01-08 08:37:05 -08001932 - Hit end of input while decoding a text or byte string
1933 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001934
Laurence Lundbladeee851742020-01-08 08:37:05 -08001935 - Encountered conflicting tags -- e.g., an item is tagged both a date
1936 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001937
Laurence Lundbladeee851742020-01-08 08:37:05 -08001938 - Encontered an array or mapp that has too many items
1939 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001940
Laurence Lundbladeee851742020-01-08 08:37:05 -08001941 - Encountered array/map nesting that is too deep
1942 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001943
Laurence Lundbladeee851742020-01-08 08:37:05 -08001944 - An epoch date > INT64_MAX or < INT64_MIN was encountered
1945 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001946
Laurence Lundbladeee851742020-01-08 08:37:05 -08001947 - The type of a map label is not a string or int
1948 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001949
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001950 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001951
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001952 */
1953
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001954
1955
Laurence Lundbladef6531662018-12-04 10:42:22 +09001956
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001957/* ===========================================================================
1958 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001959
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001960 This implements a simple sting allocator for indefinite length
1961 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
1962 implements the function type QCBORStringAllocate and allows easy
1963 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09001964
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001965 This particular allocator is built-in for convenience. The caller
1966 can implement their own. All of this following code will get
1967 dead-stripped if QCBORDecode_SetMemPool() is not called.
1968
1969 This is a very primitive memory allocator. It does not track
1970 individual allocations, only a high-water mark. A free or
1971 reallocation must be of the last chunk allocated.
1972
1973 The size of the pool and offset to free memory are packed into the
1974 first 8 bytes of the memory pool so we don't have to keep them in
1975 the decode context. Since the address of the pool may not be
1976 aligned, they have to be packed and unpacked as if they were
1977 serialized data of the wire or such.
1978
1979 The sizes packed in are uint32_t to be the same on all CPU types
1980 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08001981 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001982
1983
Laurence Lundbladeee851742020-01-08 08:37:05 -08001984static inline int
1985MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001986{
1987 // Use of UsefulInputBuf is overkill, but it is convenient.
1988 UsefulInputBuf UIB;
1989
Laurence Lundbladeee851742020-01-08 08:37:05 -08001990 // Just assume the size here. It was checked during SetUp so
1991 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001992 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
1993 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
1994 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
1995 return UsefulInputBuf_GetError(&UIB);
1996}
1997
1998
Laurence Lundbladeee851742020-01-08 08:37:05 -08001999static inline int
2000MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002001{
2002 // Use of UsefulOutBuf is overkill, but convenient. The
2003 // length check performed here is useful.
2004 UsefulOutBuf UOB;
2005
2006 UsefulOutBuf_Init(&UOB, Pool);
2007 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2008 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2009 return UsefulOutBuf_GetError(&UOB);
2010}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002011
2012
2013/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002014 Internal function for an allocation, reallocation free and destuct.
2015
2016 Having only one function rather than one each per mode saves space in
2017 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002018
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002019 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2020 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002021static UsefulBuf
2022MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002023{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002024 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002025
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002026 uint32_t uPoolSize;
2027 uint32_t uFreeOffset;
2028
2029 if(uNewSize > UINT32_MAX) {
2030 // This allocator is only good up to 4GB. This check should
2031 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2032 goto Done;
2033 }
2034 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2035
2036 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2037 goto Done;
2038 }
2039
2040 if(uNewSize) {
2041 if(pMem) {
2042 // REALLOCATION MODE
2043 // Calculate pointer to the end of the memory pool. It is
2044 // assumed that pPool + uPoolSize won't wrap around by
2045 // assuming the caller won't pass a pool buffer in that is
2046 // not in legitimate memory space.
2047 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2048
2049 // Check that the pointer for reallocation is in the range of the
2050 // pool. This also makes sure that pointer math further down
2051 // doesn't wrap under or over.
2052 if(pMem >= pPool && pMem < pPoolEnd) {
2053 // Offset to start of chunk for reallocation. This won't
2054 // wrap under because of check that pMem >= pPool. Cast
2055 // is safe because the pool is always less than UINT32_MAX
2056 // because of check in QCBORDecode_SetMemPool().
2057 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2058
2059 // Check to see if the allocation will fit. uPoolSize -
2060 // uMemOffset will not wrap under because of check that
2061 // pMem is in the range of the uPoolSize by check above.
2062 if(uNewSize <= uPoolSize - uMemOffset) {
2063 ReturnValue.ptr = pMem;
2064 ReturnValue.len = uNewSize;
2065
2066 // Addition won't wrap around over because uNewSize was
2067 // checked to be sure it is less than the pool size.
2068 uFreeOffset = uMemOffset + uNewSize32;
2069 }
2070 }
2071 } else {
2072 // ALLOCATION MODE
2073 // uPoolSize - uFreeOffset will not underflow because this
2074 // pool implementation makes sure uFreeOffset is always
2075 // smaller than uPoolSize through this check here and
2076 // reallocation case.
2077 if(uNewSize <= uPoolSize - uFreeOffset) {
2078 ReturnValue.len = uNewSize;
2079 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002080 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002081 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002082 }
2083 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002084 if(pMem) {
2085 // FREE MODE
2086 // Cast is safe because of limit on pool size in
2087 // QCBORDecode_SetMemPool()
2088 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2089 } else {
2090 // DESTRUCT MODE
2091 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002092 }
2093 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002094
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002095 UsefulBuf Pool = {pPool, uPoolSize};
2096 MemPool_Pack(Pool, uFreeOffset);
2097
2098Done:
2099 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002100}
2101
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002102
Laurence Lundbladef6531662018-12-04 10:42:22 +09002103/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002104 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002105 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002106QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2107 UsefulBuf Pool,
2108 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002109{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002110 // The pool size and free mem offset are packed into the beginning
2111 // of the pool memory. This compile time check make sure the
2112 // constant in the header is correct. This check should optimize
2113 // down to nothing.
2114 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07002115 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002116 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002117
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002118 // The pool size and free offset packed in to the beginning of pool
2119 // memory are only 32-bits. This check will optimize out on 32-bit
2120 // machines.
2121 if(Pool.len > UINT32_MAX) {
2122 return QCBOR_ERR_BUFFER_TOO_LARGE;
2123 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002124
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002125 // This checks that the pool buffer given is big enough.
2126 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
2127 return QCBOR_ERR_BUFFER_TOO_SMALL;
2128 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002129
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002130 pMe->StringAllocator.pfAllocator = MemPool_Function;
2131 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2132 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002133
Laurence Lundblade30816f22018-11-10 13:40:22 +07002134 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002135}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002136
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002137
2138
Laurence Lundblade1341c592020-04-11 14:19:05 -07002139#include <stdio.h>
2140void printdecode(QCBORDecodeContext *pMe, const char *szName)
2141{
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002142 printf("---%s--%d--%d--\narrow is current bounded level\nLevel Count Type S-Offset SaveCount Bounded E-Offset\n",
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002143 szName,
2144 (uint32_t)pMe->InBuf.cursor,
2145 (uint32_t)pMe->InBuf.UB.len);
Laurence Lundblade64b607e2020-05-13 13:05:57 -07002146 for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002147 if(&(pMe->nesting.pMapsAndArrays[i]) > pMe->nesting.pCurrent) {
2148 break;
2149 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002150
2151 // TODO: print different for BS and MA
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002152 printf("%2s %2d %5d %s %6u %5d %d %5d\n",
2153 pMe->nesting.pCurrentBounded == &(pMe->nesting.pMapsAndArrays[i]) ? "->": " ",
Laurence Lundblade1341c592020-04-11 14:19:05 -07002154 i,
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002155 pMe->nesting.pMapsAndArrays[i].u.ma.uCountCursor,
2156 pMe->nesting.pMapsAndArrays[i].uLevelType == QCBOR_TYPE_MAP ? "map " :
2157 (pMe->nesting.pMapsAndArrays[i].uLevelType == QCBOR_TYPE_ARRAY ? "array" :
2158 (pMe->nesting.pMapsAndArrays[i].uLevelType == QCBOR_TYPE_BYTE_STRING ? "bstr " :
2159 (pMe->nesting.pMapsAndArrays[i].uLevelType == QCBOR_TYPE_NONE ? "none " : "?????"))),
2160 pMe->nesting.pMapsAndArrays[i].u.ma.uStartOffset,
2161 pMe->nesting.pMapsAndArrays[i].u.ma.uCountTotal,
2162 0, // TODO: fix this
2163 pMe->nesting.pMapsAndArrays[i].u.bs.uPreviousEndOffset
Laurence Lundblade1341c592020-04-11 14:19:05 -07002164 );
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002165
Laurence Lundblade1341c592020-04-11 14:19:05 -07002166 }
Laurence Lundblade64b607e2020-05-13 13:05:57 -07002167 printf("\n");
Laurence Lundblade1341c592020-04-11 14:19:05 -07002168}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002169
2170
2171/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002172 Consume an entire map or array (and do next to
2173 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002174 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002175static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002176ConsumeItem(QCBORDecodeContext *pMe,
2177 const QCBORItem *pItemToConsume,
2178 uint_fast8_t *puNextNestLevel)
2179{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002180 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002181 QCBORItem Item;
2182
2183 printdecode(pMe, "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002184
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002185 if(IsMapOrArray(pItemToConsume->uDataType)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002186 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002187
Laurence Lundblade1341c592020-04-11 14:19:05 -07002188 /* This works for definite and indefinite length
2189 * maps and arrays by using the nesting level
2190 */
2191 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002192 uReturn = QCBORDecode_GetNext(pMe, &Item);
2193 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002194 goto Done;
2195 }
2196 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002197
Laurence Lundblade1341c592020-04-11 14:19:05 -07002198 if(puNextNestLevel != NULL) {
2199 *puNextNestLevel = Item.uNextNestLevel;
2200 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002201 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002202
Laurence Lundblade1341c592020-04-11 14:19:05 -07002203 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002204 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002205 if(puNextNestLevel != NULL) {
2206 /* Just pass the nesting level through */
2207 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2208 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002209 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002210 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002211
2212Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002213 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002214}
2215
2216
Laurence Lundblade1341c592020-04-11 14:19:05 -07002217/* Return true if the labels in Item1 and Item2 are the same.
2218 Works only for integer and string labels. Returns false
2219 for any other type. */
2220static inline bool
2221MatchLabel(QCBORItem Item1, QCBORItem Item2)
2222{
2223 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2224 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2225 return true;
2226 }
2227 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002228 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002229 return true;
2230 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002231 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002232 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2233 return true;
2234 }
2235 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2236 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2237 return true;
2238 }
2239 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002240
Laurence Lundblade1341c592020-04-11 14:19:05 -07002241 /* Other label types are never matched */
2242 return false;
2243}
2244
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002245
2246/*
2247 Returns true if Item1 and Item2 are the same type
2248 or if either are of QCBOR_TYPE_ANY.
2249 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002250static inline bool
2251MatchType(QCBORItem Item1, QCBORItem Item2)
2252{
2253 if(Item1.uDataType == Item2.uDataType) {
2254 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002255 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002256 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002257 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002258 return true;
2259 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002260 return false;
2261}
2262
2263
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002264/**
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002265 \brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002266
2267 @param[in] pMe The decode context to search.
2268 @param[in,out] pItemArray The items to search for and the items found.
2269 @param[in] pCBContext Context for the not-found item call back
2270 @param[in] pfCallback Function to call on items not matched in pItemArray
2271
2272 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2273
2274 @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.
2275
2276 @retval QCBOR_ERR_UNEXPECTED_TYPE The label was matched, but not the type.
2277
2278 @retval Also errors returned by QCBORDecode_GetNext().
2279
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002280 On input pItemArray contains a list of labels and data types
2281 of items to be found.
2282
2283 On output the fully retrieved items are filled in with
2284 values and such. The label was matched, so it never changes.
2285
2286 If an item was not found, its data type is set to none.
2287
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002288 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002289static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002290MapSearch(QCBORDecodeContext *pMe,
2291 QCBORItem *pItemArray,
2292 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002293 void *pCBContext,
2294 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002295{
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002296 QCBORError uReturn;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002297
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002298 QCBORDecodeNesting SaveNesting;
2299 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002300
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002301 /* Reposition to search from the start of the map / array */
2302 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrentBounded->u.ma.uStartOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002303
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002304 /*
2305 Loop over all the items in the map. They could be
2306 deeply nested and this should handle both definite
2307 and indefinite length maps and arrays, so this
2308 adds some complexity.
2309 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002310 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002311
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002312 uint_fast8_t uNextNestLevel;
2313
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002314 uint64_t uFoundItemBitMap = 0;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002315
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002316 /* Iterate over items in the map / array */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002317 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002318 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002319 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002320
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002321 /* Get the item */
2322 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002323 uReturn = QCBORDecode_GetNext(pMe, &Item);
2324 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002325 /* Got non-well-formed CBOR */
2326 goto Done;
2327 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002328
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002329 /* See if item has one of the labels that are of interest */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002330 int nIndex;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002331 QCBORItem *pIterator;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002332 for(pIterator = pItemArray, nIndex = 0; pIterator->uLabelType != 0; pIterator++, nIndex++) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002333 if(MatchLabel(Item, *pIterator)) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002334 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002335 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2336 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002337 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002338 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002339 /* Also try to match its type */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002340 if(!MatchType(Item, *pIterator)) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002341 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002342 goto Done;
2343 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002344
2345 /* Successful match. Return the item. */
2346 *pIterator = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002347 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002348 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002349 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002350 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002351 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002352 /*
2353 Call the callback on unmatched labels.
2354 (It is tempting to do duplicate detection here, but that would
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002355 require dynamic memory allocation because the number of labels
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002356 that might be encountered is unbounded.)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002357 */
2358 if(pfCallback) {
2359 uReturn = (*pfCallback)(pCBContext, &Item);
2360 if(uReturn != QCBOR_SUCCESS) {
2361 goto Done;
2362 }
2363 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002364 }
2365 }
2366
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002367 /*
2368 Consume the item whether matched or not. This
2369 does the work of traversing maps and array and
2370 everything in them. In this loop only the
2371 items at the current nesting level are examined
2372 to match the labels.
2373 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002374 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
2375 if(uReturn) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002376 goto Done;
2377 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002378
2379 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002380
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002381 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002382
2383 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002384 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2385 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002386
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002387 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002388 int i;
2389 QCBORItem *pIterator;
2390 for(pIterator = pItemArray, i = 0; pIterator->uLabelType != 0; pIterator++, i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002391 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002392 pIterator->uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002393 }
2394 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002395
2396Done:
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002397 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002398
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002399 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002400}
2401
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002402
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002403/*
2404Public function, see header qcbor/qcbor_decode.h file
2405*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002406void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2407 int64_t nLabel,
2408 uint8_t uQcborType,
2409 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002410{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002411 if(pMe->uLastError != QCBOR_SUCCESS) {
2412 return;
2413 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002414
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002415 QCBORItem OneItemSeach[2];
2416 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2417 OneItemSeach[0].label.int64 = nLabel;
2418 OneItemSeach[0].uDataType = uQcborType;
2419 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002420
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002421 QCBORError nReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002422 if(nReturn) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002423 pMe->uLastError = (uint8_t)nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002424 }
2425
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002426 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
2427 pMe->uLastError = QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002428 }
2429
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002430 *pItem = OneItemSeach[0];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002431}
2432
2433
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002434/*
2435Public function, see header qcbor/qcbor_decode.h file
2436*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002437void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2438 const char *szLabel,
2439 uint8_t uQcborType,
2440 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002441{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002442 if(pMe->uLastError != QCBOR_SUCCESS) {
2443 return;
2444 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002445
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002446 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002447 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2448 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2449 OneItemSeach[0].uDataType = uQcborType;
2450 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002451
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002452 QCBORError nReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002453 if(nReturn) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07002454 pMe->uLastError = (uint8_t)nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002455 }
2456
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002457 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07002458 pMe->uLastError = QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002459 }
2460
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002461 *pItem = OneItemSeach[0];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002462}
2463
2464
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002465/**
2466 @param[in] TagSpec Specification for matching tags.
2467 @param[in] uDataType A QCBOR data type
2468
2469 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2470 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
2471
2472 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value.
2473 */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002474static QCBORError CheckTagRequirement(const TagSpecification TagSpec, uint8_t uDataType)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002475{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002476 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG) {
2477 /* Must match the tag */
2478 if(uDataType == TagSpec.uTaggedType) {
2479 return QCBOR_SUCCESS;
2480 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002481 } else {
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002482 /* QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE or QCBOR_TAGSPEC_MATCH_EITHER */
2483 /* Must check all the possible types for the tag content */
2484 for(size_t i = 0; i < sizeof(TagSpec.uAllowedContentTypes); i++) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002485 if(uDataType == TagSpec.uAllowedContentTypes[i]) {
2486 return QCBOR_SUCCESS;
2487 }
2488 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002489 /* Didn't match any of the tag content types */
2490 /* Check the tag for the either case */
2491 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_EITHER) {
2492 if(uDataType == TagSpec.uTaggedType) {
2493 return QCBOR_SUCCESS;
2494 }
2495 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002496 }
2497
2498 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002499}
2500
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002501
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002502// Semi-private
2503// TODO: inline or collapse with QCBORDecode_GetTaggedStringInMapN?
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002504void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2505 int64_t nLabel,
2506 TagSpecification TagSpec,
2507 QCBORItem *pItem)
2508{
2509 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2510 if(pMe->uLastError != QCBOR_SUCCESS) {
2511 return;
2512 }
2513
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002514 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002515}
2516
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002517// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002518void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2519 const char *szLabel,
2520 TagSpecification TagSpec,
2521 QCBORItem *pItem)
2522{
2523 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2524 if(pMe->uLastError != QCBOR_SUCCESS) {
2525 return;
2526 }
2527
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002528 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002529}
2530
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002531// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002532void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2533 int64_t nLabel,
2534 TagSpecification TagSpec,
2535 UsefulBufC *pString)
2536{
2537 QCBORItem Item;
2538 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2539 if(pMe->uLastError == QCBOR_SUCCESS) {
2540 *pString = Item.val.string;
2541 }
2542}
2543
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002544// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002545void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2546 const char * szLabel,
2547 TagSpecification TagSpec,
2548 UsefulBufC *pString)
2549{
2550 QCBORItem Item;
2551 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2552 if(pMe->uLastError == QCBOR_SUCCESS) {
2553 *pString = Item.val.string;
2554 }
2555}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002556
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002557/*
2558Public function, see header qcbor/qcbor_decode.h file
2559*/
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002560QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2561{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002562 return MapSearch(pCtx, pItemList, NULL, NULL, NULL);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002563}
2564
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002565/*
2566Public function, see header qcbor/qcbor_decode.h file
2567*/
2568QCBORError QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pCtx,
2569 QCBORItem *pItemList,
2570 void *pCallbackCtx,
2571 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002572{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002573 return MapSearch(pCtx, pItemList, NULL, pCallbackCtx, pfCB);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002574}
2575
2576
Laurence Lundblade34691b92020-05-18 22:25:25 -07002577static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002578{
Laurence Lundblade34691b92020-05-18 22:25:25 -07002579 if(pMe->uLastError != QCBOR_SUCCESS) {
2580 // Already in error state; do nothing.
2581 return;
2582 }
2583
2584 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002585 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002586 if(pMe->uLastError != QCBOR_SUCCESS) {
2587 return;
2588 }
2589
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002590 /* Need to get the current pre-order nesting level and cursor to be
2591 at the first item in the map/array just entered.
2592
2593 Also need to current map nesting level and start cursor to
2594 be at the right place.
2595
2596 The UsefulInBuf offset could be anywhere, so no assumption is
2597 made about it.
2598
2599 No assumption is made about the pre-order nesting level either.
2600
2601 However the map mode nesting level is assumed to be one above
2602 the map level that is being entered.
2603 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002604 /* Seek to the data item that is the map or array */
2605 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002606 pMe->nesting.pCurrent = pMe->nesting.pCurrentBounded; // TODO: part of DecodeNesting
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002607
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002608 // TODO: check error?
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002609 QCBORDecode_EnterBoundedMode(pMe, pSearch->uDataType);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002610
Laurence Lundblade34691b92020-05-18 22:25:25 -07002611 printdecode(pMe, "FinishEnter");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002612}
2613
2614
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002615/*
2616Public function, see header qcbor/qcbor_decode.h file
2617*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002618void QCBORDecode_EnterMapInMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002619{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002620 QCBORItem OneItemSeach[2];
2621 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2622 OneItemSeach[0].label.int64 = nLabel;
2623 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2624 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002625
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002626 /* The map to enter was found, now finish of entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002627 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002628}
2629
2630
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002631/*
2632Public function, see header qcbor/qcbor_decode.h file
2633*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002634void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002635{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002636 QCBORItem OneItemSeach[2];
2637 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2638 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2639 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2640 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002641
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002642 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002643}
2644
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002645/*
2646Public function, see header qcbor/qcbor_decode.h file
2647*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002648void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002649{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002650 QCBORItem OneItemSeach[2];
2651 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2652 OneItemSeach[0].label.int64 = nLabel;
2653 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2654 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002655
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002656 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002657}
2658
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002659/*
2660Public function, see header qcbor/qcbor_decode.h file
2661*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002662void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2663{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002664 QCBORItem OneItemSeach[2];
2665 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2666 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2667 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2668 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002669
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002670 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002671}
2672
2673
2674
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002675/* Next item must be map or this generates an error */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002676void QCBORDecode_EnterBoundedMode(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002677{
Laurence Lundblade34691b92020-05-18 22:25:25 -07002678 if(pMe->uLastError != QCBOR_SUCCESS) {
2679 // Already in error state; do nothing.
2680 return;
2681 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002682
2683 /* Get the data item that is the map that is being searched */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002684 QCBORItem Item;
Laurence Lundblade986017c2020-05-23 19:25:02 -07002685 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002686 if(pMe->uLastError != QCBOR_SUCCESS) {
2687 return;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002688 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002689 if(Item.uDataType != uType) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07002690 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
2691 return;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002692 }
2693
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002694 DecodeNesting_EnterBoundedMode(&(pMe->nesting), UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002695
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002696 // TODO: restrict input to less than this or some other invalidation strategy.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002697 pMe->uMapEndOffsetCache = 0xffffffff; // Invalidate the cached map end.
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002698
Laurence Lundblade34691b92020-05-18 22:25:25 -07002699 printdecode(pMe, "EnterMapModeDone");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002700}
2701
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002702static QCBORError
2703ExitExit(QCBORDecodeContext *pMe, uint32_t uEndOffset)
2704{
2705 // TODO: is this necessary? Pretty sure it is not
2706 //pMe->nesting.pCurrentBounded->bBoundedMode = false;
2707
2708 QCBORError uErr;
2709 /* Exiting a bounded mode level. Bounded mode could be
2710 either an array, map or wrapped bstr.
2711
2712 The following have to be set when exiting a bounded mode level
2713 - The byte offset of the useful input buffer set to the item after the map, array or bstr just consumed.
2714 - The length of the useful input buf has to be adjusted if exiting bstr wrapped CBOR
2715 - The pre-order traversal nesting level, which could be just one level up, or all the way to the top.
2716 - The count of items in the pre-order nesting level if it is a definite length map or array.
2717 - The bounded nesting level, which could be one bounded level up, or all the way to the top
2718
2719 That means that the pre-order traversal must be set up
2720 to the position just after the array, map or wrapped
2721 bstr that was consumed.
2722
2723
2724*/
2725 /* First work is to set up the pre-order traversal
2726 so that it is positioned just after the array, map
2727 or wrapped bstr that was just consumed. The
2728 useful input buf cursor, nesting level and item
2729 count needs to be adjusted. The exit of the array
2730 map or wrapped bstr might be the last in the
2731 above nesting map or array and so on. Ascender()
2732 does lots of work to unwind all the way to the top
2733 through maps and arrays of definite or indefinte
2734 lengths. */
2735 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2736
2737 pMe->nesting.pCurrent = pMe->nesting.pCurrentBounded - 1; // TODO error check
2738
2739 uErr = Ascender(pMe);
2740 if(uErr != QCBOR_SUCCESS) {
2741 goto Done;
2742 }
2743
2744/*
2745 It also means that the next highest bounded mode
2746 must be put into effect. That, or the top-level sequence
2747 is reached (which is the primordial bounded bstr in a sense. */
2748 /* Also ascend to the next higest bounded mode level if
2749 there is one. */
2750 while(pMe->nesting.pCurrentBounded != &(pMe->nesting.pMapsAndArrays[0])) {
2751 pMe->nesting.pCurrentBounded--;
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002752 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002753 break;
2754 }
2755 }
2756
2757 pMe->uMapEndOffsetCache = 0xffffffff; // Invalidate the cached map end.
2758
2759Done:
2760 printdecode(pMe, "exit exit");
2761 return uErr;
2762}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002763
2764// Semi-private function
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002765void QCBORDecode_ExitBoundedMode(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002766{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002767 if(pMe->uLastError != QCBOR_SUCCESS) {
2768 // Already in error state; do nothing.
2769 return;
2770 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002771
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002772 printdecode(pMe, "start exit");
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002773
2774 QCBORError uErr = QCBOR_SUCCESS;
2775
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002776 if(!DecodeNesting_CheckBoundedType(&(pMe->nesting), uType)){
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002777 uErr = QCBOR_ERR_CLOSE_MISMATCH;
2778 goto Done;
2779 }
2780
2781 /* Have to set the offset to the end of the map/array
2782 that is being exited. If there is no cached value,
2783 from previous map search, then do a dummy search. */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002784 if(pMe->uMapEndOffsetCache == 0xffffffff) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002785 QCBORItem Dummy;
2786 Dummy.uLabelType = QCBOR_TYPE_NONE;
2787 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
2788 if(uErr != QCBOR_SUCCESS) {
2789 goto Done;
2790 }
2791 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002792
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002793 uErr = ExitExit(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002794
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002795Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002796 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002797}
2798
2799
Laurence Lundblade1341c592020-04-11 14:19:05 -07002800void QCBORDecode_RewindMap(QCBORDecodeContext *pMe)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002801{
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002802 // TODO: check for map mode; test this
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002803 //pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->u.ma.uCountTotal;
2804 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->u.ma.uStartOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002805}
2806
2807
Laurence Lundblade1341c592020-04-11 14:19:05 -07002808
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002809static QCBORError InternalEnterWrappedBstr(QCBORDecodeContext *pMe, const QCBORItem *pItem, uint8_t uTagRequirement, UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002810{
2811 if(pMe->uLastError != QCBOR_SUCCESS) {
2812 // Already in error state; do nothing.
2813 return pMe->uLastError;
2814 }
2815
2816 QCBORError uError = QCBOR_SUCCESS;
2817
2818 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
2819 uError = QCBOR_ERR_UNEXPECTED_TYPE;
2820 goto Done;;
2821 }
2822
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002823 // TODO: check for the other wrapped CBOR tag
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002824 const TagSpecification TagSpec = {uTagRequirement, QBCOR_TYPE_WRAPPED_CBOR, {QCBOR_TYPE_BYTE_STRING, 0,0,0,0,0}};
2825
2826 uError = CheckTagRequirement(TagSpec, pItem->uDataType);
2827 if(uError != QCBOR_SUCCESS) {
2828 goto Done;
2829 }
2830
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002831 if(DecodeNesting_IsDefiniteLength(&(pMe->nesting))) {
2832 /* Reverse the decrement done by GetNext() for the bstr as
2833 so the increment in ExitExit()->Ascender() will work right. */
2834 pMe->nesting.pCurrent->u.ma.uCountCursor++;
2835 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002836
2837 if(pBstr) {
2838 *pBstr = pItem->val.string;
2839 }
2840
2841 const size_t uPreviousLength = UsefulInputBuf_GetLength(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002842
2843 // Need to move UIB input cursor to the right place
2844
2845 // Really this is a subtraction and an assignment; not much code
2846 // There is a range check in the seek.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002847 // The bstr was just consumed so the cursor is at the next item after it
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002848
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002849 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002850
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002851
2852 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
2853
2854 UsefulInputBuf_SetBufferLen(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002855
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002856 uError = DecodeNesting_DescendWrappedBstr(&(pMe->nesting),
2857 uPreviousLength,
2858 uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002859Done:
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002860 printdecode(pMe, "Entered Bstr");
2861
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002862 return uError;
2863
2864}
2865
2866
2867void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe, uint8_t uTagRequirement, UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002868{
2869 if(pMe->uLastError != QCBOR_SUCCESS) {
2870 // Already in error state; do nothing.
2871 return;
2872 }
2873
2874 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002875 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002876 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
2877 if(pMe->uLastError != QCBOR_SUCCESS) {
2878 return;
2879 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002880
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002881 pMe->uLastError = (uint8_t)InternalEnterWrappedBstr(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002882}
2883
2884
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002885void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe, uint8_t uTagRequirement, int64_t nLabel, UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002886{
2887 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002888 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002889
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002890 pMe->uLastError = (uint8_t)InternalEnterWrappedBstr(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002891}
2892
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002893
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002894void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe, uint8_t uTagRequirement, const char *szLabel, UsefulBufC *pBstr)
2895{
2896 QCBORItem Item;
2897 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
2898
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002899 pMe->uLastError = (uint8_t)InternalEnterWrappedBstr(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002900}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002901
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002902
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002903void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002904{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002905 // TODO: test for right mode?
2906
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002907 /* Reset the length of the Useful\InputBuf to what it was before
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002908 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002909 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002910 UsefulInputBuf_SetBufferLen(&(pMe->InBuf),
2911 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002912
2913
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002914 QCBORError uErr = ExitExit(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
2915 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002916}
2917
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002918
Laurence Lundbladee6430642020-03-14 21:15:44 -07002919
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002920
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002921
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002922
Laurence Lundblade11a064e2020-05-07 13:13:42 -07002923
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002924
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002925static QCBORError InterpretBool(const QCBORItem *pItem, bool *pBool)
2926{
2927 switch(pItem->uDataType) {
2928 case QCBOR_TYPE_TRUE:
2929 *pBool = true;
2930 return QCBOR_SUCCESS;
2931 break;
2932
2933 case QCBOR_TYPE_FALSE:
2934 *pBool = false;
2935 return QCBOR_SUCCESS;
2936 break;
2937
2938 default:
2939 return QCBOR_ERR_UNEXPECTED_TYPE;
2940 break;
2941 }
2942}
Laurence Lundbladee6430642020-03-14 21:15:44 -07002943
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002944/*
2945Public function, see header qcbor/qcbor_decode.h file
2946*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07002947void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002948{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002949 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002950 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07002951 return;
2952 }
2953
Laurence Lundbladec4537442020-04-14 18:53:22 -07002954 QCBORError nError;
2955 QCBORItem Item;
2956
2957 nError = QCBORDecode_GetNext(pMe, &Item);
2958 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002959 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002960 return;
2961 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002962 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002963}
2964
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002965/*
2966Public function, see header qcbor/qcbor_decode.h file
2967*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002968void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002969{
2970 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002971 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002972
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002973 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002974}
2975
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002976/*
2977Public function, see header qcbor/qcbor_decode.h file
2978*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002979void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
2980{
2981 QCBORItem Item;
2982 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
2983
2984 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
2985}
2986
2987
2988
2989void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe, TagSpecification TagSpec, UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002990{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002991 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002992 // Already in error state, do nothing
2993 return;
2994 }
2995
2996 QCBORError nError;
2997 QCBORItem Item;
2998
2999 nError = QCBORDecode_GetNext(pMe, &Item);
3000 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003001 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003002 return;
3003 }
3004
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003005 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, Item.uDataType);
3006
3007 if(pMe->uLastError == QCBOR_SUCCESS) {
3008 *pBstr = Item.val.string;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003009 }
3010}
3011
Laurence Lundbladec4537442020-04-14 18:53:22 -07003012
3013
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003014
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003015static QCBORError ConvertBigNum(uint8_t uTagRequirement, const QCBORItem *pItem, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003016{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003017 *pbIsNegative = false;
3018
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003019 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 -07003020
3021 switch(pItem->uDataType) {
3022 case QCBOR_TYPE_BYTE_STRING:
3023 // TODO: check that there is no tag here?
3024 if(bMustBeTagged) {
3025 return QCBOR_ERR_UNEXPECTED_TYPE;
3026 } else {
3027 *pValue = pItem->val.string;
3028 return QCBOR_SUCCESS;
3029 }
3030 break;
3031
3032 case QCBOR_TYPE_POSBIGNUM:
3033 *pValue = pItem->val.string;
3034 return QCBOR_SUCCESS;
3035 break;
3036
3037 case QCBOR_TYPE_NEGBIGNUM:
3038 *pbIsNegative = true;
3039 *pValue = pItem->val.string;
3040 return QCBOR_SUCCESS;
3041 break;
3042
3043 default:
3044 return QCBOR_ERR_UNEXPECTED_TYPE;
3045 break;
3046 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003047}
3048
3049
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003050/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003051 @param[in] bMustBeTagged If \c true, then the data item must be tagged as either
3052 a positive or negative bignum. If \c false, then it only must be a byte string and bIsNegative
3053 will always be false on the asumption that it is positive, but it can be interpretted as
3054 negative if the the sign is know from other context.
3055 @param[out] pValue The bytes that make up the big num
3056 @param[out] pbIsNegative \c true if tagged as a negative big num. \c false otherwise.
3057
3058 if bMustBeTagged is false, then this will succeed if the data item is a plain byte string,
3059 a positive big num or a negative big num.
3060
3061 */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003062void QCBORDecode_GetBignum(QCBORDecodeContext *pMe, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003063{
3064 if(pMe->uLastError != QCBOR_SUCCESS) {
3065 // Already in error state, do nothing
3066 return;
3067 }
3068
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003069 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003070 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3071 if(uError != QCBOR_SUCCESS) {
3072 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003073 return;
3074 }
3075
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003076 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003077}
3078
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003079/*
3080Public function, see header qcbor/qcbor_decode.h file
3081*/
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003082void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003083{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003084 QCBORItem Item;
3085 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003086
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003087 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003088}
3089
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003090/*
3091Public function, see header qcbor/qcbor_decode.h file
3092*/
3093void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
3094{
3095 QCBORItem Item;
3096 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3097
3098 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
3099}
3100
3101
3102
3103// Semi private
3104QCBORError FarfMIME(uint8_t uTagRequirement, const QCBORItem *pItem, UsefulBufC *pMessage, bool *pbIsNot7Bit)
3105{
3106 const TagSpecification TagSpecText = {uTagRequirement, QCBOR_TYPE_MIME, {QCBOR_TYPE_TEXT_STRING, 0,0,0,0,0}};
3107 const TagSpecification TagSpecBinary = {uTagRequirement, QCBOR_TYPE_BINARY_MIME, {QCBOR_TYPE_BYTE_STRING, 0,0,0,0,0}};
3108
3109 QCBORError uReturn;
3110
3111 if(CheckTagRequirement(TagSpecText, pItem->uDataType)) {
3112 *pMessage = pItem->val.string;
3113 if(pbIsNot7Bit != NULL) {
3114 *pbIsNot7Bit = false;
3115 }
3116 uReturn = QCBOR_SUCCESS;
3117 } else if(CheckTagRequirement(TagSpecBinary, pItem->uDataType)) {
3118 *pMessage = pItem->val.string;
3119 if(pbIsNot7Bit != NULL) {
3120 *pbIsNot7Bit = true;
3121 }
3122 uReturn = QCBOR_SUCCESS;
3123
3124 } else {
3125 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3126 }
3127
3128 return uReturn;
3129}
3130
3131
3132
3133
3134
Laurence Lundbladec4537442020-04-14 18:53:22 -07003135
3136
3137
Laurence Lundbladee6430642020-03-14 21:15:44 -07003138
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003139typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003140
3141
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003142// The main exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003143static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003144{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003145 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003146
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003147 if(uResult != 0) {
3148 /* This loop will run a maximum of 19 times because
3149 * UINT64_MAX < 10 ^^ 19. More than that will cause
3150 * exit with the overflow error
3151 */
3152 for(; nExponent > 0; nExponent--) {
3153 if(uResult > UINT64_MAX / 10) {
3154 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3155 }
3156 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003157 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003158
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003159 for(; nExponent < 0; nExponent++) {
3160 uResult = uResult / 10;
3161 if(uResult == 0) {
3162 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3163 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003164 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003165 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003166 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003167
3168 *puResult = uResult;
3169
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003170 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003171}
3172
3173
Laurence Lundbladee6430642020-03-14 21:15:44 -07003174/* Convert a decimal fraction to an int64_t without using
3175 floating point or math libraries. Most decimal fractions
3176 will not fit in an int64_t and this will error out with
3177 under or overflow
3178 */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003179static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003180{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003181 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003182
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003183 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003184
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003185 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003186 * INT64_MAX < 2^31. More than that will cause
3187 * exist with the overflow error
3188 */
3189 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003190 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003191 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003192 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003193 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003194 nExponent--;
3195 }
3196
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003197 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003198 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003199 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3200 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003201 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003202 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003203 }
3204
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003205 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003206
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003207 return QCBOR_SUCCESS;
3208}
3209
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003210/*
3211 Compute value with signed mantissa and signed result. Works with exponent of 2 or 10 based on exponentiator.
3212 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003213static inline QCBORError ExponentiateNN(int64_t nMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
3214{
3215 uint64_t uResult;
3216
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003217 // Take the absolute value of the mantissa and convert to unsigned.
3218 // TODO: this should be possible in one intruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003219 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3220
3221 // Do the exponentiation of the positive mantissa
3222 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3223 if(uReturn) {
3224 return uReturn;
3225 }
3226
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003227
Laurence Lundblade983500d2020-05-14 11:49:34 -07003228 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3229 of INT64_MIN. This assumes two's compliment representation where
3230 INT64_MIN is one increment farther from 0 than INT64_MAX.
3231 Trying to write -INT64_MIN doesn't work to get this because the
3232 compiler tries to work with an int64_t which can't represent
3233 -INT64_MIN.
3234 */
3235 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3236
3237 // Error out if too large
3238 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003239 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3240 }
3241
3242 // Casts are safe because of checks above
3243 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3244
3245 return QCBOR_SUCCESS;
3246}
3247
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003248/*
3249 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3250 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003251static inline QCBORError ExponentitateNU(int64_t nMantissa, int64_t nExponent, uint64_t *puResult, fExponentiator pfExp)
3252{
3253 if(nMantissa < 0) {
3254 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3255 }
3256
3257 // Cast to unsigned is OK because of check for negative
3258 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3259 // Exponentiation is straight forward
3260 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3261}
3262
3263
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003264#include <math.h>
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003265
3266
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003267static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003268{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003269 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003270
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003271 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003272 const uint8_t *pByte = BigNum.ptr;
3273 size_t uLen = BigNum.len;
3274 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003275 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003276 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003277 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003278 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003279 }
3280
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003281 *pResult = uResult;
3282 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003283}
3284
Laurence Lundblade887add82020-05-17 05:50:34 -07003285static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003286{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003287 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003288}
3289
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003290static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003291{
3292 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003293 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3294 if(uError) {
3295 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003296 }
3297 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3298 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003299 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003300}
3301
3302
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003303static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003304{
3305 uint64_t uResult;
Laurence Lundbladeda095972020-06-06 18:35:33 -07003306 /* negaative int furthest from zero is INT64_MIN
3307 which is expressed as -INT64_MAX-1. The value of
3308 a negative bignum is -n-1, one further from zero
3309 than the positive bignum */
3310
3311 /* say INT64_MIN is -2; then INT64_MAX is 1.
3312 Then -n-1 <= INT64_MIN.
3313 Then -n -1 <= -INT64_MAX - 1
3314 THen n <= INT64_MAX. */
3315 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003316 if(uError) {
3317 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003318 }
3319 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
Laurence Lundblade887add82020-05-17 05:50:34 -07003320 // TODO: this code is incorrect. See RFC 7049
Laurence Lundbladeda095972020-06-06 18:35:33 -07003321 uResult++; // this is the -1 in -n-1
Laurence Lundbladee6430642020-03-14 21:15:44 -07003322 *pResult = -(int64_t)uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003323 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003324}
3325
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003326#include "fenv.h"
Laurence Lundbladec4537442020-04-14 18:53:22 -07003327
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003328
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003329/*
3330Convert a integers and floats to an int64_t.
3331
3332\param[in] uOptions Bit mask list of conversion options.
3333
3334\retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
3335
3336\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3337
3338\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3339
3340*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003341static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
3342{
3343 switch(pItem->uDataType) {
3344 // TODO: float when ifdefs are set
3345 case QCBOR_TYPE_DOUBLE:
3346 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3347 // TODO: what about under/overflow here?
3348 // Invokes the floating-point HW and/or compiler-added libraries
3349 feclearexcept(FE_ALL_EXCEPT);
3350 *pnValue = llround(pItem->val.dfnum);
3351 if(fetestexcept(FE_INVALID)) {
3352 // TODO: better error code
3353 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3354 }
3355 } else {
3356 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3357 }
3358 break;
3359
3360 case QCBOR_TYPE_INT64:
3361 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
3362 *pnValue = pItem->val.int64;
3363 } else {
3364 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3365 }
3366 break;
3367
3368 case QCBOR_TYPE_UINT64:
3369 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
3370 if(pItem->val.uint64 < INT64_MAX) {
3371 *pnValue = pItem->val.int64;
3372 } else {
3373 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3374 }
3375 } else {
3376 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3377 }
3378 break;
3379
3380 default:
3381 return QCBOR_ERR_UNEXPECTED_TYPE;
3382 }
3383 return QCBOR_SUCCESS;
3384}
3385
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003386
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003387void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
3388 uint32_t uOptions,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003389 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003390 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003391{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003392 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003393 return;
3394 }
3395
Laurence Lundbladee6430642020-03-14 21:15:44 -07003396 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003397 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3398 if(uError) {
3399 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003400 return;
3401 }
3402
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003403 if(pItem) {
3404 *pItem = Item;
3405 }
3406
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003407 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003408}
3409
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003410
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003411void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3412 int64_t nLabel,
3413 uint32_t uOptions,
3414 int64_t *pnValue,
3415 QCBORItem *pItem)
3416{
3417 QCBORItem Item;
3418 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3419
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003420 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003421}
3422
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003423
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003424void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3425 const char * szLabel,
3426 uint32_t uOptions,
3427 int64_t *pnValue,
3428 QCBORItem *pItem)
3429{
3430 if(pMe->uLastError != QCBOR_SUCCESS) {
3431 return;
3432 }
3433
3434 QCBORItem Item;
3435 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3436
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003437 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003438}
3439
3440
3441
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003442/*
3443 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003444
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003445 \param[in] uOptions Bit mask list of conversion options.
3446
3447 \retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
3448
3449 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3450
3451 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3452
3453 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003454static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
3455{
3456 QCBORError uErr;
3457
3458 switch(pItem->uDataType) {
3459
3460 case QCBOR_TYPE_POSBIGNUM:
3461 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3462 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003463 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003464 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003465 }
3466 break;
3467
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003468 case QCBOR_TYPE_NEGBIGNUM:
3469 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3470 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003471 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003472 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003473 }
3474 break;
3475
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003476#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3477 case QCBOR_TYPE_DECIMAL_FRACTION:
3478 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3479 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3480 pItem->val.expAndMantissa.nExponent,
3481 pnValue,
3482 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003483 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003484 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3485 }
3486 break;
3487
3488 case QCBOR_TYPE_BIGFLOAT:
3489 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3490 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3491 pItem->val.expAndMantissa.nExponent,
3492 pnValue,
3493 Exponentitate2);
3494 } else {
3495 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3496 }
3497 break;
3498
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003499 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3500 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3501 int64_t nMantissa;
3502 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3503 if(uErr) {
3504 return uErr;
3505 }
3506 return ExponentiateNN(nMantissa,
3507 pItem->val.expAndMantissa.nExponent,
3508 pnValue,
3509 Exponentitate10);
3510 } else {
3511 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3512 }
3513 break;
3514
3515 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3516 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3517 int64_t nMantissa;
3518 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3519 if(uErr) {
3520 return uErr;
3521 }
3522 return ExponentiateNN(nMantissa,
3523 pItem->val.expAndMantissa.nExponent,
3524 pnValue,
3525 Exponentitate10);
3526 } else {
3527 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3528 }
3529 break;
3530
3531 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3532 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3533 int64_t nMantissa;
3534 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3535 if(uErr) {
3536 return uErr;
3537 }
3538 return ExponentiateNN(nMantissa,
3539 pItem->val.expAndMantissa.nExponent,
3540 pnValue,
3541 Exponentitate2);
3542 } else {
3543 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3544 }
3545 break;
3546
3547 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3548 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3549 int64_t nMantissa;
3550 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3551 if(uErr) {
3552 return uErr;
3553 }
3554 return ExponentiateNN(nMantissa,
3555 pItem->val.expAndMantissa.nExponent,
3556 pnValue,
3557 Exponentitate2);
3558 } else {
3559 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003560 }
3561 break;
3562
Laurence Lundbladec4537442020-04-14 18:53:22 -07003563 default:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003564 return QCBOR_ERR_UNEXPECTED_TYPE;
3565#endif
Laurence Lundbladec4537442020-04-14 18:53:22 -07003566 }
3567}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003568
3569
Laurence Lundbladec4537442020-04-14 18:53:22 -07003570/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003571 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003572 */
3573void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003574{
3575 QCBORItem Item;
3576
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003577 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003578
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003579 if(pMe->uLastError == QCBOR_SUCCESS) {
3580 // The above conversion succeeded
3581 return;
3582 }
3583
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003584 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003585 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07003586 return;
3587 }
3588
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003589 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003590}
3591
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003592
3593/*
3594Public function, see header qcbor/qcbor_decode.h file
3595*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003596void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int64_t *pnValue)
3597{
3598 QCBORItem Item;
3599
3600 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, pnValue, &Item);
3601
3602 if(pMe->uLastError == QCBOR_SUCCESS) {
3603 // The above conversion succeeded
3604 return;
3605 }
3606
3607 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3608 // The above conversion failed in a way that code below can't correct
3609 return;
3610 }
3611
3612 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3613}
3614
3615
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003616/*
3617Public function, see header qcbor/qcbor_decode.h file
3618*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003619void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int64_t *pnValue)
3620{
3621 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003622 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, pnValue, &Item);
3623
3624 if(pMe->uLastError == QCBOR_SUCCESS) {
3625 // The above conversion succeeded
3626 return;
3627 }
3628
3629 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3630 // The above conversion failed in a way that code below can't correct
3631 return;
3632 }
3633
3634 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3635}
3636
3637
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003638static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3639{
3640 switch(pItem->uDataType) {
3641 // TODO: type flaot
3642 case QCBOR_TYPE_DOUBLE:
3643 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3644 feclearexcept(FE_ALL_EXCEPT);
3645 double dRounded = round(pItem->val.dfnum);
3646 // TODO: over/underflow
3647 if(fetestexcept(FE_INVALID)) {
3648 // TODO: better error code
3649 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3650 } else if(isnan(dRounded)) {
3651 // TODO: better error code
3652 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3653 } else if(dRounded >= 0) {
3654 *puValue = (uint64_t)dRounded;
3655 } else {
3656 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3657 }
3658 } else {
3659 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3660 }
3661 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003662
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003663 case QCBOR_TYPE_INT64:
3664 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
3665 if(pItem->val.int64 >= 0) {
3666 *puValue = (uint64_t)pItem->val.int64;
3667 } else {
3668 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3669 }
3670 } else {
3671 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3672 }
3673 break;
3674
3675 case QCBOR_TYPE_UINT64:
3676 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
3677 *puValue = pItem->val.uint64;
3678 } else {
3679 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3680 }
3681 break;
3682
3683 default:
3684 return QCBOR_ERR_UNEXPECTED_TYPE;
3685 }
3686 return QCBOR_SUCCESS;
3687}
Laurence Lundbladec4537442020-04-14 18:53:22 -07003688
3689
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003690void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
3691 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003692 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003693 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003694{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003695 if(pMe->uLastError != QCBOR_SUCCESS) {
3696 return;
3697 }
3698
Laurence Lundbladec4537442020-04-14 18:53:22 -07003699 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003700
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003701 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3702 if(uError) {
3703 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003704 return;
3705 }
3706
Laurence Lundbladea826c502020-05-10 21:07:00 -07003707 if(pItem) {
3708 *pItem = Item;
3709 }
3710
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003711 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003712}
3713
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003714
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003715void QCBORDecode_GetInt8ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3716{
3717 int64_t uValue;
3718 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, &uValue, pItem);
3719 if(pMe->uLastError != QCBOR_SUCCESS) {
3720 return;
3721 }
3722
3723 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3724 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3725 }
3726}
3727
3728void QCBORDecode_GetInt8ConvertInternalInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3729{
3730 int64_t uValue;
3731 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, &uValue, pItem);
3732 if(pMe->uLastError != QCBOR_SUCCESS) {
3733 return;
3734 }
3735
3736 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3737 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3738 }
3739}
3740
3741void QCBORDecode_GetInt8ConvertInternalInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3742{
3743 int64_t uValue;
3744 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, &uValue, pItem);
3745 if(pMe->uLastError != QCBOR_SUCCESS) {
3746 return;
3747 }
3748
3749 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3750 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3751 }
3752}
3753
3754
3755
3756
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003757void QCBORDecode_GetUint64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3758 int64_t nLabel,
3759 uint32_t uOptions,
3760 uint64_t *puValue,
3761 QCBORItem *pItem)
3762{
3763 QCBORItem Item;
3764 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3765
3766 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
3767}
3768
3769
3770void QCBORDecode_GetUint64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3771 const char * szLabel,
3772 uint32_t uOptions,
3773 uint64_t *puValue,
3774 QCBORItem *pItem)
3775{
3776 if(pMe->uLastError != QCBOR_SUCCESS) {
3777 return;
3778 }
3779
3780 QCBORItem Item;
3781 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3782
3783 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
3784}
3785
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003786/*
3787 Public function, see header qcbor/qcbor_decode.h file
3788*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003789static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3790{
3791 QCBORError uErr;
3792
3793 switch(pItem->uDataType) {
3794
3795 case QCBOR_TYPE_POSBIGNUM:
3796 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3797 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
3798 } else {
3799 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3800 }
3801 break;
3802
3803 case QCBOR_TYPE_NEGBIGNUM:
3804 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3805 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3806 } else {
3807 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3808 }
3809 break;
3810
3811#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3812
3813 case QCBOR_TYPE_DECIMAL_FRACTION:
3814 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3815 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3816 pItem->val.expAndMantissa.nExponent,
3817 puValue,
3818 Exponentitate10);
3819 } else {
3820 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3821 }
3822 break;
3823
3824 case QCBOR_TYPE_BIGFLOAT:
3825 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3826 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3827 pItem->val.expAndMantissa.nExponent,
3828 puValue,
3829 Exponentitate2);
3830 } else {
3831 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3832 }
3833 break;
3834
3835 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3836 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3837 // TODO: Would be better to convert to unsigned
3838 int64_t nMantissa;
3839 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3840 if(uErr != QCBOR_SUCCESS) {
3841 return uErr;
3842 }
3843 return ExponentitateNU(nMantissa,
3844 pItem->val.expAndMantissa.nExponent,
3845 puValue,
3846 Exponentitate10);
3847 } else {
3848 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3849 }
3850 break;
3851
3852 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3853 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3854 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3855 } else {
3856 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3857 }
3858 break;
3859
3860 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3861 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3862 // TODO: Would be better to convert to unsigned
3863 int64_t nMantissa;
3864 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3865 if(uErr != QCBOR_SUCCESS) {
3866 return uErr;
3867 }
3868 return ExponentitateNU(nMantissa,
3869 pItem->val.expAndMantissa.nExponent,
3870 puValue,
3871 Exponentitate2);
3872 } else {
3873 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3874 }
3875 break;
3876
3877 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3878 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3879 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3880 } else {
3881 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3882 }
3883 break;
3884#endif
3885 default:
3886 return QCBOR_ERR_UNEXPECTED_TYPE;
3887 }
3888}
3889
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003890/*
3891 Public function, see header qcbor/qcbor_decode.h file
3892*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003893void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003894{
3895 QCBORItem Item;
3896
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003897 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003898
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003899 if(pMe->uLastError == QCBOR_SUCCESS) {
3900 // The above conversion succeeded
3901 return;
3902 }
3903
3904 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3905 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07003906 return;
3907 }
3908
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003909 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003910}
3911
Laurence Lundbladec4537442020-04-14 18:53:22 -07003912
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003913/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003914 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003915*/
3916void QCBORDecode_GetUint64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, uint64_t *puValue)
3917{
3918 QCBORItem Item;
3919
3920 QCBORDecode_GetUint64ConvertInternalInMapN(pMe, nLabel, uOptions, puValue, &Item);
3921
3922 if(pMe->uLastError == QCBOR_SUCCESS) {
3923 // The above conversion succeeded
3924 return;
3925 }
3926
3927 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3928 // The above conversion failed in a way that code below can't correct
3929 return;
3930 }
3931
3932 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
3933}
3934
3935
3936/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003937 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003938*/
3939void QCBORDecode_GetUint64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, uint64_t *puValue)
3940{
3941 QCBORItem Item;
3942 QCBORDecode_GetUint64ConvertInternalInMapSZ(pMe, szLabel, uOptions, puValue, &Item);
3943
3944 if(pMe->uLastError == QCBOR_SUCCESS) {
3945 // The above conversion succeeded
3946 return;
3947 }
3948
3949 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3950 // The above conversion failed in a way that code below can't correct
3951 return;
3952 }
3953
3954 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
3955}
3956
3957
3958static QCBORError ConvertDouble(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
3959{
3960 switch(pItem->uDataType) {
3961 // TODO: float when ifdefs are set
3962 case QCBOR_TYPE_DOUBLE:
3963 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3964 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3965 *pdValue = pItem->val.dfnum;
3966 } else {
3967 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3968 }
3969 }
3970 break;
3971
3972 case QCBOR_TYPE_INT64:
3973 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
3974 // TODO: how does this work?
3975 *pdValue = (double)pItem->val.int64;
3976
3977 } else {
3978 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3979 }
3980 break;
3981
3982 case QCBOR_TYPE_UINT64:
3983 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
3984 *pdValue = (double)pItem->val.uint64;
3985 } else {
3986 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3987 }
3988 break;
3989
3990 default:
3991 return QCBOR_ERR_UNEXPECTED_TYPE;
3992 }
3993
3994 return QCBOR_SUCCESS;
3995}
3996
3997
3998
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003999void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
4000 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004001 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004002 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004003{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004004 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004005 return;
4006 }
4007
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004008 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004009
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004010 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004011 if(uError) {
4012 pMe->uLastError = (uint8_t)uError;
4013 return;
4014 }
4015
4016 if(pItem) {
4017 *pItem = Item;
4018 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004019
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004020 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004021}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004022
Laurence Lundbladec4537442020-04-14 18:53:22 -07004023
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004024void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4025 int64_t nLabel,
4026 uint32_t uOptions,
4027 double *pdValue,
4028 QCBORItem *pItem)
4029{
4030 QCBORItem Item;
4031 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4032
4033 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
4034}
4035
4036void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4037 const char * szLabel,
4038 uint32_t uOptions,
4039 double *pdValue,
4040 QCBORItem *pItem)
4041{
4042 if(pMe->uLastError != QCBOR_SUCCESS) {
4043 return;
4044 }
4045
4046 QCBORItem Item;
4047 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4048
4049 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
4050}
4051
4052
4053
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004054static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4055{
4056 double dResult;
4057
4058 dResult = 0.0;
4059 const uint8_t *pByte = BigNum.ptr;
4060 size_t uLen = BigNum.len;
4061 /* This will overflow and become the float value INFINITY if the number
4062 is too large to fit. No error will be logged.
4063 TODO: should an error be logged? */
4064 while(uLen--) {
4065 dResult = (dResult * 256.0) + (double)*pByte++;
4066 }
4067
4068 return dResult;
4069}
4070
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004071static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004072{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004073 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004074 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4075
4076 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004077 switch(pItem->uDataType) {
4078 // TODO: type float
4079 case QCBOR_TYPE_DECIMAL_FRACTION:
4080 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4081 // TODO: rounding and overflow errors
4082 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4083 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4084 } else {
4085 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4086 }
4087 break;
4088
4089 case QCBOR_TYPE_BIGFLOAT:
4090 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
4091 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4092 exp2((double)pItem->val.expAndMantissa.nExponent);
4093 } else {
4094 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4095 }
4096 break;
4097
4098 case QCBOR_TYPE_POSBIGNUM:
4099 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
4100 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4101 } else {
4102 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4103 }
4104 break;
4105
4106 case QCBOR_TYPE_NEGBIGNUM:
4107 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004108 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004109 } else {
4110 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4111 }
4112 break;
4113
4114 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4115 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4116 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4117 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4118 } else {
4119 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4120 }
4121 break;
4122
4123 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4124 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4125 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4126 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4127 } else {
4128 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4129 }
4130 break;
4131
4132 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
4133 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
4134 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4135 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4136 } else {
4137 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4138 }
4139 break;
4140
4141 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
4142 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004143 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004144 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4145 } else {
4146 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4147 }
4148 break;
4149
4150 default:
4151 return QCBOR_ERR_UNEXPECTED_TYPE;
4152 }
4153
4154 return QCBOR_SUCCESS;
4155}
4156
4157
4158/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004159 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004160*/
4161void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pdValue)
4162{
4163
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004164 QCBORItem Item;
4165
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004166 QCBORDecode_GetDoubleConvertInternal(pMe, uOptions, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004167
4168 if(pMe->uLastError == QCBOR_SUCCESS) {
4169 // The above conversion succeeded
4170 return;
4171 }
4172
4173 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4174 // The above conversion failed in a way that code below can't correct
4175 return;
4176 }
4177
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004178 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004179}
4180
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004181
4182/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004183 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004184*/
4185void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, double *pdValue)
4186{
4187 QCBORItem Item;
4188
4189 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uOptions, pdValue, &Item);
4190
4191 if(pMe->uLastError == QCBOR_SUCCESS) {
4192 // The above conversion succeeded
4193 return;
4194 }
4195
4196 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4197 // The above conversion failed in a way that code below can't correct
4198 return;
4199 }
4200
4201 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
4202}
4203
4204
4205/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004206 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004207*/
4208void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, double *pdValue)
4209{
4210 QCBORItem Item;
4211 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uOptions, pdValue, &Item);
4212
4213 if(pMe->uLastError == QCBOR_SUCCESS) {
4214 // The above conversion succeeded
4215 return;
4216 }
4217
4218 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4219 // The above conversion failed in a way that code below can't correct
4220 return;
4221 }
4222
4223 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
4224}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004225
4226
4227void FarfDecimalFraction(QCBORDecodeContext *pMe,
4228 uint8_t uTagRequirement,
4229 QCBORItem *pItem,
4230 int64_t *pnMantissa,
4231 int64_t *pnExponent)
4232{
4233 QCBORError uErr;
4234
4235 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
4236 if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
4237 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4238 return;
4239 }
4240 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4241 if(uErr != QCBOR_SUCCESS) {
4242 pMe->uLastError = (uint8_t)uErr;
4243 return;
4244 }
4245 }
4246
4247 if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
4248 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4249 return;
4250 }
4251
4252 switch (pItem->uDataType) {
4253
4254 case QCBOR_TYPE_DECIMAL_FRACTION:
4255 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
4256 *pnExponent = pItem->val.expAndMantissa.nExponent;
4257 break;
4258
4259 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4260 *pnExponent = pItem->val.expAndMantissa.nExponent;
4261
4262 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4263 if(uErr != QCBOR_SUCCESS) {
4264 pMe->uLastError = (uint8_t)uErr;
4265 }
4266 break;
4267
4268 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4269 *pnExponent = pItem->val.expAndMantissa.nExponent;
4270
4271 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4272 if(uErr != QCBOR_SUCCESS) {
4273 pMe->uLastError = (uint8_t)uErr;
4274 }
4275 break;
4276
4277 default:
4278 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4279 }
4280}
4281
4282void QCBORDecode_GetDecimalFractionN(QCBORDecodeContext *pMe,
4283 uint8_t uTagRequirement,
4284 int64_t nLabel,
4285 int64_t *pnMantissa,
4286 int64_t *pnExponent)
4287{
4288 QCBORItem Item;
4289
4290 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4291 FarfDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
4292}
4293
4294
4295
4296void QCBORDecode_GetDecimalFractionSZ(QCBORDecodeContext *pMe,
4297 uint8_t uTagRequirement,
4298 const char *szLabel,
4299 int64_t *pnMantissa,
4300 int64_t *pnExponent)
4301{
4302 QCBORItem Item;
4303
4304 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4305
4306 FarfDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
4307}
4308
4309
4310UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4311{
4312 while(uInt & 0xff0000000000UL) {
4313 uInt = uInt << 8;
4314 };
4315
4316 UsefulOutBuf UOB;
4317
4318 UsefulOutBuf_Init(&UOB, Buffer);
4319
4320 while(uInt) {
4321 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff0000000000UL) >> 56));
4322 uInt = uInt << 8;
4323 }
4324
4325 return UsefulOutBuf_OutUBuf(&UOB);
4326}
4327
4328
4329void QCBORDecode_GetDecimalFractionBigN(QCBORDecodeContext *pMe,
4330 uint8_t uTagRequirement,
4331 int64_t nLabel,
4332 UsefulBuf pBufferForMantissa,
4333 UsefulBufC *pMantissa,
4334 bool *pbIsNegative,
4335 int64_t *pnExponent)
4336{
4337 QCBORItem Item;
4338 QCBORError uErr;
4339
4340 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4341
4342 if(Item.uDataType == QCBOR_TYPE_ARRAY) {
4343 uErr = QCBORDecode_MantissaAndExponent(pMe, &Item);
4344 if(uErr != QCBOR_SUCCESS) {
4345 pMe->uLastError = (uint8_t)uErr;
4346 return;
4347 }
4348 }
4349
4350 uint64_t uMantissa;
4351
4352 switch (Item.uDataType) {
4353
4354 case QCBOR_TYPE_DECIMAL_FRACTION:
4355 if(Item.val.expAndMantissa.Mantissa.nInt >= 0) {
4356 uMantissa = (uint64_t)Item.val.expAndMantissa.Mantissa.nInt;
4357 *pbIsNegative = false;
4358 } else {
4359 uMantissa = (uint64_t)-Item.val.expAndMantissa.Mantissa.nInt;
4360 *pbIsNegative = true;
4361 }
4362 *pMantissa = ConvertIntToBigNum(uMantissa, pBufferForMantissa);
4363 *pnExponent = Item.val.expAndMantissa.nExponent;
4364 break;
4365
4366 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4367 *pnExponent = Item.val.expAndMantissa.nExponent;
4368 *pMantissa = Item.val.expAndMantissa.Mantissa.bigNum;
4369 *pbIsNegative = false;
4370 break;
4371
4372 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4373 *pnExponent = Item.val.expAndMantissa.nExponent;
4374 *pMantissa = Item.val.expAndMantissa.Mantissa.bigNum;
4375 *pbIsNegative = true;
4376 break;
4377
4378 default:
4379 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4380 }
4381}