blob: 749327b8bf12281a13ff1578a198b7b6d3ba4404 [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 Lundblade9c905e82020-04-25 11:31:38 -0700124inline static bool
125DecodeNesting_IsAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700126{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700127 if(pNesting->pCurrent == &(pNesting->pMapsAndArrays[0])) {
128 return true;
129 } else {
130 return false;
131 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700132}
133
Laurence Lundblade937ea812020-05-08 11:38:23 -0700134// Determine if at the end of a map or array while in map mode
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700135inline static bool
136DecodeNesting_AtEnd(const QCBORDecodeNesting *pNesting)
137{
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700138 if(pNesting->pCurrentMap && pNesting->pCurrentMap->uMapMode) {
139 if(pNesting->pCurrentMap->uCount == 0) {
Laurence Lundblade937ea812020-05-08 11:38:23 -0700140 // TODO: won't work for indefinite length
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700141 // In map mode and consumed all items, so it is the end
142 return true;
143 } else {
144 // In map mode, all items not consumed, so it is NOT the end
145 return false;
146 }
147 } else {
Laurence Lundblade937ea812020-05-08 11:38:23 -0700148 // Not in map mode. The end is determined in other ways.
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700149 return false;
150 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700151}
152
153
Laurence Lundbladeee851742020-01-08 08:37:05 -0800154inline static int
155DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700156{
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700157 return pNesting->pCurrent->uCount == UINT16_MAX;
158}
159
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700160inline static int
161DecodeNesting_InMapMode(const QCBORDecodeNesting *pNesting)
162{
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700163 return (bool)pNesting->pCurrentMap->uMapMode;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700164}
165
Laurence Lundbladeee851742020-01-08 08:37:05 -0800166inline static uint8_t
167DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800168{
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800169 // Check in DecodeNesting_Descend and never having
Laurence Lundbladebb87be22020-04-09 19:15:32 -0700170 // QCBOR_MAX_ARRAY_NESTING > 255 gaurantees cast is safe
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800171 return (uint8_t)(pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]));
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800172}
173
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700174inline static uint8_t
175DecodeNesting_GetMapModeLevel(QCBORDecodeNesting *pNesting)
176{
177 // Check in DecodeNesting_Descend and never having
178 // QCBOR_MAX_ARRAY_NESTING > 255 gaurantees cast is safe
179 return (uint8_t)(pNesting->pCurrentMap - &(pNesting->pMapsAndArrays[0]));
180}
181
Laurence Lundbladeee851742020-01-08 08:37:05 -0800182inline static int
183DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700184{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700185 if(DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700186 return 0;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700187 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800188
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700189 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
190}
191
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800192// Process a break. This will either ascend the nesting or error out
Laurence Lundbladeee851742020-01-08 08:37:05 -0800193inline static QCBORError
194DecodeNesting_BreakAscend(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700195{
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800196 // breaks must always occur when there is nesting
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700197 if(DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800198 return QCBOR_ERR_BAD_BREAK;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700199 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800200
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800201 // breaks can only occur when the map/array is indefinite length
202 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
203 return QCBOR_ERR_BAD_BREAK;
204 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800205
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800206 // if all OK, the break reduces the level of nesting
207 pNesting->pCurrent--;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800208
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800209 return QCBOR_SUCCESS;
210}
211
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700212// Called on every single item except breaks including decode of a map/array
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700213/* Decrements the map/array counter if possible. If decrement
214 closed out a map or array, then level up in nesting and decrement
215 again, until, the top is reached or the end of a map mode is reached
216 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800217inline static void
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700218DecodeNesting_DecrementCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800219{
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700220 while(!DecodeNesting_IsAtTop(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700221 // Not at the top level, so there is decrementing to be done.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800222
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800223 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700224 // Decrement the current nesting level if it is not indefinite.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800225 pNesting->pCurrent->uCount--;
226 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700227
228 if(pNesting->pCurrent->uCount != 0) {
229 // Did not close out an array or map, so nothing further
230 break;
231 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700232
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700233 if(pNesting->pCurrent->uMapMode) {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700234 // In map mode the level-up must be done explicitly
235 break;
236 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700237
238 // Closed out an array or map so level up
239 pNesting->pCurrent--;
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700240 /*if(pNesting->pCurrent->uMapMode) {
241 // Bring the current map level along if new level is a map
242 // TODO: must search up until a mapmode level is found.
243 pNesting->pCurrentMap = pNesting->pCurrent;
244 } */
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700245
246 // Continue with loop to see if closing out this doesn't close out more
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700247 }
248}
249
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700250inline static void
251DecodeNesting_EnterMapMode(QCBORDecodeNesting *pNesting, size_t uOffset)
252{
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700253 pNesting->pCurrentMap = pNesting->pCurrent;
254 pNesting->pCurrentMap->uMapMode = 1;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700255 // Cast to uint32_t is safe because QCBOR onl works on data < UINT32_MAX
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700256 pNesting->pCurrentMap->uOffset = (uint32_t)uOffset;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700257}
258
259inline static void
260DecodeNesting_Exit(QCBORDecodeNesting *pNesting)
261{
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700262 pNesting->pCurrentMap->uMapMode = 0;
263 pNesting->pCurrent = pNesting->pCurrentMap - 1; // TODO error check
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700264
265 DecodeNesting_DecrementCount(pNesting);
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700266
267 while(1) {
268 pNesting->pCurrentMap--;
269 if(pNesting->pCurrentMap->uMapMode) {
270 break;
271 }
272 if(pNesting->pCurrentMap == &(pNesting->pMapsAndArrays[0])) {
273 break;
274 }
275 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700276}
277
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800278// Called on every map/array
Laurence Lundbladeee851742020-01-08 08:37:05 -0800279inline static QCBORError
280DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700281{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700282 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800283
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800284 if(pItem->val.uCount == 0) {
285 // Nothing to do for empty definite lenth arrays. They are just are
286 // effectively the same as an item that is not a map or array
287 goto Done;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530288 // Empty indefinite length maps and arrays are handled elsewhere
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800289 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800290
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800291 // Error out if arrays is too long to handle
292 if(pItem->val.uCount != UINT16_MAX && pItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700293 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
294 goto Done;
295 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800296
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800297 // Error out if nesting is too deep
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700298 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
299 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
300 goto Done;
301 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800302
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800303 // The actual descend
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700304 pNesting->pCurrent++;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800305
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800306 // Record a few details for this nesting level
307 pNesting->pCurrent->uMajorType = pItem->uDataType;
308 pNesting->pCurrent->uCount = pItem->val.uCount;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700309 pNesting->pCurrent->uSaveCount = pItem->val.uCount;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700310 pNesting->pCurrent->uMapMode = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800311
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700312Done:
313 return nReturn;;
314}
315
Laurence Lundbladeee851742020-01-08 08:37:05 -0800316inline static void
317DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700318{
319 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
320}
321
322
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700323static void DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
324{
325 *pSave = *pNesting;
326 pNesting->pCurrent = pNesting->pCurrentMap;
327
328 if(pNesting->pCurrent->uCount != UINT16_MAX) {
329 pNesting->pCurrent->uCount = pNesting->pCurrent->uSaveCount;
330 }
331}
332
333static void DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
334{
335 *pNesting = *pSave;
336}
337
338
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700339
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700340
Laurence Lundbladeee851742020-01-08 08:37:05 -0800341/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800342 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
343
344 The following four functions are pretty wrappers for invocation of
345 the string allocator supplied by the caller.
346
Laurence Lundbladeee851742020-01-08 08:37:05 -0800347 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800348
Laurence Lundbladeee851742020-01-08 08:37:05 -0800349static inline void
350StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800351{
352 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
353}
354
Laurence Lundbladeee851742020-01-08 08:37:05 -0800355// StringAllocator_Reallocate called with pMem NULL is
356// equal to StringAllocator_Allocate()
357static inline UsefulBuf
358StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
359 void *pMem,
360 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800361{
362 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
363}
364
Laurence Lundbladeee851742020-01-08 08:37:05 -0800365static inline UsefulBuf
366StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800367{
368 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
369}
370
Laurence Lundbladeee851742020-01-08 08:37:05 -0800371static inline void
372StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800373{
374 if(pMe->pfAllocator) {
375 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
376 }
377}
378
379
380
Laurence Lundbladeee851742020-01-08 08:37:05 -0800381/*===========================================================================
382 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700383
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800384 See qcbor/qcbor_decode.h for definition of the object
385 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800386 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700387/*
388 Public function, see header file
389 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800390void QCBORDecode_Init(QCBORDecodeContext *me,
391 UsefulBufC EncodedCBOR,
392 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700393{
394 memset(me, 0, sizeof(QCBORDecodeContext));
395 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800396 // Don't bother with error check on decode mode. If a bad value is
397 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700398 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700399 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700400 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
401 me->auMappedTags[i] = 0xffff;
402 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700403}
404
405
406/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700407 Public function, see header file
408 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800409void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
410 QCBORStringAllocate pfAllocateFunction,
411 void *pAllocateContext,
412 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700413{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800414 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
415 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
416 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700417}
418
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800419
420/*
421 Public function, see header file
422 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800423void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me,
424 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700425{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700426 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700427}
428
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700429
430/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800431 This decodes the fundamental part of a CBOR data item, the type and
432 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800433
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700434 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800435
Laurence Lundbladeee851742020-01-08 08:37:05 -0800436 This does the network->host byte order conversion. The conversion
437 here also results in the conversion for floats in addition to that
438 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800439
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700440 This returns:
441 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800442
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800443 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800444 tags and floats and length for strings and arrays
445
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800446 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800447 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800448
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800449 The int type is preferred to uint8_t for some variables as this
450 avoids integer promotions, can reduce code size and makes
451 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700452 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800453inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
454 int *pnMajorType,
455 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800456 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700457{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700458 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800459
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700460 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800461 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800462
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700463 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800464 const int nTmpMajorType = nInitialByte >> 5;
465 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800466
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800467 // Where the number or argument accumulates
468 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800469
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800470 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800471 // Need to get 1,2,4 or 8 additional argument bytes Map
472 // LEN_IS_ONE_BYTE.. LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800473 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800474
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800475 // Loop getting all the bytes in the argument
476 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800477 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800478 // This shift and add gives the endian conversion
479 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
480 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800481 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800482 // The reserved and thus-far unused additional info values
483 nReturn = QCBOR_ERR_UNSUPPORTED;
484 goto Done;
485 } else {
486 // Less than 24, additional info is argument or 31, an indefinite length
487 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800488 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700489 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800490
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700491 if(UsefulInputBuf_GetError(pUInBuf)) {
492 nReturn = QCBOR_ERR_HIT_END;
493 goto Done;
494 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800495
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700496 // All successful if we got here.
497 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800498 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800499 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800500 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800501
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700502Done:
503 return nReturn;
504}
505
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800506
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700507/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800508 CBOR doesn't explicitly specify two's compliment for integers but all
509 CPUs use it these days and the test vectors in the RFC are so. All
510 integers in the CBOR structure are positive and the major type
511 indicates positive or negative. CBOR can express positive integers
512 up to 2^x - 1 where x is the number of bits and negative integers
513 down to 2^x. Note that negative numbers can be one more away from
514 zero than positive. Stdint, as far as I can tell, uses two's
515 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800516
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700517 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800518 used carefully here, and in particular why it isn't used in the interface.
519 Also see
520 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
521
522 Int is used for values that need less than 16-bits and would be subject
523 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700524 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800525inline static QCBORError
526DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700527{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700528 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800529
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700530 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
531 if (uNumber <= INT64_MAX) {
532 pDecodedItem->val.int64 = (int64_t)uNumber;
533 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800534
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700535 } else {
536 pDecodedItem->val.uint64 = uNumber;
537 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800538
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700539 }
540 } else {
541 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800542 // CBOR's representation of negative numbers lines up with the
543 // two-compliment representation. A negative integer has one
544 // more in range than a positive integer. INT64_MIN is
545 // equal to (-INT64_MAX) - 1.
546 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700547 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800548
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700549 } else {
550 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000551 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700552 nReturn = QCBOR_ERR_INT_OVERFLOW;
553 }
554 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800555
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700556 return nReturn;
557}
558
559// Make sure #define value line up as DecodeSimple counts on this.
560#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
561#error QCBOR_TYPE_FALSE macro value wrong
562#endif
563
564#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
565#error QCBOR_TYPE_TRUE macro value wrong
566#endif
567
568#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
569#error QCBOR_TYPE_NULL macro value wrong
570#endif
571
572#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
573#error QCBOR_TYPE_UNDEF macro value wrong
574#endif
575
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700576#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
577#error QCBOR_TYPE_BREAK macro value wrong
578#endif
579
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700580#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
581#error QCBOR_TYPE_DOUBLE macro value wrong
582#endif
583
584#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
585#error QCBOR_TYPE_FLOAT macro value wrong
586#endif
587
588/*
589 Decode true, false, floats, break...
590 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800591inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800592DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700593{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700594 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800595
Laurence Lundbladeee851742020-01-08 08:37:05 -0800596 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800597 // above make sure uAdditionalInfo values line up with uDataType values.
598 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
599 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800600
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800601 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800602 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
603 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800604
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700605 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700606 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
607 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700608 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700609 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700610 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
611 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700612 break;
613 case DOUBLE_PREC_FLOAT:
614 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700615 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700616 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800617
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700618 case CBOR_SIMPLEV_FALSE: // 20
619 case CBOR_SIMPLEV_TRUE: // 21
620 case CBOR_SIMPLEV_NULL: // 22
621 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700622 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700623 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800624
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700625 case CBOR_SIMPLEV_ONEBYTE: // 24
626 if(uNumber <= CBOR_SIMPLE_BREAK) {
627 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700628 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700629 goto Done;
630 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800631 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700632 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800633
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700634 default: // 0-19
635 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800636 /*
637 DecodeTypeAndNumber will make uNumber equal to
638 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
639 safe because the 2, 4 and 8 byte lengths of uNumber are in
640 the double/float cases above
641 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700642 pDecodedItem->val.uSimple = (uint8_t)uNumber;
643 break;
644 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800645
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700646Done:
647 return nReturn;
648}
649
650
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700651/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530652 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700653 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800654inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
655 int nMajorType,
656 uint64_t uStrLen,
657 UsefulInputBuf *pUInBuf,
658 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700659{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700660 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800661
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800662 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
663 // This check makes the casts to size_t below safe.
664
665 // 4 bytes less than the largest sizeof() so this can be tested by
666 // putting a SIZE_MAX length in the CBOR test input (no one will
667 // care the limit on strings is 4 bytes shorter).
668 if(uStrLen > SIZE_MAX-4) {
669 nReturn = QCBOR_ERR_STRING_TOO_LONG;
670 goto Done;
671 }
672
673 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530674 if(UsefulBuf_IsNULLC(Bytes)) {
675 // Failed to get the bytes for this string item
676 nReturn = QCBOR_ERR_HIT_END;
677 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700678 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530679
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800680 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530681 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800682 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530683 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700684 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530685 goto Done;
686 }
687 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800688 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530689 } else {
690 // Normal case with no string allocator
691 pDecodedItem->val.string = Bytes;
692 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800693 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800694 // Cast because ternary operator causes promotion to integer
695 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
696 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800697
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530698Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700699 return nReturn;
700}
701
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700702
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800703
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700704
705
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700706
707
Laurence Lundbladeee851742020-01-08 08:37:05 -0800708// Make sure the constants align as this is assumed by
709// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700710#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
711#error QCBOR_TYPE_ARRAY value not lined up with major type
712#endif
713#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
714#error QCBOR_TYPE_MAP value not lined up with major type
715#endif
716
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700717/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800718 This gets a single data item and decodes it including preceding
719 optional tagging. This does not deal with arrays and maps and nesting
720 except to decode the data item introducing them. Arrays and maps are
721 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800722
Laurence Lundbladeee851742020-01-08 08:37:05 -0800723 Errors detected here include: an array that is too long to decode,
724 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700725 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800726static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
727 QCBORItem *pDecodedItem,
728 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700729{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700730 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800731
Laurence Lundbladeee851742020-01-08 08:37:05 -0800732 /*
733 Get the major type and the number. Number could be length of more
734 bytes or the value depending on the major type nAdditionalInfo is
735 an encoding of the length of the uNumber and is needed to decode
736 floats and doubles
737 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800738 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700739 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800740 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800741
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700742 memset(pDecodedItem, 0, sizeof(QCBORItem));
743
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800744 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800745
Laurence Lundbladeee851742020-01-08 08:37:05 -0800746 // Error out here if we got into trouble on the type and number. The
747 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700748 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700749 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700750 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800751
Laurence Lundbladeee851742020-01-08 08:37:05 -0800752 // At this point the major type and the value are valid. We've got
753 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800754 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700755 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
756 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800757 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700758 nReturn = QCBOR_ERR_BAD_INT;
759 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800760 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700761 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700762 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800763
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700764 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
765 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800766 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
767 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
768 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
769 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530770 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700771 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800772 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700773 }
774 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800775
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700776 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
777 case CBOR_MAJOR_TYPE_MAP: // Major type 5
778 // Record the number of items in the array or map
779 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
780 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
781 goto Done;
782 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800783 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530784 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700785 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800786 // type conversion OK because of check above
787 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700788 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800789 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800790 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
791 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700792 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800793
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700794 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800795 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700796 nReturn = QCBOR_ERR_BAD_INT;
797 } else {
798 pDecodedItem->val.uTagV = uNumber;
799 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
800 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700801 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800802
Laurence Lundbladeee851742020-01-08 08:37:05 -0800803 case CBOR_MAJOR_TYPE_SIMPLE:
804 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800805 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700806 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800807
Laurence Lundbladeee851742020-01-08 08:37:05 -0800808 default:
809 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700810 nReturn = QCBOR_ERR_UNSUPPORTED;
811 break;
812 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800813
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700814Done:
815 return nReturn;
816}
817
818
819
820/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800821 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -0800822 individual chunk items together into one QCBORItem using the string
823 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800824
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530825 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700826 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800827static inline QCBORError
828GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700829{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700830 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700831
832 // Get pointer to string allocator. First use is to pass it to
833 // GetNext_Item() when option is set to allocate for *every* string.
834 // Second use here is to allocate space to coallese indefinite
835 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800836 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
837 &(me->StringAllocator) :
838 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800839
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700840 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800841 nReturn = GetNext_Item(&(me->InBuf),
842 pDecodedItem,
843 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700844 if(nReturn) {
845 goto Done;
846 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800847
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700848 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530849 // code in this function from here down can be eliminated. Run tests, except
850 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800851
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800852 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700853 const uint8_t uStringType = pDecodedItem->uDataType;
854 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700855 goto Done; // no need to do any work here on non-string types
856 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800857
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800858 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530859 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800860 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700861 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800862
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530863 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800864 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700865 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
866 goto Done;
867 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800868
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700869 // Loop getting chunk of indefinite string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700870 UsefulBufC FullString = NULLUsefulBufC;
871
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700872 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700873 // Get item for next chunk
874 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700875 // NULL string allocator passed here. Do not need to allocate
876 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -0800877 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700878 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700879 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700880 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800881
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530882 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700883 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800884 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700885 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530886 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700887 break;
888 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800889
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700890 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530891 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700892 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800893 if(StringChunkItem.uDataType != uStringType ||
894 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700895 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700896 break;
897 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800898
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530899 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800900 // The first time throurgh FullString.ptr is NULL and this is
901 // equivalent to StringAllocator_Allocate()
902 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
903 UNCONST_POINTER(FullString.ptr),
904 FullString.len + StringChunkItem.val.string.len);
905
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700906 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530907 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +0700908 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700909 break;
910 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800911
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700912 // Copy new string chunk at the end of string so far.
913 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700914 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800915
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800916 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
917 // Getting the item failed, clean up the allocated memory
918 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700919 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800920
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -0700921Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700922 return nReturn;
923}
924
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700925
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700926uint64_t ConvertTag(QCBORDecodeContext *me, uint16_t uTagVal) {
927 if(uTagVal < 0xfff0) {
928 return uTagVal;
929 } else {
930 // TODO constant and error check
931 int x = uTagVal - 0xfff0;
932 return me->auMappedTags[x];
933 }
934}
935
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700936/*
Laurence Lundblade59289e52019-12-30 13:44:37 -0800937 Gets all optional tag data items preceding a data item that is not an
938 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700939 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800940static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700941GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700942{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700943 // Stack usage: int/ptr: 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +0700944 QCBORError nReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700945
946 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {0xffff, 0xffff, 0xffff, 0xffff};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700947
Laurence Lundblade59289e52019-12-30 13:44:37 -0800948 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700949 for(;;) {
950 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700951 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700952 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700953 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800954
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700955 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
956 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700957 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700958 break;
959 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800960
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700961 // Is there room for the tag in the tags list?
962 size_t uTagIndex;
963 for(uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
964 if(auTags[uTagIndex] == 0xffff) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700965 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700966 }
967 }
968 if(uTagIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
969 return 99; // TODO error code
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700970 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800971
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700972 // Is the tag > 16 bits?
973 if(pDecodedItem->val.uTagV > 0xffff) {
974 size_t uTagMapIndex;
975 // Is there room in the tag map?
976 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
977 if(me->auMappedTags[uTagMapIndex] == 0xffff) {
978 break;
979 }
980 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
981 break;
982 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700983 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700984 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
985 // No room for the tag
986 return 97; // TODO error code
987 }
988
989 // Cover the case where tag is new and were it is already in the map
990 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
991 auTags[uTagIndex] = (uint16_t)(uTagMapIndex + 0xfff0); // TODO proper constant and cast
992
993 } else {
994 auTags[uTagIndex] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700995 }
996 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800997
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700998Done:
999 return nReturn;
1000}
1001
1002
1003/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001004 This layer takes care of map entries. It combines the label and data
1005 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001006 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001007static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001008GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001009{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001010 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001011 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001012 if(nReturn)
1013 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001014
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001015 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001016 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001017 goto Done;
1018 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001019
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001020 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1021 // In a map and caller wants maps decoded, not treated as arrays
1022
1023 if(DecodeNesting_TypeIsMap(&(me->nesting))) {
1024 // If in a map and the right decoding mode, get the label
1025
Laurence Lundbladeee851742020-01-08 08:37:05 -08001026 // Save label in pDecodedItem and get the next which will
1027 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001028 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001029 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001030 if(nReturn)
1031 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001032
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301033 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001034
1035 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1036 // strings are always good labels
1037 pDecodedItem->label.string = LabelItem.val.string;
1038 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1039 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001040 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001041 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1042 goto Done;
1043 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1044 pDecodedItem->label.int64 = LabelItem.val.int64;
1045 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1046 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1047 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1048 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1049 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1050 pDecodedItem->label.string = LabelItem.val.string;
1051 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1052 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1053 } else {
1054 // label is not an int or a string. It is an arrray
1055 // or a float or such and this implementation doesn't handle that.
1056 // Also, tags on labels are ignored.
1057 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1058 goto Done;
1059 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001060 }
1061 } else {
1062 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001063 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1064 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
1065 goto Done;
1066 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001067 // Decoding a map as an array
1068 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001069 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1070 // Cast is needed because of integer promotion
1071 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001072 }
1073 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001074
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001075Done:
1076 return nReturn;
1077}
1078
1079
1080/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001081 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001082 TODO: correct this comment
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001083 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001084static QCBORError
1085QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001086{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001087 // Stack ptr/int: 2, QCBORItem : 64
1088
Laurence Lundblade30816f22018-11-10 13:40:22 +07001089 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001090
Laurence Lundblade937ea812020-05-08 11:38:23 -07001091 /* For a pre-order traversal a non-error end occurs when there
1092 are no more bytes to consume and the nesting level is at the top.
1093 If it's not at the top, then the CBOR is not well formed. This error
1094 is caught elsewhere.
1095
1096 This handles the end of CBOR sequences as well as non-sequences. */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001097 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0 && DecodeNesting_IsAtTop(&(me->nesting))) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001098 nReturn = QCBOR_ERR_NO_MORE_ITEMS;
1099 goto Done;
1100 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001101
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001102 /* It is also an end of the input when in map mode and the cursor
Laurence Lundblade937ea812020-05-08 11:38:23 -07001103 is at the end of the map */
1104
1105
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001106 // This is to handle map and array mode
Laurence Lundblade937ea812020-05-08 11:38:23 -07001107 if(DecodeNesting_AtEnd(&(me->nesting))) {
1108// if(UsefulInputBuf_Tell(&(me->InBuf)) != 0 && DecodeNesting_AtEnd(&(me->nesting))) {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001109 nReturn = QCBOR_ERR_NO_MORE_ITEMS;
1110 goto Done;
1111 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001112
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001113 nReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001114 if(nReturn) {
1115 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001116 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301117
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001118 // Breaks ending arrays/maps are always processed at the end of this function.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301119 // They should never show up here.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301120 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301121 nReturn = QCBOR_ERR_BAD_BREAK;
1122 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301123 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001124
Laurence Lundblade6de37062018-10-15 12:22:42 +05301125 // Record the nesting level for this data item before processing any of
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301126 // decrementing and descending.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301127 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001128
Laurence Lundblade6de37062018-10-15 12:22:42 +05301129 // Process the item just received for descent or decrement, and
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001130 // ascend if decrements are enough to close out a definite length array/map
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001131 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001132 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001133 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001134 // Maps and arrays do count in as items in the map/array that encloses
1135 // them so a decrement needs to be done for them too, but that is done
1136 // only when all the items in them have been processed, not when they
Laurence Lundblade9916b1b2019-09-07 22:33:25 -07001137 // are opened with the exception of an empty map or array.
1138 if(pDecodedItem->val.uCount == 0) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001139 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundblade9916b1b2019-09-07 22:33:25 -07001140 }
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001141 } else {
1142 // Decrement the count of items in the enclosing map/array
1143 // If the count in the enclosing map/array goes to zero, that
Laurence Lundblade6de37062018-10-15 12:22:42 +05301144 // triggers a decrement in the map/array above that and
1145 // an ascend in nesting level.
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001146 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001147 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301148 if(nReturn) {
1149 goto Done;
1150 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001151
Laurence Lundblade6de37062018-10-15 12:22:42 +05301152 // For indefinite length maps/arrays, looking at any and
1153 // all breaks that might terminate them. The equivalent
1154 // for definite length maps/arrays happens in
1155 // DecodeNesting_DecrementCount().
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001156 if(!DecodeNesting_IsAtTop(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301157 while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1158 // Peek forward one item to see if it is a break.
1159 QCBORItem Peek;
1160 size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
1161 nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL);
1162 if(nReturn) {
1163 goto Done;
1164 }
1165 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
1166 // It is not a break, rewind so it can be processed normally.
1167 UsefulInputBuf_Seek(&(me->InBuf), uPeek);
1168 break;
1169 }
1170 // It is a break. Ascend one nesting level.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301171 // The break is consumed.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301172 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
1173 if(nReturn) {
1174 // break occured outside of an indefinite length array/map
1175 goto Done;
1176 }
1177 }
1178 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001179
Laurence Lundblade6de37062018-10-15 12:22:42 +05301180 // Tell the caller what level is next. This tells them what maps/arrays
1181 // were closed out and makes it possible for them to reconstruct
1182 // the tree with just the information returned by GetNext
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07001183 // TODO: pull this into DecodeNesting_GetLevel
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001184 if(me->nesting.pCurrent->uMapMode && me->nesting.pCurrent->uCount == 0) {
1185 // At end of a map / array in map mode, so next nest is 0 to
1186 // indicate this end.
1187 pDecodedItem->uNextNestLevel = 0;
1188 } else {
1189 pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting));
1190 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001191
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001192Done:
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001193 if(nReturn != QCBOR_SUCCESS) {
1194 // Make sure uDataType and uLabelType are QCBOR_TYPE_NONE
1195 memset(pDecodedItem, 0, sizeof(QCBORItem));
1196 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001197 return nReturn;
1198}
1199
1200
Laurence Lundblade59289e52019-12-30 13:44:37 -08001201/*
1202 Mostly just assign the right data type for the date string.
1203 */
1204inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1205{
1206 // Stack Use: UsefulBuf 1 16
1207 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1208 return QCBOR_ERR_BAD_OPT_TAG;
1209 }
1210
1211 const UsefulBufC Temp = pDecodedItem->val.string;
1212 pDecodedItem->val.dateString = Temp;
1213 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1214 return QCBOR_SUCCESS;
1215}
1216
1217
1218/*
1219 Mostly just assign the right data type for the bignum.
1220 */
1221inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1222{
1223 // Stack Use: UsefulBuf 1 -- 16
1224 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1225 return QCBOR_ERR_BAD_OPT_TAG;
1226 }
1227 const UsefulBufC Temp = pDecodedItem->val.string;
1228 pDecodedItem->val.bigNum = Temp;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001229 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001230 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1231 : QCBOR_TYPE_NEGBIGNUM);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001232 return QCBOR_SUCCESS;
1233}
1234
1235
1236/*
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001237 Mostly just assign the right data type for the bignum.
1238 */
1239inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
1240{
1241 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1242 return QCBOR_ERR_BAD_OPT_TAG;
1243 }
1244 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
1245 return QCBOR_SUCCESS;
1246}
1247
1248
1249/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001250 The epoch formatted date. Turns lots of different forms of encoding
1251 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001252 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001253static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001254{
1255 // Stack usage: 1
1256 QCBORError nReturn = QCBOR_SUCCESS;
1257
1258 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1259
1260 switch (pDecodedItem->uDataType) {
1261
1262 case QCBOR_TYPE_INT64:
1263 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1264 break;
1265
1266 case QCBOR_TYPE_UINT64:
1267 if(pDecodedItem->val.uint64 > INT64_MAX) {
1268 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1269 goto Done;
1270 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001271 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001272 break;
1273
1274 case QCBOR_TYPE_DOUBLE:
1275 {
1276 // This comparison needs to be done as a float before
1277 // conversion to an int64_t to be able to detect doubles
1278 // that are too large to fit into an int64_t. A double
1279 // has 52 bits of preceision. An int64_t has 63. Casting
1280 // INT64_MAX to a double actually causes a round up which
1281 // is bad and wrong for the comparison because it will
1282 // allow conversion of doubles that can't fit into a
1283 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1284 // the cutoff point as if that rounds up in conversion to
1285 // double it will still be less than INT64_MAX. 0x7ff is
1286 // picked because it has 11 bits set.
1287 //
1288 // INT64_MAX seconds is on the order of 10 billion years,
1289 // and the earth is less than 5 billion years old, so for
1290 // most uses this conversion error won't occur even though
1291 // doubles can go much larger.
1292 //
1293 // Without the 0x7ff there is a ~30 minute range of time
1294 // values 10 billion years in the past and in the future
1295 // where this this code would go wrong.
1296 const double d = pDecodedItem->val.dfnum;
1297 if(d > (double)(INT64_MAX - 0x7ff)) {
1298 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1299 goto Done;
1300 }
1301 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1302 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1303 }
1304 break;
1305
1306 default:
1307 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1308 goto Done;
1309 }
1310 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1311
1312Done:
1313 return nReturn;
1314}
1315
1316
1317#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1318/*
1319 Decode decimal fractions and big floats.
1320
1321 When called pDecodedItem must be the array that is tagged as a big
1322 float or decimal fraction, the array that has the two members, the
1323 exponent and mantissa.
1324
1325 This will fetch and decode the exponent and mantissa and put the
1326 result back into pDecodedItem.
1327 */
1328inline static QCBORError
1329QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1330{
1331 QCBORError nReturn;
1332
1333 // --- Make sure it is an array; track nesting level of members ---
1334 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1335 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1336 goto Done;
1337 }
1338
1339 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001340 // definite length arrays, but not for indefnite. Instead remember
1341 // the nesting level the two integers must be at, which is one
1342 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001343 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1344
1345 // --- Is it a decimal fraction or a bigfloat? ---
1346 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1347 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1348
1349 // --- Get the exponent ---
1350 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001351 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001352 if(nReturn != QCBOR_SUCCESS) {
1353 goto Done;
1354 }
1355 if(exponentItem.uNestingLevel != nNestLevel) {
1356 // Array is empty or a map/array encountered when expecting an int
1357 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1358 goto Done;
1359 }
1360 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1361 // Data arriving as an unsigned int < INT64_MAX has been converted
1362 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1363 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1364 // will be too large for this to handle and thus an error that will
1365 // get handled in the next else.
1366 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1367 } else {
1368 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1369 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1370 goto Done;
1371 }
1372
1373 // --- Get the mantissa ---
1374 QCBORItem mantissaItem;
1375 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1376 if(nReturn != QCBOR_SUCCESS) {
1377 goto Done;
1378 }
1379 if(mantissaItem.uNestingLevel != nNestLevel) {
1380 // Mantissa missing or map/array encountered when expecting number
1381 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1382 goto Done;
1383 }
1384 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1385 // Data arriving as an unsigned int < INT64_MAX has been converted
1386 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1387 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1388 // will be too large for this to handle and thus an error that
1389 // will get handled in an else below.
1390 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1391 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1392 // Got a good big num mantissa
1393 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1394 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001395 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1396 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1397 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001398 } else {
1399 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1400 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1401 goto Done;
1402 }
1403
1404 // --- Check that array only has the two numbers ---
1405 if(mantissaItem.uNextNestLevel == nNestLevel) {
1406 // Extra items in the decimal fraction / big num
1407 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1408 goto Done;
1409 }
1410
1411Done:
1412
1413 return nReturn;
1414}
1415#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1416
1417
1418/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001419 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001420 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001421QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001422QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001423{
1424 QCBORError nReturn;
1425
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001426 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001427 if(nReturn != QCBOR_SUCCESS) {
1428 goto Done;
1429 }
1430
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001431 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
1432 switch(pDecodedItem->uTags[i] ) {
1433 case 0xffff:
1434 // The end of the tag list or no tags
1435 // Successful exit from the loop.
1436 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001437
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001438 case CBOR_TAG_DATE_STRING:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001439 nReturn = DecodeDateString(pDecodedItem);
1440 break;
1441
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001442 case CBOR_TAG_DATE_EPOCH:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001443 nReturn = DecodeDateEpoch(pDecodedItem);
1444 break;
1445
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001446 case CBOR_TAG_POS_BIGNUM:
1447 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001448 nReturn = DecodeBigNum(pDecodedItem);
1449 break;
1450
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001451 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1452 case CBOR_TAG_DECIMAL_FRACTION:
1453 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001454 // For aggregate tagged types, what goes into pTags is only collected
1455 // from the surrounding data item, not the contents, so pTags is not
1456 // passed on here.
1457
1458 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1459 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001460 #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001461
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001462 case CBOR_TAG_BIN_UUID:
1463 nReturn = DecodeUUID(pDecodedItem);
1464
1465 default:
1466 // A tag that is not understood
1467 // A successful exit from the loop
1468 goto Done;
1469
1470 }
1471 if(nReturn != QCBOR_SUCCESS) {
1472 goto Done;
1473 }
Laurence Lundblade59289e52019-12-30 13:44:37 -08001474 }
1475
1476Done:
1477 if(nReturn != QCBOR_SUCCESS) {
1478 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1479 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1480 }
1481 return nReturn;
1482}
1483
1484
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001485QCBORError QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
1486{
1487 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
1488
1489 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
1490
1491 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
1492
1493 return uErr;
1494}
1495
1496
Laurence Lundblade59289e52019-12-30 13:44:37 -08001497/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001498 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001499 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001500QCBORError
1501QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1502 QCBORItem *pDecodedItem,
1503 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001504{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001505 QCBORError nReturn;
1506
1507 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
1508 if(nReturn != QCBOR_SUCCESS) {
1509 return nReturn;
1510 }
1511
1512 if(pTags != NULL) {
1513 pTags->uNumUsed = 0;
1514 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
1515 if(pDecodedItem->uTags[i] == 0xffff) {
1516 break;
1517 }
1518 if(pTags->uNumUsed >= pTags->uNumAllocated) {
1519 return QCBOR_ERR_TOO_MANY_TAGS;
1520 }
1521 pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]);
1522 pTags->uNumUsed++;
1523 }
1524 }
1525
1526 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001527}
1528
1529
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001530/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301531 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301532 next one down. If a layer has no work to do for a particular item
1533 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001534
Laurence Lundblade59289e52019-12-30 13:44:37 -08001535 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1536 tagged data items, turning them into the local C representation.
1537 For the most simple it is just associating a QCBOR_TYPE with the data. For
1538 the complex ones that an aggregate of data items, there is some further
1539 decoding and a little bit of recursion.
1540
1541 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301542 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301543 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001544 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001545
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301546 - GetNext_MapEntry -- This handles the combining of two
1547 items, the label and the data, that make up a map entry.
1548 It only does work on maps. It combines the label and data
1549 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001550
Laurence Lundblade59289e52019-12-30 13:44:37 -08001551 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1552 tags into bit flags associated with the data item. No actual decoding
1553 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001554
Laurence Lundblade59289e52019-12-30 13:44:37 -08001555 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301556 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301557 string allocater to create contiguous space for the item. It
1558 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001559
Laurence Lundblade59289e52019-12-30 13:44:37 -08001560 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1561 atomic data item has a "major type", an integer "argument" and optionally
1562 some content. For text and byte strings, the content is the bytes
1563 that make up the string. These are the smallest data items that are
1564 considered to be well-formed. The content may also be other data items in
1565 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001566
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001567 Roughly this takes 300 bytes of stack for vars. Need to
1568 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001569
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301570 */
1571
1572
1573/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001574 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001575 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001576int QCBORDecode_IsTagged(QCBORDecodeContext *me,
1577 const QCBORItem *pItem,
1578 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001579{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001580 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++ ) {
1581 if(pItem->uTags[i] == 0xffff) {
1582 break;
1583 }
1584 if(ConvertTag(me, pItem->uTags[i]) == uTag) {
1585 return 1;
1586 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001587 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001588
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001589 return 0;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001590}
1591
1592
1593/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001594 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001595 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001596QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001597{
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001598 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001599
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001600 // Error out if all the maps/arrays are not closed out
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001601 if(!DecodeNesting_IsAtTop(&(me->nesting))) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001602 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1603 goto Done;
1604 }
1605
1606 // Error out if not all the bytes are consumed
1607 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1608 nReturn = QCBOR_ERR_EXTRA_BYTES;
1609 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001610
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001611Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301612 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001613 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001614 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001615
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001616 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001617}
1618
1619
1620
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001621/*
1622
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001623Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001624
Laurence Lundbladeee851742020-01-08 08:37:05 -08001625 - Hit end of input before it was expected while decoding type and
1626 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001627
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001628 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001629
Laurence Lundbladeee851742020-01-08 08:37:05 -08001630 - Hit end of input while decoding a text or byte string
1631 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001632
Laurence Lundbladeee851742020-01-08 08:37:05 -08001633 - Encountered conflicting tags -- e.g., an item is tagged both a date
1634 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001635
Laurence Lundbladeee851742020-01-08 08:37:05 -08001636 - Encontered an array or mapp that has too many items
1637 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001638
Laurence Lundbladeee851742020-01-08 08:37:05 -08001639 - Encountered array/map nesting that is too deep
1640 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001641
Laurence Lundbladeee851742020-01-08 08:37:05 -08001642 - An epoch date > INT64_MAX or < INT64_MIN was encountered
1643 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001644
Laurence Lundbladeee851742020-01-08 08:37:05 -08001645 - The type of a map label is not a string or int
1646 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001647
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001648 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001649
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001650 */
1651
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001652
1653
Laurence Lundbladef6531662018-12-04 10:42:22 +09001654
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001655/* ===========================================================================
1656 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001657
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001658 This implements a simple sting allocator for indefinite length
1659 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
1660 implements the function type QCBORStringAllocate and allows easy
1661 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09001662
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001663 This particular allocator is built-in for convenience. The caller
1664 can implement their own. All of this following code will get
1665 dead-stripped if QCBORDecode_SetMemPool() is not called.
1666
1667 This is a very primitive memory allocator. It does not track
1668 individual allocations, only a high-water mark. A free or
1669 reallocation must be of the last chunk allocated.
1670
1671 The size of the pool and offset to free memory are packed into the
1672 first 8 bytes of the memory pool so we don't have to keep them in
1673 the decode context. Since the address of the pool may not be
1674 aligned, they have to be packed and unpacked as if they were
1675 serialized data of the wire or such.
1676
1677 The sizes packed in are uint32_t to be the same on all CPU types
1678 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08001679 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001680
1681
Laurence Lundbladeee851742020-01-08 08:37:05 -08001682static inline int
1683MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001684{
1685 // Use of UsefulInputBuf is overkill, but it is convenient.
1686 UsefulInputBuf UIB;
1687
Laurence Lundbladeee851742020-01-08 08:37:05 -08001688 // Just assume the size here. It was checked during SetUp so
1689 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001690 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
1691 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
1692 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
1693 return UsefulInputBuf_GetError(&UIB);
1694}
1695
1696
Laurence Lundbladeee851742020-01-08 08:37:05 -08001697static inline int
1698MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001699{
1700 // Use of UsefulOutBuf is overkill, but convenient. The
1701 // length check performed here is useful.
1702 UsefulOutBuf UOB;
1703
1704 UsefulOutBuf_Init(&UOB, Pool);
1705 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
1706 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
1707 return UsefulOutBuf_GetError(&UOB);
1708}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001709
1710
1711/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001712 Internal function for an allocation, reallocation free and destuct.
1713
1714 Having only one function rather than one each per mode saves space in
1715 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001716
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001717 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1718 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001719static UsefulBuf
1720MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001721{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001722 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001723
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001724 uint32_t uPoolSize;
1725 uint32_t uFreeOffset;
1726
1727 if(uNewSize > UINT32_MAX) {
1728 // This allocator is only good up to 4GB. This check should
1729 // optimize out if sizeof(size_t) == sizeof(uint32_t)
1730 goto Done;
1731 }
1732 const uint32_t uNewSize32 = (uint32_t)uNewSize;
1733
1734 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
1735 goto Done;
1736 }
1737
1738 if(uNewSize) {
1739 if(pMem) {
1740 // REALLOCATION MODE
1741 // Calculate pointer to the end of the memory pool. It is
1742 // assumed that pPool + uPoolSize won't wrap around by
1743 // assuming the caller won't pass a pool buffer in that is
1744 // not in legitimate memory space.
1745 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
1746
1747 // Check that the pointer for reallocation is in the range of the
1748 // pool. This also makes sure that pointer math further down
1749 // doesn't wrap under or over.
1750 if(pMem >= pPool && pMem < pPoolEnd) {
1751 // Offset to start of chunk for reallocation. This won't
1752 // wrap under because of check that pMem >= pPool. Cast
1753 // is safe because the pool is always less than UINT32_MAX
1754 // because of check in QCBORDecode_SetMemPool().
1755 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1756
1757 // Check to see if the allocation will fit. uPoolSize -
1758 // uMemOffset will not wrap under because of check that
1759 // pMem is in the range of the uPoolSize by check above.
1760 if(uNewSize <= uPoolSize - uMemOffset) {
1761 ReturnValue.ptr = pMem;
1762 ReturnValue.len = uNewSize;
1763
1764 // Addition won't wrap around over because uNewSize was
1765 // checked to be sure it is less than the pool size.
1766 uFreeOffset = uMemOffset + uNewSize32;
1767 }
1768 }
1769 } else {
1770 // ALLOCATION MODE
1771 // uPoolSize - uFreeOffset will not underflow because this
1772 // pool implementation makes sure uFreeOffset is always
1773 // smaller than uPoolSize through this check here and
1774 // reallocation case.
1775 if(uNewSize <= uPoolSize - uFreeOffset) {
1776 ReturnValue.len = uNewSize;
1777 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001778 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001779 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001780 }
1781 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001782 if(pMem) {
1783 // FREE MODE
1784 // Cast is safe because of limit on pool size in
1785 // QCBORDecode_SetMemPool()
1786 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1787 } else {
1788 // DESTRUCT MODE
1789 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001790 }
1791 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001792
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001793 UsefulBuf Pool = {pPool, uPoolSize};
1794 MemPool_Pack(Pool, uFreeOffset);
1795
1796Done:
1797 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001798}
1799
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001800
Laurence Lundbladef6531662018-12-04 10:42:22 +09001801/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001802 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09001803 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001804QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
1805 UsefulBuf Pool,
1806 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001807{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001808 // The pool size and free mem offset are packed into the beginning
1809 // of the pool memory. This compile time check make sure the
1810 // constant in the header is correct. This check should optimize
1811 // down to nothing.
1812 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001813 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001814 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001815
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001816 // The pool size and free offset packed in to the beginning of pool
1817 // memory are only 32-bits. This check will optimize out on 32-bit
1818 // machines.
1819 if(Pool.len > UINT32_MAX) {
1820 return QCBOR_ERR_BUFFER_TOO_LARGE;
1821 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001822
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001823 // This checks that the pool buffer given is big enough.
1824 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
1825 return QCBOR_ERR_BUFFER_TOO_SMALL;
1826 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001827
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001828 pMe->StringAllocator.pfAllocator = MemPool_Function;
1829 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
1830 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001831
Laurence Lundblade30816f22018-11-10 13:40:22 +07001832 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001833}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001834
Laurence Lundblade1341c592020-04-11 14:19:05 -07001835#include <stdio.h>
1836void printdecode(QCBORDecodeContext *pMe, const char *szName)
1837{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001838 printf("---%s--%d--%d--\nLevel Count Type Offset SaveCount MapMode\n",
1839 szName,
1840 (uint32_t)pMe->InBuf.cursor,
1841 (uint32_t)pMe->InBuf.UB.len);
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001842 for(int i = 0; i < QCBOR_MAX_ARRAY_NESTING; i++) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001843 if(&(pMe->nesting.pMapsAndArrays[i]) > pMe->nesting.pCurrent) {
1844 break;
1845 }
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001846 printf("%2s %2d %5d %s %6u %2d %d\n",
1847 pMe->nesting.pCurrentMap == &(pMe->nesting.pMapsAndArrays[i]) ? "->": " ",
Laurence Lundblade1341c592020-04-11 14:19:05 -07001848 i,
1849 pMe->nesting.pMapsAndArrays[i].uCount,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001850 pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_MAP ? " map" :
1851 (pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_ARRAY ? "array" :
1852 (pMe->nesting.pMapsAndArrays[i].uMajorType == QCBOR_TYPE_NONE ? " none" : "?????")),
Laurence Lundblade1341c592020-04-11 14:19:05 -07001853 pMe->nesting.pMapsAndArrays[i].uOffset,
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001854 pMe->nesting.pMapsAndArrays[i].uSaveCount,
1855 pMe->nesting.pMapsAndArrays[i].uMapMode
Laurence Lundblade1341c592020-04-11 14:19:05 -07001856 );
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001857
Laurence Lundblade1341c592020-04-11 14:19:05 -07001858 }
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001859 printf("\n");
Laurence Lundblade1341c592020-04-11 14:19:05 -07001860}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001861
1862
1863/*
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001864 *
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001865 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001866static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001867ConsumeItem(QCBORDecodeContext *pMe,
1868 const QCBORItem *pItemToConsume,
1869 uint_fast8_t *puNextNestLevel)
1870{
Laurence Lundblade1341c592020-04-11 14:19:05 -07001871 QCBORError nReturn;
1872 QCBORItem Item;
1873
1874 printdecode(pMe, "ConsumeItem");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001875
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001876 if(IsMapOrArray(pItemToConsume->uDataType)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07001877 /* There is only real work to do for maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001878
Laurence Lundblade1341c592020-04-11 14:19:05 -07001879 /* This works for definite and indefinite length
1880 * maps and arrays by using the nesting level
1881 */
1882 do {
1883 nReturn = QCBORDecode_GetNext(pMe, &Item);
1884 if(nReturn != QCBOR_SUCCESS) {
1885 goto Done;
1886 }
1887 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001888
Laurence Lundblade1341c592020-04-11 14:19:05 -07001889 if(puNextNestLevel != NULL) {
1890 *puNextNestLevel = Item.uNextNestLevel;
1891 }
1892 nReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001893
Laurence Lundblade1341c592020-04-11 14:19:05 -07001894 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001895 /* item_to_consume is not a map or array */
Laurence Lundblade1341c592020-04-11 14:19:05 -07001896 if(puNextNestLevel != NULL) {
1897 /* Just pass the nesting level through */
1898 *puNextNestLevel = pItemToConsume->uNextNestLevel;
1899 }
1900 nReturn = QCBOR_SUCCESS;
1901 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001902
1903Done:
1904 return nReturn;
1905}
1906
1907
Laurence Lundblade1341c592020-04-11 14:19:05 -07001908/* Return true if the labels in Item1 and Item2 are the same.
1909 Works only for integer and string labels. Returns false
1910 for any other type. */
1911static inline bool
1912MatchLabel(QCBORItem Item1, QCBORItem Item2)
1913{
1914 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
1915 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
1916 return true;
1917 }
1918 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001919 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07001920 return true;
1921 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001922 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07001923 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
1924 return true;
1925 }
1926 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
1927 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
1928 return true;
1929 }
1930 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001931
Laurence Lundblade1341c592020-04-11 14:19:05 -07001932 /* Other label types are never matched */
1933 return false;
1934}
1935
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001936static inline bool
1937MatchType(QCBORItem Item1, QCBORItem Item2)
1938{
1939 if(Item1.uDataType == Item2.uDataType) {
1940 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07001941 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001942 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07001943 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001944 return true;
1945 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001946 return false;
1947}
1948
1949
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001950/*
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001951 On input pItemArray contains a list of labels and data types
1952 of items to be found.
1953
1954 On output the fully retrieved items are filled in with
1955 values and such. The label was matched, so it never changes.
1956
1957 If an item was not found, its data type is set to none.
1958
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001959 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07001960static QCBORError
1961MapSearch(QCBORDecodeContext *pMe, QCBORItem *pItemArray, size_t *puOffset, size_t *puEndOffset)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001962{
Laurence Lundblade1341c592020-04-11 14:19:05 -07001963 QCBORError nReturn;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07001964
1965 // TODO: what if pre-order cursor is not at the same level as map? This should be OK.
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001966 if(!DecodeNesting_InMapMode(&(pMe->nesting))) {
1967 return QCBOR_ERR_NOT_ENTERED;
Laurence Lundblade1341c592020-04-11 14:19:05 -07001968 }
1969
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07001970 QCBORDecodeNesting SaveNesting;
1971 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundblade1341c592020-04-11 14:19:05 -07001972
1973 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->uOffset);
1974
1975 /* Loop over all the items in the map. They could be
1976 * deeply nested and this should handle both definite
1977 * and indefinite length maps and arrays, so this
1978 * adds some complexity. */
Laurence Lundblade64b607e2020-05-13 13:05:57 -07001979 const uint8_t uMapNestLevel = DecodeNesting_GetMapModeLevel(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07001980
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001981 uint_fast8_t uNextNestLevel;
1982
1983 uint64_t uFound = 0;
1984
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001985 /* Iterate over items in the map / array */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001986 do {
1987 /* Remember offset because sometims we have to return it */
Laurence Lundblade1341c592020-04-11 14:19:05 -07001988 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001989
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001990 /* Get the item */
1991 QCBORItem Item;
1992 nReturn = QCBORDecode_GetNext(pMe, &Item);
1993 if(nReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07001994 /* Got non-well-formed CBOR */
1995 goto Done;
1996 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07001997
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07001998 /* See if item has one of the labels that are of interest */
1999 int i;
2000 QCBORItem *pIterator;
2001 for(pIterator = pItemArray, i = 0; pIterator->uLabelType != 0; pIterator++, i++) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002002 if(MatchLabel(Item, *pIterator)) {
2003 // A label match has been found
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002004 if(uFound & (0x01ULL << i)) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002005 nReturn = QCBOR_ERR_DUPLICATE_LABEL;
2006 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002007 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002008 /* Also try to match its type */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002009 if(!MatchType(Item, *pIterator)) {
2010 nReturn = QCBOR_ERR_UNEXPECTED_TYPE;
2011 goto Done;
2012 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002013
2014 /* Successful match. Return the item. */
2015 *pIterator = Item;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002016 uFound |= 0x01ULL << i;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002017 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002018 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002019 }
2020 }
2021 }
2022
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002023 /* Consume the item whether matched or not. This
2024 does th work of traversing maps and array and
2025 everything in them. In this loop only the
2026 items at the current nesting level are examined
2027 to match the labels. */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002028 nReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
2029 if(nReturn) {
2030 goto Done;
2031 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002032
2033 } while (uNextNestLevel >= uMapNestLevel);
2034
2035
2036 nReturn = QCBOR_SUCCESS;
2037
2038 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
2039 // Cast OK because encoded CBOR is limited to UINT32_MAX
2040 pMe->uMapEndOffset = (uint32_t)uEndOffset;
2041 // TODO: is zero *puOffset OK?
2042 if(puEndOffset) {
2043 *puEndOffset = uEndOffset;
2044 }
2045
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002046 /* For all items not found, set the data type to QCBOR_TYPE_NONE */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002047 int i;
2048 QCBORItem *pIterator;
2049 for(pIterator = pItemArray, i = 0; pIterator->uLabelType != 0; pIterator++, i++) {
2050 if(!(uFound & (0x01ULL << i))) {
2051 pIterator->uDataType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002052 }
2053 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002054
2055Done:
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002056 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002057
Laurence Lundblade1341c592020-04-11 14:19:05 -07002058 return nReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002059}
2060
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002061
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002062// TODO: implement this
2063QCBORError QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pCtx, QCBORItem *pItemList, void *pCallbackCtx, pfItemCallback pfCB)
2064{
2065 return 0;
2066}
2067
2068
Laurence Lundblade34691b92020-05-18 22:25:25 -07002069void QCBORDecode_ExitMapMode(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002070{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002071 size_t uEndOffset;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002072
Laurence Lundblade34691b92020-05-18 22:25:25 -07002073 (void)uType; // TODO: error check
2074
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002075/*
Laurence Lundblade1341c592020-04-11 14:19:05 -07002076 if(pMe->uMapEndOffset) {
2077 uEndOffset = pMe->uMapEndOffset;
2078 // It is only valid once.
2079 pMe->uMapEndOffset = 0;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002080 } else { */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002081 QCBORItem Dummy;
2082
2083 Dummy.uLabelType = QCBOR_TYPE_NONE;
2084
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002085 QCBORError nReturn = MapSearch(pMe, &Dummy, NULL, &uEndOffset);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002086
2087 (void)nReturn; // TODO:
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002088// }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002089
2090 printdecode(pMe, "start exit");
2091 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
2092
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002093 DecodeNesting_Exit(&(pMe->nesting));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002094 printdecode(pMe, "end exit");
2095
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002096}
2097
2098
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002099void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2100 int64_t nLabel,
2101 uint8_t uQcborType,
2102 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002103{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002104 if(pMe->uLastError != QCBOR_SUCCESS) {
2105 return;
2106 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002107
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002108 QCBORItem OneItemSeach[2];
2109 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2110 OneItemSeach[0].label.int64 = nLabel;
2111 OneItemSeach[0].uDataType = uQcborType;
2112 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002113
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002114 QCBORError nReturn = MapSearch(pMe, OneItemSeach, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002115 if(nReturn) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002116 pMe->uLastError = (uint8_t)nReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002117 }
2118
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002119 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
2120 pMe->uLastError = QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002121 }
2122
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002123 *pItem = OneItemSeach[0];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002124}
2125
2126
2127QCBORError QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002128 const char *szLabel,
2129 uint8_t uQcborType,
2130 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002131{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002132 QCBORItem OneItemSeach[2];
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002133
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002134 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2135 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2136 OneItemSeach[0].uDataType = uQcborType;
2137 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002138
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002139 QCBORError nReturn = MapSearch(pMe, OneItemSeach, NULL, NULL);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002140 if(nReturn) {
2141 return nReturn;
2142 }
2143
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002144 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002145 return QCBOR_ERR_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002146 }
2147
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002148 *pItem = OneItemSeach[0];
Laurence Lundblade1341c592020-04-11 14:19:05 -07002149
2150 return QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002151}
2152
2153
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002154static QCBORError CheckTagRequirement(const TagSpecification TagSpec, uint8_t uDataType)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002155{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002156 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_TAG) {
2157 /* Must match the tag */
2158 if(uDataType == TagSpec.uTaggedType) {
2159 return QCBOR_SUCCESS;
2160 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002161 } else {
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002162 /* QCBOR_TAGSPEC_MATCH_TAG_CONTENT_TYPE or QCBOR_TAGSPEC_MATCH_EITHER */
2163 /* Must check all the possible types for the tag content */
2164 for(size_t i = 0; i < sizeof(TagSpec.uAllowedContentTypes); i++) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002165 if(uDataType == TagSpec.uAllowedContentTypes[i]) {
2166 return QCBOR_SUCCESS;
2167 }
2168 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002169 /* Didn't match any of the tag content types */
2170 /* Check the tag for the either case */
2171 if(TagSpec.uTagRequirement == QCBOR_TAGSPEC_MATCH_EITHER) {
2172 if(uDataType == TagSpec.uTaggedType) {
2173 return QCBOR_SUCCESS;
2174 }
2175 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002176 }
2177
2178 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002179}
2180
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002181
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002182void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2183 int64_t nLabel,
2184 TagSpecification TagSpec,
2185 QCBORItem *pItem)
2186{
2187 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2188 if(pMe->uLastError != QCBOR_SUCCESS) {
2189 return;
2190 }
2191
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002192 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002193}
2194
2195void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2196 const char *szLabel,
2197 TagSpecification TagSpec,
2198 QCBORItem *pItem)
2199{
2200 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2201 if(pMe->uLastError != QCBOR_SUCCESS) {
2202 return;
2203 }
2204
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002205 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem->uDataType);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002206}
2207
2208void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2209 int64_t nLabel,
2210 TagSpecification TagSpec,
2211 UsefulBufC *pString)
2212{
2213 QCBORItem Item;
2214 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2215 if(pMe->uLastError == QCBOR_SUCCESS) {
2216 *pString = Item.val.string;
2217 }
2218}
2219
2220void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2221 const char * szLabel,
2222 TagSpecification TagSpec,
2223 UsefulBufC *pString)
2224{
2225 QCBORItem Item;
2226 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2227 if(pMe->uLastError == QCBOR_SUCCESS) {
2228 *pString = Item.val.string;
2229 }
2230}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002231
Laurence Lundblade1341c592020-04-11 14:19:05 -07002232
Laurence Lundblade34691b92020-05-18 22:25:25 -07002233static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002234{
Laurence Lundblade34691b92020-05-18 22:25:25 -07002235 if(pMe->uLastError != QCBOR_SUCCESS) {
2236 // Already in error state; do nothing.
2237 return;
2238 }
2239
2240 size_t uOffset;
Laurence Lundblade986017c2020-05-23 19:25:02 -07002241 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002242 if(pMe->uLastError != QCBOR_SUCCESS) {
2243 return;
2244 }
2245
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002246 /* Need to get the current pre-order nesting level and cursor to be
2247 at the first item in the map/array just entered.
2248
2249 Also need to current map nesting level and start cursor to
2250 be at the right place.
2251
2252 The UsefulInBuf offset could be anywhere, so no assumption is
2253 made about it.
2254
2255 No assumption is made about the pre-order nesting level either.
2256
2257 However the map mode nesting level is assumed to be one above
2258 the map level that is being entered.
2259 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002260 /* Seek to the data item that is the map or array */
2261 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002262 pMe->nesting.pCurrent = pMe->nesting.pCurrentMap; // TODO: part of DecodeNesting
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002263
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002264 // TODO: check error?
Laurence Lundblade34691b92020-05-18 22:25:25 -07002265 QCBORDecode_EnterMapMode(pMe, pSearch->uDataType);
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002266
Laurence Lundblade34691b92020-05-18 22:25:25 -07002267 printdecode(pMe, "FinishEnter");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002268}
2269
2270
Laurence Lundblade34691b92020-05-18 22:25:25 -07002271void QCBORDecode_EnterMapInMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002272{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002273 QCBORItem OneItemSeach[2];
2274 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2275 OneItemSeach[0].label.int64 = nLabel;
2276 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2277 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002278
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002279 /* The map to enter was found, now finish of entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002280 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002281}
2282
2283
Laurence Lundblade34691b92020-05-18 22:25:25 -07002284void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002285{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002286 QCBORItem OneItemSeach[2];
2287 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2288 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2289 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
2290 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002291
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002292 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002293}
2294
2295
Laurence Lundblade34691b92020-05-18 22:25:25 -07002296void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07002297{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002298 QCBORItem OneItemSeach[2];
2299 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2300 OneItemSeach[0].label.int64 = nLabel;
2301 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2302 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002303
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002304 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002305}
2306
2307
2308void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
2309{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002310 QCBORItem OneItemSeach[2];
2311 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2312 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2313 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
2314 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002315
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002316 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002317}
2318
2319
2320
2321
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002322
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002323/* Next item must be map or this generates an error */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002324void QCBORDecode_EnterMapMode(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002325{
Laurence Lundblade34691b92020-05-18 22:25:25 -07002326 if(pMe->uLastError != QCBOR_SUCCESS) {
2327 // Already in error state; do nothing.
2328 return;
2329 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07002330
2331 /* Get the data item that is the map that is being searched */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002332 QCBORItem Item;
Laurence Lundblade986017c2020-05-23 19:25:02 -07002333 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002334 if(pMe->uLastError != QCBOR_SUCCESS) {
2335 return;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002336 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002337 if(Item.uDataType != uType) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07002338 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
2339 return;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002340 }
2341
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002342 DecodeNesting_EnterMapMode(&(pMe->nesting), UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002343
Laurence Lundblade34691b92020-05-18 22:25:25 -07002344 printdecode(pMe, "EnterMapModeDone");
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002345}
2346
2347
2348
2349QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
2350{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002351 return MapSearch(pCtx, pItemList, NULL, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002352}
2353
2354
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002355
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002356
2357
Laurence Lundblade1341c592020-04-11 14:19:05 -07002358void QCBORDecode_RewindMap(QCBORDecodeContext *pMe)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002359{
Laurence Lundblade1341c592020-04-11 14:19:05 -07002360 // TODO: check for map mode
2361 pMe->nesting.pCurrent->uCount = pMe->nesting.pCurrent->uSaveCount;
2362 UsefulInputBuf_Seek(&(pMe->InBuf), pMe->nesting.pCurrent->uOffset);
2363}
2364
2365
Laurence Lundblade1341c592020-04-11 14:19:05 -07002366
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002367
Laurence Lundbladee6430642020-03-14 21:15:44 -07002368
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002369
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002370
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002371
Laurence Lundblade11a064e2020-05-07 13:13:42 -07002372
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002373
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002374static QCBORError InterpretBool(const QCBORItem *pItem, bool *pBool)
2375{
2376 switch(pItem->uDataType) {
2377 case QCBOR_TYPE_TRUE:
2378 *pBool = true;
2379 return QCBOR_SUCCESS;
2380 break;
2381
2382 case QCBOR_TYPE_FALSE:
2383 *pBool = false;
2384 return QCBOR_SUCCESS;
2385 break;
2386
2387 default:
2388 return QCBOR_ERR_UNEXPECTED_TYPE;
2389 break;
2390 }
2391}
Laurence Lundbladee6430642020-03-14 21:15:44 -07002392
Laurence Lundbladec4537442020-04-14 18:53:22 -07002393void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002394{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002395 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002396 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07002397 return;
2398 }
2399
Laurence Lundbladec4537442020-04-14 18:53:22 -07002400 QCBORError nError;
2401 QCBORItem Item;
2402
2403 nError = QCBORDecode_GetNext(pMe, &Item);
2404 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002405 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002406 return;
2407 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002408 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002409}
2410
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002411void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002412{
2413 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002414 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002415
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002416 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002417}
2418
2419
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002420void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
2421{
2422 QCBORItem Item;
2423 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
2424
2425 pMe->uLastError = (uint8_t)InterpretBool(&Item, pValue);
2426}
2427
2428
2429
2430void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe, TagSpecification TagSpec, UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002431{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002432 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002433 // Already in error state, do nothing
2434 return;
2435 }
2436
2437 QCBORError nError;
2438 QCBORItem Item;
2439
2440 nError = QCBORDecode_GetNext(pMe, &Item);
2441 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002442 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002443 return;
2444 }
2445
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002446 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, Item.uDataType);
2447
2448 if(pMe->uLastError == QCBOR_SUCCESS) {
2449 *pBstr = Item.val.string;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002450 }
2451}
2452
Laurence Lundbladec4537442020-04-14 18:53:22 -07002453
2454
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002455
2456static QCBORError ConvertBigNum(const QCBORItem *pItem, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002457{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002458 *pbIsNegative = false;
2459
2460 bool bMustBeTagged = true; // TODO: fix this
2461
2462 switch(pItem->uDataType) {
2463 case QCBOR_TYPE_BYTE_STRING:
2464 // TODO: check that there is no tag here?
2465 if(bMustBeTagged) {
2466 return QCBOR_ERR_UNEXPECTED_TYPE;
2467 } else {
2468 *pValue = pItem->val.string;
2469 return QCBOR_SUCCESS;
2470 }
2471 break;
2472
2473 case QCBOR_TYPE_POSBIGNUM:
2474 *pValue = pItem->val.string;
2475 return QCBOR_SUCCESS;
2476 break;
2477
2478 case QCBOR_TYPE_NEGBIGNUM:
2479 *pbIsNegative = true;
2480 *pValue = pItem->val.string;
2481 return QCBOR_SUCCESS;
2482 break;
2483
2484 default:
2485 return QCBOR_ERR_UNEXPECTED_TYPE;
2486 break;
2487 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07002488}
2489
2490
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002491/**
2492 @param[in] bMustBeTagged If \c true, then the data item must be tagged as either
2493 a positive or negative bignum. If \c false, then it only must be a byte string and bIsNegative
2494 will always be false on the asumption that it is positive, but it can be interpretted as
2495 negative if the the sign is know from other context.
2496 @param[out] pValue The bytes that make up the big num
2497 @param[out] pbIsNegative \c true if tagged as a negative big num. \c false otherwise.
2498
2499 if bMustBeTagged is false, then this will succeed if the data item is a plain byte string,
2500 a positive big num or a negative big num.
2501
2502 */
2503void QCBORDecode_GetBignum(QCBORDecodeContext *pMe, bool bMustBeTagged, UsefulBufC *pValue, bool *pbIsNegative)
2504{
2505 if(pMe->uLastError != QCBOR_SUCCESS) {
2506 // Already in error state, do nothing
2507 return;
2508 }
2509
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002510 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002511 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
2512 if(uError != QCBOR_SUCCESS) {
2513 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002514 return;
2515 }
2516
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002517 pMe->uLastError = (uint8_t)ConvertBigNum(&Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002518}
2519
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002520void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool bMustBeTagged, UsefulBufC *pValue, bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002521{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002522 QCBORItem Item;
2523 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002524
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002525 pMe->uLastError = (uint8_t)ConvertBigNum(&Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07002526}
2527
Laurence Lundbladec4537442020-04-14 18:53:22 -07002528
2529
2530
Laurence Lundbladee6430642020-03-14 21:15:44 -07002531
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002532typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002533
2534
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002535// The main exponentiator that works on only positive numbers
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07002536static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002537{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07002538 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002539
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07002540 if(uResult != 0) {
2541 /* This loop will run a maximum of 19 times because
2542 * UINT64_MAX < 10 ^^ 19. More than that will cause
2543 * exit with the overflow error
2544 */
2545 for(; nExponent > 0; nExponent--) {
2546 if(uResult > UINT64_MAX / 10) {
2547 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
2548 }
2549 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002550 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07002551
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07002552 for(; nExponent < 0; nExponent++) {
2553 uResult = uResult / 10;
2554 if(uResult == 0) {
2555 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
2556 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07002557 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07002558 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07002559 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07002560
2561 *puResult = uResult;
2562
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002563 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07002564}
2565
2566
Laurence Lundbladee6430642020-03-14 21:15:44 -07002567/* Convert a decimal fraction to an int64_t without using
2568 floating point or math libraries. Most decimal fractions
2569 will not fit in an int64_t and this will error out with
2570 under or overflow
2571 */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07002572static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002573{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002574 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002575
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002576 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002577
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002578 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07002579 * INT64_MAX < 2^31. More than that will cause
2580 * exist with the overflow error
2581 */
2582 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002583 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002584 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07002585 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002586 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002587 nExponent--;
2588 }
2589
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002590 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002591 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002592 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
2593 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002594 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07002595 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002596 }
2597
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002598 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002599
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002600 return QCBOR_SUCCESS;
2601}
2602
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07002603/*
2604 Compute value with signed mantissa and signed result. Works with exponent of 2 or 10 based on exponentiator.
2605 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002606static inline QCBORError ExponentiateNN(int64_t nMantissa, int64_t nExponent, int64_t *pnResult, fExponentiator pfExp)
2607{
2608 uint64_t uResult;
2609
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07002610 // Take the absolute value of the mantissa and convert to unsigned.
2611 // TODO: this should be possible in one intruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002612 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
2613
2614 // Do the exponentiation of the positive mantissa
2615 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
2616 if(uReturn) {
2617 return uReturn;
2618 }
2619
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002620
Laurence Lundblade983500d2020-05-14 11:49:34 -07002621 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
2622 of INT64_MIN. This assumes two's compliment representation where
2623 INT64_MIN is one increment farther from 0 than INT64_MAX.
2624 Trying to write -INT64_MIN doesn't work to get this because the
2625 compiler tries to work with an int64_t which can't represent
2626 -INT64_MIN.
2627 */
2628 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
2629
2630 // Error out if too large
2631 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002632 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2633 }
2634
2635 // Casts are safe because of checks above
2636 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
2637
2638 return QCBOR_SUCCESS;
2639}
2640
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07002641/*
2642 Compute value with signed mantissa and unsigned result. Works with exponent of 2 or 10 based on exponentiator.
2643 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002644static inline QCBORError ExponentitateNU(int64_t nMantissa, int64_t nExponent, uint64_t *puResult, fExponentiator pfExp)
2645{
2646 if(nMantissa < 0) {
2647 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
2648 }
2649
2650 // Cast to unsigned is OK because of check for negative
2651 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
2652 // Exponentiation is straight forward
2653 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
2654}
2655
2656
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002657#include <math.h>
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002658
2659
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07002660static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002661{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002662 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002663
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002664 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002665 const uint8_t *pByte = BigNum.ptr;
2666 size_t uLen = BigNum.len;
2667 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07002668 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002669 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002670 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07002671 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002672 }
2673
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002674 *pResult = uResult;
2675 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002676}
2677
Laurence Lundblade887add82020-05-17 05:50:34 -07002678static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002679{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002680 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002681}
2682
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002683static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002684{
2685 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002686 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
2687 if(uError) {
2688 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002689 }
2690 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
2691 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002692 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002693}
2694
2695
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002696static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002697{
2698 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002699 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX-1, &uResult);
2700 if(uError) {
2701 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002702 }
2703 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
Laurence Lundblade887add82020-05-17 05:50:34 -07002704 // TODO: this code is incorrect. See RFC 7049
Laurence Lundbladee6430642020-03-14 21:15:44 -07002705 *pResult = -(int64_t)uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002706 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002707}
2708
Laurence Lundbladef6c86662020-05-12 02:08:00 -07002709#include "fenv.h"
Laurence Lundbladec4537442020-04-14 18:53:22 -07002710
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002711
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002712/*
2713Convert a integers and floats to an int64_t.
2714
2715\param[in] uOptions Bit mask list of conversion options.
2716
2717\retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
2718
2719\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
2720
2721\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
2722
2723*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002724static QCBORError ConvertInt64(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
2725{
2726 switch(pItem->uDataType) {
2727 // TODO: float when ifdefs are set
2728 case QCBOR_TYPE_DOUBLE:
2729 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
2730 // TODO: what about under/overflow here?
2731 // Invokes the floating-point HW and/or compiler-added libraries
2732 feclearexcept(FE_ALL_EXCEPT);
2733 *pnValue = llround(pItem->val.dfnum);
2734 if(fetestexcept(FE_INVALID)) {
2735 // TODO: better error code
2736 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2737 }
2738 } else {
2739 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2740 }
2741 break;
2742
2743 case QCBOR_TYPE_INT64:
2744 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
2745 *pnValue = pItem->val.int64;
2746 } else {
2747 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2748 }
2749 break;
2750
2751 case QCBOR_TYPE_UINT64:
2752 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
2753 if(pItem->val.uint64 < INT64_MAX) {
2754 *pnValue = pItem->val.int64;
2755 } else {
2756 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
2757 }
2758 } else {
2759 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2760 }
2761 break;
2762
2763 default:
2764 return QCBOR_ERR_UNEXPECTED_TYPE;
2765 }
2766 return QCBOR_SUCCESS;
2767}
2768
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002769
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002770void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
2771 uint32_t uOptions,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002772 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002773 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002774{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07002775 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002776 return;
2777 }
2778
Laurence Lundbladee6430642020-03-14 21:15:44 -07002779 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002780 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
2781 if(uError) {
2782 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002783 return;
2784 }
2785
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002786 if(pItem) {
2787 *pItem = Item;
2788 }
2789
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002790 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002791}
2792
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002793
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002794void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
2795 int64_t nLabel,
2796 uint32_t uOptions,
2797 int64_t *pnValue,
2798 QCBORItem *pItem)
2799{
2800 QCBORItem Item;
2801 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
2802
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002803 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002804}
2805
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002806
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002807void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
2808 const char * szLabel,
2809 uint32_t uOptions,
2810 int64_t *pnValue,
2811 QCBORItem *pItem)
2812{
2813 if(pMe->uLastError != QCBOR_SUCCESS) {
2814 return;
2815 }
2816
2817 QCBORItem Item;
2818 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
2819
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002820 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uOptions, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002821}
2822
2823
2824
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002825/*
2826 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002827
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002828 \param[in] uOptions Bit mask list of conversion options.
2829
2830 \retval QCBOR_ERR_CONVERSION_NOT_REQUESTED Conversion, possible, but not requested in uOptions.
2831
2832 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
2833
2834 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large or too small.
2835
2836 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002837static QCBORError Int64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, int64_t *pnValue)
2838{
2839 QCBORError uErr;
2840
2841 switch(pItem->uDataType) {
2842
2843 case QCBOR_TYPE_POSBIGNUM:
2844 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
2845 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002846 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002847 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002848 }
2849 break;
2850
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002851 case QCBOR_TYPE_NEGBIGNUM:
2852 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
2853 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002854 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002855 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002856 }
2857 break;
2858
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002859#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
2860 case QCBOR_TYPE_DECIMAL_FRACTION:
2861 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
2862 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
2863 pItem->val.expAndMantissa.nExponent,
2864 pnValue,
2865 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002866 } else {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002867 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2868 }
2869 break;
2870
2871 case QCBOR_TYPE_BIGFLOAT:
2872 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
2873 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
2874 pItem->val.expAndMantissa.nExponent,
2875 pnValue,
2876 Exponentitate2);
2877 } else {
2878 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2879 }
2880 break;
2881
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002882 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
2883 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
2884 int64_t nMantissa;
2885 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2886 if(uErr) {
2887 return uErr;
2888 }
2889 return ExponentiateNN(nMantissa,
2890 pItem->val.expAndMantissa.nExponent,
2891 pnValue,
2892 Exponentitate10);
2893 } else {
2894 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2895 }
2896 break;
2897
2898 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
2899 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
2900 int64_t nMantissa;
2901 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2902 if(uErr) {
2903 return uErr;
2904 }
2905 return ExponentiateNN(nMantissa,
2906 pItem->val.expAndMantissa.nExponent,
2907 pnValue,
2908 Exponentitate10);
2909 } else {
2910 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2911 }
2912 break;
2913
2914 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
2915 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
2916 int64_t nMantissa;
2917 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2918 if(uErr) {
2919 return uErr;
2920 }
2921 return ExponentiateNN(nMantissa,
2922 pItem->val.expAndMantissa.nExponent,
2923 pnValue,
2924 Exponentitate2);
2925 } else {
2926 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2927 }
2928 break;
2929
2930 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
2931 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
2932 int64_t nMantissa;
2933 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2934 if(uErr) {
2935 return uErr;
2936 }
2937 return ExponentiateNN(nMantissa,
2938 pItem->val.expAndMantissa.nExponent,
2939 pnValue,
2940 Exponentitate2);
2941 } else {
2942 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002943 }
2944 break;
2945
Laurence Lundbladec4537442020-04-14 18:53:22 -07002946 default:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002947 return QCBOR_ERR_UNEXPECTED_TYPE;
2948#endif
Laurence Lundbladec4537442020-04-14 18:53:22 -07002949 }
2950}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002951
2952
Laurence Lundbladec4537442020-04-14 18:53:22 -07002953/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07002954 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002955 */
2956void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07002957{
2958 QCBORItem Item;
2959
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002960 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07002961
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002962 if(pMe->uLastError == QCBOR_SUCCESS) {
2963 // The above conversion succeeded
2964 return;
2965 }
2966
Laurence Lundbladef6c86662020-05-12 02:08:00 -07002967 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002968 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07002969 return;
2970 }
2971
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002972 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07002973}
2974
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002975
2976/*
2977Public function, see header qcbor/qcbor_decode.h file
2978*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002979void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, int64_t *pnValue)
2980{
2981 QCBORItem Item;
2982
2983 QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uOptions, pnValue, &Item);
2984
2985 if(pMe->uLastError == QCBOR_SUCCESS) {
2986 // The above conversion succeeded
2987 return;
2988 }
2989
2990 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
2991 // The above conversion failed in a way that code below can't correct
2992 return;
2993 }
2994
2995 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
2996}
2997
2998
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07002999/*
3000Public function, see header qcbor/qcbor_decode.h file
3001*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003002void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, int64_t *pnValue)
3003{
3004 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003005 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uOptions, pnValue, &Item);
3006
3007 if(pMe->uLastError == QCBOR_SUCCESS) {
3008 // The above conversion succeeded
3009 return;
3010 }
3011
3012 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3013 // The above conversion failed in a way that code below can't correct
3014 return;
3015 }
3016
3017 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uOptions, pnValue);
3018}
3019
3020
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003021static QCBORError ConvertUint64(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3022{
3023 switch(pItem->uDataType) {
3024 // TODO: type flaot
3025 case QCBOR_TYPE_DOUBLE:
3026 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3027 feclearexcept(FE_ALL_EXCEPT);
3028 double dRounded = round(pItem->val.dfnum);
3029 // TODO: over/underflow
3030 if(fetestexcept(FE_INVALID)) {
3031 // TODO: better error code
3032 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3033 } else if(isnan(dRounded)) {
3034 // TODO: better error code
3035 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3036 } else if(dRounded >= 0) {
3037 *puValue = (uint64_t)dRounded;
3038 } else {
3039 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3040 }
3041 } else {
3042 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3043 }
3044 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003045
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003046 case QCBOR_TYPE_INT64:
3047 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
3048 if(pItem->val.int64 >= 0) {
3049 *puValue = (uint64_t)pItem->val.int64;
3050 } else {
3051 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3052 }
3053 } else {
3054 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3055 }
3056 break;
3057
3058 case QCBOR_TYPE_UINT64:
3059 if(uOptions & QCBOR_CONVERT_TYPE_UINT64) {
3060 *puValue = pItem->val.uint64;
3061 } else {
3062 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3063 }
3064 break;
3065
3066 default:
3067 return QCBOR_ERR_UNEXPECTED_TYPE;
3068 }
3069 return QCBOR_SUCCESS;
3070}
Laurence Lundbladec4537442020-04-14 18:53:22 -07003071
3072
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003073void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
3074 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003075 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003076 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003077{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003078 if(pMe->uLastError != QCBOR_SUCCESS) {
3079 return;
3080 }
3081
Laurence Lundbladec4537442020-04-14 18:53:22 -07003082 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003083
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003084 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3085 if(uError) {
3086 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003087 return;
3088 }
3089
Laurence Lundbladea826c502020-05-10 21:07:00 -07003090 if(pItem) {
3091 *pItem = Item;
3092 }
3093
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003094 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003095}
3096
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003097
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003098void QCBORDecode_GetUint64ConvertInternalInMapN(QCBORDecodeContext *pMe,
3099 int64_t nLabel,
3100 uint32_t uOptions,
3101 uint64_t *puValue,
3102 QCBORItem *pItem)
3103{
3104 QCBORItem Item;
3105 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3106
3107 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
3108}
3109
3110
3111void QCBORDecode_GetUint64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3112 const char * szLabel,
3113 uint32_t uOptions,
3114 uint64_t *puValue,
3115 QCBORItem *pItem)
3116{
3117 if(pMe->uLastError != QCBOR_SUCCESS) {
3118 return;
3119 }
3120
3121 QCBORItem Item;
3122 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3123
3124 pMe->uLastError = (uint8_t)ConvertUint64(&Item, uOptions, puValue);
3125}
3126
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003127/*
3128 Public function, see header qcbor/qcbor_decode.h file
3129*/
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003130static QCBORError Uint64ConvertAll(const QCBORItem *pItem, uint32_t uOptions, uint64_t *puValue)
3131{
3132 QCBORError uErr;
3133
3134 switch(pItem->uDataType) {
3135
3136 case QCBOR_TYPE_POSBIGNUM:
3137 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3138 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
3139 } else {
3140 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3141 }
3142 break;
3143
3144 case QCBOR_TYPE_NEGBIGNUM:
3145 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3146 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3147 } else {
3148 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3149 }
3150 break;
3151
3152#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
3153
3154 case QCBOR_TYPE_DECIMAL_FRACTION:
3155 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3156 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3157 pItem->val.expAndMantissa.nExponent,
3158 puValue,
3159 Exponentitate10);
3160 } else {
3161 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3162 }
3163 break;
3164
3165 case QCBOR_TYPE_BIGFLOAT:
3166 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3167 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
3168 pItem->val.expAndMantissa.nExponent,
3169 puValue,
3170 Exponentitate2);
3171 } else {
3172 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3173 }
3174 break;
3175
3176 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3177 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3178 // TODO: Would be better to convert to unsigned
3179 int64_t nMantissa;
3180 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3181 if(uErr != QCBOR_SUCCESS) {
3182 return uErr;
3183 }
3184 return ExponentitateNU(nMantissa,
3185 pItem->val.expAndMantissa.nExponent,
3186 puValue,
3187 Exponentitate10);
3188 } else {
3189 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3190 }
3191 break;
3192
3193 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3194 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3195 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3196 } else {
3197 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3198 }
3199 break;
3200
3201 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3202 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3203 // TODO: Would be better to convert to unsigned
3204 int64_t nMantissa;
3205 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
3206 if(uErr != QCBOR_SUCCESS) {
3207 return uErr;
3208 }
3209 return ExponentitateNU(nMantissa,
3210 pItem->val.expAndMantissa.nExponent,
3211 puValue,
3212 Exponentitate2);
3213 } else {
3214 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3215 }
3216 break;
3217
3218 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3219 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3220 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3221 } else {
3222 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3223 }
3224 break;
3225#endif
3226 default:
3227 return QCBOR_ERR_UNEXPECTED_TYPE;
3228 }
3229}
3230
3231
3232void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003233{
3234 QCBORItem Item;
3235
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003236 QCBORDecode_GetUInt64ConvertInternal(pMe, uOptions, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003237
Laurence Lundbladef6c86662020-05-12 02:08:00 -07003238 if(pMe->uLastError == QCBOR_SUCCESS) {
3239 // The above conversion succeeded
3240 return;
3241 }
3242
3243 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3244 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07003245 return;
3246 }
3247
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003248 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003249}
3250
Laurence Lundbladec4537442020-04-14 18:53:22 -07003251
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003252/*
3253Public function, see header qcbor/qcbor_decode.h file
3254*/
3255void QCBORDecode_GetUint64ConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, uint64_t *puValue)
3256{
3257 QCBORItem Item;
3258
3259 QCBORDecode_GetUint64ConvertInternalInMapN(pMe, nLabel, uOptions, puValue, &Item);
3260
3261 if(pMe->uLastError == QCBOR_SUCCESS) {
3262 // The above conversion succeeded
3263 return;
3264 }
3265
3266 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3267 // The above conversion failed in a way that code below can't correct
3268 return;
3269 }
3270
3271 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
3272}
3273
3274
3275/*
3276Public function, see header qcbor/qcbor_decode.h file
3277*/
3278void QCBORDecode_GetUint64ConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, uint64_t *puValue)
3279{
3280 QCBORItem Item;
3281 QCBORDecode_GetUint64ConvertInternalInMapSZ(pMe, szLabel, uOptions, puValue, &Item);
3282
3283 if(pMe->uLastError == QCBOR_SUCCESS) {
3284 // The above conversion succeeded
3285 return;
3286 }
3287
3288 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3289 // The above conversion failed in a way that code below can't correct
3290 return;
3291 }
3292
3293 pMe->uLastError = (uint8_t)Uint64ConvertAll(&Item, uOptions, puValue);
3294}
3295
3296
3297static QCBORError ConvertDouble(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
3298{
3299 switch(pItem->uDataType) {
3300 // TODO: float when ifdefs are set
3301 case QCBOR_TYPE_DOUBLE:
3302 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3303 if(uOptions & QCBOR_CONVERT_TYPE_FLOAT) {
3304 *pdValue = pItem->val.dfnum;
3305 } else {
3306 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3307 }
3308 }
3309 break;
3310
3311 case QCBOR_TYPE_INT64:
3312 if(uOptions & QCBOR_CONVERT_TYPE_INT64) {
3313 // TODO: how does this work?
3314 *pdValue = (double)pItem->val.int64;
3315
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 *pdValue = (double)pItem->val.uint64;
3324 } else {
3325 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3326 }
3327 break;
3328
3329 default:
3330 return QCBOR_ERR_UNEXPECTED_TYPE;
3331 }
3332
3333 return QCBOR_SUCCESS;
3334}
3335
3336
3337
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003338void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
3339 uint32_t uOptions,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003340 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003341 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003342{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003343 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003344 return;
3345 }
3346
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003347 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003348
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003349 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003350 if(uError) {
3351 pMe->uLastError = (uint8_t)uError;
3352 return;
3353 }
3354
3355 if(pItem) {
3356 *pItem = Item;
3357 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003358
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003359 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003360}
Laurence Lundbladec4537442020-04-14 18:53:22 -07003361
Laurence Lundbladec4537442020-04-14 18:53:22 -07003362
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003363void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
3364 int64_t nLabel,
3365 uint32_t uOptions,
3366 double *pdValue,
3367 QCBORItem *pItem)
3368{
3369 QCBORItem Item;
3370 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3371
3372 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
3373}
3374
3375void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
3376 const char * szLabel,
3377 uint32_t uOptions,
3378 double *pdValue,
3379 QCBORItem *pItem)
3380{
3381 if(pMe->uLastError != QCBOR_SUCCESS) {
3382 return;
3383 }
3384
3385 QCBORItem Item;
3386 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3387
3388 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uOptions, pdValue);
3389}
3390
3391
3392
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003393static double ConvertBigNumToDouble(const UsefulBufC BigNum)
3394{
3395 double dResult;
3396
3397 dResult = 0.0;
3398 const uint8_t *pByte = BigNum.ptr;
3399 size_t uLen = BigNum.len;
3400 /* This will overflow and become the float value INFINITY if the number
3401 is too large to fit. No error will be logged.
3402 TODO: should an error be logged? */
3403 while(uLen--) {
3404 dResult = (dResult * 256.0) + (double)*pByte++;
3405 }
3406
3407 return dResult;
3408}
3409
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003410static QCBORError DoubleConvertAll(const QCBORItem *pItem, uint32_t uOptions, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003411{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003412 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003413 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
3414
3415 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003416 switch(pItem->uDataType) {
3417 // TODO: type float
3418 case QCBOR_TYPE_DECIMAL_FRACTION:
3419 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3420 // TODO: rounding and overflow errors
3421 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
3422 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
3423 } else {
3424 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3425 }
3426 break;
3427
3428 case QCBOR_TYPE_BIGFLOAT:
3429 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
3430 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
3431 exp2((double)pItem->val.expAndMantissa.nExponent);
3432 } else {
3433 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3434 }
3435 break;
3436
3437 case QCBOR_TYPE_POSBIGNUM:
3438 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3439 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
3440 } else {
3441 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3442 }
3443 break;
3444
3445 case QCBOR_TYPE_NEGBIGNUM:
3446 if(uOptions & QCBOR_CONVERT_TYPE_BIG_NUM) {
3447 *pdValue = -ConvertBigNumToDouble(pItem->val.bigNum);
3448 } else {
3449 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3450 }
3451 break;
3452
3453 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
3454 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3455 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
3456 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
3457 } else {
3458 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3459 }
3460 break;
3461
3462 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
3463 if(uOptions & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
3464 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
3465 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
3466 } else {
3467 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3468 }
3469 break;
3470
3471 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
3472 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3473 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
3474 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
3475 } else {
3476 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3477 }
3478 break;
3479
3480 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
3481 if(uOptions & QCBOR_CONVERT_TYPE_BIGFLOAT) {
3482 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
3483 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
3484 } else {
3485 return QCBOR_ERR_CONVERSION_NOT_REQUESTED;
3486 }
3487 break;
3488
3489 default:
3490 return QCBOR_ERR_UNEXPECTED_TYPE;
3491 }
3492
3493 return QCBOR_SUCCESS;
3494}
3495
3496
3497/*
3498 Public function, see header qcbor/qcbor_decode.h file
3499*/
3500void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, double *pdValue)
3501{
3502
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003503 QCBORItem Item;
3504
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003505 QCBORDecode_GetDoubleConvertInternal(pMe, uOptions, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003506
3507 if(pMe->uLastError == QCBOR_SUCCESS) {
3508 // The above conversion succeeded
3509 return;
3510 }
3511
3512 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3513 // The above conversion failed in a way that code below can't correct
3514 return;
3515 }
3516
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003517 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003518}
3519
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003520
3521/*
3522Public function, see header qcbor/qcbor_decode.h file
3523*/
3524void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uOptions, double *pdValue)
3525{
3526 QCBORItem Item;
3527
3528 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uOptions, pdValue, &Item);
3529
3530 if(pMe->uLastError == QCBOR_SUCCESS) {
3531 // The above conversion succeeded
3532 return;
3533 }
3534
3535 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3536 // The above conversion failed in a way that code below can't correct
3537 return;
3538 }
3539
3540 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
3541}
3542
3543
3544/*
3545Public function, see header qcbor/qcbor_decode.h file
3546*/
3547void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uOptions, double *pdValue)
3548{
3549 QCBORItem Item;
3550 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uOptions, pdValue, &Item);
3551
3552 if(pMe->uLastError == QCBOR_SUCCESS) {
3553 // The above conversion succeeded
3554 return;
3555 }
3556
3557 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
3558 // The above conversion failed in a way that code below can't correct
3559 return;
3560 }
3561
3562 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uOptions, pdValue);
3563}