blob: 9bd518e60ac71ac376ac3455b6594fdbd6380007 [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 Lundblade02625d42020-06-25 14:41:41 -0700464 uint8_t uQCBORType,
465 uint64_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 Lundblade3f1318a2021-01-04 18:26:44 -0800477 /* Error out if arrays is too long to handle */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700478 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
479 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700480 uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700481 goto Done;
482 }
483
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700484 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700485 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700486 goto Done;
487 }
488
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800489 /* Fill in the new map/array level. Check above makes casts OK. */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700490 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
491 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700492
493 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700494
495Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700496 return uError;;
497}
498
499
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700500static void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700501DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
502{
503 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
504}
505
506
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700507static void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700508DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
509{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700510 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700511 pNesting->pCurrentBounded--;
512 if(DecodeNesting_IsCurrentBounded(pNesting)) {
513 break;
514 }
515 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700516}
517
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800518
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700519static void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700520DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
521{
522 pNesting->pCurrent = pNesting->pCurrentBounded;
523}
524
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700525
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700526static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700527DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700528 uint32_t uEndOffset,
529 uint32_t uStartOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700530{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700531 QCBORError uError;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700532
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700533 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700534 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700535 goto Done;
536 }
537
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800538 /* Fill in the new byte string level */
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700539 pNesting->pCurrent->u.bs.uSavedEndOffset = uEndOffset;
540 pNesting->pCurrent->u.bs.uBstrStartOffset = uStartOffset;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700541
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800542 /* Bstr wrapped levels are always bounded */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700543 pNesting->pCurrentBounded = pNesting->pCurrent;
544
545Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700546 return uError;;
547}
548
Laurence Lundbladed0304932020-06-27 10:59:38 -0700549
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700550static void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700551DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700552{
553 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700554}
555
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700556
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700557static void
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800558DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
559{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700560 if(pNesting->pCurrent->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
561 pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
562 }
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800563}
564
565
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700566static void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700567DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700568{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700569 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700570 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
571 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700572}
573
574
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700575static void
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800576DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting,
577 QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700578{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700579 *pSave = *pNesting;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700580}
581
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700582
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700583static void
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800584DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting,
585 const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700586{
587 *pNesting = *pSave;
588}
589
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700590
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700591static uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700592DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700593{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700594 return pMe->pCurrentBounded->u.bs.uSavedEndOffset;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700595}
596
597
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800598
599
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800600#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladeee851742020-01-08 08:37:05 -0800601/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800602 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
603
604 The following four functions are pretty wrappers for invocation of
605 the string allocator supplied by the caller.
606
Laurence Lundbladeee851742020-01-08 08:37:05 -0800607 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800608
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700609static void
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800610StringAllocator_Free(const QCBORInternalAllocator *pMe, const void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800611{
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300612 /* This cast to uintptr_t suppresses the "-Wcast-qual" warnings.
613 * This is the one place where the const needs to be cast away so const can
614 * be use in the rest of the code.
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800615 */
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300616 (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)(uintptr_t)pMem, 0);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800617}
618
Laurence Lundbladeee851742020-01-08 08:37:05 -0800619// StringAllocator_Reallocate called with pMem NULL is
620// equal to StringAllocator_Allocate()
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700621static UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800622StringAllocator_Reallocate(const QCBORInternalAllocator *pMe,
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800623 const void *pMem,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800624 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800625{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800626 /* See comment in StringAllocator_Free() */
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300627 return (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)(uintptr_t)pMem, uSize);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800628}
629
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700630static UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800631StringAllocator_Allocate(const QCBORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800632{
633 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
634}
635
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700636static void
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800637StringAllocator_Destruct(const QCBORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800638{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800639 /* See comment in StringAllocator_Free() */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800640 if(pMe->pfAllocator) {
641 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
642 }
643}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800644#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800645
646
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800647
648
Laurence Lundbladeee851742020-01-08 08:37:05 -0800649/*===========================================================================
650 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700651
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800652 See qcbor/qcbor_decode.h for definition of the object
653 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800654 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700655/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800656 * Public function, see header file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700657 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700658void
659QCBORDecode_Init(QCBORDecodeContext *pMe,
660 UsefulBufC EncodedCBOR,
661 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700662{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800663 memset(pMe, 0, sizeof(QCBORDecodeContext));
664 UsefulInputBuf_Init(&(pMe->InBuf), EncodedCBOR);
665 /* Don't bother with error check on decode mode. If a bad value is
666 * passed it will just act as if the default normal mode of 0 was set.
667 */
668 pMe->uDecodeMode = (uint8_t)nDecodeMode;
669 DecodeNesting_Init(&(pMe->nesting));
670
671 /* Inialize me->auMappedTags to CBOR_TAG_INVALID16. See
672 * GetNext_TaggedItem() and MapTagNumber(). */
673 memset(pMe->auMappedTags, 0xff, sizeof(pMe->auMappedTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700674}
675
676
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800677#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
678
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700679/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800680 * Public function, see header file
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700681 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700682void
683QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
684 QCBORStringAllocate pfAllocateFunction,
685 void *pAllocateContext,
686 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700687{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800688 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
689 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
690 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700691}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800692#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700693
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800694
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800695
696
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800697/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800698 * Deprecated public function, see header file
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800699 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700700void
701QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
702 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700703{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800704 /* This does nothing now. It is retained for backwards compatibility */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700705 (void)pMe;
706 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700707}
708
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700709
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800710
711
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700712/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800713 * Decoding items is done in six layers, one calling the next one
714 * down. If a layer has no work to do for a particular item, it
715 * returns quickly.
716 *
Laurence Lundblade0f01ac62024-02-18 23:07:07 -0700717 * 1. QCBORDecode_Private_GetNextTagContent - The top layer processes
718 * tagged data items, turning them into the local C representation.
719 * For the most simple it is just associating a QCBOR_TYPE with the
720 * data. For the complex ones that an aggregate of data items, there
721 * is some further decoding and some limited recursion.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800722 *
Laurence Lundblade0f01ac62024-02-18 23:07:07 -0700723 * 2. QCBORDecode_Private_GetNextMapOrArray - This manages the
724 * beginnings and ends of maps and arrays. It tracks descending into
725 * and ascending out of maps/arrays. It processes breaks that
726 * terminate indefinite-length maps and arrays.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800727 *
Laurence Lundblade0f01ac62024-02-18 23:07:07 -0700728 * 3. QCBORDecode_Private_GetNextMapEntry - This handles the combining
729 * of two items, the label and the data, that make up a map entry. It
730 * only does work on maps. It combines the label and data items into
731 * one labeled item.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800732 *
Laurence Lundblade0f01ac62024-02-18 23:07:07 -0700733 * 4. QCBORDecode_Private_GetNextTagNumber - This decodes type 6 tag
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800734 * numbers. It turns the tag numbers into bit flags associated with
735 * the data item. No actual decoding of the contents of the tag is
736 * performed here.
737 *
Laurence Lundblade0f01ac62024-02-18 23:07:07 -0700738 * 5. QCBORDecode_Private_GetNextFullString - This assembles the
739 * sub-items that make up an indefinite-length string into one string
740 * item. It uses the string allocator to create contiguous space for
741 * the item. It processes all breaks that are part of
742 * indefinite-length strings.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800743 *
Laurence Lundblade0f01ac62024-02-18 23:07:07 -0700744 * 6. QCBOR_Private_DecodeAtomicDataItem - This decodes the atomic
745 * data items in CBOR. Each atomic data item has a "major type", an
746 * integer "argument" and optionally some content. For text and byte
747 * strings, the content is the bytes that make up the string. These
748 * are the smallest data items that are considered to be well-formed.
749 * The content may also be other data items in the case of aggregate
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800750 * types. They are not handled in this layer.
751 *
Laurence Lundblade0f01ac62024-02-18 23:07:07 -0700752 * This uses about 350 bytes of stack. This number comes from
753 * instrumenting (printf address of stack variables) the code on x86
754 * compiled for size optimization.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700755 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800756
757
758/*
759 * Note about use of int and unsigned variables.
760 *
761 * See http://www.unix.org/whitepapers/64bit.html for reasons int is
762 * used carefully here, and in particular why it isn't used in the
763 * public interface. Also see
764 * https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
765 *
766 * Int is used for values that need less than 16-bits and would be
767 * subject to integer promotion and result in complaining from static
768 * analyzers.
769 */
770
771
772/**
773 * @brief Decode the CBOR head, the type and argument.
774 *
775 * @param[in] pUInBuf The input buffer to read from.
776 * @param[out] pnMajorType The decoded major type.
777 * @param[out] puArgument The decoded argument.
778 * @param[out] pnAdditionalInfo The decoded Lower 5 bits of initial byte.
779 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -0700780 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved features
781 * @retval QCBOR_ERR_HIT_END Unexpected end of input
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800782 *
783 * This decodes the CBOR "head" that every CBOR data item has. See
784 * longer explaination of the head in documentation for
785 * QCBOREncode_EncodeHead().
786 *
787 * This does the network->host byte order conversion. The conversion
788 * here also results in the conversion for floats in addition to that
789 * for lengths, tags and integer values.
790 *
791 * The int type is preferred to uint8_t for some variables as this
792 * avoids integer promotions, can reduce code size and makes static
793 * analyzers happier.
794 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700795static QCBORError
796QCBOR_Private_DecodeHead(UsefulInputBuf *pUInBuf,
797 int *pnMajorType,
798 uint64_t *puArgument,
799 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700800{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800801 QCBORError uReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800802
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800803 /* Get the initial byte that every CBOR data item has and break it
804 * down. */
805 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800806 const int nTmpMajorType = nInitialByte >> 5;
807 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800808
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800809 /* Where the argument accumulates */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800810 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800811
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800812 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800813 /* Need to get 1,2,4 or 8 additional argument bytes. Map
814 * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
815 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800816 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800817
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800818 /* Loop getting all the bytes in the argument */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800819 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800820 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800821 /* This shift and add gives the endian conversion. */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800822 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
823 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800824 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800825 /* The reserved and thus-far unused additional info values */
826 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800827 goto Done;
828 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800829 /* Less than 24, additional info is argument or 31, an
830 * indefinite-length. No more bytes to get.
831 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800832 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700833 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800834
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700835 if(UsefulInputBuf_GetError(pUInBuf)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800836 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700837 goto Done;
838 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800839
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800840 /* All successful if arrived here. */
841 uReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800842 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800843 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800844 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800845
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700846Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800847 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700848}
849
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800850
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800851/**
852 * @brief Decode integer types, major types 0 and 1.
853 *
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700854 * @param[in] nMajorType The CBOR major type (0 or 1).
855 * @param[in] uArgument The argument from the head.
856 * @param[in] nAdditionalInfo So it can be error-checked.
857 * @param[out] pDecodedItem The filled in decoded item.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800858 *
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700859 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered.
860 * @retval QCBOR_ERR_BAD_INT nAdditionalInfo indicated indefinte.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800861 *
862 * Must only be called when major type is 0 or 1.
863 *
864 * CBOR doesn't explicitly specify two's compliment for integers but
865 * all CPUs use it these days and the test vectors in the RFC are
866 * so. All integers in the CBOR structure are positive and the major
867 * type indicates positive or negative. CBOR can express positive
868 * integers up to 2^x - 1 where x is the number of bits and negative
869 * integers down to 2^x. Note that negative numbers can be one more
870 * away from zero than positive. Stdint, as far as I can tell, uses
871 * two's compliment to represent negative integers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700872 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700873static QCBORError
874QCBOR_Private_DecodeInteger(const int nMajorType,
875 const uint64_t uArgument,
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700876 const int nAdditionalInfo,
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700877 QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700878{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800879 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800880
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700881 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
882 uReturn = QCBOR_ERR_BAD_INT;
883 goto Done;
884 }
885
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700886 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800887 if (uArgument <= INT64_MAX) {
888 pDecodedItem->val.int64 = (int64_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700889 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800890
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700891 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800892 pDecodedItem->val.uint64 = uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700893 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700894 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800895
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700896 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800897 if(uArgument <= INT64_MAX) {
898 /* CBOR's representation of negative numbers lines up with
899 * the two-compliment representation. A negative integer has
900 * one more in range than a positive integer. INT64_MIN is
901 * equal to (-INT64_MAX) - 1.
902 */
903 pDecodedItem->val.int64 = (-(int64_t)uArgument) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700904 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800905
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700906 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800907 /* C can't represent a negative integer in this range so it
908 * is an error.
909 */
910 uReturn = QCBOR_ERR_INT_OVERFLOW;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700911 }
912 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800913
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700914Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800915 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700916}
917
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800918
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700919/**
920 * @brief Decode text and byte strings
921 *
922 * @param[in] pMe Decoder context.
923 * @param[in] bAllocate Whether to allocate and copy string.
924 * @param[in] nMajorType Whether it is a byte or text string.
925 * @param[in] uStrLen The length of the string.
926 * @param[in] nAdditionalInfo Whether it is an indefinite-length string.
927 * @param[out] pDecodedItem The filled-in decoded item.
928 *
929 * @retval QCBOR_ERR_HIT_END Unexpected end of input.
930 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
931 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
932 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Allocation requested, but no allocator
933 *
934 * This reads @c uStrlen bytes from the input and fills in @c
935 * pDecodedItem. If @c bAllocate is true, then memory for the string
936 * is allocated.
937 */
938static QCBORError
939QCBOR_Private_DecodeString(QCBORDecodeContext *pMe,
940 const bool bAllocate,
941 const int nMajorType,
942 const uint64_t uStrLen,
943 const int nAdditionalInfo,
944 QCBORItem *pDecodedItem)
945{
946 QCBORError uReturn = QCBOR_SUCCESS;
947
948 /* ---- Figure out the major type ---- */
949 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
950 #error QCBOR_TYPE_BYTE_STRING not lined up with major type
951 #endif
952
953 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
954 #error QCBOR_TYPE_TEXT_STRING not lined up with major type
955 #endif
956 pDecodedItem->uDataType = (uint8_t)(nMajorType + 4);
957
958 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
959 /* --- Just the head of an indefinite-length string --- */
960 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
961
962 } else {
963 /* --- A definite-length string --- */
964 /* --- (which might be a chunk of an indefinte-length string) --- */
965
966 /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
967 * CPUs. This check makes the casts to size_t below safe.
968 *
969 * The max is 4 bytes less than the largest sizeof() so this can be
970 * tested by putting a SIZE_MAX length in the CBOR test input (no
971 * one will care the limit on strings is 4 bytes shorter).
972 */
973 if(uStrLen > SIZE_MAX-4) {
974 uReturn = QCBOR_ERR_STRING_TOO_LONG;
975 goto Done;
976 }
977
978 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(&(pMe->InBuf), (size_t)uStrLen);
979 if(UsefulBuf_IsNULLC(Bytes)) {
980 /* Failed to get the bytes for this string item */
981 uReturn = QCBOR_ERR_HIT_END;
982 goto Done;
983 }
984
985 if(bAllocate) {
986#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
987 /* --- Put string in allocated memory --- */
988
989 /* Note that this is not where allocation to coalesce
990 * indefinite-length strings is done. This is for when the
991 * caller has requested all strings be allocated. Disabling
992 * indefinite length strings also disables this allocate-all
993 * option.
994 */
995
996 if(pMe->StringAllocator.pfAllocator == NULL) {
997 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
998 goto Done;
999 }
1000 UsefulBuf NewMem = StringAllocator_Allocate(&(pMe->StringAllocator), (size_t)uStrLen);
1001 if(UsefulBuf_IsNULL(NewMem)) {
1002 uReturn = QCBOR_ERR_STRING_ALLOCATE;
1003 goto Done;
1004 }
1005 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
1006 pDecodedItem->uDataAlloc = 1;
1007#else
1008 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1009#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1010 } else {
1011 /* --- Normal case with no string allocator --- */
1012 pDecodedItem->val.string = Bytes;
1013 }
1014 }
1015
1016Done:
1017 return uReturn;
1018}
1019
1020
1021/**
1022 * @brief Decode array or map.
1023 *
1024 * @param[in] uMode Decoder mode.
1025 * @param[in] nMajorType Whether it is a byte or text string.
1026 * @param[in] uItemCount The length of the string.
1027 * @param[in] nAdditionalInfo Whether it is an indefinite-length.
1028 * @param[out] pDecodedItem The filled-in decoded item.
1029 *
1030 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinites disabled.
1031 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG Too many items in array/map.
1032 *
1033 * Not much to do for arrays and maps. Just the type item count (but a
1034 * little messy because of ifdefs for indefinite-lengths and
1035 * map-as-array decoding).
1036 *
1037 * This also does the bulk of the work for @ref
1038 * QCBOR_DECODE_MODE_MAP_AS_ARRAY, a special mode to handle
1039 * arbitrarily complex map labels. This ifdefs out with
1040 * QCBOR_DISABLE_NON_INTEGER_LABELS.
1041 */
1042static QCBORError
1043QCBOR_Private_DecodeArrayOrMap(const uint8_t uMode,
1044 const int nMajorType,
1045 const uint64_t uItemCount,
1046 const int nAdditionalInfo,
1047 QCBORItem *pDecodedItem)
1048{
1049 QCBORError uReturn;
1050
1051 /* ------ Sort out the data type ------ */
1052 #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
1053 #error QCBOR_TYPE_ARRAY value not lined up with major type
1054 #endif
1055
1056 #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
1057 #error QCBOR_TYPE_MAP value not lined up with major type
1058 #endif
1059 pDecodedItem->uDataType = (uint8_t)nMajorType;
1060#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
1061 if(uMode == QCBOR_DECODE_MODE_MAP_AS_ARRAY && nMajorType == QCBOR_TYPE_MAP) {
1062 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
1063 }
1064#else
1065 (void)uMode;
1066#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
1067
1068 uReturn = QCBOR_SUCCESS;
1069
1070 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1071 /* ------ Indefinite-length array/map ----- */
1072#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
1073 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
1074#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1075 uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
1076#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1077 } else {
1078
1079#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
1080 if(uMode == QCBOR_DECODE_MODE_MAP_AS_ARRAY && nMajorType == QCBOR_TYPE_MAP) {
1081 /* ------ Definite-length map as array ------ */
1082
1083 if(uItemCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
1084 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
1085 } else {
1086 /* cast OK because of check above */
1087 pDecodedItem->val.uCount = (uint16_t)uItemCount*2;
1088 }
1089
1090 } else
1091#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
1092 {
1093 /* ------ Definite-length array/map ------ */
1094 if(uItemCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
1095 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
1096 } else {
1097 /* cast OK because of check above */
1098 pDecodedItem->val.uCount = (uint16_t)uItemCount;
1099 }
1100 }
1101 }
1102
1103 return uReturn;
1104}
1105
1106
1107/**
1108 * @brief Decode a tag number.
1109 *
1110 * @param[in] uTagNumber The length of the string.
1111 * @param[in] nAdditionalInfo So this can be error-checked.
1112 * @param[out] pDecodedItem The filled-in decoded item.
1113 *
1114 * @retval QCBOR_ERR_BAD_INT nAdditionalInfo is LEN_IS_INDEFINITE.
1115 * @retval QCBOR_ERR_TAGS_DISABLED QCBOR_DISABLE_TAGS is defined.
1116 *
1117 * Not much to do for tags, but fill in pDecodedItem and check for
1118 * error in nAdditionalInfo.
1119 */
1120static QCBORError
1121QCBOR_Private_DecodeTag(const uint64_t uTagNumber,
1122 const int nAdditionalInfo,
1123 QCBORItem *pDecodedItem)
1124{
1125#ifndef QCBOR_DISABLE_TAGS
1126 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1127 return QCBOR_ERR_BAD_INT;
1128 } else {
1129 pDecodedItem->val.uTagV = uTagNumber;
1130 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
1131 return QCBOR_SUCCESS;
1132 }
1133#else /* QCBOR_DISABLE_TAGS */
1134 (void)nAdditionalInfo;
Laurence Lundblade6c9a8242024-06-12 20:34:52 -07001135 (void)uTagNumber;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001136 (void)pDecodedItem;
1137 return QCBOR_ERR_TAGS_DISABLED;
1138#endif /* QCBOR_DISABLE_TAGS */
1139}
1140
1141
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001142/* Make sure #define value line up as DecodeSimple counts on this. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001143#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
1144#error QCBOR_TYPE_FALSE macro value wrong
1145#endif
1146
1147#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
1148#error QCBOR_TYPE_TRUE macro value wrong
1149#endif
1150
1151#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
1152#error QCBOR_TYPE_NULL macro value wrong
1153#endif
1154
1155#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
1156#error QCBOR_TYPE_UNDEF macro value wrong
1157#endif
1158
Laurence Lundblade0f99d692018-09-26 14:39:28 -07001159#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
1160#error QCBOR_TYPE_BREAK macro value wrong
1161#endif
1162
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001163#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
1164#error QCBOR_TYPE_DOUBLE macro value wrong
1165#endif
1166
1167#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
1168#error QCBOR_TYPE_FLOAT macro value wrong
1169#endif
1170
Laurence Lundblade9b334962020-08-27 10:55:53 -07001171
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001172/**
1173 * @brief Decode major type 7 -- true, false, floating-point, break...
1174 *
1175 * @param[in] nAdditionalInfo The lower five bits from the initial byte.
1176 * @param[in] uArgument The argument from the head.
1177 * @param[out] pDecodedItem The filled in decoded item.
1178 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001179 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1180 * of half-precision disabled
1181 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all float
1182 * decode is disabled.
1183 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of simple
1184 * type in input.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001185 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001186static QCBORError
1187QCBOR_Private_DecodeType7(const int nAdditionalInfo,
1188 const uint64_t uArgument,
1189 QCBORItem *pDecodedItem)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001190{
1191 QCBORError uReturn = QCBOR_SUCCESS;
1192
1193 /* uAdditionalInfo is 5 bits from the initial byte. Compile time
1194 * checks above make sure uAdditionalInfo values line up with
1195 * uDataType values. DecodeHead() never returns an AdditionalInfo
1196 * > 0x1f so cast is safe.
1197 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001198 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001199
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001200 switch(nAdditionalInfo) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001201 /* No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they
1202 * are caught before this is called.
1203 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001204
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001205 case HALF_PREC_FLOAT: /* 25 */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -07001206#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001207 /* Half-precision is returned as a double. The cast to
1208 * uint16_t is safe because the encoded value was 16 bits. It
1209 * was widened to 64 bits to be passed in here.
1210 */
1211 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +07001212 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001213#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001214 uReturn = FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -07001215 break;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001216 case SINGLE_PREC_FLOAT: /* 26 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001217#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001218 /* Single precision is normally returned as a double since
1219 * double is widely supported, there is no loss of precision,
1220 * it makes it easy for the caller in most cases and it can
1221 * be converted back to single with no loss of precision
1222 *
1223 * The cast to uint32_t is safe because the encoded value was
1224 * 32 bits. It was widened to 64 bits to be passed in here.
1225 */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001226 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001227 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uArgument);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001228#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001229 /* In the normal case, use HW to convert float to
1230 * double. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001231 pDecodedItem->val.dfnum = (double)f;
1232 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001233#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001234 /* Use of float HW is disabled, return as a float. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001235 pDecodedItem->val.fnum = f;
1236 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
1237
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001238 /* IEEE754_FloatToDouble() could be used here to return as
1239 * a double, but it adds object code and most likely
1240 * anyone disabling FLOAT HW use doesn't care about floats
1241 * and wants to save object code.
1242 */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001243#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001244 }
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001245#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1246 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -07001247 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001248
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001249 case DOUBLE_PREC_FLOAT: /* 27 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001250#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001251 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +07001252 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001253#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1254 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -07001255 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001256
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001257 case CBOR_SIMPLEV_FALSE: /* 20 */
1258 case CBOR_SIMPLEV_TRUE: /* 21 */
1259 case CBOR_SIMPLEV_NULL: /* 22 */
1260 case CBOR_SIMPLEV_UNDEF: /* 23 */
1261 case CBOR_SIMPLE_BREAK: /* 31 */
1262 break; /* nothing to do */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001263
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001264 case CBOR_SIMPLEV_ONEBYTE: /* 24 */
1265 if(uArgument <= CBOR_SIMPLE_BREAK) {
1266 /* This takes out f8 00 ... f8 1f which should be encoded
1267 * as e0 … f7
1268 */
1269 uReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001270 goto Done;
1271 }
Laurence Lundblade5e390822019-01-06 12:35:01 -08001272 /* FALLTHROUGH */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001273
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001274 default: /* 0-19 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001275 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001276 /* DecodeHead() will make uArgument equal to
1277 * nAdditionalInfo when nAdditionalInfo is < 24. This cast is
1278 * safe because the 2, 4 and 8 byte lengths of uNumber are in
1279 * the double/float cases above
Laurence Lundbladeee851742020-01-08 08:37:05 -08001280 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001281 pDecodedItem->val.uSimple = (uint8_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001282 break;
1283 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001284
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001285Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001286 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001287}
1288
1289
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001290/**
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001291 * @brief Decode a single primitive data item (decode layer 6).
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001292 *
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001293 * @param[in] pMe Decoder context.
1294 * @param[in] bAllocateStrings If true, use allocator for strings.
1295 * @param[out] pDecodedItem The filled-in decoded item.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001296 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001297 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1298 * features
1299 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1300 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1301 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1302 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001303 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Allocation requested, but no allocator
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001304 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1305 * of half-precision disabled
1306 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1307 * float decode is disabled.
1308 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1309 * simple type in input.
1310 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1311 * in input, but indefinite
1312 * lengths disabled.
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001313 * @retval QCBOR_ERR_BAD_INT nAdditionalInfo indicated indefinte.
1314 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG Too many items in array/map.
1315 * @retval QCBOR_ERR_TAGS_DISABLED QCBOR_DISABLE_TAGS is defined.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001316 *
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001317 * This decodes the most primitive/atomic data item. It does no
1318 * combining of data items.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001319 */
1320static QCBORError
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001321QCBOR_Private_DecodeAtomicDataItem(QCBORDecodeContext *pMe,
1322 const bool bAllocateStrings,
1323 QCBORItem *pDecodedItem)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001324{
1325 QCBORError uReturn;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001326 int nMajorType = 0;
1327 uint64_t uArgument = 0;
1328 int nAdditionalInfo = 0;
1329
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001330 /* Decode the "head" that every CBOR item has into the major type,
1331 * argument and the additional info.
1332 */
1333 uReturn = QCBOR_Private_DecodeHead(&(pMe->InBuf), &nMajorType, &uArgument, &nAdditionalInfo);
1334 if(uReturn != QCBOR_SUCCESS) {
1335 return uReturn;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001336 }
1337
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001338 memset(pDecodedItem, 0, sizeof(QCBORItem));
1339
1340 /* All the functions below get inlined by the optimizer. This code
1341 * is easier to read with them all being similar functions, even if
1342 * some functions don't do much.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001343 */
1344 switch (nMajorType) {
1345 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1346 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001347 return QCBOR_Private_DecodeInteger(nMajorType, uArgument, nAdditionalInfo, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001348 break;
1349
1350 case CBOR_MAJOR_TYPE_BYTE_STRING: /* Major type 2 */
1351 case CBOR_MAJOR_TYPE_TEXT_STRING: /* Major type 3 */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001352 return QCBOR_Private_DecodeString(pMe, bAllocateStrings, nMajorType, uArgument, nAdditionalInfo, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001353 break;
1354
1355 case CBOR_MAJOR_TYPE_ARRAY: /* Major type 4 */
1356 case CBOR_MAJOR_TYPE_MAP: /* Major type 5 */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001357 return QCBOR_Private_DecodeArrayOrMap(pMe->uDecodeMode, nMajorType, uArgument, nAdditionalInfo, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001358 break;
1359
1360 case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001361 return QCBOR_Private_DecodeTag(uArgument, nAdditionalInfo, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001362 break;
1363
1364 case CBOR_MAJOR_TYPE_SIMPLE:
1365 /* Major type 7: float, double, true, false, null... */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001366 return QCBOR_Private_DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001367 break;
1368
1369 default:
1370 /* Never happens because DecodeHead() should never return > 7 */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001371 return QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001372 break;
1373 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001374}
1375
1376
1377/**
1378 * @brief Process indefinite-length strings (decode layer 5).
1379 *
1380 * @param[in] pMe Decoder context
1381 * @param[out] pDecodedItem The decoded item that work is done on.
1382 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001383 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1384 * features
1385 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1386 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1387 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1388 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
1389 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1390 * of half-precision disabled
1391 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1392 * float decode is disabled.
1393 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1394 * simple type in input.
1395 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1396 * in input, but indefinite
1397 * lengths disabled.
1398 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Indefinite-length string in input,
1399 * but no string allocator.
1400 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK Error in indefinite-length string.
1401 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED Indefinite-length string in
1402 * input, but indefinite-length
1403 * strings are disabled.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001404 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001405 * If @c pDecodedItem is not an indefinite-length string, this does nothing.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001406 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001407 * If it is, this loops getting the subsequent chunk data items that
1408 * make up the string. The string allocator is used to make a
1409 * contiguous buffer for the chunks. When this completes @c
1410 * pDecodedItem contains the put-together string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001411 *
1412 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001413 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001414static QCBORError
1415QCBORDecode_Private_GetNextFullString(QCBORDecodeContext *pMe,
1416 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001417{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001418 /* Aproximate stack usage
1419 * 64-bit 32-bit
1420 * local vars 32 16
1421 * 2 UsefulBufs 32 16
1422 * QCBORItem 56 52
1423 * TOTAL 120 74
1424 */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001425 QCBORError uReturn;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001426
1427 /* A note about string allocation -- Memory for strings is
1428 * allocated either because 1) indefinte-length string chunks are
1429 * being coalecsed or 2) caller has requested all strings be
1430 * allocated. The first case is handed below here. The second case
1431 * is handled in DecodeString if the bAllocate is true. That
1432 * boolean originates here with pMe->bStringAllocateAll immediately
1433 * below. That is, QCBOR_Private_DecodeAtomicDataItem() is called
1434 * in two different contexts here 1) main-line processing which is
1435 * where definite-length strings need to be allocated if
1436 * bStringAllocateAll is true and 2) processing chunks of
1437 * indefinite-lengths strings in in which case there must be no
1438 * allocation.
1439 */
1440
1441
1442 uReturn = QCBOR_Private_DecodeAtomicDataItem(pMe, pMe->bStringAllocateAll, pDecodedItem);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001443 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001444 goto Done;
1445 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001446
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001447
1448 /* This is where out-of-place break is detected for the whole
1449 * decoding stack. Break is an error for everything that calls
1450 * QCBORDecode_Private_GetNextFullString(), so the check is
1451 * centralized here.
1452 */
1453 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
1454 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001455 goto Done;
1456 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001457
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001458
1459 /* Skip out if not an indefinite-length string */
1460 const uint8_t uStringType = pDecodedItem->uDataType;
1461 if(uStringType != QCBOR_TYPE_BYTE_STRING &&
1462 uStringType != QCBOR_TYPE_TEXT_STRING) {
1463 goto Done;
1464 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001465 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1466 goto Done;
1467 }
1468
1469#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001470 /* Can't decode indefinite-length strings without a string allocator */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001471 if(!pMe->StringAllocator.pfAllocator) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001472 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1473 goto Done;
1474 }
1475
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001476 /* Loop getting chunks of the indefinite-length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001477 UsefulBufC FullString = NULLUsefulBufC;
1478
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001479 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001480 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001481 QCBORItem StringChunkItem;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001482 /* Pass false to DecodeAtomicDataItem() because the individual
1483 * string chunks in an indefinite-length must not be
1484 * allocated. They are always copied into the allocated
1485 * contiguous buffer allocated here.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001486 */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001487 uReturn = QCBOR_Private_DecodeAtomicDataItem(pMe, false, &StringChunkItem);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001488 if(uReturn) {
1489 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001490 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001491
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001492 /* Is item is the marker for end of the indefinite-length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001493 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001494 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001495 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301496 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001497 break;
1498 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001499
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001500 /* All chunks must be of the same type, the type of the item
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001501 * that introduces the indefinite-length string. This also
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001502 * catches errors where the chunk is not a string at all and an
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001503 * indefinite-length string inside an indefinite-length string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001504 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001505 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001506 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1507 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001508 break;
1509 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001510
David Navarro9123e5b2022-03-28 16:04:03 +02001511 if (StringChunkItem.val.string.len > 0) {
1512 /* The first time throurgh FullString.ptr is NULL and this is
1513 * equivalent to StringAllocator_Allocate(). Subsequently it is
1514 * not NULL and a reallocation happens.
1515 */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001516 UsefulBuf NewMem = StringAllocator_Reallocate(&(pMe->StringAllocator),
David Navarro9123e5b2022-03-28 16:04:03 +02001517 FullString.ptr,
1518 FullString.len + StringChunkItem.val.string.len);
David Navarro9123e5b2022-03-28 16:04:03 +02001519 if(UsefulBuf_IsNULL(NewMem)) {
1520 uReturn = QCBOR_ERR_STRING_ALLOCATE;
1521 break;
1522 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001523
David Navarro9123e5b2022-03-28 16:04:03 +02001524 /* Copy new string chunk to the end of accumulated string */
1525 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001526 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001527 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001528
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001529 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1530 /* Getting the item failed, clean up the allocated memory */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001531 StringAllocator_Free(&(pMe->StringAllocator), FullString.ptr);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001532 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001533#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1534 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1535#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001536
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001537Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001538 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001539}
1540
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001541
Laurence Lundblade37286c02022-09-03 10:05:02 -07001542#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001543/**
1544 * @brief This converts a tag number to a shorter mapped value for storage.
1545 *
1546 * @param[in] pMe The decode context.
1547 * @param[in] uUnMappedTag The tag number to map
1548 * @param[out] puMappedTagNumer The stored tag number.
1549 *
1550 * @return error code.
1551 *
1552 * The main point of mapping tag numbers is make QCBORItem
1553 * smaller. With this mapping storage of 4 tags takes up 8
1554 * bytes. Without, it would take up 32 bytes.
1555 *
1556 * This maps tag numbers greater than QCBOR_LAST_UNMAPPED_TAG.
1557 * QCBOR_LAST_UNMAPPED_TAG is a little smaller than MAX_UINT16.
1558 *
1559 * See also UnMapTagNumber() and @ref QCBORItem.
1560 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001561static QCBORError
1562QCBORDecode_Private_MapTagNumber(QCBORDecodeContext *pMe,
1563 const uint64_t uUnMappedTag,
1564 uint16_t *puMappedTagNumer)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001565{
1566 if(uUnMappedTag > QCBOR_LAST_UNMAPPED_TAG) {
1567 unsigned uTagMapIndex;
1568 /* Is there room in the tag map, or is it in it already? */
1569 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
1570 if(pMe->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID64) {
1571 break;
1572 }
1573 if(pMe->auMappedTags[uTagMapIndex] == uUnMappedTag) {
1574 break;
1575 }
1576 }
1577 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1578 return QCBOR_ERR_TOO_MANY_TAGS;
1579 }
1580
1581 /* Covers the cases where tag is new and were it is already in the map */
1582 pMe->auMappedTags[uTagMapIndex] = uUnMappedTag;
1583 *puMappedTagNumer = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
1584
1585 } else {
1586 *puMappedTagNumer = (uint16_t)uUnMappedTag;
1587 }
1588
1589 return QCBOR_SUCCESS;
1590}
1591
1592
1593/**
1594 * @brief This converts a mapped tag number to the actual tag number.
1595 *
1596 * @param[in] pMe The decode context.
1597 * @param[in] uMappedTagNumber The stored tag number.
1598 *
1599 * @return The actual tag number is returned or
1600 * @ref CBOR_TAG_INVALID64 on error.
1601 *
1602 * This is the reverse of MapTagNumber()
1603 */
1604static uint64_t
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001605QCBORDecode_Private_UnMapTagNumber(const QCBORDecodeContext *pMe,
1606 const uint16_t uMappedTagNumber)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001607{
1608 if(uMappedTagNumber <= QCBOR_LAST_UNMAPPED_TAG) {
1609 return uMappedTagNumber;
1610 } else if(uMappedTagNumber == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001611 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001612 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001613 /* This won't be negative because of code below in
1614 * MapTagNumber()
1615 */
1616 const unsigned uIndex = uMappedTagNumber - (QCBOR_LAST_UNMAPPED_TAG + 1);
1617 return pMe->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001618 }
1619}
Laurence Lundblade37286c02022-09-03 10:05:02 -07001620#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001621
Laurence Lundblade9b334962020-08-27 10:55:53 -07001622
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001623/**
1624 * @brief Aggregate all tags wrapping a data item (decode layer 4).
1625 *
1626 * @param[in] pMe Decoder context
1627 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001628 *
1629 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1630 * features
1631 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1632 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1633 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1634 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
1635 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1636 * of half-precision disabled
1637 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1638 * float decode is disabled.
1639 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1640 * simple type in input.
1641 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1642 * in input, but indefinite
1643 * lengths disabled.
1644 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Indefinite-length string in input,
1645 * but no string allocator.
1646 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK Error in indefinite-length string.
1647 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED Indefinite-length string in
1648 * input, but indefinite-length
1649 * strings are disabled.
1650 * @retval QCBOR_ERR_TOO_MANY_TAGS Too many tag numbers on item.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001651 *
1652 * This loops getting atomic data items until one is not a tag
1653 * number. Usually this is largely pass-through because most
1654 * item are not tag numbers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001655 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001656static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001657QCBORDecode_Private_GetNextTagNumber(QCBORDecodeContext *pMe,
1658 QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001659{
Laurence Lundblade37286c02022-09-03 10:05:02 -07001660#ifndef QCBOR_DISABLE_TAGS
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001661 /* Accummulate the tags from multiple items here and then copy them
1662 * into the last item, the non-tag item.
1663 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001664 uint16_t auItemsTags[QCBOR_MAX_TAGS_PER_ITEM];
1665
1666 /* Initialize to CBOR_TAG_INVALID16 */
1667 #if CBOR_TAG_INVALID16 != 0xffff
1668 /* Be sure the memset does the right thing. */
1669 #err CBOR_TAG_INVALID16 tag not defined as expected
1670 #endif
1671 memset(auItemsTags, 0xff, sizeof(auItemsTags));
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001672
Laurence Lundblade9b334962020-08-27 10:55:53 -07001673 QCBORError uReturn = QCBOR_SUCCESS;
1674
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001675 /* Loop fetching data items until the item fetched is not a tag */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001676 for(;;) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001677 QCBORError uErr = QCBORDecode_Private_GetNextFullString(pMe, pDecodedItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07001678 if(uErr != QCBOR_SUCCESS) {
1679 uReturn = uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001680 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001681 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001682
Laurence Lundblade9b334962020-08-27 10:55:53 -07001683 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001684 /* Successful exit from loop; maybe got some tags, maybe not */
1685 memcpy(pDecodedItem->uTags, auItemsTags, sizeof(auItemsTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001686 break;
1687 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001688
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001689 if(auItemsTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1690 /* No room in the tag list */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001691 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001692 /* Continue on to get all tags wrapping this item even though
1693 * it is erroring out in the end. This allows decoding to
1694 * continue. This is a resource limit error, not a problem
1695 * with being well-formed CBOR.
1696 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001697 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001698 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001699 /* Slide tags over one in the array to make room at index 0.
1700 * Must use memmove because the move source and destination
1701 * overlap.
1702 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001703 memmove(&auItemsTags[1],
1704 auItemsTags,
1705 sizeof(auItemsTags) - sizeof(auItemsTags[0]));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001706
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001707 /* Map the tag */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001708 uint16_t uMappedTagNumber = 0;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001709 uReturn = QCBORDecode_Private_MapTagNumber(pMe, pDecodedItem->val.uTagV, &uMappedTagNumber);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001710 /* Continue even on error so as to consume all tags wrapping
1711 * this data item so decoding can go on. If MapTagNumber()
1712 * errors once it will continue to error.
1713 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001714 auItemsTags[0] = uMappedTagNumber;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001715 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001716
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001717Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001718 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001719
Laurence Lundblade37286c02022-09-03 10:05:02 -07001720#else /* QCBOR_DISABLE_TAGS */
1721
Laurence Lundblade0f01ac62024-02-18 23:07:07 -07001722 return QCBORDecode_Private_GetNextFullString(pMe, pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07001723
1724#endif /* QCBOR_DISABLE_TAGS */
1725}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001726
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001727
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001728/**
1729 * @brief Combine a map entry label and value into one item (decode layer 3).
1730 *
1731 * @param[in] pMe Decoder context
1732 * @param[out] pDecodedItem The decoded item that work is done on.
1733 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001734 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1735 * features
1736 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1737 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1738 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1739 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
1740 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1741 * of half-precision disabled
1742 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1743 * float decode is disabled.
1744 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1745 * simple type in input.
1746 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1747 * in input, but indefinite
1748 * lengths disabled.
1749 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Indefinite-length string in input,
1750 * but no string allocator.
1751 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK Error in indefinite-length string.
1752 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED Indefinite-length string in
1753 * input, but indefinite-length
1754 * strings are disabled.
1755 * @retval QCBOR_ERR_TOO_MANY_TAGS Too many tag numbers on item.
1756 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG Too many items in array.
1757 * @retval QCBOR_ERR_MAP_LABEL_TYPE Map label not string or integer.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001758 *
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001759 * If the current nesting level is a map, then this combines pairs of
1760 * items into one data item with a label and value.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001761 *
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001762 * This is passthrough if the current nesting level is not a map.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001763 *
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001764 * This also implements maps-as-array mode where a map is treated like
1765 * an array to allow caller to do their own label processing.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001766 */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001767
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001768static QCBORError
1769QCBORDecode_Private_GetNextMapEntry(QCBORDecodeContext *pMe,
1770 QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001771{
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001772 QCBORItem LabelItem;
1773 QCBORError uErr;
1774
1775 uErr = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
1776 if(QCBORDecode_IsUnrecoverableError(uErr)) {
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001777 goto Done;
1778 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001779
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001780 if(!DecodeNesting_IsCurrentTypeMap(&(pMe->nesting))) {
1781 /* Not decoding a map. Nothing to do. */
1782 /* When decoding maps-as-arrays, the type will be
1783 * QCBOR_TYPE_MAP_AS_ARRAY and this function will exit
1784 * here. This is now map processing for maps-as-arrays is not
1785 * done. */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001786 goto Done;
1787 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001788
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001789 /* Decoding a map entry, so the item decoded above was the label */
1790 LabelItem = *pDecodedItem;
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001791
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001792 /* Get the value of the map item */
1793 uErr = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
1794 if(QCBORDecode_IsUnrecoverableError(uErr)) {
1795 goto Done;
1796 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001797
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001798 /* Combine the label item and value item into one */
1799 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1800 pDecodedItem->uLabelType = LabelItem.uDataType;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001801
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001802#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
1803 /* QCBOR_DECODE_MODE_MAP_STRINGS_ONLY might have been a bad idea. Maybe
1804 * get rid of it in QCBOR 2.0
1805 */
1806 if(pMe->uDecodeMode == QCBOR_DECODE_MODE_MAP_STRINGS_ONLY &&
1807 LabelItem.uDataType != QCBOR_TYPE_TEXT_STRING) {
1808 uErr = QCBOR_ERR_MAP_LABEL_TYPE;
1809 goto Done;
1810 }
1811#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
1812
1813 switch(LabelItem.uDataType) {
1814 case QCBOR_TYPE_INT64:
1815 pDecodedItem->label.int64 = LabelItem.val.int64;
1816 break;
1817
1818#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
1819 case QCBOR_TYPE_UINT64:
1820 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1821 break;
1822
1823 case QCBOR_TYPE_TEXT_STRING:
1824 case QCBOR_TYPE_BYTE_STRING:
1825 pDecodedItem->label.string = LabelItem.val.string;
1826 break;
1827#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
1828
1829 default:
1830 uErr = QCBOR_ERR_MAP_LABEL_TYPE;
1831 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001832 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001833
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001834Done:
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001835 return uErr;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001836}
1837
1838
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001839#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001840/**
1841 * @brief Peek and see if next data item is a break;
1842 *
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001843 * param[in] pUIB UsefulInputBuf to read from.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001844 * @param[out] pbNextIsBreak Indicate if next was a break or not.
1845 *
1846 * @return Any decoding error.
1847 *
1848 * See if next item is a CBOR break. If it is, it is consumed,
1849 * if not it is not consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001850*/
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001851static QCBORError
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001852QCBOR_Private_NextIsBreak(QCBORDecodeContext *pMe, bool *pbNextIsBreak)
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001853{
1854 *pbNextIsBreak = false;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001855 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001856 QCBORItem Peek;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001857 size_t uPeek = UsefulInputBuf_Tell(&(pMe->InBuf));
1858 QCBORError uReturn = QCBOR_Private_DecodeAtomicDataItem(pMe, false, &Peek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001859 if(uReturn != QCBOR_SUCCESS) {
1860 return uReturn;
1861 }
1862 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001863 /* It is not a break, rewind so it can be processed normally. */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001864 UsefulInputBuf_Seek(&(pMe->InBuf), uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001865 } else {
1866 *pbNextIsBreak = true;
1867 }
1868 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001869
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001870 return QCBOR_SUCCESS;
1871}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001872#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001873
1874
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001875/**
1876 * @brief Ascend up nesting levels if all items in them have been consumed.
1877 *
1878 * @param[in] pMe The decode context.
1879 * @param[in] bMarkEnd If true mark end of maps/arrays with count of zero.
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07001880 * @param[out] pbBreak Set to true if extra break was consumed.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001881 *
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001882 * An item was just consumed, now figure out if it was the
1883 * end of an array/map map that can be closed out. That
1884 * may in turn close out the above array/map...
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07001885 *
1886 * When ascending indefinite-length arrays and maps, this will correctly
1887 * consume the break for the level above. This is a problem for the
1888 * implementation of QCBORDecode_GetArray() that must not return
1889 * that break. @c pbBreak is set to true to indicate that one
1890 * byte should be removed.
1891 *
1892 * Improvement: this could reduced further if indef is disabled
1893 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001894static QCBORError
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07001895QCBORDecode_Private_NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd, bool *pbBreak)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001896{
1897 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001898
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001899 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001900 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07001901 if(pbBreak) {
1902 *pbBreak = false;
1903 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001904
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001905 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1906 /* Nesting level is bstr-wrapped CBOR */
1907
1908 /* Ascent for bstr-wrapped CBOR is always by explicit call
1909 * so no further ascending can happen.
1910 */
1911 break;
1912
1913 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1914 /* Level is a definite-length array/map */
1915
1916 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001917 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1918 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001919 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001920 break;
1921 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001922 /* All items in a definite-length array were consumed so it
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001923 * is time to ascend one level. This happens below.
1924 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001925
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001926#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001927 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001928 /* Level is an indefinite-length array/map. */
1929
1930 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001931 bool bIsBreak = false;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001932 uReturn = QCBOR_Private_NextIsBreak(pMe, &bIsBreak);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001933 if(uReturn != QCBOR_SUCCESS) {
1934 goto Done;
1935 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001936
1937 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001938 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001939 break;
1940 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001941
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001942 /* It was a break in an indefinitelength map / array so
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001943 * it is time to ascend one level.
1944 */
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07001945 if(pbBreak) {
1946 *pbBreak = true;
1947 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001948
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001949#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001950 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001951
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001952
1953 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001954
Laurence Lundblade93d89472020-10-03 22:30:50 -07001955 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001956 * QCBORDecode_ExitBoundedMode().
1957 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001958 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001959 /* Set the count to zero for definite-length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001960 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001961 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001962 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001963 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001964
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001965 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001966 break;
1967 }
1968
1969 /* Finally, actually ascend one level. */
1970 DecodeNesting_Ascend(&(pMe->nesting));
1971 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001972
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001973 uReturn = QCBOR_SUCCESS;
1974
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001975#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001976Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001977#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1978
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001979 return uReturn;
1980}
1981
1982
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001983/**
1984 * @brief Ascending & Descending out of nesting levels (decode layer 2).
1985 *
1986 * @param[in] pMe Decoder context
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07001987 * @param[out] pbBreak Set to true if extra break was consumed.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001988 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001989
1990 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1991 * features
1992 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1993 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1994 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1995 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
1996 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1997 * of half-precision disabled
1998 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1999 * float decode is disabled.
2000 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
2001 * simple type in input.
2002 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
2003 * in input, but indefinite
2004 * lengths disabled.
2005 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Indefinite-length string in input,
2006 * but no string allocator.
2007 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK Error in indefinite-length string.
2008 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED Indefinite-length string in
2009 * input, but indefinite-length
2010 * strings are disabled.
2011 * @retval QCBOR_ERR_TOO_MANY_TAGS Too many tag numbers on item.
2012 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG Too many items in array.
2013 * @retval QCBOR_ERR_MAP_LABEL_TYPE Map label not string or integer.
2014 * @retval QCBOR_ERR_NO_MORE_ITEMS Need more items for map or array.
2015 * @retval QCBOR_ERR_BAD_BREAK Indefinite-length break in wrong
2016 * place.
2017 * @retval QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP Nesting deeper than QCBOR
2018 * can handle.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002019 *
2020 * This handles the traversal descending into and asecnding out of
2021 * maps, arrays and bstr-wrapped CBOR. It figures out the ends of
2022 * definite- and indefinte-length maps and arrays by looking at the
2023 * item count or finding CBOR breaks. It detects the ends of the
2024 * top-level sequence and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002025 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002026static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002027QCBORDecode_Private_GetNextMapOrArray(QCBORDecodeContext *pMe,
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002028 bool *pbBreak,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002029 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002030{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002031 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07002032 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002033
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002034 /* If out of bytes to consume, it is either the end of the
2035 * top-level sequence of some bstr-wrapped CBOR that was entered.
2036 *
2037 * In the case of bstr-wrapped CBOR, the length of the
2038 * UsefulInputBuf was set to that of the bstr-wrapped CBOR. When
2039 * the bstr-wrapped CBOR is exited, the length is set back to the
2040 * top-level's length or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07002041 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002042 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002043 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07002044 goto Done;
2045 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07002046
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002047 /* Check to see if at the end of a bounded definite-length map or
2048 * array. The check for a break ending indefinite-length array is
2049 * later in QCBORDecode_NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002050 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002051 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002052 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002053 goto Done;
2054 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07002055
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08002056 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002057 uReturn = QCBORDecode_Private_GetNextMapEntry(pMe, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002058 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
2059 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002060 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002061 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05302062
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002063 /* Record the nesting level for this data item before processing
2064 * any of decrementing and descending.
Laurence Lundblade642282a2020-06-23 12:00:33 -07002065 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002066 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002067
Laurence Lundblade642282a2020-06-23 12:00:33 -07002068
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07002069 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002070 if(QCBORItem_IsMapOrArray(*pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002071 /* If the new item is a map or array, descend.
2072 *
2073 * Empty indefinite-length maps and arrays are descended into,
2074 * but then ascended out of in the next chunk of code.
2075 *
2076 * Maps and arrays do count as items in the map/array that
2077 * encloses them so a decrement needs to be done for them too,
2078 * but that is done only when all the items in them have been
2079 * processed, not when they are opened with the exception of an
2080 * empty map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07002081 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002082 QCBORError uDescendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002083 uDescendErr = DecodeNesting_DescendMapOrArray(&(pMe->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07002084 pDecodedItem->uDataType,
2085 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002086 if(uDescendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002087 /* This error is probably a traversal error and it overrides
2088 * the non-traversal error.
2089 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002090 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002091 goto Done;
2092 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07002093 }
2094
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002095 if(!QCBORItem_IsMapOrArray(*pDecodedItem) ||
2096 QCBORItem_IsEmptyDefiniteLengthMapOrArray(*pDecodedItem) ||
2097 QCBORItem_IsIndefiniteLengthMapOrArray(*pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002098 /* The following cases are handled here:
2099 * - A non-aggregate item like an integer or string
2100 * - An empty definite-length map or array
2101 * - An indefinite-length map or array that might be empty or might not.
2102 *
2103 * QCBORDecode_NestLevelAscender() does the work of decrementing the count
2104 * for an definite-length map/array and break detection for an
2105 * indefinite-0length map/array. If the end of the map/array was
2106 * reached, then it ascends nesting levels, possibly all the way
2107 * to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002108 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002109 QCBORError uAscendErr;
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002110 uAscendErr = QCBORDecode_Private_NestLevelAscender(pMe, true, pbBreak);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002111 if(uAscendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002112 /* This error is probably a traversal error and it overrides
2113 * the non-traversal error.
2114 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002115 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002116 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07002117 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05302118 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002119
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07002120 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002121 /* Tell the caller what level is next. This tells them what
2122 * maps/arrays were closed out and makes it possible for them to
2123 * reconstruct the tree with just the information returned in a
2124 * QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07002125 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002126 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07002127 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002128 pDecodedItem->uNextNestLevel = 0;
2129 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002130 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002131 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002132
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002133Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002134 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002135}
2136
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002137
Laurence Lundblade37286c02022-09-03 10:05:02 -07002138#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002139/**
2140 * @brief Shift 0th tag out of the tag list.
2141 *
2142 * pDecodedItem[in,out] The data item to convert.
2143 *
2144 * The 0th tag is discarded. \ref CBOR_TAG_INVALID16 is
2145 * shifted into empty slot at the end of the tag list.
2146 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002147static void
2148QCBOR_Private_ShiftTags(QCBORItem *pDecodedItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002149{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002150 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM-1; i++) {
2151 pDecodedItem->uTags[i] = pDecodedItem->uTags[i+1];
2152 }
2153 pDecodedItem->uTags[QCBOR_MAX_TAGS_PER_ITEM-1] = CBOR_TAG_INVALID16;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002154}
Laurence Lundblade37286c02022-09-03 10:05:02 -07002155#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002156
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07002157
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002158/**
2159 * @brief Convert different epoch date formats in to the QCBOR epoch date format
2160 *
2161 * pDecodedItem[in,out] The data item to convert.
2162 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07002163 * @retval QCBOR_ERR_DATE_OVERFLOW 65-bit negative integer.
2164 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED Float-point date in input,
2165 * floating-point date disabled.
2166 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point date in input,
2167 * all floating-point disabled.
2168 * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT Unexpected and unrecoverable
2169 * error decoding date.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002170 *
2171 * The epoch date tag defined in QCBOR allows for floating-point
2172 * dates. It even allows a protocol to flop between date formats when
2173 * ever it wants. Floating-point dates aren't that useful as they are
2174 * only needed for dates beyond the age of the earth.
2175 *
2176 * This converts all the date formats into one format of an unsigned
2177 * integer plus a floating-point fraction.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002178 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002179static QCBORError
2180QCBOR_Private_DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002181{
Laurence Lundbladec7114722020-08-13 05:11:40 -07002182 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002183
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002184#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade59289e52019-12-30 13:44:37 -08002185 pDecodedItem->val.epochDate.fSecondsFraction = 0;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002186#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002187
2188 switch (pDecodedItem->uDataType) {
2189
2190 case QCBOR_TYPE_INT64:
2191 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
2192 break;
2193
2194 case QCBOR_TYPE_UINT64:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002195 /* This only happens for CBOR type 0 > INT64_MAX so it is
2196 * always an overflow.
2197 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002198 uReturn = QCBOR_ERR_DATE_OVERFLOW;
2199 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002200 break;
2201
2202 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07002203 case QCBOR_TYPE_FLOAT:
2204#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08002205 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002206 /* Convert working value to double if input was a float */
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07002207 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002208 pDecodedItem->val.dfnum :
2209 (double)pDecodedItem->val.fnum;
2210
2211 /* The conversion from float to integer requires overflow
2212 * detection since floats can be much larger than integers.
2213 * This implementation errors out on these large float values
2214 * since they are beyond the age of the earth.
2215 *
2216 * These constants for the overflow check are computed by the
2217 * compiler. They are not computed at run time.
2218 *
2219 * The factor of 0x7ff is added/subtracted to avoid a
2220 * rounding error in the wrong direction when the compiler
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002221 * computes these constants. There is rounding because a
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002222 * 64-bit integer has 63 bits of precision where a double
2223 * only has 53 bits. Without the 0x7ff factor, the compiler
2224 * may round up and produce a double for the bounds check
2225 * that is larger than can be stored in a 64-bit integer. The
2226 * amount of 0x7ff is picked because it has 11 bits set.
2227 *
2228 * Without the 0x7ff there is a ~30 minute range of time
2229 * values 10 billion years in the past and in the future
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002230 * where this code could go wrong. Some compilers
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002231 * generate a warning or error without the 0x7ff.
2232 */
2233 const double dDateMax = (double)(INT64_MAX - 0x7ff);
2234 const double dDateMin = (double)(INT64_MIN + 0x7ff);
2235
2236 if(isnan(d) || d > dDateMax || d < dDateMin) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07002237 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002238 goto Done;
2239 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002240
2241 /* The actual conversion */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002242 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07002243 pDecodedItem->val.epochDate.fSecondsFraction =
2244 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002245 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002246#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade4b270642020-08-14 12:53:07 -07002247
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002248 uReturn = QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07002249 goto Done;
2250
Laurence Lundblade9682a532020-06-06 18:33:04 -07002251#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002252 break;
2253
2254 default:
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002255 /* It's the arrays and maps that are unrecoverable because
2256 * they are not consumed here. Since this is just an error
2257 * condition, no extra code is added here to make the error
2258 * recoverable for non-arrays and maps like strings. */
2259 uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002260 goto Done;
2261 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002262
Laurence Lundblade59289e52019-12-30 13:44:37 -08002263 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
2264
2265Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07002266 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002267}
2268
2269
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002270/**
2271 * @brief Convert the days epoch date.
2272 *
2273 * pDecodedItem[in,out] The data item to convert.
2274 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07002275 * @retval QCBOR_ERR_DATE_OVERFLOW 65-bit negative integer.
2276 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED Float-point date in input,
2277 * floating-point date disabled.
2278 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point date in input,
2279 * all floating-point disabled.
2280 * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT Unexpected and unrecoverable
2281 * error decoding date.
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002282 *
2283 * This is much simpler than the other epoch date format because
2284 * floating-porint is not allowed. This is mostly a simple type check.
2285 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002286static QCBORError
2287QCBOR_Private_DecodeDaysEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002288{
2289 QCBORError uReturn = QCBOR_SUCCESS;
2290
2291 switch (pDecodedItem->uDataType) {
2292
2293 case QCBOR_TYPE_INT64:
2294 pDecodedItem->val.epochDays = pDecodedItem->val.int64;
2295 break;
2296
2297 case QCBOR_TYPE_UINT64:
2298 /* This only happens for CBOR type 0 > INT64_MAX so it is
2299 * always an overflow.
2300 */
2301 uReturn = QCBOR_ERR_DATE_OVERFLOW;
2302 goto Done;
2303 break;
2304
2305 default:
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002306 /* It's the arrays and maps that are unrecoverable because
2307 * they are not consumed here. Since this is just an error
2308 * condition, no extra code is added here to make the error
2309 * recoverable for non-arrays and maps like strings. */
2310 uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002311 goto Done;
2312 break;
2313 }
2314
2315 pDecodedItem->uDataType = QCBOR_TYPE_DAYS_EPOCH;
2316
2317Done:
2318 return uReturn;
2319}
2320
2321
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002322#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade37286c02022-09-03 10:05:02 -07002323
2324/* Forward declaration is necessary for
2325 * QCBORDecode_MantissaAndExponent(). to be able to decode bignum
2326 * tags in the mantissa. If the mantissa is a decimal fraction or big
2327 * float in error, this will result in a recurive call to
2328 * QCBORDecode_MantissaAndExponent(), but the recursion will unwined
2329 * correctly and the correct error is returned.
2330 */
2331static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002332QCBORDecode_Private_GetNextTagContent(QCBORDecodeContext *pMe,
2333 QCBORItem *pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07002334
2335
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002336/**
2337 * @brief Decode decimal fractions and big floats.
2338 *
2339 * @param[in] pMe The decode context.
2340 * @param[in,out] pDecodedItem On input the array data item that
2341 * holds the mantissa and exponent. On
2342 * output the decoded mantissa and
2343 * exponent.
2344 *
2345 * @returns Decoding errors from getting primitive data items or
2346 * \ref QCBOR_ERR_BAD_EXP_AND_MANTISSA.
2347 *
Laurence Lundblade37286c02022-09-03 10:05:02 -07002348 * When called pDecodedItem must be the array with two members, the
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002349 * exponent and mantissa.
2350 *
2351 * This will fetch and decode the exponent and mantissa and put the
2352 * result back into pDecodedItem.
Laurence Lundblade37286c02022-09-03 10:05:02 -07002353 *
2354 * This does no checking or processing of tag numbers. That is to be
2355 * done by the code that calls this.
2356 *
2357 * This stuffs the type of the mantissa into pDecodedItem with the expectation
2358 * the caller will process it.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002359 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07002360static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002361QCBORDecode_Private_ExpMantissa(QCBORDecodeContext *pMe,
2362 QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002363{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002364 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002365
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002366 /* --- Make sure it is an array; track nesting level of members --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002367 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002368 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002369 goto Done;
2370 }
2371
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002372 /* A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundblade37286c02022-09-03 10:05:02 -07002373 * definite-length arrays, but not for indefinite. Instead remember
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002374 * the nesting level the two integers must be at, which is one
2375 * deeper than that of the array.
2376 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002377 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
2378
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002379 /* --- Get the exponent --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002380 QCBORItem exponentItem;
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002381 uReturn = QCBORDecode_Private_GetNextMapOrArray(pMe, NULL, &exponentItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002382 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002383 goto Done;
2384 }
2385 if(exponentItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002386 /* Array is empty or a map/array encountered when expecting an int */
2387 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002388 goto Done;
2389 }
2390 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002391 /* Data arriving as an unsigned int < INT64_MAX has been
2392 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2393 * also means that the only data arriving here of type
2394 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2395 * and thus an error that will get handled in the next else.
2396 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002397 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
2398 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002399 /* Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX */
2400 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002401 goto Done;
2402 }
2403
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002404 /* --- Get the mantissa --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002405 QCBORItem mantissaItem;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002406 uReturn = QCBORDecode_Private_GetNextTagContent(pMe, &mantissaItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002407 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002408 goto Done;
2409 }
2410 if(mantissaItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002411 /* Mantissa missing or map/array encountered when expecting number */
2412 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002413 goto Done;
2414 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002415 /* Stuff the mantissa data type into the item to send it up to the
2416 * the next level. */
2417 pDecodedItem->uDataType = mantissaItem.uDataType;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002418 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002419 /* Data arriving as an unsigned int < INT64_MAX has been
2420 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2421 * also means that the only data arriving here of type
2422 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2423 * and thus an error that will get handled in an else below.
2424 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002425 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002426#ifndef QCBOR_DISABLE_TAGS
2427 /* With tags fully disabled a big number mantissa will error out
2428 * in the call to QCBORDecode_GetNextWithTags() because it has
2429 * a tag number.
2430 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002431 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
2432 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002433 /* Got a good big num mantissa */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002434 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002435#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002436 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002437 /* Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX */
2438 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002439 goto Done;
2440 }
2441
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002442 /* --- Check that array only has the two numbers --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002443 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002444 /* Extra items in the decimal fraction / big float */
Laurence Lundblade37286c02022-09-03 10:05:02 -07002445 /* Improvement: this should probably be an unrecoverable error. */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002446 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002447 goto Done;
2448 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002449 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002450
2451Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002452 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002453}
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002454#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002455
2456
Laurence Lundblade37286c02022-09-03 10:05:02 -07002457#ifndef QCBOR_DISABLE_TAGS
2458
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002459#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002460/**
2461 * @brief Decode the MIME type tag
2462 *
2463 * @param[in,out] pDecodedItem The item to decode.
2464 *
2465 * Handle the text and binary MIME type tags. Slightly too complicated
2466 * f or ProcessTaggedString() because the RFC 7049 MIME type was
2467 * incorreclty text-only.
2468 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002469static QCBORError
2470QCBOR_Private_DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002471{
2472 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
2473 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07002474 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002475 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
2476 } else {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002477 /* It's the arrays and maps that are unrecoverable because
2478 * they are not consumed here. Since this is just an error
2479 * condition, no extra code is added here to make the error
2480 * recoverable for non-arrays and maps like strings. */
2481 return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002482 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002483
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002484 return QCBOR_SUCCESS;
2485}
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002486#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002487
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002488/**
Laurence Lundblade99615302020-11-29 11:19:47 -08002489 * Table of CBOR tags whose content is either a text string or a byte
2490 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
2491 * of uQCBORtype indicates the content should be a byte string rather
2492 * than a text string
2493 */
2494struct StringTagMapEntry {
2495 uint16_t uTagNumber;
2496 uint8_t uQCBORtype;
2497};
2498
2499#define IS_BYTE_STRING_BIT 0x80
2500#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
2501
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002502static const struct StringTagMapEntry QCBOR_Private_StringTagMap[] = {
Laurence Lundblade99615302020-11-29 11:19:47 -08002503 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002504 {CBOR_TAG_DAYS_STRING, QCBOR_TYPE_DAYS_STRING},
Laurence Lundblade99615302020-11-29 11:19:47 -08002505 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
2506 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
2507 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
2508 {CBOR_TAG_URI, QCBOR_TYPE_URI},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002509#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002510 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
2511 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
2512 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
2513 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002514#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade99615302020-11-29 11:19:47 -08002515 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
2516 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
2517};
2518
2519
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002520/**
2521 * @brief Process standard CBOR tags whose content is a string
2522 *
2523 * @param[in] uTag The tag.
2524 * @param[in,out] pDecodedItem The data item.
2525 *
2526 * @returns This returns QCBOR_SUCCESS if the tag was procssed,
2527 * \ref QCBOR_ERR_UNSUPPORTED if the tag was not processed and
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002528 * \ref QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT if the content type was wrong for the tag.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002529 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002530 * Process the CBOR tags that whose content is a byte string or a text
2531 * string and for which the string is just passed on to the caller.
2532 *
2533 * This maps the CBOR tag to the QCBOR type and checks the content
2534 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08002535 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08002536 * possible.
Laurence Lundblade99615302020-11-29 11:19:47 -08002537 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002538static QCBORError
2539QCBOR_Private_ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002540{
Laurence Lundblade99615302020-11-29 11:19:47 -08002541 /* This only works on tags that were not mapped; no need for other yet */
2542 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
2543 return QCBOR_ERR_UNSUPPORTED;
2544 }
2545
2546 unsigned uIndex;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002547 for(uIndex = 0; QCBOR_Private_StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
2548 if(QCBOR_Private_StringTagMap[uIndex].uTagNumber == uTag) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002549 break;
2550 }
2551 }
2552
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002553 const uint8_t uQCBORType = QCBOR_Private_StringTagMap[uIndex].uQCBORtype;
Laurence Lundblade99615302020-11-29 11:19:47 -08002554 if(uQCBORType == QCBOR_TYPE_NONE) {
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002555 /* repurpose this error to mean not handled here */
Laurence Lundblade99615302020-11-29 11:19:47 -08002556 return QCBOR_ERR_UNSUPPORTED;
2557 }
2558
2559 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
2560 if(uQCBORType & IS_BYTE_STRING_BIT) {
2561 uExpectedType = QCBOR_TYPE_BYTE_STRING;
2562 }
2563
2564 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002565 /* It's the arrays and maps that are unrecoverable because
2566 * they are not consumed here. Since this is just an error
2567 * condition, no extra code is added here to make the error
2568 * recoverable for non-arrays and maps like strings. */
2569 return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002570 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002571
Laurence Lundblade99615302020-11-29 11:19:47 -08002572 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002573 return QCBOR_SUCCESS;
2574}
Laurence Lundblade37286c02022-09-03 10:05:02 -07002575#endif /* QCBOR_DISABLE_TAGS */
2576
2577
2578#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07002579/**
2580 * @brief Figures out data type for exponent mantissa tags.
2581 *
2582 * @param[in] uTagToProcess Either @ref CBOR_TAG_DECIMAL_FRACTION or
2583 * @ref CBOR_TAG_BIG_FLOAT.
2584 * @param[in] pDecodedItem Item being decoded.
2585 *
2586 * @returns One of the 6 values between \ref QCBOR_TYPE_DECIMAL_FRACTION
2587 * and @ref QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM.
2588 *
2589 * Does mapping between a CBOR tag number and a QCBOR type. with a
2590 * little bit of logic and arithmatic.
2591 *
2592 * Used in serveral contexts. Does the work where sometimes the data
2593 * item is explicitly tagged and sometimes not.
Laurence Lundblade37286c02022-09-03 10:05:02 -07002594 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002595static uint8_t
2596QCBOR_Private_ExpMantissaDataType(const uint16_t uTagToProcess,
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07002597 const QCBORItem *pDecodedItem)
Laurence Lundblade37286c02022-09-03 10:05:02 -07002598{
2599 uint8_t uBase = uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ?
2600 QCBOR_TYPE_DECIMAL_FRACTION :
2601 QCBOR_TYPE_BIGFLOAT;
2602 if(pDecodedItem->uDataType != QCBOR_TYPE_INT64) {
2603 uBase = (uint8_t)(uBase + pDecodedItem->uDataType - QCBOR_TYPE_POSBIGNUM + 1);
2604 }
2605 return uBase;
2606}
2607#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002608
2609
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002610/**
2611 * @brief Decode tag content for select tags (decoding layer 1).
2612 *
2613 * @param[in] pMe The decode context.
2614 * @param[out] pDecodedItem The decoded item.
2615 *
2616 * @return Decoding error code.
2617 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002618 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
2619 * but the whole tag was not decoded. Here, the whole tags (tag number
2620 * and tag content) that are supported by QCBOR are decoded. This is a
2621 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002622 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002623static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002624QCBORDecode_Private_GetNextTagContent(QCBORDecodeContext *pMe,
2625 QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002626{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002627 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002628
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002629 uReturn = QCBORDecode_Private_GetNextMapOrArray(pMe, NULL, pDecodedItem);
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002630 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002631 goto Done;
2632 }
2633
Laurence Lundblade37286c02022-09-03 10:05:02 -07002634#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002635 /* When there are no tag numbers for the item, this exits first
2636 * thing and effectively does nothing.
2637 *
2638 * This loops over all the tag numbers accumulated for this item
2639 * trying to decode and interpret them. This stops at the end of
2640 * the list or at the first tag number that can't be interpreted by
2641 * this code. This is effectively a recursive processing of the
2642 * tags number list that handles nested tags.
2643 */
2644 while(1) {
2645 /* Don't bother to unmap tags via QCBORITem.uTags since this
2646 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2647 */
2648 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002649
Laurence Lundblade99615302020-11-29 11:19:47 -08002650 if(uTagToProcess == CBOR_TAG_INVALID16) {
2651 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002652 break;
2653
Laurence Lundblade99615302020-11-29 11:19:47 -08002654 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002655 uReturn = QCBOR_Private_DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002656
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002657 } else if(uTagToProcess == CBOR_TAG_DAYS_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002658 uReturn = QCBOR_Private_DecodeDaysEpoch(pDecodedItem);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002659
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002660#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002661 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2662 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002663 uReturn = QCBORDecode_Private_ExpMantissa(pMe, pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07002664 /* --- Which is it, decimal fraction or a bigfloat? --- */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002665 pDecodedItem->uDataType = QCBOR_Private_ExpMantissaDataType(uTagToProcess, pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07002666
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002667#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002668#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002669 } else if(uTagToProcess == CBOR_TAG_MIME ||
2670 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002671 uReturn = QCBOR_Private_DecodeMIME(pDecodedItem);
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002672#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002673
Laurence Lundblade99615302020-11-29 11:19:47 -08002674 } else {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002675 /* See if it is a passthrough byte/text string tag; process if so */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002676 uReturn = QCBOR_Private_ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002677
Laurence Lundblade99615302020-11-29 11:19:47 -08002678 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002679 /* It wasn't a passthrough byte/text string tag so it is
Laurence Lundblade99615302020-11-29 11:19:47 -08002680 * an unknown tag. This is the exit from the loop on the
2681 * first unknown tag. It is a successful exit.
2682 */
2683 uReturn = QCBOR_SUCCESS;
2684 break;
2685 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002686 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002687
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002688 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002689 /* Error exit from the loop */
2690 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002691 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002692
2693 /* A tag was successfully processed, shift it out of the list of
2694 * tags returned. This is the loop increment.
2695 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002696 QCBOR_Private_ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002697 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002698#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002699
2700Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002701 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002702}
2703
2704
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002705/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002706 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002707 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002708QCBORError
2709QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2710{
2711 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002712 uErr = QCBORDecode_Private_GetNextTagContent(pMe, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002713 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002714 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2715 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2716 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002717 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002718}
2719
2720
2721/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002722 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002723 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002724QCBORError
2725QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2726{
2727 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2728 const UsefulInputBuf Save = pMe->InBuf;
2729
2730 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2731
2732 pMe->nesting = SaveNesting;
2733 pMe->InBuf = Save;
2734
2735 return uErr;
2736}
2737
2738
2739/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002740 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002741 */
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002742void
2743QCBORDecode_VPeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2744{
2745 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladef00b8be2024-03-08 10:34:33 -08002746 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2747 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002748 return;
2749 }
2750
2751 pMe->uLastError = (uint8_t)QCBORDecode_PeekNext(pMe, pDecodedItem);
2752}
2753
2754
2755/*
2756 * Public function, see header qcbor/qcbor_decode.h file
2757 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002758void
2759QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002760{
2761 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladef00b8be2024-03-08 10:34:33 -08002762 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2763 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002764 return;
2765 }
2766
2767 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2768}
2769
2770
2771/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002772 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002773 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002774QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002775QCBORDecode_GetNextWithTags(QCBORDecodeContext *pMe,
2776 QCBORItem *pDecodedItem,
2777 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002778{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002779#ifndef QCBOR_DISABLE_TAGS
2780
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002781 QCBORError uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002782
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002783 uReturn = QCBORDecode_GetNext(pMe, pDecodedItem);
2784 if(uReturn != QCBOR_SUCCESS) {
2785 return uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002786 }
2787
2788 if(pTags != NULL) {
2789 pTags->uNumUsed = 0;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002790 /* Reverse the order because pTags is reverse of QCBORItem.uTags. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002791 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2792 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002793 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002794 }
2795 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2796 return QCBOR_ERR_TOO_MANY_TAGS;
2797 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002798 pTags->puTags[pTags->uNumUsed] = QCBORDecode_Private_UnMapTagNumber(pMe,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002799 pTags->uNumUsed++;
2800 }
2801 }
2802
2803 return QCBOR_SUCCESS;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002804
2805#else /* QCBOR_DISABLE_TAGS */
2806 (void)pMe;
2807 (void)pDecodedItem;
2808 (void)pTags;
2809 return QCBOR_ERR_TAGS_DISABLED;
2810#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002811}
2812
2813
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002814/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002815 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302816 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002817bool
2818QCBORDecode_IsTagged(QCBORDecodeContext *pMe,
2819 const QCBORItem *pItem,
2820 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002821{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002822#ifndef QCBOR_DISABLE_TAGS
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002823 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2824 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002825 break;
2826 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002827 if(QCBORDecode_Private_UnMapTagNumber(pMe, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002828 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002829 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002830 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002831#else /* QCBOR_TAGS_DISABLED */
2832 (void)pMe;
2833 (void)pItem;
2834 (void)uTag;
2835#endif /* QCBOR_TAGS_DISABLED */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002836
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002837 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002838}
2839
2840
2841/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002842 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002843 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002844QCBORError
2845QCBORDecode_PartialFinish(QCBORDecodeContext *pMe, size_t *puConsumed)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002846{
Laurence Lundblade87495732021-02-26 10:05:55 -07002847 if(puConsumed != NULL) {
2848 *puConsumed = pMe->InBuf.cursor;
2849 }
2850
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002851 QCBORError uReturn = pMe->uLastError;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002852
2853 if(uReturn != QCBOR_SUCCESS) {
2854 goto Done;
2855 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002856
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002857 /* Error out if all the maps/arrays are not closed out */
2858 if(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002859 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002860 goto Done;
2861 }
2862
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002863 /* Error out if not all the bytes are consumed */
2864 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002865 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002866 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002867
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002868Done:
Laurence Lundblade87495732021-02-26 10:05:55 -07002869 return uReturn;
2870}
2871
2872
2873/*
2874 * Public function, see header qcbor/qcbor_decode.h file
2875 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002876QCBORError
2877QCBORDecode_Finish(QCBORDecodeContext *pMe)
Laurence Lundblade87495732021-02-26 10:05:55 -07002878{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002879#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002880 /* Call the destructor for the string allocator if there is one.
2881 * Always called, even if there are errors; always have to clean up.
2882 */
2883 StringAllocator_Destruct(&(pMe->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002884#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002885
Laurence Lundblade87495732021-02-26 10:05:55 -07002886 return QCBORDecode_PartialFinish(pMe, NULL);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002887}
2888
2889
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002890/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002891 * Public function, see header qcbor/qcbor_decode.h file
2892 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002893uint64_t
2894QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2895 const QCBORItem *pItem,
2896 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002897{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002898#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002899 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2900 return CBOR_TAG_INVALID64;
2901 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002902 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2903 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002904 } else {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002905 return QCBORDecode_Private_UnMapTagNumber(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002906 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002907#else /* QCBOR_DISABLE_TAGS */
2908 (void)pMe;
2909 (void)pItem;
2910 (void)uIndex;
2911
2912 return CBOR_TAG_INVALID64;
2913#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002914}
2915
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002916
Laurence Lundblade9b334962020-08-27 10:55:53 -07002917/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002918 * Public function, see header qcbor/qcbor_decode.h file
2919 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002920uint64_t
2921QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2922 uint32_t uIndex)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002923{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002924#ifndef QCBOR_DISABLE_TAGS
2925
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002926 if(pMe->uLastError != QCBOR_SUCCESS) {
2927 return CBOR_TAG_INVALID64;
2928 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002929 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2930 return CBOR_TAG_INVALID64;
2931 } else {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002932 return QCBORDecode_Private_UnMapTagNumber(pMe, pMe->uLastTags[uIndex]);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002933 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002934#else /* QCBOR_DISABLE_TAGS */
2935 (void)pMe;
2936 (void)uIndex;
2937
2938 return CBOR_TAG_INVALID64;
2939#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002940}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002941
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002942
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002943
2944
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002945#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002946
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002947/* ===========================================================================
2948 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002949
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002950 This implements a simple sting allocator for indefinite-length
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002951 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2952 implements the function type QCBORStringAllocate and allows easy
2953 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002954
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002955 This particular allocator is built-in for convenience. The caller
2956 can implement their own. All of this following code will get
2957 dead-stripped if QCBORDecode_SetMemPool() is not called.
2958
2959 This is a very primitive memory allocator. It does not track
2960 individual allocations, only a high-water mark. A free or
2961 reallocation must be of the last chunk allocated.
2962
2963 The size of the pool and offset to free memory are packed into the
2964 first 8 bytes of the memory pool so we don't have to keep them in
2965 the decode context. Since the address of the pool may not be
2966 aligned, they have to be packed and unpacked as if they were
2967 serialized data of the wire or such.
2968
2969 The sizes packed in are uint32_t to be the same on all CPU types
2970 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002971 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002972
2973
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002974static int
Laurence Lundbladeee851742020-01-08 08:37:05 -08002975MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002976{
2977 // Use of UsefulInputBuf is overkill, but it is convenient.
2978 UsefulInputBuf UIB;
2979
Laurence Lundbladeee851742020-01-08 08:37:05 -08002980 // Just assume the size here. It was checked during SetUp so
2981 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002982 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002983 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2984 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2985 return UsefulInputBuf_GetError(&UIB);
2986}
2987
2988
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002989static int
Laurence Lundbladeee851742020-01-08 08:37:05 -08002990MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002991{
2992 // Use of UsefulOutBuf is overkill, but convenient. The
2993 // length check performed here is useful.
2994 UsefulOutBuf UOB;
2995
2996 UsefulOutBuf_Init(&UOB, Pool);
2997 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2998 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2999 return UsefulOutBuf_GetError(&UOB);
3000}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003001
3002
3003/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003004 Internal function for an allocation, reallocation free and destuct.
3005
3006 Having only one function rather than one each per mode saves space in
3007 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003008
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003009 Code Reviewers: THIS FUNCTION DOES POINTER MATH
3010 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08003011static UsefulBuf
3012MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003013{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003014 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003015
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003016 uint32_t uPoolSize;
3017 uint32_t uFreeOffset;
3018
3019 if(uNewSize > UINT32_MAX) {
3020 // This allocator is only good up to 4GB. This check should
3021 // optimize out if sizeof(size_t) == sizeof(uint32_t)
3022 goto Done;
3023 }
3024 const uint32_t uNewSize32 = (uint32_t)uNewSize;
3025
3026 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
3027 goto Done;
3028 }
3029
3030 if(uNewSize) {
3031 if(pMem) {
3032 // REALLOCATION MODE
3033 // Calculate pointer to the end of the memory pool. It is
3034 // assumed that pPool + uPoolSize won't wrap around by
3035 // assuming the caller won't pass a pool buffer in that is
3036 // not in legitimate memory space.
3037 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
3038
3039 // Check that the pointer for reallocation is in the range of the
3040 // pool. This also makes sure that pointer math further down
3041 // doesn't wrap under or over.
3042 if(pMem >= pPool && pMem < pPoolEnd) {
3043 // Offset to start of chunk for reallocation. This won't
3044 // wrap under because of check that pMem >= pPool. Cast
3045 // is safe because the pool is always less than UINT32_MAX
3046 // because of check in QCBORDecode_SetMemPool().
3047 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
3048
3049 // Check to see if the allocation will fit. uPoolSize -
3050 // uMemOffset will not wrap under because of check that
3051 // pMem is in the range of the uPoolSize by check above.
3052 if(uNewSize <= uPoolSize - uMemOffset) {
3053 ReturnValue.ptr = pMem;
3054 ReturnValue.len = uNewSize;
3055
3056 // Addition won't wrap around over because uNewSize was
3057 // checked to be sure it is less than the pool size.
3058 uFreeOffset = uMemOffset + uNewSize32;
3059 }
3060 }
3061 } else {
3062 // ALLOCATION MODE
3063 // uPoolSize - uFreeOffset will not underflow because this
3064 // pool implementation makes sure uFreeOffset is always
3065 // smaller than uPoolSize through this check here and
3066 // reallocation case.
3067 if(uNewSize <= uPoolSize - uFreeOffset) {
3068 ReturnValue.len = uNewSize;
3069 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08003070 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003071 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003072 }
3073 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003074 if(pMem) {
3075 // FREE MODE
3076 // Cast is safe because of limit on pool size in
3077 // QCBORDecode_SetMemPool()
3078 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
3079 } else {
3080 // DESTRUCT MODE
3081 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003082 }
3083 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003084
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003085 UsefulBuf Pool = {pPool, uPoolSize};
3086 MemPool_Pack(Pool, uFreeOffset);
3087
3088Done:
3089 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003090}
3091
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003092
Laurence Lundbladef6531662018-12-04 10:42:22 +09003093/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003094 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09003095 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003096QCBORError
3097QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
3098 UsefulBuf Pool,
3099 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003100{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003101 // The pool size and free mem offset are packed into the beginning
Dave Thaler93c01182022-08-06 15:08:35 -04003102 // of the pool memory. This compile time check makes sure the
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003103 // constant in the header is correct. This check should optimize
3104 // down to nothing.
Dave Thaler93c01182022-08-06 15:08:35 -04003105#ifdef _MSC_VER
3106#pragma warning(push)
3107#pragma warning(disable:4127) // conditional expression is constant
3108#endif
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003109 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003110 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003111 }
Dave Thaler93c01182022-08-06 15:08:35 -04003112#ifdef _MSC_VER
3113#pragma warning(pop)
3114#endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003115
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003116 // The pool size and free offset packed in to the beginning of pool
3117 // memory are only 32-bits. This check will optimize out on 32-bit
3118 // machines.
3119 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003120 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003121 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003122
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003123 // This checks that the pool buffer given is big enough.
3124 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003125 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003126 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003127
Laurence Lundblade3427dee2021-06-20 11:11:24 -07003128 QCBORDecode_SetUpAllocator(pMe, MemPool_Function, Pool.ptr, bAllStrings);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003129
Laurence Lundblade30816f22018-11-10 13:40:22 +07003130 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003131}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08003132#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003133
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003134
3135
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003136static void
3137QCBORDecode_Private_CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07003138{
Laurence Lundblade37286c02022-09-03 10:05:02 -07003139#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade9b334962020-08-27 10:55:53 -07003140 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
Laurence Lundblade37286c02022-09-03 10:05:02 -07003141#else
3142 (void)pMe;
3143 (void)pItem;
3144#endif
Laurence Lundblade9b334962020-08-27 10:55:53 -07003145}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003146
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003147
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003148/**
3149 * @brief Consume an entire map or array including its contents.
3150 *
3151 * @param[in] pMe The decoder context.
3152 * @param[in] pItemToConsume The array/map whose contents are to be
3153 * consumed.
3154 * @param[out] puNextNestLevel The next nesting level after the item was
3155 * fully consumed.
3156 *
3157 * This may be called when @c pItemToConsume is not an array or
3158 * map. In that case, this is just a pass through for @c puNextNestLevel
3159 * since there is nothing to do.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003160 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003161static QCBORError
3162QCBORDecode_Private_ConsumeItem(QCBORDecodeContext *pMe,
3163 const QCBORItem *pItemToConsume,
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003164 bool *pbBreak,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003165 uint8_t *puNextNestLevel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003166{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003167 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003168 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003169
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003170 /* If it is a map or array, this will tell if it is empty. */
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003171 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
3172
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003173 if(QCBORItem_IsMapOrArray(*pItemToConsume) && !bIsEmpty) {
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003174 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003175
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003176 /* This works for definite- and indefinite-length maps and
3177 * arrays by using the nesting level
Laurence Lundblade1341c592020-04-11 14:19:05 -07003178 */
3179 do {
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003180 uReturn = QCBORDecode_Private_GetNextMapOrArray(pMe, pbBreak, &Item);
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003181 if(QCBORDecode_IsUnrecoverableError(uReturn) ||
3182 uReturn == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003183 goto Done;
3184 }
3185 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003186
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003187 *puNextNestLevel = Item.uNextNestLevel;
3188
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003189 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003190
Laurence Lundblade1341c592020-04-11 14:19:05 -07003191 } else {
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003192 /* pItemToConsume is not a map or array. Just pass the nesting
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003193 * level through. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003194 *puNextNestLevel = pItemToConsume->uNextNestLevel;
3195
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003196 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003197 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003198
3199Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003200 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003201}
3202
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003203
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003204/*
3205 * Public function, see header qcbor/qcbor_decode.h file
3206 */
3207void
3208QCBORDecode_VGetNextConsume(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003209{
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003210 QCBORDecode_VGetNext(pMe, pDecodedItem);
3211
3212 if(pMe->uLastError == QCBOR_SUCCESS) {
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003213 pMe->uLastError = (uint8_t)QCBORDecode_Private_ConsumeItem(pMe, pDecodedItem, NULL,
Máté Tóth-Pálc6d59682021-05-26 18:55:30 +02003214 &pDecodedItem->uNextNestLevel);
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003215 }
3216}
3217
3218
Laurence Lundblade11654912024-05-09 11:49:24 -07003219/*
3220 * Public function, see header qcbor/qcbor_decode.h file
3221 */
Laurence Lundblade535bb5e2024-06-16 12:06:32 -07003222QCBORError
3223QCBORDecode_EndCheck(QCBORDecodeContext *pMe)
Laurence Lundblade11654912024-05-09 11:49:24 -07003224{
Laurence Lundblade535bb5e2024-06-16 12:06:32 -07003225 size_t uCursorOffset;
3226 QCBORError uErr;
Laurence Lundblade11654912024-05-09 11:49:24 -07003227
Laurence Lundblade535bb5e2024-06-16 12:06:32 -07003228 uErr = QCBORDecode_GetError(pMe);
3229 if(uErr != QCBOR_SUCCESS) {
3230 return uErr;
Laurence Lundblade11654912024-05-09 11:49:24 -07003231 }
3232
3233 uCursorOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
3234
3235 if(uCursorOffset == UsefulInputBuf_GetBufferLength(&(pMe->InBuf))) {
Laurence Lundblade535bb5e2024-06-16 12:06:32 -07003236 return QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade11654912024-05-09 11:49:24 -07003237 }
Laurence Lundblade535bb5e2024-06-16 12:06:32 -07003238
3239 return QCBOR_SUCCESS;
Laurence Lundblade11654912024-05-09 11:49:24 -07003240}
3241
3242
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003243/**
3244 * @brief Rewind cursor to start as if map or array were just entered.
3245 *
3246 * @param[in] pMe The decoding context
3247 *
3248 * This affects the nesting tracking and the UsefulInputBuf.
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003249 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003250static void
3251QCBORDecode_Private_RewindMapOrArray(QCBORDecodeContext *pMe)
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003252{
3253 /* Reset nesting tracking to the deepest bounded level */
3254 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
3255
3256 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3257
3258 /* Reposition traversal cursor to the start of the map/array */
3259 UsefulInputBuf_Seek(&(pMe->InBuf),
3260 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
3261}
3262
3263
3264/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003265 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003266 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003267void
3268QCBORDecode_Rewind(QCBORDecodeContext *pMe)
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003269{
3270 if(pMe->nesting.pCurrentBounded != NULL) {
3271 /* In a bounded map, array or bstr-wrapped CBOR */
3272
3273 if(DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
3274 /* In bstr-wrapped CBOR. */
3275
3276 /* Reposition traversal cursor to start of wrapping byte string */
3277 UsefulInputBuf_Seek(&(pMe->InBuf),
3278 pMe->nesting.pCurrentBounded->u.bs.uBstrStartOffset);
3279 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
3280
3281 } else {
3282 /* In a map or array */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003283 QCBORDecode_Private_RewindMapOrArray(pMe);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003284 }
3285
3286 } else {
3287 /* Not in anything bounded */
3288
3289 /* Reposition traversal cursor to the start of input CBOR */
3290 UsefulInputBuf_Seek(&(pMe->InBuf), 0ULL);
3291
3292 /* Reset nesting tracking to beginning of input. */
3293 DecodeNesting_Init(&(pMe->nesting));
3294 }
3295
3296 pMe->uLastError = QCBOR_SUCCESS;
3297}
3298
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003299
Laurence Lundblade9b334962020-08-27 10:55:53 -07003300
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003301
3302
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003303typedef struct {
3304 void *pCBContext;
3305 QCBORItemCallback pfCallback;
3306} MapSearchCallBack;
3307
3308typedef struct {
3309 size_t uStartOffset;
3310 uint16_t uItemCount;
3311} MapSearchInfo;
3312
3313
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003314/**
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003315 * @brief Search a map for a set of items.
3316 *
3317 * @param[in] pMe The decode context to search.
3318 * @param[in,out] pItemArray The items to search for and the items found.
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003319 * @param[out] pInfo Several bits of meta-info returned by search.
3320 * @param[in] pCallBack Callback object or @c NULL.
3321 * TODO: fix params
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003322 *
3323 * @retval QCBOR_ERR_NOT_ENTERED Trying to search without entering a map.
3324 *
3325 * @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
3326 * were found for one of the labels being
3327 * search for. This duplicate detection is
3328 * only performed for items in pItemArray,
3329 * not every item in the map.
3330 *
3331 * @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
3332 * wrong for the matchd label.
3333 *
3334 * @retval Also errors returned by QCBORDecode_GetNext().
3335 *
3336 * On input, \c pItemArray contains a list of labels and data types of
3337 * items to be found.
3338 *
3339 * On output, the fully retrieved items are filled in with values and
3340 * such. The label was matched, so it never changes.
3341 *
3342 * If an item was not found, its data type is set to @ref QCBOR_TYPE_NONE.
3343 *
3344 * This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003345 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003346static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003347QCBORDecode_Private_MapSearch(QCBORDecodeContext *pMe,
3348 QCBORItem *pItemArray,
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003349 MapSearchInfo *pInfo,
3350 MapSearchCallBack *pCallBack)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003351{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003352 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003353 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07003354
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003355 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003356 uReturn = pMe->uLastError;
3357 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003358 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003359
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003360 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003361 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
3362 /* QCBOR_TYPE_NONE as first item indicates just looking
3363 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003364 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
3365 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003366 }
3367
Laurence Lundblade085d7952020-07-24 10:26:30 -07003368 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
3369 // It is an empty bounded array or map
3370 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
3371 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003372 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07003373 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003374 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003375 // Nothing is ever found in an empty array or map. All items
3376 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07003377 uReturn = QCBOR_SUCCESS;
3378 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003379 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003380 }
3381
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003382 QCBORDecodeNesting SaveNesting;
Laurence Lundblade11654912024-05-09 11:49:24 -07003383 size_t uSavePos = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade085d7952020-07-24 10:26:30 -07003384 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
3385
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003386 /* Reposition to search from the start of the map / array */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003387 QCBORDecode_Private_RewindMapOrArray(pMe);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003388
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003389 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003390 Loop over all the items in the map or array. Each item
3391 could be a map or array, but label matching is only at
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003392 the main level. This handles definite- and indefinite-
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003393 length maps and arrays. The only reason this is ever
3394 called on arrays is to find their end position.
3395
3396 This will always run over all items in order to do
3397 duplicate detection.
3398
3399 This will exit with failure if it encounters an
3400 unrecoverable error, but continue on for recoverable
3401 errors.
3402
3403 If a recoverable error occurs on a matched item, then
3404 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003405 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07003406 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003407 if(pInfo) {
3408 pInfo->uItemCount = 0;
3409 }
Máté Tóth-Pál2f2aa5f2021-05-17 21:35:09 +02003410 uint8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003411 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003412 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07003413 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003414
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003415 /* Get the item */
3416 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003417 QCBORError uResult = QCBORDecode_Private_GetNextTagContent(pMe, &Item);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003418 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003419 /* The map/array can't be decoded when unrecoverable errors occur */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003420 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003421 goto Done;
3422 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003423 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003424 /* Unexpected end of map or array. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003425 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003426 goto Done;
3427 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003428
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003429 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003430 bool bMatched = false;
3431 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003432 if(QCBORItem_MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003433 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003434 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
3435 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003436 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003437 }
Laurence Lundblade63926052021-03-29 16:05:51 -07003438 if(uResult != QCBOR_SUCCESS) {
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003439 /* The label matches, but the data item is in error.
3440 * It is OK to have recoverable errors on items that are not
3441 * matched. */
Laurence Lundblade63926052021-03-29 16:05:51 -07003442 uReturn = uResult;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003443 goto Done;
3444 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003445 if(!QCBORItem_MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade63926052021-03-29 16:05:51 -07003446 /* The data item is not of the type(s) requested */
3447 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003448 goto Done;
3449 }
3450
Laurence Lundblade1341c592020-04-11 14:19:05 -07003451 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003452 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003453 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003454 if(pInfo) {
3455 pInfo->uStartOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003456 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003457 bMatched = true;
3458 }
3459 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003460
3461
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003462 if(!bMatched && pCallBack != NULL) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003463 /*
3464 Call the callback on unmatched labels.
3465 (It is tempting to do duplicate detection here, but that would
3466 require dynamic memory allocation because the number of labels
3467 that might be encountered is unbounded.)
3468 */
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003469 uReturn = (*(pCallBack->pfCallback))(pCallBack->pCBContext, &Item);
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003470 if(uReturn != QCBOR_SUCCESS) {
3471 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003472 }
3473 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003474
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003475 /*
3476 Consume the item whether matched or not. This
3477 does the work of traversing maps and array and
3478 everything in them. In this loop only the
3479 items at the current nesting level are examined
3480 to match the labels.
3481 */
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003482 uReturn = QCBORDecode_Private_ConsumeItem(pMe, &Item, NULL, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003483 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003484 goto Done;
3485 }
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003486
3487 if(pInfo) {
3488 pInfo->uItemCount++;
3489 }
3490
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003491 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003492
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003493 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003494
3495 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003496
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003497 // Check here makes sure that this won't accidentally be
3498 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003499 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003500 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
3501 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003502 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
3503 goto Done;
3504 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003505 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
3506 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003507
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003508 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003509 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundblade11654912024-05-09 11:49:24 -07003510 UsefulInputBuf_Seek(&(pMe->InBuf), uSavePos);
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003511
3512 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003513 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07003514 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003515 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003516 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
3517 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003518 }
3519 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003520
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003521 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003522}
3523
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003524
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003525/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003526 * Public function, see header qcbor/qcbor_decode.h file
3527 */
3528void
3529QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
3530 int64_t nLabel,
3531 uint8_t uQcborType,
3532 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003533{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003534 if(pMe->uLastError != QCBOR_SUCCESS) {
3535 return;
3536 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003537
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003538 QCBORItem OneItemSeach[2];
3539 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3540 OneItemSeach[0].label.int64 = nLabel;
3541 OneItemSeach[0].uDataType = uQcborType;
3542 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003543
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003544 QCBORError uReturn = QCBORDecode_Private_MapSearch(pMe, OneItemSeach, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003545
3546 *pItem = OneItemSeach[0];
3547
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003548 if(uReturn != QCBOR_SUCCESS) {
3549 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003550 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003551 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003552 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003553 }
3554
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003555 Done:
3556 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003557}
3558
3559
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003560/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003561 * Public function, see header qcbor/qcbor_decode.h file
3562 */
3563void
3564QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
3565 const char *szLabel,
3566 uint8_t uQcborType,
3567 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003568{
Laurence Lundbladeda095972020-06-06 18:35:33 -07003569 if(pMe->uLastError != QCBOR_SUCCESS) {
3570 return;
3571 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003572
Laurence Lundbladeec290b82024-06-10 11:10:54 -07003573#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003574 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003575 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3576 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3577 OneItemSeach[0].uDataType = uQcborType;
3578 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003579
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003580 QCBORError uReturn = QCBORDecode_Private_MapSearch(pMe, OneItemSeach, NULL, NULL);
3581
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003582 if(uReturn != QCBOR_SUCCESS) {
3583 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003584 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003585 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003586 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003587 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003588 }
3589
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003590 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003591Done:
Laurence Lundbladeec290b82024-06-10 11:10:54 -07003592
3593#else
3594 (void)pMe;
3595 (void)szLabel;
3596 (void)uQcborType;
3597 (void)pItem;
3598 QCBORError uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
3599#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
3600
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003601 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003602}
3603
3604
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003605
3606/**
3607 * @brief Semi-private. Get pointer, length and item for an array or map.
3608 *
3609 * @param[in] pMe The decode context.
3610 * @param[in] uType CBOR major type, either array/map.
3611 * @param[out] pItem The item for the array/map.
3612 * @param[out] pEncodedCBOR Pointer and length of the encoded map or array.
3613 *
3614 * The next item to be decoded must be a map or array as specified by \c uType.
3615 *
3616 * \c pItem will be filled in with the label and tags of the array or map
3617 * in addition to \c pEncodedCBOR giving the pointer and length of the
3618 * encoded CBOR.
3619 *
3620 * When this is complete, the traversal cursor is at the end of the array or
3621 * map that was retrieved.
3622 */
3623void
3624QCBORDecode_Private_GetArrayOrMap(QCBORDecodeContext *pMe,
3625 const uint8_t uType,
3626 QCBORItem *pItem,
3627 UsefulBufC *pEncodedCBOR)
3628{
3629 QCBORError uErr;
3630 uint8_t uNestLevel;
3631 size_t uStartingCursor;
3632 size_t uStartOfReturned;
3633 size_t uEndOfReturned;
3634 size_t uTempSaveCursor;
3635 bool bInMap;
3636 QCBORItem LabelItem;
3637 bool EndedByBreak;
3638
3639 uStartingCursor = UsefulInputBuf_Tell(&(pMe->InBuf));
3640 bInMap = DecodeNesting_IsCurrentTypeMap(&(pMe->nesting));
3641
3642 /* Could call GetNext here, but don't need to because this
3643 * is only interested in arrays and maps. */
3644 uErr = QCBORDecode_Private_GetNextMapOrArray(pMe, NULL, pItem);
3645 if(uErr != QCBOR_SUCCESS) {
3646 pMe->uLastError = (uint8_t)uErr;
3647 return;
3648 }
3649
Laurence Lundblade5db34da2024-05-30 03:14:35 -07003650 uint8_t uItemDataType = pItem->uDataType;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07003651#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
Laurence Lundblade5db34da2024-05-30 03:14:35 -07003652 if(uItemDataType == QCBOR_TYPE_MAP_AS_ARRAY) {
3653 uItemDataType = QCBOR_TYPE_ARRAY;
3654 }
Laurence Lundbladeec290b82024-06-10 11:10:54 -07003655#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
Laurence Lundblade5db34da2024-05-30 03:14:35 -07003656
3657 if(uItemDataType != uType) {
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003658 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
3659 return;
3660 }
3661
3662 if(bInMap) {
3663 /* If the item is in a map, the start of the array/map
3664 * itself, not the label, must be found. Do this by
3665 * rewinding to the starting position and fetching
3666 * just the label data item. QCBORDecode_Private_GetNextTagNumber()
3667 * doesn't do any of the array/map item counting or nesting
3668 * level tracking. Used here it will just fetech the label
3669 * data item.
3670 *
3671 * Have to save the cursor and put it back to the position
3672 * after the full item once the label as been fetched by
3673 * itself.
3674 */
3675 uTempSaveCursor = UsefulInputBuf_Tell(&(pMe->InBuf));
3676 UsefulInputBuf_Seek(&(pMe->InBuf), uStartingCursor);
3677
3678 /* Item has been fetched once so safe to ignore error */
3679 (void)QCBORDecode_Private_GetNextTagNumber(pMe, &LabelItem);
3680
3681 uStartOfReturned = UsefulInputBuf_Tell(&(pMe->InBuf));
3682 UsefulInputBuf_Seek(&(pMe->InBuf), uTempSaveCursor);
3683 } else {
3684 uStartOfReturned = uStartingCursor;
3685 }
3686
3687 /* Consume the entire array/map to find the end */
3688 uErr = QCBORDecode_Private_ConsumeItem(pMe, pItem, &EndedByBreak, &uNestLevel);
3689 if(uErr != QCBOR_SUCCESS) {
3690 pMe->uLastError = (uint8_t)uErr;
3691 goto Done;
3692 }
3693
3694 /* Fill in returned values */
3695 uEndOfReturned = UsefulInputBuf_Tell(&(pMe->InBuf));
3696 if(EndedByBreak) {
3697 /* When ascending nesting levels, a break for the level above
3698 * was consumed. That break is not a part of what is consumed here. */
3699 uEndOfReturned--;
3700 }
3701 pEncodedCBOR->ptr = UsefulInputBuf_OffsetToPointer(&(pMe->InBuf), uStartOfReturned);
3702 pEncodedCBOR->len = uEndOfReturned - uStartOfReturned;
3703
3704Done:
3705 return;
3706}
3707
3708
3709/**
3710 * @brief Semi-private. Get pointer, length and item count of an array or map.
3711 *
3712 * @param[in] pMe The decode context.
3713 * @param[in] pTarget The label and type of the array or map to retrieve.
3714 * @param[out] pItem The item for the array/map.
3715 * @param[out] pEncodedCBOR Pointer and length of the encoded map or array.
3716 *
3717 * The next item to be decoded must be a map or array as specified by \c uType.
3718 *
3719 * When this is complete, the traversal cursor is unchanged.
3720 */void
3721QCBORDecode_Private_SearchAndGetArrayOrMap(QCBORDecodeContext *pMe,
3722 QCBORItem *pTarget,
3723 QCBORItem *pItem,
3724 UsefulBufC *pEncodedCBOR)
3725{
3726 MapSearchInfo Info;
3727 QCBORDecodeNesting SaveNesting;
3728 size_t uSaveCursor;
3729
3730 pMe->uLastError = (uint8_t)QCBORDecode_Private_MapSearch(pMe, pTarget, &Info, NULL);
3731 if(pMe->uLastError != QCBOR_SUCCESS) {
3732 return;
3733 }
3734
3735 /* Save the whole position of things so they can be restored.
3736 * so the cursor position is unchanged by this operation, like
3737 * all the other GetXxxxInMap() operations. */
3738 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
3739 uSaveCursor = UsefulInputBuf_Tell(&(pMe->InBuf));
3740
3741 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3742 UsefulInputBuf_Seek(&(pMe->InBuf), Info.uStartOffset);
3743 QCBORDecode_Private_GetArrayOrMap(pMe, pTarget[0].uDataType, pItem, pEncodedCBOR);
3744
3745 UsefulInputBuf_Seek(&(pMe->InBuf), uSaveCursor);
3746 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
3747}
3748
3749
3750
3751
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003752/**
3753 * @brief Is a QCBOR_TYPE in the type list?
3754 *
3755 * @param[in] uDataType Type to check for.
3756 * @param[in] puTypeList List to check.
3757 *
3758 * @retval QCBOR_SUCCESS If in the list.
3759 * @retval QCBOR_ERR_UNEXPECTED_TYPE Not in the list.
3760 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07003761static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003762QCBOR_Private_CheckTypeList(const int uDataType,
3763 const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003764{
3765 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08003766 if(uDataType == puTypeList[i]) { /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003767 return QCBOR_SUCCESS;
3768 }
3769 }
3770 return QCBOR_ERR_UNEXPECTED_TYPE;
3771}
3772
Laurence Lundblade67257dc2020-07-27 03:33:37 -07003773
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003774/**
Laurence Lundblade37286c02022-09-03 10:05:02 -07003775 * Match a tag/type specification against the type of the item.
3776 *
3777 * @param[in] TagSpec Specification for matching tags.
3778 * @param[in] pItem The item to check.
3779 *
3780 * @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
3781 * @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
3782 *
3783 * This checks the item data type of untagged items as well as of
3784 * tagged items against a specification to see if decoding should
3785 * proceed.
3786 *
3787 * This relies on the automatic tag decoding done by QCBOR that turns
3788 * tag numbers into particular QCBOR_TYPEs so there is no actual
3789 * comparsion of tag numbers, just of QCBOR_TYPEs.
3790 *
3791 * This checks the data item type as possibly representing the tag
3792 * number or as the tag content type.
3793 *
3794 * If QCBOR_DISABLE_TAGS is #defined, this primarily checks the item
3795 * data type against the allowed tag content types. It will also error out
3796 * if the caller tries to require a tag because there is no way that can
3797 * ever be fulfilled.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003798 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07003799static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003800QCBOR_Private_CheckTagRequirement(const QCBOR_Private_TagSpec TagSpec,
3801 const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07003802{
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08003803 const int nItemType = pItem->uDataType; /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade37286c02022-09-03 10:05:02 -07003804 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
3805
3806#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08003807 /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003808 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
3809 pItem->uTags[0] != CBOR_TAG_INVALID16) {
3810 /* There are tags that QCBOR couldn't process on this item and
Laurence Lundblade37286c02022-09-03 10:05:02 -07003811 * the caller has told us there should not be.
3812 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003813 return QCBOR_ERR_UNEXPECTED_TYPE;
3814 }
3815
Laurence Lundblade9b334962020-08-27 10:55:53 -07003816 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
Laurence Lundblade37286c02022-09-03 10:05:02 -07003817 /* Must match the tag number and only the tag */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003818 return QCBOR_Private_CheckTypeList(nItemType, TagSpec.uTaggedTypes);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003819 }
3820
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003821 QCBORError uReturn = QCBOR_Private_CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003822 if(uReturn == QCBOR_SUCCESS) {
3823 return QCBOR_SUCCESS;
3824 }
3825
3826 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
3827 /* Must match the content type and only the content type.
Laurence Lundblade37286c02022-09-03 10:05:02 -07003828 * There was no match just above so it is a fail. */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003829 return QCBOR_ERR_UNEXPECTED_TYPE;
3830 }
3831
Laurence Lundblade37286c02022-09-03 10:05:02 -07003832 /* QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG: If here it can match either the tag or the content
3833 * and it hasn't matched the content, so the end
3834 * result is whether it matches the tag. This is
3835 * the tag optional case that the CBOR standard discourages.
3836 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003837
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003838 return QCBOR_Private_CheckTypeList(nItemType, TagSpec.uTaggedTypes);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003839
Laurence Lundblade37286c02022-09-03 10:05:02 -07003840#else /* QCBOR_DISABLE_TAGS */
3841 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
3842 return QCBOR_ERR_UNEXPECTED_TYPE;
3843 }
3844
Laurence Lundblade0f01ac62024-02-18 23:07:07 -07003845 return QCBOR_Private_CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
Laurence Lundblade37286c02022-09-03 10:05:02 -07003846
3847#endif /* QCBOR_DISABLE_TAGS */
3848}
Laurence Lundblade9b334962020-08-27 10:55:53 -07003849
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003850
3851/**
3852 * @brief Get an item by label to match a tag specification.
3853 *
3854 * @param[in] pMe The decode context.
3855 * @param[in] nLabel The label to search map for.
3856 * @param[in] TagSpec The tag number specification to match.
3857 * @param[out] pItem The item found.
3858 *
3859 * This finds the item with the given label in currently open
3860 * map. Then checks that its tag number and types matches the tag
3861 * specification. If not, an error is set in the decode context.
3862 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003863static void
3864QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
3865 const int64_t nLabel,
3866 const QCBOR_Private_TagSpec TagSpec,
3867 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003868{
3869 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
3870 if(pMe->uLastError != QCBOR_SUCCESS) {
3871 return;
3872 }
3873
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003874 pMe->uLastError = (uint8_t)QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003875}
3876
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003877
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003878/**
3879 * @brief Get an item by label to match a tag specification.
3880 *
3881 * @param[in] pMe The decode context.
3882 * @param[in] szLabel The label to search map for.
3883 * @param[in] TagSpec The tag number specification to match.
3884 * @param[out] pItem The item found.
3885 *
3886 * This finds the item with the given label in currently open
3887 * map. Then checks that its tag number and types matches the tag
3888 * specification. If not, an error is set in the decode context.
3889 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003890static void
3891QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
3892 const char *szLabel,
3893 const QCBOR_Private_TagSpec TagSpec,
3894 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003895{
3896 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
3897 if(pMe->uLastError != QCBOR_SUCCESS) {
3898 return;
3899 }
3900
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003901 pMe->uLastError = (uint8_t)QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003902}
3903
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003904
3905/**
3906 * @brief Semi-private to get an string by label to match a tag specification.
3907 *
3908 * @param[in] pMe The decode context.
3909 * @param[in] nLabel The label to search map for.
3910 * @param[in] TagSpec The tag number specification to match.
3911 * @param[out] pString The string found.
3912 *
3913 * This finds the string with the given label in currently open
3914 * map. Then checks that its tag number and types matches the tag
3915 * specification. If not, an error is set in the decode context.
3916 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003917void
3918QCBORDecode_Private_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
3919 const int64_t nLabel,
3920 const QCBOR_Private_TagSpec TagSpec,
3921 UsefulBufC *pString)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003922{
3923 QCBORItem Item;
3924 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
3925 if(pMe->uLastError == QCBOR_SUCCESS) {
3926 *pString = Item.val.string;
3927 }
3928}
3929
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003930
3931/**
3932 * @brief Semi-private to get an string by label to match a tag specification.
3933 *
3934 * @param[in] pMe The decode context.
3935 * @param[in] szLabel The label to search map for.
3936 * @param[in] TagSpec The tag number specification to match.
3937 * @param[out] pString The string found.
3938 *
3939 * This finds the string with the given label in currently open
3940 * map. Then checks that its tag number and types matches the tag
3941 * specification. If not, an error is set in the decode context.
3942 */void
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003943QCBORDecode_Private_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
3944 const char * szLabel,
3945 const QCBOR_Private_TagSpec TagSpec,
3946 UsefulBufC *pString)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003947{
3948 QCBORItem Item;
3949 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
3950 if(pMe->uLastError == QCBOR_SUCCESS) {
3951 *pString = Item.val.string;
3952 }
3953}
Laurence Lundblade1341c592020-04-11 14:19:05 -07003954
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003955
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003956/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003957 * Public function, see header qcbor/qcbor_decode.h file
3958 */
3959void
3960QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003961{
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003962 QCBORError uErr = QCBORDecode_Private_MapSearch(pMe, pItemList, NULL, NULL);
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003963 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003964}
3965
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003966/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003967 * Public function, see header qcbor/qcbor_decode.h file
3968 */
3969void
3970QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3971 QCBORItem *pItemList,
3972 void *pCallbackCtx,
3973 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003974{
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003975 MapSearchCallBack CallBack;
3976 CallBack.pCBContext = pCallbackCtx;
3977 CallBack.pfCallback = pfCB;
3978
3979 QCBORError uErr = QCBORDecode_Private_MapSearch(pMe, pItemList, NULL, &CallBack);
3980
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003981 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003982}
3983
3984
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003985/**
3986 * @brief Search for a map/array by label and enter it
3987 *
3988 * @param[in] pMe The decode context.
3989 * @param[in] pSearch The map/array to search for.
3990 *
3991 * @c pSearch is expected to contain one item of type map or array
3992 * with the label specified. The current bounded map will be searched for
3993 * this and if found will be entered.
3994 *
3995 * If the label is not found, or the item found is not a map or array,
3996 * the error state is set.
3997 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003998static void
3999QCBORDecode_Private_SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07004000{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07004001 // The first item in pSearch is the one that is to be
4002 // entered. It should be the only one filled in. Any other
4003 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07004004 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07004005 return;
4006 }
4007
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07004008 MapSearchInfo Info;
4009 pMe->uLastError = (uint8_t)QCBORDecode_Private_MapSearch(pMe, pSearch, &Info, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07004010 if(pMe->uLastError != QCBOR_SUCCESS) {
4011 return;
4012 }
4013
Laurence Lundblade9b334962020-08-27 10:55:53 -07004014 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07004015 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07004016 return;
4017 }
4018
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004019
4020 /* The map or array was found. Now enter it.
4021 *
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08004022 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
4023 * next item for the pre-order traversal cursor to be the map/array
4024 * found by MapSearch(). The next few lines of code force the
4025 * cursor to that.
4026 *
4027 * There is no need to retain the old cursor because
4028 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
4029 * beginning of the map/array being entered.
4030 *
4031 * The cursor is forced by: 1) setting the input buffer position to
4032 * the item offset found by MapSearch(), 2) setting the map/array
4033 * counter to the total in the map/array, 3) setting the nesting
4034 * level. Setting the map/array counter to the total is not
4035 * strictly correct, but this is OK because this cursor only needs
4036 * to be used to get one item and MapSearch() has already found it
4037 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004038 */
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07004039 UsefulInputBuf_Seek(&(pMe->InBuf), Info.uStartOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004040
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08004041 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
4042
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004043 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07004044
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004045 QCBORDecode_Private_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004046}
4047
4048
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004049/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004050 * Public function, see header qcbor/qcbor_decode.h file
4051 */
4052void
4053QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004054{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07004055 QCBORItem OneItemSeach[2];
4056 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
4057 OneItemSeach[0].label.int64 = nLabel;
4058 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
4059 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07004060
Laurence Lundblade9b334962020-08-27 10:55:53 -07004061 /* The map to enter was found, now finish off entering it. */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004062 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004063}
4064
4065
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004066/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004067 * Public function, see header qcbor/qcbor_decode.h file
4068 */
4069void
4070QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004071{
Laurence Lundbladeec290b82024-06-10 11:10:54 -07004072#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07004073 QCBORItem OneItemSeach[2];
4074 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
4075 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
4076 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
4077 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07004078
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004079 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladeec290b82024-06-10 11:10:54 -07004080#else
4081 (void)szLabel;
4082 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
4083#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004084}
4085
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004086/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004087 * Public function, see header qcbor/qcbor_decode.h file
4088 */
4089void
4090QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07004091{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07004092 QCBORItem OneItemSeach[2];
4093 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
4094 OneItemSeach[0].label.int64 = nLabel;
4095 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
4096 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07004097
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004098 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07004099}
4100
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004101/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004102 * Public function, see header qcbor/qcbor_decode.h file
4103 */
4104void
4105QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundblade34691b92020-05-18 22:25:25 -07004106{
Laurence Lundbladeec290b82024-06-10 11:10:54 -07004107#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07004108 QCBORItem OneItemSeach[2];
4109 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
4110 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
4111 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
4112 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07004113
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004114 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladeec290b82024-06-10 11:10:54 -07004115#else
4116 (void)szLabel;
4117 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
4118#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
Laurence Lundblade1341c592020-04-11 14:19:05 -07004119}
4120
4121
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004122/**
4123 * @brief Semi-private to do the the work for EnterMap() and EnterArray().
4124 *
4125 * @param[in] pMe The decode context
4126 * @param[in] uType QCBOR_TYPE_MAP or QCBOR_TYPE_ARRAY.
4127 * @param[out] pItem The data item for the map or array entered.
4128 *
4129 * The next item in the traversal must be a map or array. This
4130 * consumes that item and does the book keeping to enter the map or
4131 * array.
4132 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004133void
4134QCBORDecode_Private_EnterBoundedMapOrArray(QCBORDecodeContext *pMe,
4135 const uint8_t uType,
4136 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004137{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07004138 QCBORError uErr;
4139
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004140 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07004141 if(pMe->uLastError != QCBOR_SUCCESS) {
4142 // Already in error state; do nothing.
4143 return;
4144 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07004145
Laurence Lundbladed40951e2020-08-28 11:11:14 -07004146 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004147 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07004148 uErr = QCBORDecode_GetNext(pMe, &Item);
4149 if(uErr != QCBOR_SUCCESS) {
4150 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07004151 }
Laurence Lundblade5db34da2024-05-30 03:14:35 -07004152
4153 uint8_t uItemDataType = Item.uDataType;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07004154
4155#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
Laurence Lundblade5db34da2024-05-30 03:14:35 -07004156 if(uItemDataType == QCBOR_TYPE_MAP_AS_ARRAY ) {
4157 uItemDataType = QCBOR_TYPE_ARRAY;
4158 }
Laurence Lundbladeec290b82024-06-10 11:10:54 -07004159#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
4160
Laurence Lundblade5db34da2024-05-30 03:14:35 -07004161 if(uItemDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07004162 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
4163 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07004164 }
4165
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004166 QCBORDecode_Private_CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07004167
4168
Laurence Lundbladef0499502020-08-01 11:55:57 -07004169 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07004170 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004171 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
4172 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07004173 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004174 pMe->nesting.pCurrent->u.ma.uCountCursor++;
4175 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07004176 // Special case to increment nesting level for zero-length maps
4177 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07004178 DecodeNesting_Descend(&(pMe->nesting), uType);
4179 }
4180
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07004181 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004182
Laurence Lundbladec45b5672020-07-25 23:16:36 -07004183 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
4184 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004185
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07004186 if(pItem != NULL) {
4187 *pItem = Item;
4188 }
4189
Laurence Lundbladec45b5672020-07-25 23:16:36 -07004190Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004191 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004192}
4193
Laurence Lundblade02625d42020-06-25 14:41:41 -07004194
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004195/**
4196 * @brief Exit a bounded map, array or bstr (semi-private).
4197 *
4198 * @param[in] pMe Decode context.
4199 * @param[in] uEndOffset The input buffer offset of the end of item exited.
4200 *
4201 * @returns QCBOR_SUCCESS or an error code.
4202 *
4203 * This is the common work for exiting a level that is a bounded map,
4204 * array or bstr wrapped CBOR.
4205 *
4206 * One chunk of work is to set up the pre-order traversal so it is at
4207 * the item just after the bounded map, array or bstr that is being
4208 * exited. This is somewhat complex.
4209 *
4210 * The other work is to level-up the bounded mode to next higest
4211 * bounded mode or the top level if there isn't one.
Laurence Lundblade02625d42020-06-25 14:41:41 -07004212 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004213static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004214QCBORDecode_Private_ExitBoundedLevel(QCBORDecodeContext *pMe,
4215 const uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004216{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004217 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004218
Laurence Lundblade02625d42020-06-25 14:41:41 -07004219 /*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004220 * First the pre-order-traversal byte offset is positioned to the
4221 * item just after the bounded mode item that was just consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07004222 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004223 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
4224
Laurence Lundblade02625d42020-06-25 14:41:41 -07004225 /*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004226 * Next, set the current nesting level to one above the bounded
4227 * level that was just exited.
4228 *
4229 * DecodeNesting_CheckBoundedType() is always called before this
4230 * and makes sure pCurrentBounded is valid.
Laurence Lundblade02625d42020-06-25 14:41:41 -07004231 */
4232 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
4233
4234 /*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004235 * This does the complex work of leveling up the pre-order
4236 * traversal when the end of a map or array or another bounded
4237 * level is reached. It may do nothing, or ascend all the way to
4238 * the top level.
Laurence Lundblade02625d42020-06-25 14:41:41 -07004239 */
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07004240 uErr = QCBORDecode_Private_NestLevelAscender(pMe, NULL, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004241 if(uErr != QCBOR_SUCCESS) {
4242 goto Done;
4243 }
4244
Laurence Lundblade02625d42020-06-25 14:41:41 -07004245 /*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004246 * This makes the next highest bounded level the current bounded
4247 * level. If there is no next highest level, then no bounded mode
4248 * is in effect.
Laurence Lundblade02625d42020-06-25 14:41:41 -07004249 */
4250 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004251
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07004252 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004253
4254Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004255 return uErr;
4256}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004257
Laurence Lundblade02625d42020-06-25 14:41:41 -07004258
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004259/**
4260 * @brief Get started exiting a map or array (semi-private)
4261 *
4262 * @param[in] pMe The decode context
4263 * @param[in] uType QCBOR_TYPE_ARRAY or QCBOR_TYPE_MAP
4264 *
4265 * This does some work for map and array exiting (but not
4266 * bstr exiting). Then QCBORDecode_Private_ExitBoundedLevel()
4267 * is called to do the rest.
4268 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004269void
4270QCBORDecode_Private_ExitBoundedMapOrArray(QCBORDecodeContext *pMe,
4271 const uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004272{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004273 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07004274 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004275 return;
4276 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004277
Laurence Lundblade02625d42020-06-25 14:41:41 -07004278 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004279
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07004280 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07004281 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004282 goto Done;
4283 }
4284
Laurence Lundblade02625d42020-06-25 14:41:41 -07004285 /*
4286 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004287 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07004288 from previous map search, then do a dummy search.
4289 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07004290 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004291 QCBORItem Dummy;
4292 Dummy.uLabelType = QCBOR_TYPE_NONE;
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07004293 uErr = QCBORDecode_Private_MapSearch(pMe, &Dummy, NULL, NULL);
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004294 if(uErr != QCBOR_SUCCESS) {
4295 goto Done;
4296 }
4297 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004298
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004299 uErr = QCBORDecode_Private_ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004300
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004301Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004302 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004303}
4304
4305
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004306/**
4307 * @brief The main work of entering some byte-string wrapped CBOR.
4308 *
4309 * @param[in] pMe The decode context.
4310 * @param[in] pItem The byte string item.
4311 * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX
4312 * @param[out] pBstr Pointer and length of byte string entered.
4313 *
4314 * This is called once the byte string item has been decoded to do all
4315 * the book keeping work for descending a nesting level into the
4316 * nested CBOR.
4317 *
4318 * See QCBORDecode_EnterBstrWrapped() for details on uTagRequirement.
4319 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07004320static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004321QCBORDecode_Private_EnterBstrWrapped(QCBORDecodeContext *pMe,
4322 const QCBORItem *pItem,
4323 const uint8_t uTagRequirement,
4324 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004325{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07004326 if(pBstr) {
4327 *pBstr = NULLUsefulBufC;
4328 }
4329
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004330 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004331 /* Already in error state; do nothing. */
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004332 return pMe->uLastError;
4333 }
4334
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004335 QCBORError uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004336
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004337 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004338 {
4339 uTagRequirement,
4340 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
4341 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4342 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004343
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004344 uError = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004345 if(uError != QCBOR_SUCCESS) {
4346 goto Done;
4347 }
4348
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004349 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004350 /* Reverse the decrement done by GetNext() for the bstr so the
4351 * increment in QCBORDecode_NestLevelAscender() called by
4352 * ExitBoundedLevel() will work right.
4353 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004354 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07004355 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004356
4357 if(pBstr) {
4358 *pBstr = pItem->val.string;
4359 }
4360
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004361 /* This saves the current length of the UsefulInputBuf and then
4362 * narrows the UsefulInputBuf to start and length of the wrapped
4363 * CBOR that is being entered.
4364 *
4365 * Most of these calls are simple inline accessors so this doesn't
4366 * amount to much code.
4367 */
4368
Laurence Lundbladea4308a82020-10-03 18:08:57 -07004369 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004370 /* This check makes the cast of uPreviousLength to uint32_t below safe. */
4371 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07004372 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07004373 goto Done;
4374 }
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004375
4376 const size_t uStartOfBstr = UsefulInputBuf_PointerToOffset(&(pMe->InBuf),
4377 pItem->val.string.ptr);
4378 /* This check makes the cast of uStartOfBstr to uint32_t below safe. */
4379 if(uStartOfBstr == SIZE_MAX || uStartOfBstr > QCBOR_MAX_DECODE_INPUT_SIZE) {
4380 /* This should never happen because pItem->val.string.ptr should
4381 * always be valid since it was just returned.
4382 */
4383 uError = QCBOR_ERR_INPUT_TOO_LARGE;
4384 goto Done;
4385 }
4386
4387 const size_t uEndOfBstr = uStartOfBstr + pItem->val.string.len;
4388
4389 UsefulInputBuf_Seek(&(pMe->InBuf), uStartOfBstr);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07004390 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004391
Laurence Lundblade02625d42020-06-25 14:41:41 -07004392 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07004393 (uint32_t)uPreviousLength,
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004394 (uint32_t)uStartOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004395Done:
4396 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004397}
4398
4399
Laurence Lundblade02625d42020-06-25 14:41:41 -07004400/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004401 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07004402 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004403void
4404QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
4405 const uint8_t uTagRequirement,
4406 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07004407{
4408 if(pMe->uLastError != QCBOR_SUCCESS) {
4409 // Already in error state; do nothing.
4410 return;
4411 }
4412
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004413 /* Get the data item that is the byte string being entered */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004414 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07004415 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4416 if(pMe->uLastError != QCBOR_SUCCESS) {
4417 return;
4418 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07004419
Laurence Lundblade31fddb72024-05-13 13:03:35 -07004420 if(Item.uDataAlloc) {
4421 pMe->uLastError = QCBOR_ERR_CANNOT_ENTER_ALLOCATED_STRING;
4422 return;
4423 }
4424
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004425 pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
4426 &Item,
4427 uTagRequirement,
4428 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07004429}
4430
4431
Laurence Lundblade02625d42020-06-25 14:41:41 -07004432/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004433 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07004434 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004435void
4436QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
4437 const int64_t nLabel,
4438 const uint8_t uTagRequirement,
4439 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004440{
4441 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004442 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004443
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004444 pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
4445 &Item,
4446 uTagRequirement,
4447 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004448}
4449
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004450
Laurence Lundblade02625d42020-06-25 14:41:41 -07004451/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004452 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07004453 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004454void
4455QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
4456 const char *szLabel,
4457 const uint8_t uTagRequirement,
4458 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004459{
4460 QCBORItem Item;
4461 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4462
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004463 pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
4464 &Item,
4465 uTagRequirement,
4466 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004467}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004468
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004469
Laurence Lundblade02625d42020-06-25 14:41:41 -07004470/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004471 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07004472 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004473void
4474QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004475{
Laurence Lundblade02625d42020-06-25 14:41:41 -07004476 if(pMe->uLastError != QCBOR_SUCCESS) {
4477 // Already in error state; do nothing.
4478 return;
4479 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004480
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07004481 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07004482 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07004483 return;
4484 }
4485
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004486 const uint32_t uEndOfBstr = (uint32_t)UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
4487
Laurence Lundblade02625d42020-06-25 14:41:41 -07004488 /*
4489 Reset the length of the UsefulInputBuf to what it was before
4490 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004491 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07004492 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004493 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004494
4495
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004496 QCBORError uErr = QCBORDecode_Private_ExitBoundedLevel(pMe, uEndOfBstr);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004497 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004498}
4499
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004500
Laurence Lundbladee6430642020-03-14 21:15:44 -07004501
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004502/**
4503 * @brief Process simple type true and false, a boolean
4504 *
4505 * @param[in] pMe The decode context.
4506 * @param[in] pItem The item with either true or false.
4507 * @param[out] pBool The boolean value output.
4508 *
4509 * Sets the internal error if the item isn't a true or a false. Also
4510 * records any tag numbers as the tag numbers of the last item.
4511 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004512static void
4513QCBORDecode_Private_ProcessBool(QCBORDecodeContext *pMe,
4514 const QCBORItem *pItem,
4515 bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004516{
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004517 if(pMe->uLastError != QCBOR_SUCCESS) {
4518 /* Already in error state, do nothing */
4519 return;
4520 }
4521
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004522 switch(pItem->uDataType) {
4523 case QCBOR_TYPE_TRUE:
4524 *pBool = true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004525 break;
4526
4527 case QCBOR_TYPE_FALSE:
4528 *pBool = false;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004529 break;
4530
4531 default:
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004532 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004533 break;
4534 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004535 QCBORDecode_Private_CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004536}
Laurence Lundbladee6430642020-03-14 21:15:44 -07004537
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004538
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004539/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004540 * Public function, see header qcbor/qcbor_decode.h file
4541 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004542void
4543QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004544{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004545 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004546 /* Already in error state, do nothing */
Laurence Lundbladee6430642020-03-14 21:15:44 -07004547 return;
4548 }
4549
Laurence Lundbladec4537442020-04-14 18:53:22 -07004550 QCBORItem Item;
4551
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004552 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4553
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004554 QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004555}
4556
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004557
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004558/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004559 * Public function, see header qcbor/qcbor_decode.h file
4560 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004561void
4562QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe,
4563 const int64_t nLabel,
4564 bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004565{
4566 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004567 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004568
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004569 QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004570}
4571
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004572
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004573/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004574 * Public function, see header qcbor/qcbor_decode.h file
4575 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004576void
4577QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe,
4578 const char *szLabel,
4579 bool *pValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004580{
4581 QCBORItem Item;
4582 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4583
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004584 QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004585}
4586
4587
Laurence Lundblade3888f002024-06-12 21:20:56 -07004588/**
4589 * @brief Process simple values.
4590 *
4591 * @param[in] pMe The decode context.
4592 * @param[in] pItem The item with the simple value.
4593 * @param[out] puSimple The simple value output.
4594 *
4595 * Sets the internal error if the item isn't a true or a false. Also
4596 * records any tag numbers as the tag numbers of the last item.
4597 */
4598static void
4599QCBORDecode_Private_ProcessSimple(QCBORDecodeContext *pMe,
4600 const QCBORItem *pItem,
4601 uint8_t *puSimple)
4602{
4603 if(pMe->uLastError != QCBOR_SUCCESS) {
4604 return;
4605 }
4606
4607 /* It's kind of lame to remap true...undef back to simple values, but
4608 * this function isn't used much and to not do it would require
4609 * changing GetNext() behavior in an incompatible way.
4610 */
4611 switch(pItem->uDataType) {
4612 case QCBOR_TYPE_UKNOWN_SIMPLE:
4613 *puSimple = pItem->val.uSimple;
4614 break;
4615
4616 case QCBOR_TYPE_TRUE:
4617 *puSimple = CBOR_SIMPLEV_TRUE;
4618 break;
4619
4620 case QCBOR_TYPE_FALSE:
4621 *puSimple = CBOR_SIMPLEV_FALSE;
4622 break;
4623
4624 case QCBOR_TYPE_NULL:
4625 *puSimple = CBOR_SIMPLEV_NULL;
4626 break;
4627
4628 case QCBOR_TYPE_UNDEF:
4629 *puSimple = CBOR_SIMPLEV_UNDEF;
4630 break;
4631
4632 default:
4633 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4634 return;
4635 }
4636 QCBORDecode_Private_CopyTags(pMe, pItem);
4637}
4638
4639/*
4640 * Public function, see header qcbor/qcbor_decode.h file
4641 */
4642void
4643QCBORDecode_GetSimple(QCBORDecodeContext *pMe, uint8_t *puSimple)
4644{
4645 QCBORItem Item;
4646
4647 QCBORDecode_VGetNext(pMe, &Item);
4648 QCBORDecode_Private_ProcessSimple(pMe, &Item, puSimple);
4649}
4650
4651/*
4652 * Public function, see header qcbor/qcbor_decode.h file
4653 */
4654void
4655QCBORDecode_GetSimpleInMapN(QCBORDecodeContext *pMe,
4656 int64_t nLabel,
4657 uint8_t *puSimpleValue)
4658{
4659 QCBORItem Item;
4660 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4661
4662 QCBORDecode_Private_ProcessSimple(pMe, &Item, puSimpleValue);
4663}
4664
4665/*
4666 * Public function, see header qcbor/qcbor_decode.h file
4667 */
4668void
4669QCBORDecode_GetSimpleInMapSZ(QCBORDecodeContext *pMe,
4670 const char *szLabel,
4671 uint8_t *puSimpleValue)
4672{
4673 QCBORItem Item;
4674 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4675
4676 QCBORDecode_Private_ProcessSimple(pMe, &Item, puSimpleValue);
4677}
4678
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004679
Laurence Lundbladec7114722020-08-13 05:11:40 -07004680
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004681/**
4682 * @brief Common processing for an epoch date.
4683 *
4684 * @param[in] pMe The decode context.
4685 * @param[in] pItem The item with the date.
4686 * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX.
4687 * @param[out] pnTime The returned date.
4688 *
4689 * Common processing for the date tag. Mostly make sure the tag
4690 * content is correct and copy forward any further other tag numbers.
4691 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004692static void
4693QCBORDecode_Private_ProcessEpochDate(QCBORDecodeContext *pMe,
4694 QCBORItem *pItem,
4695 const uint8_t uTagRequirement,
4696 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07004697{
4698 if(pMe->uLastError != QCBOR_SUCCESS) {
4699 // Already in error state, do nothing
4700 return;
4701 }
4702
4703 QCBORError uErr;
4704
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004705 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladec7114722020-08-13 05:11:40 -07004706 {
4707 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004708 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4709 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07004710 };
4711
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004712 uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004713 if(uErr != QCBOR_SUCCESS) {
4714 goto Done;
4715 }
4716
4717 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004718 uErr = QCBOR_Private_DecodeDateEpoch(pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004719 if(uErr != QCBOR_SUCCESS) {
4720 goto Done;
4721 }
4722 }
4723
Laurence Lundblade9b334962020-08-27 10:55:53 -07004724 // Save the tags in the last item's tags in the decode context
4725 // for QCBORDecode_GetNthTagOfLast()
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004726 QCBORDecode_Private_CopyTags(pMe, pItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07004727
Laurence Lundbladec7114722020-08-13 05:11:40 -07004728 *pnTime = pItem->val.epochDate.nSeconds;
4729
4730Done:
4731 pMe->uLastError = (uint8_t)uErr;
4732}
4733
4734
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004735
4736/*
4737 * Public function, see header qcbor/qcbor_spiffy_decode.h file
4738 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004739void
4740QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
4741 uint8_t uTagRequirement,
4742 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07004743{
4744 if(pMe->uLastError != QCBOR_SUCCESS) {
4745 // Already in error state, do nothing
4746 return;
4747 }
4748
4749 QCBORItem Item;
4750 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4751
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004752 QCBORDecode_Private_ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004753}
4754
4755
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004756/*
4757 * Public function, see header qcbor/qcbor_spiffy_decode.h file
4758 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07004759void
4760QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
4761 int64_t nLabel,
4762 uint8_t uTagRequirement,
4763 int64_t *pnTime)
4764{
4765 QCBORItem Item;
4766 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004767 QCBORDecode_Private_ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004768}
4769
4770
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004771/*
4772 * Public function, see header qcbor/qcbor_spiffy_decode.h file
4773 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07004774void
4775QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
4776 const char *szLabel,
4777 uint8_t uTagRequirement,
4778 int64_t *pnTime)
4779{
4780 QCBORItem Item;
4781 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004782 QCBORDecode_Private_ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004783}
4784
4785
4786
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004787/**
4788 * @brief Common processing for an epoch date.
4789 *
4790 * @param[in] pMe The decode context.
4791 * @param[in] pItem The item with the date.
4792 * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX.
4793 * @param[out] pnDays The returned day count.
4794 *
4795 * Common processing for the RFC 8943 day-count tag. Mostly make sure
4796 * the tag content is correct and copy forward any further other tag
4797 * numbers.
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004798 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004799static void
4800QCBORDecode_Private_ProcessEpochDays(QCBORDecodeContext *pMe,
4801 QCBORItem *pItem,
4802 uint8_t uTagRequirement,
4803 int64_t *pnDays)
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004804{
4805 if(pMe->uLastError != QCBOR_SUCCESS) {
4806 /* Already in error state, do nothing */
4807 return;
4808 }
4809
4810 QCBORError uErr;
4811
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004812 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004813 {
4814 uTagRequirement,
4815 {QCBOR_TYPE_DAYS_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4816 {QCBOR_TYPE_INT64, QCBOR_TYPE_UINT64, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4817 };
4818
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004819 uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004820 if(uErr != QCBOR_SUCCESS) {
4821 goto Done;
4822 }
4823
4824 if(pItem->uDataType != QCBOR_TYPE_DAYS_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004825 uErr = QCBOR_Private_DecodeDaysEpoch(pItem);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004826 if(uErr != QCBOR_SUCCESS) {
4827 goto Done;
4828 }
4829 }
4830
4831 /* Save the tags in the last item's tags in the decode context
4832 * for QCBORDecode_GetNthTagOfLast()
4833 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004834 QCBORDecode_Private_CopyTags(pMe, pItem);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004835
4836 *pnDays = pItem->val.epochDays;
4837
4838Done:
4839 pMe->uLastError = (uint8_t)uErr;
4840}
4841
4842
4843/*
4844 * Public function, see header qcbor/qcbor_decode.h
4845 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004846void
4847QCBORDecode_GetEpochDays(QCBORDecodeContext *pMe,
4848 uint8_t uTagRequirement,
4849 int64_t *pnDays)
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004850{
4851 if(pMe->uLastError != QCBOR_SUCCESS) {
4852 /* Already in error state, do nothing */
4853 return;
4854 }
4855
4856 QCBORItem Item;
4857 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4858
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004859 QCBORDecode_Private_ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004860}
4861
4862
4863/*
4864 * Public function, see header qcbor/qcbor_decode.h
4865 */
4866void
4867QCBORDecode_GetEpochDaysInMapN(QCBORDecodeContext *pMe,
4868 int64_t nLabel,
4869 uint8_t uTagRequirement,
4870 int64_t *pnDays)
4871{
4872 QCBORItem Item;
4873 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004874 QCBORDecode_Private_ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004875}
4876
4877
4878/*
4879 * Public function, see header qcbor/qcbor_decode.h
4880 */
4881void
4882QCBORDecode_GetEpochDaysInMapSZ(QCBORDecodeContext *pMe,
4883 const char *szLabel,
4884 uint8_t uTagRequirement,
4885 int64_t *pnDays)
4886{
4887 QCBORItem Item;
4888 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004889 QCBORDecode_Private_ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004890}
4891
4892
4893
Laurence Lundblade37286c02022-09-03 10:05:02 -07004894/*
4895 * @brief Get a string that matches the type/tag specification.
4896 */
4897void
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004898QCBORDecode_Private_GetTaggedString(QCBORDecodeContext *pMe,
4899 const QCBOR_Private_TagSpec TagSpec,
4900 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004901{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004902 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade37286c02022-09-03 10:05:02 -07004903 /* Already in error state, do nothing */
Laurence Lundbladec4537442020-04-14 18:53:22 -07004904 return;
4905 }
4906
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004907 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004908 QCBORItem Item;
4909
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004910 uError = QCBORDecode_GetNext(pMe, &Item);
4911 if(uError != QCBOR_SUCCESS) {
4912 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004913 return;
4914 }
4915
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004916 pMe->uLastError = (uint8_t)QCBOR_Private_CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004917
4918 if(pMe->uLastError == QCBOR_SUCCESS) {
4919 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07004920 } else {
4921 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004922 }
4923}
4924
Laurence Lundbladec4537442020-04-14 18:53:22 -07004925
4926
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004927
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004928/**
4929 * @brief Common processing for a big number tag.
4930 *
4931 * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX.
4932 * @param[in] pItem The item with the date.
4933 * @param[out] pValue The returned big number
4934 * @param[out] pbIsNegative The returned sign of the big number.
4935 *
4936 * Common processing for the big number tag. Mostly make sure
4937 * the tag content is correct and copy forward any further other tag
4938 * numbers.
4939 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07004940static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004941QCBOR_Private_ProcessBigNum(const uint8_t uTagRequirement,
4942 const QCBORItem *pItem,
4943 UsefulBufC *pValue,
4944 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004945{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004946 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004947 {
4948 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004949 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4950 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004951 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004952
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004953 QCBORError uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004954 if(uErr != QCBOR_SUCCESS) {
4955 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004956 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004957
4958 *pValue = pItem->val.string;
4959
4960 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
4961 *pbIsNegative = false;
4962 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
4963 *pbIsNegative = true;
4964 }
4965
4966 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004967}
4968
4969
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004970/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004971 * Public function, see header qcbor/qcbor_spiffy_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004972 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004973void
4974QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
4975 const uint8_t uTagRequirement,
4976 UsefulBufC *pValue,
4977 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004978{
4979 if(pMe->uLastError != QCBOR_SUCCESS) {
4980 // Already in error state, do nothing
4981 return;
4982 }
4983
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004984 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004985 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4986 if(uError != QCBOR_SUCCESS) {
4987 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004988 return;
4989 }
4990
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004991 pMe->uLastError = (uint8_t)QCBOR_Private_ProcessBigNum(uTagRequirement,
4992 &Item,
4993 pValue,
4994 pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004995}
4996
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004997
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004998/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004999 * Public function, see header qcbor/qcbor_spiffy_decode.h
5000 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005001void
5002QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
5003 const int64_t nLabel,
5004 const uint8_t uTagRequirement,
5005 UsefulBufC *pValue,
5006 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07005007{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005008 QCBORItem Item;
5009 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005010 if(pMe->uLastError != QCBOR_SUCCESS) {
5011 return;
5012 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005013
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005014 pMe->uLastError = (uint8_t)QCBOR_Private_ProcessBigNum(uTagRequirement,
5015 &Item,
5016 pValue,
5017 pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07005018}
5019
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005020
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005021/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005022 * Public function, see header qcbor/qcbor_spiffy_decode.h
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005023 */
5024void
5025QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
5026 const char *szLabel,
5027 const uint8_t uTagRequirement,
5028 UsefulBufC *pValue,
5029 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005030{
5031 QCBORItem Item;
5032 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005033 if(pMe->uLastError != QCBOR_SUCCESS) {
5034 return;
5035 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005036
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005037 pMe->uLastError = (uint8_t)QCBOR_Private_ProcessBigNum(uTagRequirement,
5038 &Item,
5039 pValue,
5040 pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005041}
5042
5043
5044
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005045/**
5046 * @brief Common processing for MIME tag (semi-private).
5047 *
5048 * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX.
5049 * @param[in] pItem The item with the date.
5050 * @param[out] pMessage The returned MIME message.
5051 * @param[out] pbIsTag257 If true, binary MIME, if not, text MIME.
5052 *
5053 * Common processing for the MIME tag. Mostly make sure the tag
5054 * content is correct and copy forward any further other tag
5055 * numbers. See QCBORDecode_GetMIMEMessage().
5056 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07005057QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005058QCBORDecode_Private_GetMIME(const uint8_t uTagRequirement,
Laurence Lundblade37286c02022-09-03 10:05:02 -07005059 const QCBORItem *pItem,
5060 UsefulBufC *pMessage,
5061 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005062{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005063 const QCBOR_Private_TagSpec TagSpecText =
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07005064 {
5065 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005066 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
5067 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07005068 };
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005069 const QCBOR_Private_TagSpec TagSpecBinary =
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07005070 {
5071 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005072 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
5073 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07005074 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005075
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005076 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07005077
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005078 if(QCBOR_Private_CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005079 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07005080 if(pbIsTag257 != NULL) {
5081 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005082 }
5083 uReturn = QCBOR_SUCCESS;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005084 } else if(QCBOR_Private_CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005085 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07005086 if(pbIsTag257 != NULL) {
5087 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005088 }
5089 uReturn = QCBOR_SUCCESS;
5090
5091 } else {
5092 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
5093 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07005094
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005095 return uReturn;
5096}
5097
Laurence Lundblade93d89472020-10-03 22:30:50 -07005098// Improvement: add methods for wrapped CBOR, a simple alternate
5099// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07005100
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005101
5102
5103
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005104#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07005105
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005106/**
5107 * @brief Prototype for conversion of exponent and mantissa to unsigned integer.
5108 *
5109 * @param[in] uMantissa The mantissa.
5110 * @param[in] nExponent The exponent.
5111 * @param[out] puResult The resulting integer.
5112 *
5113 * Concrete implementations of this are for exponent base 10 and 2 supporting
5114 * decimal fractions and big floats.
5115 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005116typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005117
5118
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005119/**
5120 * @brief Base 10 exponentiate a mantissa and exponent into an unsigned 64-bit integer.
5121 *
5122 * @param[in] uMantissa The unsigned integer mantissa.
5123 * @param[in] nExponent The signed integer exponent.
5124 * @param[out] puResult Place to return the unsigned integer result.
5125 *
5126 * This computes: mantissa * 10 ^^ exponent as for a decimal fraction. The output is a 64-bit
5127 * unsigned integer.
5128 *
5129 * There are many inputs for which the result will not fit in the
5130 * 64-bit integer and \ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will
5131 * be returned.
5132 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07005133static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005134QCBOR_Private_Exponentitate10(const uint64_t uMantissa,
5135 int64_t nExponent,
5136 uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07005137{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005138 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005139
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005140 if(uResult != 0) {
5141 /* This loop will run a maximum of 19 times because
5142 * UINT64_MAX < 10 ^^ 19. More than that will cause
5143 * exit with the overflow error
5144 */
5145 for(; nExponent > 0; nExponent--) {
5146 if(uResult > UINT64_MAX / 10) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005147 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005148 }
5149 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005150 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005151
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005152 for(; nExponent < 0; nExponent++) {
5153 uResult = uResult / 10;
5154 if(uResult == 0) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005155 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005156 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005157 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005158 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005159 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07005160
5161 *puResult = uResult;
5162
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005163 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005164}
5165
5166
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005167/**
5168 * @brief Base 2 exponentiate a mantissa and exponent into an unsigned 64-bit integer.
5169 *
5170 * @param[in] uMantissa The unsigned integer mantissa.
5171 * @param[in] nExponent The signed integer exponent.
5172 * @param[out] puResult Place to return the unsigned integer result.
5173 *
5174 * This computes: mantissa * 2 ^^ exponent as for a big float. The
5175 * output is a 64-bit unsigned integer.
5176 *
5177 * There are many inputs for which the result will not fit in the
5178 * 64-bit integer and \ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will
5179 * be returned.
5180 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07005181static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005182QCBOR_Private_Exponentitate2(const uint64_t uMantissa,
5183 int64_t nExponent,
5184 uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005185{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005186 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005187
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005188 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005189
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005190 /* This loop will run a maximum of 64 times because INT64_MAX <
5191 * 2^31. More than that will cause exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07005192 */
5193 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005194 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005195 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005196 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005197 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005198 nExponent--;
5199 }
5200
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005201 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005202 if(uResult == 0) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005203 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005204 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005205 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005206 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005207 }
5208
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005209 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005210
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005211 return QCBOR_SUCCESS;
5212}
5213
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005214
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005215/**
5216 * @brief Exponentiate a signed mantissa and signed exponent to produce a signed result.
5217 *
5218 * @param[in] nMantissa Signed integer mantissa.
5219 * @param[in] nExponent Signed integer exponent.
5220 * @param[out] pnResult Place to put the signed integer result.
5221 * @param[in] pfExp Exponentiation function.
5222 *
5223 * @returns Error code
5224 *
5225 * \c pfExp performs exponentiation on and unsigned mantissa and
5226 * produces an unsigned result. This converts the mantissa from signed
5227 * and converts the result to signed. The exponentiation function is
5228 * either for base 2 or base 10 (and could be other if needed).
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005229 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005230static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005231QCBOR_Private_ExponentiateNN(const int64_t nMantissa,
5232 const int64_t nExponent,
5233 int64_t *pnResult,
5234 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005235{
5236 uint64_t uResult;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005237 uint64_t uMantissa;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005238
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005239 /* Take the absolute value and put it into an unsigned. */
5240 if(nMantissa >= 0) {
5241 /* Positive case is straightforward */
5242 uMantissa = (uint64_t)nMantissa;
5243 } else if(nMantissa != INT64_MIN) {
5244 /* The common negative case. See next. */
5245 uMantissa = (uint64_t)-nMantissa;
5246 } else {
5247 /* int64_t and uint64_t are always two's complement per the
5248 * C standard (and since QCBOR uses these it only works with
5249 * two's complement, which is pretty much universal these
5250 * days). The range of a negative two's complement integer is
5251 * one more that than a positive, so the simple code above might
5252 * not work all the time because you can't simply negate the
5253 * value INT64_MIN because it can't be represented in an
5254 * int64_t. -INT64_MIN can however be represented in a
5255 * uint64_t. Some compilers seem to recognize this case for the
5256 * above code and put the correct value in uMantissa, however
5257 * they are not required to do this by the C standard. This next
5258 * line does however work for all compilers.
5259 *
5260 * This does assume two's complement where -INT64_MIN ==
5261 * INT64_MAX + 1 (which wouldn't be true for one's complement or
5262 * sign and magnitude (but we know we're using two's complement
5263 * because int64_t requires it)).
5264 *
5265 * See these, particularly the detailed commentary:
5266 * https://stackoverflow.com/questions/54915742/does-c99-mandate-a-int64-t-type-be-available-always
5267 * https://stackoverflow.com/questions/37301078/is-negating-int-min-undefined-behaviour
5268 */
5269 uMantissa = (uint64_t)INT64_MAX+1;
5270 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005271
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005272 /* Call the exponentiator passed for either base 2 or base 10.
5273 * Here is where most of the overflow errors are caught. */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005274 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
5275 if(uReturn) {
5276 return uReturn;
5277 }
5278
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005279 /* Convert back to the sign of the original mantissa */
5280 if(nMantissa >= 0) {
5281 if(uResult > INT64_MAX) {
5282 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5283 }
5284 *pnResult = (int64_t)uResult;
5285 } else {
5286 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
5287 * of INT64_MIN. This assumes two's compliment representation
5288 * where INT64_MIN is one increment farther from 0 than
5289 * INT64_MAX. Trying to write -INT64_MIN doesn't work to get
5290 * this because the compiler makes it an int64_t which can't
5291 * represent -INT64_MIN. Also see above.
5292 */
5293 if(uResult > (uint64_t)INT64_MAX+1) {
5294 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5295 }
5296 *pnResult = -(int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005297 }
5298
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005299 return QCBOR_SUCCESS;
5300}
5301
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005302
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005303/**
5304 * @brief Exponentiate an unsigned mantissa and signed exponent to produce an unsigned result.
5305 *
5306 * @param[in] nMantissa Signed integer mantissa.
5307 * @param[in] nExponent Signed integer exponent.
5308 * @param[out] puResult Place to put the signed integer result.
5309 * @param[in] pfExp Exponentiation function.
5310 *
5311 * @returns Error code
5312 *
5313 * \c pfExp performs exponentiation on and unsigned mantissa and
5314 * produces an unsigned result. This errors out if the mantissa
5315 * is negative because the output is unsigned.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005316 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005317static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005318QCBOR_Private_ExponentitateNU(const int64_t nMantissa,
5319 const int64_t nExponent,
5320 uint64_t *puResult,
5321 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005322{
5323 if(nMantissa < 0) {
5324 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5325 }
5326
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005327 /* Cast to unsigned is OK because of check for negative.
5328 * Cast to unsigned is OK because UINT64_MAX > INT64_MAX.
5329 * Exponentiation is straight forward
5330 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005331 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
5332}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005333
5334
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005335/**
5336 * @brief Exponentiate an usnigned mantissa and unsigned exponent to produce an unsigned result.
5337 *
5338 * @param[in] uMantissa Unsigned integer mantissa.
5339 * @param[in] nExponent Unsigned integer exponent.
5340 * @param[out] puResult Place to put the unsigned integer result.
5341 * @param[in] pfExp Exponentiation function.
5342 *
5343 * @returns Error code
5344 *
5345 * \c pfExp performs exponentiation on and unsigned mantissa and
5346 * produces an unsigned result so this is just a wrapper that does
5347 * nothing (and is likely inlined).
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005348 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005349static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005350QCBOR_Private_ExponentitateUU(const uint64_t uMantissa,
5351 const int64_t nExponent,
5352 uint64_t *puResult,
5353 fExponentiator pfExp)
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005354{
5355 return (*pfExp)(uMantissa, nExponent, puResult);
5356}
5357
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005358#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005359
5360
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005361
5362
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005363/**
5364 * @brief Convert a CBOR big number to a uint64_t.
5365 *
5366 * @param[in] BigNum Bytes of the big number to convert.
5367 * @param[in] uMax Maximum value allowed for the result.
5368 * @param[out] pResult Place to put the unsigned integer result.
5369 *
5370 * @returns Error code
5371 *
5372 * Many values will overflow because a big num can represent a much
5373 * larger range than uint64_t.
5374 */
5375static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005376QCBOR_Private_ConvertBigNumToUnsigned(const UsefulBufC BigNum,
5377 const uint64_t uMax,
5378 uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005379{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005380 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005381
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005382 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005383 const uint8_t *pByte = BigNum.ptr;
5384 size_t uLen = BigNum.len;
5385 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07005386 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07005387 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005388 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07005389 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005390 }
5391
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005392 *pResult = uResult;
5393 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005394}
5395
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005396
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005397/**
5398 * @brief Convert a CBOR postive big number to a uint64_t.
5399 *
5400 * @param[in] BigNum Bytes of the big number to convert.
5401 * @param[out] pResult Place to put the unsigned integer result.
5402 *
5403 * @returns Error code
5404 *
5405 * Many values will overflow because a big num can represent a much
5406 * larger range than uint64_t.
5407 */
5408static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005409QCBOR_Private_ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum,
5410 uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005411{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005412 return QCBOR_Private_ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005413}
5414
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005415
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005416/**
5417 * @brief Convert a CBOR positive big number to an int64_t.
5418 *
5419 * @param[in] BigNum Bytes of the big number to convert.
5420 * @param[out] pResult Place to put the signed integer result.
5421 *
5422 * @returns Error code
5423 *
5424 * Many values will overflow because a big num can represent a much
5425 * larger range than int64_t.
5426 */
5427static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005428QCBOR_Private_ConvertPositiveBigNumToSigned(const UsefulBufC BigNum,
5429 int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005430{
5431 uint64_t uResult;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005432 QCBORError uError = QCBOR_Private_ConvertBigNumToUnsigned(BigNum,
5433 INT64_MAX,
5434 &uResult);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005435 if(uError) {
5436 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005437 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005438 /* Cast is safe because ConvertBigNumToUnsigned limits to INT64_MAX */
Laurence Lundbladee6430642020-03-14 21:15:44 -07005439 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005440 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005441}
5442
5443
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005444/**
5445 * @brief Convert a CBOR negative big number to an int64_t.
5446 *
5447 * @param[in] BigNum Bytes of the big number to convert.
5448 * @param[out] pnResult Place to put the signed integer result.
5449 *
5450 * @returns Error code
5451 *
5452 * Many values will overflow because a big num can represent a much
5453 * larger range than int64_t.
5454 */
5455static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005456QCBOR_Private_ConvertNegativeBigNumToSigned(const UsefulBufC BigNum,
5457 int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005458{
5459 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005460 /* The negative integer furthest from zero for a C int64_t is
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005461 * INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
5462 * negative number in CBOR is computed as -n - 1 where n is the
5463 * encoded integer, where n is what is in the variable BigNum. When
5464 * converting BigNum to a uint64_t, the maximum value is thus
5465 * INT64_MAX, so that when it -n - 1 is applied to it the result
5466 * will never be further from 0 than INT64_MIN.
5467 *
5468 * -n - 1 <= INT64_MIN.
5469 * -n - 1 <= -INT64_MAX - 1
5470 * n <= INT64_MAX.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005471 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005472 QCBORError uError = QCBOR_Private_ConvertBigNumToUnsigned(BigNum,
5473 INT64_MAX,
5474 &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005475 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005476 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005477 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005478
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005479 /* Now apply -n - 1. The cast is safe because
5480 * ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
5481 * is the largest positive integer that an int64_t can
5482 * represent. */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005483 *pnResult = -(int64_t)uResult - 1;
5484
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005485 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005486}
5487
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005488
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005489
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005490
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005491/**
5492 * @brief Convert integers and floats to an int64_t.
5493 *
5494 * @param[in] pItem The item to convert.
5495 * @param[in] uConvertTypes Bit mask list of conversion options.
5496 * @param[out] pnValue The resulting converted value.
5497 *
5498 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
5499 * in uConvertTypes.
5500 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
5501 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
5502 * or too small.
5503 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07005504static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005505QCBOR_Private_ConvertInt64(const QCBORItem *pItem,
5506 const uint32_t uConvertTypes,
5507 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005508{
5509 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005510 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005511 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005512#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005513 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005514 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
5515 http://www.cplusplus.com/reference/cmath/llround/
5516 */
5517 // Not interested in FE_INEXACT
5518 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005519 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
5520 *pnValue = llround(pItem->val.dfnum);
5521 } else {
5522 *pnValue = lroundf(pItem->val.fnum);
5523 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005524 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
5525 // llround() shouldn't result in divide by zero, but catch
5526 // it here in case it unexpectedly does. Don't try to
5527 // distinguish between the various exceptions because it seems
5528 // they vary by CPU, compiler and OS.
5529 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005530 }
5531 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005532 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005533 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005534#else
5535 return QCBOR_ERR_HW_FLOAT_DISABLED;
5536#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005537 break;
5538
5539 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005540 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005541 *pnValue = pItem->val.int64;
5542 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005543 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005544 }
5545 break;
5546
5547 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005548 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005549 if(pItem->val.uint64 < INT64_MAX) {
5550 *pnValue = pItem->val.int64;
5551 } else {
5552 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5553 }
5554 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005555 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005556 }
5557 break;
5558
5559 default:
5560 return QCBOR_ERR_UNEXPECTED_TYPE;
5561 }
5562 return QCBOR_SUCCESS;
5563}
5564
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005565
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005566/**
5567 * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
5568 *
5569 * @param[in] pMe The decode context.
5570 * @param[in] uConvertTypes Bit mask list of conversion options.
5571 * @param[out] pnValue Result of the conversion.
5572 * @param[in,out] pItem Temporary space to store Item, returned item.
5573 *
5574 * See QCBORDecode_GetInt64Convert().
5575 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005576void
5577QCBORDecode_Private_GetInt64Convert(QCBORDecodeContext *pMe,
5578 uint32_t uConvertTypes,
5579 int64_t *pnValue,
5580 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005581{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07005582 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07005583 return;
5584 }
5585
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005586 QCBORError uError = QCBORDecode_GetNext(pMe, pItem);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005587 if(uError) {
5588 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005589 return;
5590 }
5591
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005592 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005593 uConvertTypes,
5594 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005595}
5596
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005597/**
5598 * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
5599 *
5600 * @param[in] pMe The decode context.
5601 * @param[in] nLabel Label to find in map.
5602 * @param[in] uConvertTypes Bit mask list of conversion options.
5603 * @param[out] pnValue Result of the conversion.
5604 * @param[in,out] pItem Temporary space to store Item, returned item.
5605 *
5606 * See QCBORDecode_GetInt64ConvertInMapN().
5607 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005608void
5609QCBORDecode_Private_GetInt64ConvertInMapN(QCBORDecodeContext *pMe,
5610 int64_t nLabel,
5611 uint32_t uConvertTypes,
5612 int64_t *pnValue,
5613 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005614{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005615 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005616 if(pMe->uLastError != QCBOR_SUCCESS) {
5617 return;
5618 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005619
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005620 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
5621 uConvertTypes,
5622 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005623}
5624
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005625/**
5626 * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
5627 *
5628 * @param[in] pMe The decode context.
5629 * @param[in] szLabel Label to find in map.
5630 * @param[in] uConvertTypes Bit mask list of conversion options.
5631 * @param[out] pnValue Result of the conversion.
5632 * @param[in,out] pItem Temporary space to store Item, returned item.
5633 *
5634 * See QCBORDecode_GetInt64ConvertInMapSZ().
5635 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005636void
5637QCBORDecode_Private_GetInt64ConvertInMapSZ(QCBORDecodeContext *pMe,
5638 const char * szLabel,
5639 uint32_t uConvertTypes,
5640 int64_t *pnValue,
5641 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005642{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005643 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005644 if(pMe->uLastError != QCBOR_SUCCESS) {
5645 return;
5646 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005647
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005648 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
5649 uConvertTypes,
5650 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005651}
5652
5653
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005654/**
5655 * @brief Convert many number types to an int64_t.
5656 *
5657 * @param[in] pItem The item to convert.
5658 * @param[in] uConvertTypes Bit mask list of conversion options.
5659 * @param[out] pnValue The resulting converted value.
5660 *
5661 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
5662 * in uConvertTypes.
5663 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
5664 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
5665 * or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005666 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07005667static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005668QCBOR_Private_Int64ConvertAll(const QCBORItem *pItem,
5669 const uint32_t uConvertTypes,
5670 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005671{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005672 switch(pItem->uDataType) {
5673
5674 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005675 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005676 return QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005677 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005678 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005679 }
5680 break;
5681
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005682 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005683 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005684 return QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005685 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005686 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005687 }
5688 break;
5689
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005690#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005691 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005692 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
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_Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -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 Lundblade784b54b2020-08-10 01:24:52 -07005702 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005703 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005704 return QCBOR_Private_ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005705 pItem->val.expAndMantissa.nExponent,
5706 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005707 QCBOR_Private_Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005708 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005709 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005710 }
5711 break;
5712
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005713 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005714 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005715 int64_t nMantissa;
5716 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005717 uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005718 if(uErr) {
5719 return uErr;
5720 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005721 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005722 pItem->val.expAndMantissa.nExponent,
5723 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005724 QCBOR_Private_Exponentitate10);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005725 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005726 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005727 }
5728 break;
5729
5730 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005731 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005732 int64_t nMantissa;
5733 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005734 uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005735 if(uErr) {
5736 return uErr;
5737 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005738 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005739 pItem->val.expAndMantissa.nExponent,
5740 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005741 QCBOR_Private_Exponentitate10);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005742 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005743 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005744 }
5745 break;
5746
5747 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005748 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005749 int64_t nMantissa;
5750 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005751 uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005752 if(uErr) {
5753 return uErr;
5754 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005755 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005756 pItem->val.expAndMantissa.nExponent,
5757 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005758 QCBOR_Private_Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005759 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005760 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005761 }
5762 break;
5763
5764 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005765 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005766 int64_t nMantissa;
5767 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005768 uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005769 if(uErr) {
5770 return uErr;
5771 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005772 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005773 pItem->val.expAndMantissa.nExponent,
5774 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005775 QCBOR_Private_Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005776 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005777 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005778 }
5779 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005780#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005781
Laurence Lundbladee6430642020-03-14 21:15:44 -07005782
Laurence Lundbladec4537442020-04-14 18:53:22 -07005783 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005784 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005785}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005786
5787
Laurence Lundbladec4537442020-04-14 18:53:22 -07005788/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005789 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005790 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005791void
5792QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe,
5793 const uint32_t uConvertTypes,
5794 int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07005795{
5796 QCBORItem Item;
5797
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005798 QCBORDecode_Private_GetInt64Convert(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07005799
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005800 if(pMe->uLastError == QCBOR_SUCCESS) {
5801 // The above conversion succeeded
5802 return;
5803 }
5804
Laurence Lundbladef6c86662020-05-12 02:08:00 -07005805 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005806 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07005807 return;
5808 }
5809
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005810 pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
5811 uConvertTypes,
5812 pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005813}
5814
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005815
5816/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005817 * Public function, see header qcbor/qcbor_decode.h file
5818 */
5819void
5820QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
5821 const int64_t nLabel,
5822 const uint32_t uConvertTypes,
5823 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005824{
5825 QCBORItem Item;
5826
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005827 QCBORDecode_Private_GetInt64ConvertInMapN(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07005828 nLabel,
5829 uConvertTypes,
5830 pnValue,
5831 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005832
5833 if(pMe->uLastError == QCBOR_SUCCESS) {
5834 // The above conversion succeeded
5835 return;
5836 }
5837
5838 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5839 // The above conversion failed in a way that code below can't correct
5840 return;
5841 }
5842
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005843 pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
5844 uConvertTypes,
5845 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005846}
5847
5848
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005849/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005850 * Public function, see header qcbor/qcbor_decode.h file
5851 */
5852void
5853QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
5854 const char *szLabel,
5855 const uint32_t uConvertTypes,
5856 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005857{
5858 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005859 QCBORDecode_Private_GetInt64ConvertInMapSZ(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07005860 szLabel,
5861 uConvertTypes,
5862 pnValue,
5863 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005864
5865 if(pMe->uLastError == QCBOR_SUCCESS) {
5866 // The above conversion succeeded
5867 return;
5868 }
5869
5870 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5871 // The above conversion failed in a way that code below can't correct
5872 return;
5873 }
5874
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005875 pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
5876 uConvertTypes,
5877 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005878}
5879
5880
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005881/**
5882 * @brief Convert many number types to an uint64_t.
5883 *
5884 * @param[in] pItem The item to convert.
5885 * @param[in] uConvertTypes Bit mask list of conversion options.
5886 * @param[out] puValue The resulting converted value.
5887 *
5888 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
5889 * in uConvertTypes.
5890 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
5891 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
5892 * or too small.
5893 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005894static QCBORError
5895QCBOR_Private_ConvertUInt64(const QCBORItem *pItem,
5896 const uint32_t uConvertTypes,
5897 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005898{
5899 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005900 case QCBOR_TYPE_DOUBLE:
5901 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005902#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005903 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005904 // Can't use llround here because it will not convert values
5905 // greater than INT64_MAX and less than UINT64_MAX that
5906 // need to be converted so it is more complicated.
5907 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
5908 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
5909 if(isnan(pItem->val.dfnum)) {
5910 return QCBOR_ERR_FLOAT_EXCEPTION;
5911 } else if(pItem->val.dfnum < 0) {
5912 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5913 } else {
5914 double dRounded = round(pItem->val.dfnum);
5915 // See discussion in DecodeDateEpoch() for
5916 // explanation of - 0x7ff
5917 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
5918 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5919 }
5920 *puValue = (uint64_t)dRounded;
5921 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005922 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005923 if(isnan(pItem->val.fnum)) {
5924 return QCBOR_ERR_FLOAT_EXCEPTION;
5925 } else if(pItem->val.fnum < 0) {
5926 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5927 } else {
5928 float fRounded = roundf(pItem->val.fnum);
5929 // See discussion in DecodeDateEpoch() for
5930 // explanation of - 0x7ff
5931 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
5932 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5933 }
5934 *puValue = (uint64_t)fRounded;
5935 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005936 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005937 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
5938 // round() and roundf() shouldn't result in exceptions here, but
5939 // catch them to be robust and thorough. Don't try to
5940 // distinguish between the various exceptions because it seems
5941 // they vary by CPU, compiler and OS.
5942 return QCBOR_ERR_FLOAT_EXCEPTION;
5943 }
5944
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005945 } else {
5946 return QCBOR_ERR_UNEXPECTED_TYPE;
5947 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005948#else
5949 return QCBOR_ERR_HW_FLOAT_DISABLED;
5950#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005951 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005952
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005953 case QCBOR_TYPE_INT64:
5954 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
5955 if(pItem->val.int64 >= 0) {
5956 *puValue = (uint64_t)pItem->val.int64;
5957 } else {
5958 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5959 }
5960 } else {
5961 return QCBOR_ERR_UNEXPECTED_TYPE;
5962 }
5963 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005964
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005965 case QCBOR_TYPE_UINT64:
5966 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
5967 *puValue = pItem->val.uint64;
5968 } else {
5969 return QCBOR_ERR_UNEXPECTED_TYPE;
5970 }
5971 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005972
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005973 default:
5974 return QCBOR_ERR_UNEXPECTED_TYPE;
5975 }
5976
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005977 return QCBOR_SUCCESS;
5978}
Laurence Lundbladec4537442020-04-14 18:53:22 -07005979
5980
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005981/**
5982 * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
5983 *
5984 * @param[in] pMe The decode context.
5985 * @param[in] uConvertTypes Bit mask list of conversion options.
5986 * @param[out] puValue Result of the conversion.
5987 * @param[in,out] pItem Temporary space to store Item, returned item.
5988 *
5989 * See QCBORDecode_GetUInt64Convert().
5990 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005991void
5992QCBORDecode_Private_GetUInt64Convert(QCBORDecodeContext *pMe,
5993 const uint32_t uConvertTypes,
5994 uint64_t *puValue,
5995 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07005996{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005997 if(pMe->uLastError != QCBOR_SUCCESS) {
5998 return;
5999 }
6000
Laurence Lundbladec4537442020-04-14 18:53:22 -07006001 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07006002
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07006003 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6004 if(uError) {
6005 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07006006 return;
6007 }
6008
Laurence Lundbladea826c502020-05-10 21:07:00 -07006009 if(pItem) {
6010 *pItem = Item;
6011 }
6012
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006013 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(&Item,
6014 uConvertTypes,
6015 puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07006016}
6017
Laurence Lundblade9c905e82020-04-25 11:31:38 -07006018
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006019/**
6020 * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
6021 *
6022 * @param[in] pMe The decode context.
6023 * @param[in] nLabel Label to find in map.
6024 * @param[in] uConvertTypes Bit mask list of conversion options.
6025 * @param[out] puValue Result of the conversion.
6026 * @param[in,out] pItem Temporary space to store Item, returned item.
6027 *
6028 * See QCBORDecode_GetUInt64ConvertInMapN().
6029 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006030void
6031QCBORDecode_Private_GetUInt64ConvertInMapN(QCBORDecodeContext *pMe,
6032 const int64_t nLabel,
6033 const uint32_t uConvertTypes,
6034 uint64_t *puValue,
6035 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006036{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006037 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07006038 if(pMe->uLastError != QCBOR_SUCCESS) {
6039 return;
6040 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006041
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006042 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
6043 uConvertTypes,
6044 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006045}
6046
6047
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006048/**
6049 * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
6050 *
6051 * @param[in] pMe The decode context.
6052 * @param[in] szLabel Label to find in map.
6053 * @param[in] uConvertTypes Bit mask list of conversion options.
6054 * @param[out] puValue Result of the conversion.
6055 * @param[in,out] pItem Temporary space to store Item, returned item.
6056 *
6057 * See QCBORDecode_GetUInt64ConvertInMapSZ().
6058 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006059void
6060QCBORDecode_Private_GetUInt64ConvertInMapSZ(QCBORDecodeContext *pMe,
6061 const char *szLabel,
6062 const uint32_t uConvertTypes,
6063 uint64_t *puValue,
6064 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006065{
6066 if(pMe->uLastError != QCBOR_SUCCESS) {
6067 return;
6068 }
6069
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006070 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07006071 if(pMe->uLastError != QCBOR_SUCCESS) {
6072 return;
6073 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006074
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006075 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
6076 uConvertTypes,
6077 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006078}
6079
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006080
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006081/**
6082 * @brief Convert many number types to an unt64_t.
6083 *
6084 * @param[in] pItem The item to convert.
6085 * @param[in] uConvertTypes Bit mask list of conversion options.
6086 * @param[out] puValue The resulting converted value.
6087 *
6088 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
6089 * in uConvertTypes.
6090 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
6091 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
6092 * or too small.
6093 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07006094static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006095QCBOR_Private_UInt64ConvertAll(const QCBORItem *pItem,
6096 const uint32_t uConvertTypes,
6097 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006098{
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08006099 switch(pItem->uDataType) { /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006100
6101 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006102 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006103 return QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006104 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006105 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006106 }
6107 break;
6108
6109 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006110 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006111 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
6112 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006113 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006114 }
6115 break;
6116
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006117#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006118
6119 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006120 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006121 return QCBOR_Private_ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006122 pItem->val.expAndMantissa.nExponent,
6123 puValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006124 QCBOR_Private_Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006125 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006126 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006127 }
6128 break;
6129
6130 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006131 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006132 return QCBOR_Private_ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006133 pItem->val.expAndMantissa.nExponent,
6134 puValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006135 QCBOR_Private_Exponentitate2);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006136 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006137 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006138 }
6139 break;
6140
6141 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006142 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006143 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006144 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006145 uErr = QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &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_Exponentitate10);
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_DECIMAL_FRACTION_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;
6165
6166 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006167 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006168 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006169 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006170 uErr = QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum,
6171 &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006172 if(uErr != QCBOR_SUCCESS) {
6173 return uErr;
6174 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006175 return QCBOR_Private_ExponentitateUU(uMantissa,
6176 pItem->val.expAndMantissa.nExponent,
6177 puValue,
6178 QCBOR_Private_Exponentitate2);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006179 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006180 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006181 }
6182 break;
6183
6184 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006185 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006186 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
6187 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006188 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006189 }
6190 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006191#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006192 default:
6193 return QCBOR_ERR_UNEXPECTED_TYPE;
6194 }
6195}
6196
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006197
Laurence Lundblade4e2da002020-06-13 23:08:31 -07006198/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006199 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07006200 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006201void
6202QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe,
6203 const uint32_t uConvertTypes,
6204 uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07006205{
6206 QCBORItem Item;
6207
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006208 QCBORDecode_Private_GetUInt64Convert(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07006209
Laurence Lundbladef6c86662020-05-12 02:08:00 -07006210 if(pMe->uLastError == QCBOR_SUCCESS) {
6211 // The above conversion succeeded
6212 return;
6213 }
6214
6215 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6216 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07006217 return;
6218 }
6219
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006220 pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
6221 uConvertTypes,
6222 puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07006223}
6224
Laurence Lundbladec4537442020-04-14 18:53:22 -07006225
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006226/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006227 * Public function, see header qcbor/qcbor_decode.h file
6228 */
6229void
6230QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
6231 const int64_t nLabel,
6232 const uint32_t uConvertTypes,
6233 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006234{
6235 QCBORItem Item;
6236
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006237 QCBORDecode_Private_GetUInt64ConvertInMapN(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07006238 nLabel,
6239 uConvertTypes,
6240 puValue,
6241 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006242
6243 if(pMe->uLastError == QCBOR_SUCCESS) {
6244 // The above conversion succeeded
6245 return;
6246 }
6247
6248 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6249 // The above conversion failed in a way that code below can't correct
6250 return;
6251 }
6252
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006253 pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
6254 uConvertTypes,
6255 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006256}
6257
6258
6259/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006260 * Public function, see header qcbor/qcbor_decode.h file
6261 */
6262void
6263QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
6264 const char *szLabel,
6265 const uint32_t uConvertTypes,
6266 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006267{
6268 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006269 QCBORDecode_Private_GetUInt64ConvertInMapSZ(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07006270 szLabel,
6271 uConvertTypes,
6272 puValue,
6273 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006274
6275 if(pMe->uLastError == QCBOR_SUCCESS) {
6276 // The above conversion succeeded
6277 return;
6278 }
6279
6280 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6281 // The above conversion failed in a way that code below can't correct
6282 return;
6283 }
6284
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006285 pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
6286 uConvertTypes,
6287 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006288}
6289
6290
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07006291
6292
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02006293#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006294/**
6295 * @brief Basic conversions to a double.
6296 *
6297 * @param[in] pItem The item to convert
6298 * @param[in] uConvertTypes Bit flags indicating source types for conversion
6299 * @param[out] pdValue The value converted to a double
6300 *
6301 * This does the conversions that don't need much object code,
6302 * the conversions from int, uint and float to double.
6303 *
6304 * See QCBOR_Private_DoubleConvertAll() for the full set
6305 * of conversions.
6306 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006307static QCBORError
6308QCBOR_Private_ConvertDouble(const QCBORItem *pItem,
6309 const uint32_t uConvertTypes,
6310 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006311{
6312 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006313 case QCBOR_TYPE_FLOAT:
6314#ifndef QCBOR_DISABLE_FLOAT_HW_USE
6315 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
6316 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07006317 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006318 *pdValue = (double)pItem->val.fnum;
6319 } else {
6320 return QCBOR_ERR_UNEXPECTED_TYPE;
6321 }
6322 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08006323#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006324 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08006325#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006326 break;
6327
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006328 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006329 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
6330 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006331 *pdValue = pItem->val.dfnum;
6332 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006333 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006334 }
6335 }
6336 break;
6337
6338 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006339#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006340 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07006341 // A simple cast seems to do the job with no worry of exceptions.
6342 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006343 *pdValue = (double)pItem->val.int64;
6344
6345 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006346 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006347 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006348#else
6349 return QCBOR_ERR_HW_FLOAT_DISABLED;
6350#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006351 break;
6352
6353 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006354#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006355 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07006356 // A simple cast seems to do the job with no worry of exceptions.
6357 // There will be precision loss for some values.
6358 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006359 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006360 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006361 }
6362 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006363#else
6364 return QCBOR_ERR_HW_FLOAT_DISABLED;
6365#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006366
6367 default:
6368 return QCBOR_ERR_UNEXPECTED_TYPE;
6369 }
6370
6371 return QCBOR_SUCCESS;
6372}
6373
6374
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006375/**
6376 * @brief Almost-public method to decode a number and convert to double (semi-private).
6377 *
6378 * @param[in] pMe The decode context.
6379 * @param[in] uConvertTypes Bit mask list of conversion options
6380 * @param[out] pdValue The output of the conversion.
6381 * @param[in,out] pItem Temporary space to store Item, returned item.
6382 *
6383 * See QCBORDecode_GetDoubleConvert().
6384 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006385void
6386QCBORDecode_Private_GetDoubleConvert(QCBORDecodeContext *pMe,
6387 const uint32_t uConvertTypes,
6388 double *pdValue,
6389 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07006390{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006391 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07006392 return;
6393 }
6394
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006395 QCBORError uError = QCBORDecode_GetNext(pMe, pItem);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006396 if(uError) {
6397 pMe->uLastError = (uint8_t)uError;
6398 return;
6399 }
6400
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006401 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006402 uConvertTypes,
6403 pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006404}
Laurence Lundbladec4537442020-04-14 18:53:22 -07006405
Laurence Lundbladec4537442020-04-14 18:53:22 -07006406
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006407/**
6408 * @brief Almost-public method to decode a number and convert to double (semi-private).
6409 *
6410 * @param[in] pMe The decode context.
6411 * @param[in] nLabel Label to find in map.
6412 * @param[in] uConvertTypes Bit mask list of conversion options
6413 * @param[out] pdValue The output of the conversion.
6414 * @param[in,out] pItem Temporary space to store Item, returned item.
6415 *
6416 * See QCBORDecode_GetDoubleConvertInMapN().
6417 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006418void
6419QCBORDecode_Private_GetDoubleConvertInMapN(QCBORDecodeContext *pMe,
6420 const int64_t nLabel,
6421 const uint32_t uConvertTypes,
6422 double *pdValue,
6423 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006424{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006425 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07006426 if(pMe->uLastError != QCBOR_SUCCESS) {
6427 return;
6428 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006429
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006430 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
6431 uConvertTypes,
6432 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006433}
6434
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006435
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006436/**
6437 * @brief Almost-public method to decode a number and convert to double (semi-private).
6438 *
6439 * @param[in] pMe The decode context.
6440 * @param[in] szLabel Label to find in map.
6441 * @param[in] uConvertTypes Bit mask list of conversion options
6442 * @param[out] pdValue The output of the conversion.
6443 * @param[in,out] pItem Temporary space to store Item, returned item.
6444 *
6445 * See QCBORDecode_GetDoubleConvertInMapSZ().
6446 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006447void
6448QCBORDecode_Private_GetDoubleConvertInMapSZ(QCBORDecodeContext *pMe,
6449 const char *szLabel,
6450 const uint32_t uConvertTypes,
6451 double *pdValue,
6452 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006453{
6454 if(pMe->uLastError != QCBOR_SUCCESS) {
6455 return;
6456 }
6457
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006458 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07006459 if(pMe->uLastError != QCBOR_SUCCESS) {
6460 return;
6461 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006462
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006463 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
6464 uConvertTypes,
6465 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006466}
6467
6468
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006469#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006470/**
6471 * @brief Convert a big number to double-precision float.
6472 *
6473 * @param[in] BigNum The big number to convert
6474 *
6475 * @returns The double value.
6476 *
6477 * This will always succeed. It will lose precision for larger
6478 * numbers. If the big number is too large to fit (more than
6479 * 1.7976931348623157E+308) infinity will be returned. NaN is never
6480 * returned.
6481 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006482static double
6483QCBOR_Private_ConvertBigNumToDouble(const UsefulBufC BigNum)
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07006484{
6485 double dResult;
6486
6487 dResult = 0.0;
6488 const uint8_t *pByte = BigNum.ptr;
6489 size_t uLen = BigNum.len;
6490 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006491 * is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07006492 while(uLen--) {
6493 dResult = (dResult * 256.0) + (double)*pByte++;
6494 }
6495
6496 return dResult;
6497}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006498#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
6499
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07006500
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006501
6502
6503/**
6504 * @brief Convert many number types to a double.
6505 *
6506 * @param[in] pItem The item to convert.
6507 * @param[in] uConvertTypes Bit mask list of conversion options.
6508 * @param[out] pdValue The resulting converted value.
6509 *
6510 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
6511 * in uConvertTypes.
6512 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
6513 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
6514 * or too small.
6515 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07006516static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006517QCBOR_Private_DoubleConvertAll(const QCBORItem *pItem,
6518 const uint32_t uConvertTypes,
6519 double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006520{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006521#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07006522 /*
Laurence Lundblade16a207a2021-09-18 17:22:46 -07006523 * What Every Computer Scientist Should Know About Floating-Point Arithmetic
6524 * https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
6525 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006526 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07006527
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006528#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006529 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006530 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07006531 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006532 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
6533 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
6534 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006535 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006536 }
6537 break;
6538
6539 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006540 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07006541 // Underflow gives 0, overflow gives infinity
6542 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
6543 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006544 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006545 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006546 }
6547 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006548#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006549
6550 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006551 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006552 *pdValue = QCBOR_Private_ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006553 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006554 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006555 }
6556 break;
6557
6558 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006559 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006560 *pdValue = -1-QCBOR_Private_ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006561 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006562 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006563 }
6564 break;
6565
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006566#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006567 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006568 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006569 double dMantissa = QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006570 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
6571 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006572 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006573 }
6574 break;
6575
6576 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006577 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006578 double dMantissa = -QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006579 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
6580 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006581 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006582 }
6583 break;
6584
6585 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006586 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006587 double dMantissa = QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006588 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
6589 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006590 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006591 }
6592 break;
6593
6594 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006595 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006596 double dMantissa = -1-QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006597 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
6598 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006599 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006600 }
6601 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006602#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade410c7e02020-06-25 23:35:29 -07006603
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006604 default:
6605 return QCBOR_ERR_UNEXPECTED_TYPE;
6606 }
6607
6608 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006609
6610#else
6611 (void)pItem;
6612 (void)uConvertTypes;
6613 (void)pdValue;
6614 return QCBOR_ERR_HW_FLOAT_DISABLED;
6615#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
6616
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006617}
6618
6619
6620/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006621 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006622 */
6623void
6624QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
6625 const uint32_t uConvertTypes,
6626 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006627{
6628
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006629 QCBORItem Item;
6630
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006631 QCBORDecode_Private_GetDoubleConvert(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006632
6633 if(pMe->uLastError == QCBOR_SUCCESS) {
6634 // The above conversion succeeded
6635 return;
6636 }
6637
6638 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6639 // The above conversion failed in a way that code below can't correct
6640 return;
6641 }
6642
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006643 pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
6644 uConvertTypes,
6645 pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07006646}
6647
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006648
6649/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006650 * Public function, see header qcbor/qcbor_decode.h file
6651 */
6652void
6653QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
6654 const int64_t nLabel,
6655 const uint32_t uConvertTypes,
6656 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006657{
6658 QCBORItem Item;
6659
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006660 QCBORDecode_Private_GetDoubleConvertInMapN(pMe,
6661 nLabel,
6662 uConvertTypes,
6663 pdValue,
6664 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006665
6666 if(pMe->uLastError == QCBOR_SUCCESS) {
6667 // The above conversion succeeded
6668 return;
6669 }
6670
6671 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6672 // The above conversion failed in a way that code below can't correct
6673 return;
6674 }
6675
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006676 pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
6677 uConvertTypes,
6678 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006679}
6680
6681
6682/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006683 * Public function, see header qcbor/qcbor_decode.h file
6684 */
6685void
6686QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
6687 const char *szLabel,
6688 const uint32_t uConvertTypes,
6689 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006690{
6691 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006692 QCBORDecode_Private_GetDoubleConvertInMapSZ(pMe,
6693 szLabel,
6694 uConvertTypes,
6695 pdValue,
6696 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006697
6698 if(pMe->uLastError == QCBOR_SUCCESS) {
6699 // The above conversion succeeded
6700 return;
6701 }
6702
6703 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6704 // The above conversion failed in a way that code below can't correct
6705 return;
6706 }
6707
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006708 pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
6709 uConvertTypes,
6710 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006711}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02006712#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006713
6714
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006715
6716
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006717#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006718/**
6719 * @brief Convert an integer to a big number
6720 *
6721 * @param[in] uInt The integer to convert.
6722 * @param[in] Buffer The buffer to output the big number to.
6723 *
6724 * @returns The big number or NULLUsefulBufC is the buffer is to small.
6725 *
6726 * This always succeeds unless the buffer is too small.
6727 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006728static UsefulBufC
6729QCBOR_Private_ConvertIntToBigNum(uint64_t uInt, const UsefulBuf Buffer)
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006730{
6731 while((uInt & 0xff00000000000000UL) == 0) {
6732 uInt = uInt << 8;
6733 };
6734
6735 UsefulOutBuf UOB;
6736
6737 UsefulOutBuf_Init(&UOB, Buffer);
6738
6739 while(uInt) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006740 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
6741 uInt = uInt << 8;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006742 }
6743
6744 return UsefulOutBuf_OutUBuf(&UOB);
6745}
6746
6747
Laurence Lundblade37286c02022-09-03 10:05:02 -07006748/**
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006749 * @brief Check and/or complete exponent and mantissa item.
Laurence Lundblade37286c02022-09-03 10:05:02 -07006750 *
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006751 * @param[in] pMe The decoder context.
6752 * @param[in] TagSpec Expected type(s).
6753 * @param[in,out] pItem See below.
Laurence Lundblade37286c02022-09-03 10:05:02 -07006754 *
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006755 * This is for decimal fractions and big floats, both of which are an
6756 * exponent and mantissa.
Laurence Lundblade37286c02022-09-03 10:05:02 -07006757 *
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006758 * If the item item had a tag number indicating it was a
6759 * decimal fraction or big float, then the input @c pItem will
6760 * have been decoded as exponent and mantissa. If there was
6761 * no tag number, the caller is asking this be decoded as a
6762 * big float or decimal fraction and @c pItem just has the
6763 * first item in an exponent and mantissa.
Laurence Lundblade37286c02022-09-03 10:05:02 -07006764 *
6765 * On output, the item is always a fully decoded decimal fraction or
6766 * big float.
6767 *
6768 * This errors out if the input type does not meet the TagSpec.
6769 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07006770static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006771QCBOR_Private_ExpMantissaTypeHandler(QCBORDecodeContext *pMe,
6772 const QCBOR_Private_TagSpec TagSpec,
6773 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006774{
6775 QCBORError uErr;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006776
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006777 /* pItem could either be a decoded exponent and mantissa or
6778 * the opening array of an undecoded exponent and mantissa. This
Laurence Lundblade37286c02022-09-03 10:05:02 -07006779 * check will succeed on either, but doesn't say which it was.
6780 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006781 uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07006782 if(uErr != QCBOR_SUCCESS) {
6783 goto Done;
6784 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006785
Laurence Lundblade37286c02022-09-03 10:05:02 -07006786 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006787 /* The item is an array, which means is is an undecoded exponent
6788 * and mantissa. This call consumes the items in the array and
6789 * results in a decoded exponent and mantissa in pItem. This is
Laurence Lundblade37286c02022-09-03 10:05:02 -07006790 * the case where there was no tag.
6791 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006792 uErr = QCBORDecode_Private_ExpMantissa(pMe, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006793 if(uErr != QCBOR_SUCCESS) {
6794 goto Done;
6795 }
6796
Laurence Lundblade37286c02022-09-03 10:05:02 -07006797 /* The above decode didn't determine whether it is a decimal
6798 * fraction or big num. Which of these two depends on what the
6799 * caller wants it decoded as since there is no tag, so fish the
6800 * type out of the TagSpec. */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006801 pItem->uDataType = QCBOR_Private_ExpMantissaDataType(TagSpec.uTaggedTypes[0], pItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07006802
6803 /* No need to check the type again. All that we need to know was
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006804 * that it decoded correctly as a exponent and mantissa. The
Laurence Lundblade37286c02022-09-03 10:05:02 -07006805 * QCBOR type is set out by what was requested.
6806 */
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006807 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07006808
6809 /* If the item was not an array and the check passed, then
6810 * it is a fully decoded big float or decimal fraction and
6811 * matches what is requested.
6812 */
6813
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006814Done:
6815 return uErr;
6816}
6817
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006818
Laurence Lundblade37286c02022-09-03 10:05:02 -07006819/* Some notes from the work to disable tags.
6820 *
6821 * The API for big floats and decimal fractions seems good.
6822 * If there's any issue with it it's that the code size to
6823 * implement is a bit large because of the conversion
6824 * to/from int and bignum that is required. There is no API
6825 * that doesn't do the conversion so dead stripping will never
6826 * leave that code out.
6827 *
6828 * The implementation itself seems correct, but not as clean
6829 * and neat as it could be. It could probably be smaller too.
6830 *
6831 * The implementation has three main parts / functions
6832 * - The decoding of the array of two
6833 * - All the tag and type checking for the various API functions
6834 * - Conversion to/from bignum and int
6835 *
6836 * The type checking seems like it wastes the most code for
6837 * what it needs to do.
6838 *
6839 * The inlining for the conversion is probably making the
6840 * overall code base larger.
6841 *
6842 * The tests cases could be organized a lot better and be
6843 * more thorough.
6844 *
6845 * Seems also like there could be more common code in the
6846 * first tier part of the public API. Some functions only
6847 * vary by a TagSpec.
6848 */
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006849
6850/**
6851 * @brief Common processor for exponent and mantissa.
6852 *
6853 * @param[in] pMe The decode context.
6854 * @param[in] TagSpec The expected/allowed tags.
6855 * @param[in] pItem The data item to process.
6856 * @param[out] pnMantissa The returned mantissa as an int64_t.
6857 * @param[out] pnExponent The returned exponent as an int64_t.
6858 *
6859 * This handles exponent and mantissa for base 2 and 10. This
6860 * is limited to a mantissa that is an int64_t. See also
6861 * QCBORDecode_Private_ProcessExpMantissaBig().
6862 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006863static void
6864QCBOR_Private_ProcessExpMantissa(QCBORDecodeContext *pMe,
6865 const QCBOR_Private_TagSpec TagSpec,
6866 QCBORItem *pItem,
6867 int64_t *pnMantissa,
6868 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006869{
6870 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006871
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006872 uErr = QCBOR_Private_ExpMantissaTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006873 if(uErr != QCBOR_SUCCESS) {
6874 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006875 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006876
Laurence Lundblade9b334962020-08-27 10:55:53 -07006877 switch (pItem->uDataType) {
6878
6879 case QCBOR_TYPE_DECIMAL_FRACTION:
6880 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade9b334962020-08-27 10:55:53 -07006881 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade37286c02022-09-03 10:05:02 -07006882 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
Laurence Lundblade9b334962020-08-27 10:55:53 -07006883 break;
6884
Laurence Lundblade37286c02022-09-03 10:05:02 -07006885#ifndef QCBOR_DISABLE_TAGS
6886 /* If tags are disabled, mantissas can never be big nums */
Laurence Lundblade9b334962020-08-27 10:55:53 -07006887 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
6888 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
6889 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006890 uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
Laurence Lundblade9b334962020-08-27 10:55:53 -07006891 break;
6892
6893 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
6894 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
6895 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006896 uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
Laurence Lundblade9b334962020-08-27 10:55:53 -07006897 break;
Laurence Lundblade37286c02022-09-03 10:05:02 -07006898#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade9b334962020-08-27 10:55:53 -07006899
6900 default:
6901 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
6902 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006903
6904 Done:
6905 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006906}
6907
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006908
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006909/**
6910 * @brief Decode exponent and mantissa into a big number.
6911 *
6912 * @param[in] pMe The decode context.
6913 * @param[in] TagSpec The expected/allowed tags.
6914 * @param[in] pItem Item to decode and convert.
6915 * @param[in] BufferForMantissa Buffer to output mantissa into.
6916 * @param[out] pMantissa The output mantissa.
6917 * @param[out] pbIsNegative The sign of the output.
6918 * @param[out] pnExponent The mantissa of the output.
6919 *
6920 * This is the common processing of a decimal fraction or a big float
6921 * into a big number. This will decode and consume all the CBOR items
6922 * that make up the decimal fraction or big float.
6923 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006924static void
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006925QCBORDecode_Private_ProcessExpMantissaBig(QCBORDecodeContext *pMe,
6926 const QCBOR_Private_TagSpec TagSpec,
6927 QCBORItem *pItem,
6928 const UsefulBuf BufferForMantissa,
6929 UsefulBufC *pMantissa,
6930 bool *pbIsNegative,
6931 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006932{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006933 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006934
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006935 uErr = QCBOR_Private_ExpMantissaTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006936 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006937 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006938 }
6939
6940 uint64_t uMantissa;
6941
6942 switch (pItem->uDataType) {
6943
6944 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006945 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07006946 /* See comments in ExponentiateNN() on handling INT64_MIN */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006947 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
6948 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
6949 *pbIsNegative = false;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07006950 } else if(pItem->val.expAndMantissa.Mantissa.nInt != INT64_MIN) {
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006951 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
6952 *pbIsNegative = true;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07006953 } else {
6954 uMantissa = (uint64_t)INT64_MAX+1;
6955 *pbIsNegative = true;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006956 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006957 *pMantissa = QCBOR_Private_ConvertIntToBigNum(uMantissa,
6958 BufferForMantissa);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006959 *pnExponent = pItem->val.expAndMantissa.nExponent;
6960 break;
6961
Laurence Lundblade37286c02022-09-03 10:05:02 -07006962#ifndef QCBOR_DISABLE_TAGS
6963 /* If tags are disabled, mantissas can never be big nums */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006964 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006965 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006966 *pnExponent = pItem->val.expAndMantissa.nExponent;
6967 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
6968 *pbIsNegative = false;
6969 break;
6970
6971 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006972 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006973 *pnExponent = pItem->val.expAndMantissa.nExponent;
6974 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
6975 *pbIsNegative = true;
6976 break;
Laurence Lundblade37286c02022-09-03 10:05:02 -07006977#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006978
6979 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006980 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006981 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006982
6983Done:
6984 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006985}
6986
6987
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006988/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006989 * Public function, see header qcbor/qcbor_decode.h file
6990 */
6991void
6992QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
6993 const uint8_t uTagRequirement,
6994 int64_t *pnMantissa,
6995 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006996{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006997 if(pMe->uLastError != QCBOR_SUCCESS) {
6998 return;
6999 }
7000
7001 QCBORItem Item;
7002 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
7003 if(uError) {
7004 pMe->uLastError = (uint8_t)uError;
7005 return;
7006 }
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 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007015
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007016 QCBOR_Private_ProcessExpMantissa(pMe,
7017 TagSpec,
7018 &Item,
7019 pnMantissa,
7020 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007021}
7022
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007023
7024/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007025 * Public function, see header qcbor/qcbor_decode.h file
7026 */
7027void
7028QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
7029 const int64_t nLabel,
7030 const uint8_t uTagRequirement,
7031 int64_t *pnMantissa,
7032 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007033{
7034 if(pMe->uLastError != QCBOR_SUCCESS) {
7035 return;
7036 }
7037
7038 QCBORItem Item;
7039 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
7040
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007041 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007042 {
7043 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07007044 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
7045 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
7046 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007047 };
7048
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007049 QCBOR_Private_ProcessExpMantissa(pMe,
7050 TagSpec,
7051 &Item,
7052 pnMantissa,
7053 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007054}
7055
7056
7057/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007058 * Public function, see header qcbor/qcbor_decode.h file
7059 */
7060void
7061QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
7062 const char *szLabel,
7063 const uint8_t uTagRequirement,
7064 int64_t *pnMantissa,
7065 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007066{
7067 if(pMe->uLastError != QCBOR_SUCCESS) {
7068 return;
7069 }
7070
7071 QCBORItem Item;
7072 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
7073
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007074 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007075 {
7076 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07007077 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
7078 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
7079 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007080 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07007081
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007082 QCBOR_Private_ProcessExpMantissa(pMe,
7083 TagSpec,
7084 &Item,
7085 pnMantissa,
7086 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007087}
7088
7089
7090/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007091 * Public function, see header qcbor/qcbor_decode.h file
7092 */
7093void
7094QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
7095 const uint8_t uTagRequirement,
7096 const UsefulBuf MantissaBuffer,
7097 UsefulBufC *pMantissa,
7098 bool *pbMantissaIsNegative,
7099 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007100{
7101 if(pMe->uLastError != QCBOR_SUCCESS) {
7102 return;
7103 }
7104
7105 QCBORItem Item;
7106 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
7107 if(uError) {
7108 pMe->uLastError = (uint8_t)uError;
7109 return;
7110 }
7111
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007112 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007113 {
7114 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07007115 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
7116 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
7117 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007118 };
7119
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07007120 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
7121 TagSpec,
7122 &Item,
7123 MantissaBuffer,
7124 pMantissa,
7125 pbMantissaIsNegative,
7126 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007127}
7128
7129
7130/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007131 * Public function, see header qcbor/qcbor_decode.h file
7132 */
7133void
7134QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
7135 const int64_t nLabel,
7136 const uint8_t uTagRequirement,
7137 const UsefulBuf BufferForMantissa,
7138 UsefulBufC *pMantissa,
7139 bool *pbIsNegative,
7140 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07007141{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007142 if(pMe->uLastError != QCBOR_SUCCESS) {
7143 return;
7144 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07007145
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007146 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07007147 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07007148 if(pMe->uLastError != QCBOR_SUCCESS) {
7149 return;
7150 }
7151
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007152 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007153 {
7154 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07007155 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
7156 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
7157 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007158 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007159
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07007160 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
7161 TagSpec,
7162 &Item,
7163 BufferForMantissa,
7164 pMantissa,
7165 pbIsNegative,
7166 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007167}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07007168
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007169
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007170/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007171 * Public function, see header qcbor/qcbor_decode.h file
7172 */
7173void
7174QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
7175 const char *szLabel,
7176 const uint8_t uTagRequirement,
7177 const UsefulBuf BufferForMantissa,
7178 UsefulBufC *pMantissa,
7179 bool *pbIsNegative,
7180 int64_t *pnExponent)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007181{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007182 if(pMe->uLastError != QCBOR_SUCCESS) {
7183 return;
7184 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007185
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007186 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007187 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
7188 if(pMe->uLastError != QCBOR_SUCCESS) {
7189 return;
7190 }
7191
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007192 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007193 {
7194 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07007195 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
7196 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
7197 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007198 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007199
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07007200 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
7201 TagSpec,
7202 &Item,
7203 BufferForMantissa,
7204 pMantissa,
7205 pbIsNegative,
7206 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007207}
7208
7209
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007210/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007211 * Public function, see header qcbor/qcbor_decode.h file
7212 */
7213void
7214QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
7215 const uint8_t uTagRequirement,
7216 int64_t *pnMantissa,
7217 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007218{
7219 if(pMe->uLastError != QCBOR_SUCCESS) {
7220 return;
7221 }
7222
7223 QCBORItem Item;
7224 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
7225 if(uError) {
7226 pMe->uLastError = (uint8_t)uError;
7227 return;
7228 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007229 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007230 {
7231 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07007232 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
7233 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
7234 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007235 };
7236
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007237 QCBOR_Private_ProcessExpMantissa(pMe,
7238 TagSpec,
7239 &Item,
7240 pnMantissa,
7241 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007242}
7243
7244
7245/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007246 * Public function, see header qcbor/qcbor_decode.h file
7247 */
7248void
7249QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
7250 const int64_t nLabel,
7251 const uint8_t uTagRequirement,
7252 int64_t *pnMantissa,
7253 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007254{
7255 if(pMe->uLastError != QCBOR_SUCCESS) {
7256 return;
7257 }
7258
7259 QCBORItem Item;
7260 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
7261 if(pMe->uLastError != QCBOR_SUCCESS) {
7262 return;
7263 }
7264
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007265 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007266 {
7267 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07007268 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
7269 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
7270 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007271 };
7272
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007273 QCBOR_Private_ProcessExpMantissa(pMe,
7274 TagSpec,
7275 &Item,
7276 pnMantissa,
7277 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007278}
7279
7280
7281/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007282 * Public function, see header qcbor/qcbor_decode.h file
7283 */
7284void
7285QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
7286 const char *szLabel,
7287 const uint8_t uTagRequirement,
7288 int64_t *pnMantissa,
7289 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007290{
7291 if(pMe->uLastError != QCBOR_SUCCESS) {
7292 return;
7293 }
7294
7295 QCBORItem Item;
7296 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
7297 if(pMe->uLastError != QCBOR_SUCCESS) {
7298 return;
7299 }
7300
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007301 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007302 {
7303 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07007304 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
7305 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
7306 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007307 };
7308
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007309 QCBOR_Private_ProcessExpMantissa(pMe,
7310 TagSpec,
7311 &Item,
7312 pnMantissa,
7313 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007314}
7315
7316
7317/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007318 * Public function, see header qcbor/qcbor_decode.h file
7319 */
7320void
7321QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
7322 const uint8_t uTagRequirement,
7323 const UsefulBuf MantissaBuffer,
7324 UsefulBufC *pMantissa,
7325 bool *pbMantissaIsNegative,
7326 int64_t *pnExponent)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007327{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007328 if(pMe->uLastError != QCBOR_SUCCESS) {
7329 return;
7330 }
7331
7332 QCBORItem Item;
7333 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
7334 if(uError) {
7335 pMe->uLastError = (uint8_t)uError;
7336 return;
7337 }
7338
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007339 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007340 {
7341 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07007342 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
7343 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
7344 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007345 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007346
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07007347 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
7348 TagSpec,
7349 &Item,
7350 MantissaBuffer,
7351 pMantissa,
7352 pbMantissaIsNegative,
7353 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007354}
7355
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007356
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007357/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007358 * Public function, see header qcbor/qcbor_decode.h file
7359 */
7360void
7361QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
7362 const int64_t nLabel,
7363 const uint8_t uTagRequirement,
7364 const UsefulBuf BufferForMantissa,
7365 UsefulBufC *pMantissa,
7366 bool *pbIsNegative,
7367 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007368{
7369 if(pMe->uLastError != QCBOR_SUCCESS) {
7370 return;
7371 }
7372
7373 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007374 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
7375 if(pMe->uLastError != QCBOR_SUCCESS) {
7376 return;
7377 }
7378
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007379 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007380 {
7381 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07007382 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
7383 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
7384 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007385 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007386
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07007387 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
7388 TagSpec,
7389 &Item,
7390 BufferForMantissa,
7391 pMantissa,
7392 pbIsNegative,
7393 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007394}
7395
7396
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007397/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007398 * Public function, see header qcbor/qcbor_decode.h file
7399 */
7400void
7401QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
7402 const char *szLabel,
7403 const uint8_t uTagRequirement,
7404 const UsefulBuf BufferForMantissa,
7405 UsefulBufC *pMantissa,
7406 bool *pbIsNegative,
7407 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007408{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007409 if(pMe->uLastError != QCBOR_SUCCESS) {
7410 return;
7411 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007412
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007413 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007414 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
7415 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07007416 return;
7417 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07007418
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007419 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007420 {
7421 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07007422 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
7423 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
7424 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007425 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007426
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07007427 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
7428 TagSpec,
7429 &Item,
7430 BufferForMantissa,
7431 pMantissa,
7432 pbIsNegative,
7433 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07007434}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007435
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07007436#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */