blob: a5e8066ca27d693fa585000666fdc1a9eedd0195 [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
116// TODO: test Map as array better?
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
126DecodeNesting_GetLevel(const QCBORDecodeNesting *pNesting)
127{
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
134
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700135inline static bool DecodeNesting_InBoundedMode(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700136{
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700137 return pNesting->pCurrent->bBoundedMode;
138 //return pNesting->pCurrent->uType & QCBOR_NEST_TYPE_IS_BOUNDED;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700139}
140
141/*inline static bool IsArray(const QCBORDecodeNesting *pNesting)
142{
143 const unsigned uIndex = DecodeNesting_GetLevel(pNesting);
144
145 return (0x01ULL << ((uIndex * 3) + 1)) & pNesting->uTypeBitMap;
146}
147
148inline static bool IsBstr(const QCBORDecodeNesting *pNesting)
149{
150 const unsigned uIndex = DecodeNesting_GetLevel(pNesting);
151
152 return (0x01ULL << ((uIndex * 3) + 2)) & pNesting->uTypeBitMap;
153}*/
154
155
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700156inline static bool
157DecodeNesting_IsAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700158{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700159 if(pNesting->pCurrent == &(pNesting->pMapsAndArrays[0])) {
160 return true;
161 } else {
162 return false;
163 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700164}
165
Laurence Lundblade937ea812020-05-08 11:38:23 -0700166// Determine if at the end of a map or array while in map mode
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700167inline static bool
168DecodeNesting_AtEnd(const QCBORDecodeNesting *pNesting)
169{
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700170 if(pNesting->pCurrentBounded && DecodeNesting_InBoundedMode(pNesting)) {
171 if(pNesting->pCurrentBounded->uCount == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700172 // In map mode and consumed all items, so it is the end
173 return true;
174 } else {
175 // In map mode, all items not consumed, so it is NOT the end
176 return false;
177 }
178 } else {
Laurence Lundblade937ea812020-05-08 11:38:23 -0700179 // Not in map mode. The end is determined in other ways.
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700180 return false;
181 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700182}
183
184
Laurence Lundbladeee851742020-01-08 08:37:05 -0800185inline static int
186DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700187{
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700188 return pNesting->pCurrent->uCount == UINT16_MAX;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700189 //return pNesting->pCurrent->uType & QCBOR_NEST_TYPE_IS_INDEFINITE;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700190}
191
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800192
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700193inline static uint8_t
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700194DecodeNesting_GetBoundedModeLevel(QCBORDecodeNesting *pNesting)
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700195{
196 // Check in DecodeNesting_Descend and never having
197 // QCBOR_MAX_ARRAY_NESTING > 255 gaurantees cast is safe
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700198 return (uint8_t)(pNesting->pCurrentBounded - &(pNesting->pMapsAndArrays[0]));
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700199}
200
Laurence Lundbladeee851742020-01-08 08:37:05 -0800201inline static int
202DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700203{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700204 if(DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700205 return 0;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700206 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800207
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700208 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
209}
210
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700211inline static bool
212DecodeNesting_BoundedIsType(const QCBORDecodeNesting *pNesting, uint8_t uType)
213{
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700214 if(pNesting->pCurrentBounded->uMajorType == uType) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700215 return true;
216 } else {
217 return false;
218 }
219}
220
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700221
222// return 1 if closed out an array or map
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700223inline static void
224DecodeNesting_DecrementX(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700225{
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700226 pNesting->pCurrent->uCount--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700227}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700228
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700229inline static bool
230DecodeNesting_IsEndOfDefiniteLengthMapOrArray(QCBORDecodeNesting *pNesting)
231{
232 if(pNesting->pCurrent->uCount == 0) {
233 return true;
234 } else {
235 return false;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700236 }
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800237}
238
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700239inline static void
240DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
241{
242 pNesting->pCurrent--;
243}
244
245
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700246
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700247
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700248inline static void
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700249DecodeNesting_EnterBoundedMode(QCBORDecodeNesting *pNesting, size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700250{
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700251 /* Have descended into this before this is called. The job here is just to mark it in bounded mode */
252 pNesting->pCurrentBounded = pNesting->pCurrent;
253 pNesting->pCurrent->bBoundedMode = true;
254 //pNesting->pCurrentBounded->uType |= QCBOR_NEST_TYPE_IS_BOUNDED;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700255 // Cast to uint32_t is safe because QCBOR restricts encoded input to < UINT32_MAX
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700256 pNesting->pCurrentBounded->uOffset = (uint32_t)uOffset;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700257}
258
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700259
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700260
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700261
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700262inline static QCBORError
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700263DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uQCBORType, uint64_t uCount, uint32_t uEndOffset, uint32_t uEndOfBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700264{
265 QCBORError nReturn = QCBOR_SUCCESS;
266
267 if(uCount == 0) {
268 // Nothing to do for empty definite lenth arrays. They are just are
269 // effectively the same as an item that is not a map or array
270 goto Done;
271 // Empty indefinite length maps and arrays are handled elsewhere
272 }
273
274 // Error out if arrays is too long to handle
275 if(uCount != UINT16_MAX && uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
276 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
277 goto Done;
278 }
279
280 // Error out if nesting is too deep
281 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
282 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
283 goto Done;
284 }
285
286 // The actual descend
287 pNesting->pCurrent++;
288
289 // Fill in the new level fully
290 pNesting->pCurrent->uMajorType = uQCBORType;
291 pNesting->pCurrent->uCount = (uint16_t)uCount;
292 pNesting->pCurrent->uSaveCount = (uint16_t)uCount;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700293 pNesting->pCurrent->uPreviousEndOffset = uEndOffset;
294 pNesting->pCurrent->uEndOfBstr = uEndOfBstr;
295 pNesting->pCurrent->bBoundedMode = false;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700296
297Done:
298 return nReturn;;
299}
300
301
302
Laurence Lundbladeee851742020-01-08 08:37:05 -0800303inline static void
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700304DecodeNesting_Init(QCBORDecodeNesting *pNesting, size_t uEndOffset)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700305{
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700306 pNesting->pMapsAndArrays[0].uMajorType = QCBOR_TYPE_BYTE_STRING;
307 // TODO: is cast in the right place?
308 pNesting->pMapsAndArrays[0].uPreviousEndOffset = (uint32_t)uEndOffset;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700309 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
310}
311
312
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700313static void DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
314{
315 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700316 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700317
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700318 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700319 pNesting->pCurrent->uCount = pNesting->pCurrent->uSaveCount;
320 }
321}
322
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700323static inline void DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700324{
325 *pNesting = *pSave;
326}
327
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700328QCBORError DecodeNesting_EnterBstr(QCBORDecodeNesting *pNesting, uint32_t uEndOffset)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700329{
330 QCBORError uReturn ;
331
332 // Error out if nesting is too deep
333 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
334 uReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
335 goto Done;
336 }
337
338 // The actual descend
339 pNesting->pCurrent++;
340
341 // Record a few details for this nesting level
342 pNesting->pCurrent->uMajorType = 1; // TODO the right value for a bstr
343 pNesting->pCurrent->uCount = 0xffff;
344 pNesting->pCurrent->uSaveCount = 0xffff;
345 pNesting->pCurrent->uType = 0;
346
347 uReturn = QCBOR_SUCCESS;
348
349Done:
350 return uReturn;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700351}
352
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700353
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700354
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700355
Laurence Lundbladeee851742020-01-08 08:37:05 -0800356/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800357 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
358
359 The following four functions are pretty wrappers for invocation of
360 the string allocator supplied by the caller.
361
Laurence Lundbladeee851742020-01-08 08:37:05 -0800362 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800363
Laurence Lundbladeee851742020-01-08 08:37:05 -0800364static inline void
365StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800366{
367 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
368}
369
Laurence Lundbladeee851742020-01-08 08:37:05 -0800370// StringAllocator_Reallocate called with pMem NULL is
371// equal to StringAllocator_Allocate()
372static inline UsefulBuf
373StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
374 void *pMem,
375 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800376{
377 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
378}
379
Laurence Lundbladeee851742020-01-08 08:37:05 -0800380static inline UsefulBuf
381StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800382{
383 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
384}
385
Laurence Lundbladeee851742020-01-08 08:37:05 -0800386static inline void
387StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800388{
389 if(pMe->pfAllocator) {
390 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
391 }
392}
393
394
395
Laurence Lundbladeee851742020-01-08 08:37:05 -0800396/*===========================================================================
397 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700398
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800399 See qcbor/qcbor_decode.h for definition of the object
400 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800401 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700402/*
403 Public function, see header file
404 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800405void QCBORDecode_Init(QCBORDecodeContext *me,
406 UsefulBufC EncodedCBOR,
407 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700408{
409 memset(me, 0, sizeof(QCBORDecodeContext));
410 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800411 // Don't bother with error check on decode mode. If a bad value is
412 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700413 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700414 DecodeNesting_Init(&(me->nesting), EncodedCBOR.len);
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700415 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700416 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700417 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700418}
419
420
421/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700422 Public function, see header file
423 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800424void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
425 QCBORStringAllocate pfAllocateFunction,
426 void *pAllocateContext,
427 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700428{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800429 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
430 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
431 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700432}
433
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800434
435/*
436 Public function, see header file
437 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800438void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me,
439 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700440{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700441 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700442}
443
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700444
445/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800446 This decodes the fundamental part of a CBOR data item, the type and
447 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800448
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700449 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800450
Laurence Lundbladeee851742020-01-08 08:37:05 -0800451 This does the network->host byte order conversion. The conversion
452 here also results in the conversion for floats in addition to that
453 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800454
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700455 This returns:
456 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800457
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800458 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800459 tags and floats and length for strings and arrays
460
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800461 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800462 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800463
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800464 The int type is preferred to uint8_t for some variables as this
465 avoids integer promotions, can reduce code size and makes
466 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700467 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800468inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
469 int *pnMajorType,
470 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800471 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700472{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700473 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800474
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700475 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800476 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800477
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700478 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800479 const int nTmpMajorType = nInitialByte >> 5;
480 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800481
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800482 // Where the number or argument accumulates
483 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800484
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800485 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700486 // Need to get 1,2,4 or 8 additional argument bytes. Map
487 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800488 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800489
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800490 // Loop getting all the bytes in the argument
491 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800492 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800493 // This shift and add gives the endian conversion
494 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
495 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800496 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800497 // The reserved and thus-far unused additional info values
498 nReturn = QCBOR_ERR_UNSUPPORTED;
499 goto Done;
500 } else {
501 // Less than 24, additional info is argument or 31, an indefinite length
502 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800503 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700504 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800505
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700506 if(UsefulInputBuf_GetError(pUInBuf)) {
507 nReturn = QCBOR_ERR_HIT_END;
508 goto Done;
509 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800510
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700511 // All successful if we got here.
512 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800513 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800514 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800515 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800516
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700517Done:
518 return nReturn;
519}
520
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800521
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700522/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800523 CBOR doesn't explicitly specify two's compliment for integers but all
524 CPUs use it these days and the test vectors in the RFC are so. All
525 integers in the CBOR structure are positive and the major type
526 indicates positive or negative. CBOR can express positive integers
527 up to 2^x - 1 where x is the number of bits and negative integers
528 down to 2^x. Note that negative numbers can be one more away from
529 zero than positive. Stdint, as far as I can tell, uses two's
530 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800531
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700532 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800533 used carefully here, and in particular why it isn't used in the interface.
534 Also see
535 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
536
537 Int is used for values that need less than 16-bits and would be subject
538 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700539 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800540inline static QCBORError
541DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700542{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700543 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800544
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700545 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
546 if (uNumber <= INT64_MAX) {
547 pDecodedItem->val.int64 = (int64_t)uNumber;
548 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800549
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700550 } else {
551 pDecodedItem->val.uint64 = uNumber;
552 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800553
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700554 }
555 } else {
556 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800557 // CBOR's representation of negative numbers lines up with the
558 // two-compliment representation. A negative integer has one
559 // more in range than a positive integer. INT64_MIN is
560 // equal to (-INT64_MAX) - 1.
561 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700562 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800563
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700564 } else {
565 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000566 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700567 nReturn = QCBOR_ERR_INT_OVERFLOW;
568 }
569 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800570
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700571 return nReturn;
572}
573
574// Make sure #define value line up as DecodeSimple counts on this.
575#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
576#error QCBOR_TYPE_FALSE macro value wrong
577#endif
578
579#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
580#error QCBOR_TYPE_TRUE macro value wrong
581#endif
582
583#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
584#error QCBOR_TYPE_NULL macro value wrong
585#endif
586
587#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
588#error QCBOR_TYPE_UNDEF macro value wrong
589#endif
590
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700591#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
592#error QCBOR_TYPE_BREAK macro value wrong
593#endif
594
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700595#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
596#error QCBOR_TYPE_DOUBLE macro value wrong
597#endif
598
599#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
600#error QCBOR_TYPE_FLOAT macro value wrong
601#endif
602
603/*
604 Decode true, false, floats, break...
605 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800606inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800607DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700608{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700609 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800610
Laurence Lundbladeee851742020-01-08 08:37:05 -0800611 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800612 // above make sure uAdditionalInfo values line up with uDataType values.
613 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
614 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800615
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800616 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800617 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
618 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800619
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700620 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700621 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
622 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700623 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700624 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700625 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
626 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700627 break;
628 case DOUBLE_PREC_FLOAT:
629 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700630 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700631 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800632
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700633 case CBOR_SIMPLEV_FALSE: // 20
634 case CBOR_SIMPLEV_TRUE: // 21
635 case CBOR_SIMPLEV_NULL: // 22
636 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700637 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700638 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800639
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700640 case CBOR_SIMPLEV_ONEBYTE: // 24
641 if(uNumber <= CBOR_SIMPLE_BREAK) {
642 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700643 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700644 goto Done;
645 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800646 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700647 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800648
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700649 default: // 0-19
650 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800651 /*
652 DecodeTypeAndNumber will make uNumber equal to
653 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
654 safe because the 2, 4 and 8 byte lengths of uNumber are in
655 the double/float cases above
656 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700657 pDecodedItem->val.uSimple = (uint8_t)uNumber;
658 break;
659 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800660
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700661Done:
662 return nReturn;
663}
664
665
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700666/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530667 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700668 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800669inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
670 int nMajorType,
671 uint64_t uStrLen,
672 UsefulInputBuf *pUInBuf,
673 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700674{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700675 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800676
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800677 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
678 // This check makes the casts to size_t below safe.
679
680 // 4 bytes less than the largest sizeof() so this can be tested by
681 // putting a SIZE_MAX length in the CBOR test input (no one will
682 // care the limit on strings is 4 bytes shorter).
683 if(uStrLen > SIZE_MAX-4) {
684 nReturn = QCBOR_ERR_STRING_TOO_LONG;
685 goto Done;
686 }
687
688 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530689 if(UsefulBuf_IsNULLC(Bytes)) {
690 // Failed to get the bytes for this string item
691 nReturn = QCBOR_ERR_HIT_END;
692 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700693 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530694
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800695 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530696 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800697 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530698 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700699 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530700 goto Done;
701 }
702 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800703 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530704 } else {
705 // Normal case with no string allocator
706 pDecodedItem->val.string = Bytes;
707 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800708 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800709 // Cast because ternary operator causes promotion to integer
710 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
711 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800712
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530713Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700714 return nReturn;
715}
716
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700717
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800718
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700719
720
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700721
722
Laurence Lundbladeee851742020-01-08 08:37:05 -0800723// Make sure the constants align as this is assumed by
724// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700725#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
726#error QCBOR_TYPE_ARRAY value not lined up with major type
727#endif
728#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
729#error QCBOR_TYPE_MAP value not lined up with major type
730#endif
731
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700732/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800733 This gets a single data item and decodes it including preceding
734 optional tagging. This does not deal with arrays and maps and nesting
735 except to decode the data item introducing them. Arrays and maps are
736 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800737
Laurence Lundbladeee851742020-01-08 08:37:05 -0800738 Errors detected here include: an array that is too long to decode,
739 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700740 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800741static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
742 QCBORItem *pDecodedItem,
743 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700744{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700745 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800746
Laurence Lundbladeee851742020-01-08 08:37:05 -0800747 /*
748 Get the major type and the number. Number could be length of more
749 bytes or the value depending on the major type nAdditionalInfo is
750 an encoding of the length of the uNumber and is needed to decode
751 floats and doubles
752 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800753 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700754 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800755 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800756
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700757 memset(pDecodedItem, 0, sizeof(QCBORItem));
758
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800759 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800760
Laurence Lundbladeee851742020-01-08 08:37:05 -0800761 // Error out here if we got into trouble on the type and number. The
762 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700763 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700764 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700765 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800766
Laurence Lundbladeee851742020-01-08 08:37:05 -0800767 // At this point the major type and the value are valid. We've got
768 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800769 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700770 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
771 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800772 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700773 nReturn = QCBOR_ERR_BAD_INT;
774 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800775 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700776 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700777 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800778
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700779 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
780 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800781 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
782 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
783 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
784 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530785 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700786 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800787 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700788 }
789 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800790
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700791 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
792 case CBOR_MAJOR_TYPE_MAP: // Major type 5
793 // Record the number of items in the array or map
794 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
795 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
796 goto Done;
797 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800798 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530799 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700800 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800801 // type conversion OK because of check above
802 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700803 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800804 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800805 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
806 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700807 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800808
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700809 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800810 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700811 nReturn = QCBOR_ERR_BAD_INT;
812 } else {
813 pDecodedItem->val.uTagV = uNumber;
814 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
815 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700816 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800817
Laurence Lundbladeee851742020-01-08 08:37:05 -0800818 case CBOR_MAJOR_TYPE_SIMPLE:
819 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800820 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700821 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800822
Laurence Lundbladeee851742020-01-08 08:37:05 -0800823 default:
824 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700825 nReturn = QCBOR_ERR_UNSUPPORTED;
826 break;
827 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800828
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700829Done:
830 return nReturn;
831}
832
833
834
835/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800836 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -0800837 individual chunk items together into one QCBORItem using the string
838 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800839
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530840 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700841 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800842static inline QCBORError
843GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700844{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700845 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700846
847 // Get pointer to string allocator. First use is to pass it to
848 // GetNext_Item() when option is set to allocate for *every* string.
849 // Second use here is to allocate space to coallese indefinite
850 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800851 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
852 &(me->StringAllocator) :
853 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800854
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700855 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800856 nReturn = GetNext_Item(&(me->InBuf),
857 pDecodedItem,
858 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700859 if(nReturn) {
860 goto Done;
861 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800862
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700863 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530864 // code in this function from here down can be eliminated. Run tests, except
865 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800866
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800867 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700868 const uint8_t uStringType = pDecodedItem->uDataType;
869 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700870 goto Done; // no need to do any work here on non-string types
871 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800872
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800873 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530874 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800875 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700876 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800877
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530878 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800879 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700880 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
881 goto Done;
882 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800883
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700884 // Loop getting chunk of indefinite string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700885 UsefulBufC FullString = NULLUsefulBufC;
886
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700887 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700888 // Get item for next chunk
889 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700890 // NULL string allocator passed here. Do not need to allocate
891 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -0800892 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700893 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700894 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700895 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800896
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530897 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700898 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800899 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700900 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530901 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700902 break;
903 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800904
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700905 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530906 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700907 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800908 if(StringChunkItem.uDataType != uStringType ||
909 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700910 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700911 break;
912 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800913
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530914 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800915 // The first time throurgh FullString.ptr is NULL and this is
916 // equivalent to StringAllocator_Allocate()
917 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
918 UNCONST_POINTER(FullString.ptr),
919 FullString.len + StringChunkItem.val.string.len);
920
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700921 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530922 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +0700923 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700924 break;
925 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800926
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700927 // Copy new string chunk at the end of string so far.
928 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700929 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800930
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800931 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
932 // Getting the item failed, clean up the allocated memory
933 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700934 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800935
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700936Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700937 return nReturn;
938}
939
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700940
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700941uint64_t ConvertTag(QCBORDecodeContext *me, uint16_t uTagVal) {
942 if(uTagVal < 0xfff0) {
943 return uTagVal;
944 } else {
945 // TODO constant and error check
946 int x = uTagVal - 0xfff0;
947 return me->auMappedTags[x];
948 }
949}
950
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700951/*
Laurence Lundblade59289e52019-12-30 13:44:37 -0800952 Gets all optional tag data items preceding a data item that is not an
953 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700954 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800955static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700956GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700957{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700958 // Stack usage: int/ptr: 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +0700959 QCBORError nReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700960
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700961 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
962 CBOR_TAG_INVALID16,
963 CBOR_TAG_INVALID16,
964 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700965
Laurence Lundblade59289e52019-12-30 13:44:37 -0800966 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700967 for(;;) {
968 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700969 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700970 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700971 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800972
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700973 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
974 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700975 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700976 break;
977 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800978
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700979 // Is there room for the tag in the tags list?
980 size_t uTagIndex;
981 for(uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700982 if(auTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700983 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700984 }
985 }
986 if(uTagIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700987 return QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700988 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800989
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700990 // Is the tag > 16 bits?
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700991 if(pDecodedItem->val.uTagV > CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700992 size_t uTagMapIndex;
993 // Is there room in the tag map?
994 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700995 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700996 break;
997 }
998 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
999 break;
1000 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001001 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001002 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1003 // No room for the tag
1004 return 97; // TODO error code
1005 }
1006
1007 // Cover the case where tag is new and were it is already in the map
1008 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
1009 auTags[uTagIndex] = (uint16_t)(uTagMapIndex + 0xfff0); // TODO proper constant and cast
1010
1011 } else {
1012 auTags[uTagIndex] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001013 }
1014 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001015
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001016Done:
1017 return nReturn;
1018}
1019
1020
1021/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001022 This layer takes care of map entries. It combines the label and data
1023 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001024 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001025static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001026GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001027{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001028 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001029 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001030 if(nReturn)
1031 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001032
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001033 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001034 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001035 goto Done;
1036 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001037
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001038 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1039 // In a map and caller wants maps decoded, not treated as arrays
1040
1041 if(DecodeNesting_TypeIsMap(&(me->nesting))) {
1042 // If in a map and the right decoding mode, get the label
1043
Laurence Lundbladeee851742020-01-08 08:37:05 -08001044 // Save label in pDecodedItem and get the next which will
1045 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001046 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001047 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001048 if(nReturn)
1049 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001050
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301051 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001052
1053 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1054 // strings are always good labels
1055 pDecodedItem->label.string = LabelItem.val.string;
1056 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1057 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001058 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001059 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1060 goto Done;
1061 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1062 pDecodedItem->label.int64 = LabelItem.val.int64;
1063 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1064 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1065 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1066 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1067 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1068 pDecodedItem->label.string = LabelItem.val.string;
1069 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1070 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1071 } else {
1072 // label is not an int or a string. It is an arrray
1073 // or a float or such and this implementation doesn't handle that.
1074 // Also, tags on labels are ignored.
1075 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1076 goto Done;
1077 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001078 }
1079 } else {
1080 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001081 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1082 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1083 goto Done;
1084 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001085 // Decoding a map as an array
1086 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001087 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1088 // Cast is needed because of integer promotion
1089 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001090 }
1091 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001092
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001093Done:
1094 return nReturn;
1095}
1096
1097
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001098static QCBORError
1099NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1100{
1101 *pbNextIsBreak = false;
1102 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
1103 // TODO: use the Peek method?
1104 QCBORItem Peek;
1105 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1106 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1107 if(uReturn != QCBOR_SUCCESS) {
1108 return uReturn;
1109 }
1110 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
1111 // It is not a break, rewind so it can be processed normally.
1112 UsefulInputBuf_Seek(pUIB, uPeek);
1113 } else {
1114 *pbNextIsBreak = true;
1115 }
1116 }
1117
1118 return QCBOR_SUCCESS;
1119}
1120
1121
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001122/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001123 An item was just consumed, now figure out if it was the
1124 end of an array or map that can be closed out. That
1125 may in turn close out another map or array.
1126 */
1127static QCBORError Ascender(QCBORDecodeContext *pMe)
1128{
1129 QCBORError uReturn;
1130
1131 /* This loops ascending nesting levels as long as there is ascending to do */
1132 while(1) {
1133 if(!DecodeNesting_IsAtTop(&(pMe->nesting)) && !DecodeNesting_IsIndefiniteLength(&(pMe->nesting))) {
1134 /* 1st Case: in a definite length array (not a CBOR sequence). Simply
1135 decrement the item count. If it doesn't go to zero, then all is done.
1136 If it does go to zero, the bottom of the loop ascends one nesting level
1137 and the loop continues.
1138 */
1139 DecodeNesting_DecrementX(&(pMe->nesting));
1140 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
1141 /* Didn't close out map or array; all work here is done */
1142 break;
1143 }
1144
1145 } else {
1146 /* 2nd, 3rd, 4th and 5th cases where a check for a following CBOR break must be checked for */
1147 bool bIsBreak = false;
1148 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1149 if(uReturn != QCBOR_SUCCESS) {
1150 goto Done;
1151 }
1152
1153 if(bIsBreak) {
1154 if(DecodeNesting_IsAtTop(&(pMe->nesting))) {
1155 /* 2nd case where a break occurs at the top level and thus
1156 in a CBOR sequence. Always an error because break is
1157 not inside an indefinite length map or array. */
1158 uReturn = QCBOR_ERR_BAD_BREAK;
1159 goto Done;
1160 } else {
1161 /* 3rd case, the normal end of an indefinite length map
1162 or array. The bottom of the loop ascends one nesting
1163 level and the loop continues. */
1164 }
1165 } else {
1166 /* 4th case where an indefinite length array is not closed out
1167 and 5th case which is just an item in a CBOR sequence. In either
1168 there is no close out so all work here is done.
1169 */
1170 break;
1171 }
1172 }
1173
1174 /* All items in the level have been consumed. */
1175
1176 /* But ascent in bounded mode is only by explicit call to QCBORDecode_ExitBoundedMode() */
1177 if(DecodeNesting_InBoundedMode(&(pMe->nesting))) {
1178 /* Set the count to zero for indefinite length arrays to indicate cursor is at end of bounded map / array */
1179 pMe->nesting.pCurrent->uCount = 0;
1180 break;
1181 }
1182
1183 /* Finally, actually ascend one level. */
1184 DecodeNesting_Ascend(&(pMe->nesting));
1185 }
1186
1187 uReturn = QCBOR_SUCCESS;
1188
1189Done:
1190 return uReturn;
1191}
1192
1193
1194/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001195 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001196 TODO: correct this comment
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001197 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001198static QCBORError
1199QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001200{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001201 QCBORError uReturn;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001202 /* === First figure out if at the end of traversal === */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001203
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001204 /* Case 1. Out of bytes to consume.
1205
1206 This is either the end of the top-level CBOR that was give
1207 to QCBORDecode_Init() or the end of a tag 24 bstr wrapped CBOR.
1208 It is detected by all bytes being consumed from the UsefulInputBuf.
1209
1210 To go back out of the tag 24 bstr wrapped item, the caller must
1211 explicitly call Exit() which will reset the UsefulInputBuf
1212 to the next highest bstr wrapped or the top level.
1213
1214 This is always the end condition that QCBORDecode_Finish()
1215 considers complete.
1216
1217 TODO: can the DecodeNesting_IsAtTop be removed? QCBORDecode_Finish()
1218 will perform this check.
1219
1220 */
Laurence Lundblade937ea812020-05-08 11:38:23 -07001221 /* For a pre-order traversal a non-error end occurs when there
1222 are no more bytes to consume and the nesting level is at the top.
1223 If it's not at the top, then the CBOR is not well formed. This error
1224 is caught elsewhere.
1225
1226 This handles the end of CBOR sequences as well as non-sequences. */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001227 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0 && DecodeNesting_IsAtTop(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001228 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001229 goto Done;
1230 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001231
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001232
1233 /* Case 2. End of map or array in bounded mode
1234
1235 The caller is attempting traveral of a bounded map or array and
1236 has got to the end of it.
1237
1238 The caller must explicitly exit the bounded mode map or array
1239 to get past this condition.
1240
1241 To complete a decode of the full input CBOR, the caller must
1242 exit all maps and arrays in bounded mode and this is never
1243 the successful end of decoding.
1244
1245 */
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001246 /* It is also an end of the input when in map mode and the cursor
Laurence Lundblade937ea812020-05-08 11:38:23 -07001247 is at the end of the map */
1248
1249
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001250 // This is to handle bounded mode
Laurence Lundblade937ea812020-05-08 11:38:23 -07001251 if(DecodeNesting_AtEnd(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001252 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001253 goto Done;
1254 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001255
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001256 /* === Not at the end; get another item === */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001257 uReturn = GetNext_MapEntry(me, pDecodedItem);
1258 if(uReturn) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001259 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001260 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301261
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001262 // Breaks ending arrays/maps are always processed at the end of this function.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301263 // They should never show up here.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301264 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001265 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301266 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301267 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001268
Laurence Lundblade6de37062018-10-15 12:22:42 +05301269 // Record the nesting level for this data item before processing any of
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301270 // decrementing and descending.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301271 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001272
Laurence Lundblade6de37062018-10-15 12:22:42 +05301273 // Process the item just received for descent or decrement, and
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001274 // ascend if decrements are enough to close out a definite length array/map
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001275 if(IsMapOrArray(pDecodedItem->uDataType) && pDecodedItem->val.uCount != 0) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001276 // If the new item is array or map, the nesting level descends
Laurence Lundblade0750fc42020-06-20 21:02:34 -07001277 uReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem->uDataType, pDecodedItem->val.uCount, 0L, 0L);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001278 // Maps and arrays do count in as items in the map/array that encloses
1279 // them so a decrement needs to be done for them too, but that is done
1280 // only when all the items in them have been processed, not when they
Laurence Lundblade9916b1b2019-09-07 22:33:25 -07001281 // are opened with the exception of an empty map or array.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001282 if(uReturn != QCBOR_SUCCESS) {
1283 goto Done;
1284 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001285 }
1286
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001287 if(!IsMapOrArray(pDecodedItem->uDataType) ||
1288 pDecodedItem->val.uCount == 0 || pDecodedItem->val.uCount == UINT16_MAX) {
1289 /* The following cases are handled here:
1290 - A non-aggregate like an integer or string
1291 - An empty definite length map or array
1292 - An indefinite length map or array that might be empty or might not.
1293 */
1294
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001295
1296
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001297 /* === Figure out if item got closed out maps or arrays === */
1298
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001299 /*
1300 This needs to decrement, check for end and ascend
1301 the tree until an an ascend is not possible or the bounded
1302 limit is reached or the end of the encoded CBOR input
1303 is reached. For
1304 definite length maps and arrays the end is by count. For
1305 indefinite it is by a break.
1306
1307 Also state needs to be set that can tell the code at the
1308 beginning of this function that the end was reached.
1309
1310 This is complicated...
1311
1312
1313 This will handle an indefinite length array
1314 inside a definte length array inside an indefinite
1315 length array...
1316
1317 */
1318
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001319 // Decrement the count of items in the enclosing map/array
1320 // If the count in the enclosing map/array goes to zero, that
Laurence Lundblade6de37062018-10-15 12:22:42 +05301321 // triggers a decrement in the map/array above that and
1322 // an ascend in nesting level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001323 /* If the just consumed item is at the end of a map or
1324 array ascend in the nesting tracking. That may
1325 in turn may be the end of the above nesting level
1326 and so on up to the end of the whole encoded CBOR.
1327
1328 Each level could be a definite or indefinte length
1329 map or array. These are handled very differently.
1330
1331 */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001332 uReturn = Ascender(me);
1333 if(uReturn) {
1334 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001335 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301336 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001337
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001338
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001339
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001340 /* === Tell the caller the nest level of the next item === */
1341
Laurence Lundblade6de37062018-10-15 12:22:42 +05301342 // Tell the caller what level is next. This tells them what maps/arrays
1343 // were closed out and makes it possible for them to reconstruct
1344 // the tree with just the information returned by GetNext
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07001345 // TODO: pull this into DecodeNesting_GetLevel
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001346 if(DecodeNesting_InBoundedMode(&(me->nesting)) && me->nesting.pCurrent->uCount == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001347 // At end of a map / array in map mode, so next nest is 0 to
1348 // indicate this end.
1349 pDecodedItem->uNextNestLevel = 0;
1350 } else {
1351 pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting));
1352 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001353
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001354Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001355 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001356 // Make sure uDataType and uLabelType are QCBOR_TYPE_NONE
1357 memset(pDecodedItem, 0, sizeof(QCBORItem));
1358 }
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001359 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001360}
1361
1362
Laurence Lundblade59289e52019-12-30 13:44:37 -08001363/*
1364 Mostly just assign the right data type for the date string.
1365 */
1366inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1367{
1368 // Stack Use: UsefulBuf 1 16
1369 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1370 return QCBOR_ERR_BAD_OPT_TAG;
1371 }
1372
1373 const UsefulBufC Temp = pDecodedItem->val.string;
1374 pDecodedItem->val.dateString = Temp;
1375 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1376 return QCBOR_SUCCESS;
1377}
1378
1379
1380/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001381 The epoch formatted date. Turns lots of different forms of encoding
1382 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001383 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001384static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001385{
1386 // Stack usage: 1
1387 QCBORError nReturn = QCBOR_SUCCESS;
1388
1389 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1390
1391 switch (pDecodedItem->uDataType) {
1392
1393 case QCBOR_TYPE_INT64:
1394 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1395 break;
1396
1397 case QCBOR_TYPE_UINT64:
1398 if(pDecodedItem->val.uint64 > INT64_MAX) {
1399 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1400 goto Done;
1401 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001402 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001403 break;
1404
1405 case QCBOR_TYPE_DOUBLE:
1406 {
1407 // This comparison needs to be done as a float before
1408 // conversion to an int64_t to be able to detect doubles
1409 // that are too large to fit into an int64_t. A double
1410 // has 52 bits of preceision. An int64_t has 63. Casting
1411 // INT64_MAX to a double actually causes a round up which
1412 // is bad and wrong for the comparison because it will
1413 // allow conversion of doubles that can't fit into a
1414 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1415 // the cutoff point as if that rounds up in conversion to
1416 // double it will still be less than INT64_MAX. 0x7ff is
1417 // picked because it has 11 bits set.
1418 //
1419 // INT64_MAX seconds is on the order of 10 billion years,
1420 // and the earth is less than 5 billion years old, so for
1421 // most uses this conversion error won't occur even though
1422 // doubles can go much larger.
1423 //
1424 // Without the 0x7ff there is a ~30 minute range of time
1425 // values 10 billion years in the past and in the future
1426 // where this this code would go wrong.
1427 const double d = pDecodedItem->val.dfnum;
1428 if(d > (double)(INT64_MAX - 0x7ff)) {
1429 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1430 goto Done;
1431 }
1432 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1433 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1434 }
1435 break;
1436
1437 default:
1438 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1439 goto Done;
1440 }
1441 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1442
1443Done:
1444 return nReturn;
1445}
1446
1447
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001448/*
1449 Mostly just assign the right data type for the bignum.
1450 */
1451inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1452{
1453 // Stack Use: UsefulBuf 1 -- 16
1454 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1455 return QCBOR_ERR_BAD_OPT_TAG;
1456 }
1457 const UsefulBufC Temp = pDecodedItem->val.string;
1458 pDecodedItem->val.bigNum = Temp;
1459 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1460 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1461 : QCBOR_TYPE_NEGBIGNUM);
1462 return QCBOR_SUCCESS;
1463}
1464
1465
Laurence Lundblade59289e52019-12-30 13:44:37 -08001466#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1467/*
1468 Decode decimal fractions and big floats.
1469
1470 When called pDecodedItem must be the array that is tagged as a big
1471 float or decimal fraction, the array that has the two members, the
1472 exponent and mantissa.
1473
1474 This will fetch and decode the exponent and mantissa and put the
1475 result back into pDecodedItem.
1476 */
1477inline static QCBORError
1478QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1479{
1480 QCBORError nReturn;
1481
1482 // --- Make sure it is an array; track nesting level of members ---
1483 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1484 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1485 goto Done;
1486 }
1487
1488 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001489 // definite length arrays, but not for indefnite. Instead remember
1490 // the nesting level the two integers must be at, which is one
1491 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001492 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1493
1494 // --- Is it a decimal fraction or a bigfloat? ---
1495 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1496 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1497
1498 // --- Get the exponent ---
1499 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001500 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001501 if(nReturn != QCBOR_SUCCESS) {
1502 goto Done;
1503 }
1504 if(exponentItem.uNestingLevel != nNestLevel) {
1505 // Array is empty or a map/array encountered when expecting an int
1506 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1507 goto Done;
1508 }
1509 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1510 // Data arriving as an unsigned int < INT64_MAX has been converted
1511 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1512 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1513 // will be too large for this to handle and thus an error that will
1514 // get handled in the next else.
1515 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1516 } else {
1517 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1518 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1519 goto Done;
1520 }
1521
1522 // --- Get the mantissa ---
1523 QCBORItem mantissaItem;
1524 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1525 if(nReturn != QCBOR_SUCCESS) {
1526 goto Done;
1527 }
1528 if(mantissaItem.uNestingLevel != nNestLevel) {
1529 // Mantissa missing or map/array encountered when expecting number
1530 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1531 goto Done;
1532 }
1533 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1534 // Data arriving as an unsigned int < INT64_MAX has been converted
1535 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1536 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1537 // will be too large for this to handle and thus an error that
1538 // will get handled in an else below.
1539 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1540 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1541 // Got a good big num mantissa
1542 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1543 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001544 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1545 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1546 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001547 } else {
1548 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1549 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1550 goto Done;
1551 }
1552
1553 // --- Check that array only has the two numbers ---
1554 if(mantissaItem.uNextNestLevel == nNestLevel) {
1555 // Extra items in the decimal fraction / big num
1556 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1557 goto Done;
1558 }
1559
1560Done:
1561
1562 return nReturn;
1563}
1564#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1565
1566
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001567
1568/*
1569 */
1570inline static QCBORError DecodeURI(QCBORItem *pDecodedItem)
1571{
1572 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1573 return QCBOR_ERR_BAD_OPT_TAG;
1574 }
1575 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1576 return QCBOR_SUCCESS;
1577}
1578
1579
1580inline static QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
1581{
1582 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1583 return QCBOR_ERR_BAD_OPT_TAG;
1584 }
1585 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
1586 return QCBOR_SUCCESS;
1587}
1588
1589
1590inline static QCBORError DecodeB64(QCBORItem *pDecodedItem)
1591{
1592 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1593 return QCBOR_ERR_BAD_OPT_TAG;
1594 }
1595 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
1596 return QCBOR_SUCCESS;
1597}
1598
1599
1600inline static QCBORError DecodeRegex(QCBORItem *pDecodedItem)
1601{
1602 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1603 return QCBOR_ERR_BAD_OPT_TAG;
1604 }
1605 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
1606 return QCBOR_SUCCESS;
1607}
1608
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001609inline static QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
1610{
1611 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1612 return QCBOR_ERR_BAD_OPT_TAG;
1613 }
1614 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
1615 return QCBOR_SUCCESS;
1616}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001617
1618inline static QCBORError DecodeMIME(QCBORItem *pDecodedItem)
1619{
1620 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1621 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
1622 } else if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1623 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1624 } else {
1625 return QCBOR_ERR_BAD_OPT_TAG;
1626 }
1627 return QCBOR_SUCCESS;
1628}
1629
1630
1631/*
1632 */
1633inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1634{
1635 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1636 return QCBOR_ERR_BAD_OPT_TAG;
1637 }
1638 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
1639 return QCBOR_SUCCESS;
1640}
1641
1642
Laurence Lundblade59289e52019-12-30 13:44:37 -08001643/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001644 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001645 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001646QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001647QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001648{
1649 QCBORError nReturn;
1650
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001651 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001652 if(nReturn != QCBOR_SUCCESS) {
1653 goto Done;
1654 }
1655
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001656 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
1657 switch(pDecodedItem->uTags[i] ) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001658
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001659 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001660 nReturn = DecodeDateString(pDecodedItem);
1661 break;
1662
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001663 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001664 nReturn = DecodeDateEpoch(pDecodedItem);
1665 break;
1666
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001667 case CBOR_TAG_POS_BIGNUM:
1668 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001669 nReturn = DecodeBigNum(pDecodedItem);
1670 break;
1671
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001672 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1673 case CBOR_TAG_DECIMAL_FRACTION:
1674 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001675 // For aggregate tagged types, what goes into pTags is only collected
1676 // from the surrounding data item, not the contents, so pTags is not
1677 // passed on here.
1678
1679 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1680 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001681 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001682
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001683 case CBOR_TAG_CBOR:
1684 nReturn = DecodeWrappedCBOR(pDecodedItem);
1685 break;
1686
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001687 case CBOR_TAG_URI:
1688 nReturn = DecodeURI(pDecodedItem);
1689 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001690
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001691 case CBOR_TAG_B64URL:
1692 nReturn = DecodeB64URL(pDecodedItem);
1693 break;
1694
1695 case CBOR_TAG_B64:
1696 nReturn = DecodeB64(pDecodedItem);
1697 break;
1698
1699 case CBOR_TAG_MIME:
1700 case CBOR_TAG_BINARY_MIME:
1701 nReturn = DecodeMIME(pDecodedItem);
1702 break;
1703
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001704 case CBOR_TAG_REGEX:
1705 nReturn = DecodeRegex(pDecodedItem);
1706 break;
1707
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001708 case CBOR_TAG_BIN_UUID:
1709 nReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001710 break;
1711
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001712 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001713 // The end of the tag list or no tags
1714 // Successful exit from the loop.
1715 goto Done;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001716
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001717 default:
1718 // A tag that is not understood
1719 // A successful exit from the loop
1720 goto Done;
1721
1722 }
1723 if(nReturn != QCBOR_SUCCESS) {
1724 goto Done;
1725 }
Laurence Lundblade59289e52019-12-30 13:44:37 -08001726 }
1727
1728Done:
1729 if(nReturn != QCBOR_SUCCESS) {
1730 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1731 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1732 }
1733 return nReturn;
1734}
1735
1736
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001737QCBORError QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
1738{
1739 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
1740
1741 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
1742
1743 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
1744
1745 return uErr;
1746}
1747
1748
Laurence Lundblade59289e52019-12-30 13:44:37 -08001749/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001750 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001751 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001752QCBORError
1753QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1754 QCBORItem *pDecodedItem,
1755 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001756{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001757 QCBORError nReturn;
1758
1759 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
1760 if(nReturn != QCBOR_SUCCESS) {
1761 return nReturn;
1762 }
1763
1764 if(pTags != NULL) {
1765 pTags->uNumUsed = 0;
1766 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001767 if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001768 break;
1769 }
1770 if(pTags->uNumUsed >= pTags->uNumAllocated) {
1771 return QCBOR_ERR_TOO_MANY_TAGS;
1772 }
1773 pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]);
1774 pTags->uNumUsed++;
1775 }
1776 }
1777
1778 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001779}
1780
1781
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001782/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301783 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301784 next one down. If a layer has no work to do for a particular item
1785 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001786
Laurence Lundblade59289e52019-12-30 13:44:37 -08001787 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1788 tagged data items, turning them into the local C representation.
1789 For the most simple it is just associating a QCBOR_TYPE with the data. For
1790 the complex ones that an aggregate of data items, there is some further
1791 decoding and a little bit of recursion.
1792
1793 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301794 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301795 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001796 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001797
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301798 - GetNext_MapEntry -- This handles the combining of two
1799 items, the label and the data, that make up a map entry.
1800 It only does work on maps. It combines the label and data
1801 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001802
Laurence Lundblade59289e52019-12-30 13:44:37 -08001803 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1804 tags into bit flags associated with the data item. No actual decoding
1805 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001806
Laurence Lundblade59289e52019-12-30 13:44:37 -08001807 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301808 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301809 string allocater to create contiguous space for the item. It
1810 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001811
Laurence Lundblade59289e52019-12-30 13:44:37 -08001812 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1813 atomic data item has a "major type", an integer "argument" and optionally
1814 some content. For text and byte strings, the content is the bytes
1815 that make up the string. These are the smallest data items that are
1816 considered to be well-formed. The content may also be other data items in
1817 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001818
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001819 Roughly this takes 300 bytes of stack for vars. Need to
1820 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001821
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301822 */
1823
1824
1825/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001826 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001827 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001828int QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001829 const QCBORItem *pItem,
1830 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001831{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001832 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++ ) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001833 if(pItem->uTags[i] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001834 break;
1835 }
1836 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
1837 return 1;
1838 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001839 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001840
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001841 return 0;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001842}
1843
1844
1845/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001846 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001847 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001848QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001849{
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001850 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001851
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001852 // Error out if all the maps/arrays are not closed out
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001853 if(!DecodeNesting_IsAtTop(&(me->nesting))) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001854 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1855 goto Done;
1856 }
1857
1858 // Error out if not all the bytes are consumed
1859 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1860 nReturn = QCBOR_ERR_EXTRA_BYTES;
1861 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001862
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001863Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301864 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001865 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001866 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001867
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001868 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001869}
1870
1871
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001872/*
1873Public function, see header qcbor/qcbor_decode.h file
1874*/
Laurence Lundblade2b843b52020-06-16 20:51:03 -07001875uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
1876 const QCBORItem *pItem,
1877 unsigned int uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001878{
1879 if(uIndex > QCBOR_MAX_TAGS_PER_ITEM) {
1880 return CBOR_TAG_INVALID16;
1881 } else if(pItem->uTags[uIndex] <= QCBOR_LAST_UNMAPPED_TAG) {
1882 return pItem->uTags[uIndex];
1883 } else if(pItem->uTags[uIndex] < QCBOR_NUM_MAPPED_TAGS + QCBOR_LAST_UNMAPPED_TAG) {
1884 return pMe->auMappedTags[pItem->uTags[uIndex] - QCBOR_LAST_UNMAPPED_TAG];
1885 } else {
1886 return CBOR_TAG_INVALID16;
1887 }
1888}
1889
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001890
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001891/*
1892
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001893Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001894
Laurence Lundbladeee851742020-01-08 08:37:05 -08001895 - Hit end of input before it was expected while decoding type and
1896 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001897
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001898 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001899
Laurence Lundbladeee851742020-01-08 08:37:05 -08001900 - Hit end of input while decoding a text or byte string
1901 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001902
Laurence Lundbladeee851742020-01-08 08:37:05 -08001903 - Encountered conflicting tags -- e.g., an item is tagged both a date
1904 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001905
Laurence Lundbladeee851742020-01-08 08:37:05 -08001906 - Encontered an array or mapp that has too many items
1907 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001908
Laurence Lundbladeee851742020-01-08 08:37:05 -08001909 - Encountered array/map nesting that is too deep
1910 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001911
Laurence Lundbladeee851742020-01-08 08:37:05 -08001912 - An epoch date > INT64_MAX or < INT64_MIN was encountered
1913 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001914
Laurence Lundbladeee851742020-01-08 08:37:05 -08001915 - The type of a map label is not a string or int
1916 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001917
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001918 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001919
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001920 */
1921
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001922
1923
Laurence Lundbladef6531662018-12-04 10:42:22 +09001924
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001925/* ===========================================================================
1926 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001927
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001928 This implements a simple sting allocator for indefinite length
1929 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
1930 implements the function type QCBORStringAllocate and allows easy
1931 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09001932
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001933 This particular allocator is built-in for convenience. The caller
1934 can implement their own. All of this following code will get
1935 dead-stripped if QCBORDecode_SetMemPool() is not called.
1936
1937 This is a very primitive memory allocator. It does not track
1938 individual allocations, only a high-water mark. A free or
1939 reallocation must be of the last chunk allocated.
1940
1941 The size of the pool and offset to free memory are packed into the
1942 first 8 bytes of the memory pool so we don't have to keep them in
1943 the decode context. Since the address of the pool may not be
1944 aligned, they have to be packed and unpacked as if they were
1945 serialized data of the wire or such.
1946
1947 The sizes packed in are uint32_t to be the same on all CPU types
1948 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08001949 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001950
1951
Laurence Lundbladeee851742020-01-08 08:37:05 -08001952static inline int
1953MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001954{
1955 // Use of UsefulInputBuf is overkill, but it is convenient.
1956 UsefulInputBuf UIB;
1957
Laurence Lundbladeee851742020-01-08 08:37:05 -08001958 // Just assume the size here. It was checked during SetUp so
1959 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001960 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
1961 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
1962 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
1963 return UsefulInputBuf_GetError(&UIB);
1964}
1965
1966
Laurence Lundbladeee851742020-01-08 08:37:05 -08001967static inline int
1968MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001969{
1970 // Use of UsefulOutBuf is overkill, but convenient. The
1971 // length check performed here is useful.
1972 UsefulOutBuf UOB;
1973
1974 UsefulOutBuf_Init(&UOB, Pool);
1975 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
1976 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
1977 return UsefulOutBuf_GetError(&UOB);
1978}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001979
1980
1981/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001982 Internal function for an allocation, reallocation free and destuct.
1983
1984 Having only one function rather than one each per mode saves space in
1985 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001986
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001987 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1988 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001989static UsefulBuf
1990MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001991{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001992 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001993
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001994 uint32_t uPoolSize;
1995 uint32_t uFreeOffset;
1996
1997 if(uNewSize > UINT32_MAX) {
1998 // This allocator is only good up to 4GB. This check should
1999 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2000 goto Done;
2001 }
2002 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2003
2004 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2005 goto Done;
2006 }
2007
2008 if(uNewSize) {
2009 if(pMem) {
2010 // REALLOCATION MODE
2011 // Calculate pointer to the end of the memory pool. It is
2012 // assumed that pPool + uPoolSize won't wrap around by
2013 // assuming the caller won't pass a pool buffer in that is
2014 // not in legitimate memory space.
2015 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2016
2017 // Check that the pointer for reallocation is in the range of the
2018 // pool. This also makes sure that pointer math further down
2019 // doesn't wrap under or over.
2020 if(pMem >= pPool && pMem < pPoolEnd) {
2021 // Offset to start of chunk for reallocation. This won't
2022 // wrap under because of check that pMem >= pPool. Cast
2023 // is safe because the pool is always less than UINT32_MAX
2024 // because of check in QCBORDecode_SetMemPool().
2025 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2026
2027 // Check to see if the allocation will fit. uPoolSize -
2028 // uMemOffset will not wrap under because of check that
2029 // pMem is in the range of the uPoolSize by check above.
2030 if(uNewSize <= uPoolSize - uMemOffset) {
2031 ReturnValue.ptr = pMem;
2032 ReturnValue.len = uNewSize;
2033
2034 // Addition won't wrap around over because uNewSize was
2035 // checked to be sure it is less than the pool size.
2036 uFreeOffset = uMemOffset + uNewSize32;
2037 }
2038 }
2039 } else {
2040 // ALLOCATION MODE
2041 // uPoolSize - uFreeOffset will not underflow because this
2042 // pool implementation makes sure uFreeOffset is always
2043 // smaller than uPoolSize through this check here and
2044 // reallocation case.
2045 if(uNewSize <= uPoolSize - uFreeOffset) {
2046 ReturnValue.len = uNewSize;
2047 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002048 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002049 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002050 }
2051 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002052 if(pMem) {
2053 // FREE MODE
2054 // Cast is safe because of limit on pool size in
2055 // QCBORDecode_SetMemPool()
2056 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2057 } else {
2058 // DESTRUCT MODE
2059 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002060 }
2061 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002062
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002063 UsefulBuf Pool = {pPool, uPoolSize};
2064 MemPool_Pack(Pool, uFreeOffset);
2065
2066Done:
2067 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002068}
2069
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002070
Laurence Lundbladef6531662018-12-04 10:42:22 +09002071/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002072 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002073 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002074QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2075 UsefulBuf Pool,
2076 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002077{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002078 // The pool size and free mem offset are packed into the beginning
2079 // of the pool memory. This compile time check make sure the
2080 // constant in the header is correct. This check should optimize
2081 // down to nothing.
2082 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07002083 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002084 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002085
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002086 // The pool size and free offset packed in to the beginning of pool
2087 // memory are only 32-bits. This check will optimize out on 32-bit
2088 // machines.
2089 if(Pool.len > UINT32_MAX) {
2090 return QCBOR_ERR_BUFFER_TOO_LARGE;
2091 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002092
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002093 // This checks that the pool buffer given is big enough.
2094 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
2095 return QCBOR_ERR_BUFFER_TOO_SMALL;
2096 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002097
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002098 pMe->StringAllocator.pfAllocator = MemPool_Function;
2099 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2100 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002101
Laurence Lundblade30816f22018-11-10 13:40:22 +07002102 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002103}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002104
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002105
2106
Laurence Lundblade1341c592020-04-11 14:19:05 -07002107#include <stdio.h>
2108void printdecode(QCBORDecodeContext *pMe, const char *szName)
2109{
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002110 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 -07002111 szName,
2112 (uint32_t)pMe->InBuf.cursor,
2113 (uint32_t)pMe->InBuf.UB.len);
Laurence Lundblade64b607e2020-05-13 13:05:57 -07002114 for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002115 if(&(pMe->nesting.pMapsAndArrays[i]) > pMe->nesting.pCurrent) {
2116 break;
2117 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002118 printf("%2s %2d %5d %s %6u %5d %d %5d\n",
2119 pMe->nesting.pCurrentBounded == &(pMe->nesting.pMapsAndArrays[i]) ? "->": " ",
Laurence Lundblade1341c592020-04-11 14:19:05 -07002120 i,
2121 pMe->nesting.pMapsAndArrays[i].uCount,
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002122 pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_MAP ? "map " :
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002123 (pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_ARRAY ? "array" :
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002124 (pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_BYTE_STRING ? "bstr " :
2125 (pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_NONE ? "none " : "?????"))),
Laurence Lundblade1341c592020-04-11 14:19:05 -07002126 pMe->nesting.pMapsAndArrays[i].uOffset,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002127 pMe->nesting.pMapsAndArrays[i].uSaveCount,
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002128 pMe->nesting.pMapsAndArrays[i].bBoundedMode,
2129 pMe->nesting.pMapsAndArrays[i].uPreviousEndOffset
Laurence Lundblade1341c592020-04-11 14:19:05 -07002130 );
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002131
Laurence Lundblade1341c592020-04-11 14:19:05 -07002132 }
Laurence Lundblade64b607e2020-05-13 13:05:57 -07002133 printf("\n");
Laurence Lundblade1341c592020-04-11 14:19:05 -07002134}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002135
2136
2137/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002138 Consume an entire map or array (and do next to
2139 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002140 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002141static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002142ConsumeItem(QCBORDecodeContext *pMe,
2143 const QCBORItem *pItemToConsume,
2144 uint_fast8_t *puNextNestLevel)
2145{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002146 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002147 QCBORItem Item;
2148
2149 printdecode(pMe, "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002150
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002151 if(IsMapOrArray(pItemToConsume->uDataType)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002152 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002153
Laurence Lundblade1341c592020-04-11 14:19:05 -07002154 /* This works for definite and indefinite length
2155 * maps and arrays by using the nesting level
2156 */
2157 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002158 uReturn = QCBORDecode_GetNext(pMe, &Item);
2159 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002160 goto Done;
2161 }
2162 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002163
Laurence Lundblade1341c592020-04-11 14:19:05 -07002164 if(puNextNestLevel != NULL) {
2165 *puNextNestLevel = Item.uNextNestLevel;
2166 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002167 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002168
Laurence Lundblade1341c592020-04-11 14:19:05 -07002169 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002170 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002171 if(puNextNestLevel != NULL) {
2172 /* Just pass the nesting level through */
2173 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2174 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002175 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002176 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002177
2178Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002179 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002180}
2181
2182
Laurence Lundblade1341c592020-04-11 14:19:05 -07002183/* Return true if the labels in Item1 and Item2 are the same.
2184 Works only for integer and string labels. Returns false
2185 for any other type. */
2186static inline bool
2187MatchLabel(QCBORItem Item1, QCBORItem Item2)
2188{
2189 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2190 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2191 return true;
2192 }
2193 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002194 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002195 return true;
2196 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002197 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002198 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2199 return true;
2200 }
2201 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2202 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2203 return true;
2204 }
2205 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002206
Laurence Lundblade1341c592020-04-11 14:19:05 -07002207 /* Other label types are never matched */
2208 return false;
2209}
2210
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002211
2212/*
2213 Returns true if Item1 and Item2 are the same type
2214 or if either are of QCBOR_TYPE_ANY.
2215 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002216static inline bool
2217MatchType(QCBORItem Item1, QCBORItem Item2)
2218{
2219 if(Item1.uDataType == Item2.uDataType) {
2220 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002221 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002222 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002223 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002224 return true;
2225 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002226 return false;
2227}
2228
2229
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002230/**
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002231 \brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002232
2233 @param[in] pMe The decode context to search.
2234 @param[in,out] pItemArray The items to search for and the items found.
2235 @param[in] pCBContext Context for the not-found item call back
2236 @param[in] pfCallback Function to call on items not matched in pItemArray
2237
2238 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2239
2240 @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.
2241
2242 @retval QCBOR_ERR_UNEXPECTED_TYPE The label was matched, but not the type.
2243
2244 @retval Also errors returned by QCBORDecode_GetNext().
2245
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002246 On input pItemArray contains a list of labels and data types
2247 of items to be found.
2248
2249 On output the fully retrieved items are filled in with
2250 values and such. The label was matched, so it never changes.
2251
2252 If an item was not found, its data type is set to none.
2253
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002254 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002255static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002256MapSearch(QCBORDecodeContext *pMe,
2257 QCBORItem *pItemArray,
2258 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002259 void *pCBContext,
2260 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002261{
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002262 QCBORError uReturn;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002263
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002264 QCBORDecodeNesting SaveNesting;
2265 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002266
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002267 // Reposition to search from the start of the map / array
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002268 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrentBounded->uOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002269
2270 /* Loop over all the items in the map. They could be
2271 * deeply nested and this should handle both definite
2272 * and indefinite length maps and arrays, so this
2273 * adds some complexity. */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002274 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002275
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002276 uint_fast8_t uNextNestLevel;
2277
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002278 uint64_t uFoundItemBitMap = 0;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002279
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002280 /* Iterate over items in the map / array */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002281 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002282 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002283 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002284
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002285 /* Get the item */
2286 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002287 uReturn = QCBORDecode_GetNext(pMe, &Item);
2288 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002289 /* Got non-well-formed CBOR */
2290 goto Done;
2291 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002292
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002293 /* See if item has one of the labels that are of interest */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002294 int nIndex;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002295 QCBORItem *pIterator;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002296 for(pIterator = pItemArray, nIndex = 0; pIterator->uLabelType != 0; pIterator++, nIndex++) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002297 if(MatchLabel(Item, *pIterator)) {
2298 // A label match has been found
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002299 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2300 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002301 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002302 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002303 /* Also try to match its type */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002304 if(!MatchType(Item, *pIterator)) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002305 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002306 goto Done;
2307 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002308
2309 /* Successful match. Return the item. */
2310 *pIterator = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002311 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002312 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002313 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002314 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002315 } else {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002316 /* Call the callback on unmatched labels */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002317 /* It is tempting to do duplicate detection here, but that would
2318 require dynamic memory allocation because the number of labels
2319 that might be encountered is unbounded.
2320 */
2321 if(pfCallback) {
2322 uReturn = (*pfCallback)(pCBContext, &Item);
2323 if(uReturn != QCBOR_SUCCESS) {
2324 goto Done;
2325 }
2326 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002327 }
2328 }
2329
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002330 /* Consume the item whether matched or not. This
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002331 does the work of traversing maps and array and
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002332 everything in them. In this loop only the
2333 items at the current nesting level are examined
2334 to match the labels. */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002335 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
2336 if(uReturn) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002337 goto Done;
2338 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002339
2340 } while (uNextNestLevel >= uMapNestLevel);
2341
2342
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002343 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002344
2345 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
2346 // Cast OK because encoded CBOR is limited to UINT32_MAX
2347 pMe->uMapEndOffset = (uint32_t)uEndOffset;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002348
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002349 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002350 int i;
2351 QCBORItem *pIterator;
2352 for(pIterator = pItemArray, i = 0; pIterator->uLabelType != 0; pIterator++, i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002353 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002354 pIterator->uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002355 }
2356 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002357
2358Done:
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002359 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002360
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002361 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002362}
2363
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002364
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002365/*
2366Public function, see header qcbor/qcbor_decode.h file
2367*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002368void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2369 int64_t nLabel,
2370 uint8_t uQcborType,
2371 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002372{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002373 if(pMe->uLastError != QCBOR_SUCCESS) {
2374 return;
2375 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002376
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002377 QCBORItem OneItemSeach[2];
2378 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2379 OneItemSeach[0].label.int64 = nLabel;
2380 OneItemSeach[0].uDataType = uQcborType;
2381 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002382
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002383 QCBORError nReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002384 if(nReturn) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002385 pMe->uLastError = (uint8_t)nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002386 }
2387
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002388 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
2389 pMe->uLastError = QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002390 }
2391
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002392 *pItem = OneItemSeach[0];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002393}
2394
2395
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002396/*
2397Public function, see header qcbor/qcbor_decode.h file
2398*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002399void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2400 const char *szLabel,
2401 uint8_t uQcborType,
2402 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002403{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002404 if(pMe->uLastError != QCBOR_SUCCESS) {
2405 return;
2406 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002407
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002408 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002409 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2410 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2411 OneItemSeach[0].uDataType = uQcborType;
2412 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002413
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002414 QCBORError nReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002415 if(nReturn) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07002416 pMe->uLastError = (uint8_t)nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002417 }
2418
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002419 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07002420 pMe->uLastError = QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002421 }
2422
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002423 *pItem = OneItemSeach[0];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002424}
2425
2426
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002427/**
2428 @param[in] TagSpec Specification for matching tags.
2429 @param[in] uDataType A QCBOR data type
2430
2431 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2432 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
2433
2434 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered tag value.
2435 */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002436static QCBORError CheckTagRequirement(const TagSpecification TagSpec, uint8_t uDataType)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002437{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002438 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG) {
2439 /* Must match the tag */
2440 if(uDataType == TagSpec.uTaggedType) {
2441 return QCBOR_SUCCESS;
2442 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002443 } else {
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002444 /* QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE or QCBOR_TAGSPEC_MATCH_EITHER */
2445 /* Must check all the possible types for the tag content */
2446 for(size_t i = 0; i < sizeof(TagSpec.uAllowedContentTypes); i++) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002447 if(uDataType == TagSpec.uAllowedContentTypes[i]) {
2448 return QCBOR_SUCCESS;
2449 }
2450 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002451 /* Didn't match any of the tag content types */
2452 /* Check the tag for the either case */
2453 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_EITHER) {
2454 if(uDataType == TagSpec.uTaggedType) {
2455 return QCBOR_SUCCESS;
2456 }
2457 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002458 }
2459
2460 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002461}
2462
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002463
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002464// Semi-private
2465// TODO: inline or collapse with QCBORDecode_GetTaggedStringInMapN?
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002466void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2467 int64_t nLabel,
2468 TagSpecification TagSpec,
2469 QCBORItem *pItem)
2470{
2471 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2472 if(pMe->uLastError != QCBOR_SUCCESS) {
2473 return;
2474 }
2475
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002476 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002477}
2478
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002479// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002480void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2481 const char *szLabel,
2482 TagSpecification TagSpec,
2483 QCBORItem *pItem)
2484{
2485 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2486 if(pMe->uLastError != QCBOR_SUCCESS) {
2487 return;
2488 }
2489
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002490 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002491}
2492
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002493// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002494void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2495 int64_t nLabel,
2496 TagSpecification TagSpec,
2497 UsefulBufC *pString)
2498{
2499 QCBORItem Item;
2500 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2501 if(pMe->uLastError == QCBOR_SUCCESS) {
2502 *pString = Item.val.string;
2503 }
2504}
2505
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002506// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002507void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2508 const char * szLabel,
2509 TagSpecification TagSpec,
2510 UsefulBufC *pString)
2511{
2512 QCBORItem Item;
2513 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2514 if(pMe->uLastError == QCBOR_SUCCESS) {
2515 *pString = Item.val.string;
2516 }
2517}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002518
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002519/*
2520Public function, see header qcbor/qcbor_decode.h file
2521*/
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002522QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2523{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002524 return MapSearch(pCtx, pItemList, NULL, NULL, NULL);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002525}
2526
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002527/*
2528Public function, see header qcbor/qcbor_decode.h file
2529*/
2530QCBORError QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pCtx,
2531 QCBORItem *pItemList,
2532 void *pCallbackCtx,
2533 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002534{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002535 return MapSearch(pCtx, pItemList, NULL, pCallbackCtx, pfCB);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002536}
2537
2538
Laurence Lundblade34691b92020-05-18 22:25:25 -07002539static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002540{
Laurence Lundblade34691b92020-05-18 22:25:25 -07002541 if(pMe->uLastError != QCBOR_SUCCESS) {
2542 // Already in error state; do nothing.
2543 return;
2544 }
2545
2546 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002547 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002548 if(pMe->uLastError != QCBOR_SUCCESS) {
2549 return;
2550 }
2551
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002552 /* Need to get the current pre-order nesting level and cursor to be
2553 at the first item in the map/array just entered.
2554
2555 Also need to current map nesting level and start cursor to
2556 be at the right place.
2557
2558 The UsefulInBuf offset could be anywhere, so no assumption is
2559 made about it.
2560
2561 No assumption is made about the pre-order nesting level either.
2562
2563 However the map mode nesting level is assumed to be one above
2564 the map level that is being entered.
2565 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002566 /* Seek to the data item that is the map or array */
2567 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002568 pMe->nesting.pCurrent = pMe->nesting.pCurrentBounded; // TODO: part of DecodeNesting
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002569
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002570 // TODO: check error?
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002571 QCBORDecode_EnterBoundedMode(pMe, pSearch->uDataType);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002572
Laurence Lundblade34691b92020-05-18 22:25:25 -07002573 printdecode(pMe, "FinishEnter");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002574}
2575
2576
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002577/*
2578Public function, see header qcbor/qcbor_decode.h file
2579*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002580void QCBORDecode_EnterMapInMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002581{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002582 QCBORItem OneItemSeach[2];
2583 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2584 OneItemSeach[0].label.int64 = nLabel;
2585 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2586 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002587
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002588 /* The map to enter was found, now finish of entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002589 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002590}
2591
2592
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002593/*
2594Public function, see header qcbor/qcbor_decode.h file
2595*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002596void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002597{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002598 QCBORItem OneItemSeach[2];
2599 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2600 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2601 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2602 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002603
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002604 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002605}
2606
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002607/*
2608Public function, see header qcbor/qcbor_decode.h file
2609*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002610void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002611{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002612 QCBORItem OneItemSeach[2];
2613 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2614 OneItemSeach[0].label.int64 = nLabel;
2615 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2616 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002617
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002618 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002619}
2620
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002621/*
2622Public function, see header qcbor/qcbor_decode.h file
2623*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07002624void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2625{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002626 QCBORItem OneItemSeach[2];
2627 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2628 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2629 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2630 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002631
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002632 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002633}
2634
2635
2636
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002637/* Next item must be map or this generates an error */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002638void QCBORDecode_EnterBoundedMode(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002639{
Laurence Lundblade34691b92020-05-18 22:25:25 -07002640 if(pMe->uLastError != QCBOR_SUCCESS) {
2641 // Already in error state; do nothing.
2642 return;
2643 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002644
2645 /* Get the data item that is the map that is being searched */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002646 QCBORItem Item;
Laurence Lundblade986017c2020-05-23 19:25:02 -07002647 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002648 if(pMe->uLastError != QCBOR_SUCCESS) {
2649 return;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002650 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002651 if(Item.uDataType != uType) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07002652 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
2653 return;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002654 }
2655
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002656 DecodeNesting_EnterBoundedMode(&(pMe->nesting), UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002657
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002658 // TODO: restrict input to less than this or some other invalidation strategy.
2659 pMe->uMapEndOffset = 0xffffffff; // Invalidate the cached map end.
2660
Laurence Lundblade34691b92020-05-18 22:25:25 -07002661 printdecode(pMe, "EnterMapModeDone");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002662}
2663
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002664
2665// Semi-private function
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002666void QCBORDecode_ExitBoundedMode(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002667{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002668 if(pMe->uLastError != QCBOR_SUCCESS) {
2669 // Already in error state; do nothing.
2670 return;
2671 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002672
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002673 printdecode(pMe, "start exit");
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002674
2675 QCBORError uErr = QCBOR_SUCCESS;
2676
2677 if(!DecodeNesting_BoundedIsType(&(pMe->nesting), uType)){
2678 uErr = QCBOR_ERR_CLOSE_MISMATCH;
2679 goto Done;
2680 }
2681
2682 /* Have to set the offset to the end of the map/array
2683 that is being exited. If there is no cached value,
2684 from previous map search, then do a dummy search. */
2685 if(pMe->uMapEndOffset == 0xffffffff) {
2686 QCBORItem Dummy;
2687 Dummy.uLabelType = QCBOR_TYPE_NONE;
2688 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
2689 if(uErr != QCBOR_SUCCESS) {
2690 goto Done;
2691 }
2692 }
2693 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->uMapEndOffset);
2694 pMe->uMapEndOffset = 0xffffffff; // Invalidate the cached map end.
2695
2696 /* Before acending, mark this level as no longer in bound mode. */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002697 pMe->nesting.pCurrentBounded->bBoundedMode = false;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002698
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002699 // Always go up one level
2700 // Need error check to know level is bounded mode and not at top level
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002701 pMe->nesting.pCurrent = pMe->nesting.pCurrentBounded - 1; // TODO error check
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002702
2703 uErr = Ascender(pMe);
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002704 if(uErr != QCBOR_SUCCESS) {
2705 goto Done;
2706 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002707
2708 /* Also ascend to the next higest bounded mode level if
2709 there is one. */
2710 while(1) {
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002711 pMe->nesting.pCurrentBounded--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002712 if(DecodeNesting_InBoundedMode(&(pMe->nesting))) {
2713 break;
2714 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002715 if(pMe->nesting.pCurrentBounded == &(pMe->nesting.pMapsAndArrays[0])) {
2716 pMe->nesting.pCurrentBounded = NULL;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002717 break;
2718 }
2719 }
2720
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002721Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002722 printdecode(pMe, "end exit");
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002723 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002724}
2725
2726
Laurence Lundblade1341c592020-04-11 14:19:05 -07002727void QCBORDecode_RewindMap(QCBORDecodeContext *pMe)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002728{
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002729 // TODO: check for map mode; test this
Laurence Lundblade1341c592020-04-11 14:19:05 -07002730 pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->uSaveCount;
2731 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->uOffset);
2732}
2733
2734
Laurence Lundblade1341c592020-04-11 14:19:05 -07002735
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002736static QCBORError FarfWrappedBstr(QCBORDecodeContext *pMe, const QCBORItem *pItem, uint8_t uTagRequirement, UsefulBufC *pBstr)
2737{
2738 if(pMe->uLastError != QCBOR_SUCCESS) {
2739 // Already in error state; do nothing.
2740 return pMe->uLastError;
2741 }
2742
2743 QCBORError uError = QCBOR_SUCCESS;
2744
2745 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
2746 uError = QCBOR_ERR_UNEXPECTED_TYPE;
2747 goto Done;;
2748 }
2749
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002750 // TODO: check for the other wrapped CBOR tag
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002751 const TagSpecification TagSpec = {uTagRequirement, QBCOR_TYPE_WRAPPED_CBOR, {QCBOR_TYPE_BYTE_STRING, 0,0,0,0,0}};
2752
2753 uError = CheckTagRequirement(TagSpec, pItem->uDataType);
2754 if(uError != QCBOR_SUCCESS) {
2755 goto Done;
2756 }
2757
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002758 //if(pMe->nesting.pCurrent)
2759 pMe->nesting.pCurrent->uCount++; // Don't count the bstr yet
2760
2761 if(pBstr) {
2762 *pBstr = pItem->val.string;
2763 }
2764
2765 const size_t uPreviousLength = UsefulInputBuf_GetLength(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002766
2767 // Need to move UIB input cursor to the right place
2768
2769 // Really this is a subtraction and an assignment; not much code
2770 // There is a range check in the seek.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002771 // The bstr was just consumed so the cursor is at the next item after it
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002772
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002773 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002774
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002775
2776 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
2777
2778 UsefulInputBuf_SetBufferLen(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002779
2780 // TODO: comment on cast
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002781 uError = DecodeNesting_Descend(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING, UINT16_MAX, (uint32_t)uPreviousLength, (uint32_t)uEndOfBstr);
2782 pMe->nesting.pCurrent->bBoundedMode = true;
2783 pMe->nesting.pCurrentBounded = pMe->nesting.pCurrent;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002784
2785Done:
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002786 printdecode(pMe, "Entered Bstr");
2787
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002788 return uError;
2789
2790}
2791
2792
2793void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe, uint8_t uTagRequirement, UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002794{
2795 if(pMe->uLastError != QCBOR_SUCCESS) {
2796 // Already in error state; do nothing.
2797 return;
2798 }
2799
2800 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002801 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002802 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
2803 if(pMe->uLastError != QCBOR_SUCCESS) {
2804 return;
2805 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002806
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002807 pMe->uLastError = (uint8_t)FarfWrappedBstr(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002808}
2809
2810
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002811void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe, uint8_t uTagRequirement, int64_t nLabel, UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002812{
2813 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002814 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002815
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002816 pMe->uLastError = (uint8_t)FarfWrappedBstr(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002817}
2818
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002819
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002820void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe, uint8_t uTagRequirement, const char *szLabel, UsefulBufC *pBstr)
2821{
2822 QCBORItem Item;
2823 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
2824
2825 pMe->uLastError = (uint8_t)FarfWrappedBstr(pMe, &Item, uTagRequirement, pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002826}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002827
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002828void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002829{
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002830 /* Reset the length of the Useful\InputBuf to what it was before
2831 the bstr wrapped CBOR was entered
2832 */
2833 UsefulInputBuf_SetBufferLen(&(pMe->InBuf), pMe->nesting.pCurrentBounded->uPreviousEndOffset);
2834
2835 // Put the pre-order traversal cursor in the right place
2836 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrentBounded->uEndOfBstr);
2837
2838 // Invalidate the cached bounded mode end.
2839 pMe->uMapEndOffset = UINT32_MAX;
2840
2841
2842 // Always go up one level
2843 // Need error check to know level is bounded mode and not at top level
2844 pMe->nesting.pCurrent = pMe->nesting.pCurrentBounded - 1; // TODO error check
2845
2846 QCBORError uErr = Ascender(pMe);
2847 if(uErr != QCBOR_SUCCESS) {
2848 goto Done;
2849 }
2850
2851 /* Also ascend to the next highest bounded mode level if
2852 there is one. */
2853 while(1) {
2854 pMe->nesting.pCurrentBounded--;
2855 if(DecodeNesting_InBoundedMode(&(pMe->nesting))) {
2856 break;
2857 }
2858 if(pMe->nesting.pCurrentBounded == &(pMe->nesting.pMapsAndArrays[0])) {
2859 //pMe->nesting.pCurrentBounded = NULL;
2860 break;
2861 }
2862 }
2863
2864 pMe->nesting.pCurrent = pMe->nesting.pCurrentBounded;
2865
2866Done:
2867 // TODO: set last error here
2868 printdecode(pMe, "Exited Bstr");
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002869}
2870
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002871
Laurence Lundbladee6430642020-03-14 21:15:44 -07002872
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002873
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002874
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002875
Laurence Lundblade11a064e2020-05-07 13:13:42 -07002876
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002877
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002878static QCBORError InterpretBool(const QCBORItem *pItem, bool *pBool)
2879{
2880 switch(pItem->uDataType) {
2881 case QCBOR_TYPE_TRUE:
2882 *pBool = true;
2883 return QCBOR_SUCCESS;
2884 break;
2885
2886 case QCBOR_TYPE_FALSE:
2887 *pBool = false;
2888 return QCBOR_SUCCESS;
2889 break;
2890
2891 default:
2892 return QCBOR_ERR_UNEXPECTED_TYPE;
2893 break;
2894 }
2895}
Laurence Lundbladee6430642020-03-14 21:15:44 -07002896
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002897/*
2898Public function, see header qcbor/qcbor_decode.h file
2899*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07002900void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002901{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002902 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002903 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07002904 return;
2905 }
2906
Laurence Lundbladec4537442020-04-14 18:53:22 -07002907 QCBORError nError;
2908 QCBORItem Item;
2909
2910 nError = QCBORDecode_GetNext(pMe, &Item);
2911 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002912 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002913 return;
2914 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002915 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002916}
2917
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002918/*
2919Public function, see header qcbor/qcbor_decode.h file
2920*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002921void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002922{
2923 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002924 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002925
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002926 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002927}
2928
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002929/*
2930Public function, see header qcbor/qcbor_decode.h file
2931*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002932void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
2933{
2934 QCBORItem Item;
2935 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
2936
2937 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
2938}
2939
2940
2941
2942void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe, TagSpecification TagSpec, UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002943{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002944 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002945 // Already in error state, do nothing
2946 return;
2947 }
2948
2949 QCBORError nError;
2950 QCBORItem Item;
2951
2952 nError = QCBORDecode_GetNext(pMe, &Item);
2953 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002954 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002955 return;
2956 }
2957
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002958 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, Item.uDataType);
2959
2960 if(pMe->uLastError == QCBOR_SUCCESS) {
2961 *pBstr = Item.val.string;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002962 }
2963}
2964
Laurence Lundbladec4537442020-04-14 18:53:22 -07002965
2966
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002967
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002968static QCBORError ConvertBigNum(uint8_t uTagRequirement, const QCBORItem *pItem, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002969{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002970 *pbIsNegative = false;
2971
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002972 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 -07002973
2974 switch(pItem->uDataType) {
2975 case QCBOR_TYPE_BYTE_STRING:
2976 // TODO: check that there is no tag here?
2977 if(bMustBeTagged) {
2978 return QCBOR_ERR_UNEXPECTED_TYPE;
2979 } else {
2980 *pValue = pItem->val.string;
2981 return QCBOR_SUCCESS;
2982 }
2983 break;
2984
2985 case QCBOR_TYPE_POSBIGNUM:
2986 *pValue = pItem->val.string;
2987 return QCBOR_SUCCESS;
2988 break;
2989
2990 case QCBOR_TYPE_NEGBIGNUM:
2991 *pbIsNegative = true;
2992 *pValue = pItem->val.string;
2993 return QCBOR_SUCCESS;
2994 break;
2995
2996 default:
2997 return QCBOR_ERR_UNEXPECTED_TYPE;
2998 break;
2999 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003000}
3001
3002
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003003/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003004 @param[in] bMustBeTagged If \c true, then the data item must be tagged as either
3005 a positive or negative bignum. If \c false, then it only must be a byte string and bIsNegative
3006 will always be false on the asumption that it is positive, but it can be interpretted as
3007 negative if the the sign is know from other context.
3008 @param[out] pValue The bytes that make up the big num
3009 @param[out] pbIsNegative \c true if tagged as a negative big num. \c false otherwise.
3010
3011 if bMustBeTagged is false, then this will succeed if the data item is a plain byte string,
3012 a positive big num or a negative big num.
3013
3014 */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003015void QCBORDecode_GetBignum(QCBORDecodeContext *pMe, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003016{
3017 if(pMe->uLastError != QCBOR_SUCCESS) {
3018 // Already in error state, do nothing
3019 return;
3020 }
3021
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003022 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003023 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3024 if(uError != QCBOR_SUCCESS) {
3025 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003026 return;
3027 }
3028
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003029 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003030}
3031
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003032/*
3033Public function, see header qcbor/qcbor_decode.h file
3034*/
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003035void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003036{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003037 QCBORItem Item;
3038 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003039
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003040 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003041}
3042
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003043/*
3044Public function, see header qcbor/qcbor_decode.h file
3045*/
3046void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative)
3047{
3048 QCBORItem Item;
3049 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3050
3051 pMe->uLastError = (uint8_t)ConvertBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
3052}
3053
3054
3055
3056// Semi private
3057QCBORError FarfMIME(uint8_t uTagRequirement, const QCBORItem *pItem, UsefulBufC *pMessage, bool *pbIsNot7Bit)
3058{
3059 const TagSpecification TagSpecText = {uTagRequirement, QCBOR_TYPE_MIME, {QCBOR_TYPE_TEXT_STRING, 0,0,0,0,0}};
3060 const TagSpecification TagSpecBinary = {uTagRequirement, QCBOR_TYPE_BINARY_MIME, {QCBOR_TYPE_BYTE_STRING, 0,0,0,0,0}};
3061
3062 QCBORError uReturn;
3063
3064 if(CheckTagRequirement(TagSpecText, pItem->uDataType)) {
3065 *pMessage = pItem->val.string;
3066 if(pbIsNot7Bit != NULL) {
3067 *pbIsNot7Bit = false;
3068 }
3069 uReturn = QCBOR_SUCCESS;
3070 } else if(CheckTagRequirement(TagSpecBinary, pItem->uDataType)) {
3071 *pMessage = pItem->val.string;
3072 if(pbIsNot7Bit != NULL) {
3073 *pbIsNot7Bit = true;
3074 }
3075 uReturn = QCBOR_SUCCESS;
3076
3077 } else {
3078 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3079 }
3080
3081 return uReturn;
3082}
3083
3084
3085
3086
3087
Laurence Lundbladec4537442020-04-14 18:53:22 -07003088
3089
3090
Laurence Lundbladee6430642020-03-14 21:15:44 -07003091
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003092typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003093
3094
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003095// The main exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003096static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003097{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003098 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003099
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003100 if(uResult != 0) {
3101 /* This loop will run a maximum of 19 times because
3102 * UINT64_MAX < 10 ^^ 19. More than that will cause
3103 * exit with the overflow error
3104 */
3105 for(; nExponent > 0; nExponent--) {
3106 if(uResult > UINT64_MAX / 10) {
3107 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3108 }
3109 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003110 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003111
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003112 for(; nExponent < 0; nExponent++) {
3113 uResult = uResult / 10;
3114 if(uResult == 0) {
3115 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3116 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003117 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003118 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003119 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003120
3121 *puResult = uResult;
3122
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003123 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003124}
3125
3126
Laurence Lundbladee6430642020-03-14 21:15:44 -07003127/* Convert a decimal fraction to an int64_t without using
3128 floating point or math libraries. Most decimal fractions
3129 will not fit in an int64_t and this will error out with
3130 under or overflow
3131 */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003132static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003133{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003134 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003135
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003136 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003137
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003138 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003139 * INT64_MAX < 2^31. More than that will cause
3140 * exist with the overflow error
3141 */
3142 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003143 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003144 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003145 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003146 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003147 nExponent--;
3148 }
3149
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003150 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003151 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003152 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3153 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003154 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003155 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003156 }
3157
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003158 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003159
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003160 return QCBOR_SUCCESS;
3161}
3162
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003163/*
3164 Compute value with signed mantissa and signed result. Works with exponent of 2 or 10 based on exponentiator.
3165 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003166static inline QCBORError ExponentiateNN(int64_t nMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
3167{
3168 uint64_t uResult;
3169
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003170 // Take the absolute value of the mantissa and convert to unsigned.
3171 // TODO: this should be possible in one intruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003172 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3173
3174 // Do the exponentiation of the positive mantissa
3175 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3176 if(uReturn) {
3177 return uReturn;
3178 }
3179
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003180
Laurence Lundblade983500d2020-05-14 11:49:34 -07003181 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3182 of INT64_MIN. This assumes two's compliment representation where
3183 INT64_MIN is one increment farther from 0 than INT64_MAX.
3184 Trying to write -INT64_MIN doesn't work to get this because the
3185 compiler tries to work with an int64_t which can't represent
3186 -INT64_MIN.
3187 */
3188 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3189
3190 // Error out if too large
3191 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003192 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3193 }
3194
3195 // Casts are safe because of checks above
3196 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3197
3198 return QCBOR_SUCCESS;
3199}
3200
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003201/*
3202 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
3203 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003204static inline QCBORError ExponentitateNU(int64_t nMantissa, int64_t nExponent, uint64_t *puResult, fExponentiator pfExp)
3205{
3206 if(nMantissa < 0) {
3207 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3208 }
3209
3210 // Cast to unsigned is OK because of check for negative
3211 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3212 // Exponentiation is straight forward
3213 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3214}
3215
3216
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003217#include <math.h>
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003218
3219
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003220static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003221{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003222 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003223
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003224 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003225 const uint8_t *pByte = BigNum.ptr;
3226 size_t uLen = BigNum.len;
3227 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003228 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003229 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003230 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003231 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003232 }
3233
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003234 *pResult = uResult;
3235 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003236}
3237
Laurence Lundblade887add82020-05-17 05:50:34 -07003238static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003239{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003240 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003241}
3242
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003243static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003244{
3245 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003246 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3247 if(uError) {
3248 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003249 }
3250 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3251 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003252 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003253}
3254
3255
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003256static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003257{
3258 uint64_t uResult;
Laurence Lundbladeda095972020-06-06 18:35:33 -07003259 /* negaative int furthest from zero is INT64_MIN
3260 which is expressed as -INT64_MAX-1. The value of
3261 a negative bignum is -n-1, one further from zero
3262 than the positive bignum */
3263
3264 /* say INT64_MIN is -2; then INT64_MAX is 1.
3265 Then -n-1 <= INT64_MIN.
3266 Then -n -1 <= -INT64_MAX - 1
3267 THen n <= INT64_MAX. */
3268 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003269 if(uError) {
3270 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003271 }
3272 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
Laurence Lundblade887add82020-05-17 05:50:34 -07003273 // TODO: this code is incorrect. See RFC 7049
Laurence Lundbladeda095972020-06-06 18:35:33 -07003274 uResult++; // this is the -1 in -n-1
Laurence Lundbladee6430642020-03-14 21:15:44 -07003275 *pResult = -(int64_t)uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003276 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003277}
3278
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003279#include "fenv.h"
Laurence Lundbladec4537442020-04-14 18:53:22 -07003280
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003281
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003282/*
3283Convert a integers and floats to an int64_t.
3284
3285\param[in] uOptions Bit mask list of conversion options.
3286
3287\retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
3288
3289\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3290
3291\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3292
3293*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003294static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
3295{
3296 switch(pItem->uDataType) {
3297 // TODO: float when ifdefs are set
3298 case QCBOR_TYPE_DOUBLE:
3299 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3300 // TODO: what about under/overflow here?
3301 // Invokes the floating-point HW and/or compiler-added libraries
3302 feclearexcept(FE_ALL_EXCEPT);
3303 *pnValue = llround(pItem->val.dfnum);
3304 if(fetestexcept(FE_INVALID)) {
3305 // TODO: better error code
3306 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3307 }
3308 } else {
3309 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3310 }
3311 break;
3312
3313 case QCBOR_TYPE_INT64:
3314 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
3315 *pnValue = pItem->val.int64;
3316 } else {
3317 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3318 }
3319 break;
3320
3321 case QCBOR_TYPE_UINT64:
3322 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
3323 if(pItem->val.uint64 < INT64_MAX) {
3324 *pnValue = pItem->val.int64;
3325 } else {
3326 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3327 }
3328 } else {
3329 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3330 }
3331 break;
3332
3333 default:
3334 return QCBOR_ERR_UNEXPECTED_TYPE;
3335 }
3336 return QCBOR_SUCCESS;
3337}
3338
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003339
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003340void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
3341 uint32_t uOptions,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003342 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003343 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003344{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003345 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003346 return;
3347 }
3348
Laurence Lundbladee6430642020-03-14 21:15:44 -07003349 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003350 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3351 if(uError) {
3352 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003353 return;
3354 }
3355
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003356 if(pItem) {
3357 *pItem = Item;
3358 }
3359
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003360 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003361}
3362
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003363
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003364void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3365 int64_t nLabel,
3366 uint32_t uOptions,
3367 int64_t *pnValue,
3368 QCBORItem *pItem)
3369{
3370 QCBORItem Item;
3371 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3372
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003373 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003374}
3375
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003376
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003377void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3378 const char * szLabel,
3379 uint32_t uOptions,
3380 int64_t *pnValue,
3381 QCBORItem *pItem)
3382{
3383 if(pMe->uLastError != QCBOR_SUCCESS) {
3384 return;
3385 }
3386
3387 QCBORItem Item;
3388 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3389
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003390 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003391}
3392
3393
3394
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003395/*
3396 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003397
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003398 \param[in] uOptions Bit mask list of conversion options.
3399
3400 \retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
3401
3402 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3403
3404 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
3405
3406 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003407static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
3408{
3409 QCBORError uErr;
3410
3411 switch(pItem->uDataType) {
3412
3413 case QCBOR_TYPE_POSBIGNUM:
3414 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3415 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003416 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003417 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003418 }
3419 break;
3420
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003421 case QCBOR_TYPE_NEGBIGNUM:
3422 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3423 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003424 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003425 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003426 }
3427 break;
3428
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003429#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3430 case QCBOR_TYPE_DECIMAL_FRACTION:
3431 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3432 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3433 pItem->val.expAndMantissa.nExponent,
3434 pnValue,
3435 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003436 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003437 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3438 }
3439 break;
3440
3441 case QCBOR_TYPE_BIGFLOAT:
3442 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3443 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
3444 pItem->val.expAndMantissa.nExponent,
3445 pnValue,
3446 Exponentitate2);
3447 } else {
3448 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3449 }
3450 break;
3451
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003452 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3453 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3454 int64_t nMantissa;
3455 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3456 if(uErr) {
3457 return uErr;
3458 }
3459 return ExponentiateNN(nMantissa,
3460 pItem->val.expAndMantissa.nExponent,
3461 pnValue,
3462 Exponentitate10);
3463 } else {
3464 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3465 }
3466 break;
3467
3468 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3469 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3470 int64_t nMantissa;
3471 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3472 if(uErr) {
3473 return uErr;
3474 }
3475 return ExponentiateNN(nMantissa,
3476 pItem->val.expAndMantissa.nExponent,
3477 pnValue,
3478 Exponentitate10);
3479 } else {
3480 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3481 }
3482 break;
3483
3484 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3485 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3486 int64_t nMantissa;
3487 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3488 if(uErr) {
3489 return uErr;
3490 }
3491 return ExponentiateNN(nMantissa,
3492 pItem->val.expAndMantissa.nExponent,
3493 pnValue,
3494 Exponentitate2);
3495 } else {
3496 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3497 }
3498 break;
3499
3500 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3501 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3502 int64_t nMantissa;
3503 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3504 if(uErr) {
3505 return uErr;
3506 }
3507 return ExponentiateNN(nMantissa,
3508 pItem->val.expAndMantissa.nExponent,
3509 pnValue,
3510 Exponentitate2);
3511 } else {
3512 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003513 }
3514 break;
3515
Laurence Lundbladec4537442020-04-14 18:53:22 -07003516 default:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003517 return QCBOR_ERR_UNEXPECTED_TYPE;
3518#endif
Laurence Lundbladec4537442020-04-14 18:53:22 -07003519 }
3520}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003521
3522
Laurence Lundbladec4537442020-04-14 18:53:22 -07003523/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003524 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003525 */
3526void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003527{
3528 QCBORItem Item;
3529
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003530 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003531
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003532 if(pMe->uLastError == QCBOR_SUCCESS) {
3533 // The above conversion succeeded
3534 return;
3535 }
3536
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003537 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003538 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07003539 return;
3540 }
3541
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003542 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003543}
3544
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003545
3546/*
3547Public function, see header qcbor/qcbor_decode.h file
3548*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003549void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int64_t *pnValue)
3550{
3551 QCBORItem Item;
3552
3553 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, pnValue, &Item);
3554
3555 if(pMe->uLastError == QCBOR_SUCCESS) {
3556 // The above conversion succeeded
3557 return;
3558 }
3559
3560 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3561 // The above conversion failed in a way that code below can't correct
3562 return;
3563 }
3564
3565 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3566}
3567
3568
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003569/*
3570Public function, see header qcbor/qcbor_decode.h file
3571*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003572void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int64_t *pnValue)
3573{
3574 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003575 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, pnValue, &Item);
3576
3577 if(pMe->uLastError == QCBOR_SUCCESS) {
3578 // The above conversion succeeded
3579 return;
3580 }
3581
3582 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3583 // The above conversion failed in a way that code below can't correct
3584 return;
3585 }
3586
3587 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3588}
3589
3590
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003591static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3592{
3593 switch(pItem->uDataType) {
3594 // TODO: type flaot
3595 case QCBOR_TYPE_DOUBLE:
3596 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3597 feclearexcept(FE_ALL_EXCEPT);
3598 double dRounded = round(pItem->val.dfnum);
3599 // TODO: over/underflow
3600 if(fetestexcept(FE_INVALID)) {
3601 // TODO: better error code
3602 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3603 } else if(isnan(dRounded)) {
3604 // TODO: better error code
3605 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3606 } else if(dRounded >= 0) {
3607 *puValue = (uint64_t)dRounded;
3608 } else {
3609 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3610 }
3611 } else {
3612 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3613 }
3614 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003615
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003616 case QCBOR_TYPE_INT64:
3617 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
3618 if(pItem->val.int64 >= 0) {
3619 *puValue = (uint64_t)pItem->val.int64;
3620 } else {
3621 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3622 }
3623 } else {
3624 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3625 }
3626 break;
3627
3628 case QCBOR_TYPE_UINT64:
3629 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
3630 *puValue = pItem->val.uint64;
3631 } else {
3632 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3633 }
3634 break;
3635
3636 default:
3637 return QCBOR_ERR_UNEXPECTED_TYPE;
3638 }
3639 return QCBOR_SUCCESS;
3640}
Laurence Lundbladec4537442020-04-14 18:53:22 -07003641
3642
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003643void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
3644 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003645 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003646 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003647{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003648 if(pMe->uLastError != QCBOR_SUCCESS) {
3649 return;
3650 }
3651
Laurence Lundbladec4537442020-04-14 18:53:22 -07003652 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003653
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003654 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3655 if(uError) {
3656 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003657 return;
3658 }
3659
Laurence Lundbladea826c502020-05-10 21:07:00 -07003660 if(pItem) {
3661 *pItem = Item;
3662 }
3663
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003664 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003665}
3666
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003667
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003668void QCBORDecode_GetInt8ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3669{
3670 int64_t uValue;
3671 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, &uValue, pItem);
3672 if(pMe->uLastError != QCBOR_SUCCESS) {
3673 return;
3674 }
3675
3676 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3677 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3678 }
3679}
3680
3681void QCBORDecode_GetInt8ConvertInternalInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3682{
3683 int64_t uValue;
3684 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, &uValue, pItem);
3685 if(pMe->uLastError != QCBOR_SUCCESS) {
3686 return;
3687 }
3688
3689 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3690 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3691 }
3692}
3693
3694void QCBORDecode_GetInt8ConvertInternalInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int8_t *pnValue, QCBORItem *pItem)
3695{
3696 int64_t uValue;
3697 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, &uValue, pItem);
3698 if(pMe->uLastError != QCBOR_SUCCESS) {
3699 return;
3700 }
3701
3702 if(QCBOR_Int64ToInt8(uValue, pnValue)) {
3703 pMe->uLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3704 }
3705}
3706
3707
3708
3709
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003710void QCBORDecode_GetUint64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3711 int64_t nLabel,
3712 uint32_t uOptions,
3713 uint64_t *puValue,
3714 QCBORItem *pItem)
3715{
3716 QCBORItem Item;
3717 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3718
3719 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
3720}
3721
3722
3723void QCBORDecode_GetUint64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3724 const char * szLabel,
3725 uint32_t uOptions,
3726 uint64_t *puValue,
3727 QCBORItem *pItem)
3728{
3729 if(pMe->uLastError != QCBOR_SUCCESS) {
3730 return;
3731 }
3732
3733 QCBORItem Item;
3734 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3735
3736 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
3737}
3738
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003739/*
3740 Public function, see header qcbor/qcbor_decode.h file
3741*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003742static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3743{
3744 QCBORError uErr;
3745
3746 switch(pItem->uDataType) {
3747
3748 case QCBOR_TYPE_POSBIGNUM:
3749 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3750 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
3751 } else {
3752 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3753 }
3754 break;
3755
3756 case QCBOR_TYPE_NEGBIGNUM:
3757 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3758 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3759 } else {
3760 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3761 }
3762 break;
3763
3764#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3765
3766 case QCBOR_TYPE_DECIMAL_FRACTION:
3767 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3768 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3769 pItem->val.expAndMantissa.nExponent,
3770 puValue,
3771 Exponentitate10);
3772 } else {
3773 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3774 }
3775 break;
3776
3777 case QCBOR_TYPE_BIGFLOAT:
3778 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3779 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3780 pItem->val.expAndMantissa.nExponent,
3781 puValue,
3782 Exponentitate2);
3783 } else {
3784 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3785 }
3786 break;
3787
3788 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3789 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3790 // TODO: Would be better to convert to unsigned
3791 int64_t nMantissa;
3792 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3793 if(uErr != QCBOR_SUCCESS) {
3794 return uErr;
3795 }
3796 return ExponentitateNU(nMantissa,
3797 pItem->val.expAndMantissa.nExponent,
3798 puValue,
3799 Exponentitate10);
3800 } else {
3801 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3802 }
3803 break;
3804
3805 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3806 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3807 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3808 } else {
3809 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3810 }
3811 break;
3812
3813 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3814 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3815 // TODO: Would be better to convert to unsigned
3816 int64_t nMantissa;
3817 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3818 if(uErr != QCBOR_SUCCESS) {
3819 return uErr;
3820 }
3821 return ExponentitateNU(nMantissa,
3822 pItem->val.expAndMantissa.nExponent,
3823 puValue,
3824 Exponentitate2);
3825 } else {
3826 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3827 }
3828 break;
3829
3830 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3831 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3832 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3833 } else {
3834 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3835 }
3836 break;
3837#endif
3838 default:
3839 return QCBOR_ERR_UNEXPECTED_TYPE;
3840 }
3841}
3842
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003843/*
3844 Public function, see header qcbor/qcbor_decode.h file
3845*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003846void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003847{
3848 QCBORItem Item;
3849
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003850 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003851
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003852 if(pMe->uLastError == QCBOR_SUCCESS) {
3853 // The above conversion succeeded
3854 return;
3855 }
3856
3857 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3858 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07003859 return;
3860 }
3861
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003862 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003863}
3864
Laurence Lundbladec4537442020-04-14 18:53:22 -07003865
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003866/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003867 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003868*/
3869void QCBORDecode_GetUint64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, uint64_t *puValue)
3870{
3871 QCBORItem Item;
3872
3873 QCBORDecode_GetUint64ConvertInternalInMapN(pMe, nLabel, uOptions, puValue, &Item);
3874
3875 if(pMe->uLastError == QCBOR_SUCCESS) {
3876 // The above conversion succeeded
3877 return;
3878 }
3879
3880 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3881 // The above conversion failed in a way that code below can't correct
3882 return;
3883 }
3884
3885 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
3886}
3887
3888
3889/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003890 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003891*/
3892void QCBORDecode_GetUint64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, uint64_t *puValue)
3893{
3894 QCBORItem Item;
3895 QCBORDecode_GetUint64ConvertInternalInMapSZ(pMe, szLabel, uOptions, puValue, &Item);
3896
3897 if(pMe->uLastError == QCBOR_SUCCESS) {
3898 // The above conversion succeeded
3899 return;
3900 }
3901
3902 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3903 // The above conversion failed in a way that code below can't correct
3904 return;
3905 }
3906
3907 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
3908}
3909
3910
3911static QCBORError ConvertDouble(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
3912{
3913 switch(pItem->uDataType) {
3914 // TODO: float when ifdefs are set
3915 case QCBOR_TYPE_DOUBLE:
3916 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3917 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3918 *pdValue = pItem->val.dfnum;
3919 } else {
3920 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3921 }
3922 }
3923 break;
3924
3925 case QCBOR_TYPE_INT64:
3926 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
3927 // TODO: how does this work?
3928 *pdValue = (double)pItem->val.int64;
3929
3930 } else {
3931 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3932 }
3933 break;
3934
3935 case QCBOR_TYPE_UINT64:
3936 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
3937 *pdValue = (double)pItem->val.uint64;
3938 } else {
3939 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3940 }
3941 break;
3942
3943 default:
3944 return QCBOR_ERR_UNEXPECTED_TYPE;
3945 }
3946
3947 return QCBOR_SUCCESS;
3948}
3949
3950
3951
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003952void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
3953 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003954 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003955 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003956{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003957 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003958 return;
3959 }
3960
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003961 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003962
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003963 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003964 if(uError) {
3965 pMe->uLastError = (uint8_t)uError;
3966 return;
3967 }
3968
3969 if(pItem) {
3970 *pItem = Item;
3971 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003972
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003973 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003974}
Laurence Lundbladec4537442020-04-14 18:53:22 -07003975
Laurence Lundbladec4537442020-04-14 18:53:22 -07003976
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003977void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
3978 int64_t nLabel,
3979 uint32_t uOptions,
3980 double *pdValue,
3981 QCBORItem *pItem)
3982{
3983 QCBORItem Item;
3984 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3985
3986 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
3987}
3988
3989void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3990 const char * szLabel,
3991 uint32_t uOptions,
3992 double *pdValue,
3993 QCBORItem *pItem)
3994{
3995 if(pMe->uLastError != QCBOR_SUCCESS) {
3996 return;
3997 }
3998
3999 QCBORItem Item;
4000 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4001
4002 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
4003}
4004
4005
4006
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004007static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4008{
4009 double dResult;
4010
4011 dResult = 0.0;
4012 const uint8_t *pByte = BigNum.ptr;
4013 size_t uLen = BigNum.len;
4014 /* This will overflow and become the float value INFINITY if the number
4015 is too large to fit. No error will be logged.
4016 TODO: should an error be logged? */
4017 while(uLen--) {
4018 dResult = (dResult * 256.0) + (double)*pByte++;
4019 }
4020
4021 return dResult;
4022}
4023
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004024static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004025{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004026 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004027 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4028
4029 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004030 switch(pItem->uDataType) {
4031 // TODO: type float
4032 case QCBOR_TYPE_DECIMAL_FRACTION:
4033 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4034 // TODO: rounding and overflow errors
4035 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4036 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4037 } else {
4038 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4039 }
4040 break;
4041
4042 case QCBOR_TYPE_BIGFLOAT:
4043 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
4044 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4045 exp2((double)pItem->val.expAndMantissa.nExponent);
4046 } else {
4047 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4048 }
4049 break;
4050
4051 case QCBOR_TYPE_POSBIGNUM:
4052 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
4053 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4054 } else {
4055 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4056 }
4057 break;
4058
4059 case QCBOR_TYPE_NEGBIGNUM:
4060 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004061 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004062 } else {
4063 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4064 }
4065 break;
4066
4067 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4068 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4069 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4070 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4071 } else {
4072 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4073 }
4074 break;
4075
4076 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4077 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
4078 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4079 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4080 } else {
4081 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4082 }
4083 break;
4084
4085 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
4086 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
4087 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4088 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4089 } else {
4090 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4091 }
4092 break;
4093
4094 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
4095 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004096 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004097 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4098 } else {
4099 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
4100 }
4101 break;
4102
4103 default:
4104 return QCBOR_ERR_UNEXPECTED_TYPE;
4105 }
4106
4107 return QCBOR_SUCCESS;
4108}
4109
4110
4111/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004112 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004113*/
4114void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pdValue)
4115{
4116
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004117 QCBORItem Item;
4118
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004119 QCBORDecode_GetDoubleConvertInternal(pMe, uOptions, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004120
4121 if(pMe->uLastError == QCBOR_SUCCESS) {
4122 // The above conversion succeeded
4123 return;
4124 }
4125
4126 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4127 // The above conversion failed in a way that code below can't correct
4128 return;
4129 }
4130
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004131 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004132}
4133
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004134
4135/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004136 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004137*/
4138void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, double *pdValue)
4139{
4140 QCBORItem Item;
4141
4142 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uOptions, pdValue, &Item);
4143
4144 if(pMe->uLastError == QCBOR_SUCCESS) {
4145 // The above conversion succeeded
4146 return;
4147 }
4148
4149 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4150 // The above conversion failed in a way that code below can't correct
4151 return;
4152 }
4153
4154 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
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_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, double *pdValue)
4162{
4163 QCBORItem Item;
4164 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uOptions, pdValue, &Item);
4165
4166 if(pMe->uLastError == QCBOR_SUCCESS) {
4167 // The above conversion succeeded
4168 return;
4169 }
4170
4171 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4172 // The above conversion failed in a way that code below can't correct
4173 return;
4174 }
4175
4176 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
4177}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004178
4179
4180void FarfDecimalFraction(QCBORDecodeContext *pMe,
4181 uint8_t uTagRequirement,
4182 QCBORItem *pItem,
4183 int64_t *pnMantissa,
4184 int64_t *pnExponent)
4185{
4186 QCBORError uErr;
4187
4188 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
4189 if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
4190 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4191 return;
4192 }
4193 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4194 if(uErr != QCBOR_SUCCESS) {
4195 pMe->uLastError = (uint8_t)uErr;
4196 return;
4197 }
4198 }
4199
4200 if(uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE) {
4201 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4202 return;
4203 }
4204
4205 switch (pItem->uDataType) {
4206
4207 case QCBOR_TYPE_DECIMAL_FRACTION:
4208 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
4209 *pnExponent = pItem->val.expAndMantissa.nExponent;
4210 break;
4211
4212 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4213 *pnExponent = pItem->val.expAndMantissa.nExponent;
4214
4215 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4216 if(uErr != QCBOR_SUCCESS) {
4217 pMe->uLastError = (uint8_t)uErr;
4218 }
4219 break;
4220
4221 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4222 *pnExponent = pItem->val.expAndMantissa.nExponent;
4223
4224 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
4225 if(uErr != QCBOR_SUCCESS) {
4226 pMe->uLastError = (uint8_t)uErr;
4227 }
4228 break;
4229
4230 default:
4231 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4232 }
4233}
4234
4235void QCBORDecode_GetDecimalFractionN(QCBORDecodeContext *pMe,
4236 uint8_t uTagRequirement,
4237 int64_t nLabel,
4238 int64_t *pnMantissa,
4239 int64_t *pnExponent)
4240{
4241 QCBORItem Item;
4242
4243 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4244 FarfDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
4245}
4246
4247
4248
4249void QCBORDecode_GetDecimalFractionSZ(QCBORDecodeContext *pMe,
4250 uint8_t uTagRequirement,
4251 const char *szLabel,
4252 int64_t *pnMantissa,
4253 int64_t *pnExponent)
4254{
4255 QCBORItem Item;
4256
4257 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4258
4259 FarfDecimalFraction(pMe, uTagRequirement, &Item, pnMantissa, pnExponent);
4260}
4261
4262
4263UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4264{
4265 while(uInt & 0xff0000000000UL) {
4266 uInt = uInt << 8;
4267 };
4268
4269 UsefulOutBuf UOB;
4270
4271 UsefulOutBuf_Init(&UOB, Buffer);
4272
4273 while(uInt) {
4274 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff0000000000UL) >> 56));
4275 uInt = uInt << 8;
4276 }
4277
4278 return UsefulOutBuf_OutUBuf(&UOB);
4279}
4280
4281
4282void QCBORDecode_GetDecimalFractionBigN(QCBORDecodeContext *pMe,
4283 uint8_t uTagRequirement,
4284 int64_t nLabel,
4285 UsefulBuf pBufferForMantissa,
4286 UsefulBufC *pMantissa,
4287 bool *pbIsNegative,
4288 int64_t *pnExponent)
4289{
4290 QCBORItem Item;
4291 QCBORError uErr;
4292
4293 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4294
4295 if(Item.uDataType == QCBOR_TYPE_ARRAY) {
4296 uErr = QCBORDecode_MantissaAndExponent(pMe, &Item);
4297 if(uErr != QCBOR_SUCCESS) {
4298 pMe->uLastError = (uint8_t)uErr;
4299 return;
4300 }
4301 }
4302
4303 uint64_t uMantissa;
4304
4305 switch (Item.uDataType) {
4306
4307 case QCBOR_TYPE_DECIMAL_FRACTION:
4308 if(Item.val.expAndMantissa.Mantissa.nInt >= 0) {
4309 uMantissa = (uint64_t)Item.val.expAndMantissa.Mantissa.nInt;
4310 *pbIsNegative = false;
4311 } else {
4312 uMantissa = (uint64_t)-Item.val.expAndMantissa.Mantissa.nInt;
4313 *pbIsNegative = true;
4314 }
4315 *pMantissa = ConvertIntToBigNum(uMantissa, pBufferForMantissa);
4316 *pnExponent = Item.val.expAndMantissa.nExponent;
4317 break;
4318
4319 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
4320 *pnExponent = Item.val.expAndMantissa.nExponent;
4321 *pMantissa = Item.val.expAndMantissa.Mantissa.bigNum;
4322 *pbIsNegative = false;
4323 break;
4324
4325 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
4326 *pnExponent = Item.val.expAndMantissa.nExponent;
4327 *pMantissa = Item.val.expAndMantissa.Mantissa.bigNum;
4328 *pbIsNegative = true;
4329 break;
4330
4331 default:
4332 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4333 }
4334}