blob: c4bc73507b992f5dfb03f4d588828df431ad3a93 [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 Lundblade8e36f812024-01-26 10:59:29 -07003 Copyright (c) 2018-2024, Laurence Lundblade.
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02004 Copyright (c) 2021, Arm Limited.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07005 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08006
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07007Redistribution and use in source and binary forms, with or without
8modification, are permitted provided that the following conditions are
9met:
10 * Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above
13 copyright notice, this list of conditions and the following
14 disclaimer in the documentation and/or other materials provided
15 with the distribution.
16 * Neither the name of The Linux Foundation nor the names of its
17 contributors, nor the name "Laurence Lundblade" may be used to
18 endorse or promote products derived from this software without
19 specific prior written permission.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080020
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070021THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
22WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
24ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
25BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
30OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080032 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070033
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080034
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080035#include "qcbor/qcbor_decode.h"
Laurence Lundblade67257dc2020-07-27 03:33:37 -070036#include "qcbor/qcbor_spiffy_decode.h"
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080037#include "ieee754.h" /* Does not use math.h */
Laurence Lundbladec7114722020-08-13 05:11:40 -070038
39#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080040
41#include <math.h> /* For isnan(), llround(), llroudf(), round(), roundf(),
42 * pow(), exp2()
43 */
44#include <fenv.h> /* feclearexcept(), fetestexcept() */
45
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080046#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070047
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070048
Laurence Lundblade68cb61c2023-02-12 13:21:44 -080049#if (defined(__GNUC__) && !defined(__clang__))
Laurence Lundblade8e36f812024-01-26 10:59:29 -070050/*
Laurence Lundblade68cb61c2023-02-12 13:21:44 -080051 * This is how the -Wmaybe-uninitialized compiler warning is
52 * handled. It can’t be ignored because some version of gcc enable it
53 * with -Wall which is a common and useful gcc warning option. It also
54 * can’t be ignored because it is the goal of QCBOR to compile clean
55 * out of the box in all environments.
56 *
57 * The big problem with -Wmaybe-uninitialized is that it generates
58 * false positives. It complains things are uninitialized when they
59 * are not. This is because it is not a thorough static analyzer. This
60 * is why “maybe” is in its name. The problem is it is just not
61 * thorough enough to understand all the code (and someone saw fit to
62 * put it in gcc and worse to enable it with -Wall).
63 *
64 * One solution would be to change the code so -Wmaybe-uninitialized
65 * doesn’t get confused, for example adding an unnecessary extra
66 * initialization to zero. (If variables were truly uninitialized, the
67 * correct path is to understand the code thoroughly and set them to
68 * the correct value at the correct time; in essence this is already
69 * done; -Wmaybe-uninitialized just can’t tell). This path is not
70 * taken because it makes the code bigger and is kind of the tail
71 * wagging the dog.
72 *
73 * The solution here is to just use a pragma to disable it for the
74 * whole file. Disabling it for each line makes the code fairly ugly
75 * requiring #pragma to push, pop and ignore. Another reason is the
76 * warnings issues vary by version of gcc and which optimization
77 * optimizations are selected. Another reason is that compilers other
78 * than gcc don’t have -Wmaybe-uninitialized.
79 *
80 * One may ask how to be sure these warnings are false positives and
81 * not real issues. 1) The code has been read carefully to check. 2)
82 * Testing is pretty thorough. 3) This code has been run through
83 * thorough high-quality static analyzers.
84 *
85 * In particularly, most of the warnings are about
86 * Item.Item->uDataType being uninitialized. QCBORDecode_GetNext()
87 * *always* sets this value and test case confirm
88 * this. -Wmaybe-uninitialized just can't tell.
89 *
90 * https://stackoverflow.com/questions/5080848/disable-gcc-may-be-used-uninitialized-on-a-particular-variable
91 */
92#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
Laurence Lundblade8e36f812024-01-26 10:59:29 -070093#endif
Laurence Lundblade68cb61c2023-02-12 13:21:44 -080094
95
96
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080097
Laurence Lundbladea9489f82020-09-12 13:50:56 -070098#define SIZEOF_C_ARRAY(array,type) (sizeof(array)/sizeof(type))
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070099
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700100
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800101
102
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700103static bool
104QCBORItem_IsMapOrArray(const QCBORItem Item)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700105{
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700106 const uint8_t uDataType = Item.uDataType;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700107 return uDataType == QCBOR_TYPE_MAP ||
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700108#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
109 uDataType == QCBOR_TYPE_MAP_AS_ARRAY ||
110#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
111 uDataType == QCBOR_TYPE_ARRAY;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700112}
113
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700114static bool
115QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem Item)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700116{
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700117 if(!QCBORItem_IsMapOrArray(Item)){
Laurence Lundblade02625d42020-06-25 14:41:41 -0700118 return false;
119 }
120
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700121 if(Item.val.uCount != 0) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700122 return false;
123 }
124 return true;
125}
126
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700127static bool
128QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem Item)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700129{
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800130#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700131 if(!QCBORItem_IsMapOrArray(Item)){
Laurence Lundblade02625d42020-06-25 14:41:41 -0700132 return false;
133 }
134
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700135 if(Item.val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700136 return false;
137 }
138 return true;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800139#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700140 (void)Item;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800141 return false;
142#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700143}
144
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700145/* Return true if the labels in Item1 and Item2 are the same.
146 Works only for integer and string labels. Returns false
147 for any other type. */
148static bool
149QCBORItem_MatchLabel(const QCBORItem Item1, const QCBORItem Item2)
150{
151 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
152 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
153 return true;
154 }
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700155#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700156 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
157 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
158 return true;
159 }
160 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
161 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
162 return true;
163 }
164 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
165 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
166 return true;
167 }
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700168#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700169 }
170
171 /* Other label types are never matched */
172 return false;
173}
174
175
176/*
177 Returns true if Item1 and Item2 are the same type
178 or if either are of QCBOR_TYPE_ANY.
179 */
180static bool
181QCBORItem_MatchType(const QCBORItem Item1, const QCBORItem Item2)
182{
183 if(Item1.uDataType == Item2.uDataType) {
184 return true;
185 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
186 return true;
187 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
188 return true;
189 }
190 return false;
191}
192
Laurence Lundblade02625d42020-06-25 14:41:41 -0700193
Laurence Lundbladeee851742020-01-08 08:37:05 -0800194/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700195 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -0800196 ===========================================================================*/
197
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700198/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800199 * See comments about and typedef of QCBORDecodeNesting in qcbor_private.h,
200 * the data structure all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700201 */
202
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700203
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700204static uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700205DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700206{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700207 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800208 /* Limit in DecodeNesting_Descend against more than
209 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700210 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700211 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700212}
213
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700214
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700215static uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700216DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700217{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700218 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800219 /* Limit in DecodeNesting_Descend against more than
220 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700221 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700222 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700223}
224
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700225
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700226static uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700227DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700228{
229 return pNesting->pCurrentBounded->u.ma.uStartOffset;
230}
231
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700232
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700233static bool
Laurence Lundblade085d7952020-07-24 10:26:30 -0700234DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
235{
236 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
237 return true;
238 } else {
239 return false;
240 }
241}
242
243
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700244static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700245DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700246{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700247 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700248 return true;
249 } else {
250 return false;
251 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700252}
253
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700254
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700255static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700256DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700257{
258 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800259 /* Not a map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700260 return false;
261 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800262
263#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700264 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800265 /* Is indefinite */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700266 return false;
267 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800268
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800269#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
270
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800271 /* All checks passed; is a definte length map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700272 return true;
273}
274
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700275static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700276DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700277{
278 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800279 /* is a byte string */
Laurence Lundblade642282a2020-06-23 12:00:33 -0700280 return true;
281 }
282 return false;
283}
284
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700285
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700286static bool
287DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700288{
289 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
290 return true;
291 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700292 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700293 return true;
294 }
295 return false;
296}
297
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700298
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700299static void
300DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700301{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800302 /* Should be only called on maps and arrays */
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700303 /*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800304 * DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
305 * larger than DecodeNesting_EnterBoundedMode which keeps it less than
306 * uin32_t so the cast is safe.
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700307 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700308 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700309
310 if(bIsEmpty) {
311 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
312 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700313}
314
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700315
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700316static void
317DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700318{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700319 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700320}
321
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700322
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700323static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700324DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700325{
326 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800327 /* No bounded map or array set up */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700328 return false;
329 }
330 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800331 /* Not a map or array; end of those is by byte count */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700332 return false;
333 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700334 if(!DecodeNesting_IsCurrentBounded(pNesting)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800335 /* In a traveral at a level deeper than the bounded level */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700336 return false;
337 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800338 /* Works for both definite- and indefinitelength maps/arrays */
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800339 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0 &&
340 pNesting->pCurrentBounded->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800341 /* Count is not zero, still unconsumed item */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700342 return false;
343 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800344 /* All checks passed, got to the end of an array or map*/
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700345 return true;
346}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700347
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700348
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700349static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700350DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700351{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800352 /* Must only be called on map / array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700353 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
354 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700355 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700356 return false;
357 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700358}
359
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700360
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700361static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700362DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700363{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700364 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
365 return true;
366 } else {
367 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700368 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700369}
370
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700371
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700372static bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700373DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700374{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700375 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700376 return false;
377 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700378
Laurence Lundblade5db34da2024-05-30 03:14:35 -0700379 uint8_t uItemDataType = pNesting->pCurrentBounded->uLevelType;
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700380#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
Laurence Lundblade5db34da2024-05-30 03:14:35 -0700381 if(uItemDataType == QCBOR_TYPE_MAP_AS_ARRAY) {
382 uItemDataType = QCBOR_TYPE_ARRAY;
383 }
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700384#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
Laurence Lundblade5db34da2024-05-30 03:14:35 -0700385
386 if(uItemDataType != uType) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700387 return false;
388 }
389
390 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700391}
392
Laurence Lundblade02625d42020-06-25 14:41:41 -0700393
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700394static void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700395DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700396{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800397 /* Only call on a definite-length array / map */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700398 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700399}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700400
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700401
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700402static void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700403DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
404{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800405 /* Only call on a definite-length array / map */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700406 pNesting->pCurrent->u.ma.uCountCursor++;
407}
408
409
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700410static void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700411DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
412{
413 pNesting->pCurrent--;
414}
415
Laurence Lundblade02625d42020-06-25 14:41:41 -0700416
417static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700418DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700419{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800420 /* Error out if nesting is too deep */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700421 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700422 return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700423 }
424
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800425 /* The actual descend */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700426 pNesting->pCurrent++;
427
428 pNesting->pCurrent->uLevelType = uType;
429
430 return QCBOR_SUCCESS;
431}
432
433
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700434static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800435DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting,
436 bool bIsEmpty,
437 size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700438{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700439 /*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800440 * Should only be called on map/array.
441 *
442 * Have descended into this before this is called. The job here is
443 * just to mark it in bounded mode.
444 *
445 * Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
446 * uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET.
447 *
448 * Cast of uOffset to uint32_t for cases where SIZE_MAX < UINT32_MAX.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700449 */
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -0800450 if((uint32_t)uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700451 return QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700452 }
453
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700454 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700455
456 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700457
458 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700459}
460
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700461
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700462static QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700463DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundbladeb95afec2024-08-26 10:51:28 -0700464 const uint8_t uQCBORType,
465 const uint16_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700466{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700467 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700468
469 if(uCount == 0) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800470 /* Nothing to do for empty definite-length arrays. They are just are
471 * effectively the same as an item that is not a map or array.
472 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700473 goto Done;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800474 /* Empty indefinite-length maps and arrays are handled elsewhere */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700475 }
476
Laurence Lundbladeb95afec2024-08-26 10:51:28 -0700477 /* Rely on check in QCBOR_Private_DecodeArrayOrMap() for definite-length
478 * arrays and maps that are too long */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700479
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700480 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700481 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700482 goto Done;
483 }
484
Laurence Lundbladeb95afec2024-08-26 10:51:28 -0700485 pNesting->pCurrent->u.ma.uCountCursor = uCount;
486 pNesting->pCurrent->u.ma.uCountTotal = uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700487
488 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700489
490Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700491 return uError;;
492}
493
494
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700495static void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700496DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
497{
498 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
499}
500
501
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700502static void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700503DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
504{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700505 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700506 pNesting->pCurrentBounded--;
507 if(DecodeNesting_IsCurrentBounded(pNesting)) {
508 break;
509 }
510 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700511}
512
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800513
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700514static void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700515DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
516{
517 pNesting->pCurrent = pNesting->pCurrentBounded;
518}
519
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700520
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700521static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700522DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700523 uint32_t uEndOffset,
524 uint32_t uStartOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700525{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700526 QCBORError uError;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700527
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700528 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700529 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700530 goto Done;
531 }
532
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800533 /* Fill in the new byte string level */
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700534 pNesting->pCurrent->u.bs.uSavedEndOffset = uEndOffset;
535 pNesting->pCurrent->u.bs.uBstrStartOffset = uStartOffset;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700536
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800537 /* Bstr wrapped levels are always bounded */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700538 pNesting->pCurrentBounded = pNesting->pCurrent;
539
540Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700541 return uError;;
542}
543
Laurence Lundbladed0304932020-06-27 10:59:38 -0700544
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700545static void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700546DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700547{
548 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700549}
550
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700551
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700552static void
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800553DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
554{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700555 if(pNesting->pCurrent->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
556 pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
557 }
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800558}
559
560
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700561static void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700562DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700563{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700564 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700565 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
566 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700567}
568
569
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700570static void
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800571DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting,
572 QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700573{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700574 *pSave = *pNesting;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700575}
576
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700577
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700578static void
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800579DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting,
580 const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700581{
582 *pNesting = *pSave;
583}
584
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700585
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700586static uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700587DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700588{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700589 return pMe->pCurrentBounded->u.bs.uSavedEndOffset;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700590}
591
592
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800593
594
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800595#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladeee851742020-01-08 08:37:05 -0800596/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800597 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
598
599 The following four functions are pretty wrappers for invocation of
600 the string allocator supplied by the caller.
601
Laurence Lundbladeee851742020-01-08 08:37:05 -0800602 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800603
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700604static void
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800605StringAllocator_Free(const QCBORInternalAllocator *pMe, const void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800606{
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300607 /* This cast to uintptr_t suppresses the "-Wcast-qual" warnings.
608 * This is the one place where the const needs to be cast away so const can
609 * be use in the rest of the code.
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800610 */
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300611 (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)(uintptr_t)pMem, 0);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800612}
613
Laurence Lundbladeee851742020-01-08 08:37:05 -0800614// StringAllocator_Reallocate called with pMem NULL is
615// equal to StringAllocator_Allocate()
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700616static UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800617StringAllocator_Reallocate(const QCBORInternalAllocator *pMe,
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800618 const void *pMem,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800619 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800620{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800621 /* See comment in StringAllocator_Free() */
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300622 return (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)(uintptr_t)pMem, uSize);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800623}
624
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700625static UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800626StringAllocator_Allocate(const QCBORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800627{
628 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
629}
630
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700631static void
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800632StringAllocator_Destruct(const QCBORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800633{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800634 /* See comment in StringAllocator_Free() */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800635 if(pMe->pfAllocator) {
636 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
637 }
638}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800639#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800640
641
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800642
643
Laurence Lundbladeee851742020-01-08 08:37:05 -0800644/*===========================================================================
645 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700646
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800647 See qcbor/qcbor_decode.h for definition of the object
648 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800649 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700650/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800651 * Public function, see header file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700652 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700653void
654QCBORDecode_Init(QCBORDecodeContext *pMe,
655 UsefulBufC EncodedCBOR,
656 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700657{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800658 memset(pMe, 0, sizeof(QCBORDecodeContext));
659 UsefulInputBuf_Init(&(pMe->InBuf), EncodedCBOR);
660 /* Don't bother with error check on decode mode. If a bad value is
661 * passed it will just act as if the default normal mode of 0 was set.
662 */
663 pMe->uDecodeMode = (uint8_t)nDecodeMode;
664 DecodeNesting_Init(&(pMe->nesting));
665
666 /* Inialize me->auMappedTags to CBOR_TAG_INVALID16. See
667 * GetNext_TaggedItem() and MapTagNumber(). */
668 memset(pMe->auMappedTags, 0xff, sizeof(pMe->auMappedTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700669}
670
671
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800672#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
673
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700674/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800675 * Public function, see header file
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700676 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700677void
678QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
679 QCBORStringAllocate pfAllocateFunction,
680 void *pAllocateContext,
681 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700682{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800683 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
684 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
685 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700686}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800687#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700688
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800689
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800690
691
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800692/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800693 * Deprecated public function, see header file
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800694 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700695void
696QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
697 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700698{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800699 /* This does nothing now. It is retained for backwards compatibility */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700700 (void)pMe;
701 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700702}
703
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700704
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800705
706
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700707/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800708 * Decoding items is done in six layers, one calling the next one
709 * down. If a layer has no work to do for a particular item, it
710 * returns quickly.
711 *
Laurence Lundblade0f01ac62024-02-18 23:07:07 -0700712 * 1. QCBORDecode_Private_GetNextTagContent - The top layer processes
713 * tagged data items, turning them into the local C representation.
714 * For the most simple it is just associating a QCBOR_TYPE with the
715 * data. For the complex ones that an aggregate of data items, there
716 * is some further decoding and some limited recursion.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800717 *
Laurence Lundblade0f01ac62024-02-18 23:07:07 -0700718 * 2. QCBORDecode_Private_GetNextMapOrArray - This manages the
719 * beginnings and ends of maps and arrays. It tracks descending into
720 * and ascending out of maps/arrays. It processes breaks that
721 * terminate indefinite-length maps and arrays.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800722 *
Laurence Lundblade0f01ac62024-02-18 23:07:07 -0700723 * 3. QCBORDecode_Private_GetNextMapEntry - This handles the combining
724 * of two items, the label and the data, that make up a map entry. It
725 * only does work on maps. It combines the label and data items into
726 * one labeled item.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800727 *
Laurence Lundblade0f01ac62024-02-18 23:07:07 -0700728 * 4. QCBORDecode_Private_GetNextTagNumber - This decodes type 6 tag
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800729 * numbers. It turns the tag numbers into bit flags associated with
730 * the data item. No actual decoding of the contents of the tag is
731 * performed here.
732 *
Laurence Lundblade0f01ac62024-02-18 23:07:07 -0700733 * 5. QCBORDecode_Private_GetNextFullString - This assembles the
734 * sub-items that make up an indefinite-length string into one string
735 * item. It uses the string allocator to create contiguous space for
736 * the item. It processes all breaks that are part of
737 * indefinite-length strings.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800738 *
Laurence Lundblade0f01ac62024-02-18 23:07:07 -0700739 * 6. QCBOR_Private_DecodeAtomicDataItem - This decodes the atomic
740 * data items in CBOR. Each atomic data item has a "major type", an
741 * integer "argument" and optionally some content. For text and byte
742 * strings, the content is the bytes that make up the string. These
743 * are the smallest data items that are considered to be well-formed.
744 * The content may also be other data items in the case of aggregate
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800745 * types. They are not handled in this layer.
746 *
Laurence Lundblade0f01ac62024-02-18 23:07:07 -0700747 * This uses about 350 bytes of stack. This number comes from
748 * instrumenting (printf address of stack variables) the code on x86
749 * compiled for size optimization.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700750 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800751
752
753/*
754 * Note about use of int and unsigned variables.
755 *
756 * See http://www.unix.org/whitepapers/64bit.html for reasons int is
757 * used carefully here, and in particular why it isn't used in the
758 * public interface. Also see
759 * https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
760 *
761 * Int is used for values that need less than 16-bits and would be
762 * subject to integer promotion and result in complaining from static
763 * analyzers.
764 */
765
766
767/**
768 * @brief Decode the CBOR head, the type and argument.
769 *
770 * @param[in] pUInBuf The input buffer to read from.
771 * @param[out] pnMajorType The decoded major type.
772 * @param[out] puArgument The decoded argument.
773 * @param[out] pnAdditionalInfo The decoded Lower 5 bits of initial byte.
774 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -0700775 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved features
776 * @retval QCBOR_ERR_HIT_END Unexpected end of input
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800777 *
778 * This decodes the CBOR "head" that every CBOR data item has. See
779 * longer explaination of the head in documentation for
780 * QCBOREncode_EncodeHead().
781 *
782 * This does the network->host byte order conversion. The conversion
783 * here also results in the conversion for floats in addition to that
784 * for lengths, tags and integer values.
785 *
786 * The int type is preferred to uint8_t for some variables as this
787 * avoids integer promotions, can reduce code size and makes static
788 * analyzers happier.
789 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700790static QCBORError
791QCBOR_Private_DecodeHead(UsefulInputBuf *pUInBuf,
792 int *pnMajorType,
793 uint64_t *puArgument,
794 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700795{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800796 QCBORError uReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800797
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800798 /* Get the initial byte that every CBOR data item has and break it
799 * down. */
800 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800801 const int nTmpMajorType = nInitialByte >> 5;
802 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800803
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800804 /* Where the argument accumulates */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800805 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800806
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800807 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800808 /* Need to get 1,2,4 or 8 additional argument bytes. Map
809 * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
810 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800811 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800812
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800813 /* Loop getting all the bytes in the argument */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800814 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800815 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800816 /* This shift and add gives the endian conversion. */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800817 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
818 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800819 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800820 /* The reserved and thus-far unused additional info values */
821 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800822 goto Done;
823 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800824 /* Less than 24, additional info is argument or 31, an
825 * indefinite-length. No more bytes to get.
826 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800827 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700828 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800829
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700830 if(UsefulInputBuf_GetError(pUInBuf)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800831 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700832 goto Done;
833 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800834
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800835 /* All successful if arrived here. */
836 uReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800837 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800838 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800839 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800840
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700841Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800842 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700843}
844
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800845
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800846/**
847 * @brief Decode integer types, major types 0 and 1.
848 *
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700849 * @param[in] nMajorType The CBOR major type (0 or 1).
850 * @param[in] uArgument The argument from the head.
851 * @param[in] nAdditionalInfo So it can be error-checked.
852 * @param[out] pDecodedItem The filled in decoded item.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800853 *
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700854 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered.
855 * @retval QCBOR_ERR_BAD_INT nAdditionalInfo indicated indefinte.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800856 *
857 * Must only be called when major type is 0 or 1.
858 *
859 * CBOR doesn't explicitly specify two's compliment for integers but
860 * all CPUs use it these days and the test vectors in the RFC are
861 * so. All integers in the CBOR structure are positive and the major
862 * type indicates positive or negative. CBOR can express positive
863 * integers up to 2^x - 1 where x is the number of bits and negative
864 * integers down to 2^x. Note that negative numbers can be one more
865 * away from zero than positive. Stdint, as far as I can tell, uses
866 * two's compliment to represent negative integers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700867 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700868static QCBORError
869QCBOR_Private_DecodeInteger(const int nMajorType,
870 const uint64_t uArgument,
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700871 const int nAdditionalInfo,
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700872 QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700873{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800874 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800875
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700876 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
877 uReturn = QCBOR_ERR_BAD_INT;
878 goto Done;
879 }
880
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700881 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800882 if (uArgument <= INT64_MAX) {
883 pDecodedItem->val.int64 = (int64_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700884 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800885
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700886 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800887 pDecodedItem->val.uint64 = uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700888 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700889 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800890
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700891 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800892 if(uArgument <= INT64_MAX) {
893 /* CBOR's representation of negative numbers lines up with
894 * the two-compliment representation. A negative integer has
895 * one more in range than a positive integer. INT64_MIN is
896 * equal to (-INT64_MAX) - 1.
897 */
898 pDecodedItem->val.int64 = (-(int64_t)uArgument) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700899 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800900
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700901 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800902 /* C can't represent a negative integer in this range so it
903 * is an error.
904 */
905 uReturn = QCBOR_ERR_INT_OVERFLOW;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700906 }
907 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800908
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700909Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800910 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700911}
912
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800913
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700914/**
915 * @brief Decode text and byte strings
916 *
917 * @param[in] pMe Decoder context.
918 * @param[in] bAllocate Whether to allocate and copy string.
919 * @param[in] nMajorType Whether it is a byte or text string.
920 * @param[in] uStrLen The length of the string.
921 * @param[in] nAdditionalInfo Whether it is an indefinite-length string.
922 * @param[out] pDecodedItem The filled-in decoded item.
923 *
924 * @retval QCBOR_ERR_HIT_END Unexpected end of input.
925 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
926 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
927 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Allocation requested, but no allocator
928 *
929 * This reads @c uStrlen bytes from the input and fills in @c
930 * pDecodedItem. If @c bAllocate is true, then memory for the string
931 * is allocated.
932 */
933static QCBORError
934QCBOR_Private_DecodeString(QCBORDecodeContext *pMe,
935 const bool bAllocate,
936 const int nMajorType,
937 const uint64_t uStrLen,
938 const int nAdditionalInfo,
939 QCBORItem *pDecodedItem)
940{
941 QCBORError uReturn = QCBOR_SUCCESS;
942
943 /* ---- Figure out the major type ---- */
944 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
945 #error QCBOR_TYPE_BYTE_STRING not lined up with major type
946 #endif
947
948 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
949 #error QCBOR_TYPE_TEXT_STRING not lined up with major type
950 #endif
951 pDecodedItem->uDataType = (uint8_t)(nMajorType + 4);
952
953 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
954 /* --- Just the head of an indefinite-length string --- */
955 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
956
957 } else {
958 /* --- A definite-length string --- */
959 /* --- (which might be a chunk of an indefinte-length string) --- */
960
961 /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
962 * CPUs. This check makes the casts to size_t below safe.
963 *
964 * The max is 4 bytes less than the largest sizeof() so this can be
965 * tested by putting a SIZE_MAX length in the CBOR test input (no
966 * one will care the limit on strings is 4 bytes shorter).
967 */
968 if(uStrLen > SIZE_MAX-4) {
969 uReturn = QCBOR_ERR_STRING_TOO_LONG;
970 goto Done;
971 }
972
973 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(&(pMe->InBuf), (size_t)uStrLen);
974 if(UsefulBuf_IsNULLC(Bytes)) {
975 /* Failed to get the bytes for this string item */
976 uReturn = QCBOR_ERR_HIT_END;
977 goto Done;
978 }
979
980 if(bAllocate) {
981#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
982 /* --- Put string in allocated memory --- */
983
984 /* Note that this is not where allocation to coalesce
985 * indefinite-length strings is done. This is for when the
986 * caller has requested all strings be allocated. Disabling
987 * indefinite length strings also disables this allocate-all
988 * option.
989 */
990
991 if(pMe->StringAllocator.pfAllocator == NULL) {
992 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
993 goto Done;
994 }
995 UsefulBuf NewMem = StringAllocator_Allocate(&(pMe->StringAllocator), (size_t)uStrLen);
996 if(UsefulBuf_IsNULL(NewMem)) {
997 uReturn = QCBOR_ERR_STRING_ALLOCATE;
998 goto Done;
999 }
1000 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
1001 pDecodedItem->uDataAlloc = 1;
1002#else
1003 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1004#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1005 } else {
1006 /* --- Normal case with no string allocator --- */
1007 pDecodedItem->val.string = Bytes;
1008 }
1009 }
1010
1011Done:
1012 return uReturn;
1013}
1014
1015
1016/**
1017 * @brief Decode array or map.
1018 *
1019 * @param[in] uMode Decoder mode.
1020 * @param[in] nMajorType Whether it is a byte or text string.
1021 * @param[in] uItemCount The length of the string.
1022 * @param[in] nAdditionalInfo Whether it is an indefinite-length.
1023 * @param[out] pDecodedItem The filled-in decoded item.
1024 *
1025 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinites disabled.
1026 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG Too many items in array/map.
1027 *
1028 * Not much to do for arrays and maps. Just the type item count (but a
1029 * little messy because of ifdefs for indefinite-lengths and
1030 * map-as-array decoding).
1031 *
1032 * This also does the bulk of the work for @ref
1033 * QCBOR_DECODE_MODE_MAP_AS_ARRAY, a special mode to handle
1034 * arbitrarily complex map labels. This ifdefs out with
1035 * QCBOR_DISABLE_NON_INTEGER_LABELS.
1036 */
1037static QCBORError
1038QCBOR_Private_DecodeArrayOrMap(const uint8_t uMode,
1039 const int nMajorType,
Laurence Lundbladeb95afec2024-08-26 10:51:28 -07001040 uint64_t uItemCount,
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001041 const int nAdditionalInfo,
1042 QCBORItem *pDecodedItem)
1043{
1044 QCBORError uReturn;
1045
1046 /* ------ Sort out the data type ------ */
1047 #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
1048 #error QCBOR_TYPE_ARRAY value not lined up with major type
1049 #endif
1050
1051 #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
1052 #error QCBOR_TYPE_MAP value not lined up with major type
1053 #endif
1054 pDecodedItem->uDataType = (uint8_t)nMajorType;
1055#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
1056 if(uMode == QCBOR_DECODE_MODE_MAP_AS_ARRAY && nMajorType == QCBOR_TYPE_MAP) {
1057 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
1058 }
1059#else
1060 (void)uMode;
1061#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
1062
1063 uReturn = QCBOR_SUCCESS;
1064
1065 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1066 /* ------ Indefinite-length array/map ----- */
1067#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
1068 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
1069#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1070 uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
1071#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1072 } else {
Laurence Lundbladeb95afec2024-08-26 10:51:28 -07001073 /* ----- Definite-length array/map ----- */
1074 if(uItemCount > (nMajorType == QCBOR_TYPE_MAP ? QCBOR_MAX_ITEMS_IN_MAP : QCBOR_MAX_ITEMS_IN_ARRAY)) {
1075 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001076
Laurence Lundbladeb95afec2024-08-26 10:51:28 -07001077 } else {
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001078#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
Laurence Lundbladeb95afec2024-08-26 10:51:28 -07001079 if(uMode == QCBOR_DECODE_MODE_MAP_AS_ARRAY && nMajorType == QCBOR_TYPE_MAP) {
1080 /* ------ Map as array ------ */
1081 uItemCount *= 2;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001082 }
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001083#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
Laurence Lundbladeb95afec2024-08-26 10:51:28 -07001084
1085 /* cast OK because of check above */
1086 pDecodedItem->val.uCount = (uint16_t)uItemCount;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001087 }
1088 }
1089
1090 return uReturn;
1091}
1092
1093
1094/**
1095 * @brief Decode a tag number.
1096 *
1097 * @param[in] uTagNumber The length of the string.
1098 * @param[in] nAdditionalInfo So this can be error-checked.
1099 * @param[out] pDecodedItem The filled-in decoded item.
1100 *
1101 * @retval QCBOR_ERR_BAD_INT nAdditionalInfo is LEN_IS_INDEFINITE.
1102 * @retval QCBOR_ERR_TAGS_DISABLED QCBOR_DISABLE_TAGS is defined.
1103 *
1104 * Not much to do for tags, but fill in pDecodedItem and check for
1105 * error in nAdditionalInfo.
1106 */
1107static QCBORError
1108QCBOR_Private_DecodeTag(const uint64_t uTagNumber,
1109 const int nAdditionalInfo,
1110 QCBORItem *pDecodedItem)
1111{
1112#ifndef QCBOR_DISABLE_TAGS
1113 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1114 return QCBOR_ERR_BAD_INT;
1115 } else {
1116 pDecodedItem->val.uTagV = uTagNumber;
1117 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
1118 return QCBOR_SUCCESS;
1119 }
1120#else /* QCBOR_DISABLE_TAGS */
1121 (void)nAdditionalInfo;
Laurence Lundblade6c9a8242024-06-12 20:34:52 -07001122 (void)uTagNumber;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001123 (void)pDecodedItem;
1124 return QCBOR_ERR_TAGS_DISABLED;
1125#endif /* QCBOR_DISABLE_TAGS */
1126}
1127
1128
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001129/* Make sure #define value line up as DecodeSimple counts on this. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001130#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
1131#error QCBOR_TYPE_FALSE macro value wrong
1132#endif
1133
1134#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
1135#error QCBOR_TYPE_TRUE macro value wrong
1136#endif
1137
1138#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
1139#error QCBOR_TYPE_NULL macro value wrong
1140#endif
1141
1142#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
1143#error QCBOR_TYPE_UNDEF macro value wrong
1144#endif
1145
Laurence Lundblade0f99d692018-09-26 14:39:28 -07001146#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
1147#error QCBOR_TYPE_BREAK macro value wrong
1148#endif
1149
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001150#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
1151#error QCBOR_TYPE_DOUBLE macro value wrong
1152#endif
1153
1154#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
1155#error QCBOR_TYPE_FLOAT macro value wrong
1156#endif
1157
Laurence Lundblade9b334962020-08-27 10:55:53 -07001158
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001159/**
1160 * @brief Decode major type 7 -- true, false, floating-point, break...
1161 *
1162 * @param[in] nAdditionalInfo The lower five bits from the initial byte.
1163 * @param[in] uArgument The argument from the head.
1164 * @param[out] pDecodedItem The filled in decoded item.
1165 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001166 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1167 * of half-precision disabled
1168 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all float
1169 * decode is disabled.
1170 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of simple
1171 * type in input.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001172 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001173static QCBORError
1174QCBOR_Private_DecodeType7(const int nAdditionalInfo,
1175 const uint64_t uArgument,
1176 QCBORItem *pDecodedItem)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001177{
1178 QCBORError uReturn = QCBOR_SUCCESS;
1179
1180 /* uAdditionalInfo is 5 bits from the initial byte. Compile time
1181 * checks above make sure uAdditionalInfo values line up with
1182 * uDataType values. DecodeHead() never returns an AdditionalInfo
1183 * > 0x1f so cast is safe.
1184 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001185 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001186
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001187 switch(nAdditionalInfo) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001188 /* No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they
1189 * are caught before this is called.
1190 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001191
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001192 case HALF_PREC_FLOAT: /* 25 */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -07001193#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001194 /* Half-precision is returned as a double. The cast to
1195 * uint16_t is safe because the encoded value was 16 bits. It
1196 * was widened to 64 bits to be passed in here.
1197 */
1198 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +07001199 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001200#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001201 uReturn = FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -07001202 break;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001203 case SINGLE_PREC_FLOAT: /* 26 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001204#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001205 /* Single precision is normally returned as a double since
1206 * double is widely supported, there is no loss of precision,
1207 * it makes it easy for the caller in most cases and it can
1208 * be converted back to single with no loss of precision
1209 *
1210 * The cast to uint32_t is safe because the encoded value was
1211 * 32 bits. It was widened to 64 bits to be passed in here.
1212 */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001213 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001214 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uArgument);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001215#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001216 /* In the normal case, use HW to convert float to
1217 * double. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001218 pDecodedItem->val.dfnum = (double)f;
1219 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001220#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001221 /* Use of float HW is disabled, return as a float. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001222 pDecodedItem->val.fnum = f;
1223 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
1224
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001225 /* IEEE754_FloatToDouble() could be used here to return as
1226 * a double, but it adds object code and most likely
1227 * anyone disabling FLOAT HW use doesn't care about floats
1228 * and wants to save object code.
1229 */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001230#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001231 }
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001232#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1233 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -07001234 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001235
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001236 case DOUBLE_PREC_FLOAT: /* 27 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001237#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001238 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +07001239 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001240#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1241 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -07001242 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001243
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001244 case CBOR_SIMPLEV_FALSE: /* 20 */
1245 case CBOR_SIMPLEV_TRUE: /* 21 */
1246 case CBOR_SIMPLEV_NULL: /* 22 */
1247 case CBOR_SIMPLEV_UNDEF: /* 23 */
1248 case CBOR_SIMPLE_BREAK: /* 31 */
1249 break; /* nothing to do */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001250
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001251 case CBOR_SIMPLEV_ONEBYTE: /* 24 */
1252 if(uArgument <= CBOR_SIMPLE_BREAK) {
1253 /* This takes out f8 00 ... f8 1f which should be encoded
1254 * as e0 … f7
1255 */
1256 uReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001257 goto Done;
1258 }
Laurence Lundblade5e390822019-01-06 12:35:01 -08001259 /* FALLTHROUGH */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001260
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001261 default: /* 0-19 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001262 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001263 /* DecodeHead() will make uArgument equal to
1264 * nAdditionalInfo when nAdditionalInfo is < 24. This cast is
1265 * safe because the 2, 4 and 8 byte lengths of uNumber are in
1266 * the double/float cases above
Laurence Lundbladeee851742020-01-08 08:37:05 -08001267 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001268 pDecodedItem->val.uSimple = (uint8_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001269 break;
1270 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001271
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001272Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001273 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001274}
1275
1276
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001277/**
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001278 * @brief Decode a single primitive data item (decode layer 6).
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001279 *
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001280 * @param[in] pMe Decoder context.
1281 * @param[in] bAllocateStrings If true, use allocator for strings.
1282 * @param[out] pDecodedItem The filled-in decoded item.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001283 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001284 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1285 * features
1286 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1287 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1288 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1289 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001290 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Allocation requested, but no allocator
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001291 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1292 * of half-precision disabled
1293 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1294 * float decode is disabled.
1295 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1296 * simple type in input.
1297 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1298 * in input, but indefinite
1299 * lengths disabled.
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001300 * @retval QCBOR_ERR_BAD_INT nAdditionalInfo indicated indefinte.
1301 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG Too many items in array/map.
1302 * @retval QCBOR_ERR_TAGS_DISABLED QCBOR_DISABLE_TAGS is defined.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001303 *
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001304 * This decodes the most primitive/atomic data item. It does no
1305 * combining of data items.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001306 */
1307static QCBORError
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001308QCBOR_Private_DecodeAtomicDataItem(QCBORDecodeContext *pMe,
1309 const bool bAllocateStrings,
1310 QCBORItem *pDecodedItem)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001311{
1312 QCBORError uReturn;
Laurence Lundbladec7374282024-07-29 12:47:18 -07001313 int nMajorType = 0;
1314 uint64_t uArgument = 0;
1315 int nAdditionalInfo = 0;
1316
1317 memset(pDecodedItem, 0, sizeof(QCBORItem));
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001318
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001319 /* Decode the "head" that every CBOR item has into the major type,
1320 * argument and the additional info.
1321 */
1322 uReturn = QCBOR_Private_DecodeHead(&(pMe->InBuf), &nMajorType, &uArgument, &nAdditionalInfo);
1323 if(uReturn != QCBOR_SUCCESS) {
1324 return uReturn;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001325 }
1326
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001327 /* All the functions below get inlined by the optimizer. This code
1328 * is easier to read with them all being similar functions, even if
1329 * some functions don't do much.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001330 */
1331 switch (nMajorType) {
1332 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1333 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001334 return QCBOR_Private_DecodeInteger(nMajorType, uArgument, nAdditionalInfo, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001335 break;
1336
1337 case CBOR_MAJOR_TYPE_BYTE_STRING: /* Major type 2 */
1338 case CBOR_MAJOR_TYPE_TEXT_STRING: /* Major type 3 */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001339 return QCBOR_Private_DecodeString(pMe, bAllocateStrings, nMajorType, uArgument, nAdditionalInfo, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001340 break;
1341
1342 case CBOR_MAJOR_TYPE_ARRAY: /* Major type 4 */
1343 case CBOR_MAJOR_TYPE_MAP: /* Major type 5 */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001344 return QCBOR_Private_DecodeArrayOrMap(pMe->uDecodeMode, nMajorType, uArgument, nAdditionalInfo, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001345 break;
1346
1347 case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001348 return QCBOR_Private_DecodeTag(uArgument, nAdditionalInfo, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001349 break;
1350
1351 case CBOR_MAJOR_TYPE_SIMPLE:
1352 /* Major type 7: float, double, true, false, null... */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001353 return QCBOR_Private_DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001354 break;
1355
1356 default:
1357 /* Never happens because DecodeHead() should never return > 7 */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001358 return QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001359 break;
1360 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001361}
1362
1363
1364/**
1365 * @brief Process indefinite-length strings (decode layer 5).
1366 *
1367 * @param[in] pMe Decoder context
1368 * @param[out] pDecodedItem The decoded item that work is done on.
1369 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001370 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1371 * features
1372 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1373 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1374 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1375 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
1376 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1377 * of half-precision disabled
1378 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1379 * float decode is disabled.
1380 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1381 * simple type in input.
1382 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1383 * in input, but indefinite
1384 * lengths disabled.
1385 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Indefinite-length string in input,
1386 * but no string allocator.
1387 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK Error in indefinite-length string.
1388 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED Indefinite-length string in
1389 * input, but indefinite-length
1390 * strings are disabled.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001391 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001392 * If @c pDecodedItem is not an indefinite-length string, this does nothing.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001393 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001394 * If it is, this loops getting the subsequent chunk data items that
1395 * make up the string. The string allocator is used to make a
1396 * contiguous buffer for the chunks. When this completes @c
1397 * pDecodedItem contains the put-together string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001398 *
1399 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001400 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001401static QCBORError
1402QCBORDecode_Private_GetNextFullString(QCBORDecodeContext *pMe,
1403 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001404{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001405 /* Aproximate stack usage
1406 * 64-bit 32-bit
1407 * local vars 32 16
1408 * 2 UsefulBufs 32 16
1409 * QCBORItem 56 52
1410 * TOTAL 120 74
1411 */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001412 QCBORError uReturn;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001413
1414 /* A note about string allocation -- Memory for strings is
1415 * allocated either because 1) indefinte-length string chunks are
1416 * being coalecsed or 2) caller has requested all strings be
1417 * allocated. The first case is handed below here. The second case
1418 * is handled in DecodeString if the bAllocate is true. That
1419 * boolean originates here with pMe->bStringAllocateAll immediately
1420 * below. That is, QCBOR_Private_DecodeAtomicDataItem() is called
1421 * in two different contexts here 1) main-line processing which is
1422 * where definite-length strings need to be allocated if
1423 * bStringAllocateAll is true and 2) processing chunks of
1424 * indefinite-lengths strings in in which case there must be no
1425 * allocation.
1426 */
1427
1428
1429 uReturn = QCBOR_Private_DecodeAtomicDataItem(pMe, pMe->bStringAllocateAll, pDecodedItem);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001430 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001431 goto Done;
1432 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001433
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001434
1435 /* This is where out-of-place break is detected for the whole
1436 * decoding stack. Break is an error for everything that calls
1437 * QCBORDecode_Private_GetNextFullString(), so the check is
1438 * centralized here.
1439 */
1440 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
1441 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001442 goto Done;
1443 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001444
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001445
1446 /* Skip out if not an indefinite-length string */
1447 const uint8_t uStringType = pDecodedItem->uDataType;
1448 if(uStringType != QCBOR_TYPE_BYTE_STRING &&
1449 uStringType != QCBOR_TYPE_TEXT_STRING) {
1450 goto Done;
1451 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001452 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1453 goto Done;
1454 }
1455
1456#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001457 /* Can't decode indefinite-length strings without a string allocator */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001458 if(!pMe->StringAllocator.pfAllocator) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001459 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1460 goto Done;
1461 }
1462
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001463 /* Loop getting chunks of the indefinite-length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001464 UsefulBufC FullString = NULLUsefulBufC;
1465
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001466 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001467 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001468 QCBORItem StringChunkItem;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001469 /* Pass false to DecodeAtomicDataItem() because the individual
1470 * string chunks in an indefinite-length must not be
1471 * allocated. They are always copied into the allocated
1472 * contiguous buffer allocated here.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001473 */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001474 uReturn = QCBOR_Private_DecodeAtomicDataItem(pMe, false, &StringChunkItem);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001475 if(uReturn) {
1476 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001477 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001478
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001479 /* Is item is the marker for end of the indefinite-length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001480 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001481 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001482 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301483 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001484 break;
1485 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001486
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001487 /* All chunks must be of the same type, the type of the item
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001488 * that introduces the indefinite-length string. This also
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001489 * catches errors where the chunk is not a string at all and an
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001490 * indefinite-length string inside an indefinite-length string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001491 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001492 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001493 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1494 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001495 break;
1496 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001497
David Navarro9123e5b2022-03-28 16:04:03 +02001498 if (StringChunkItem.val.string.len > 0) {
1499 /* The first time throurgh FullString.ptr is NULL and this is
1500 * equivalent to StringAllocator_Allocate(). Subsequently it is
1501 * not NULL and a reallocation happens.
1502 */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001503 UsefulBuf NewMem = StringAllocator_Reallocate(&(pMe->StringAllocator),
David Navarro9123e5b2022-03-28 16:04:03 +02001504 FullString.ptr,
1505 FullString.len + StringChunkItem.val.string.len);
David Navarro9123e5b2022-03-28 16:04:03 +02001506 if(UsefulBuf_IsNULL(NewMem)) {
1507 uReturn = QCBOR_ERR_STRING_ALLOCATE;
1508 break;
1509 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001510
David Navarro9123e5b2022-03-28 16:04:03 +02001511 /* Copy new string chunk to the end of accumulated string */
1512 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001513 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001514 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001515
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001516 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1517 /* Getting the item failed, clean up the allocated memory */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001518 StringAllocator_Free(&(pMe->StringAllocator), FullString.ptr);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001519 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001520#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1521 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1522#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001523
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001524Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001525 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001526}
1527
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001528
Laurence Lundblade37286c02022-09-03 10:05:02 -07001529#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001530/**
1531 * @brief This converts a tag number to a shorter mapped value for storage.
1532 *
1533 * @param[in] pMe The decode context.
1534 * @param[in] uUnMappedTag The tag number to map
1535 * @param[out] puMappedTagNumer The stored tag number.
1536 *
1537 * @return error code.
1538 *
1539 * The main point of mapping tag numbers is make QCBORItem
1540 * smaller. With this mapping storage of 4 tags takes up 8
1541 * bytes. Without, it would take up 32 bytes.
1542 *
1543 * This maps tag numbers greater than QCBOR_LAST_UNMAPPED_TAG.
1544 * QCBOR_LAST_UNMAPPED_TAG is a little smaller than MAX_UINT16.
1545 *
1546 * See also UnMapTagNumber() and @ref QCBORItem.
1547 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001548static QCBORError
1549QCBORDecode_Private_MapTagNumber(QCBORDecodeContext *pMe,
1550 const uint64_t uUnMappedTag,
1551 uint16_t *puMappedTagNumer)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001552{
1553 if(uUnMappedTag > QCBOR_LAST_UNMAPPED_TAG) {
1554 unsigned uTagMapIndex;
1555 /* Is there room in the tag map, or is it in it already? */
1556 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
1557 if(pMe->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID64) {
1558 break;
1559 }
1560 if(pMe->auMappedTags[uTagMapIndex] == uUnMappedTag) {
1561 break;
1562 }
1563 }
1564 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1565 return QCBOR_ERR_TOO_MANY_TAGS;
1566 }
1567
1568 /* Covers the cases where tag is new and were it is already in the map */
1569 pMe->auMappedTags[uTagMapIndex] = uUnMappedTag;
1570 *puMappedTagNumer = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
1571
1572 } else {
1573 *puMappedTagNumer = (uint16_t)uUnMappedTag;
1574 }
1575
1576 return QCBOR_SUCCESS;
1577}
1578
1579
1580/**
1581 * @brief This converts a mapped tag number to the actual tag number.
1582 *
1583 * @param[in] pMe The decode context.
1584 * @param[in] uMappedTagNumber The stored tag number.
1585 *
1586 * @return The actual tag number is returned or
1587 * @ref CBOR_TAG_INVALID64 on error.
1588 *
1589 * This is the reverse of MapTagNumber()
1590 */
1591static uint64_t
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001592QCBORDecode_Private_UnMapTagNumber(const QCBORDecodeContext *pMe,
1593 const uint16_t uMappedTagNumber)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001594{
1595 if(uMappedTagNumber <= QCBOR_LAST_UNMAPPED_TAG) {
1596 return uMappedTagNumber;
1597 } else if(uMappedTagNumber == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001598 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001599 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001600 /* This won't be negative because of code below in
1601 * MapTagNumber()
1602 */
1603 const unsigned uIndex = uMappedTagNumber - (QCBOR_LAST_UNMAPPED_TAG + 1);
1604 return pMe->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001605 }
1606}
Laurence Lundblade37286c02022-09-03 10:05:02 -07001607#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001608
Laurence Lundblade9b334962020-08-27 10:55:53 -07001609
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001610/**
1611 * @brief Aggregate all tags wrapping a data item (decode layer 4).
1612 *
1613 * @param[in] pMe Decoder context
1614 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001615 *
1616 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1617 * features
1618 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1619 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1620 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1621 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
1622 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1623 * of half-precision disabled
1624 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1625 * float decode is disabled.
1626 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1627 * simple type in input.
1628 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1629 * in input, but indefinite
1630 * lengths disabled.
1631 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Indefinite-length string in input,
1632 * but no string allocator.
1633 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK Error in indefinite-length string.
1634 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED Indefinite-length string in
1635 * input, but indefinite-length
1636 * strings are disabled.
1637 * @retval QCBOR_ERR_TOO_MANY_TAGS Too many tag numbers on item.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001638 *
1639 * This loops getting atomic data items until one is not a tag
1640 * number. Usually this is largely pass-through because most
1641 * item are not tag numbers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001642 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001643static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001644QCBORDecode_Private_GetNextTagNumber(QCBORDecodeContext *pMe,
1645 QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001646{
Laurence Lundblade37286c02022-09-03 10:05:02 -07001647#ifndef QCBOR_DISABLE_TAGS
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001648 /* Accummulate the tags from multiple items here and then copy them
1649 * into the last item, the non-tag item.
1650 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001651 uint16_t auItemsTags[QCBOR_MAX_TAGS_PER_ITEM];
1652
1653 /* Initialize to CBOR_TAG_INVALID16 */
1654 #if CBOR_TAG_INVALID16 != 0xffff
1655 /* Be sure the memset does the right thing. */
1656 #err CBOR_TAG_INVALID16 tag not defined as expected
1657 #endif
1658 memset(auItemsTags, 0xff, sizeof(auItemsTags));
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001659
Laurence Lundblade9b334962020-08-27 10:55:53 -07001660 QCBORError uReturn = QCBOR_SUCCESS;
1661
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001662 /* Loop fetching data items until the item fetched is not a tag */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001663 for(;;) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001664 QCBORError uErr = QCBORDecode_Private_GetNextFullString(pMe, pDecodedItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07001665 if(uErr != QCBOR_SUCCESS) {
1666 uReturn = uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001667 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001668 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001669
Laurence Lundblade9b334962020-08-27 10:55:53 -07001670 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001671 /* Successful exit from loop; maybe got some tags, maybe not */
1672 memcpy(pDecodedItem->uTags, auItemsTags, sizeof(auItemsTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001673 break;
1674 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001675
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001676 if(auItemsTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1677 /* No room in the tag list */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001678 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001679 /* Continue on to get all tags wrapping this item even though
1680 * it is erroring out in the end. This allows decoding to
1681 * continue. This is a resource limit error, not a problem
1682 * with being well-formed CBOR.
1683 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001684 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001685 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001686 /* Slide tags over one in the array to make room at index 0.
1687 * Must use memmove because the move source and destination
1688 * overlap.
1689 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001690 memmove(&auItemsTags[1],
1691 auItemsTags,
1692 sizeof(auItemsTags) - sizeof(auItemsTags[0]));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001693
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001694 /* Map the tag */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001695 uint16_t uMappedTagNumber = 0;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001696 uReturn = QCBORDecode_Private_MapTagNumber(pMe, pDecodedItem->val.uTagV, &uMappedTagNumber);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001697 /* Continue even on error so as to consume all tags wrapping
1698 * this data item so decoding can go on. If MapTagNumber()
1699 * errors once it will continue to error.
1700 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001701 auItemsTags[0] = uMappedTagNumber;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001702 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001703
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001704Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001705 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001706
Laurence Lundblade37286c02022-09-03 10:05:02 -07001707#else /* QCBOR_DISABLE_TAGS */
1708
Laurence Lundblade0f01ac62024-02-18 23:07:07 -07001709 return QCBORDecode_Private_GetNextFullString(pMe, pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07001710
1711#endif /* QCBOR_DISABLE_TAGS */
1712}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001713
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001714
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001715/**
1716 * @brief Combine a map entry label and value into one item (decode layer 3).
1717 *
1718 * @param[in] pMe Decoder context
1719 * @param[out] pDecodedItem The decoded item that work is done on.
1720 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001721 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1722 * features
1723 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1724 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1725 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1726 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
1727 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1728 * of half-precision disabled
1729 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1730 * float decode is disabled.
1731 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1732 * simple type in input.
1733 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1734 * in input, but indefinite
1735 * lengths disabled.
1736 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Indefinite-length string in input,
1737 * but no string allocator.
1738 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK Error in indefinite-length string.
1739 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED Indefinite-length string in
1740 * input, but indefinite-length
1741 * strings are disabled.
1742 * @retval QCBOR_ERR_TOO_MANY_TAGS Too many tag numbers on item.
1743 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG Too many items in array.
1744 * @retval QCBOR_ERR_MAP_LABEL_TYPE Map label not string or integer.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001745 *
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001746 * If the current nesting level is a map, then this combines pairs of
1747 * items into one data item with a label and value.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001748 *
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001749 * This is passthrough if the current nesting level is not a map.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001750 *
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001751 * This also implements maps-as-array mode where a map is treated like
1752 * an array to allow caller to do their own label processing.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001753 */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001754
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001755static QCBORError
1756QCBORDecode_Private_GetNextMapEntry(QCBORDecodeContext *pMe,
1757 QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001758{
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001759 QCBORItem LabelItem;
1760 QCBORError uErr;
1761
1762 uErr = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
1763 if(QCBORDecode_IsUnrecoverableError(uErr)) {
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001764 goto Done;
1765 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001766
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001767 if(!DecodeNesting_IsCurrentTypeMap(&(pMe->nesting))) {
1768 /* Not decoding a map. Nothing to do. */
1769 /* When decoding maps-as-arrays, the type will be
1770 * QCBOR_TYPE_MAP_AS_ARRAY and this function will exit
1771 * here. This is now map processing for maps-as-arrays is not
1772 * done. */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001773 goto Done;
1774 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001775
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001776 /* Decoding a map entry, so the item decoded above was the label */
1777 LabelItem = *pDecodedItem;
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001778
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001779 /* Get the value of the map item */
1780 uErr = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
1781 if(QCBORDecode_IsUnrecoverableError(uErr)) {
1782 goto Done;
1783 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001784
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001785 /* Combine the label item and value item into one */
1786 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1787 pDecodedItem->uLabelType = LabelItem.uDataType;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001788
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001789#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
1790 /* QCBOR_DECODE_MODE_MAP_STRINGS_ONLY might have been a bad idea. Maybe
1791 * get rid of it in QCBOR 2.0
1792 */
1793 if(pMe->uDecodeMode == QCBOR_DECODE_MODE_MAP_STRINGS_ONLY &&
1794 LabelItem.uDataType != QCBOR_TYPE_TEXT_STRING) {
1795 uErr = QCBOR_ERR_MAP_LABEL_TYPE;
1796 goto Done;
1797 }
1798#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
1799
1800 switch(LabelItem.uDataType) {
1801 case QCBOR_TYPE_INT64:
1802 pDecodedItem->label.int64 = LabelItem.val.int64;
1803 break;
1804
1805#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
1806 case QCBOR_TYPE_UINT64:
1807 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1808 break;
1809
1810 case QCBOR_TYPE_TEXT_STRING:
1811 case QCBOR_TYPE_BYTE_STRING:
1812 pDecodedItem->label.string = LabelItem.val.string;
1813 break;
1814#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
1815
1816 default:
1817 uErr = QCBOR_ERR_MAP_LABEL_TYPE;
1818 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001819 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001820
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001821Done:
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001822 return uErr;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001823}
1824
1825
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001826#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001827/**
1828 * @brief Peek and see if next data item is a break;
1829 *
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001830 * param[in] pUIB UsefulInputBuf to read from.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001831 * @param[out] pbNextIsBreak Indicate if next was a break or not.
1832 *
1833 * @return Any decoding error.
1834 *
1835 * See if next item is a CBOR break. If it is, it is consumed,
1836 * if not it is not consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001837*/
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001838static QCBORError
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001839QCBOR_Private_NextIsBreak(QCBORDecodeContext *pMe, bool *pbNextIsBreak)
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001840{
1841 *pbNextIsBreak = false;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001842 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001843 QCBORItem Peek;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001844 size_t uPeek = UsefulInputBuf_Tell(&(pMe->InBuf));
1845 QCBORError uReturn = QCBOR_Private_DecodeAtomicDataItem(pMe, false, &Peek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001846 if(uReturn != QCBOR_SUCCESS) {
1847 return uReturn;
1848 }
1849 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001850 /* It is not a break, rewind so it can be processed normally. */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001851 UsefulInputBuf_Seek(&(pMe->InBuf), uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001852 } else {
1853 *pbNextIsBreak = true;
1854 }
1855 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001856
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001857 return QCBOR_SUCCESS;
1858}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001859#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001860
1861
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001862/**
1863 * @brief Ascend up nesting levels if all items in them have been consumed.
1864 *
1865 * @param[in] pMe The decode context.
1866 * @param[in] bMarkEnd If true mark end of maps/arrays with count of zero.
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07001867 * @param[out] pbBreak Set to true if extra break was consumed.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001868 *
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001869 * An item was just consumed, now figure out if it was the
1870 * end of an array/map map that can be closed out. That
1871 * may in turn close out the above array/map...
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07001872 *
1873 * When ascending indefinite-length arrays and maps, this will correctly
1874 * consume the break for the level above. This is a problem for the
1875 * implementation of QCBORDecode_GetArray() that must not return
1876 * that break. @c pbBreak is set to true to indicate that one
1877 * byte should be removed.
1878 *
1879 * Improvement: this could reduced further if indef is disabled
1880 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001881static QCBORError
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07001882QCBORDecode_Private_NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd, bool *pbBreak)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001883{
1884 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001885
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001886 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001887 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07001888 if(pbBreak) {
1889 *pbBreak = false;
1890 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001891
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001892 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1893 /* Nesting level is bstr-wrapped CBOR */
1894
1895 /* Ascent for bstr-wrapped CBOR is always by explicit call
1896 * so no further ascending can happen.
1897 */
1898 break;
1899
1900 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1901 /* Level is a definite-length array/map */
1902
1903 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001904 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1905 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001906 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001907 break;
1908 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001909 /* All items in a definite-length array were consumed so it
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001910 * is time to ascend one level. This happens below.
1911 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001912
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001913#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001914 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001915 /* Level is an indefinite-length array/map. */
1916
1917 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001918 bool bIsBreak = false;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001919 uReturn = QCBOR_Private_NextIsBreak(pMe, &bIsBreak);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001920 if(uReturn != QCBOR_SUCCESS) {
1921 goto Done;
1922 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001923
1924 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001925 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001926 break;
1927 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001928
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001929 /* It was a break in an indefinitelength map / array so
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001930 * it is time to ascend one level.
1931 */
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07001932 if(pbBreak) {
1933 *pbBreak = true;
1934 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001935
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001936#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001937 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001938
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001939
1940 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001941
Laurence Lundblade93d89472020-10-03 22:30:50 -07001942 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001943 * QCBORDecode_ExitBoundedMode().
1944 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001945 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001946 /* Set the count to zero for definite-length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001947 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001948 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001949 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001950 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001951
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001952 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001953 break;
1954 }
1955
1956 /* Finally, actually ascend one level. */
1957 DecodeNesting_Ascend(&(pMe->nesting));
1958 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001959
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001960 uReturn = QCBOR_SUCCESS;
1961
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001962#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001963Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001964#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1965
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001966 return uReturn;
1967}
1968
1969
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001970/**
1971 * @brief Ascending & Descending out of nesting levels (decode layer 2).
1972 *
1973 * @param[in] pMe Decoder context
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07001974 * @param[out] pbBreak Set to true if extra break was consumed.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001975 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001976
1977 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1978 * features
1979 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1980 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1981 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1982 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
1983 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1984 * of half-precision disabled
1985 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1986 * float decode is disabled.
1987 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1988 * simple type in input.
1989 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1990 * in input, but indefinite
1991 * lengths disabled.
1992 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Indefinite-length string in input,
1993 * but no string allocator.
1994 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK Error in indefinite-length string.
1995 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED Indefinite-length string in
1996 * input, but indefinite-length
1997 * strings are disabled.
1998 * @retval QCBOR_ERR_TOO_MANY_TAGS Too many tag numbers on item.
1999 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG Too many items in array.
2000 * @retval QCBOR_ERR_MAP_LABEL_TYPE Map label not string or integer.
2001 * @retval QCBOR_ERR_NO_MORE_ITEMS Need more items for map or array.
2002 * @retval QCBOR_ERR_BAD_BREAK Indefinite-length break in wrong
2003 * place.
2004 * @retval QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP Nesting deeper than QCBOR
2005 * can handle.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002006 *
2007 * This handles the traversal descending into and asecnding out of
2008 * maps, arrays and bstr-wrapped CBOR. It figures out the ends of
2009 * definite- and indefinte-length maps and arrays by looking at the
2010 * item count or finding CBOR breaks. It detects the ends of the
2011 * top-level sequence and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002012 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002013static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002014QCBORDecode_Private_GetNextMapOrArray(QCBORDecodeContext *pMe,
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002015 bool *pbBreak,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002016 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002017{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002018 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07002019 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002020
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002021 /* If out of bytes to consume, it is either the end of the
2022 * top-level sequence of some bstr-wrapped CBOR that was entered.
2023 *
2024 * In the case of bstr-wrapped CBOR, the length of the
2025 * UsefulInputBuf was set to that of the bstr-wrapped CBOR. When
2026 * the bstr-wrapped CBOR is exited, the length is set back to the
2027 * top-level's length or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07002028 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002029 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002030 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07002031 goto Done;
2032 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07002033
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002034 /* Check to see if at the end of a bounded definite-length map or
2035 * array. The check for a break ending indefinite-length array is
2036 * later in QCBORDecode_NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002037 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002038 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002039 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002040 goto Done;
2041 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07002042
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08002043 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002044 uReturn = QCBORDecode_Private_GetNextMapEntry(pMe, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002045 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
2046 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002047 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002048 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05302049
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002050 /* Record the nesting level for this data item before processing
2051 * any of decrementing and descending.
Laurence Lundblade642282a2020-06-23 12:00:33 -07002052 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002053 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002054
Laurence Lundblade642282a2020-06-23 12:00:33 -07002055
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07002056 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002057 if(QCBORItem_IsMapOrArray(*pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002058 /* If the new item is a map or array, descend.
2059 *
2060 * Empty indefinite-length maps and arrays are descended into,
2061 * but then ascended out of in the next chunk of code.
2062 *
2063 * Maps and arrays do count as items in the map/array that
2064 * encloses them so a decrement needs to be done for them too,
2065 * but that is done only when all the items in them have been
2066 * processed, not when they are opened with the exception of an
2067 * empty map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07002068 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002069 QCBORError uDescendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002070 uDescendErr = DecodeNesting_DescendMapOrArray(&(pMe->nesting),
Laurence Lundbladeb95afec2024-08-26 10:51:28 -07002071 pDecodedItem->uDataType,
2072 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002073 if(uDescendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002074 /* This error is probably a traversal error and it overrides
2075 * the non-traversal error.
2076 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002077 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002078 goto Done;
2079 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07002080 }
2081
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002082 if(!QCBORItem_IsMapOrArray(*pDecodedItem) ||
2083 QCBORItem_IsEmptyDefiniteLengthMapOrArray(*pDecodedItem) ||
2084 QCBORItem_IsIndefiniteLengthMapOrArray(*pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002085 /* The following cases are handled here:
2086 * - A non-aggregate item like an integer or string
2087 * - An empty definite-length map or array
2088 * - An indefinite-length map or array that might be empty or might not.
2089 *
2090 * QCBORDecode_NestLevelAscender() does the work of decrementing the count
2091 * for an definite-length map/array and break detection for an
2092 * indefinite-0length map/array. If the end of the map/array was
2093 * reached, then it ascends nesting levels, possibly all the way
2094 * to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002095 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002096 QCBORError uAscendErr;
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002097 uAscendErr = QCBORDecode_Private_NestLevelAscender(pMe, true, pbBreak);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002098 if(uAscendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002099 /* This error is probably a traversal error and it overrides
2100 * the non-traversal error.
2101 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002102 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002103 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07002104 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05302105 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002106
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07002107 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002108 /* Tell the caller what level is next. This tells them what
2109 * maps/arrays were closed out and makes it possible for them to
2110 * reconstruct the tree with just the information returned in a
2111 * QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07002112 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002113 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07002114 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002115 pDecodedItem->uNextNestLevel = 0;
2116 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002117 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002118 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002119
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002120Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002121 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002122}
2123
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002124
Laurence Lundblade37286c02022-09-03 10:05:02 -07002125#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002126/**
2127 * @brief Shift 0th tag out of the tag list.
2128 *
2129 * pDecodedItem[in,out] The data item to convert.
2130 *
Laurence Lundblade88ba5662024-11-03 02:10:24 -08002131 * The 0th tag is discarded. @ref CBOR_TAG_INVALID16 is
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002132 * shifted into empty slot at the end of the tag list.
2133 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002134static void
2135QCBOR_Private_ShiftTags(QCBORItem *pDecodedItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002136{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002137 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM-1; i++) {
2138 pDecodedItem->uTags[i] = pDecodedItem->uTags[i+1];
2139 }
2140 pDecodedItem->uTags[QCBOR_MAX_TAGS_PER_ITEM-1] = CBOR_TAG_INVALID16;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002141}
Laurence Lundblade37286c02022-09-03 10:05:02 -07002142#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002143
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07002144
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002145/**
2146 * @brief Convert different epoch date formats in to the QCBOR epoch date format
2147 *
2148 * pDecodedItem[in,out] The data item to convert.
2149 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07002150 * @retval QCBOR_ERR_DATE_OVERFLOW 65-bit negative integer.
2151 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED Float-point date in input,
2152 * floating-point date disabled.
2153 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point date in input,
2154 * all floating-point disabled.
2155 * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT Unexpected and unrecoverable
2156 * error decoding date.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002157 *
2158 * The epoch date tag defined in QCBOR allows for floating-point
2159 * dates. It even allows a protocol to flop between date formats when
2160 * ever it wants. Floating-point dates aren't that useful as they are
2161 * only needed for dates beyond the age of the earth.
2162 *
2163 * This converts all the date formats into one format of an unsigned
2164 * integer plus a floating-point fraction.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002165 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002166static QCBORError
2167QCBOR_Private_DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002168{
Laurence Lundbladec7114722020-08-13 05:11:40 -07002169 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002170
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002171#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade59289e52019-12-30 13:44:37 -08002172 pDecodedItem->val.epochDate.fSecondsFraction = 0;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002173#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002174
2175 switch (pDecodedItem->uDataType) {
2176
2177 case QCBOR_TYPE_INT64:
2178 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
2179 break;
2180
2181 case QCBOR_TYPE_UINT64:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002182 /* This only happens for CBOR type 0 > INT64_MAX so it is
2183 * always an overflow.
2184 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002185 uReturn = QCBOR_ERR_DATE_OVERFLOW;
2186 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002187 break;
2188
2189 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07002190 case QCBOR_TYPE_FLOAT:
2191#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08002192 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002193 /* Convert working value to double if input was a float */
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07002194 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002195 pDecodedItem->val.dfnum :
2196 (double)pDecodedItem->val.fnum;
2197
2198 /* The conversion from float to integer requires overflow
2199 * detection since floats can be much larger than integers.
2200 * This implementation errors out on these large float values
2201 * since they are beyond the age of the earth.
2202 *
2203 * These constants for the overflow check are computed by the
2204 * compiler. They are not computed at run time.
2205 *
2206 * The factor of 0x7ff is added/subtracted to avoid a
2207 * rounding error in the wrong direction when the compiler
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002208 * computes these constants. There is rounding because a
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002209 * 64-bit integer has 63 bits of precision where a double
2210 * only has 53 bits. Without the 0x7ff factor, the compiler
2211 * may round up and produce a double for the bounds check
2212 * that is larger than can be stored in a 64-bit integer. The
2213 * amount of 0x7ff is picked because it has 11 bits set.
2214 *
2215 * Without the 0x7ff there is a ~30 minute range of time
2216 * values 10 billion years in the past and in the future
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002217 * where this code could go wrong. Some compilers
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002218 * generate a warning or error without the 0x7ff.
2219 */
2220 const double dDateMax = (double)(INT64_MAX - 0x7ff);
2221 const double dDateMin = (double)(INT64_MIN + 0x7ff);
2222
2223 if(isnan(d) || d > dDateMax || d < dDateMin) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07002224 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002225 goto Done;
2226 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002227
2228 /* The actual conversion */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002229 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07002230 pDecodedItem->val.epochDate.fSecondsFraction =
2231 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002232 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002233#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade4b270642020-08-14 12:53:07 -07002234
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002235 uReturn = QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07002236 goto Done;
2237
Laurence Lundblade9682a532020-06-06 18:33:04 -07002238#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002239 break;
2240
2241 default:
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002242 /* It's the arrays and maps that are unrecoverable because
2243 * they are not consumed here. Since this is just an error
2244 * condition, no extra code is added here to make the error
2245 * recoverable for non-arrays and maps like strings. */
2246 uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002247 goto Done;
2248 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002249
Laurence Lundblade59289e52019-12-30 13:44:37 -08002250 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
2251
2252Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07002253 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002254}
2255
2256
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002257/**
2258 * @brief Convert the days epoch date.
2259 *
2260 * pDecodedItem[in,out] The data item to convert.
2261 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07002262 * @retval QCBOR_ERR_DATE_OVERFLOW 65-bit negative integer.
2263 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED Float-point date in input,
2264 * floating-point date disabled.
2265 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point date in input,
2266 * all floating-point disabled.
2267 * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT Unexpected and unrecoverable
2268 * error decoding date.
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002269 *
2270 * This is much simpler than the other epoch date format because
2271 * floating-porint is not allowed. This is mostly a simple type check.
2272 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002273static QCBORError
2274QCBOR_Private_DecodeDaysEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002275{
2276 QCBORError uReturn = QCBOR_SUCCESS;
2277
2278 switch (pDecodedItem->uDataType) {
2279
2280 case QCBOR_TYPE_INT64:
2281 pDecodedItem->val.epochDays = pDecodedItem->val.int64;
2282 break;
2283
2284 case QCBOR_TYPE_UINT64:
2285 /* This only happens for CBOR type 0 > INT64_MAX so it is
2286 * always an overflow.
2287 */
2288 uReturn = QCBOR_ERR_DATE_OVERFLOW;
2289 goto Done;
2290 break;
2291
2292 default:
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002293 /* It's the arrays and maps that are unrecoverable because
2294 * they are not consumed here. Since this is just an error
2295 * condition, no extra code is added here to make the error
2296 * recoverable for non-arrays and maps like strings. */
2297 uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002298 goto Done;
2299 break;
2300 }
2301
2302 pDecodedItem->uDataType = QCBOR_TYPE_DAYS_EPOCH;
2303
2304Done:
2305 return uReturn;
2306}
2307
2308
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002309#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade37286c02022-09-03 10:05:02 -07002310
2311/* Forward declaration is necessary for
2312 * QCBORDecode_MantissaAndExponent(). to be able to decode bignum
2313 * tags in the mantissa. If the mantissa is a decimal fraction or big
2314 * float in error, this will result in a recurive call to
2315 * QCBORDecode_MantissaAndExponent(), but the recursion will unwined
2316 * correctly and the correct error is returned.
2317 */
2318static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002319QCBORDecode_Private_GetNextTagContent(QCBORDecodeContext *pMe,
2320 QCBORItem *pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07002321
2322
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002323/**
2324 * @brief Decode decimal fractions and big floats.
2325 *
2326 * @param[in] pMe The decode context.
2327 * @param[in,out] pDecodedItem On input the array data item that
2328 * holds the mantissa and exponent. On
2329 * output the decoded mantissa and
2330 * exponent.
2331 *
2332 * @returns Decoding errors from getting primitive data items or
Laurence Lundblade88ba5662024-11-03 02:10:24 -08002333 * @ref QCBOR_ERR_BAD_EXP_AND_MANTISSA.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002334 *
Laurence Lundblade37286c02022-09-03 10:05:02 -07002335 * When called pDecodedItem must be the array with two members, the
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002336 * exponent and mantissa.
2337 *
2338 * This will fetch and decode the exponent and mantissa and put the
2339 * result back into pDecodedItem.
Laurence Lundblade37286c02022-09-03 10:05:02 -07002340 *
2341 * This does no checking or processing of tag numbers. That is to be
2342 * done by the code that calls this.
2343 *
2344 * This stuffs the type of the mantissa into pDecodedItem with the expectation
2345 * the caller will process it.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002346 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07002347static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002348QCBORDecode_Private_ExpMantissa(QCBORDecodeContext *pMe,
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07002349 QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002350{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002351 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002352
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002353 /* --- Make sure it is an array; track nesting level of members --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002354 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002355 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002356 goto Done;
2357 }
2358
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002359 /* A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07002360 * definite-length arrays, but not for indefinite. Instead remember
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002361 * the nesting level the two integers must be at, which is one
2362 * deeper than that of the array.
2363 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002364 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
2365
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002366 /* --- Get the exponent --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002367 QCBORItem exponentItem;
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07002368 uReturn = QCBORDecode_GetNext(pMe, &exponentItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002369 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002370 goto Done;
2371 }
2372 if(exponentItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002373 /* Array is empty or a map/array encountered when expecting an int */
2374 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002375 goto Done;
2376 }
2377 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002378 /* Data arriving as an unsigned int < INT64_MAX has been
2379 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2380 * also means that the only data arriving here of type
2381 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2382 * and thus an error that will get handled in the next else.
2383 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002384 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
2385 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002386 /* Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX */
2387 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002388 goto Done;
2389 }
2390
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002391 /* --- Get the mantissa --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002392 QCBORItem mantissaItem;
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07002393 uReturn = QCBORDecode_GetNext(pMe, &mantissaItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002394 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002395 goto Done;
2396 }
2397 if(mantissaItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002398 /* Mantissa missing or map/array encountered when expecting number */
2399 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002400 goto Done;
2401 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002402 /* Stuff the mantissa data type into the item to send it up to the
2403 * the next level. */
2404 pDecodedItem->uDataType = mantissaItem.uDataType;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002405 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002406 /* Data arriving as an unsigned int < INT64_MAX has been
2407 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2408 * also means that the only data arriving here of type
2409 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2410 * and thus an error that will get handled in an else below.
2411 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002412 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002413#ifndef QCBOR_DISABLE_TAGS
2414 /* With tags fully disabled a big number mantissa will error out
2415 * in the call to QCBORDecode_GetNextWithTags() because it has
2416 * a tag number.
2417 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002418 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
2419 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002420 /* Got a good big num mantissa */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002421 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002422#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002423 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002424 /* Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX */
2425 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002426 goto Done;
2427 }
2428
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002429 /* --- Check that array only has the two numbers --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002430 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002431 /* Extra items in the decimal fraction / big float */
Laurence Lundblade37286c02022-09-03 10:05:02 -07002432 /* Improvement: this should probably be an unrecoverable error. */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002433 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002434 goto Done;
2435 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002436 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002437
2438Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002439 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002440}
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002441#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002442
2443
Laurence Lundblade37286c02022-09-03 10:05:02 -07002444#ifndef QCBOR_DISABLE_TAGS
2445
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002446#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002447/**
2448 * @brief Decode the MIME type tag
2449 *
2450 * @param[in,out] pDecodedItem The item to decode.
2451 *
2452 * Handle the text and binary MIME type tags. Slightly too complicated
2453 * f or ProcessTaggedString() because the RFC 7049 MIME type was
2454 * incorreclty text-only.
2455 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002456static QCBORError
2457QCBOR_Private_DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002458{
2459 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
2460 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07002461 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002462 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
2463 } else {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002464 /* It's the arrays and maps that are unrecoverable because
2465 * they are not consumed here. Since this is just an error
2466 * condition, no extra code is added here to make the error
2467 * recoverable for non-arrays and maps like strings. */
2468 return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002469 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002470
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002471 return QCBOR_SUCCESS;
2472}
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002473#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002474
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002475/**
Laurence Lundblade99615302020-11-29 11:19:47 -08002476 * Table of CBOR tags whose content is either a text string or a byte
2477 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
2478 * of uQCBORtype indicates the content should be a byte string rather
2479 * than a text string
2480 */
2481struct StringTagMapEntry {
2482 uint16_t uTagNumber;
2483 uint8_t uQCBORtype;
2484};
2485
2486#define IS_BYTE_STRING_BIT 0x80
2487#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
2488
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002489static const struct StringTagMapEntry QCBOR_Private_StringTagMap[] = {
Laurence Lundblade99615302020-11-29 11:19:47 -08002490 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002491 {CBOR_TAG_DAYS_STRING, QCBOR_TYPE_DAYS_STRING},
Laurence Lundblade99615302020-11-29 11:19:47 -08002492 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
2493 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
2494 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
2495 {CBOR_TAG_URI, QCBOR_TYPE_URI},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002496#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002497 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
2498 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
2499 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
2500 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002501#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade99615302020-11-29 11:19:47 -08002502 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
2503 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
2504};
2505
2506
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002507/**
2508 * @brief Process standard CBOR tags whose content is a string
2509 *
2510 * @param[in] uTag The tag.
2511 * @param[in,out] pDecodedItem The data item.
2512 *
2513 * @returns This returns QCBOR_SUCCESS if the tag was procssed,
Laurence Lundblade88ba5662024-11-03 02:10:24 -08002514 * @ref QCBOR_ERR_UNSUPPORTED if the tag was not processed and
2515 * @ref QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT if the content type was wrong for the tag.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002516 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002517 * Process the CBOR tags that whose content is a byte string or a text
2518 * string and for which the string is just passed on to the caller.
2519 *
2520 * This maps the CBOR tag to the QCBOR type and checks the content
2521 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08002522 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08002523 * possible.
Laurence Lundblade99615302020-11-29 11:19:47 -08002524 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002525static QCBORError
2526QCBOR_Private_ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002527{
Laurence Lundblade99615302020-11-29 11:19:47 -08002528 /* This only works on tags that were not mapped; no need for other yet */
2529 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
2530 return QCBOR_ERR_UNSUPPORTED;
2531 }
2532
2533 unsigned uIndex;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002534 for(uIndex = 0; QCBOR_Private_StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
2535 if(QCBOR_Private_StringTagMap[uIndex].uTagNumber == uTag) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002536 break;
2537 }
2538 }
2539
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002540 const uint8_t uQCBORType = QCBOR_Private_StringTagMap[uIndex].uQCBORtype;
Laurence Lundblade99615302020-11-29 11:19:47 -08002541 if(uQCBORType == QCBOR_TYPE_NONE) {
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002542 /* repurpose this error to mean not handled here */
Laurence Lundblade99615302020-11-29 11:19:47 -08002543 return QCBOR_ERR_UNSUPPORTED;
2544 }
2545
2546 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
2547 if(uQCBORType & IS_BYTE_STRING_BIT) {
2548 uExpectedType = QCBOR_TYPE_BYTE_STRING;
2549 }
2550
2551 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002552 /* It's the arrays and maps that are unrecoverable because
2553 * they are not consumed here. Since this is just an error
2554 * condition, no extra code is added here to make the error
2555 * recoverable for non-arrays and maps like strings. */
2556 return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002557 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002558
Laurence Lundblade99615302020-11-29 11:19:47 -08002559 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002560 return QCBOR_SUCCESS;
2561}
Laurence Lundblade37286c02022-09-03 10:05:02 -07002562#endif /* QCBOR_DISABLE_TAGS */
2563
2564
2565#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07002566/**
2567 * @brief Figures out data type for exponent mantissa tags.
2568 *
2569 * @param[in] uTagToProcess Either @ref CBOR_TAG_DECIMAL_FRACTION or
2570 * @ref CBOR_TAG_BIG_FLOAT.
2571 * @param[in] pDecodedItem Item being decoded.
2572 *
Laurence Lundblade88ba5662024-11-03 02:10:24 -08002573 * @returns One of the 6 values between @ref QCBOR_TYPE_DECIMAL_FRACTION
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07002574 * and @ref QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM.
2575 *
2576 * Does mapping between a CBOR tag number and a QCBOR type. with a
2577 * little bit of logic and arithmatic.
2578 *
2579 * Used in serveral contexts. Does the work where sometimes the data
2580 * item is explicitly tagged and sometimes not.
Laurence Lundblade37286c02022-09-03 10:05:02 -07002581 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002582static uint8_t
2583QCBOR_Private_ExpMantissaDataType(const uint16_t uTagToProcess,
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07002584 const QCBORItem *pDecodedItem)
Laurence Lundblade37286c02022-09-03 10:05:02 -07002585{
2586 uint8_t uBase = uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ?
2587 QCBOR_TYPE_DECIMAL_FRACTION :
2588 QCBOR_TYPE_BIGFLOAT;
2589 if(pDecodedItem->uDataType != QCBOR_TYPE_INT64) {
2590 uBase = (uint8_t)(uBase + pDecodedItem->uDataType - QCBOR_TYPE_POSBIGNUM + 1);
2591 }
2592 return uBase;
2593}
2594#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002595
2596
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002597/**
2598 * @brief Decode tag content for select tags (decoding layer 1).
2599 *
2600 * @param[in] pMe The decode context.
2601 * @param[out] pDecodedItem The decoded item.
2602 *
2603 * @return Decoding error code.
2604 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002605 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
2606 * but the whole tag was not decoded. Here, the whole tags (tag number
2607 * and tag content) that are supported by QCBOR are decoded. This is a
2608 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002609 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002610static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002611QCBORDecode_Private_GetNextTagContent(QCBORDecodeContext *pMe,
2612 QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002613{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002614 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002615
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002616 uReturn = QCBORDecode_Private_GetNextMapOrArray(pMe, NULL, pDecodedItem);
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002617 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002618 goto Done;
2619 }
2620
Laurence Lundblade37286c02022-09-03 10:05:02 -07002621#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002622 /* When there are no tag numbers for the item, this exits first
2623 * thing and effectively does nothing.
2624 *
2625 * This loops over all the tag numbers accumulated for this item
2626 * trying to decode and interpret them. This stops at the end of
2627 * the list or at the first tag number that can't be interpreted by
2628 * this code. This is effectively a recursive processing of the
2629 * tags number list that handles nested tags.
2630 */
2631 while(1) {
2632 /* Don't bother to unmap tags via QCBORITem.uTags since this
2633 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2634 */
2635 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002636
Laurence Lundblade99615302020-11-29 11:19:47 -08002637 if(uTagToProcess == CBOR_TAG_INVALID16) {
2638 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002639 break;
2640
Laurence Lundblade99615302020-11-29 11:19:47 -08002641 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002642 uReturn = QCBOR_Private_DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002643
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002644 } else if(uTagToProcess == CBOR_TAG_DAYS_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002645 uReturn = QCBOR_Private_DecodeDaysEpoch(pDecodedItem);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002646
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002647#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002648 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2649 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002650 uReturn = QCBORDecode_Private_ExpMantissa(pMe, pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07002651 /* --- Which is it, decimal fraction or a bigfloat? --- */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002652 pDecodedItem->uDataType = QCBOR_Private_ExpMantissaDataType(uTagToProcess, pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07002653
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002654#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002655#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002656 } else if(uTagToProcess == CBOR_TAG_MIME ||
2657 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002658 uReturn = QCBOR_Private_DecodeMIME(pDecodedItem);
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002659#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002660
Laurence Lundblade99615302020-11-29 11:19:47 -08002661 } else {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002662 /* See if it is a passthrough byte/text string tag; process if so */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002663 uReturn = QCBOR_Private_ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002664
Laurence Lundblade99615302020-11-29 11:19:47 -08002665 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002666 /* It wasn't a passthrough byte/text string tag so it is
Laurence Lundblade99615302020-11-29 11:19:47 -08002667 * an unknown tag. This is the exit from the loop on the
2668 * first unknown tag. It is a successful exit.
2669 */
2670 uReturn = QCBOR_SUCCESS;
2671 break;
2672 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002673 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002674
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002675 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002676 /* Error exit from the loop */
2677 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002678 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002679
2680 /* A tag was successfully processed, shift it out of the list of
2681 * tags returned. This is the loop increment.
2682 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002683 QCBOR_Private_ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002684 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002685#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002686
2687Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002688 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002689}
2690
2691
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002692/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002693 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002694 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002695QCBORError
2696QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2697{
2698 QCBORError uErr;
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07002699 uErr = QCBORDecode_Private_GetNextTagContent(pMe, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002700 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002701 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2702 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2703 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002704 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002705}
2706
2707
2708/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002709 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002710 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002711QCBORError
2712QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2713{
2714 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2715 const UsefulInputBuf Save = pMe->InBuf;
2716
2717 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2718
2719 pMe->nesting = SaveNesting;
2720 pMe->InBuf = Save;
2721
2722 return uErr;
2723}
2724
2725
2726/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002727 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002728 */
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002729void
2730QCBORDecode_VPeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2731{
2732 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladef00b8be2024-03-08 10:34:33 -08002733 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2734 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002735 return;
2736 }
2737
2738 pMe->uLastError = (uint8_t)QCBORDecode_PeekNext(pMe, pDecodedItem);
2739}
2740
2741
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07002742static void
2743QCBORDecode_Private_CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2744{
2745#ifndef QCBOR_DISABLE_TAGS
2746 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2747#else
2748 (void)pMe;
2749 (void)pItem;
2750#endif
2751}
2752
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002753/*
2754 * Public function, see header qcbor/qcbor_decode.h file
2755 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002756void
2757QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002758{
2759 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladef00b8be2024-03-08 10:34:33 -08002760 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2761 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002762 return;
2763 }
2764
2765 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07002766 QCBORDecode_Private_CopyTags(pMe, pDecodedItem);
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002767}
2768
2769
2770/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002771 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002772 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002773QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002774QCBORDecode_GetNextWithTags(QCBORDecodeContext *pMe,
2775 QCBORItem *pDecodedItem,
2776 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002777{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002778#ifndef QCBOR_DISABLE_TAGS
2779
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002780 QCBORError uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002781
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002782 uReturn = QCBORDecode_GetNext(pMe, pDecodedItem);
2783 if(uReturn != QCBOR_SUCCESS) {
2784 return uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002785 }
2786
2787 if(pTags != NULL) {
2788 pTags->uNumUsed = 0;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002789 /* Reverse the order because pTags is reverse of QCBORItem.uTags. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002790 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2791 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002792 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002793 }
2794 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2795 return QCBOR_ERR_TOO_MANY_TAGS;
2796 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002797 pTags->puTags[pTags->uNumUsed] = QCBORDecode_Private_UnMapTagNumber(pMe,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002798 pTags->uNumUsed++;
2799 }
2800 }
2801
2802 return QCBOR_SUCCESS;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002803
2804#else /* QCBOR_DISABLE_TAGS */
2805 (void)pMe;
2806 (void)pDecodedItem;
2807 (void)pTags;
2808 return QCBOR_ERR_TAGS_DISABLED;
2809#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002810}
2811
2812
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002813/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002814 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302815 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002816bool
2817QCBORDecode_IsTagged(QCBORDecodeContext *pMe,
2818 const QCBORItem *pItem,
2819 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002820{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002821#ifndef QCBOR_DISABLE_TAGS
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002822 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2823 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002824 break;
2825 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002826 if(QCBORDecode_Private_UnMapTagNumber(pMe, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002827 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002828 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002829 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002830#else /* QCBOR_TAGS_DISABLED */
2831 (void)pMe;
2832 (void)pItem;
2833 (void)uTag;
2834#endif /* QCBOR_TAGS_DISABLED */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002835
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002836 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002837}
2838
2839
2840/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002841 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002842 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002843QCBORError
2844QCBORDecode_PartialFinish(QCBORDecodeContext *pMe, size_t *puConsumed)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002845{
Laurence Lundblade87495732021-02-26 10:05:55 -07002846 if(puConsumed != NULL) {
2847 *puConsumed = pMe->InBuf.cursor;
2848 }
2849
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002850 QCBORError uReturn = pMe->uLastError;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002851
2852 if(uReturn != QCBOR_SUCCESS) {
2853 goto Done;
2854 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002855
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002856 /* Error out if all the maps/arrays are not closed out */
2857 if(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002858 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002859 goto Done;
2860 }
2861
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002862 /* Error out if not all the bytes are consumed */
2863 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002864 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002865 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002866
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002867Done:
Laurence Lundblade87495732021-02-26 10:05:55 -07002868 return uReturn;
2869}
2870
2871
2872/*
2873 * Public function, see header qcbor/qcbor_decode.h file
2874 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002875QCBORError
2876QCBORDecode_Finish(QCBORDecodeContext *pMe)
Laurence Lundblade87495732021-02-26 10:05:55 -07002877{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002878#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002879 /* Call the destructor for the string allocator if there is one.
2880 * Always called, even if there are errors; always have to clean up.
2881 */
2882 StringAllocator_Destruct(&(pMe->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002883#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002884
Laurence Lundblade87495732021-02-26 10:05:55 -07002885 return QCBORDecode_PartialFinish(pMe, NULL);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002886}
2887
2888
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002889/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002890 * Public function, see header qcbor/qcbor_decode.h file
2891 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002892uint64_t
2893QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2894 const QCBORItem *pItem,
2895 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002896{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002897#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002898 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2899 return CBOR_TAG_INVALID64;
2900 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002901 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2902 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002903 } else {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002904 return QCBORDecode_Private_UnMapTagNumber(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002905 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002906#else /* QCBOR_DISABLE_TAGS */
2907 (void)pMe;
2908 (void)pItem;
2909 (void)uIndex;
2910
2911 return CBOR_TAG_INVALID64;
2912#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002913}
2914
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002915
Laurence Lundblade9b334962020-08-27 10:55:53 -07002916/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002917 * Public function, see header qcbor/qcbor_decode.h file
2918 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002919uint64_t
2920QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2921 uint32_t uIndex)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002922{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002923#ifndef QCBOR_DISABLE_TAGS
2924
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002925 if(pMe->uLastError != QCBOR_SUCCESS) {
2926 return CBOR_TAG_INVALID64;
2927 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002928 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2929 return CBOR_TAG_INVALID64;
2930 } else {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002931 return QCBORDecode_Private_UnMapTagNumber(pMe, pMe->uLastTags[uIndex]);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002932 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002933#else /* QCBOR_DISABLE_TAGS */
2934 (void)pMe;
2935 (void)uIndex;
2936
2937 return CBOR_TAG_INVALID64;
2938#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002939}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002940
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002941
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002942
2943
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002944#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002945
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002946/* ===========================================================================
2947 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002948
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002949 This implements a simple sting allocator for indefinite-length
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002950 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2951 implements the function type QCBORStringAllocate and allows easy
2952 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002953
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002954 This particular allocator is built-in for convenience. The caller
2955 can implement their own. All of this following code will get
2956 dead-stripped if QCBORDecode_SetMemPool() is not called.
2957
2958 This is a very primitive memory allocator. It does not track
2959 individual allocations, only a high-water mark. A free or
2960 reallocation must be of the last chunk allocated.
2961
2962 The size of the pool and offset to free memory are packed into the
2963 first 8 bytes of the memory pool so we don't have to keep them in
2964 the decode context. Since the address of the pool may not be
2965 aligned, they have to be packed and unpacked as if they were
2966 serialized data of the wire or such.
2967
2968 The sizes packed in are uint32_t to be the same on all CPU types
2969 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002970 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002971
2972
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002973static int
Laurence Lundbladeee851742020-01-08 08:37:05 -08002974MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002975{
2976 // Use of UsefulInputBuf is overkill, but it is convenient.
2977 UsefulInputBuf UIB;
2978
Laurence Lundbladeee851742020-01-08 08:37:05 -08002979 // Just assume the size here. It was checked during SetUp so
2980 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002981 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002982 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2983 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2984 return UsefulInputBuf_GetError(&UIB);
2985}
2986
2987
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002988static int
Laurence Lundbladeee851742020-01-08 08:37:05 -08002989MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002990{
2991 // Use of UsefulOutBuf is overkill, but convenient. The
2992 // length check performed here is useful.
2993 UsefulOutBuf UOB;
2994
2995 UsefulOutBuf_Init(&UOB, Pool);
2996 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2997 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2998 return UsefulOutBuf_GetError(&UOB);
2999}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003000
3001
3002/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003003 Internal function for an allocation, reallocation free and destuct.
3004
3005 Having only one function rather than one each per mode saves space in
3006 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003007
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003008 Code Reviewers: THIS FUNCTION DOES POINTER MATH
3009 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08003010static UsefulBuf
3011MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003012{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003013 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003014
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003015 uint32_t uPoolSize;
3016 uint32_t uFreeOffset;
3017
3018 if(uNewSize > UINT32_MAX) {
3019 // This allocator is only good up to 4GB. This check should
3020 // optimize out if sizeof(size_t) == sizeof(uint32_t)
3021 goto Done;
3022 }
3023 const uint32_t uNewSize32 = (uint32_t)uNewSize;
3024
3025 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
3026 goto Done;
3027 }
3028
3029 if(uNewSize) {
3030 if(pMem) {
3031 // REALLOCATION MODE
3032 // Calculate pointer to the end of the memory pool. It is
3033 // assumed that pPool + uPoolSize won't wrap around by
3034 // assuming the caller won't pass a pool buffer in that is
3035 // not in legitimate memory space.
3036 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
3037
3038 // Check that the pointer for reallocation is in the range of the
3039 // pool. This also makes sure that pointer math further down
3040 // doesn't wrap under or over.
3041 if(pMem >= pPool && pMem < pPoolEnd) {
3042 // Offset to start of chunk for reallocation. This won't
3043 // wrap under because of check that pMem >= pPool. Cast
3044 // is safe because the pool is always less than UINT32_MAX
3045 // because of check in QCBORDecode_SetMemPool().
3046 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
3047
3048 // Check to see if the allocation will fit. uPoolSize -
3049 // uMemOffset will not wrap under because of check that
3050 // pMem is in the range of the uPoolSize by check above.
3051 if(uNewSize <= uPoolSize - uMemOffset) {
3052 ReturnValue.ptr = pMem;
3053 ReturnValue.len = uNewSize;
3054
3055 // Addition won't wrap around over because uNewSize was
3056 // checked to be sure it is less than the pool size.
3057 uFreeOffset = uMemOffset + uNewSize32;
3058 }
3059 }
3060 } else {
3061 // ALLOCATION MODE
3062 // uPoolSize - uFreeOffset will not underflow because this
3063 // pool implementation makes sure uFreeOffset is always
3064 // smaller than uPoolSize through this check here and
3065 // reallocation case.
3066 if(uNewSize <= uPoolSize - uFreeOffset) {
3067 ReturnValue.len = uNewSize;
3068 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08003069 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003070 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003071 }
3072 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003073 if(pMem) {
3074 // FREE MODE
3075 // Cast is safe because of limit on pool size in
3076 // QCBORDecode_SetMemPool()
3077 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
3078 } else {
3079 // DESTRUCT MODE
3080 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003081 }
3082 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003083
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003084 UsefulBuf Pool = {pPool, uPoolSize};
3085 MemPool_Pack(Pool, uFreeOffset);
3086
3087Done:
3088 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003089}
3090
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003091
Laurence Lundbladef6531662018-12-04 10:42:22 +09003092/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003093 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09003094 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003095QCBORError
3096QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
3097 UsefulBuf Pool,
3098 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003099{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003100 // The pool size and free mem offset are packed into the beginning
Dave Thaler93c01182022-08-06 15:08:35 -04003101 // of the pool memory. This compile time check makes sure the
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003102 // constant in the header is correct. This check should optimize
3103 // down to nothing.
Dave Thaler93c01182022-08-06 15:08:35 -04003104#ifdef _MSC_VER
3105#pragma warning(push)
3106#pragma warning(disable:4127) // conditional expression is constant
3107#endif
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003108 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003109 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003110 }
Dave Thaler93c01182022-08-06 15:08:35 -04003111#ifdef _MSC_VER
3112#pragma warning(pop)
3113#endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003114
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003115 // The pool size and free offset packed in to the beginning of pool
3116 // memory are only 32-bits. This check will optimize out on 32-bit
3117 // machines.
3118 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003119 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003120 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003121
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003122 // This checks that the pool buffer given is big enough.
3123 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003124 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003125 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003126
Laurence Lundblade3427dee2021-06-20 11:11:24 -07003127 QCBORDecode_SetUpAllocator(pMe, MemPool_Function, Pool.ptr, bAllStrings);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003128
Laurence Lundblade30816f22018-11-10 13:40:22 +07003129 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003130}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08003131#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003132
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003133
3134
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003135
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003136/**
3137 * @brief Consume an entire map or array including its contents.
3138 *
3139 * @param[in] pMe The decoder context.
3140 * @param[in] pItemToConsume The array/map whose contents are to be
3141 * consumed.
Laurence Lundbladed82ca402025-06-16 11:01:16 -07003142 * @param[out] pbBreak Set to true if extra break was consumed.
3143 * Can be NULL.
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003144 * @param[out] puNextNestLevel The next nesting level after the item was
3145 * fully consumed.
3146 *
3147 * This may be called when @c pItemToConsume is not an array or
3148 * map. In that case, this is just a pass through for @c puNextNestLevel
3149 * since there is nothing to do.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003150 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003151static QCBORError
3152QCBORDecode_Private_ConsumeItem(QCBORDecodeContext *pMe,
3153 const QCBORItem *pItemToConsume,
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003154 bool *pbBreak,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003155 uint8_t *puNextNestLevel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003156{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003157 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003158 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003159
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003160 /* If it is a map or array, this will tell if it is empty. */
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003161 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
3162
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003163 if(QCBORItem_IsMapOrArray(*pItemToConsume) && !bIsEmpty) {
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003164 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003165
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003166 /* This works for definite- and indefinite-length maps and
3167 * arrays by using the nesting level
Laurence Lundblade1341c592020-04-11 14:19:05 -07003168 */
3169 do {
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003170 uReturn = QCBORDecode_Private_GetNextMapOrArray(pMe, pbBreak, &Item);
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003171 if(QCBORDecode_IsUnrecoverableError(uReturn) ||
3172 uReturn == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003173 goto Done;
3174 }
3175 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003176
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003177 *puNextNestLevel = Item.uNextNestLevel;
3178
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003179 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003180
Laurence Lundblade1341c592020-04-11 14:19:05 -07003181 } else {
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003182 /* pItemToConsume is not a map or array. Just pass the nesting
Laurence Lundbladed82ca402025-06-16 11:01:16 -07003183 * level through. Ensure pbBreak is false. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003184 *puNextNestLevel = pItemToConsume->uNextNestLevel;
Laurence Lundbladed82ca402025-06-16 11:01:16 -07003185 if(pbBreak) {
3186 *pbBreak = false;
3187 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003188
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003189 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003190 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003191
3192Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003193 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003194}
3195
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003196
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003197/*
3198 * Public function, see header qcbor/qcbor_decode.h file
3199 */
3200void
3201QCBORDecode_VGetNextConsume(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003202{
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003203 QCBORDecode_VGetNext(pMe, pDecodedItem);
3204
3205 if(pMe->uLastError == QCBOR_SUCCESS) {
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003206 pMe->uLastError = (uint8_t)QCBORDecode_Private_ConsumeItem(pMe, pDecodedItem, NULL,
Máté Tóth-Pálc6d59682021-05-26 18:55:30 +02003207 &pDecodedItem->uNextNestLevel);
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003208 }
3209}
3210
3211
Laurence Lundblade11654912024-05-09 11:49:24 -07003212/*
3213 * Public function, see header qcbor/qcbor_decode.h file
3214 */
Laurence Lundblade535bb5e2024-06-16 12:06:32 -07003215QCBORError
3216QCBORDecode_EndCheck(QCBORDecodeContext *pMe)
Laurence Lundblade11654912024-05-09 11:49:24 -07003217{
Laurence Lundblade535bb5e2024-06-16 12:06:32 -07003218 size_t uCursorOffset;
3219 QCBORError uErr;
Laurence Lundblade11654912024-05-09 11:49:24 -07003220
Laurence Lundblade535bb5e2024-06-16 12:06:32 -07003221 uErr = QCBORDecode_GetError(pMe);
3222 if(uErr != QCBOR_SUCCESS) {
3223 return uErr;
Laurence Lundblade11654912024-05-09 11:49:24 -07003224 }
3225
3226 uCursorOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
3227
3228 if(uCursorOffset == UsefulInputBuf_GetBufferLength(&(pMe->InBuf))) {
Laurence Lundblade535bb5e2024-06-16 12:06:32 -07003229 return QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade11654912024-05-09 11:49:24 -07003230 }
Laurence Lundblade535bb5e2024-06-16 12:06:32 -07003231
3232 return QCBOR_SUCCESS;
Laurence Lundblade11654912024-05-09 11:49:24 -07003233}
3234
3235
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003236/**
3237 * @brief Rewind cursor to start as if map or array were just entered.
3238 *
3239 * @param[in] pMe The decoding context
3240 *
3241 * This affects the nesting tracking and the UsefulInputBuf.
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003242 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003243static void
3244QCBORDecode_Private_RewindMapOrArray(QCBORDecodeContext *pMe)
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003245{
3246 /* Reset nesting tracking to the deepest bounded level */
3247 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
3248
3249 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3250
3251 /* Reposition traversal cursor to the start of the map/array */
3252 UsefulInputBuf_Seek(&(pMe->InBuf),
3253 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
3254}
3255
3256
3257/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003258 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003259 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003260void
3261QCBORDecode_Rewind(QCBORDecodeContext *pMe)
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003262{
3263 if(pMe->nesting.pCurrentBounded != NULL) {
3264 /* In a bounded map, array or bstr-wrapped CBOR */
3265
3266 if(DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
3267 /* In bstr-wrapped CBOR. */
3268
3269 /* Reposition traversal cursor to start of wrapping byte string */
3270 UsefulInputBuf_Seek(&(pMe->InBuf),
3271 pMe->nesting.pCurrentBounded->u.bs.uBstrStartOffset);
3272 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
3273
3274 } else {
3275 /* In a map or array */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003276 QCBORDecode_Private_RewindMapOrArray(pMe);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003277 }
3278
3279 } else {
3280 /* Not in anything bounded */
3281
3282 /* Reposition traversal cursor to the start of input CBOR */
3283 UsefulInputBuf_Seek(&(pMe->InBuf), 0ULL);
3284
3285 /* Reset nesting tracking to beginning of input. */
3286 DecodeNesting_Init(&(pMe->nesting));
3287 }
3288
3289 pMe->uLastError = QCBOR_SUCCESS;
3290}
3291
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003292
Laurence Lundblade9b334962020-08-27 10:55:53 -07003293
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003294
3295
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003296typedef struct {
3297 void *pCBContext;
3298 QCBORItemCallback pfCallback;
3299} MapSearchCallBack;
3300
3301typedef struct {
3302 size_t uStartOffset;
3303 uint16_t uItemCount;
3304} MapSearchInfo;
3305
3306
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003307/**
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003308 * @brief Search a map for a set of items.
3309 *
3310 * @param[in] pMe The decode context to search.
3311 * @param[in,out] pItemArray The items to search for and the items found.
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003312 * @param[out] pInfo Several bits of meta-info returned by search.
3313 * @param[in] pCallBack Callback object or @c NULL.
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003314 *
3315 * @retval QCBOR_ERR_NOT_ENTERED Trying to search without entering a map.
3316 *
3317 * @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
3318 * were found for one of the labels being
3319 * search for. This duplicate detection is
3320 * only performed for items in pItemArray,
3321 * not every item in the map.
3322 *
3323 * @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
3324 * wrong for the matchd label.
3325 *
3326 * @retval Also errors returned by QCBORDecode_GetNext().
3327 *
Laurence Lundblade88ba5662024-11-03 02:10:24 -08003328 * On input, @c pItemArray contains a list of labels and data types of
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003329 * items to be found.
3330 *
3331 * On output, the fully retrieved items are filled in with values and
3332 * such. The label was matched, so it never changes.
3333 *
3334 * If an item was not found, its data type is set to @ref QCBOR_TYPE_NONE.
3335 *
3336 * This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003337 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003338static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003339QCBORDecode_Private_MapSearch(QCBORDecodeContext *pMe,
3340 QCBORItem *pItemArray,
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003341 MapSearchInfo *pInfo,
3342 MapSearchCallBack *pCallBack)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003343{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003344 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003345 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07003346
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003347 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003348 uReturn = pMe->uLastError;
3349 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003350 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003351
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003352 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003353 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
3354 /* QCBOR_TYPE_NONE as first item indicates just looking
3355 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003356 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
3357 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003358 }
3359
Laurence Lundblade085d7952020-07-24 10:26:30 -07003360 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
3361 // It is an empty bounded array or map
3362 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
3363 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003364 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07003365 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003366 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003367 // Nothing is ever found in an empty array or map. All items
3368 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07003369 uReturn = QCBOR_SUCCESS;
3370 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003371 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003372 }
3373
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003374 QCBORDecodeNesting SaveNesting;
Laurence Lundblade11654912024-05-09 11:49:24 -07003375 size_t uSavePos = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade085d7952020-07-24 10:26:30 -07003376 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
3377
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003378 /* Reposition to search from the start of the map / array */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003379 QCBORDecode_Private_RewindMapOrArray(pMe);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003380
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003381 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003382 Loop over all the items in the map or array. Each item
3383 could be a map or array, but label matching is only at
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003384 the main level. This handles definite- and indefinite-
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003385 length maps and arrays. The only reason this is ever
3386 called on arrays is to find their end position.
3387
3388 This will always run over all items in order to do
3389 duplicate detection.
3390
3391 This will exit with failure if it encounters an
3392 unrecoverable error, but continue on for recoverable
3393 errors.
3394
3395 If a recoverable error occurs on a matched item, then
3396 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003397 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07003398 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003399 if(pInfo) {
3400 pInfo->uItemCount = 0;
3401 }
Máté Tóth-Pál2f2aa5f2021-05-17 21:35:09 +02003402 uint8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003403 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003404 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07003405 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003406
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003407 /* Get the item */
3408 QCBORItem Item;
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07003409 /* QCBORDecode_Private_GetNextTagContent() rather than GetNext()
3410 * because a label match is performed on recoverable errors to
3411 * be able to return the the error code for the found item. */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003412 QCBORError uResult = QCBORDecode_Private_GetNextTagContent(pMe, &Item);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003413 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003414 /* The map/array can't be decoded when unrecoverable errors occur */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003415 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003416 goto Done;
3417 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003418 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003419 /* Unexpected end of map or array. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003420 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003421 goto Done;
3422 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003423
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003424 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003425 bool bMatched = false;
3426 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003427 if(QCBORItem_MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003428 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003429 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
3430 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003431 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003432 }
Laurence Lundblade63926052021-03-29 16:05:51 -07003433 if(uResult != QCBOR_SUCCESS) {
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003434 /* The label matches, but the data item is in error.
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07003435 * It is OK to have recoverable errors on items that
3436 * are not matched. */
Laurence Lundblade63926052021-03-29 16:05:51 -07003437 uReturn = uResult;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003438 goto Done;
3439 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003440 if(!QCBORItem_MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade63926052021-03-29 16:05:51 -07003441 /* The data item is not of the type(s) requested */
3442 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003443 goto Done;
3444 }
3445
Laurence Lundblade1341c592020-04-11 14:19:05 -07003446 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003447 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003448 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003449 if(pInfo) {
3450 pInfo->uStartOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003451 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003452 bMatched = true;
3453 }
3454 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003455
3456
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003457 if(!bMatched && pCallBack != NULL) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003458 /*
3459 Call the callback on unmatched labels.
3460 (It is tempting to do duplicate detection here, but that would
3461 require dynamic memory allocation because the number of labels
3462 that might be encountered is unbounded.)
3463 */
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003464 uReturn = (*(pCallBack->pfCallback))(pCallBack->pCBContext, &Item);
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003465 if(uReturn != QCBOR_SUCCESS) {
3466 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003467 }
3468 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003469
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003470 /*
3471 Consume the item whether matched or not. This
3472 does the work of traversing maps and array and
3473 everything in them. In this loop only the
3474 items at the current nesting level are examined
3475 to match the labels.
3476 */
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003477 uReturn = QCBORDecode_Private_ConsumeItem(pMe, &Item, NULL, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003478 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003479 goto Done;
3480 }
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003481
3482 if(pInfo) {
3483 pInfo->uItemCount++;
3484 }
3485
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003486 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003487
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003488 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003489
3490 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003491
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003492 // Check here makes sure that this won't accidentally be
3493 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003494 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003495 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
3496 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003497 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
3498 goto Done;
3499 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003500 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
3501 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003502
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003503 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003504 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundblade11654912024-05-09 11:49:24 -07003505 UsefulInputBuf_Seek(&(pMe->InBuf), uSavePos);
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003506
3507 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003508 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07003509 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003510 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003511 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
3512 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003513 }
3514 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003515
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003516 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003517}
3518
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003519
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003520/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003521 * Public function, see header qcbor/qcbor_decode.h file
3522 */
3523void
3524QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
3525 int64_t nLabel,
3526 uint8_t uQcborType,
3527 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003528{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003529 if(pMe->uLastError != QCBOR_SUCCESS) {
3530 return;
3531 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003532
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003533 QCBORItem OneItemSeach[2];
3534 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3535 OneItemSeach[0].label.int64 = nLabel;
3536 OneItemSeach[0].uDataType = uQcborType;
3537 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003538
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003539 QCBORError uReturn = QCBORDecode_Private_MapSearch(pMe, OneItemSeach, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003540
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003541 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07003542 pItem->uDataType = QCBOR_TYPE_NONE;
3543 pItem->uLabelType = QCBOR_TYPE_NONE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003544 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003545 }
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07003546
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003547 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003548 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003549 }
3550
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07003551 *pItem = OneItemSeach[0];
3552 QCBORDecode_Private_CopyTags(pMe, pItem);
3553
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003554 Done:
3555 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003556}
3557
3558
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003559/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003560 * Public function, see header qcbor/qcbor_decode.h file
3561 */
3562void
3563QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
3564 const char *szLabel,
3565 uint8_t uQcborType,
3566 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003567{
Laurence Lundbladeda095972020-06-06 18:35:33 -07003568 if(pMe->uLastError != QCBOR_SUCCESS) {
3569 return;
3570 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003571
Laurence Lundbladeec290b82024-06-10 11:10:54 -07003572#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003573 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003574 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3575 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3576 OneItemSeach[0].uDataType = uQcborType;
3577 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003578
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003579 QCBORError uReturn = QCBORDecode_Private_MapSearch(pMe, OneItemSeach, NULL, NULL);
3580
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003581 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07003582 pItem->uDataType = QCBOR_TYPE_NONE;
3583 pItem->uLabelType = QCBOR_TYPE_NONE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003584 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003585 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003586 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003587 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003588 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003589 }
3590
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003591 *pItem = OneItemSeach[0];
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07003592 QCBORDecode_Private_CopyTags(pMe, pItem);
Laurence Lundbladeec290b82024-06-10 11:10:54 -07003593
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07003594Done:
Laurence Lundbladeec290b82024-06-10 11:10:54 -07003595#else
3596 (void)pMe;
3597 (void)szLabel;
3598 (void)uQcborType;
3599 (void)pItem;
3600 QCBORError uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
3601#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
3602
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003603 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003604}
3605
3606
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003607
3608/**
3609 * @brief Semi-private. Get pointer, length and item for an array or map.
3610 *
3611 * @param[in] pMe The decode context.
3612 * @param[in] uType CBOR major type, either array/map.
3613 * @param[out] pItem The item for the array/map.
3614 * @param[out] pEncodedCBOR Pointer and length of the encoded map or array.
3615 *
Laurence Lundblade88ba5662024-11-03 02:10:24 -08003616 * The next item to be decoded must be a map or array as specified by @c uType.
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003617 *
Laurence Lundblade88ba5662024-11-03 02:10:24 -08003618 * @c pItem will be filled in with the label and tags of the array or map
3619 * in addition to @c pEncodedCBOR giving the pointer and length of the
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003620 * encoded CBOR.
3621 *
3622 * When this is complete, the traversal cursor is at the end of the array or
3623 * map that was retrieved.
3624 */
3625void
3626QCBORDecode_Private_GetArrayOrMap(QCBORDecodeContext *pMe,
3627 const uint8_t uType,
3628 QCBORItem *pItem,
3629 UsefulBufC *pEncodedCBOR)
3630{
3631 QCBORError uErr;
3632 uint8_t uNestLevel;
3633 size_t uStartingCursor;
3634 size_t uStartOfReturned;
3635 size_t uEndOfReturned;
3636 size_t uTempSaveCursor;
3637 bool bInMap;
3638 QCBORItem LabelItem;
3639 bool EndedByBreak;
3640
3641 uStartingCursor = UsefulInputBuf_Tell(&(pMe->InBuf));
3642 bInMap = DecodeNesting_IsCurrentTypeMap(&(pMe->nesting));
3643
3644 /* Could call GetNext here, but don't need to because this
3645 * is only interested in arrays and maps. */
3646 uErr = QCBORDecode_Private_GetNextMapOrArray(pMe, NULL, pItem);
3647 if(uErr != QCBOR_SUCCESS) {
3648 pMe->uLastError = (uint8_t)uErr;
3649 return;
3650 }
3651
Laurence Lundblade5db34da2024-05-30 03:14:35 -07003652 uint8_t uItemDataType = pItem->uDataType;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07003653#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
Laurence Lundblade5db34da2024-05-30 03:14:35 -07003654 if(uItemDataType == QCBOR_TYPE_MAP_AS_ARRAY) {
3655 uItemDataType = QCBOR_TYPE_ARRAY;
3656 }
Laurence Lundbladeec290b82024-06-10 11:10:54 -07003657#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
Laurence Lundblade5db34da2024-05-30 03:14:35 -07003658
3659 if(uItemDataType != uType) {
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003660 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
3661 return;
3662 }
3663
3664 if(bInMap) {
3665 /* If the item is in a map, the start of the array/map
3666 * itself, not the label, must be found. Do this by
3667 * rewinding to the starting position and fetching
3668 * just the label data item. QCBORDecode_Private_GetNextTagNumber()
3669 * doesn't do any of the array/map item counting or nesting
3670 * level tracking. Used here it will just fetech the label
3671 * data item.
3672 *
3673 * Have to save the cursor and put it back to the position
3674 * after the full item once the label as been fetched by
3675 * itself.
3676 */
3677 uTempSaveCursor = UsefulInputBuf_Tell(&(pMe->InBuf));
3678 UsefulInputBuf_Seek(&(pMe->InBuf), uStartingCursor);
3679
3680 /* Item has been fetched once so safe to ignore error */
3681 (void)QCBORDecode_Private_GetNextTagNumber(pMe, &LabelItem);
3682
3683 uStartOfReturned = UsefulInputBuf_Tell(&(pMe->InBuf));
3684 UsefulInputBuf_Seek(&(pMe->InBuf), uTempSaveCursor);
3685 } else {
3686 uStartOfReturned = uStartingCursor;
3687 }
3688
3689 /* Consume the entire array/map to find the end */
3690 uErr = QCBORDecode_Private_ConsumeItem(pMe, pItem, &EndedByBreak, &uNestLevel);
3691 if(uErr != QCBOR_SUCCESS) {
3692 pMe->uLastError = (uint8_t)uErr;
3693 goto Done;
3694 }
3695
3696 /* Fill in returned values */
3697 uEndOfReturned = UsefulInputBuf_Tell(&(pMe->InBuf));
3698 if(EndedByBreak) {
3699 /* When ascending nesting levels, a break for the level above
3700 * was consumed. That break is not a part of what is consumed here. */
3701 uEndOfReturned--;
3702 }
3703 pEncodedCBOR->ptr = UsefulInputBuf_OffsetToPointer(&(pMe->InBuf), uStartOfReturned);
3704 pEncodedCBOR->len = uEndOfReturned - uStartOfReturned;
3705
3706Done:
3707 return;
3708}
3709
3710
3711/**
3712 * @brief Semi-private. Get pointer, length and item count of an array or map.
3713 *
3714 * @param[in] pMe The decode context.
3715 * @param[in] pTarget The label and type of the array or map to retrieve.
3716 * @param[out] pItem The item for the array/map.
3717 * @param[out] pEncodedCBOR Pointer and length of the encoded map or array.
3718 *
Laurence Lundblade88ba5662024-11-03 02:10:24 -08003719 * The next item to be decoded must be a map or array as specified by @c uType.
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003720 *
3721 * When this is complete, the traversal cursor is unchanged.
3722 */void
3723QCBORDecode_Private_SearchAndGetArrayOrMap(QCBORDecodeContext *pMe,
3724 QCBORItem *pTarget,
3725 QCBORItem *pItem,
3726 UsefulBufC *pEncodedCBOR)
3727{
3728 MapSearchInfo Info;
3729 QCBORDecodeNesting SaveNesting;
3730 size_t uSaveCursor;
3731
3732 pMe->uLastError = (uint8_t)QCBORDecode_Private_MapSearch(pMe, pTarget, &Info, NULL);
3733 if(pMe->uLastError != QCBOR_SUCCESS) {
3734 return;
3735 }
3736
3737 /* Save the whole position of things so they can be restored.
3738 * so the cursor position is unchanged by this operation, like
3739 * all the other GetXxxxInMap() operations. */
3740 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
3741 uSaveCursor = UsefulInputBuf_Tell(&(pMe->InBuf));
3742
3743 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3744 UsefulInputBuf_Seek(&(pMe->InBuf), Info.uStartOffset);
3745 QCBORDecode_Private_GetArrayOrMap(pMe, pTarget[0].uDataType, pItem, pEncodedCBOR);
3746
3747 UsefulInputBuf_Seek(&(pMe->InBuf), uSaveCursor);
3748 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
3749}
3750
3751
3752
3753
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003754/**
3755 * @brief Is a QCBOR_TYPE in the type list?
3756 *
3757 * @param[in] uDataType Type to check for.
3758 * @param[in] puTypeList List to check.
3759 *
3760 * @retval QCBOR_SUCCESS If in the list.
3761 * @retval QCBOR_ERR_UNEXPECTED_TYPE Not in the list.
3762 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07003763static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003764QCBOR_Private_CheckTypeList(const int uDataType,
3765 const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003766{
3767 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08003768 if(uDataType == puTypeList[i]) { /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003769 return QCBOR_SUCCESS;
3770 }
3771 }
3772 return QCBOR_ERR_UNEXPECTED_TYPE;
3773}
3774
Laurence Lundblade67257dc2020-07-27 03:33:37 -07003775
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003776/**
Laurence Lundblade37286c02022-09-03 10:05:02 -07003777 * Match a tag/type specification against the type of the item.
3778 *
3779 * @param[in] TagSpec Specification for matching tags.
3780 * @param[in] pItem The item to check.
3781 *
Laurence Lundblade88ba5662024-11-03 02:10:24 -08003782 * @retval QCBOR_SUCCESS @c uDataType is allowed by @c TagSpec
3783 * @retval QCBOR_ERR_UNEXPECTED_TYPE @c uDataType is not allowed by @c TagSpec
Laurence Lundblade37286c02022-09-03 10:05:02 -07003784 *
3785 * This checks the item data type of untagged items as well as of
3786 * tagged items against a specification to see if decoding should
3787 * proceed.
3788 *
3789 * This relies on the automatic tag decoding done by QCBOR that turns
3790 * tag numbers into particular QCBOR_TYPEs so there is no actual
3791 * comparsion of tag numbers, just of QCBOR_TYPEs.
3792 *
3793 * This checks the data item type as possibly representing the tag
3794 * number or as the tag content type.
3795 *
Laurence Lundbladec4bded32024-10-09 10:34:39 -07003796 * If QCBOR_DISABLE_TAGS is #defined, this primarily checks the item
3797 * data type against the allowed tag content types, but also checks
3798 * against the tagged types. The QCBOR_TYPEs checked will never be
3799 * associated with tag numbers, but this checking is needed for the
3800 * text and byte string use cases .
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003801 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07003802static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003803QCBOR_Private_CheckTagRequirement(const QCBOR_Private_TagSpec TagSpec,
3804 const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07003805{
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08003806 const int nItemType = pItem->uDataType; /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade37286c02022-09-03 10:05:02 -07003807 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
3808
3809#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08003810 /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003811 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
3812 pItem->uTags[0] != CBOR_TAG_INVALID16) {
3813 /* There are tags that QCBOR couldn't process on this item and
Laurence Lundblade37286c02022-09-03 10:05:02 -07003814 * the caller has told us there should not be.
3815 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003816 return QCBOR_ERR_UNEXPECTED_TYPE;
3817 }
3818
Laurence Lundblade9b334962020-08-27 10:55:53 -07003819 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
Laurence Lundblade37286c02022-09-03 10:05:02 -07003820 /* Must match the tag number and only the tag */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003821 return QCBOR_Private_CheckTypeList(nItemType, TagSpec.uTaggedTypes);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003822 }
3823
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003824 QCBORError uReturn = QCBOR_Private_CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003825 if(uReturn == QCBOR_SUCCESS) {
3826 return QCBOR_SUCCESS;
3827 }
3828
3829 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
3830 /* Must match the content type and only the content type.
Laurence Lundblade37286c02022-09-03 10:05:02 -07003831 * There was no match just above so it is a fail. */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003832 return QCBOR_ERR_UNEXPECTED_TYPE;
3833 }
3834
Laurence Lundbladec4bded32024-10-09 10:34:39 -07003835 /* QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG: If here it can match either
3836 * the tag or the content and it hasn't matched the content, so the
3837 * end result is whether it matches the tag. This is the tag
3838 * optional case that the CBOR standard discourages.
Laurence Lundblade37286c02022-09-03 10:05:02 -07003839 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003840
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003841 return QCBOR_Private_CheckTypeList(nItemType, TagSpec.uTaggedTypes);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003842
Laurence Lundblade37286c02022-09-03 10:05:02 -07003843#else /* QCBOR_DISABLE_TAGS */
3844 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
Laurence Lundbladec4bded32024-10-09 10:34:39 -07003845 /* This is only checking base QCBOR types, not those associated
3846 * with tag numbers since you can get here with tag numbers.
3847 */
3848 return QCBOR_Private_CheckTypeList(nItemType, TagSpec.uTaggedTypes);
Laurence Lundblade37286c02022-09-03 10:05:02 -07003849 }
3850
Laurence Lundblade0f01ac62024-02-18 23:07:07 -07003851 return QCBOR_Private_CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
Laurence Lundblade37286c02022-09-03 10:05:02 -07003852
3853#endif /* QCBOR_DISABLE_TAGS */
3854}
Laurence Lundblade9b334962020-08-27 10:55:53 -07003855
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003856
3857/**
3858 * @brief Get an item by label to match a tag specification.
3859 *
3860 * @param[in] pMe The decode context.
3861 * @param[in] nLabel The label to search map for.
3862 * @param[in] TagSpec The tag number specification to match.
3863 * @param[out] pItem The item found.
3864 *
3865 * This finds the item with the given label in currently open
3866 * map. Then checks that its tag number and types matches the tag
3867 * specification. If not, an error is set in the decode context.
3868 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003869static void
3870QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
3871 const int64_t nLabel,
3872 const QCBOR_Private_TagSpec TagSpec,
3873 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003874{
3875 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
3876 if(pMe->uLastError != QCBOR_SUCCESS) {
3877 return;
3878 }
3879
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003880 pMe->uLastError = (uint8_t)QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003881}
3882
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003883
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003884/**
3885 * @brief Get an item by label to match a tag specification.
3886 *
3887 * @param[in] pMe The decode context.
3888 * @param[in] szLabel The label to search map for.
3889 * @param[in] TagSpec The tag number specification to match.
3890 * @param[out] pItem The item found.
3891 *
3892 * This finds the item with the given label in currently open
3893 * map. Then checks that its tag number and types matches the tag
3894 * specification. If not, an error is set in the decode context.
3895 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003896static void
3897QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
3898 const char *szLabel,
3899 const QCBOR_Private_TagSpec TagSpec,
3900 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003901{
3902 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
3903 if(pMe->uLastError != QCBOR_SUCCESS) {
3904 return;
3905 }
3906
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003907 pMe->uLastError = (uint8_t)QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003908}
3909
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003910
3911/**
3912 * @brief Semi-private to get an string by label to match a tag specification.
3913 *
3914 * @param[in] pMe The decode context.
3915 * @param[in] nLabel The label to search map for.
3916 * @param[in] TagSpec The tag number specification to match.
3917 * @param[out] pString The string found.
3918 *
3919 * This finds the string with the given label in currently open
3920 * map. Then checks that its tag number and types matches the tag
3921 * specification. If not, an error is set in the decode context.
3922 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003923void
3924QCBORDecode_Private_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
3925 const int64_t nLabel,
3926 const QCBOR_Private_TagSpec TagSpec,
3927 UsefulBufC *pString)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003928{
3929 QCBORItem Item;
3930 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
3931 if(pMe->uLastError == QCBOR_SUCCESS) {
3932 *pString = Item.val.string;
3933 }
3934}
3935
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003936
3937/**
3938 * @brief Semi-private to get an string by label to match a tag specification.
3939 *
3940 * @param[in] pMe The decode context.
3941 * @param[in] szLabel The label to search map for.
3942 * @param[in] TagSpec The tag number specification to match.
3943 * @param[out] pString The string found.
3944 *
3945 * This finds the string with the given label in currently open
3946 * map. Then checks that its tag number and types matches the tag
3947 * specification. If not, an error is set in the decode context.
3948 */void
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003949QCBORDecode_Private_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
3950 const char * szLabel,
3951 const QCBOR_Private_TagSpec TagSpec,
3952 UsefulBufC *pString)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003953{
3954 QCBORItem Item;
3955 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
3956 if(pMe->uLastError == QCBOR_SUCCESS) {
3957 *pString = Item.val.string;
3958 }
3959}
Laurence Lundblade1341c592020-04-11 14:19:05 -07003960
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003961
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003962/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003963 * Public function, see header qcbor/qcbor_decode.h file
3964 */
3965void
3966QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003967{
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003968 QCBORError uErr = QCBORDecode_Private_MapSearch(pMe, pItemList, NULL, NULL);
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003969 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003970}
3971
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003972/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003973 * Public function, see header qcbor/qcbor_decode.h file
3974 */
3975void
3976QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3977 QCBORItem *pItemList,
3978 void *pCallbackCtx,
3979 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003980{
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003981 MapSearchCallBack CallBack;
3982 CallBack.pCBContext = pCallbackCtx;
3983 CallBack.pfCallback = pfCB;
3984
3985 QCBORError uErr = QCBORDecode_Private_MapSearch(pMe, pItemList, NULL, &CallBack);
3986
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003987 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003988}
3989
3990
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003991/**
3992 * @brief Search for a map/array by label and enter it
3993 *
3994 * @param[in] pMe The decode context.
3995 * @param[in] pSearch The map/array to search for.
3996 *
3997 * @c pSearch is expected to contain one item of type map or array
3998 * with the label specified. The current bounded map will be searched for
3999 * this and if found will be entered.
4000 *
4001 * If the label is not found, or the item found is not a map or array,
4002 * the error state is set.
4003 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004004static void
4005QCBORDecode_Private_SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07004006{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07004007 // The first item in pSearch is the one that is to be
4008 // entered. It should be the only one filled in. Any other
4009 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07004010 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07004011 return;
4012 }
4013
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07004014 MapSearchInfo Info;
4015 pMe->uLastError = (uint8_t)QCBORDecode_Private_MapSearch(pMe, pSearch, &Info, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07004016 if(pMe->uLastError != QCBOR_SUCCESS) {
4017 return;
4018 }
4019
Laurence Lundblade9b334962020-08-27 10:55:53 -07004020 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07004021 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07004022 return;
4023 }
4024
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004025
4026 /* The map or array was found. Now enter it.
4027 *
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08004028 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
4029 * next item for the pre-order traversal cursor to be the map/array
4030 * found by MapSearch(). The next few lines of code force the
4031 * cursor to that.
4032 *
4033 * There is no need to retain the old cursor because
4034 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
4035 * beginning of the map/array being entered.
4036 *
4037 * The cursor is forced by: 1) setting the input buffer position to
4038 * the item offset found by MapSearch(), 2) setting the map/array
4039 * counter to the total in the map/array, 3) setting the nesting
4040 * level. Setting the map/array counter to the total is not
4041 * strictly correct, but this is OK because this cursor only needs
4042 * to be used to get one item and MapSearch() has already found it
4043 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004044 */
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07004045 UsefulInputBuf_Seek(&(pMe->InBuf), Info.uStartOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004046
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08004047 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
4048
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004049 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07004050
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004051 QCBORDecode_Private_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004052}
4053
4054
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004055/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004056 * Public function, see header qcbor/qcbor_decode.h file
4057 */
4058void
4059QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004060{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07004061 QCBORItem OneItemSeach[2];
4062 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
4063 OneItemSeach[0].label.int64 = nLabel;
4064 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
4065 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07004066
Laurence Lundblade9b334962020-08-27 10:55:53 -07004067 /* The map to enter was found, now finish off entering it. */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004068 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004069}
4070
4071
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004072/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004073 * Public function, see header qcbor/qcbor_decode.h file
4074 */
4075void
4076QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004077{
Laurence Lundbladeec290b82024-06-10 11:10:54 -07004078#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07004079 QCBORItem OneItemSeach[2];
4080 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
4081 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
4082 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
4083 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07004084
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004085 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladeec290b82024-06-10 11:10:54 -07004086#else
4087 (void)szLabel;
4088 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
4089#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004090}
4091
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004092/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004093 * Public function, see header qcbor/qcbor_decode.h file
4094 */
4095void
4096QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07004097{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07004098 QCBORItem OneItemSeach[2];
4099 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
4100 OneItemSeach[0].label.int64 = nLabel;
4101 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
4102 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07004103
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004104 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07004105}
4106
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004107/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004108 * Public function, see header qcbor/qcbor_decode.h file
4109 */
4110void
4111QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundblade34691b92020-05-18 22:25:25 -07004112{
Laurence Lundbladeec290b82024-06-10 11:10:54 -07004113#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07004114 QCBORItem OneItemSeach[2];
4115 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
4116 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
4117 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
4118 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07004119
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004120 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladeec290b82024-06-10 11:10:54 -07004121#else
4122 (void)szLabel;
4123 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
4124#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
Laurence Lundblade1341c592020-04-11 14:19:05 -07004125}
4126
4127
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004128/**
4129 * @brief Semi-private to do the the work for EnterMap() and EnterArray().
4130 *
4131 * @param[in] pMe The decode context
4132 * @param[in] uType QCBOR_TYPE_MAP or QCBOR_TYPE_ARRAY.
4133 * @param[out] pItem The data item for the map or array entered.
4134 *
4135 * The next item in the traversal must be a map or array. This
4136 * consumes that item and does the book keeping to enter the map or
4137 * array.
4138 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004139void
4140QCBORDecode_Private_EnterBoundedMapOrArray(QCBORDecodeContext *pMe,
4141 const uint8_t uType,
4142 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004143{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07004144 QCBORError uErr;
4145
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004146 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07004147 if(pMe->uLastError != QCBOR_SUCCESS) {
4148 // Already in error state; do nothing.
4149 return;
4150 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07004151
Laurence Lundbladed40951e2020-08-28 11:11:14 -07004152 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004153 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07004154 uErr = QCBORDecode_GetNext(pMe, &Item);
4155 if(uErr != QCBOR_SUCCESS) {
4156 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07004157 }
Laurence Lundblade5db34da2024-05-30 03:14:35 -07004158
4159 uint8_t uItemDataType = Item.uDataType;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07004160
4161#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
Laurence Lundblade5db34da2024-05-30 03:14:35 -07004162 if(uItemDataType == QCBOR_TYPE_MAP_AS_ARRAY ) {
4163 uItemDataType = QCBOR_TYPE_ARRAY;
4164 }
Laurence Lundbladeec290b82024-06-10 11:10:54 -07004165#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
4166
Laurence Lundblade5db34da2024-05-30 03:14:35 -07004167 if(uItemDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07004168 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
4169 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07004170 }
4171
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004172 QCBORDecode_Private_CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07004173
4174
Laurence Lundbladef0499502020-08-01 11:55:57 -07004175 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07004176 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004177 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
4178 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07004179 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004180 pMe->nesting.pCurrent->u.ma.uCountCursor++;
4181 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07004182 // Special case to increment nesting level for zero-length maps
4183 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07004184 DecodeNesting_Descend(&(pMe->nesting), uType);
4185 }
4186
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07004187 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004188
Laurence Lundbladec45b5672020-07-25 23:16:36 -07004189 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
4190 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004191
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07004192 if(pItem != NULL) {
4193 *pItem = Item;
4194 }
4195
Laurence Lundbladec45b5672020-07-25 23:16:36 -07004196Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004197 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004198}
4199
Laurence Lundblade02625d42020-06-25 14:41:41 -07004200
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004201/**
4202 * @brief Exit a bounded map, array or bstr (semi-private).
4203 *
4204 * @param[in] pMe Decode context.
4205 * @param[in] uEndOffset The input buffer offset of the end of item exited.
4206 *
4207 * @returns QCBOR_SUCCESS or an error code.
4208 *
4209 * This is the common work for exiting a level that is a bounded map,
4210 * array or bstr wrapped CBOR.
4211 *
4212 * One chunk of work is to set up the pre-order traversal so it is at
4213 * the item just after the bounded map, array or bstr that is being
4214 * exited. This is somewhat complex.
4215 *
4216 * The other work is to level-up the bounded mode to next higest
4217 * bounded mode or the top level if there isn't one.
Laurence Lundblade02625d42020-06-25 14:41:41 -07004218 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004219static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004220QCBORDecode_Private_ExitBoundedLevel(QCBORDecodeContext *pMe,
4221 const uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004222{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004223 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004224
Laurence Lundblade02625d42020-06-25 14:41:41 -07004225 /*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004226 * First the pre-order-traversal byte offset is positioned to the
4227 * item just after the bounded mode item that was just consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07004228 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004229 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
4230
Laurence Lundblade02625d42020-06-25 14:41:41 -07004231 /*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004232 * Next, set the current nesting level to one above the bounded
4233 * level that was just exited.
4234 *
4235 * DecodeNesting_CheckBoundedType() is always called before this
4236 * and makes sure pCurrentBounded is valid.
Laurence Lundblade02625d42020-06-25 14:41:41 -07004237 */
4238 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
4239
4240 /*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004241 * This does the complex work of leveling up the pre-order
4242 * traversal when the end of a map or array or another bounded
4243 * level is reached. It may do nothing, or ascend all the way to
4244 * the top level.
Laurence Lundblade02625d42020-06-25 14:41:41 -07004245 */
Philip Odom83c4af02025-02-19 21:58:01 -08004246 uErr = QCBORDecode_Private_NestLevelAscender(pMe, NULL, NULL);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004247 if(uErr != QCBOR_SUCCESS) {
4248 goto Done;
4249 }
4250
Laurence Lundblade02625d42020-06-25 14:41:41 -07004251 /*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004252 * This makes the next highest bounded level the current bounded
4253 * level. If there is no next highest level, then no bounded mode
4254 * is in effect.
Laurence Lundblade02625d42020-06-25 14:41:41 -07004255 */
4256 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004257
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07004258 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004259
4260Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004261 return uErr;
4262}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004263
Laurence Lundblade02625d42020-06-25 14:41:41 -07004264
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004265/**
4266 * @brief Get started exiting a map or array (semi-private)
4267 *
4268 * @param[in] pMe The decode context
4269 * @param[in] uType QCBOR_TYPE_ARRAY or QCBOR_TYPE_MAP
4270 *
4271 * This does some work for map and array exiting (but not
4272 * bstr exiting). Then QCBORDecode_Private_ExitBoundedLevel()
4273 * is called to do the rest.
4274 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004275void
4276QCBORDecode_Private_ExitBoundedMapOrArray(QCBORDecodeContext *pMe,
4277 const uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004278{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004279 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07004280 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004281 return;
4282 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004283
Laurence Lundblade02625d42020-06-25 14:41:41 -07004284 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004285
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07004286 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07004287 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004288 goto Done;
4289 }
4290
Laurence Lundblade02625d42020-06-25 14:41:41 -07004291 /*
4292 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004293 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07004294 from previous map search, then do a dummy search.
4295 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07004296 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004297 QCBORItem Dummy;
4298 Dummy.uLabelType = QCBOR_TYPE_NONE;
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07004299 uErr = QCBORDecode_Private_MapSearch(pMe, &Dummy, NULL, NULL);
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004300 if(uErr != QCBOR_SUCCESS) {
4301 goto Done;
4302 }
4303 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004304
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004305 uErr = QCBORDecode_Private_ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004306
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004307Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004308 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004309}
4310
4311
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004312/**
4313 * @brief The main work of entering some byte-string wrapped CBOR.
4314 *
4315 * @param[in] pMe The decode context.
4316 * @param[in] pItem The byte string item.
4317 * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX
4318 * @param[out] pBstr Pointer and length of byte string entered.
4319 *
4320 * This is called once the byte string item has been decoded to do all
4321 * the book keeping work for descending a nesting level into the
4322 * nested CBOR.
4323 *
4324 * See QCBORDecode_EnterBstrWrapped() for details on uTagRequirement.
4325 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07004326static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004327QCBORDecode_Private_EnterBstrWrapped(QCBORDecodeContext *pMe,
4328 const QCBORItem *pItem,
4329 const uint8_t uTagRequirement,
4330 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004331{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07004332 if(pBstr) {
4333 *pBstr = NULLUsefulBufC;
4334 }
4335
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004336 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004337 /* Already in error state; do nothing. */
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004338 return pMe->uLastError;
4339 }
4340
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004341 QCBORError uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004342
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004343 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004344 {
4345 uTagRequirement,
4346 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
4347 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4348 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004349
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004350 uError = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004351 if(uError != QCBOR_SUCCESS) {
4352 goto Done;
4353 }
4354
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004355 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004356 /* Reverse the decrement done by GetNext() for the bstr so the
4357 * increment in QCBORDecode_NestLevelAscender() called by
4358 * ExitBoundedLevel() will work right.
4359 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004360 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07004361 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004362
4363 if(pBstr) {
4364 *pBstr = pItem->val.string;
4365 }
4366
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004367 /* This saves the current length of the UsefulInputBuf and then
4368 * narrows the UsefulInputBuf to start and length of the wrapped
4369 * CBOR that is being entered.
4370 *
4371 * Most of these calls are simple inline accessors so this doesn't
4372 * amount to much code.
4373 */
4374
Laurence Lundbladea4308a82020-10-03 18:08:57 -07004375 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004376 /* This check makes the cast of uPreviousLength to uint32_t below safe. */
4377 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07004378 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07004379 goto Done;
4380 }
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004381
4382 const size_t uStartOfBstr = UsefulInputBuf_PointerToOffset(&(pMe->InBuf),
4383 pItem->val.string.ptr);
4384 /* This check makes the cast of uStartOfBstr to uint32_t below safe. */
4385 if(uStartOfBstr == SIZE_MAX || uStartOfBstr > QCBOR_MAX_DECODE_INPUT_SIZE) {
4386 /* This should never happen because pItem->val.string.ptr should
4387 * always be valid since it was just returned.
4388 */
4389 uError = QCBOR_ERR_INPUT_TOO_LARGE;
4390 goto Done;
4391 }
4392
4393 const size_t uEndOfBstr = uStartOfBstr + pItem->val.string.len;
4394
4395 UsefulInputBuf_Seek(&(pMe->InBuf), uStartOfBstr);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07004396 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004397
Laurence Lundblade02625d42020-06-25 14:41:41 -07004398 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07004399 (uint32_t)uPreviousLength,
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004400 (uint32_t)uStartOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004401Done:
4402 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004403}
4404
4405
Laurence Lundblade02625d42020-06-25 14:41:41 -07004406/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004407 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07004408 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004409void
4410QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
4411 const uint8_t uTagRequirement,
4412 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07004413{
4414 if(pMe->uLastError != QCBOR_SUCCESS) {
4415 // Already in error state; do nothing.
4416 return;
4417 }
4418
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004419 /* Get the data item that is the byte string being entered */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004420 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07004421 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4422 if(pMe->uLastError != QCBOR_SUCCESS) {
4423 return;
4424 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07004425
Laurence Lundblade31fddb72024-05-13 13:03:35 -07004426 if(Item.uDataAlloc) {
4427 pMe->uLastError = QCBOR_ERR_CANNOT_ENTER_ALLOCATED_STRING;
4428 return;
4429 }
4430
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004431 pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
4432 &Item,
4433 uTagRequirement,
4434 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07004435}
4436
4437
Laurence Lundblade02625d42020-06-25 14:41:41 -07004438/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004439 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07004440 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004441void
4442QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
4443 const int64_t nLabel,
4444 const uint8_t uTagRequirement,
4445 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004446{
4447 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004448 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004449
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004450 pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
4451 &Item,
4452 uTagRequirement,
4453 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004454}
4455
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004456
Laurence Lundblade02625d42020-06-25 14:41:41 -07004457/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004458 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07004459 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004460void
4461QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
4462 const char *szLabel,
4463 const uint8_t uTagRequirement,
4464 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004465{
4466 QCBORItem Item;
4467 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4468
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004469 pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
4470 &Item,
4471 uTagRequirement,
4472 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004473}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004474
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004475
Laurence Lundblade02625d42020-06-25 14:41:41 -07004476/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004477 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07004478 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004479void
4480QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004481{
Laurence Lundblade02625d42020-06-25 14:41:41 -07004482 if(pMe->uLastError != QCBOR_SUCCESS) {
4483 // Already in error state; do nothing.
4484 return;
4485 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004486
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07004487 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07004488 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07004489 return;
4490 }
4491
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004492 const uint32_t uEndOfBstr = (uint32_t)UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
4493
Laurence Lundblade02625d42020-06-25 14:41:41 -07004494 /*
4495 Reset the length of the UsefulInputBuf to what it was before
4496 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004497 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07004498 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004499 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004500
4501
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004502 QCBORError uErr = QCBORDecode_Private_ExitBoundedLevel(pMe, uEndOfBstr);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004503 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004504}
4505
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004506
Laurence Lundbladee6430642020-03-14 21:15:44 -07004507
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004508/**
4509 * @brief Process simple type true and false, a boolean
4510 *
4511 * @param[in] pMe The decode context.
4512 * @param[in] pItem The item with either true or false.
4513 * @param[out] pBool The boolean value output.
4514 *
4515 * Sets the internal error if the item isn't a true or a false. Also
4516 * records any tag numbers as the tag numbers of the last item.
4517 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004518static void
4519QCBORDecode_Private_ProcessBool(QCBORDecodeContext *pMe,
4520 const QCBORItem *pItem,
4521 bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004522{
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004523 if(pMe->uLastError != QCBOR_SUCCESS) {
4524 /* Already in error state, do nothing */
4525 return;
4526 }
4527
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004528 switch(pItem->uDataType) {
4529 case QCBOR_TYPE_TRUE:
4530 *pBool = true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004531 break;
4532
4533 case QCBOR_TYPE_FALSE:
4534 *pBool = false;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004535 break;
4536
4537 default:
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004538 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004539 break;
4540 }
4541}
Laurence Lundbladee6430642020-03-14 21:15:44 -07004542
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004543
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004544/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004545 * Public function, see header qcbor/qcbor_decode.h file
4546 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004547void
4548QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004549{
Laurence Lundbladec4537442020-04-14 18:53:22 -07004550 QCBORItem Item;
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07004551 QCBORDecode_VGetNext(pMe, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004552 QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004553}
4554
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004555
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004556/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004557 * Public function, see header qcbor/qcbor_decode.h file
4558 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004559void
4560QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe,
4561 const int64_t nLabel,
4562 bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004563{
4564 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004565 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004566 QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004567}
4568
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004569
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004570/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004571 * Public function, see header qcbor/qcbor_decode.h file
4572 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004573void
4574QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe,
4575 const char *szLabel,
4576 bool *pValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004577{
4578 QCBORItem Item;
4579 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004580 QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004581}
4582
4583
Laurence Lundblade3888f002024-06-12 21:20:56 -07004584/**
4585 * @brief Process simple values.
4586 *
4587 * @param[in] pMe The decode context.
4588 * @param[in] pItem The item with the simple value.
4589 * @param[out] puSimple The simple value output.
4590 *
4591 * Sets the internal error if the item isn't a true or a false. Also
4592 * records any tag numbers as the tag numbers of the last item.
4593 */
4594static void
4595QCBORDecode_Private_ProcessSimple(QCBORDecodeContext *pMe,
4596 const QCBORItem *pItem,
4597 uint8_t *puSimple)
4598{
4599 if(pMe->uLastError != QCBOR_SUCCESS) {
4600 return;
4601 }
4602
4603 /* It's kind of lame to remap true...undef back to simple values, but
4604 * this function isn't used much and to not do it would require
4605 * changing GetNext() behavior in an incompatible way.
4606 */
4607 switch(pItem->uDataType) {
4608 case QCBOR_TYPE_UKNOWN_SIMPLE:
4609 *puSimple = pItem->val.uSimple;
4610 break;
4611
4612 case QCBOR_TYPE_TRUE:
4613 *puSimple = CBOR_SIMPLEV_TRUE;
4614 break;
4615
4616 case QCBOR_TYPE_FALSE:
4617 *puSimple = CBOR_SIMPLEV_FALSE;
4618 break;
4619
4620 case QCBOR_TYPE_NULL:
4621 *puSimple = CBOR_SIMPLEV_NULL;
4622 break;
4623
4624 case QCBOR_TYPE_UNDEF:
4625 *puSimple = CBOR_SIMPLEV_UNDEF;
4626 break;
4627
4628 default:
4629 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4630 return;
4631 }
Laurence Lundblade3888f002024-06-12 21:20:56 -07004632}
4633
4634/*
4635 * Public function, see header qcbor/qcbor_decode.h file
4636 */
4637void
4638QCBORDecode_GetSimple(QCBORDecodeContext *pMe, uint8_t *puSimple)
4639{
4640 QCBORItem Item;
Laurence Lundblade3888f002024-06-12 21:20:56 -07004641 QCBORDecode_VGetNext(pMe, &Item);
4642 QCBORDecode_Private_ProcessSimple(pMe, &Item, puSimple);
4643}
4644
4645/*
4646 * Public function, see header qcbor/qcbor_decode.h file
4647 */
4648void
4649QCBORDecode_GetSimpleInMapN(QCBORDecodeContext *pMe,
4650 int64_t nLabel,
4651 uint8_t *puSimpleValue)
4652{
4653 QCBORItem Item;
4654 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3888f002024-06-12 21:20:56 -07004655 QCBORDecode_Private_ProcessSimple(pMe, &Item, puSimpleValue);
4656}
4657
4658/*
4659 * Public function, see header qcbor/qcbor_decode.h file
4660 */
4661void
4662QCBORDecode_GetSimpleInMapSZ(QCBORDecodeContext *pMe,
4663 const char *szLabel,
4664 uint8_t *puSimpleValue)
4665{
4666 QCBORItem Item;
4667 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3888f002024-06-12 21:20:56 -07004668 QCBORDecode_Private_ProcessSimple(pMe, &Item, puSimpleValue);
4669}
4670
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004671
Laurence Lundbladec7114722020-08-13 05:11:40 -07004672
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004673/**
4674 * @brief Common processing for an epoch date.
4675 *
4676 * @param[in] pMe The decode context.
4677 * @param[in] pItem The item with the date.
4678 * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX.
4679 * @param[out] pnTime The returned date.
4680 *
4681 * Common processing for the date tag. Mostly make sure the tag
4682 * content is correct and copy forward any further other tag numbers.
4683 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004684static void
4685QCBORDecode_Private_ProcessEpochDate(QCBORDecodeContext *pMe,
4686 QCBORItem *pItem,
4687 const uint8_t uTagRequirement,
4688 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07004689{
4690 if(pMe->uLastError != QCBOR_SUCCESS) {
4691 // Already in error state, do nothing
4692 return;
4693 }
4694
4695 QCBORError uErr;
4696
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004697 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladec7114722020-08-13 05:11:40 -07004698 {
4699 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004700 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4701 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07004702 };
4703
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004704 uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004705 if(uErr != QCBOR_SUCCESS) {
4706 goto Done;
4707 }
4708
4709 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004710 uErr = QCBOR_Private_DecodeDateEpoch(pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004711 if(uErr != QCBOR_SUCCESS) {
4712 goto Done;
4713 }
4714 }
4715
4716 *pnTime = pItem->val.epochDate.nSeconds;
4717
4718Done:
4719 pMe->uLastError = (uint8_t)uErr;
4720}
4721
4722
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004723
4724/*
4725 * Public function, see header qcbor/qcbor_spiffy_decode.h file
4726 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004727void
4728QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
4729 uint8_t uTagRequirement,
4730 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07004731{
Laurence Lundbladec7114722020-08-13 05:11:40 -07004732 QCBORItem Item;
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07004733 QCBORDecode_VGetNext(pMe, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004734 QCBORDecode_Private_ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004735}
4736
4737
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004738/*
4739 * Public function, see header qcbor/qcbor_spiffy_decode.h file
4740 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07004741void
4742QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
4743 int64_t nLabel,
4744 uint8_t uTagRequirement,
4745 int64_t *pnTime)
4746{
4747 QCBORItem Item;
4748 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004749 QCBORDecode_Private_ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004750}
4751
4752
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004753/*
4754 * Public function, see header qcbor/qcbor_spiffy_decode.h file
4755 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07004756void
4757QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
4758 const char *szLabel,
4759 uint8_t uTagRequirement,
4760 int64_t *pnTime)
4761{
4762 QCBORItem Item;
4763 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004764 QCBORDecode_Private_ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004765}
4766
4767
4768
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004769/**
4770 * @brief Common processing for an epoch date.
4771 *
4772 * @param[in] pMe The decode context.
4773 * @param[in] pItem The item with the date.
4774 * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX.
4775 * @param[out] pnDays The returned day count.
4776 *
4777 * Common processing for the RFC 8943 day-count tag. Mostly make sure
4778 * the tag content is correct and copy forward any further other tag
4779 * numbers.
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004780 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004781static void
4782QCBORDecode_Private_ProcessEpochDays(QCBORDecodeContext *pMe,
4783 QCBORItem *pItem,
4784 uint8_t uTagRequirement,
4785 int64_t *pnDays)
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004786{
4787 if(pMe->uLastError != QCBOR_SUCCESS) {
4788 /* Already in error state, do nothing */
4789 return;
4790 }
4791
4792 QCBORError uErr;
4793
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004794 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004795 {
4796 uTagRequirement,
4797 {QCBOR_TYPE_DAYS_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4798 {QCBOR_TYPE_INT64, QCBOR_TYPE_UINT64, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4799 };
4800
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004801 uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004802 if(uErr != QCBOR_SUCCESS) {
4803 goto Done;
4804 }
4805
4806 if(pItem->uDataType != QCBOR_TYPE_DAYS_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004807 uErr = QCBOR_Private_DecodeDaysEpoch(pItem);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004808 if(uErr != QCBOR_SUCCESS) {
4809 goto Done;
4810 }
4811 }
4812
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004813 *pnDays = pItem->val.epochDays;
4814
4815Done:
4816 pMe->uLastError = (uint8_t)uErr;
4817}
4818
4819
4820/*
4821 * Public function, see header qcbor/qcbor_decode.h
4822 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004823void
4824QCBORDecode_GetEpochDays(QCBORDecodeContext *pMe,
4825 uint8_t uTagRequirement,
4826 int64_t *pnDays)
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004827{
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004828 QCBORItem Item;
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07004829 QCBORDecode_VGetNext(pMe, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004830 QCBORDecode_Private_ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004831}
4832
4833
4834/*
4835 * Public function, see header qcbor/qcbor_decode.h
4836 */
4837void
4838QCBORDecode_GetEpochDaysInMapN(QCBORDecodeContext *pMe,
4839 int64_t nLabel,
4840 uint8_t uTagRequirement,
4841 int64_t *pnDays)
4842{
4843 QCBORItem Item;
4844 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004845 QCBORDecode_Private_ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004846}
4847
4848
4849/*
4850 * Public function, see header qcbor/qcbor_decode.h
4851 */
4852void
4853QCBORDecode_GetEpochDaysInMapSZ(QCBORDecodeContext *pMe,
4854 const char *szLabel,
4855 uint8_t uTagRequirement,
4856 int64_t *pnDays)
4857{
4858 QCBORItem Item;
4859 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004860 QCBORDecode_Private_ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004861}
4862
4863
4864
Laurence Lundblade37286c02022-09-03 10:05:02 -07004865/*
4866 * @brief Get a string that matches the type/tag specification.
4867 */
4868void
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004869QCBORDecode_Private_GetTaggedString(QCBORDecodeContext *pMe,
4870 const QCBOR_Private_TagSpec TagSpec,
4871 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004872{
Laurence Lundbladec4537442020-04-14 18:53:22 -07004873 QCBORItem Item;
4874
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07004875 QCBORDecode_VGetNext(pMe, &Item);
4876 if(pMe->uLastError) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004877 return;
4878 }
4879
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004880 pMe->uLastError = (uint8_t)QCBOR_Private_CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004881
4882 if(pMe->uLastError == QCBOR_SUCCESS) {
4883 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07004884 } else {
4885 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004886 }
4887}
4888
Laurence Lundbladec4537442020-04-14 18:53:22 -07004889
4890
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004891
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004892/**
4893 * @brief Common processing for a big number tag.
4894 *
4895 * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX.
4896 * @param[in] pItem The item with the date.
4897 * @param[out] pValue The returned big number
4898 * @param[out] pbIsNegative The returned sign of the big number.
4899 *
4900 * Common processing for the big number tag. Mostly make sure
4901 * the tag content is correct and copy forward any further other tag
4902 * numbers.
4903 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07004904static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004905QCBOR_Private_ProcessBigNum(const uint8_t uTagRequirement,
4906 const QCBORItem *pItem,
4907 UsefulBufC *pValue,
4908 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004909{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004910 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004911 {
4912 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004913 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4914 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004915 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004916
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004917 QCBORError uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004918 if(uErr != QCBOR_SUCCESS) {
4919 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004920 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004921
4922 *pValue = pItem->val.string;
4923
4924 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
4925 *pbIsNegative = false;
4926 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
4927 *pbIsNegative = true;
4928 }
4929
4930 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004931}
4932
4933
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004934/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004935 * Public function, see header qcbor/qcbor_spiffy_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004936 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004937void
4938QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
4939 const uint8_t uTagRequirement,
4940 UsefulBufC *pValue,
4941 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004942{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004943 QCBORItem Item;
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07004944 QCBORDecode_VGetNext(pMe, &Item);
4945 if(pMe->uLastError) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004946 return;
4947 }
4948
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004949 pMe->uLastError = (uint8_t)QCBOR_Private_ProcessBigNum(uTagRequirement,
4950 &Item,
4951 pValue,
4952 pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004953}
4954
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004955
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004956/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004957 * Public function, see header qcbor/qcbor_spiffy_decode.h
4958 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004959void
4960QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
4961 const int64_t nLabel,
4962 const uint8_t uTagRequirement,
4963 UsefulBufC *pValue,
4964 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004965{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004966 QCBORItem Item;
4967 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004968 if(pMe->uLastError != QCBOR_SUCCESS) {
4969 return;
4970 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004971
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004972 pMe->uLastError = (uint8_t)QCBOR_Private_ProcessBigNum(uTagRequirement,
4973 &Item,
4974 pValue,
4975 pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004976}
4977
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004978
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004979/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004980 * Public function, see header qcbor/qcbor_spiffy_decode.h
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004981 */
4982void
4983QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
4984 const char *szLabel,
4985 const uint8_t uTagRequirement,
4986 UsefulBufC *pValue,
4987 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004988{
4989 QCBORItem Item;
4990 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004991 if(pMe->uLastError != QCBOR_SUCCESS) {
4992 return;
4993 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004994
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004995 pMe->uLastError = (uint8_t)QCBOR_Private_ProcessBigNum(uTagRequirement,
4996 &Item,
4997 pValue,
4998 pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004999}
5000
5001
5002
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005003/**
5004 * @brief Common processing for MIME tag (semi-private).
5005 *
5006 * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX.
5007 * @param[in] pItem The item with the date.
5008 * @param[out] pMessage The returned MIME message.
5009 * @param[out] pbIsTag257 If true, binary MIME, if not, text MIME.
5010 *
5011 * Common processing for the MIME tag. Mostly make sure the tag
5012 * content is correct and copy forward any further other tag
5013 * numbers. See QCBORDecode_GetMIMEMessage().
5014 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07005015QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005016QCBORDecode_Private_GetMIME(const uint8_t uTagRequirement,
Laurence Lundblade37286c02022-09-03 10:05:02 -07005017 const QCBORItem *pItem,
5018 UsefulBufC *pMessage,
5019 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005020{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005021 const QCBOR_Private_TagSpec TagSpecText =
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07005022 {
5023 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005024 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
5025 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07005026 };
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005027 const QCBOR_Private_TagSpec TagSpecBinary =
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07005028 {
5029 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005030 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
5031 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07005032 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005033
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005034 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07005035
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005036 if(QCBOR_Private_CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005037 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07005038 if(pbIsTag257 != NULL) {
5039 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005040 }
5041 uReturn = QCBOR_SUCCESS;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005042 } else if(QCBOR_Private_CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005043 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07005044 if(pbIsTag257 != NULL) {
5045 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005046 }
5047 uReturn = QCBOR_SUCCESS;
5048
5049 } else {
5050 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
5051 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07005052
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005053 return uReturn;
5054}
5055
Laurence Lundblade93d89472020-10-03 22:30:50 -07005056// Improvement: add methods for wrapped CBOR, a simple alternate
5057// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07005058
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005059
5060
5061
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005062#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07005063
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005064/**
5065 * @brief Prototype for conversion of exponent and mantissa to unsigned integer.
5066 *
5067 * @param[in] uMantissa The mantissa.
5068 * @param[in] nExponent The exponent.
5069 * @param[out] puResult The resulting integer.
5070 *
5071 * Concrete implementations of this are for exponent base 10 and 2 supporting
5072 * decimal fractions and big floats.
5073 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005074typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005075
5076
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005077/**
5078 * @brief Base 10 exponentiate a mantissa and exponent into an unsigned 64-bit integer.
5079 *
5080 * @param[in] uMantissa The unsigned integer mantissa.
5081 * @param[in] nExponent The signed integer exponent.
5082 * @param[out] puResult Place to return the unsigned integer result.
5083 *
5084 * This computes: mantissa * 10 ^^ exponent as for a decimal fraction. The output is a 64-bit
5085 * unsigned integer.
5086 *
5087 * There are many inputs for which the result will not fit in the
Laurence Lundblade88ba5662024-11-03 02:10:24 -08005088 * 64-bit integer and @ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005089 * be returned.
5090 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07005091static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005092QCBOR_Private_Exponentitate10(const uint64_t uMantissa,
5093 int64_t nExponent,
5094 uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07005095{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005096 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005097
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005098 if(uResult != 0) {
5099 /* This loop will run a maximum of 19 times because
5100 * UINT64_MAX < 10 ^^ 19. More than that will cause
5101 * exit with the overflow error
5102 */
5103 for(; nExponent > 0; nExponent--) {
5104 if(uResult > UINT64_MAX / 10) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005105 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005106 }
5107 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005108 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005109
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005110 for(; nExponent < 0; nExponent++) {
5111 uResult = uResult / 10;
5112 if(uResult == 0) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005113 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005114 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005115 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005116 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005117 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07005118
5119 *puResult = uResult;
5120
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005121 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005122}
5123
5124
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005125/**
5126 * @brief Base 2 exponentiate a mantissa and exponent into an unsigned 64-bit integer.
5127 *
5128 * @param[in] uMantissa The unsigned integer mantissa.
5129 * @param[in] nExponent The signed integer exponent.
5130 * @param[out] puResult Place to return the unsigned integer result.
5131 *
5132 * This computes: mantissa * 2 ^^ exponent as for a big float. The
5133 * output is a 64-bit unsigned integer.
5134 *
5135 * There are many inputs for which the result will not fit in the
Laurence Lundblade88ba5662024-11-03 02:10:24 -08005136 * 64-bit integer and @ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005137 * be returned.
5138 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07005139static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005140QCBOR_Private_Exponentitate2(const uint64_t uMantissa,
5141 int64_t nExponent,
5142 uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005143{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005144 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005145
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005146 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005147
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005148 /* This loop will run a maximum of 64 times because INT64_MAX <
5149 * 2^31. More than that will cause exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07005150 */
5151 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005152 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005153 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005154 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005155 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005156 nExponent--;
5157 }
5158
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005159 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005160 if(uResult == 0) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005161 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005162 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005163 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005164 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005165 }
5166
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005167 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005168
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005169 return QCBOR_SUCCESS;
5170}
5171
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005172
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005173/**
5174 * @brief Exponentiate a signed mantissa and signed exponent to produce a signed result.
5175 *
5176 * @param[in] nMantissa Signed integer mantissa.
5177 * @param[in] nExponent Signed integer exponent.
5178 * @param[out] pnResult Place to put the signed integer result.
5179 * @param[in] pfExp Exponentiation function.
5180 *
5181 * @returns Error code
5182 *
Laurence Lundblade88ba5662024-11-03 02:10:24 -08005183 * @c pfExp performs exponentiation on and unsigned mantissa and
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005184 * produces an unsigned result. This converts the mantissa from signed
5185 * and converts the result to signed. The exponentiation function is
5186 * either for base 2 or base 10 (and could be other if needed).
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005187 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005188static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005189QCBOR_Private_ExponentiateNN(const int64_t nMantissa,
5190 const int64_t nExponent,
5191 int64_t *pnResult,
5192 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005193{
5194 uint64_t uResult;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005195 uint64_t uMantissa;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005196
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005197 /* Take the absolute value and put it into an unsigned. */
5198 if(nMantissa >= 0) {
5199 /* Positive case is straightforward */
5200 uMantissa = (uint64_t)nMantissa;
5201 } else if(nMantissa != INT64_MIN) {
5202 /* The common negative case. See next. */
5203 uMantissa = (uint64_t)-nMantissa;
5204 } else {
5205 /* int64_t and uint64_t are always two's complement per the
5206 * C standard (and since QCBOR uses these it only works with
5207 * two's complement, which is pretty much universal these
5208 * days). The range of a negative two's complement integer is
5209 * one more that than a positive, so the simple code above might
5210 * not work all the time because you can't simply negate the
5211 * value INT64_MIN because it can't be represented in an
5212 * int64_t. -INT64_MIN can however be represented in a
5213 * uint64_t. Some compilers seem to recognize this case for the
5214 * above code and put the correct value in uMantissa, however
5215 * they are not required to do this by the C standard. This next
5216 * line does however work for all compilers.
5217 *
5218 * This does assume two's complement where -INT64_MIN ==
5219 * INT64_MAX + 1 (which wouldn't be true for one's complement or
5220 * sign and magnitude (but we know we're using two's complement
5221 * because int64_t requires it)).
5222 *
5223 * See these, particularly the detailed commentary:
5224 * https://stackoverflow.com/questions/54915742/does-c99-mandate-a-int64-t-type-be-available-always
5225 * https://stackoverflow.com/questions/37301078/is-negating-int-min-undefined-behaviour
5226 */
5227 uMantissa = (uint64_t)INT64_MAX+1;
5228 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005229
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005230 /* Call the exponentiator passed for either base 2 or base 10.
5231 * Here is where most of the overflow errors are caught. */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005232 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
5233 if(uReturn) {
5234 return uReturn;
5235 }
5236
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005237 /* Convert back to the sign of the original mantissa */
5238 if(nMantissa >= 0) {
5239 if(uResult > INT64_MAX) {
5240 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5241 }
5242 *pnResult = (int64_t)uResult;
5243 } else {
5244 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
5245 * of INT64_MIN. This assumes two's compliment representation
5246 * where INT64_MIN is one increment farther from 0 than
5247 * INT64_MAX. Trying to write -INT64_MIN doesn't work to get
5248 * this because the compiler makes it an int64_t which can't
5249 * represent -INT64_MIN. Also see above.
5250 */
5251 if(uResult > (uint64_t)INT64_MAX+1) {
5252 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5253 }
5254 *pnResult = -(int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005255 }
5256
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005257 return QCBOR_SUCCESS;
5258}
5259
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005260
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005261/**
5262 * @brief Exponentiate an unsigned mantissa and signed exponent to produce an unsigned result.
5263 *
5264 * @param[in] nMantissa Signed integer mantissa.
5265 * @param[in] nExponent Signed integer exponent.
5266 * @param[out] puResult Place to put the signed integer result.
5267 * @param[in] pfExp Exponentiation function.
5268 *
5269 * @returns Error code
5270 *
Laurence Lundblade88ba5662024-11-03 02:10:24 -08005271 * @c pfExp performs exponentiation on and unsigned mantissa and
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005272 * produces an unsigned result. This errors out if the mantissa
5273 * is negative because the output is unsigned.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005274 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005275static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005276QCBOR_Private_ExponentitateNU(const int64_t nMantissa,
5277 const int64_t nExponent,
5278 uint64_t *puResult,
5279 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005280{
5281 if(nMantissa < 0) {
5282 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5283 }
5284
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005285 /* Cast to unsigned is OK because of check for negative.
5286 * Cast to unsigned is OK because UINT64_MAX > INT64_MAX.
5287 * Exponentiation is straight forward
5288 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005289 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
5290}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005291
5292
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005293/**
5294 * @brief Exponentiate an usnigned mantissa and unsigned exponent to produce an unsigned result.
5295 *
5296 * @param[in] uMantissa Unsigned integer mantissa.
5297 * @param[in] nExponent Unsigned integer exponent.
5298 * @param[out] puResult Place to put the unsigned integer result.
5299 * @param[in] pfExp Exponentiation function.
5300 *
5301 * @returns Error code
5302 *
Laurence Lundblade88ba5662024-11-03 02:10:24 -08005303 * @c pfExp performs exponentiation on and unsigned mantissa and
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005304 * produces an unsigned result so this is just a wrapper that does
5305 * nothing (and is likely inlined).
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005306 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005307static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005308QCBOR_Private_ExponentitateUU(const uint64_t uMantissa,
5309 const int64_t nExponent,
5310 uint64_t *puResult,
5311 fExponentiator pfExp)
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005312{
5313 return (*pfExp)(uMantissa, nExponent, puResult);
5314}
5315
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005316#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005317
5318
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005319
5320
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005321/**
5322 * @brief Convert a CBOR big number to a uint64_t.
5323 *
5324 * @param[in] BigNum Bytes of the big number to convert.
5325 * @param[in] uMax Maximum value allowed for the result.
5326 * @param[out] pResult Place to put the unsigned integer result.
5327 *
5328 * @returns Error code
5329 *
5330 * Many values will overflow because a big num can represent a much
5331 * larger range than uint64_t.
5332 */
5333static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005334QCBOR_Private_ConvertBigNumToUnsigned(const UsefulBufC BigNum,
5335 const uint64_t uMax,
5336 uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005337{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005338 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005339
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005340 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005341 const uint8_t *pByte = BigNum.ptr;
5342 size_t uLen = BigNum.len;
5343 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07005344 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07005345 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005346 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07005347 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005348 }
5349
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005350 *pResult = uResult;
5351 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005352}
5353
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005354
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005355/**
5356 * @brief Convert a CBOR postive big number to a uint64_t.
5357 *
5358 * @param[in] BigNum Bytes of the big number to convert.
5359 * @param[out] pResult Place to put the unsigned integer result.
5360 *
5361 * @returns Error code
5362 *
5363 * Many values will overflow because a big num can represent a much
5364 * larger range than uint64_t.
5365 */
5366static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005367QCBOR_Private_ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum,
5368 uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005369{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005370 return QCBOR_Private_ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005371}
5372
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005373
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005374/**
5375 * @brief Convert a CBOR positive big number to an int64_t.
5376 *
5377 * @param[in] BigNum Bytes of the big number to convert.
5378 * @param[out] pResult Place to put the signed integer result.
5379 *
5380 * @returns Error code
5381 *
5382 * Many values will overflow because a big num can represent a much
5383 * larger range than int64_t.
5384 */
5385static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005386QCBOR_Private_ConvertPositiveBigNumToSigned(const UsefulBufC BigNum,
5387 int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005388{
5389 uint64_t uResult;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005390 QCBORError uError = QCBOR_Private_ConvertBigNumToUnsigned(BigNum,
5391 INT64_MAX,
5392 &uResult);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005393 if(uError) {
5394 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005395 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005396 /* Cast is safe because ConvertBigNumToUnsigned limits to INT64_MAX */
Laurence Lundbladee6430642020-03-14 21:15:44 -07005397 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005398 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005399}
5400
5401
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005402/**
5403 * @brief Convert a CBOR negative big number to an int64_t.
5404 *
5405 * @param[in] BigNum Bytes of the big number to convert.
5406 * @param[out] pnResult Place to put the signed integer result.
5407 *
5408 * @returns Error code
5409 *
5410 * Many values will overflow because a big num can represent a much
5411 * larger range than int64_t.
5412 */
5413static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005414QCBOR_Private_ConvertNegativeBigNumToSigned(const UsefulBufC BigNum,
5415 int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005416{
5417 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005418 /* The negative integer furthest from zero for a C int64_t is
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005419 * INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
5420 * negative number in CBOR is computed as -n - 1 where n is the
5421 * encoded integer, where n is what is in the variable BigNum. When
5422 * converting BigNum to a uint64_t, the maximum value is thus
5423 * INT64_MAX, so that when it -n - 1 is applied to it the result
5424 * will never be further from 0 than INT64_MIN.
5425 *
5426 * -n - 1 <= INT64_MIN.
5427 * -n - 1 <= -INT64_MAX - 1
5428 * n <= INT64_MAX.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005429 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005430 QCBORError uError = QCBOR_Private_ConvertBigNumToUnsigned(BigNum,
5431 INT64_MAX,
5432 &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005433 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005434 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005435 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005436
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005437 /* Now apply -n - 1. The cast is safe because
5438 * ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
5439 * is the largest positive integer that an int64_t can
5440 * represent. */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005441 *pnResult = -(int64_t)uResult - 1;
5442
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005443 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005444}
5445
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005446
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005447
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005448
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005449/**
5450 * @brief Convert integers and floats to an int64_t.
5451 *
5452 * @param[in] pItem The item to convert.
5453 * @param[in] uConvertTypes Bit mask list of conversion options.
5454 * @param[out] pnValue The resulting converted value.
5455 *
5456 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
5457 * in uConvertTypes.
5458 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
5459 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
5460 * or too small.
Laurence Lundblade818c9052025-06-27 11:13:04 -07005461 * @retval QCBOR_ERR_FLOAT_EXCEPTION Encountered NaN or infinity or such.
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005462 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07005463static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005464QCBOR_Private_ConvertInt64(const QCBORItem *pItem,
5465 const uint32_t uConvertTypes,
5466 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005467{
5468 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005469#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade818c9052025-06-27 11:13:04 -07005470 case QCBOR_TYPE_FLOAT:
5471 if(!(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT)) {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005472 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005473 }
Laurence Lundblade818c9052025-06-27 11:13:04 -07005474 if(isnan(pItem->val.fnum)) {
5475 /* In some environments, llround() will succeed on NaN
5476 * when it really shouldn't, so catch the error here. */
5477 return QCBOR_ERR_FLOAT_EXCEPTION;
5478 }
5479 if(pItem->val.fnum == INFINITY || pItem->val.fnum == -INFINITY) {
5480 return QCBOR_ERR_FLOAT_EXCEPTION;
5481 }
5482 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
5483 * http://www.cplusplus.com/reference/cmath/llround/
5484 */
5485 /* Not interested in FE_INEXACT */
5486 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
5487 *pnValue = lroundf(pItem->val.fnum);
5488 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
5489 /* llround() shouldn't result in divide by zero, but catch
5490 * it here in case it unexpectedly does. Don't try to
5491 * distinguish between the various exceptions because it seems
5492 * they vary by CPU, compiler and OS.
5493 */
5494 return QCBOR_ERR_FLOAT_EXCEPTION;
5495 }
5496 break;
5497
5498 case QCBOR_TYPE_DOUBLE:
5499 if(!(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT)) {
5500 return QCBOR_ERR_UNEXPECTED_TYPE;
5501 }
5502 if(isnan(pItem->val.dfnum)) {
5503 /* In some environments, llround() will succeed on NaN
5504 * when it really shouldn't, so catch the error here. */
5505 return QCBOR_ERR_FLOAT_EXCEPTION;
5506 }
5507 if(pItem->val.dfnum == INFINITY || pItem->val.dfnum == -INFINITY) {
5508 return QCBOR_ERR_FLOAT_EXCEPTION;
5509 }
5510 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
5511 * http://www.cplusplus.com/reference/cmath/llround/
5512 */
5513 /* Not interested in FE_INEXACT */
5514 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
5515 *pnValue = llround(pItem->val.dfnum);
5516 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
5517 /* llround() shouldn't result in divide by zero, but catch
5518 * it here in case it unexpectedly does. Don't try to
5519 * distinguish between the various exceptions because it seems
5520 * they vary by CPU, compiler and OS.
5521 */
5522 return QCBOR_ERR_FLOAT_EXCEPTION;
5523 }
5524 break;
5525
5526#else /* ! QCBOR_DISABLE_FLOAT_HW_USE */
5527 case QCBOR_TYPE_FLOAT:
5528 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005529 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundblade818c9052025-06-27 11:13:04 -07005530#endif /* ! QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005531 break;
5532
5533 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005534 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005535 *pnValue = pItem->val.int64;
5536 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005537 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005538 }
5539 break;
5540
5541 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005542 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005543 if(pItem->val.uint64 < INT64_MAX) {
5544 *pnValue = pItem->val.int64;
5545 } else {
5546 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5547 }
5548 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005549 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005550 }
5551 break;
5552
5553 default:
5554 return QCBOR_ERR_UNEXPECTED_TYPE;
5555 }
5556 return QCBOR_SUCCESS;
5557}
5558
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005559
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005560/**
5561 * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
5562 *
5563 * @param[in] pMe The decode context.
5564 * @param[in] uConvertTypes Bit mask list of conversion options.
5565 * @param[out] pnValue Result of the conversion.
5566 * @param[in,out] pItem Temporary space to store Item, returned item.
5567 *
5568 * See QCBORDecode_GetInt64Convert().
5569 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005570void
5571QCBORDecode_Private_GetInt64Convert(QCBORDecodeContext *pMe,
5572 uint32_t uConvertTypes,
5573 int64_t *pnValue,
5574 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005575{
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07005576 QCBORDecode_VGetNext(pMe, pItem);
5577 if(pMe->uLastError) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07005578 return;
5579 }
5580
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005581 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005582 uConvertTypes,
5583 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005584}
5585
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005586/**
5587 * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
5588 *
5589 * @param[in] pMe The decode context.
5590 * @param[in] nLabel Label to find in map.
5591 * @param[in] uConvertTypes Bit mask list of conversion options.
5592 * @param[out] pnValue Result of the conversion.
5593 * @param[in,out] pItem Temporary space to store Item, returned item.
5594 *
5595 * See QCBORDecode_GetInt64ConvertInMapN().
5596 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005597void
5598QCBORDecode_Private_GetInt64ConvertInMapN(QCBORDecodeContext *pMe,
5599 int64_t nLabel,
5600 uint32_t uConvertTypes,
5601 int64_t *pnValue,
5602 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005603{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005604 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005605 if(pMe->uLastError != QCBOR_SUCCESS) {
5606 return;
5607 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005608
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005609 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
5610 uConvertTypes,
5611 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005612}
5613
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005614/**
5615 * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
5616 *
5617 * @param[in] pMe The decode context.
5618 * @param[in] szLabel Label to find in map.
5619 * @param[in] uConvertTypes Bit mask list of conversion options.
5620 * @param[out] pnValue Result of the conversion.
5621 * @param[in,out] pItem Temporary space to store Item, returned item.
5622 *
5623 * See QCBORDecode_GetInt64ConvertInMapSZ().
5624 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005625void
5626QCBORDecode_Private_GetInt64ConvertInMapSZ(QCBORDecodeContext *pMe,
5627 const char * szLabel,
5628 uint32_t uConvertTypes,
5629 int64_t *pnValue,
5630 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005631{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005632 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005633 if(pMe->uLastError != QCBOR_SUCCESS) {
5634 return;
5635 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005636
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005637 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
5638 uConvertTypes,
5639 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005640}
5641
5642
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005643/**
5644 * @brief Convert many number types to an int64_t.
5645 *
5646 * @param[in] pItem The item to convert.
5647 * @param[in] uConvertTypes Bit mask list of conversion options.
5648 * @param[out] pnValue The resulting converted value.
5649 *
5650 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
5651 * in uConvertTypes.
5652 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
5653 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
5654 * or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005655 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07005656static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005657QCBOR_Private_Int64ConvertAll(const QCBORItem *pItem,
5658 const uint32_t uConvertTypes,
5659 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005660{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005661 switch(pItem->uDataType) {
5662
5663 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005664 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005665 return QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005666 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005667 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005668 }
5669 break;
5670
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005671 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005672 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005673 return QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005674 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005675 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005676 }
5677 break;
5678
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005679#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005680 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005681 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005682 return QCBOR_Private_ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005683 pItem->val.expAndMantissa.nExponent,
5684 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005685 &QCBOR_Private_Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005686 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005687 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005688 }
5689 break;
5690
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005691 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005692 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005693 return QCBOR_Private_ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005694 pItem->val.expAndMantissa.nExponent,
5695 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005696 QCBOR_Private_Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005697 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005698 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005699 }
5700 break;
5701
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005702 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005703 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005704 int64_t nMantissa;
5705 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005706 uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005707 if(uErr) {
5708 return uErr;
5709 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005710 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005711 pItem->val.expAndMantissa.nExponent,
5712 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005713 QCBOR_Private_Exponentitate10);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005714 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005715 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005716 }
5717 break;
5718
5719 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005720 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005721 int64_t nMantissa;
5722 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005723 uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005724 if(uErr) {
5725 return uErr;
5726 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005727 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005728 pItem->val.expAndMantissa.nExponent,
5729 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005730 QCBOR_Private_Exponentitate10);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005731 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005732 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005733 }
5734 break;
5735
5736 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005737 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005738 int64_t nMantissa;
5739 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005740 uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005741 if(uErr) {
5742 return uErr;
5743 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005744 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005745 pItem->val.expAndMantissa.nExponent,
5746 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005747 QCBOR_Private_Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005748 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005749 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005750 }
5751 break;
5752
5753 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005754 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005755 int64_t nMantissa;
5756 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005757 uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005758 if(uErr) {
5759 return uErr;
5760 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005761 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005762 pItem->val.expAndMantissa.nExponent,
5763 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005764 QCBOR_Private_Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005765 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005766 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005767 }
5768 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005769#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005770
Laurence Lundbladee6430642020-03-14 21:15:44 -07005771
Laurence Lundbladec4537442020-04-14 18:53:22 -07005772 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005773 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005774}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005775
5776
Laurence Lundbladec4537442020-04-14 18:53:22 -07005777/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005778 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005779 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005780void
5781QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe,
5782 const uint32_t uConvertTypes,
5783 int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07005784{
5785 QCBORItem Item;
5786
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005787 QCBORDecode_Private_GetInt64Convert(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07005788
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005789 if(pMe->uLastError == QCBOR_SUCCESS) {
5790 // The above conversion succeeded
5791 return;
5792 }
5793
Laurence Lundbladef6c86662020-05-12 02:08:00 -07005794 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005795 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07005796 return;
5797 }
5798
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005799 pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
5800 uConvertTypes,
5801 pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005802}
5803
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005804
5805/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005806 * Public function, see header qcbor/qcbor_decode.h file
5807 */
5808void
5809QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
5810 const int64_t nLabel,
5811 const uint32_t uConvertTypes,
5812 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005813{
5814 QCBORItem Item;
5815
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005816 QCBORDecode_Private_GetInt64ConvertInMapN(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07005817 nLabel,
5818 uConvertTypes,
5819 pnValue,
5820 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005821
5822 if(pMe->uLastError == QCBOR_SUCCESS) {
5823 // The above conversion succeeded
5824 return;
5825 }
5826
5827 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5828 // The above conversion failed in a way that code below can't correct
5829 return;
5830 }
5831
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005832 pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
5833 uConvertTypes,
5834 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005835}
5836
5837
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005838/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005839 * Public function, see header qcbor/qcbor_decode.h file
5840 */
5841void
5842QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
5843 const char *szLabel,
5844 const uint32_t uConvertTypes,
5845 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005846{
5847 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005848 QCBORDecode_Private_GetInt64ConvertInMapSZ(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07005849 szLabel,
5850 uConvertTypes,
5851 pnValue,
5852 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005853
5854 if(pMe->uLastError == QCBOR_SUCCESS) {
5855 // The above conversion succeeded
5856 return;
5857 }
5858
5859 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5860 // The above conversion failed in a way that code below can't correct
5861 return;
5862 }
5863
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005864 pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
5865 uConvertTypes,
5866 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005867}
5868
5869
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005870/**
5871 * @brief Convert many number types to an uint64_t.
5872 *
5873 * @param[in] pItem The item to convert.
5874 * @param[in] uConvertTypes Bit mask list of conversion options.
5875 * @param[out] puValue The resulting converted value.
5876 *
5877 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
5878 * in uConvertTypes.
5879 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
5880 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
5881 * or too small.
5882 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005883static QCBORError
5884QCBOR_Private_ConvertUInt64(const QCBORItem *pItem,
5885 const uint32_t uConvertTypes,
5886 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005887{
5888 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005889 case QCBOR_TYPE_DOUBLE:
5890 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005891#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005892 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005893 // Can't use llround here because it will not convert values
5894 // greater than INT64_MAX and less than UINT64_MAX that
5895 // need to be converted so it is more complicated.
5896 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
5897 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
5898 if(isnan(pItem->val.dfnum)) {
5899 return QCBOR_ERR_FLOAT_EXCEPTION;
5900 } else if(pItem->val.dfnum < 0) {
5901 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5902 } else {
5903 double dRounded = round(pItem->val.dfnum);
5904 // See discussion in DecodeDateEpoch() for
5905 // explanation of - 0x7ff
5906 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
5907 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5908 }
5909 *puValue = (uint64_t)dRounded;
5910 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005911 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005912 if(isnan(pItem->val.fnum)) {
5913 return QCBOR_ERR_FLOAT_EXCEPTION;
5914 } else if(pItem->val.fnum < 0) {
5915 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5916 } else {
5917 float fRounded = roundf(pItem->val.fnum);
5918 // See discussion in DecodeDateEpoch() for
5919 // explanation of - 0x7ff
5920 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
5921 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5922 }
5923 *puValue = (uint64_t)fRounded;
5924 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005925 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005926 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
5927 // round() and roundf() shouldn't result in exceptions here, but
5928 // catch them to be robust and thorough. Don't try to
5929 // distinguish between the various exceptions because it seems
5930 // they vary by CPU, compiler and OS.
5931 return QCBOR_ERR_FLOAT_EXCEPTION;
5932 }
5933
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005934 } else {
5935 return QCBOR_ERR_UNEXPECTED_TYPE;
5936 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005937#else
5938 return QCBOR_ERR_HW_FLOAT_DISABLED;
5939#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005940 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005941
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005942 case QCBOR_TYPE_INT64:
5943 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
5944 if(pItem->val.int64 >= 0) {
5945 *puValue = (uint64_t)pItem->val.int64;
5946 } else {
5947 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5948 }
5949 } else {
5950 return QCBOR_ERR_UNEXPECTED_TYPE;
5951 }
5952 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005953
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005954 case QCBOR_TYPE_UINT64:
5955 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
5956 *puValue = pItem->val.uint64;
5957 } else {
5958 return QCBOR_ERR_UNEXPECTED_TYPE;
5959 }
5960 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005961
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005962 default:
5963 return QCBOR_ERR_UNEXPECTED_TYPE;
5964 }
5965
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005966 return QCBOR_SUCCESS;
5967}
Laurence Lundbladec4537442020-04-14 18:53:22 -07005968
5969
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005970/**
5971 * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
5972 *
5973 * @param[in] pMe The decode context.
5974 * @param[in] uConvertTypes Bit mask list of conversion options.
5975 * @param[out] puValue Result of the conversion.
5976 * @param[in,out] pItem Temporary space to store Item, returned item.
5977 *
5978 * See QCBORDecode_GetUInt64Convert().
5979 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005980void
5981QCBORDecode_Private_GetUInt64Convert(QCBORDecodeContext *pMe,
5982 const uint32_t uConvertTypes,
5983 uint64_t *puValue,
5984 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07005985{
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07005986 QCBORDecode_VGetNext(pMe, pItem);
5987 if(pMe->uLastError) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005988 return;
5989 }
5990
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07005991 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005992 uConvertTypes,
5993 puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07005994}
5995
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005996
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005997/**
5998 * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
5999 *
6000 * @param[in] pMe The decode context.
6001 * @param[in] nLabel Label to find in map.
6002 * @param[in] uConvertTypes Bit mask list of conversion options.
6003 * @param[out] puValue Result of the conversion.
6004 * @param[in,out] pItem Temporary space to store Item, returned item.
6005 *
6006 * See QCBORDecode_GetUInt64ConvertInMapN().
6007 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006008void
6009QCBORDecode_Private_GetUInt64ConvertInMapN(QCBORDecodeContext *pMe,
6010 const int64_t nLabel,
6011 const uint32_t uConvertTypes,
6012 uint64_t *puValue,
6013 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006014{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006015 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07006016 if(pMe->uLastError != QCBOR_SUCCESS) {
6017 return;
6018 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006019
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006020 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
6021 uConvertTypes,
6022 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006023}
6024
6025
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006026/**
6027 * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
6028 *
6029 * @param[in] pMe The decode context.
6030 * @param[in] szLabel Label to find in map.
6031 * @param[in] uConvertTypes Bit mask list of conversion options.
6032 * @param[out] puValue Result of the conversion.
6033 * @param[in,out] pItem Temporary space to store Item, returned item.
6034 *
6035 * See QCBORDecode_GetUInt64ConvertInMapSZ().
6036 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006037void
6038QCBORDecode_Private_GetUInt64ConvertInMapSZ(QCBORDecodeContext *pMe,
6039 const char *szLabel,
6040 const uint32_t uConvertTypes,
6041 uint64_t *puValue,
6042 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006043{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006044 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07006045 if(pMe->uLastError != QCBOR_SUCCESS) {
6046 return;
6047 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006048
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006049 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
6050 uConvertTypes,
6051 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006052}
6053
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006054
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006055/**
6056 * @brief Convert many number types to an unt64_t.
6057 *
6058 * @param[in] pItem The item to convert.
6059 * @param[in] uConvertTypes Bit mask list of conversion options.
6060 * @param[out] puValue The resulting converted value.
6061 *
6062 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
6063 * in uConvertTypes.
6064 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
6065 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
6066 * or too small.
6067 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07006068static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006069QCBOR_Private_UInt64ConvertAll(const QCBORItem *pItem,
6070 const uint32_t uConvertTypes,
6071 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006072{
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08006073 switch(pItem->uDataType) { /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006074
6075 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006076 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006077 return QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006078 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006079 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006080 }
6081 break;
6082
6083 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006084 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006085 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
6086 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006087 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006088 }
6089 break;
6090
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006091#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006092
6093 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006094 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006095 return QCBOR_Private_ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006096 pItem->val.expAndMantissa.nExponent,
6097 puValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006098 QCBOR_Private_Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006099 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006100 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006101 }
6102 break;
6103
6104 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006105 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006106 return QCBOR_Private_ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006107 pItem->val.expAndMantissa.nExponent,
6108 puValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006109 QCBOR_Private_Exponentitate2);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006110 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006111 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006112 }
6113 break;
6114
6115 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006116 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006117 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006118 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006119 uErr = QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006120 if(uErr != QCBOR_SUCCESS) {
6121 return uErr;
6122 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006123 return QCBOR_Private_ExponentitateUU(uMantissa,
6124 pItem->val.expAndMantissa.nExponent,
6125 puValue,
6126 QCBOR_Private_Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006127 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006128 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006129 }
6130 break;
6131
6132 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006133 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006134 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
6135 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006136 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006137 }
6138 break;
6139
6140 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006141 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006142 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006143 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006144 uErr = QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum,
6145 &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006146 if(uErr != QCBOR_SUCCESS) {
6147 return uErr;
6148 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006149 return QCBOR_Private_ExponentitateUU(uMantissa,
6150 pItem->val.expAndMantissa.nExponent,
6151 puValue,
6152 QCBOR_Private_Exponentitate2);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006153 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006154 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006155 }
6156 break;
6157
6158 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006159 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006160 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
6161 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006162 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006163 }
6164 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006165#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006166 default:
6167 return QCBOR_ERR_UNEXPECTED_TYPE;
6168 }
6169}
6170
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006171
Laurence Lundblade4e2da002020-06-13 23:08:31 -07006172/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006173 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07006174 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006175void
6176QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe,
6177 const uint32_t uConvertTypes,
6178 uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07006179{
6180 QCBORItem Item;
6181
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006182 QCBORDecode_Private_GetUInt64Convert(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07006183
Laurence Lundbladef6c86662020-05-12 02:08:00 -07006184 if(pMe->uLastError == QCBOR_SUCCESS) {
6185 // The above conversion succeeded
6186 return;
6187 }
6188
6189 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6190 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07006191 return;
6192 }
6193
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006194 pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
6195 uConvertTypes,
6196 puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07006197}
6198
Laurence Lundbladec4537442020-04-14 18:53:22 -07006199
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006200/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006201 * Public function, see header qcbor/qcbor_decode.h file
6202 */
6203void
6204QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
6205 const int64_t nLabel,
6206 const uint32_t uConvertTypes,
6207 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006208{
6209 QCBORItem Item;
6210
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006211 QCBORDecode_Private_GetUInt64ConvertInMapN(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07006212 nLabel,
6213 uConvertTypes,
6214 puValue,
6215 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006216
6217 if(pMe->uLastError == QCBOR_SUCCESS) {
6218 // The above conversion succeeded
6219 return;
6220 }
6221
6222 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6223 // The above conversion failed in a way that code below can't correct
6224 return;
6225 }
6226
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006227 pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
6228 uConvertTypes,
6229 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006230}
6231
6232
6233/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006234 * Public function, see header qcbor/qcbor_decode.h file
6235 */
6236void
6237QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
6238 const char *szLabel,
6239 const uint32_t uConvertTypes,
6240 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006241{
6242 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006243 QCBORDecode_Private_GetUInt64ConvertInMapSZ(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07006244 szLabel,
6245 uConvertTypes,
6246 puValue,
6247 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006248
6249 if(pMe->uLastError == QCBOR_SUCCESS) {
6250 // The above conversion succeeded
6251 return;
6252 }
6253
6254 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6255 // The above conversion failed in a way that code below can't correct
6256 return;
6257 }
6258
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006259 pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
6260 uConvertTypes,
6261 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006262}
6263
6264
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07006265
6266
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02006267#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006268/**
6269 * @brief Basic conversions to a double.
6270 *
6271 * @param[in] pItem The item to convert
6272 * @param[in] uConvertTypes Bit flags indicating source types for conversion
6273 * @param[out] pdValue The value converted to a double
6274 *
6275 * This does the conversions that don't need much object code,
6276 * the conversions from int, uint and float to double.
6277 *
6278 * See QCBOR_Private_DoubleConvertAll() for the full set
6279 * of conversions.
6280 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006281static QCBORError
6282QCBOR_Private_ConvertDouble(const QCBORItem *pItem,
6283 const uint32_t uConvertTypes,
6284 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006285{
6286 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006287 case QCBOR_TYPE_FLOAT:
6288#ifndef QCBOR_DISABLE_FLOAT_HW_USE
6289 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
6290 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07006291 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006292 *pdValue = (double)pItem->val.fnum;
6293 } else {
6294 return QCBOR_ERR_UNEXPECTED_TYPE;
6295 }
6296 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08006297#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006298 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08006299#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006300 break;
6301
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006302 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006303 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
6304 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006305 *pdValue = pItem->val.dfnum;
6306 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006307 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006308 }
6309 }
6310 break;
6311
6312 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006313#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006314 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07006315 // A simple cast seems to do the job with no worry of exceptions.
6316 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006317 *pdValue = (double)pItem->val.int64;
6318
6319 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006320 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006321 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006322#else
6323 return QCBOR_ERR_HW_FLOAT_DISABLED;
6324#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006325 break;
6326
6327 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006328#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006329 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07006330 // A simple cast seems to do the job with no worry of exceptions.
6331 // There will be precision loss for some values.
6332 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006333 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006334 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006335 }
6336 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006337#else
6338 return QCBOR_ERR_HW_FLOAT_DISABLED;
6339#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006340
6341 default:
6342 return QCBOR_ERR_UNEXPECTED_TYPE;
6343 }
6344
6345 return QCBOR_SUCCESS;
6346}
6347
6348
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006349/**
6350 * @brief Almost-public method to decode a number and convert to double (semi-private).
6351 *
6352 * @param[in] pMe The decode context.
6353 * @param[in] uConvertTypes Bit mask list of conversion options
6354 * @param[out] pdValue The output of the conversion.
6355 * @param[in,out] pItem Temporary space to store Item, returned item.
6356 *
6357 * See QCBORDecode_GetDoubleConvert().
6358 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006359void
6360QCBORDecode_Private_GetDoubleConvert(QCBORDecodeContext *pMe,
6361 const uint32_t uConvertTypes,
6362 double *pdValue,
6363 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07006364{
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07006365 QCBORDecode_VGetNext(pMe, pItem);
6366 if(pMe->uLastError) {
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006367 return;
6368 }
6369
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006370 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006371 uConvertTypes,
6372 pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006373}
Laurence Lundbladec4537442020-04-14 18:53:22 -07006374
Laurence Lundbladec4537442020-04-14 18:53:22 -07006375
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006376/**
6377 * @brief Almost-public method to decode a number and convert to double (semi-private).
6378 *
6379 * @param[in] pMe The decode context.
6380 * @param[in] nLabel Label to find in map.
6381 * @param[in] uConvertTypes Bit mask list of conversion options
6382 * @param[out] pdValue The output of the conversion.
6383 * @param[in,out] pItem Temporary space to store Item, returned item.
6384 *
6385 * See QCBORDecode_GetDoubleConvertInMapN().
6386 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006387void
6388QCBORDecode_Private_GetDoubleConvertInMapN(QCBORDecodeContext *pMe,
6389 const int64_t nLabel,
6390 const uint32_t uConvertTypes,
6391 double *pdValue,
6392 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006393{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006394 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07006395 if(pMe->uLastError != QCBOR_SUCCESS) {
6396 return;
6397 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006398
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006399 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
6400 uConvertTypes,
6401 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006402}
6403
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006404
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006405/**
6406 * @brief Almost-public method to decode a number and convert to double (semi-private).
6407 *
6408 * @param[in] pMe The decode context.
6409 * @param[in] szLabel Label to find in map.
6410 * @param[in] uConvertTypes Bit mask list of conversion options
6411 * @param[out] pdValue The output of the conversion.
6412 * @param[in,out] pItem Temporary space to store Item, returned item.
6413 *
6414 * See QCBORDecode_GetDoubleConvertInMapSZ().
6415 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006416void
6417QCBORDecode_Private_GetDoubleConvertInMapSZ(QCBORDecodeContext *pMe,
6418 const char *szLabel,
6419 const uint32_t uConvertTypes,
6420 double *pdValue,
6421 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006422{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006423 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07006424 if(pMe->uLastError != QCBOR_SUCCESS) {
6425 return;
6426 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006427
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006428 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
6429 uConvertTypes,
6430 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006431}
6432
6433
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006434#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006435/**
6436 * @brief Convert a big number to double-precision float.
6437 *
6438 * @param[in] BigNum The big number to convert
6439 *
6440 * @returns The double value.
6441 *
6442 * This will always succeed. It will lose precision for larger
6443 * numbers. If the big number is too large to fit (more than
6444 * 1.7976931348623157E+308) infinity will be returned. NaN is never
6445 * returned.
6446 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006447static double
6448QCBOR_Private_ConvertBigNumToDouble(const UsefulBufC BigNum)
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07006449{
6450 double dResult;
6451
6452 dResult = 0.0;
6453 const uint8_t *pByte = BigNum.ptr;
6454 size_t uLen = BigNum.len;
6455 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006456 * is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07006457 while(uLen--) {
6458 dResult = (dResult * 256.0) + (double)*pByte++;
6459 }
6460
6461 return dResult;
6462}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006463#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
6464
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07006465
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006466
6467
6468/**
6469 * @brief Convert many number types to a double.
6470 *
6471 * @param[in] pItem The item to convert.
6472 * @param[in] uConvertTypes Bit mask list of conversion options.
6473 * @param[out] pdValue The resulting converted value.
6474 *
6475 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
6476 * in uConvertTypes.
6477 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
6478 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
6479 * or too small.
6480 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07006481static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006482QCBOR_Private_DoubleConvertAll(const QCBORItem *pItem,
6483 const uint32_t uConvertTypes,
6484 double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006485{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006486#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07006487 /*
Laurence Lundblade16a207a2021-09-18 17:22:46 -07006488 * What Every Computer Scientist Should Know About Floating-Point Arithmetic
6489 * https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
6490 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006491 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07006492
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006493#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006494 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006495 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07006496 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006497 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
6498 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
6499 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006500 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006501 }
6502 break;
6503
6504 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006505 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07006506 // Underflow gives 0, overflow gives infinity
6507 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
6508 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006509 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006510 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006511 }
6512 break;
Laurence Lundblade20fba4f2024-10-30 07:52:33 -07006513#endif /* ! QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006514
6515 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006516 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006517 *pdValue = QCBOR_Private_ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006518 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006519 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006520 }
6521 break;
6522
6523 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006524 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006525 *pdValue = -1-QCBOR_Private_ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006526 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006527 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006528 }
6529 break;
6530
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006531#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006532 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006533 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006534 double dMantissa = QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006535 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
6536 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006537 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006538 }
6539 break;
6540
6541 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade20fba4f2024-10-30 07:52:33 -07006542 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
6543 /* Must subtract 1 for CBOR negative integer offset */
6544 double dMantissa = -1-QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
6545 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006546 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006547 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006548 }
6549 break;
6550
6551 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade20fba4f2024-10-30 07:52:33 -07006552 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
6553 double dMantissa = QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
6554 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006555 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006556 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006557 }
6558 break;
6559
6560 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade20fba4f2024-10-30 07:52:33 -07006561 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
6562 double dMantissa = -1-QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
6563 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006564 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006565 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006566 }
6567 break;
Laurence Lundblade20fba4f2024-10-30 07:52:33 -07006568#endif /* ! QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade410c7e02020-06-25 23:35:29 -07006569
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006570 default:
6571 return QCBOR_ERR_UNEXPECTED_TYPE;
6572 }
6573
6574 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006575
6576#else
6577 (void)pItem;
6578 (void)uConvertTypes;
6579 (void)pdValue;
6580 return QCBOR_ERR_HW_FLOAT_DISABLED;
6581#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
6582
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006583}
6584
6585
6586/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006587 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006588 */
6589void
6590QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
6591 const uint32_t uConvertTypes,
6592 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006593{
6594
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006595 QCBORItem Item;
6596
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006597 QCBORDecode_Private_GetDoubleConvert(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006598
6599 if(pMe->uLastError == QCBOR_SUCCESS) {
6600 // The above conversion succeeded
6601 return;
6602 }
6603
6604 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6605 // The above conversion failed in a way that code below can't correct
6606 return;
6607 }
6608
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006609 pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
6610 uConvertTypes,
6611 pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07006612}
6613
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006614
6615/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006616 * Public function, see header qcbor/qcbor_decode.h file
6617 */
6618void
6619QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
6620 const int64_t nLabel,
6621 const uint32_t uConvertTypes,
6622 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006623{
6624 QCBORItem Item;
6625
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006626 QCBORDecode_Private_GetDoubleConvertInMapN(pMe,
6627 nLabel,
6628 uConvertTypes,
6629 pdValue,
6630 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006631
6632 if(pMe->uLastError == QCBOR_SUCCESS) {
6633 // The above conversion succeeded
6634 return;
6635 }
6636
6637 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6638 // The above conversion failed in a way that code below can't correct
6639 return;
6640 }
6641
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006642 pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
6643 uConvertTypes,
6644 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006645}
6646
6647
6648/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006649 * Public function, see header qcbor/qcbor_decode.h file
6650 */
6651void
6652QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
6653 const char *szLabel,
6654 const uint32_t uConvertTypes,
6655 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006656{
6657 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006658 QCBORDecode_Private_GetDoubleConvertInMapSZ(pMe,
6659 szLabel,
6660 uConvertTypes,
6661 pdValue,
6662 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006663
6664 if(pMe->uLastError == QCBOR_SUCCESS) {
6665 // The above conversion succeeded
6666 return;
6667 }
6668
6669 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6670 // The above conversion failed in a way that code below can't correct
6671 return;
6672 }
6673
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006674 pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
6675 uConvertTypes,
6676 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006677}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02006678#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006679
6680
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006681
6682
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006683#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006684/**
6685 * @brief Convert an integer to a big number
6686 *
6687 * @param[in] uInt The integer to convert.
6688 * @param[in] Buffer The buffer to output the big number to.
6689 *
6690 * @returns The big number or NULLUsefulBufC is the buffer is to small.
6691 *
6692 * This always succeeds unless the buffer is too small.
6693 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006694static UsefulBufC
6695QCBOR_Private_ConvertIntToBigNum(uint64_t uInt, const UsefulBuf Buffer)
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006696{
6697 while((uInt & 0xff00000000000000UL) == 0) {
6698 uInt = uInt << 8;
6699 };
6700
6701 UsefulOutBuf UOB;
6702
6703 UsefulOutBuf_Init(&UOB, Buffer);
6704
6705 while(uInt) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006706 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
6707 uInt = uInt << 8;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006708 }
6709
6710 return UsefulOutBuf_OutUBuf(&UOB);
6711}
6712
6713
Laurence Lundblade37286c02022-09-03 10:05:02 -07006714/**
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006715 * @brief Check and/or complete exponent and mantissa item.
Laurence Lundblade37286c02022-09-03 10:05:02 -07006716 *
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006717 * @param[in] pMe The decoder context.
6718 * @param[in] TagSpec Expected type(s).
6719 * @param[in,out] pItem See below.
Laurence Lundblade37286c02022-09-03 10:05:02 -07006720 *
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006721 * This is for decimal fractions and big floats, both of which are an
6722 * exponent and mantissa.
Laurence Lundblade37286c02022-09-03 10:05:02 -07006723 *
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006724 * If the item item had a tag number indicating it was a
6725 * decimal fraction or big float, then the input @c pItem will
6726 * have been decoded as exponent and mantissa. If there was
6727 * no tag number, the caller is asking this be decoded as a
6728 * big float or decimal fraction and @c pItem just has the
6729 * first item in an exponent and mantissa.
Laurence Lundblade37286c02022-09-03 10:05:02 -07006730 *
6731 * On output, the item is always a fully decoded decimal fraction or
6732 * big float.
6733 *
6734 * This errors out if the input type does not meet the TagSpec.
6735 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07006736static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006737QCBOR_Private_ExpMantissaTypeHandler(QCBORDecodeContext *pMe,
6738 const QCBOR_Private_TagSpec TagSpec,
6739 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006740{
6741 QCBORError uErr;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006742
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006743 /* pItem could either be a decoded exponent and mantissa or
6744 * the opening array of an undecoded exponent and mantissa. This
Laurence Lundblade37286c02022-09-03 10:05:02 -07006745 * check will succeed on either, but doesn't say which it was.
6746 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006747 uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07006748 if(uErr != QCBOR_SUCCESS) {
6749 goto Done;
6750 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006751
Laurence Lundblade37286c02022-09-03 10:05:02 -07006752 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006753 /* The item is an array, which means is is an undecoded exponent
6754 * and mantissa. This call consumes the items in the array and
6755 * results in a decoded exponent and mantissa in pItem. This is
Laurence Lundblade37286c02022-09-03 10:05:02 -07006756 * the case where there was no tag.
6757 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006758 uErr = QCBORDecode_Private_ExpMantissa(pMe, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006759 if(uErr != QCBOR_SUCCESS) {
6760 goto Done;
6761 }
6762
Laurence Lundblade37286c02022-09-03 10:05:02 -07006763 /* The above decode didn't determine whether it is a decimal
6764 * fraction or big num. Which of these two depends on what the
6765 * caller wants it decoded as since there is no tag, so fish the
6766 * type out of the TagSpec. */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006767 pItem->uDataType = QCBOR_Private_ExpMantissaDataType(TagSpec.uTaggedTypes[0], pItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07006768
6769 /* No need to check the type again. All that we need to know was
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006770 * that it decoded correctly as a exponent and mantissa. The
Laurence Lundblade37286c02022-09-03 10:05:02 -07006771 * QCBOR type is set out by what was requested.
6772 */
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006773 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07006774
6775 /* If the item was not an array and the check passed, then
6776 * it is a fully decoded big float or decimal fraction and
6777 * matches what is requested.
6778 */
6779
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006780Done:
6781 return uErr;
6782}
6783
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006784
Laurence Lundblade37286c02022-09-03 10:05:02 -07006785/* Some notes from the work to disable tags.
6786 *
6787 * The API for big floats and decimal fractions seems good.
6788 * If there's any issue with it it's that the code size to
6789 * implement is a bit large because of the conversion
6790 * to/from int and bignum that is required. There is no API
6791 * that doesn't do the conversion so dead stripping will never
6792 * leave that code out.
6793 *
6794 * The implementation itself seems correct, but not as clean
6795 * and neat as it could be. It could probably be smaller too.
6796 *
6797 * The implementation has three main parts / functions
6798 * - The decoding of the array of two
6799 * - All the tag and type checking for the various API functions
6800 * - Conversion to/from bignum and int
6801 *
6802 * The type checking seems like it wastes the most code for
6803 * what it needs to do.
6804 *
6805 * The inlining for the conversion is probably making the
6806 * overall code base larger.
6807 *
6808 * The tests cases could be organized a lot better and be
6809 * more thorough.
6810 *
6811 * Seems also like there could be more common code in the
6812 * first tier part of the public API. Some functions only
6813 * vary by a TagSpec.
6814 */
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006815
6816/**
6817 * @brief Common processor for exponent and mantissa.
6818 *
6819 * @param[in] pMe The decode context.
6820 * @param[in] TagSpec The expected/allowed tags.
6821 * @param[in] pItem The data item to process.
6822 * @param[out] pnMantissa The returned mantissa as an int64_t.
6823 * @param[out] pnExponent The returned exponent as an int64_t.
6824 *
6825 * This handles exponent and mantissa for base 2 and 10. This
6826 * is limited to a mantissa that is an int64_t. See also
6827 * QCBORDecode_Private_ProcessExpMantissaBig().
6828 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006829static void
6830QCBOR_Private_ProcessExpMantissa(QCBORDecodeContext *pMe,
6831 const QCBOR_Private_TagSpec TagSpec,
6832 QCBORItem *pItem,
6833 int64_t *pnMantissa,
6834 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006835{
6836 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006837
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07006838 if(pMe->uLastError) {
6839 return;
6840 }
6841
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006842 uErr = QCBOR_Private_ExpMantissaTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006843 if(uErr != QCBOR_SUCCESS) {
6844 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006845 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006846
Laurence Lundblade9b334962020-08-27 10:55:53 -07006847 switch (pItem->uDataType) {
6848
6849 case QCBOR_TYPE_DECIMAL_FRACTION:
6850 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade9b334962020-08-27 10:55:53 -07006851 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade37286c02022-09-03 10:05:02 -07006852 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
Laurence Lundblade9b334962020-08-27 10:55:53 -07006853 break;
6854
Laurence Lundblade37286c02022-09-03 10:05:02 -07006855#ifndef QCBOR_DISABLE_TAGS
6856 /* If tags are disabled, mantissas can never be big nums */
Laurence Lundblade9b334962020-08-27 10:55:53 -07006857 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
6858 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
6859 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006860 uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
Laurence Lundblade9b334962020-08-27 10:55:53 -07006861 break;
6862
6863 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
6864 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
6865 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006866 uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
Laurence Lundblade9b334962020-08-27 10:55:53 -07006867 break;
Laurence Lundblade37286c02022-09-03 10:05:02 -07006868#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade9b334962020-08-27 10:55:53 -07006869
6870 default:
6871 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
6872 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006873
6874 Done:
6875 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006876}
6877
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006878
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006879/**
6880 * @brief Decode exponent and mantissa into a big number.
6881 *
6882 * @param[in] pMe The decode context.
6883 * @param[in] TagSpec The expected/allowed tags.
6884 * @param[in] pItem Item to decode and convert.
6885 * @param[in] BufferForMantissa Buffer to output mantissa into.
6886 * @param[out] pMantissa The output mantissa.
6887 * @param[out] pbIsNegative The sign of the output.
6888 * @param[out] pnExponent The mantissa of the output.
6889 *
6890 * This is the common processing of a decimal fraction or a big float
6891 * into a big number. This will decode and consume all the CBOR items
6892 * that make up the decimal fraction or big float.
6893 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006894static void
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006895QCBORDecode_Private_ProcessExpMantissaBig(QCBORDecodeContext *pMe,
6896 const QCBOR_Private_TagSpec TagSpec,
6897 QCBORItem *pItem,
6898 const UsefulBuf BufferForMantissa,
6899 UsefulBufC *pMantissa,
6900 bool *pbIsNegative,
6901 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006902{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006903 QCBORError uErr;
Laurence Lundblade20fba4f2024-10-30 07:52:33 -07006904 uint64_t uMantissa;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006905
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07006906 if(pMe->uLastError != QCBOR_SUCCESS) {
6907 return;
6908 }
6909
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006910 uErr = QCBOR_Private_ExpMantissaTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006911 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006912 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006913 }
6914
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006915 switch (pItem->uDataType) {
6916
6917 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006918 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006919 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
6920 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
6921 *pbIsNegative = false;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07006922 } else {
Laurence Lundblade20fba4f2024-10-30 07:52:33 -07006923 if(pItem->val.expAndMantissa.Mantissa.nInt != INT64_MIN) {
6924 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
6925 } else {
6926 /* Can't negate like above when int64_t is INT64_MIN because it
6927 * will overflow. See ExponentNN() */
6928 uMantissa = (uint64_t)INT64_MAX+1;
6929 }
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07006930 *pbIsNegative = true;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006931 }
Laurence Lundblade20fba4f2024-10-30 07:52:33 -07006932 /* Reverse the offset by 1 for type 1 negative value to be consistent
6933 * with big num case below which don't offset because it requires
6934 * big number arithmetic. This is a bug fix for QCBOR v1.5.
6935 */
6936 uMantissa--;
6937 *pMantissa = QCBOR_Private_ConvertIntToBigNum(uMantissa, BufferForMantissa);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006938 *pnExponent = pItem->val.expAndMantissa.nExponent;
6939 break;
6940
Laurence Lundblade37286c02022-09-03 10:05:02 -07006941#ifndef QCBOR_DISABLE_TAGS
6942 /* If tags are disabled, mantissas can never be big nums */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006943 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006944 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006945 *pnExponent = pItem->val.expAndMantissa.nExponent;
6946 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
6947 *pbIsNegative = false;
6948 break;
6949
6950 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006951 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006952 *pnExponent = pItem->val.expAndMantissa.nExponent;
6953 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
6954 *pbIsNegative = true;
6955 break;
Laurence Lundblade37286c02022-09-03 10:05:02 -07006956#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006957
6958 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006959 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006960 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006961
6962Done:
6963 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006964}
6965
6966
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006967/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006968 * Public function, see header qcbor/qcbor_decode.h file
6969 */
6970void
6971QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
6972 const uint8_t uTagRequirement,
6973 int64_t *pnMantissa,
6974 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006975{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006976 QCBORItem Item;
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07006977 QCBORDecode_VGetNext(pMe, &Item);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006978
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006979 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006980 {
6981 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006982 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6983 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6984 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006985 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006986
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006987 QCBOR_Private_ProcessExpMantissa(pMe,
6988 TagSpec,
6989 &Item,
6990 pnMantissa,
6991 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006992}
6993
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006994
6995/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006996 * Public function, see header qcbor/qcbor_decode.h file
6997 */
6998void
6999QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
7000 const int64_t nLabel,
7001 const uint8_t uTagRequirement,
7002 int64_t *pnMantissa,
7003 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007004{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007005 QCBORItem Item;
7006 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
7007
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007008 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007009 {
7010 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07007011 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
7012 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
7013 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007014 };
7015
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007016 QCBOR_Private_ProcessExpMantissa(pMe,
7017 TagSpec,
7018 &Item,
7019 pnMantissa,
7020 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007021}
7022
7023
7024/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007025 * Public function, see header qcbor/qcbor_decode.h file
7026 */
7027void
7028QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
7029 const char *szLabel,
7030 const uint8_t uTagRequirement,
7031 int64_t *pnMantissa,
7032 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007033{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007034 QCBORItem Item;
7035 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
7036
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007037 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007038 {
7039 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07007040 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
7041 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
7042 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007043 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07007044
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007045 QCBOR_Private_ProcessExpMantissa(pMe,
7046 TagSpec,
7047 &Item,
7048 pnMantissa,
7049 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007050}
7051
7052
7053/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007054 * Public function, see header qcbor/qcbor_decode.h file
7055 */
7056void
7057QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
7058 const uint8_t uTagRequirement,
7059 const UsefulBuf MantissaBuffer,
7060 UsefulBufC *pMantissa,
7061 bool *pbMantissaIsNegative,
7062 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007063{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007064 QCBORItem Item;
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07007065 QCBORDecode_VGetNext(pMe, &Item);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007066
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007067 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007068 {
7069 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07007070 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
7071 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
7072 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007073 };
7074
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07007075 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
7076 TagSpec,
7077 &Item,
7078 MantissaBuffer,
7079 pMantissa,
7080 pbMantissaIsNegative,
7081 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007082}
7083
7084
7085/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007086 * Public function, see header qcbor/qcbor_decode.h file
7087 */
7088void
7089QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
7090 const int64_t nLabel,
7091 const uint8_t uTagRequirement,
7092 const UsefulBuf BufferForMantissa,
7093 UsefulBufC *pMantissa,
7094 bool *pbIsNegative,
7095 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07007096{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07007097
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007098 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07007099 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07007100
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007101 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007102 {
7103 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07007104 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
7105 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
7106 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007107 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007108
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07007109 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
7110 TagSpec,
7111 &Item,
7112 BufferForMantissa,
7113 pMantissa,
7114 pbIsNegative,
7115 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007116}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07007117
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007118
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007119/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007120 * Public function, see header qcbor/qcbor_decode.h file
7121 */
7122void
7123QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
7124 const char *szLabel,
7125 const uint8_t uTagRequirement,
7126 const UsefulBuf BufferForMantissa,
7127 UsefulBufC *pMantissa,
7128 bool *pbIsNegative,
7129 int64_t *pnExponent)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007130{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007131 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007132 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007133
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007134 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007135 {
7136 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07007137 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
7138 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
7139 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007140 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007141
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07007142 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
7143 TagSpec,
7144 &Item,
7145 BufferForMantissa,
7146 pMantissa,
7147 pbIsNegative,
7148 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007149}
7150
7151
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007152/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007153 * Public function, see header qcbor/qcbor_decode.h file
7154 */
7155void
7156QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
7157 const uint8_t uTagRequirement,
7158 int64_t *pnMantissa,
7159 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007160{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007161 QCBORItem Item;
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07007162 QCBORDecode_VGetNext(pMe, &Item);
7163
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007164 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007165 {
7166 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07007167 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
7168 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
7169 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007170 };
7171
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007172 QCBOR_Private_ProcessExpMantissa(pMe,
7173 TagSpec,
7174 &Item,
7175 pnMantissa,
7176 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007177}
7178
7179
7180/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007181 * Public function, see header qcbor/qcbor_decode.h file
7182 */
7183void
7184QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
7185 const int64_t nLabel,
7186 const uint8_t uTagRequirement,
7187 int64_t *pnMantissa,
7188 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007189{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007190 QCBORItem Item;
7191 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007192
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007193 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007194 {
7195 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07007196 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
7197 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
7198 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007199 };
7200
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007201 QCBOR_Private_ProcessExpMantissa(pMe,
7202 TagSpec,
7203 &Item,
7204 pnMantissa,
7205 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007206}
7207
7208
7209/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007210 * Public function, see header qcbor/qcbor_decode.h file
7211 */
7212void
7213QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
7214 const char *szLabel,
7215 const uint8_t uTagRequirement,
7216 int64_t *pnMantissa,
7217 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007218{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007219 QCBORItem Item;
7220 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007221
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007222 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007223 {
7224 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07007225 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
7226 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
7227 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007228 };
7229
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007230 QCBOR_Private_ProcessExpMantissa(pMe,
7231 TagSpec,
7232 &Item,
7233 pnMantissa,
7234 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007235}
7236
7237
7238/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007239 * Public function, see header qcbor/qcbor_decode.h file
7240 */
7241void
7242QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
7243 const uint8_t uTagRequirement,
7244 const UsefulBuf MantissaBuffer,
7245 UsefulBufC *pMantissa,
7246 bool *pbMantissaIsNegative,
7247 int64_t *pnExponent)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007248{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007249 QCBORItem Item;
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07007250 QCBORDecode_VGetNext(pMe, &Item);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007251
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007252 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007253 {
7254 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07007255 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
7256 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
7257 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007258 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007259
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07007260 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
7261 TagSpec,
7262 &Item,
7263 MantissaBuffer,
7264 pMantissa,
7265 pbMantissaIsNegative,
7266 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007267}
7268
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007269
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007270/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007271 * Public function, see header qcbor/qcbor_decode.h file
7272 */
7273void
7274QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
7275 const int64_t nLabel,
7276 const uint8_t uTagRequirement,
7277 const UsefulBuf BufferForMantissa,
7278 UsefulBufC *pMantissa,
7279 bool *pbIsNegative,
7280 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007281{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007282 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007283 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007284
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007285 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007286 {
7287 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07007288 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
7289 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
7290 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007291 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007292
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07007293 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
7294 TagSpec,
7295 &Item,
7296 BufferForMantissa,
7297 pMantissa,
7298 pbIsNegative,
7299 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007300}
7301
7302
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007303/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007304 * Public function, see header qcbor/qcbor_decode.h file
7305 */
7306void
7307QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
7308 const char *szLabel,
7309 const uint8_t uTagRequirement,
7310 const UsefulBuf BufferForMantissa,
7311 UsefulBufC *pMantissa,
7312 bool *pbIsNegative,
7313 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007314{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007315 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007316 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07007317
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007318 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007319 {
7320 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07007321 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
7322 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
7323 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007324 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007325
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07007326 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
7327 TagSpec,
7328 &Item,
7329 BufferForMantissa,
7330 pMantissa,
7331 pbIsNegative,
7332 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07007333}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007334
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07007335#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */