blob: 2992ce19452102201d333fb86c4e7b1b1c6ccfe3 [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 Lundblade721b56e2024-10-22 03:02:04 -070037#include "qcbor/qcbor_tag_decode.h"
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080038#include "ieee754.h" /* Does not use math.h */
Laurence Lundbladec7114722020-08-13 05:11:40 -070039
40#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080041
42#include <math.h> /* For isnan(), llround(), llroudf(), round(), roundf(),
43 * pow(), exp2()
44 */
45#include <fenv.h> /* feclearexcept(), fetestexcept() */
46
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080047#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070048
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070049
Laurence Lundblade68cb61c2023-02-12 13:21:44 -080050#if (defined(__GNUC__) && !defined(__clang__))
Laurence Lundblade8e36f812024-01-26 10:59:29 -070051/*
Laurence Lundblade68cb61c2023-02-12 13:21:44 -080052 * This is how the -Wmaybe-uninitialized compiler warning is
53 * handled. It can’t be ignored because some version of gcc enable it
54 * with -Wall which is a common and useful gcc warning option. It also
55 * can’t be ignored because it is the goal of QCBOR to compile clean
56 * out of the box in all environments.
57 *
58 * The big problem with -Wmaybe-uninitialized is that it generates
59 * false positives. It complains things are uninitialized when they
60 * are not. This is because it is not a thorough static analyzer. This
61 * is why “maybe” is in its name. The problem is it is just not
62 * thorough enough to understand all the code (and someone saw fit to
63 * put it in gcc and worse to enable it with -Wall).
64 *
65 * One solution would be to change the code so -Wmaybe-uninitialized
66 * doesn’t get confused, for example adding an unnecessary extra
67 * initialization to zero. (If variables were truly uninitialized, the
68 * correct path is to understand the code thoroughly and set them to
69 * the correct value at the correct time; in essence this is already
70 * done; -Wmaybe-uninitialized just can’t tell). This path is not
71 * taken because it makes the code bigger and is kind of the tail
72 * wagging the dog.
73 *
74 * The solution here is to just use a pragma to disable it for the
75 * whole file. Disabling it for each line makes the code fairly ugly
76 * requiring #pragma to push, pop and ignore. Another reason is the
77 * warnings issues vary by version of gcc and which optimization
78 * optimizations are selected. Another reason is that compilers other
79 * than gcc don’t have -Wmaybe-uninitialized.
80 *
81 * One may ask how to be sure these warnings are false positives and
82 * not real issues. 1) The code has been read carefully to check. 2)
83 * Testing is pretty thorough. 3) This code has been run through
84 * thorough high-quality static analyzers.
85 *
86 * In particularly, most of the warnings are about
87 * Item.Item->uDataType being uninitialized. QCBORDecode_GetNext()
88 * *always* sets this value and test case confirm
89 * this. -Wmaybe-uninitialized just can't tell.
90 *
91 * https://stackoverflow.com/questions/5080848/disable-gcc-may-be-used-uninitialized-on-a-particular-variable
92 */
93#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
Laurence Lundblade8e36f812024-01-26 10:59:29 -070094#endif
Laurence Lundblade68cb61c2023-02-12 13:21:44 -080095
96
97
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080098
Laurence Lundbladea9489f82020-09-12 13:50:56 -070099#define SIZEOF_C_ARRAY(array,type) (sizeof(array)/sizeof(type))
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700100
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700101
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800102
103
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700104static bool
105QCBORItem_IsMapOrArray(const QCBORItem Item)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700106{
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700107 const uint8_t uDataType = Item.uDataType;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700108 return uDataType == QCBOR_TYPE_MAP ||
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700109#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
110 uDataType == QCBOR_TYPE_MAP_AS_ARRAY ||
111#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
112 uDataType == QCBOR_TYPE_ARRAY;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700113}
114
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700115static bool
116QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem Item)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700117{
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700118 if(!QCBORItem_IsMapOrArray(Item)){
Laurence Lundblade02625d42020-06-25 14:41:41 -0700119 return false;
120 }
121
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700122 if(Item.val.uCount != 0) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700123 return false;
124 }
125 return true;
126}
127
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700128static bool
129QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem Item)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700130{
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800131#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700132 if(!QCBORItem_IsMapOrArray(Item)){
Laurence Lundblade02625d42020-06-25 14:41:41 -0700133 return false;
134 }
135
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700136 if(Item.val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700137 return false;
138 }
139 return true;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800140#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700141 (void)Item;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800142 return false;
143#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700144}
145
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700146/* Return true if the labels in Item1 and Item2 are the same.
147 Works only for integer and string labels. Returns false
148 for any other type. */
149static bool
150QCBORItem_MatchLabel(const QCBORItem Item1, const QCBORItem Item2)
151{
152 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
153 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
154 return true;
155 }
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700156#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700157 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
158 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
159 return true;
160 }
161 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
162 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
163 return true;
164 }
165 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
166 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
167 return true;
168 }
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700169#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700170 }
171
172 /* Other label types are never matched */
173 return false;
174}
175
176
177/*
178 Returns true if Item1 and Item2 are the same type
179 or if either are of QCBOR_TYPE_ANY.
180 */
181static bool
182QCBORItem_MatchType(const QCBORItem Item1, const QCBORItem Item2)
183{
184 if(Item1.uDataType == Item2.uDataType) {
185 return true;
186 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
187 return true;
188 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
189 return true;
190 }
191 return false;
192}
193
Laurence Lundblade02625d42020-06-25 14:41:41 -0700194
Laurence Lundbladeee851742020-01-08 08:37:05 -0800195/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700196 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -0800197 ===========================================================================*/
198
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700199/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800200 * See comments about and typedef of QCBORDecodeNesting in qcbor_private.h,
201 * the data structure all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700202 */
203
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700204
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700205static uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700206DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700207{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700208 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800209 /* Limit in DecodeNesting_Descend against more than
210 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700211 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700212 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700213}
214
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700215
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700216static uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700217DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700218{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700219 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800220 /* Limit in DecodeNesting_Descend against more than
221 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700222 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700223 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700224}
225
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700226
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700227static uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700228DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700229{
230 return pNesting->pCurrentBounded->u.ma.uStartOffset;
231}
232
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700233
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700234static bool
Laurence Lundblade085d7952020-07-24 10:26:30 -0700235DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
236{
237 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
238 return true;
239 } else {
240 return false;
241 }
242}
243
244
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700245static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700246DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700247{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700248 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700249 return true;
250 } else {
251 return false;
252 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700253}
254
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700255
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700256static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700257DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700258{
259 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800260 /* Not a map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700261 return false;
262 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800263
264#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700265 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800266 /* Is indefinite */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700267 return false;
268 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800269
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800270#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
271
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800272 /* All checks passed; is a definte length map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700273 return true;
274}
275
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700276static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700277DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700278{
279 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800280 /* is a byte string */
Laurence Lundblade642282a2020-06-23 12:00:33 -0700281 return true;
282 }
283 return false;
284}
285
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700286
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700287static bool
288DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700289{
290 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
291 return true;
292 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700293 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700294 return true;
295 }
296 return false;
297}
298
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700299
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700300static void
301DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700302{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800303 /* Should be only called on maps and arrays */
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700304 /*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800305 * DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
306 * larger than DecodeNesting_EnterBoundedMode which keeps it less than
307 * uin32_t so the cast is safe.
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700308 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700309 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700310
311 if(bIsEmpty) {
312 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
313 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700314}
315
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700316
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700317static void
318DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700319{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700320 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700321}
322
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700323
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700324static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700325DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700326{
327 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800328 /* No bounded map or array set up */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700329 return false;
330 }
331 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800332 /* Not a map or array; end of those is by byte count */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700333 return false;
334 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700335 if(!DecodeNesting_IsCurrentBounded(pNesting)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800336 /* In a traveral at a level deeper than the bounded level */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700337 return false;
338 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800339 /* Works for both definite- and indefinitelength maps/arrays */
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800340 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0 &&
341 pNesting->pCurrentBounded->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800342 /* Count is not zero, still unconsumed item */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700343 return false;
344 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800345 /* All checks passed, got to the end of an array or map*/
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700346 return true;
347}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700348
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700349
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700350static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700351DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700352{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800353 /* Must only be called on map / array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700354 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
355 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700356 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700357 return false;
358 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700359}
360
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700361
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700362static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700363DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700364{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700365 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
366 return true;
367 } else {
368 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700369 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700370}
371
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700372
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700373static bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700374DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700375{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700376 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700377 return false;
378 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700379
Laurence Lundblade5db34da2024-05-30 03:14:35 -0700380 uint8_t uItemDataType = pNesting->pCurrentBounded->uLevelType;
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700381#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
Laurence Lundblade5db34da2024-05-30 03:14:35 -0700382 if(uItemDataType == QCBOR_TYPE_MAP_AS_ARRAY) {
383 uItemDataType = QCBOR_TYPE_ARRAY;
384 }
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700385#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
Laurence Lundblade5db34da2024-05-30 03:14:35 -0700386
387 if(uItemDataType != uType) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700388 return false;
389 }
390
391 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700392}
393
Laurence Lundblade02625d42020-06-25 14:41:41 -0700394
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700395static void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700396DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700397{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800398 /* Only call on a definite-length array / map */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700399 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700400}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700401
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700402
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700403static void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700404DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
405{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800406 /* Only call on a definite-length array / map */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700407 pNesting->pCurrent->u.ma.uCountCursor++;
408}
409
410
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700411static void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700412DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
413{
414 pNesting->pCurrent--;
415}
416
Laurence Lundblade02625d42020-06-25 14:41:41 -0700417
418static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700419DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700420{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800421 /* Error out if nesting is too deep */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700422 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700423 return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700424 }
425
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800426 /* The actual descend */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700427 pNesting->pCurrent++;
428
429 pNesting->pCurrent->uLevelType = uType;
430
431 return QCBOR_SUCCESS;
432}
433
434
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700435static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800436DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting,
437 bool bIsEmpty,
438 size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700439{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700440 /*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800441 * Should only be called on map/array.
442 *
443 * Have descended into this before this is called. The job here is
444 * just to mark it in bounded mode.
445 *
446 * Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
447 * uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET.
448 *
449 * Cast of uOffset to uint32_t for cases where SIZE_MAX < UINT32_MAX.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700450 */
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -0800451 if((uint32_t)uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700452 return QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700453 }
454
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700455 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700456
457 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700458
459 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700460}
461
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700462
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700463static QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700464DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundbladeb95afec2024-08-26 10:51:28 -0700465 const uint8_t uQCBORType,
466 const uint16_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700467{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700468 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700469
470 if(uCount == 0) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800471 /* Nothing to do for empty definite-length arrays. They are just are
472 * effectively the same as an item that is not a map or array.
473 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700474 goto Done;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800475 /* Empty indefinite-length maps and arrays are handled elsewhere */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700476 }
477
Laurence Lundbladeb95afec2024-08-26 10:51:28 -0700478 /* Rely on check in QCBOR_Private_DecodeArrayOrMap() for definite-length
479 * arrays and maps that are too long */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700480
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700481 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700482 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700483 goto Done;
484 }
485
Laurence Lundbladeb95afec2024-08-26 10:51:28 -0700486 pNesting->pCurrent->u.ma.uCountCursor = uCount;
487 pNesting->pCurrent->u.ma.uCountTotal = uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700488
489 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700490
491Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700492 return uError;;
493}
494
495
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700496static void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700497DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
498{
499 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
500}
501
502
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700503static void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700504DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
505{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700506 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700507 pNesting->pCurrentBounded--;
508 if(DecodeNesting_IsCurrentBounded(pNesting)) {
509 break;
510 }
511 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700512}
513
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800514
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700515static void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700516DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
517{
518 pNesting->pCurrent = pNesting->pCurrentBounded;
519}
520
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700521
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700522static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700523DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700524 uint32_t uEndOffset,
525 uint32_t uStartOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700526{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700527 QCBORError uError;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700528
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700529 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700530 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700531 goto Done;
532 }
533
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800534 /* Fill in the new byte string level */
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700535 pNesting->pCurrent->u.bs.uSavedEndOffset = uEndOffset;
536 pNesting->pCurrent->u.bs.uBstrStartOffset = uStartOffset;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700537
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800538 /* Bstr wrapped levels are always bounded */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700539 pNesting->pCurrentBounded = pNesting->pCurrent;
540
541Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700542 return uError;;
543}
544
Laurence Lundbladed0304932020-06-27 10:59:38 -0700545
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700546static void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700547DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700548{
549 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700550}
551
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700552
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700553static void
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800554DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
555{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700556 if(pNesting->pCurrent->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
557 pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
558 }
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800559}
560
561
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700562static void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700563DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700564{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700565 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700566 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
567 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700568}
569
570
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700571static void
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800572DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting,
573 QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700574{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700575 *pSave = *pNesting;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700576}
577
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700578
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700579static void
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800580DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting,
581 const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700582{
583 *pNesting = *pSave;
584}
585
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700586
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700587static uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700588DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700589{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700590 return pMe->pCurrentBounded->u.bs.uSavedEndOffset;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700591}
592
593
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800594
595
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800596#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladeee851742020-01-08 08:37:05 -0800597/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800598 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
599
600 The following four functions are pretty wrappers for invocation of
601 the string allocator supplied by the caller.
602
Laurence Lundbladeee851742020-01-08 08:37:05 -0800603 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800604
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700605static void
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800606StringAllocator_Free(const QCBORInternalAllocator *pMe, const void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800607{
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300608 /* This cast to uintptr_t suppresses the "-Wcast-qual" warnings.
609 * This is the one place where the const needs to be cast away so const can
610 * be use in the rest of the code.
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800611 */
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300612 (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)(uintptr_t)pMem, 0);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800613}
614
Laurence Lundbladeee851742020-01-08 08:37:05 -0800615// StringAllocator_Reallocate called with pMem NULL is
616// equal to StringAllocator_Allocate()
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700617static UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800618StringAllocator_Reallocate(const QCBORInternalAllocator *pMe,
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800619 const void *pMem,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800620 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800621{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800622 /* See comment in StringAllocator_Free() */
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300623 return (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)(uintptr_t)pMem, uSize);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800624}
625
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700626static UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800627StringAllocator_Allocate(const QCBORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800628{
629 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
630}
631
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700632static void
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800633StringAllocator_Destruct(const QCBORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800634{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800635 /* See comment in StringAllocator_Free() */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800636 if(pMe->pfAllocator) {
637 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
638 }
639}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800640#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800641
642
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800643
644
Laurence Lundbladeee851742020-01-08 08:37:05 -0800645/*===========================================================================
646 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700647
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800648 See qcbor/qcbor_decode.h for definition of the object
649 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800650 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700651/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800652 * Public function, see header file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700653 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700654void
655QCBORDecode_Init(QCBORDecodeContext *pMe,
656 UsefulBufC EncodedCBOR,
657 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700658{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800659 memset(pMe, 0, sizeof(QCBORDecodeContext));
660 UsefulInputBuf_Init(&(pMe->InBuf), EncodedCBOR);
661 /* Don't bother with error check on decode mode. If a bad value is
662 * passed it will just act as if the default normal mode of 0 was set.
663 */
664 pMe->uDecodeMode = (uint8_t)nDecodeMode;
665 DecodeNesting_Init(&(pMe->nesting));
666
667 /* Inialize me->auMappedTags to CBOR_TAG_INVALID16. See
668 * GetNext_TaggedItem() and MapTagNumber(). */
669 memset(pMe->auMappedTags, 0xff, sizeof(pMe->auMappedTags));
Laurence Lundblade721b56e2024-10-22 03:02:04 -0700670
671 pMe->uTagNumberCheckOffset = SIZE_MAX;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700672}
673
674
Laurence Lundblade721b56e2024-10-22 03:02:04 -0700675/*
676 * Public function, see header file
677 */
678void
679QCBORDecode_CompatibilityV1(QCBORDecodeContext *pMe)
680{
681 pMe->uDecodeMode |= QCBOR_DECODE_UNPROCESSED_TAG_NUMBERS;
682#ifndef QCBOR_DISABLE_TAGS
683 QCBORDecode_InstallTagDecoders(pMe, QCBORDecode_TagDecoderTablev1, NULL);
684#endif /* ! QCBOR_DISABLE_TAGS */
685}
686
687
688
689
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800690#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
691
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700692/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800693 * Public function, see header file
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700694 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700695void
696QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
697 QCBORStringAllocate pfAllocateFunction,
698 void *pAllocateContext,
699 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700700{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800701 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
702 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
703 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700704}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800705#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700706
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800707
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800708
709
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.
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -0700776 * @param[in] bRequirePreferred Require preferred serialization for argument.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800777 * @param[out] pnMajorType The decoded major type.
778 * @param[out] puArgument The decoded argument.
779 * @param[out] pnAdditionalInfo The decoded Lower 5 bits of initial byte.
780 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -0700781 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved features
782 * @retval QCBOR_ERR_HIT_END Unexpected end of input
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800783 *
784 * This decodes the CBOR "head" that every CBOR data item has. See
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -0700785 * longer description in QCBOREncode_EncodeHead().
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800786 *
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -0700787 * This does the network to host byte order conversion. The conversion
788 * here also provides the conversion for floats in addition to that
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800789 * 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,
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -0700797#ifndef QCBOR_DISABLE_DECODE_CONFORMANCE
798 bool bRequirePreferred,
799#endif
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700800 int *pnMajorType,
801 uint64_t *puArgument,
802 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700803{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800804 QCBORError uReturn;
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -0700805 uint64_t uArgument;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800806
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -0700807 /* Get and break down initial byte that every CBOR data item has */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800808 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800809 const int nTmpMajorType = nInitialByte >> 5;
810 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -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 Lundblade9b2ae8a2024-07-12 11:00:20 -0700821 /* This shift-and-add gives the endian conversion. */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800822 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
823 }
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -0700824
825#ifndef QCBOR_DISABLE_DECODE_CONFORMANCE
826 /* If requested, check that argument is in preferred form */
827 if(bRequirePreferred) {
828 uint64_t uMinArgument;
829
830 if(nAdditionalInfo == LEN_IS_ONE_BYTE) {
831 if(uArgument < 24) {
832 uReturn = QCBOR_ERR_PREFERRED_CONFORMANCE;
833 goto Done;
834 }
835 } else {
836 if(nTmpMajorType != CBOR_MAJOR_TYPE_SIMPLE) {
837 /* Check only if not a floating-point number */
838 int nArgLen = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE - 1];
839 uMinArgument = UINT64_MAX >> ((int)sizeof(uint64_t) - nArgLen) * 8;
840 if(uArgument <= uMinArgument) {
841 uReturn = QCBOR_ERR_PREFERRED_CONFORMANCE;
842 goto Done;
843 }
844 }
845 }
846 }
847#endif /* ! QCBOR_DISABLE_DECODE_CONFORMANCE */
848
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800849 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800850 /* The reserved and thus-far unused additional info values */
851 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800852 goto Done;
853 } else {
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -0700854#ifndef QCBOR_DISABLE_DECODE_CONFORMANCE
855 if(bRequirePreferred && nAdditionalInfo == LEN_IS_INDEFINITE) {
856 uReturn = QCBOR_ERR_PREFERRED_CONFORMANCE;
857 goto Done;
858 }
859#endif /* ! QCBOR_DISABLE_DECODE_CONFORMANCE */
860
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800861 /* Less than 24, additional info is argument or 31, an
862 * indefinite-length. No more bytes to get.
863 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800864 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700865 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800866
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700867 if(UsefulInputBuf_GetError(pUInBuf)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800868 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700869 goto Done;
870 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800871
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800872 /* All successful if arrived here. */
873 uReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800874 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800875 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800876 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800877
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700878Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800879 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700880}
881
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800882
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800883/**
884 * @brief Decode integer types, major types 0 and 1.
885 *
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700886 * @param[in] nMajorType The CBOR major type (0 or 1).
887 * @param[in] uArgument The argument from the head.
888 * @param[in] nAdditionalInfo So it can be error-checked.
889 * @param[out] pDecodedItem The filled in decoded item.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800890 *
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700891 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered.
892 * @retval QCBOR_ERR_BAD_INT nAdditionalInfo indicated indefinte.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800893 *
894 * Must only be called when major type is 0 or 1.
895 *
896 * CBOR doesn't explicitly specify two's compliment for integers but
897 * all CPUs use it these days and the test vectors in the RFC are
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700898 * so. All integers in encoded CBOR are unsigned and the CBOR major
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800899 * type indicates positive or negative. CBOR can express positive
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700900 * integers up to 2^64 - 1 negative integers down to -2^64. Note that
901 * negative numbers can be one more
902 * away from zero than positive because there is no negative zero.
903 *
904 * The "65-bit negs" are values CBOR can encode that can't fit
905 * into an int64_t or uint64_t. They decoded as a special type
906 * QCBOR_TYPE_65BIT_NEG_INT. Not that this type does NOT
907 * take into account the offset of one for CBOR negative integers.
908 * It must be applied to get the correct value. Applying this offset
909 * would overflow a uint64_t.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700910 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700911static QCBORError
912QCBOR_Private_DecodeInteger(const int nMajorType,
913 const uint64_t uArgument,
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700914 const int nAdditionalInfo,
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700915 QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700916{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800917 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800918
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700919 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
920 uReturn = QCBOR_ERR_BAD_INT;
921 goto Done;
922 }
923
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700924 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800925 if (uArgument <= INT64_MAX) {
926 pDecodedItem->val.int64 = (int64_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700927 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800928
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700929 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800930 pDecodedItem->val.uint64 = uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700931 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700932 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800933
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700934 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800935 if(uArgument <= INT64_MAX) {
Laurence Lundblade14ce2282024-07-24 22:13:35 -0700936 /* INT64_MIN is one further away from 0 than INT64_MAX
937 * so the -1 here doesn't overflow. */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800938 pDecodedItem->val.int64 = (-(int64_t)uArgument) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700939 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800940
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700941 } else {
Laurence Lundblade2d493002024-02-01 11:09:17 -0700942 pDecodedItem->val.uint64 = uArgument;
943 pDecodedItem->uDataType = QCBOR_TYPE_65BIT_NEG_INT;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700944 }
945 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800946
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700947Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800948 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700949}
950
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800951
Laurence Lundbladeec290b82024-06-10 11:10:54 -0700952/**
953 * @brief Decode text and byte strings
954 *
955 * @param[in] pMe Decoder context.
956 * @param[in] bAllocate Whether to allocate and copy string.
957 * @param[in] nMajorType Whether it is a byte or text string.
958 * @param[in] uStrLen The length of the string.
959 * @param[in] nAdditionalInfo Whether it is an indefinite-length string.
960 * @param[out] pDecodedItem The filled-in decoded item.
961 *
962 * @retval QCBOR_ERR_HIT_END Unexpected end of input.
963 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
964 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
965 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Allocation requested, but no allocator
966 *
967 * This reads @c uStrlen bytes from the input and fills in @c
968 * pDecodedItem. If @c bAllocate is true, then memory for the string
969 * is allocated.
970 */
971static QCBORError
972QCBOR_Private_DecodeString(QCBORDecodeContext *pMe,
973 const bool bAllocate,
974 const int nMajorType,
975 const uint64_t uStrLen,
976 const int nAdditionalInfo,
977 QCBORItem *pDecodedItem)
978{
979 QCBORError uReturn = QCBOR_SUCCESS;
980
981 /* ---- Figure out the major type ---- */
982 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
983 #error QCBOR_TYPE_BYTE_STRING not lined up with major type
984 #endif
985
986 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
987 #error QCBOR_TYPE_TEXT_STRING not lined up with major type
988 #endif
989 pDecodedItem->uDataType = (uint8_t)(nMajorType + 4);
990
991 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
992 /* --- Just the head of an indefinite-length string --- */
993 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
994
995 } else {
996 /* --- A definite-length string --- */
997 /* --- (which might be a chunk of an indefinte-length string) --- */
998
999 /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
1000 * CPUs. This check makes the casts to size_t below safe.
1001 *
1002 * The max is 4 bytes less than the largest sizeof() so this can be
1003 * tested by putting a SIZE_MAX length in the CBOR test input (no
1004 * one will care the limit on strings is 4 bytes shorter).
1005 */
1006 if(uStrLen > SIZE_MAX-4) {
1007 uReturn = QCBOR_ERR_STRING_TOO_LONG;
1008 goto Done;
1009 }
1010
1011 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(&(pMe->InBuf), (size_t)uStrLen);
1012 if(UsefulBuf_IsNULLC(Bytes)) {
1013 /* Failed to get the bytes for this string item */
1014 uReturn = QCBOR_ERR_HIT_END;
1015 goto Done;
1016 }
1017
1018 if(bAllocate) {
1019#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
1020 /* --- Put string in allocated memory --- */
1021
1022 /* Note that this is not where allocation to coalesce
1023 * indefinite-length strings is done. This is for when the
1024 * caller has requested all strings be allocated. Disabling
1025 * indefinite length strings also disables this allocate-all
1026 * option.
1027 */
1028
1029 if(pMe->StringAllocator.pfAllocator == NULL) {
1030 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1031 goto Done;
1032 }
1033 UsefulBuf NewMem = StringAllocator_Allocate(&(pMe->StringAllocator), (size_t)uStrLen);
1034 if(UsefulBuf_IsNULL(NewMem)) {
1035 uReturn = QCBOR_ERR_STRING_ALLOCATE;
1036 goto Done;
1037 }
1038 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
1039 pDecodedItem->uDataAlloc = 1;
1040#else
1041 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1042#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1043 } else {
1044 /* --- Normal case with no string allocator --- */
1045 pDecodedItem->val.string = Bytes;
1046 }
1047 }
1048
1049Done:
1050 return uReturn;
1051}
1052
1053
1054/**
1055 * @brief Decode array or map.
1056 *
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001057 * @param[in] uDecodeMode3Bit Decoder mode.
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001058 * @param[in] nMajorType Whether it is a byte or text string.
1059 * @param[in] uItemCount The length of the string.
1060 * @param[in] nAdditionalInfo Whether it is an indefinite-length.
1061 * @param[out] pDecodedItem The filled-in decoded item.
1062 *
1063 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinites disabled.
1064 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG Too many items in array/map.
1065 *
1066 * Not much to do for arrays and maps. Just the type item count (but a
1067 * little messy because of ifdefs for indefinite-lengths and
1068 * map-as-array decoding).
1069 *
1070 * This also does the bulk of the work for @ref
1071 * QCBOR_DECODE_MODE_MAP_AS_ARRAY, a special mode to handle
1072 * arbitrarily complex map labels. This ifdefs out with
1073 * QCBOR_DISABLE_NON_INTEGER_LABELS.
1074 */
1075static QCBORError
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001076QCBOR_Private_DecodeArrayOrMap(const uint8_t uDecodeMode3Bit,
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001077 const int nMajorType,
Laurence Lundbladeb95afec2024-08-26 10:51:28 -07001078 uint64_t uItemCount,
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001079 const int nAdditionalInfo,
1080 QCBORItem *pDecodedItem)
1081{
1082 QCBORError uReturn;
1083
1084 /* ------ Sort out the data type ------ */
1085 #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
1086 #error QCBOR_TYPE_ARRAY value not lined up with major type
1087 #endif
1088
1089 #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
1090 #error QCBOR_TYPE_MAP value not lined up with major type
1091 #endif
1092 pDecodedItem->uDataType = (uint8_t)nMajorType;
1093#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001094 if(uDecodeMode3Bit == QCBOR_DECODE_MODE_MAP_AS_ARRAY && nMajorType == QCBOR_TYPE_MAP) {
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001095 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
1096 }
1097#else
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001098 (void)uDecodeMode3Bit;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001099#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
1100
1101 uReturn = QCBOR_SUCCESS;
1102
1103 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1104 /* ------ Indefinite-length array/map ----- */
1105#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
1106 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
1107#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1108 uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
1109#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1110 } else {
Laurence Lundbladeb95afec2024-08-26 10:51:28 -07001111 /* ----- Definite-length array/map ----- */
1112 if(uItemCount > (nMajorType == QCBOR_TYPE_MAP ? QCBOR_MAX_ITEMS_IN_MAP : QCBOR_MAX_ITEMS_IN_ARRAY)) {
1113 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001114
Laurence Lundbladeb95afec2024-08-26 10:51:28 -07001115 } else {
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001116#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001117 if(uDecodeMode3Bit == QCBOR_DECODE_MODE_MAP_AS_ARRAY && nMajorType == QCBOR_TYPE_MAP) {
Laurence Lundbladeb95afec2024-08-26 10:51:28 -07001118 /* ------ Map as array ------ */
1119 uItemCount *= 2;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001120 }
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001121#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
Laurence Lundbladeb95afec2024-08-26 10:51:28 -07001122
1123 /* cast OK because of check above */
1124 pDecodedItem->val.uCount = (uint16_t)uItemCount;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001125 }
1126 }
1127
1128 return uReturn;
1129}
1130
1131
1132/**
1133 * @brief Decode a tag number.
1134 *
1135 * @param[in] uTagNumber The length of the string.
1136 * @param[in] nAdditionalInfo So this can be error-checked.
1137 * @param[out] pDecodedItem The filled-in decoded item.
1138 *
1139 * @retval QCBOR_ERR_BAD_INT nAdditionalInfo is LEN_IS_INDEFINITE.
1140 * @retval QCBOR_ERR_TAGS_DISABLED QCBOR_DISABLE_TAGS is defined.
1141 *
1142 * Not much to do for tags, but fill in pDecodedItem and check for
1143 * error in nAdditionalInfo.
1144 */
1145static QCBORError
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001146QCBOR_Private_DecodeTagNumber(const uint64_t uTagNumber,
1147 const int nAdditionalInfo,
1148 QCBORItem *pDecodedItem)
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001149{
1150#ifndef QCBOR_DISABLE_TAGS
1151 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1152 return QCBOR_ERR_BAD_INT;
1153 } else {
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001154 pDecodedItem->val.uTagNumber = uTagNumber;
1155 pDecodedItem->uDataType = QCBOR_TYPE_TAG_NUMBER;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001156 return QCBOR_SUCCESS;
1157 }
1158#else /* QCBOR_DISABLE_TAGS */
1159 (void)nAdditionalInfo;
Laurence Lundblade6c9a8242024-06-12 20:34:52 -07001160 (void)uTagNumber;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001161 (void)pDecodedItem;
1162 return QCBOR_ERR_TAGS_DISABLED;
1163#endif /* QCBOR_DISABLE_TAGS */
1164}
1165
1166
Laurence Lundblade14ce2282024-07-24 22:13:35 -07001167#ifndef USEFULBUF_DISABLE_ALL_FLOAT
1168
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001169#if !defined(QCBOR_DISABLE_DECODE_CONFORMANCE) && !defined(QCBOR_DISABLE_PREFERRED_FLOAT)
1170
1171static QCBORError
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001172QCBORDecode_Private_HalfConformance(const double d, const uint8_t uDecodeMode3Bit)
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001173{
1174 struct IEEE754_ToInt ToInt;
1175
1176 /* Only need to check for conversion to integer because
1177 * half-precision is always preferred serialization. Don't
1178 * need special checker for half-precision because whole
1179 * numbers always convert perfectly from half to double.
1180 *
1181 * This catches half-precision with NaN payload too.
1182 *
1183 * The only thing allowed here is a double/half-precision that
1184 * can't be converted to anything but a double.
1185 */
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001186 if(uDecodeMode3Bit >= QCBOR_DECODE_MODE_DCBOR) {
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001187 ToInt = IEEE754_DoubleToInt(d);
1188 if(ToInt.type != QCBOR_TYPE_DOUBLE) {
1189 return QCBOR_ERR_DCBOR_CONFORMANCE;
1190 }
1191 }
1192
1193 return QCBOR_SUCCESS;
1194}
1195
1196
1197static QCBORError
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001198QCBORDecode_Private_SingleConformance(const float f, const uint8_t uDecodeMode3Bit)
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001199{
1200 struct IEEE754_ToInt ToInt;
1201 IEEE754_union ToSmaller;
1202
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001203 if(uDecodeMode3Bit >= QCBOR_DECODE_MODE_DCBOR) {
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001204 /* See if it could have been encoded as an integer */
1205 ToInt = IEEE754_SingleToInt(f);
1206 if(ToInt.type == IEEE754_ToInt_IS_INT || ToInt.type == IEEE754_ToInt_IS_UINT) {
1207 return QCBOR_ERR_DCBOR_CONFORMANCE;
1208 }
1209
1210 /* Make sure there is no NaN payload */
1211 if(IEEE754_SingleHasNaNPayload(f)) {
1212 return QCBOR_ERR_DCBOR_CONFORMANCE;
1213 }
1214 }
1215
1216 /* See if it could have been encoded shorter */
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001217 if(uDecodeMode3Bit >= QCBOR_DECODE_MODE_PREFERRED) {
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001218 ToSmaller = IEEE754_SingleToHalf(f, true);
1219 if(ToSmaller.uSize != sizeof(float)) {
1220 return QCBOR_ERR_PREFERRED_CONFORMANCE;
1221 }
1222 }
1223
1224 return QCBOR_SUCCESS;
1225}
1226
1227
1228static QCBORError
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001229QCBORDecode_Private_DoubleConformance(const double d, uint8_t uDecodeMode3Bit)
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001230{
1231 struct IEEE754_ToInt ToInt;
1232 IEEE754_union ToSmaller;
1233
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001234 if(uDecodeMode3Bit >= QCBOR_DECODE_MODE_DCBOR) {
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001235 /* See if it could have been encoded as an integer */
1236 ToInt = IEEE754_DoubleToInt(d);
1237 if(ToInt.type == IEEE754_ToInt_IS_INT || ToInt.type == IEEE754_ToInt_IS_UINT) {
1238 return QCBOR_ERR_DCBOR_CONFORMANCE;
1239 }
1240 /* Make sure there is no NaN payload */
1241 if(IEEE754_DoubleHasNaNPayload(d)) {
1242 return QCBOR_ERR_DCBOR_CONFORMANCE;
1243 }
1244 }
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001245
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001246 /* See if it could have been encoded shorter */
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001247 if(uDecodeMode3Bit >= QCBOR_DECODE_MODE_PREFERRED) {
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001248 ToSmaller = IEEE754_DoubleToSmaller(d, true, true);
1249 if(ToSmaller.uSize != sizeof(double)) {
1250 return QCBOR_ERR_PREFERRED_CONFORMANCE;
1251 }
1252 }
1253
1254 return QCBOR_SUCCESS;
1255}
Laurence Lundblade14ce2282024-07-24 22:13:35 -07001256#else /* ! QCBOR_DISABLE_DECODE_CONFORMANCE && ! QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001257
1258static QCBORError
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001259QCBORDecode_Private_SingleConformance(const float f, uint8_t uDecodeMode3Bit)
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001260{
1261 (void)f;
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001262 if(uDecodeMode3Bit>= QCBOR_DECODE_MODE_PREFERRED) {
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001263 return QCBOR_ERR_CANT_CHECK_FLOAT_CONFORMANCE;
1264 } else {
1265 return QCBOR_SUCCESS;
1266 }
1267}
1268
1269static QCBORError
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001270QCBORDecode_Private_DoubleConformance(const double d, uint8_t uDecodeMode3Bit)
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001271{
1272 (void)d;
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001273 if(uDecodeMode3Bit>= QCBOR_DECODE_MODE_PREFERRED) {
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001274 return QCBOR_ERR_CANT_CHECK_FLOAT_CONFORMANCE;
1275 } else {
1276 return QCBOR_SUCCESS;
1277 }
1278}
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001279#endif /* ! QCBOR_DISABLE_DECODE_CONFORMANCE && ! QCBOR_DISABLE_PREFERRED_FLOAT */
1280
1281
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001282/*
1283 * Decode a float
1284 */
1285static QCBORError
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001286QCBOR_Private_DecodeFloat(const uint8_t uDecodeMode3Bit,
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001287 const int nAdditionalInfo,
1288 const uint64_t uArgument,
1289 QCBORItem *pDecodedItem)
1290{
1291 QCBORError uReturn = QCBOR_SUCCESS;
1292 float single;
1293
1294 (void)single; /* Avoid unused error from various #ifndefs */
1295
1296 switch(nAdditionalInfo) {
1297 case HALF_PREC_FLOAT: /* 25 */
1298#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
1299 /* Half-precision is returned as a double. The cast to
1300 * uint16_t is safe because the encoded value was 16 bits. It
1301 * was widened to 64 bits to be passed in here.
1302 */
1303 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uArgument);
1304 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
1305
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001306 uReturn = QCBORDecode_Private_HalfConformance(pDecodedItem->val.dfnum, uDecodeMode3Bit);
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001307 if(uReturn != QCBOR_SUCCESS) {
1308 break;
1309 }
1310#endif /* ! QCBOR_DISABLE_PREFERRED_FLOAT */
1311 uReturn = FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS);
1312 break;
1313
1314 case SINGLE_PREC_FLOAT: /* 26 */
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001315 /* Single precision is normally returned as a double since
1316 * double is widely supported, there is no loss of precision,
1317 * it makes it easy for the caller in most cases and it can
1318 * be converted back to single with no loss of precision
1319 *
1320 * The cast to uint32_t is safe because the encoded value was
1321 * 32 bits. It was widened to 64 bits to be passed in here.
1322 */
1323 single = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uArgument);
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001324 uReturn = QCBORDecode_Private_SingleConformance(single, uDecodeMode3Bit);
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001325 if(uReturn != QCBOR_SUCCESS) {
1326 break;
1327 }
1328
1329#ifndef QCBOR_DISABLE_FLOAT_HW_USE
1330 /* In the normal case, use HW to convert float to
1331 * double. */
1332 pDecodedItem->val.dfnum = (double)single;
1333 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
1334#else /* QCBOR_DISABLE_FLOAT_HW_USE */
1335 /* Use of float HW is disabled, return as a float. */
1336 pDecodedItem->val.fnum = single;
1337 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
1338
1339 /* IEEE754_FloatToDouble() could be used here to return as
1340 * a double, but it adds object code and most likely
1341 * anyone disabling FLOAT HW use doesn't care about floats
1342 * and wants to save object code.
1343 */
1344#endif /* ! QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001345 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
1346 break;
1347
1348 case DOUBLE_PREC_FLOAT: /* 27 */
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001349 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uArgument);
1350 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
1351
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001352 uReturn = QCBORDecode_Private_DoubleConformance(pDecodedItem->val.dfnum, uDecodeMode3Bit);
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001353 if(uReturn != QCBOR_SUCCESS) {
1354 break;
1355 }
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001356 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
1357 break;
1358 }
1359
1360 return uReturn;
1361}
Laurence Lundblade14ce2282024-07-24 22:13:35 -07001362#endif /* ! USEFULBUF_DISABLE_ALL_FLOAT */
1363
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001364
1365
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001366/* Make sure #define value line up as DecodeSimple counts on this. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001367#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
1368#error QCBOR_TYPE_FALSE macro value wrong
1369#endif
1370
1371#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
1372#error QCBOR_TYPE_TRUE macro value wrong
1373#endif
1374
1375#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
1376#error QCBOR_TYPE_NULL macro value wrong
1377#endif
1378
1379#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
1380#error QCBOR_TYPE_UNDEF macro value wrong
1381#endif
1382
Laurence Lundblade0f99d692018-09-26 14:39:28 -07001383#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
1384#error QCBOR_TYPE_BREAK macro value wrong
1385#endif
1386
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001387#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
1388#error QCBOR_TYPE_DOUBLE macro value wrong
1389#endif
1390
1391#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
1392#error QCBOR_TYPE_FLOAT macro value wrong
1393#endif
1394
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001395/**
1396 * @brief Decode major type 7 -- true, false, floating-point, break...
1397 *
1398 * @param[in] nAdditionalInfo The lower five bits from the initial byte.
1399 * @param[in] uArgument The argument from the head.
1400 * @param[out] pDecodedItem The filled in decoded item.
1401 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001402 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1403 * of half-precision disabled
1404 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all float
1405 * decode is disabled.
1406 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of simple
1407 * type in input.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001408 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001409static QCBORError
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001410QCBOR_Private_DecodeType7(const uint8_t uDecodeMode3Bit,
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001411 const int nAdditionalInfo,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001412 const uint64_t uArgument,
1413 QCBORItem *pDecodedItem)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001414{
1415 QCBORError uReturn = QCBOR_SUCCESS;
1416
1417 /* uAdditionalInfo is 5 bits from the initial byte. Compile time
1418 * checks above make sure uAdditionalInfo values line up with
1419 * uDataType values. DecodeHead() never returns an AdditionalInfo
1420 * > 0x1f so cast is safe.
1421 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001422 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001423
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001424 switch(nAdditionalInfo) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001425 /* No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they
1426 * are caught before this is called.
1427 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001428
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001429 case HALF_PREC_FLOAT: /* 25 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001430 case SINGLE_PREC_FLOAT: /* 26 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001431 case DOUBLE_PREC_FLOAT: /* 27 */
Laurence Lundblade14ce2282024-07-24 22:13:35 -07001432#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001433 uReturn = QCBOR_Private_DecodeFloat(uDecodeMode3Bit, nAdditionalInfo, uArgument, pDecodedItem);
Laurence Lundblade14ce2282024-07-24 22:13:35 -07001434#else
1435 uReturn = QCBOR_ERR_ALL_FLOAT_DISABLED;
1436#endif /* ! USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade12d32c52018-09-19 11:25:27 -07001437 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001438
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001439 case CBOR_SIMPLEV_FALSE: /* 20 */
1440 case CBOR_SIMPLEV_TRUE: /* 21 */
1441 case CBOR_SIMPLEV_NULL: /* 22 */
1442 case CBOR_SIMPLEV_UNDEF: /* 23 */
1443 case CBOR_SIMPLE_BREAK: /* 31 */
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001444#ifndef QCBOR_DISABLE_DECODE_CONFORMANCE
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001445 if(uDecodeMode3Bit >= QCBOR_ENCODE_MODE_DCBOR &&
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001446 nAdditionalInfo == CBOR_SIMPLEV_UNDEF) {
1447 uReturn = QCBOR_ERR_DCBOR_CONFORMANCE;
1448 goto Done;
1449 }
1450#endif /* ! QCBOR_DISABLE_DECODE_CONFORMANCE */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001451 break; /* nothing to do */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001452
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001453 case CBOR_SIMPLEV_ONEBYTE: /* 24 */
1454 if(uArgument <= CBOR_SIMPLE_BREAK) {
1455 /* This takes out f8 00 ... f8 1f which should be encoded
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001456 * as e0 … f7 -- preferred serialization check for simple values.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001457 */
1458 uReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001459 goto Done;
1460 }
Laurence Lundblade5e390822019-01-06 12:35:01 -08001461 /* FALLTHROUGH */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001462
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001463 default: /* 0-19 */
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001464#ifndef QCBOR_DISABLE_DECODE_CONFORMANCE
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001465 if(uDecodeMode3Bit >= QCBOR_ENCODE_MODE_DCBOR &&
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001466 (uArgument < CBOR_SIMPLEV_FALSE || uArgument > CBOR_SIMPLEV_NULL)) {
1467 uReturn = QCBOR_ERR_DCBOR_CONFORMANCE;
1468 goto Done;
1469 }
1470#endif /* !QCBOR_DISABLE_DECODE_CONFORMANCE */
1471
1472 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
1473 /* QCBOR_Private_DecodeHead() will make uArgument equal to
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001474 * nAdditionalInfo when nAdditionalInfo is < 24. This cast is
1475 * safe because the 2, 4 and 8 byte lengths of uNumber are in
1476 * the double/float cases above
Laurence Lundbladeee851742020-01-08 08:37:05 -08001477 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001478 pDecodedItem->val.uSimple = (uint8_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001479 break;
1480 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001481
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001482Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001483 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001484}
1485
1486
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001487/**
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001488 * @brief Decode a single primitive data item (decode layer 6).
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001489 *
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001490 * @param[in] pMe Decoder context.
1491 * @param[in] bAllocateStrings If true, use allocator for strings.
1492 * @param[out] pDecodedItem The filled-in decoded item.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001493 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001494 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1495 * features
1496 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1497 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1498 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1499 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001500 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Allocation requested, but no allocator
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001501 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1502 * of half-precision disabled
1503 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1504 * float decode is disabled.
1505 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1506 * simple type in input.
1507 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1508 * in input, but indefinite
1509 * lengths disabled.
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001510 * @retval QCBOR_ERR_BAD_INT nAdditionalInfo indicated indefinte.
1511 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG Too many items in array/map.
1512 * @retval QCBOR_ERR_TAGS_DISABLED QCBOR_DISABLE_TAGS is defined.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001513 *
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001514 * This decodes the most primitive/atomic data item. It does no
1515 * combining of data items.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001516 */
1517static QCBORError
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001518QCBOR_Private_DecodeAtomicDataItem(QCBORDecodeContext *pMe,
1519 const bool bAllocateStrings,
1520 QCBORItem *pDecodedItem)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001521{
1522 QCBORError uReturn;
Laurence Lundbladede2e1502024-08-26 11:37:05 -07001523 int nMajorType = 0;
1524 uint64_t uArgument = 0;
1525 int nAdditionalInfo = 0;
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001526 uint8_t uDecodeMode3Bit = pMe->uDecodeMode & QCBOR_DECODE_MODE_MASK;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001527
Laurence Lundblade14ce2282024-07-24 22:13:35 -07001528 memset(pDecodedItem, 0, sizeof(QCBORItem));
1529
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001530 /* Decode the "head" that every CBOR item has into the major type,
1531 * argument and the additional info.
1532 */
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001533 uReturn = QCBOR_Private_DecodeHead(&(pMe->InBuf),
1534#ifndef QCBOR_DISABLE_DECODE_CONFORMANCE
1535 // TODO: make this prettier; will optimizer take out stuff without ifdef?
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001536 uDecodeMode3Bit >= QCBOR_DECODE_MODE_PREFERRED,
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001537#endif /* !QCBOR_DISABLE_DECODE_CONFORMANCE */
1538 &nMajorType,
1539 &uArgument,
1540 &nAdditionalInfo);
Laurence Lundblade14ce2282024-07-24 22:13:35 -07001541
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001542 if(uReturn != QCBOR_SUCCESS) {
1543 return uReturn;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001544 }
1545
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001546 /* All the functions below get inlined by the optimizer. This code
1547 * is easier to read with them all being similar functions, even if
1548 * some functions don't do much.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001549 */
1550 switch (nMajorType) {
1551 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1552 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001553 return QCBOR_Private_DecodeInteger(nMajorType, uArgument, nAdditionalInfo, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001554 break;
1555
1556 case CBOR_MAJOR_TYPE_BYTE_STRING: /* Major type 2 */
1557 case CBOR_MAJOR_TYPE_TEXT_STRING: /* Major type 3 */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001558 return QCBOR_Private_DecodeString(pMe, bAllocateStrings, nMajorType, uArgument, nAdditionalInfo, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001559 break;
1560
1561 case CBOR_MAJOR_TYPE_ARRAY: /* Major type 4 */
1562 case CBOR_MAJOR_TYPE_MAP: /* Major type 5 */
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001563 return QCBOR_Private_DecodeArrayOrMap(uDecodeMode3Bit, nMajorType, uArgument, nAdditionalInfo, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001564 break;
1565
1566 case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001567 return QCBOR_Private_DecodeTagNumber(uArgument, nAdditionalInfo, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001568 break;
1569
1570 case CBOR_MAJOR_TYPE_SIMPLE:
1571 /* Major type 7: float, double, true, false, null... */
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001572 return QCBOR_Private_DecodeType7(uDecodeMode3Bit, nAdditionalInfo, uArgument, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001573 break;
1574
1575 default:
1576 /* Never happens because DecodeHead() should never return > 7 */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001577 return QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001578 break;
1579 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001580}
1581
1582
1583/**
1584 * @brief Process indefinite-length strings (decode layer 5).
1585 *
1586 * @param[in] pMe Decoder context
1587 * @param[out] pDecodedItem The decoded item that work is done on.
1588 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001589 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1590 * features
1591 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1592 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1593 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1594 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
1595 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1596 * of half-precision disabled
1597 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1598 * float decode is disabled.
1599 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1600 * simple type in input.
1601 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1602 * in input, but indefinite
1603 * lengths disabled.
1604 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Indefinite-length string in input,
1605 * but no string allocator.
1606 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK Error in indefinite-length string.
1607 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED Indefinite-length string in
1608 * input, but indefinite-length
1609 * strings are disabled.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001610 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001611 * If @c pDecodedItem is not an indefinite-length string, this does nothing.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001612 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001613 * If it is, this loops getting the subsequent chunk data items that
1614 * make up the string. The string allocator is used to make a
1615 * contiguous buffer for the chunks. When this completes @c
1616 * pDecodedItem contains the put-together string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001617 *
1618 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001619 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001620static QCBORError
1621QCBORDecode_Private_GetNextFullString(QCBORDecodeContext *pMe,
1622 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001623{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001624 /* Aproximate stack usage
1625 * 64-bit 32-bit
1626 * local vars 32 16
1627 * 2 UsefulBufs 32 16
1628 * QCBORItem 56 52
1629 * TOTAL 120 74
1630 */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001631 QCBORError uReturn;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001632
1633 /* A note about string allocation -- Memory for strings is
1634 * allocated either because 1) indefinte-length string chunks are
1635 * being coalecsed or 2) caller has requested all strings be
1636 * allocated. The first case is handed below here. The second case
1637 * is handled in DecodeString if the bAllocate is true. That
1638 * boolean originates here with pMe->bStringAllocateAll immediately
1639 * below. That is, QCBOR_Private_DecodeAtomicDataItem() is called
1640 * in two different contexts here 1) main-line processing which is
1641 * where definite-length strings need to be allocated if
1642 * bStringAllocateAll is true and 2) processing chunks of
1643 * indefinite-lengths strings in in which case there must be no
1644 * allocation.
1645 */
1646
1647
1648 uReturn = QCBOR_Private_DecodeAtomicDataItem(pMe, pMe->bStringAllocateAll, pDecodedItem);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001649 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001650 goto Done;
1651 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001652
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001653 /* This is where out-of-place break is detected for the whole
1654 * decoding stack. Break is an error for everything that calls
1655 * QCBORDecode_Private_GetNextFullString(), so the check is
1656 * centralized here.
1657 */
1658 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
1659 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001660 goto Done;
1661 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001662
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001663
1664 /* Skip out if not an indefinite-length string */
1665 const uint8_t uStringType = pDecodedItem->uDataType;
1666 if(uStringType != QCBOR_TYPE_BYTE_STRING &&
1667 uStringType != QCBOR_TYPE_TEXT_STRING) {
1668 goto Done;
1669 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001670 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1671 goto Done;
1672 }
1673
1674#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001675 /* Can't decode indefinite-length strings without a string allocator */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001676 if(!pMe->StringAllocator.pfAllocator) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001677 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1678 goto Done;
1679 }
1680
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001681 /* Loop getting chunks of the indefinite-length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001682 UsefulBufC FullString = NULLUsefulBufC;
1683
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001684 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001685 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001686 QCBORItem StringChunkItem;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001687 /* Pass false to DecodeAtomicDataItem() because the individual
1688 * string chunks in an indefinite-length must not be
1689 * allocated. They are always copied into the allocated
1690 * contiguous buffer allocated here.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001691 */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001692 uReturn = QCBOR_Private_DecodeAtomicDataItem(pMe, false, &StringChunkItem);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001693 if(uReturn) {
1694 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001695 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001696
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001697 /* Is item is the marker for end of the indefinite-length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001698 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001699 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001700 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301701 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001702 break;
1703 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001704
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001705 /* All chunks must be of the same type, the type of the item
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001706 * that introduces the indefinite-length string. This also
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001707 * catches errors where the chunk is not a string at all and an
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001708 * indefinite-length string inside an indefinite-length string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001709 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001710 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001711 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1712 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001713 break;
1714 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001715
David Navarro9123e5b2022-03-28 16:04:03 +02001716 if (StringChunkItem.val.string.len > 0) {
1717 /* The first time throurgh FullString.ptr is NULL and this is
1718 * equivalent to StringAllocator_Allocate(). Subsequently it is
1719 * not NULL and a reallocation happens.
1720 */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001721 UsefulBuf NewMem = StringAllocator_Reallocate(&(pMe->StringAllocator),
David Navarro9123e5b2022-03-28 16:04:03 +02001722 FullString.ptr,
1723 FullString.len + StringChunkItem.val.string.len);
David Navarro9123e5b2022-03-28 16:04:03 +02001724 if(UsefulBuf_IsNULL(NewMem)) {
1725 uReturn = QCBOR_ERR_STRING_ALLOCATE;
1726 break;
1727 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001728
David Navarro9123e5b2022-03-28 16:04:03 +02001729 /* Copy new string chunk to the end of accumulated string */
1730 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001731 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001732 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001733
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001734 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1735 /* Getting the item failed, clean up the allocated memory */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001736 StringAllocator_Free(&(pMe->StringAllocator), FullString.ptr);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001737 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001738#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1739 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1740#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001741
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001742Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001743 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001744}
1745
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001746
Laurence Lundblade37286c02022-09-03 10:05:02 -07001747#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001748/**
1749 * @brief This converts a tag number to a shorter mapped value for storage.
1750 *
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001751 * @param[in] pMe The decode context.
1752 * @param[in] uUnMappedTag The tag number to map
1753 * @param[out] puMappedTagNumber The stored tag number.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001754 *
1755 * @return error code.
1756 *
1757 * The main point of mapping tag numbers is make QCBORItem
1758 * smaller. With this mapping storage of 4 tags takes up 8
1759 * bytes. Without, it would take up 32 bytes.
1760 *
1761 * This maps tag numbers greater than QCBOR_LAST_UNMAPPED_TAG.
1762 * QCBOR_LAST_UNMAPPED_TAG is a little smaller than MAX_UINT16.
1763 *
1764 * See also UnMapTagNumber() and @ref QCBORItem.
1765 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001766static QCBORError
1767QCBORDecode_Private_MapTagNumber(QCBORDecodeContext *pMe,
1768 const uint64_t uUnMappedTag,
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001769 uint16_t *puMappedTagNumber)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001770{
1771 if(uUnMappedTag > QCBOR_LAST_UNMAPPED_TAG) {
1772 unsigned uTagMapIndex;
1773 /* Is there room in the tag map, or is it in it already? */
1774 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
1775 if(pMe->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID64) {
1776 break;
1777 }
1778 if(pMe->auMappedTags[uTagMapIndex] == uUnMappedTag) {
1779 break;
1780 }
1781 }
1782 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1783 return QCBOR_ERR_TOO_MANY_TAGS;
1784 }
1785
1786 /* Covers the cases where tag is new and were it is already in the map */
1787 pMe->auMappedTags[uTagMapIndex] = uUnMappedTag;
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001788 *puMappedTagNumber = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001789
1790 } else {
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001791 *puMappedTagNumber = (uint16_t)uUnMappedTag;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001792 }
1793
1794 return QCBOR_SUCCESS;
1795}
1796
1797
1798/**
1799 * @brief This converts a mapped tag number to the actual tag number.
1800 *
1801 * @param[in] pMe The decode context.
1802 * @param[in] uMappedTagNumber The stored tag number.
1803 *
1804 * @return The actual tag number is returned or
1805 * @ref CBOR_TAG_INVALID64 on error.
1806 *
1807 * This is the reverse of MapTagNumber()
1808 */
1809static uint64_t
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001810QCBORDecode_Private_UnMapTagNumber(const QCBORDecodeContext *pMe,
1811 const uint16_t uMappedTagNumber)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001812{
1813 if(uMappedTagNumber <= QCBOR_LAST_UNMAPPED_TAG) {
1814 return uMappedTagNumber;
1815 } else if(uMappedTagNumber == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001816 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001817 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001818 /* This won't be negative because of code below in
1819 * MapTagNumber()
1820 */
1821 const unsigned uIndex = uMappedTagNumber - (QCBOR_LAST_UNMAPPED_TAG + 1);
1822 return pMe->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001823 }
1824}
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001825
1826
1827static const struct QCBORTagDecoderEntry *
1828QCBORDecode_Private_LookUpTagDecoder(const struct QCBORTagDecoderEntry *pTagContentTable,
1829 const uint64_t uTagNumber)
1830{
1831 const struct QCBORTagDecoderEntry *pTE;
1832
1833 if(pTagContentTable == NULL) {
1834 return NULL;
1835 }
1836
1837 for(pTE = pTagContentTable; pTE->uTagNumber != CBOR_TAG_INVALID64; pTE++) {
1838 if(pTE->uTagNumber == uTagNumber || pTE->uTagNumber == CBOR_TAG_ANY) {
1839 break;
1840 }
1841 }
1842
1843 if(pTE->uTagNumber == CBOR_TAG_INVALID64) {
1844 return NULL;
1845 }
1846
1847 return pTE;
1848}
1849#endif /* ! QCBOR_DISABLE_TAGS */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001850
Laurence Lundblade9b334962020-08-27 10:55:53 -07001851
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001852/**
1853 * @brief Aggregate all tags wrapping a data item (decode layer 4).
1854 *
1855 * @param[in] pMe Decoder context
1856 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001857 *
1858 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1859 * features
1860 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1861 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1862 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1863 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
1864 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1865 * of half-precision disabled
1866 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1867 * float decode is disabled.
1868 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1869 * simple type in input.
1870 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1871 * in input, but indefinite
1872 * lengths disabled.
1873 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Indefinite-length string in input,
1874 * but no string allocator.
1875 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK Error in indefinite-length string.
1876 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED Indefinite-length string in
1877 * input, but indefinite-length
1878 * strings are disabled.
1879 * @retval QCBOR_ERR_TOO_MANY_TAGS Too many tag numbers on item.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001880 *
1881 * This loops getting atomic data items until one is not a tag
1882 * number. Usually this is largely pass-through because most
1883 * item are not tag numbers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001884 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001885static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001886QCBORDecode_Private_GetNextTagNumber(QCBORDecodeContext *pMe,
1887 QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001888{
Laurence Lundblade37286c02022-09-03 10:05:02 -07001889#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001890 int nIndex;
1891 QCBORError uErr;
1892 uint16_t uMappedTagNumber;
1893 QCBORError uReturn;
1894
1895 /* Accummulate the tag numbers from multiple items here and then
1896 * copy them into the last item, the non-tag-number item.
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001897 */
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001898 QCBORMappedTagNumbers auTagNumbers;;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001899
1900 /* Initialize to CBOR_TAG_INVALID16 */
1901 #if CBOR_TAG_INVALID16 != 0xffff
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001902 /* Be sure the memset is initializing to CBOR_TAG_INVALID16 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001903 #err CBOR_TAG_INVALID16 tag not defined as expected
1904 #endif
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001905 memset(auTagNumbers, 0xff, sizeof(auTagNumbers));
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001906
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001907 /* Loop fetching data items until the item fetched is not a tag number */
1908 uReturn = QCBOR_SUCCESS;
1909 for(nIndex = 0; ; nIndex++) {
1910 uErr = QCBORDecode_Private_GetNextFullString(pMe, pDecodedItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07001911 if(uErr != QCBOR_SUCCESS) {
1912 uReturn = uErr;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001913 break;
1914 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001915
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001916 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG_NUMBER) {
1917 /* Successful exit from loop; maybe got some tags, maybe not */
1918 memcpy(pDecodedItem->auTagNumbers, auTagNumbers, sizeof(auTagNumbers));
1919 break;
1920 }
1921
1922 if(nIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
1923 /* No room in the item's tag number array */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001924 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001925 /* Continue on to get all tag numbers wrapping this item even
1926 * though it is erroring out in the end. This allows decoding
1927 * to continue. This is a QCBOR resource limit error, not a
1928 * problem with being well-formed CBOR.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001929 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001930 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001931 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001932
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001933 /* Map the tag number */
1934 uMappedTagNumber = 0;
1935 uReturn = QCBORDecode_Private_MapTagNumber(pMe, pDecodedItem->val.uTagNumber, &uMappedTagNumber);
1936 /* Continue even on error so as to consume all tag numbers
1937 * wrapping this data item so decoding can go on. If
1938 * QCBORDecode_Private_MapTagNumber() errors once it will
1939 * continue to error.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001940 */
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001941
1942 auTagNumbers[nIndex] = uMappedTagNumber;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001943 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001944
Laurence Lundblade9b334962020-08-27 10:55:53 -07001945 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001946
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001947#else /* ! QCBOR_DISABLE_TAGS */
Laurence Lundblade37286c02022-09-03 10:05:02 -07001948
Laurence Lundblade0f01ac62024-02-18 23:07:07 -07001949 return QCBORDecode_Private_GetNextFullString(pMe, pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07001950
Laurence Lundblade721b56e2024-10-22 03:02:04 -07001951#endif /* ! QCBOR_DISABLE_TAGS */
Laurence Lundblade37286c02022-09-03 10:05:02 -07001952}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001953
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001954
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001955/**
1956 * @brief Combine a map entry label and value into one item (decode layer 3).
1957 *
1958 * @param[in] pMe Decoder context
1959 * @param[out] pDecodedItem The decoded item that work is done on.
1960 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001961 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1962 * features
1963 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1964 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1965 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1966 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
1967 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1968 * of half-precision disabled
1969 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1970 * float decode is disabled.
1971 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1972 * simple type in input.
1973 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1974 * in input, but indefinite
1975 * lengths disabled.
1976 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Indefinite-length string in input,
1977 * but no string allocator.
1978 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK Error in indefinite-length string.
1979 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED Indefinite-length string in
1980 * input, but indefinite-length
1981 * strings are disabled.
1982 * @retval QCBOR_ERR_TOO_MANY_TAGS Too many tag numbers on item.
1983 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG Too many items in array.
1984 * @retval QCBOR_ERR_MAP_LABEL_TYPE Map label not string or integer.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001985 *
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001986 * If the current nesting level is a map, then this combines pairs of
1987 * items into one data item with a label and value.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001988 *
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001989 * This is passthrough if the current nesting level is not a map.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001990 *
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001991 * This also implements maps-as-array mode where a map is treated like
1992 * an array to allow caller to do their own label processing.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001993 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001994static QCBORError
1995QCBORDecode_Private_GetNextMapEntry(QCBORDecodeContext *pMe,
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001996 QCBORItem *pDecodedItem,
1997 uint32_t *puLabelEndOffset)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001998{
Laurence Lundbladeec290b82024-06-10 11:10:54 -07001999 QCBORItem LabelItem;
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07002000 QCBORError uErr, uErr2;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07002001
2002 uErr = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
2003 if(QCBORDecode_IsUnrecoverableError(uErr)) {
Laurence Lundblade742df4a2018-10-13 20:07:17 +08002004 goto Done;
2005 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002006
Laurence Lundbladeec290b82024-06-10 11:10:54 -07002007 if(!DecodeNesting_IsCurrentTypeMap(&(pMe->nesting))) {
2008 /* Not decoding a map. Nothing to do. */
2009 /* When decoding maps-as-arrays, the type will be
2010 * QCBOR_TYPE_MAP_AS_ARRAY and this function will exit
2011 * here. This is now map processing for maps-as-arrays is not
2012 * done. */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002013 goto Done;
2014 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08002015
Laurence Lundbladeec290b82024-06-10 11:10:54 -07002016 /* Decoding a map entry, so the item decoded above was the label */
2017 LabelItem = *pDecodedItem;
Laurence Lundblade721b56e2024-10-22 03:02:04 -07002018
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07002019 if(puLabelEndOffset != NULL) {
2020 /* Cast is OK because lengths are all 32-bit in QCBOR */
2021 *puLabelEndOffset = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
2022 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08002023
Laurence Lundbladeec290b82024-06-10 11:10:54 -07002024 /* Get the value of the map item */
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07002025 uErr2 = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
2026 if(QCBORDecode_IsUnrecoverableError(uErr2)) {
2027 uErr = uErr2;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07002028 goto Done;
2029 }
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07002030 if(uErr2 != QCBOR_SUCCESS) {
Laurence Lundblade721b56e2024-10-22 03:02:04 -07002031 /* The recoverable error for the value overrides the recoverable
2032 * error for the label, if there was an error for the label */
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07002033 uErr = uErr2;
2034 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002035
Laurence Lundbladeec290b82024-06-10 11:10:54 -07002036 /* Combine the label item and value item into one */
2037 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
2038 pDecodedItem->uLabelType = LabelItem.uDataType;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09002039
Laurence Lundbladeec290b82024-06-10 11:10:54 -07002040#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
Laurence Lundblade721b56e2024-10-22 03:02:04 -07002041 /* TODO: QCBOR_DECODE_MODE_MAP_STRINGS_ONLY might have been a bad idea. Maybe
Laurence Lundbladeec290b82024-06-10 11:10:54 -07002042 * get rid of it in QCBOR 2.0
2043 */
Laurence Lundblade721b56e2024-10-22 03:02:04 -07002044 if((pMe->uDecodeMode & QCBOR_DECODE_MODE_MASK) == QCBOR_DECODE_MODE_MAP_STRINGS_ONLY &&
Laurence Lundbladeec290b82024-06-10 11:10:54 -07002045 LabelItem.uDataType != QCBOR_TYPE_TEXT_STRING) {
2046 uErr = QCBOR_ERR_MAP_LABEL_TYPE;
2047 goto Done;
2048 }
2049#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
2050
2051 switch(LabelItem.uDataType) {
2052 case QCBOR_TYPE_INT64:
2053 pDecodedItem->label.int64 = LabelItem.val.int64;
2054 break;
2055
2056#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
2057 case QCBOR_TYPE_UINT64:
2058 pDecodedItem->label.uint64 = LabelItem.val.uint64;
2059 break;
2060
2061 case QCBOR_TYPE_TEXT_STRING:
2062 case QCBOR_TYPE_BYTE_STRING:
2063 pDecodedItem->label.string = LabelItem.val.string;
2064 break;
2065#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
2066
2067 default:
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07002068 /* It is possible to skip over labels that are non-aggregate
2069 * types like floats, but not to skip over labels that are
2070 * arrays or maps. We might eventually handle more label
2071 * types like floats as they are not too hard and we now
2072 * have QCBOR_DISABLE_NON_INTEGER_LABELS */
2073 if(!pMe->bAllowAllLabels || QCBORItem_IsMapOrArray(LabelItem)) {
2074 uErr = QCBOR_ERR_MAP_LABEL_TYPE;
2075 goto Done;
2076 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002077 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002078
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002079Done:
Laurence Lundbladeec290b82024-06-10 11:10:54 -07002080 return uErr;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002081}
2082
2083
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08002084#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002085/**
2086 * @brief Peek and see if next data item is a break;
2087 *
Laurence Lundbladeec290b82024-06-10 11:10:54 -07002088 * param[in] pUIB UsefulInputBuf to read from.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002089 * @param[out] pbNextIsBreak Indicate if next was a break or not.
2090 *
2091 * @return Any decoding error.
2092 *
2093 * See if next item is a CBOR break. If it is, it is consumed,
2094 * if not it is not consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07002095*/
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002096static QCBORError
Laurence Lundbladeec290b82024-06-10 11:10:54 -07002097QCBOR_Private_NextIsBreak(QCBORDecodeContext *pMe, bool *pbNextIsBreak)
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002098{
2099 *pbNextIsBreak = false;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07002100 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002101 QCBORItem Peek;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07002102 size_t uPeek = UsefulInputBuf_Tell(&(pMe->InBuf));
2103 QCBORError uReturn = QCBOR_Private_DecodeAtomicDataItem(pMe, false, &Peek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002104 if(uReturn != QCBOR_SUCCESS) {
2105 return uReturn;
2106 }
2107 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002108 /* It is not a break, rewind so it can be processed normally. */
Laurence Lundbladeec290b82024-06-10 11:10:54 -07002109 UsefulInputBuf_Seek(&(pMe->InBuf), uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002110 } else {
2111 *pbNextIsBreak = true;
2112 }
2113 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002114
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002115 return QCBOR_SUCCESS;
2116}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08002117#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002118
2119
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002120/**
2121 * @brief Ascend up nesting levels if all items in them have been consumed.
2122 *
2123 * @param[in] pMe The decode context.
2124 * @param[in] bMarkEnd If true mark end of maps/arrays with count of zero.
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002125 * @param[out] pbBreak Set to true if extra break was consumed.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002126 *
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08002127 * An item was just consumed, now figure out if it was the
2128 * end of an array/map map that can be closed out. That
2129 * may in turn close out the above array/map...
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002130 *
2131 * When ascending indefinite-length arrays and maps, this will correctly
2132 * consume the break for the level above. This is a problem for the
2133 * implementation of QCBORDecode_GetArray() that must not return
2134 * that break. @c pbBreak is set to true to indicate that one
2135 * byte should be removed.
2136 *
2137 * Improvement: this could reduced further if indef is disabled
2138 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002139static QCBORError
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002140QCBORDecode_Private_NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd, bool *pbBreak)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002141{
2142 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002143
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08002144 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07002145 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002146 if(pbBreak) {
2147 *pbBreak = false;
2148 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07002149
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08002150 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
2151 /* Nesting level is bstr-wrapped CBOR */
2152
2153 /* Ascent for bstr-wrapped CBOR is always by explicit call
2154 * so no further ascending can happen.
2155 */
2156 break;
2157
2158 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
2159 /* Level is a definite-length array/map */
2160
2161 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07002162 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
2163 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08002164 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07002165 break;
2166 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002167 /* All items in a definite-length array were consumed so it
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08002168 * is time to ascend one level. This happens below.
2169 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07002170
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08002171#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002172 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08002173 /* Level is an indefinite-length array/map. */
2174
2175 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002176 bool bIsBreak = false;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07002177 uReturn = QCBOR_Private_NextIsBreak(pMe, &bIsBreak);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002178 if(uReturn != QCBOR_SUCCESS) {
2179 goto Done;
2180 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07002181
2182 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08002183 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002184 break;
2185 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07002186
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002187 /* It was a break in an indefinitelength map / array so
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08002188 * it is time to ascend one level.
2189 */
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002190 if(pbBreak) {
2191 *pbBreak = true;
2192 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002193
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08002194#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002195 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07002196
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08002197
2198 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07002199
Laurence Lundblade93d89472020-10-03 22:30:50 -07002200 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08002201 * QCBORDecode_ExitBoundedMode().
2202 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07002203 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002204 /* Set the count to zero for definite-length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08002205 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07002206 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08002207 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07002208 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07002209
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07002210 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002211 break;
2212 }
2213
2214 /* Finally, actually ascend one level. */
2215 DecodeNesting_Ascend(&(pMe->nesting));
2216 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07002217
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002218 uReturn = QCBOR_SUCCESS;
2219
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08002220#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002221Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08002222#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
2223
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002224 return uReturn;
2225}
2226
2227
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002228/**
2229 * @brief Ascending & Descending out of nesting levels (decode layer 2).
2230 *
2231 * @param[in] pMe Decoder context
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002232 * @param[out] pbBreak Set to true if extra break was consumed.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002233 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07002234
2235 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
2236 * features
2237 * @retval QCBOR_ERR_HIT_END Unexpected end of input
2238 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
2239 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
2240 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
2241 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
2242 * of half-precision disabled
2243 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
2244 * float decode is disabled.
2245 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
2246 * simple type in input.
2247 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
2248 * in input, but indefinite
2249 * lengths disabled.
2250 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Indefinite-length string in input,
2251 * but no string allocator.
2252 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK Error in indefinite-length string.
2253 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED Indefinite-length string in
2254 * input, but indefinite-length
2255 * strings are disabled.
2256 * @retval QCBOR_ERR_TOO_MANY_TAGS Too many tag numbers on item.
2257 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG Too many items in array.
2258 * @retval QCBOR_ERR_MAP_LABEL_TYPE Map label not string or integer.
2259 * @retval QCBOR_ERR_NO_MORE_ITEMS Need more items for map or array.
2260 * @retval QCBOR_ERR_BAD_BREAK Indefinite-length break in wrong
2261 * place.
2262 * @retval QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP Nesting deeper than QCBOR
2263 * can handle.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002264 *
2265 * This handles the traversal descending into and asecnding out of
2266 * maps, arrays and bstr-wrapped CBOR. It figures out the ends of
2267 * definite- and indefinte-length maps and arrays by looking at the
2268 * item count or finding CBOR breaks. It detects the ends of the
2269 * top-level sequence and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002270 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002271static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002272QCBORDecode_Private_GetNextMapOrArray(QCBORDecodeContext *pMe,
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002273 bool *pbBreak,
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07002274 QCBORItem *pDecodedItem,
2275 uint32_t *puLabelEndOffset)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002276{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002277 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07002278 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002279
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002280 /* If out of bytes to consume, it is either the end of the
2281 * top-level sequence of some bstr-wrapped CBOR that was entered.
2282 *
2283 * In the case of bstr-wrapped CBOR, the length of the
2284 * UsefulInputBuf was set to that of the bstr-wrapped CBOR. When
2285 * the bstr-wrapped CBOR is exited, the length is set back to the
2286 * top-level's length or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07002287 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002288 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002289 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07002290 goto Done;
2291 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07002292
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002293 /* Check to see if at the end of a bounded definite-length map or
2294 * array. The check for a break ending indefinite-length array is
2295 * later in QCBORDecode_NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002296 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002297 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002298 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07002299 goto Done;
2300 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07002301
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08002302 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07002303 uReturn = QCBORDecode_Private_GetNextMapEntry(pMe, pDecodedItem, puLabelEndOffset);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002304 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
2305 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002306 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002307 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05302308
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002309 /* Record the nesting level for this data item before processing
2310 * any of decrementing and descending.
Laurence Lundblade642282a2020-06-23 12:00:33 -07002311 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002312 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002313
Laurence Lundblade642282a2020-06-23 12:00:33 -07002314
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07002315 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002316 if(QCBORItem_IsMapOrArray(*pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002317 /* If the new item is a map or array, descend.
2318 *
2319 * Empty indefinite-length maps and arrays are descended into,
2320 * but then ascended out of in the next chunk of code.
2321 *
2322 * Maps and arrays do count as items in the map/array that
2323 * encloses them so a decrement needs to be done for them too,
2324 * but that is done only when all the items in them have been
2325 * processed, not when they are opened with the exception of an
2326 * empty map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07002327 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002328 QCBORError uDescendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002329 uDescendErr = DecodeNesting_DescendMapOrArray(&(pMe->nesting),
Laurence Lundbladeb95afec2024-08-26 10:51:28 -07002330 pDecodedItem->uDataType,
2331 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002332 if(uDescendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002333 /* This error is probably a traversal error and it overrides
2334 * the non-traversal error.
2335 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002336 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002337 goto Done;
2338 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07002339 }
2340
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002341 if(!QCBORItem_IsMapOrArray(*pDecodedItem) ||
2342 QCBORItem_IsEmptyDefiniteLengthMapOrArray(*pDecodedItem) ||
2343 QCBORItem_IsIndefiniteLengthMapOrArray(*pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002344 /* The following cases are handled here:
2345 * - A non-aggregate item like an integer or string
2346 * - An empty definite-length map or array
2347 * - An indefinite-length map or array that might be empty or might not.
2348 *
2349 * QCBORDecode_NestLevelAscender() does the work of decrementing the count
2350 * for an definite-length map/array and break detection for an
2351 * indefinite-0length map/array. If the end of the map/array was
2352 * reached, then it ascends nesting levels, possibly all the way
2353 * to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002354 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002355 QCBORError uAscendErr;
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002356 uAscendErr = QCBORDecode_Private_NestLevelAscender(pMe, true, pbBreak);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002357 if(uAscendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002358 /* This error is probably a traversal error and it overrides
2359 * the non-traversal error.
2360 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002361 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002362 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07002363 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05302364 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002365
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07002366 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002367 /* Tell the caller what level is next. This tells them what
2368 * maps/arrays were closed out and makes it possible for them to
2369 * reconstruct the tree with just the information returned in a
2370 * QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07002371 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002372 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07002373 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002374 pDecodedItem->uNextNestLevel = 0;
2375 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002376 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002377 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002378
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002379Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002380 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002381}
2382
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002383
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002384/**
2385 * @brief Decode tag content for select tags (decoding layer 1).
2386 *
2387 * @param[in] pMe The decode context.
2388 * @param[out] pDecodedItem The decoded item.
2389 *
2390 * @return Decoding error code.
2391 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002392 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
2393 * but the whole tag was not decoded. Here, the whole tags (tag number
Laurence Lundblade721b56e2024-10-22 03:02:04 -07002394 * and tag content) are decoded. This is a
Laurence Lundblade99615302020-11-29 11:19:47 -08002395 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002396 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002397static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002398QCBORDecode_Private_GetNextTagContent(QCBORDecodeContext *pMe,
2399 QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002400{
Laurence Lundblade721b56e2024-10-22 03:02:04 -07002401 QCBORError uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002402
Laurence Lundblade721b56e2024-10-22 03:02:04 -07002403 uErr = QCBORDecode_Private_GetNextMapOrArray(pMe, NULL, pDecodedItem, NULL);
2404
2405#ifndef QCBOR_DISABLE_TAGS
2406 uint64_t uTagNumber;
2407 int nTagIndex;
2408 const struct QCBORTagDecoderEntry *pTagDecoder;
2409
2410 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002411 goto Done;
2412 }
2413
Laurence Lundblade721b56e2024-10-22 03:02:04 -07002414 /* Loop over tag numbers in reverse, those closest to content first */
2415 for(nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >= 0; nTagIndex--) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002416
Laurence Lundblade721b56e2024-10-22 03:02:04 -07002417 if(pDecodedItem->auTagNumbers[nTagIndex] == CBOR_TAG_INVALID16) {
2418 continue; /* Empty slot, skip to next */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002419 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002420
Laurence Lundblade721b56e2024-10-22 03:02:04 -07002421 /* See if there's a content decoder for it */
2422 uTagNumber = QCBORDecode_Private_UnMapTagNumber(pMe, pDecodedItem->auTagNumbers[nTagIndex]);
2423 pTagDecoder = QCBORDecode_Private_LookUpTagDecoder(pMe->pTagDecoderTable, uTagNumber);
2424 if(pTagDecoder == NULL) {
2425 break; /* Successful exist -- a tag that we can't decode */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002426 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002427
Laurence Lundblade721b56e2024-10-22 03:02:04 -07002428 /* Call the content decoder */
2429 uErr = pTagDecoder->pfContentDecoder(pMe, pMe->pTagDecodersContext, pTagDecoder->uTagNumber, pDecodedItem);
2430 if(uErr != QCBOR_SUCCESS) {
2431 break; /* Error exit from the loop */
2432 }
2433
2434 /* Remove tag number from list since its content was decoded */
2435 pDecodedItem->auTagNumbers[nTagIndex] = CBOR_TAG_INVALID16;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002436 }
2437
2438Done:
Laurence Lundblade721b56e2024-10-22 03:02:04 -07002439#endif /* ! QCBOR_DISABLE_TAGS */
2440
2441 return uErr;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002442}
2443
2444
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07002445/**
2446 * @brief Consume an entire map or array including its contents.
2447 *
2448 * @param[in] pMe The decoder context.
2449 * @param[in] pItemToConsume The array/map whose contents are to be
2450 * consumed.
2451 * @param[out] puNextNestLevel The next nesting level after the item was
2452 * fully consumed.
2453 *
2454 * This may be called when @c pItemToConsume is not an array or
2455 * map. In that case, this is just a pass through for @c puNextNestLevel
2456 * since there is nothing to do.
2457 */
2458static QCBORError
2459QCBORDecode_Private_ConsumeItem(QCBORDecodeContext *pMe,
2460 const QCBORItem *pItemToConsume,
2461 bool *pbBreak,
2462 uint8_t *puNextNestLevel)
2463{
2464 QCBORError uReturn;
2465 QCBORItem Item;
2466
2467 /* If it is a map or array, this will tell if it is empty. */
2468 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2469
2470 if(QCBORItem_IsMapOrArray(*pItemToConsume) && !bIsEmpty) {
2471 /* There is only real work to do for non-empty maps and arrays */
2472
2473 /* This works for definite- and indefinite-length maps and
2474 * arrays by using the nesting level
2475 */
2476 do {
2477 uReturn = QCBORDecode_Private_GetNextMapOrArray(pMe, pbBreak, &Item, NULL);
2478 if(QCBORDecode_IsUnrecoverableError(uReturn) ||
2479 uReturn == QCBOR_ERR_NO_MORE_ITEMS) {
2480 goto Done;
2481 }
2482 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
2483
2484 *puNextNestLevel = Item.uNextNestLevel;
2485
2486 uReturn = QCBOR_SUCCESS;
2487
2488 } else {
2489 /* pItemToConsume is not a map or array. Just pass the nesting
2490 * level through. */
2491 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2492
2493 uReturn = QCBOR_SUCCESS;
2494 }
2495
2496Done:
2497 return uReturn;
2498}
2499
2500
Laurence Lundblade721b56e2024-10-22 03:02:04 -07002501#ifndef QCBOR_DISABLE_DECODE_CONFORMANCE
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07002502/*
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07002503 * This consumes the next item. It returns the starting position of
2504 * the label and the length of the label. It also returns the nest
2505 * level of the item consumed.
2506 */
2507static QCBORError
2508QCBORDecode_Private_GetLabelAndConsume(QCBORDecodeContext *pMe,
2509 uint8_t *puNestLevel,
2510 size_t *puLabelStart,
2511 size_t *puLabelLen)
2512{
2513 QCBORError uErr;
2514 QCBORItem Item;
2515 uint8_t uLevel;
2516 uint32_t uLabelOffset;
2517
2518 /* Get the label and consume it should it be complex */
2519 *puLabelStart = UsefulInputBuf_Tell(&(pMe->InBuf));
2520
2521 uErr = QCBORDecode_Private_GetNextMapOrArray(pMe, NULL, &Item, &uLabelOffset);
2522 if(uErr != QCBOR_SUCCESS) {
2523 goto Done;
2524 }
2525 *puLabelLen = uLabelOffset - *puLabelStart;
2526 *puNestLevel = Item.uNestingLevel;
2527 uErr = QCBORDecode_Private_ConsumeItem(pMe, &Item, NULL, &uLevel);
2528
2529Done:
2530 return uErr;
2531}
2532
2533
2534/* Loop over items in a map until the end of the map looking for
2535 * duplicates. This starts at the current position in the map, not at
2536 * the beginning of the map.
2537 *
2538 * This saves and restores the traversal cursor and nest tracking so
2539 * they are the same on exit as they were on entry.
2540 */
2541static QCBORError
2542QCBORDecode_Private_CheckDups(QCBORDecodeContext *pMe,
2543 const uint8_t uNestLevel,
2544 const size_t uCompareLabelStart,
2545 const size_t uCompareLabelLen)
2546{
2547 QCBORError uErr;
2548 size_t uLabelStart;
2549 size_t uLabelLen;
2550 uint8_t uLevel;
2551 int nCompare;
2552
2553 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2554 const UsefulInputBuf Save = pMe->InBuf;
2555
2556 do {
2557 uErr = QCBORDecode_Private_GetLabelAndConsume(pMe, &uLevel, &uLabelStart, &uLabelLen);
2558 if(uErr != QCBOR_SUCCESS) {
2559 if(uErr == QCBOR_ERR_NO_MORE_ITEMS) {
2560 uErr = QCBOR_SUCCESS; /* Successful end */
2561 }
2562 break;
2563 }
2564
2565 if(uLevel != uNestLevel) {
2566 break; /* Successful end of loop */
2567 }
2568
2569 /* This check for dups works for labels that are preferred
2570 * serialization and are not maps. If the labels are not in
2571 * preferred serialization, then the check has to be more
2572 * complicated and is type-specific because it uses the decoded
2573 * value, not the encoded CBOR. It is further complicated for
2574 * maps because the order of items in a map that is a label
2575 * doesn't matter when checking that is is the duplicate of
2576 * another map that is a label. QCBOR so far only turns on this
2577 * dup checking as part of CDE checking which requires preferred
2578 * serialization. See 5.6 in RFC 8949.
2579 */
2580 nCompare = UsefulInputBuf_Compare(&(pMe->InBuf),
2581 uCompareLabelStart, uCompareLabelLen,
2582 uLabelStart, uLabelLen);
2583 if(nCompare == 0) {
2584 uErr = QCBOR_ERR_DUPLICATE_LABEL;
2585 break;
2586 }
2587 } while (1);
2588
2589 pMe->nesting = SaveNesting;
2590 pMe->InBuf = Save;
2591
2592 return uErr;
2593}
2594
2595
2596/* This does sort order and duplicate detection on a map. The and all
2597 * it's members must be in preferred serialization so the comparisons
2598 * work correctly.
2599 */
2600static QCBORError
2601QCBORDecode_Private_CheckMap(QCBORDecodeContext *pMe, const QCBORItem *pMapToCheck)
2602{
2603 QCBORError uErr;
2604 uint8_t uNestLevel;
2605 size_t offset2, offset1, length2, length1;
2606
2607 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2608 const UsefulInputBuf Save = pMe->InBuf;
2609 pMe->bAllowAllLabels = 1;
2610
2611 /* This loop runs over all the items in the map once, comparing
2612 * each adjacent pair for correct ordering. It also calls CheckDup
2613 * on each one which also runs over the remaining items in the map
2614 * checking for duplicates. So duplicate checking runs in n^2.
2615 */
2616
2617 offset2 = SIZE_MAX;
2618 length2 = SIZE_MAX; // To avoid uninitialized warning
2619 while(1) {
2620 uErr = QCBORDecode_Private_GetLabelAndConsume(pMe, &uNestLevel, &offset1, &length1);
2621 if(uErr != QCBOR_SUCCESS) {
2622 if(uErr == QCBOR_ERR_NO_MORE_ITEMS) {
2623 uErr = QCBOR_SUCCESS; /* Successful exit from loop */
2624 }
2625 break;
2626 }
2627
2628 if(uNestLevel < pMapToCheck->uNextNestLevel) {
2629 break; /* Successful exit from loop */
2630 }
2631
2632 if(offset2 != SIZE_MAX) {
2633 /* Check that the labels are ordered. Check is not done the
2634 * first time through the loop when offset2 is unset. Since
2635 * this does comparison of the items in encoded form they
2636 * must be preferred serialization encoded. See RFC 8949
2637 * 4.2.1.
2638 */
2639 if(UsefulInputBuf_Compare(&(pMe->InBuf), offset2, length2, offset1, length1) > 0) {
2640 uErr = QCBOR_ERR_UNSORTED;
2641 break;
2642 }
2643 }
2644
2645 uErr = QCBORDecode_Private_CheckDups(pMe, pMapToCheck->uNextNestLevel, offset1, length1);
2646 if(uErr != QCBOR_SUCCESS) {
2647 break;
2648 }
2649
2650 offset2 = offset1;
2651 length2 = length1;
2652 }
2653
2654 pMe->bAllowAllLabels = 0;
2655 pMe->nesting = SaveNesting;
2656 pMe->InBuf = Save;
2657
2658 return uErr;
2659}
Laurence Lundblade721b56e2024-10-22 03:02:04 -07002660#endif /* ! QCBOR_DISABLE_DECODE_CONFORMANCE */
2661
2662static QCBORError
2663QCBORDecode_Private_GetItemChecks(QCBORDecodeContext *pMe,
2664 QCBORError uErr,
2665 const size_t uOffset,
2666 QCBORItem *pDecodedItem)
2667{
2668 (void)pMe; /* Avoid warning for next two ifdefs */
2669 (void)uOffset;
2670
2671#ifndef QCBOR_DISABLE_DECODE_CONFORMANCE
2672 if(uErr == QCBOR_SUCCESS &&
2673 (pMe->uDecodeMode & QCBOR_DECODE_MODE_MASK) >= QCBOR_ENCODE_MODE_CDE &&
2674 pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
2675 /* Traverse map checking sort order and for duplicates */
2676 uErr = QCBORDecode_Private_CheckMap(pMe, pDecodedItem);
2677 }
2678#endif /* ! QCBOR_DISABLE_CONFORMANCE */
2679
2680#ifndef QCBOR_DISABLE_TAGS
2681 if(uErr == QCBOR_SUCCESS &&
2682 !(pMe->uDecodeMode & QCBOR_DECODE_UNPROCESSED_TAG_NUMBERS) &&
2683 pDecodedItem->auTagNumbers[0] != CBOR_TAG_INVALID16) {
2684 /* Not QCBOR v1; there are tag numbers -- check they were consumed */
2685 if(uOffset != pMe->uTagNumberCheckOffset || pMe->uTagNumberIndex != 255) {
2686 uErr = QCBOR_ERR_UNPROCESSED_TAG_NUMBER;
2687 }
2688 }
2689#endif /* ! QCBOR_DISABLE_TAGS */
2690
2691 if(uErr != QCBOR_SUCCESS) {
2692 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2693 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2694 }
2695
2696 return uErr;
2697}
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07002698
2699
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002700/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002701 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002702 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002703QCBORError
2704QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2705{
2706 QCBORError uErr;
Laurence Lundblade721b56e2024-10-22 03:02:04 -07002707 size_t uOffset;
2708
2709 uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07002710 uErr = QCBORDecode_Private_GetNextTagContent(pMe, pDecodedItem);
Laurence Lundblade721b56e2024-10-22 03:02:04 -07002711 uErr = QCBORDecode_Private_GetItemChecks(pMe, uErr, uOffset, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002712 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002713}
2714
2715
2716/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002717 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002718 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002719QCBORError
2720QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2721{
2722 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2723 const UsefulInputBuf Save = pMe->InBuf;
2724
2725 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2726
2727 pMe->nesting = SaveNesting;
2728 pMe->InBuf = Save;
2729
2730 return uErr;
2731}
2732
2733
2734/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002735 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002736 */
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002737void
2738QCBORDecode_VPeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2739{
2740 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladef00b8be2024-03-08 10:34:33 -08002741 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2742 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002743 return;
2744 }
2745
2746 pMe->uLastError = (uint8_t)QCBORDecode_PeekNext(pMe, pDecodedItem);
2747}
2748
2749
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07002750static void
Laurence Lundblade721b56e2024-10-22 03:02:04 -07002751QCBORDecode_Private_SaveTagNumbers(QCBORDecodeContext *pMe, const QCBORItem *pItem)
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07002752{
2753#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade721b56e2024-10-22 03:02:04 -07002754 memcpy(pMe->auLastTags, pItem->auTagNumbers, sizeof(pItem->auTagNumbers));
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07002755#else
2756 (void)pMe;
2757 (void)pItem;
2758#endif
2759}
2760
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002761/*
2762 * Public function, see header qcbor/qcbor_decode.h file
2763 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002764void
2765QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002766{
2767 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladef00b8be2024-03-08 10:34:33 -08002768 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2769 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002770 return;
2771 }
2772
2773 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
Laurence Lundblade721b56e2024-10-22 03:02:04 -07002774 QCBORDecode_Private_SaveTagNumbers(pMe, pDecodedItem);
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002775}
2776
2777
2778/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002779 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002780 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002781QCBORError
2782QCBORDecode_PartialFinish(QCBORDecodeContext *pMe, size_t *puConsumed)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002783{
Laurence Lundblade87495732021-02-26 10:05:55 -07002784 if(puConsumed != NULL) {
2785 *puConsumed = pMe->InBuf.cursor;
2786 }
2787
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002788 QCBORError uReturn = pMe->uLastError;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002789
2790 if(uReturn != QCBOR_SUCCESS) {
2791 goto Done;
2792 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002793
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002794 /* Error out if all the maps/arrays are not closed out */
2795 if(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002796 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002797 goto Done;
2798 }
2799
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002800 /* Error out if not all the bytes are consumed */
2801 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002802 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002803 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002804
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002805Done:
Laurence Lundblade87495732021-02-26 10:05:55 -07002806 return uReturn;
2807}
2808
2809
2810/*
2811 * Public function, see header qcbor/qcbor_decode.h file
2812 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002813QCBORError
2814QCBORDecode_Finish(QCBORDecodeContext *pMe)
Laurence Lundblade87495732021-02-26 10:05:55 -07002815{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002816#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002817 /* Call the destructor for the string allocator if there is one.
2818 * Always called, even if there are errors; always have to clean up.
2819 */
2820 StringAllocator_Destruct(&(pMe->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002821#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002822
Laurence Lundblade87495732021-02-26 10:05:55 -07002823 return QCBORDecode_PartialFinish(pMe, NULL);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002824}
2825
2826
Laurence Lundblade721b56e2024-10-22 03:02:04 -07002827#ifndef QCBOR_DISABLE_TAGS
2828/*
2829 * Public function, see header qcbor/qcbor_decode.h file
2830 */
2831uint64_t
2832QCBORDecode_GetNthTagNumber(const QCBORDecodeContext *pMe,
2833 const QCBORItem *pItem,
2834 uint8_t uIndex)
2835{
2836 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2837 return CBOR_TAG_INVALID64;
2838 }
2839 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2840 return CBOR_TAG_INVALID64;
2841 }
2842
2843 return QCBORDecode_Private_UnMapTagNumber(pMe, pItem->auTagNumbers[uIndex]);
2844}
2845
2846
2847/*
2848 * Public function, see header qcbor/qcbor_decode.h file
2849 */
2850uint64_t
2851QCBORDecode_GetNthTagNumberOfLast(QCBORDecodeContext *pMe,
2852 uint8_t uIndex)
2853{
2854 if(pMe->uLastError != QCBOR_SUCCESS) {
2855 return CBOR_TAG_INVALID64;
2856 }
2857 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2858 return CBOR_TAG_INVALID64;
2859 }
2860
2861 return QCBORDecode_Private_UnMapTagNumber(pMe, pMe->auLastTags[uIndex]);
2862}
2863
2864
2865/*
2866 * Public function, see header qcbor/qcbor_decode.h file
2867 */
2868static uint64_t
2869QCBORDecode_Private_GetNthTagNumberReverse(const QCBORDecodeContext *pMe,
2870 const uint16_t puTagNumbers[],
2871 const uint32_t uIndex)
2872{
2873 uint32_t uArrayIndex;
2874
2875 /* Find number of tag numbers */
2876 for(uArrayIndex = QCBOR_MAX_TAGS_PER_ITEM-1; uArrayIndex > 0; uArrayIndex--) {
2877 if(puTagNumbers[uArrayIndex] != CBOR_TAG_INVALID16) {
2878 break;
2879 }
2880 }
2881 if(uIndex > uArrayIndex) {
2882 return CBOR_TAG_INVALID64;
2883 }
2884
2885 return QCBORDecode_Private_UnMapTagNumber(pMe, puTagNumbers[uArrayIndex - uIndex]);
2886}
2887
2888
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002889/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002890 * Public function, see header qcbor/qcbor_decode.h file
2891 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002892uint64_t
2893QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2894 const QCBORItem *pItem,
Laurence Lundblade721b56e2024-10-22 03:02:04 -07002895 const uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002896{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002897 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2898 return CBOR_TAG_INVALID64;
2899 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002900
Laurence Lundblade721b56e2024-10-22 03:02:04 -07002901 return QCBORDecode_Private_GetNthTagNumberReverse(pMe, pItem->auTagNumbers, uIndex);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002902}
2903
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002904
Laurence Lundblade9b334962020-08-27 10:55:53 -07002905/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002906 * Public function, see header qcbor/qcbor_decode.h file
2907 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002908uint64_t
2909QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2910 uint32_t uIndex)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002911{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002912 if(pMe->uLastError != QCBOR_SUCCESS) {
2913 return CBOR_TAG_INVALID64;
2914 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002915 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2916 return CBOR_TAG_INVALID64;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002917 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002918
Laurence Lundblade721b56e2024-10-22 03:02:04 -07002919 return QCBORDecode_Private_GetNthTagNumberReverse(pMe, pMe->auLastTags, uIndex);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002920}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002921
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002922
Laurence Lundblade721b56e2024-10-22 03:02:04 -07002923/*
2924 * Public function, see header qcbor/qcbor_decode.h file
2925 */
2926QCBORError
2927QCBORDecode_GetNextTagNumber(QCBORDecodeContext *pMe, uint64_t *puTagNumber)
2928{
2929 QCBORItem Item;
2930 size_t uOffset;
2931 QCBORError uErr;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002932
Laurence Lundblade721b56e2024-10-22 03:02:04 -07002933 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2934 const UsefulInputBuf Save = pMe->InBuf;
2935
2936 uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
2937 if(uOffset == pMe->uTagNumberCheckOffset) {
2938 pMe->uTagNumberIndex++;
2939 } else {
2940 pMe->uTagNumberIndex = 0;
2941 }
2942
2943 *puTagNumber = CBOR_TAG_INVALID64;
2944 uErr = QCBORDecode_Private_GetNextTagContent(pMe, &Item);
2945 if(uErr) {
2946 return uErr;
2947 }
2948
2949 *puTagNumber = QCBORDecode_GetNthTagNumber(pMe, &Item, pMe->uTagNumberIndex);
2950 if(*puTagNumber == CBOR_TAG_INVALID64 ||
2951 QCBORDecode_GetNthTagNumber(pMe, &Item, pMe->uTagNumberIndex+1) == CBOR_TAG_INVALID64 ) {
2952 pMe->uTagNumberIndex = QCBOR_ALL_TAGS_PROCESSED;
2953 }
2954 pMe->uTagNumberCheckOffset = uOffset;
2955
2956 pMe->nesting = SaveNesting;
2957 pMe->InBuf = Save;
2958
2959 return QCBOR_SUCCESS;
2960}
2961
2962
2963/*
2964 * Public function, see header qcbor/qcbor_decode.h file
2965 */
2966void
2967QCBORDecode_VGetNextTagNumber(QCBORDecodeContext *pMe, uint64_t *puTagNumber)
2968{
2969 pMe->uLastError = (uint8_t)QCBORDecode_GetNextTagNumber(pMe, puTagNumber);
2970}
2971
2972#endif /* ! QCBOR_DISABLE_TAGS */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002973
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002974#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002975
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002976/* ===========================================================================
2977 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002978
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002979 This implements a simple sting allocator for indefinite-length
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002980 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2981 implements the function type QCBORStringAllocate and allows easy
2982 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002983
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002984 This particular allocator is built-in for convenience. The caller
2985 can implement their own. All of this following code will get
2986 dead-stripped if QCBORDecode_SetMemPool() is not called.
2987
2988 This is a very primitive memory allocator. It does not track
2989 individual allocations, only a high-water mark. A free or
2990 reallocation must be of the last chunk allocated.
2991
2992 The size of the pool and offset to free memory are packed into the
2993 first 8 bytes of the memory pool so we don't have to keep them in
2994 the decode context. Since the address of the pool may not be
2995 aligned, they have to be packed and unpacked as if they were
2996 serialized data of the wire or such.
2997
2998 The sizes packed in are uint32_t to be the same on all CPU types
2999 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08003000 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003001
3002
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003003static int
Laurence Lundbladeee851742020-01-08 08:37:05 -08003004MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003005{
3006 // Use of UsefulInputBuf is overkill, but it is convenient.
3007 UsefulInputBuf UIB;
3008
Laurence Lundbladeee851742020-01-08 08:37:05 -08003009 // Just assume the size here. It was checked during SetUp so
3010 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07003011 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003012 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
3013 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
3014 return UsefulInputBuf_GetError(&UIB);
3015}
3016
3017
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003018static int
Laurence Lundbladeee851742020-01-08 08:37:05 -08003019MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003020{
3021 // Use of UsefulOutBuf is overkill, but convenient. The
3022 // length check performed here is useful.
3023 UsefulOutBuf UOB;
3024
3025 UsefulOutBuf_Init(&UOB, Pool);
3026 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
3027 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
3028 return UsefulOutBuf_GetError(&UOB);
3029}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003030
3031
3032/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003033 Internal function for an allocation, reallocation free and destuct.
3034
3035 Having only one function rather than one each per mode saves space in
3036 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003037
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003038 Code Reviewers: THIS FUNCTION DOES POINTER MATH
3039 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08003040static UsefulBuf
3041MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003042{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003043 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003044
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003045 uint32_t uPoolSize;
3046 uint32_t uFreeOffset;
3047
3048 if(uNewSize > UINT32_MAX) {
3049 // This allocator is only good up to 4GB. This check should
3050 // optimize out if sizeof(size_t) == sizeof(uint32_t)
3051 goto Done;
3052 }
3053 const uint32_t uNewSize32 = (uint32_t)uNewSize;
3054
3055 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
3056 goto Done;
3057 }
3058
3059 if(uNewSize) {
3060 if(pMem) {
3061 // REALLOCATION MODE
3062 // Calculate pointer to the end of the memory pool. It is
3063 // assumed that pPool + uPoolSize won't wrap around by
3064 // assuming the caller won't pass a pool buffer in that is
3065 // not in legitimate memory space.
3066 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
3067
3068 // Check that the pointer for reallocation is in the range of the
3069 // pool. This also makes sure that pointer math further down
3070 // doesn't wrap under or over.
3071 if(pMem >= pPool && pMem < pPoolEnd) {
3072 // Offset to start of chunk for reallocation. This won't
3073 // wrap under because of check that pMem >= pPool. Cast
3074 // is safe because the pool is always less than UINT32_MAX
3075 // because of check in QCBORDecode_SetMemPool().
3076 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
3077
3078 // Check to see if the allocation will fit. uPoolSize -
3079 // uMemOffset will not wrap under because of check that
3080 // pMem is in the range of the uPoolSize by check above.
3081 if(uNewSize <= uPoolSize - uMemOffset) {
3082 ReturnValue.ptr = pMem;
3083 ReturnValue.len = uNewSize;
3084
3085 // Addition won't wrap around over because uNewSize was
3086 // checked to be sure it is less than the pool size.
3087 uFreeOffset = uMemOffset + uNewSize32;
3088 }
3089 }
3090 } else {
3091 // ALLOCATION MODE
3092 // uPoolSize - uFreeOffset will not underflow because this
3093 // pool implementation makes sure uFreeOffset is always
3094 // smaller than uPoolSize through this check here and
3095 // reallocation case.
3096 if(uNewSize <= uPoolSize - uFreeOffset) {
3097 ReturnValue.len = uNewSize;
3098 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08003099 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003100 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003101 }
3102 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003103 if(pMem) {
3104 // FREE MODE
3105 // Cast is safe because of limit on pool size in
3106 // QCBORDecode_SetMemPool()
3107 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
3108 } else {
3109 // DESTRUCT MODE
3110 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003111 }
3112 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003113
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003114 UsefulBuf Pool = {pPool, uPoolSize};
3115 MemPool_Pack(Pool, uFreeOffset);
3116
3117Done:
3118 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003119}
3120
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003121
Laurence Lundbladef6531662018-12-04 10:42:22 +09003122/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003123 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09003124 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003125QCBORError
3126QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
3127 UsefulBuf Pool,
3128 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003129{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003130 // The pool size and free mem offset are packed into the beginning
Dave Thaler93c01182022-08-06 15:08:35 -04003131 // of the pool memory. This compile time check makes sure the
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003132 // constant in the header is correct. This check should optimize
3133 // down to nothing.
Dave Thaler93c01182022-08-06 15:08:35 -04003134#ifdef _MSC_VER
3135#pragma warning(push)
3136#pragma warning(disable:4127) // conditional expression is constant
3137#endif
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003138 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003139 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003140 }
Dave Thaler93c01182022-08-06 15:08:35 -04003141#ifdef _MSC_VER
3142#pragma warning(pop)
3143#endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003144
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003145 // The pool size and free offset packed in to the beginning of pool
3146 // memory are only 32-bits. This check will optimize out on 32-bit
3147 // machines.
3148 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003149 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003150 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003151
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003152 // This checks that the pool buffer given is big enough.
3153 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003154 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003155 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003156
Laurence Lundblade3427dee2021-06-20 11:11:24 -07003157 QCBORDecode_SetUpAllocator(pMe, MemPool_Function, Pool.ptr, bAllStrings);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003158
Laurence Lundblade30816f22018-11-10 13:40:22 +07003159 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003160}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08003161#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003162
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003163
3164
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003165/*
3166 * Public function, see header qcbor/qcbor_decode.h file
3167 */
3168void
3169QCBORDecode_VGetNextConsume(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003170{
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003171 QCBORDecode_VGetNext(pMe, pDecodedItem);
3172
3173 if(pMe->uLastError == QCBOR_SUCCESS) {
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003174 pMe->uLastError = (uint8_t)QCBORDecode_Private_ConsumeItem(pMe, pDecodedItem, NULL,
Máté Tóth-Pálc6d59682021-05-26 18:55:30 +02003175 &pDecodedItem->uNextNestLevel);
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003176 }
3177}
3178
3179
Laurence Lundblade11654912024-05-09 11:49:24 -07003180/*
3181 * Public function, see header qcbor/qcbor_decode.h file
3182 */
Laurence Lundblade535bb5e2024-06-16 12:06:32 -07003183QCBORError
3184QCBORDecode_EndCheck(QCBORDecodeContext *pMe)
Laurence Lundblade11654912024-05-09 11:49:24 -07003185{
Laurence Lundblade535bb5e2024-06-16 12:06:32 -07003186 size_t uCursorOffset;
3187 QCBORError uErr;
Laurence Lundblade11654912024-05-09 11:49:24 -07003188
Laurence Lundblade535bb5e2024-06-16 12:06:32 -07003189 uErr = QCBORDecode_GetError(pMe);
3190 if(uErr != QCBOR_SUCCESS) {
3191 return uErr;
Laurence Lundblade11654912024-05-09 11:49:24 -07003192 }
3193
3194 uCursorOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
3195
3196 if(uCursorOffset == UsefulInputBuf_GetBufferLength(&(pMe->InBuf))) {
Laurence Lundblade535bb5e2024-06-16 12:06:32 -07003197 return QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade11654912024-05-09 11:49:24 -07003198 }
Laurence Lundblade535bb5e2024-06-16 12:06:32 -07003199
3200 return QCBOR_SUCCESS;
Laurence Lundblade11654912024-05-09 11:49:24 -07003201}
3202
3203
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003204/**
3205 * @brief Rewind cursor to start as if map or array were just entered.
3206 *
3207 * @param[in] pMe The decoding context
3208 *
3209 * This affects the nesting tracking and the UsefulInputBuf.
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003210 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003211static void
3212QCBORDecode_Private_RewindMapOrArray(QCBORDecodeContext *pMe)
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003213{
3214 /* Reset nesting tracking to the deepest bounded level */
3215 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
3216
3217 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3218
3219 /* Reposition traversal cursor to the start of the map/array */
3220 UsefulInputBuf_Seek(&(pMe->InBuf),
3221 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
3222}
3223
3224
3225/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003226 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003227 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003228void
3229QCBORDecode_Rewind(QCBORDecodeContext *pMe)
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003230{
3231 if(pMe->nesting.pCurrentBounded != NULL) {
3232 /* In a bounded map, array or bstr-wrapped CBOR */
3233
3234 if(DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
3235 /* In bstr-wrapped CBOR. */
3236
3237 /* Reposition traversal cursor to start of wrapping byte string */
3238 UsefulInputBuf_Seek(&(pMe->InBuf),
3239 pMe->nesting.pCurrentBounded->u.bs.uBstrStartOffset);
3240 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
3241
3242 } else {
3243 /* In a map or array */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003244 QCBORDecode_Private_RewindMapOrArray(pMe);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003245 }
3246
3247 } else {
3248 /* Not in anything bounded */
3249
3250 /* Reposition traversal cursor to the start of input CBOR */
3251 UsefulInputBuf_Seek(&(pMe->InBuf), 0ULL);
3252
3253 /* Reset nesting tracking to beginning of input. */
3254 DecodeNesting_Init(&(pMe->nesting));
3255 }
3256
3257 pMe->uLastError = QCBOR_SUCCESS;
3258}
3259
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003260
Laurence Lundblade9b334962020-08-27 10:55:53 -07003261
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003262
3263
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003264typedef struct {
3265 void *pCBContext;
3266 QCBORItemCallback pfCallback;
3267} MapSearchCallBack;
3268
3269typedef struct {
3270 size_t uStartOffset;
3271 uint16_t uItemCount;
3272} MapSearchInfo;
3273
3274
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003275/**
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003276 * @brief Search a map for a set of items.
3277 *
3278 * @param[in] pMe The decode context to search.
3279 * @param[in,out] pItemArray The items to search for and the items found.
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003280 * @param[out] pInfo Several bits of meta-info returned by search.
3281 * @param[in] pCallBack Callback object or @c NULL.
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003282 *
3283 * @retval QCBOR_ERR_NOT_ENTERED Trying to search without entering a map.
3284 *
3285 * @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
3286 * were found for one of the labels being
3287 * search for. This duplicate detection is
3288 * only performed for items in pItemArray,
3289 * not every item in the map.
3290 *
3291 * @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
3292 * wrong for the matchd label.
3293 *
3294 * @retval Also errors returned by QCBORDecode_GetNext().
3295 *
Laurence Lundblade88ba5662024-11-03 02:10:24 -08003296 * On input, @c pItemArray contains a list of labels and data types of
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003297 * items to be found.
3298 *
3299 * On output, the fully retrieved items are filled in with values and
3300 * such. The label was matched, so it never changes.
3301 *
3302 * If an item was not found, its data type is set to @ref QCBOR_TYPE_NONE.
3303 *
3304 * This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003305 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003306static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003307QCBORDecode_Private_MapSearch(QCBORDecodeContext *pMe,
3308 QCBORItem *pItemArray,
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003309 MapSearchInfo *pInfo,
3310 MapSearchCallBack *pCallBack)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003311{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003312 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003313 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07003314
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003315 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003316 uReturn = pMe->uLastError;
3317 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003318 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003319
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003320 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003321 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
3322 /* QCBOR_TYPE_NONE as first item indicates just looking
3323 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003324 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
3325 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003326 }
3327
Laurence Lundblade085d7952020-07-24 10:26:30 -07003328 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
3329 // It is an empty bounded array or map
3330 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
3331 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003332 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07003333 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003334 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003335 // Nothing is ever found in an empty array or map. All items
3336 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07003337 uReturn = QCBOR_SUCCESS;
3338 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003339 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003340 }
3341
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003342 QCBORDecodeNesting SaveNesting;
Laurence Lundblade11654912024-05-09 11:49:24 -07003343 size_t uSavePos = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade085d7952020-07-24 10:26:30 -07003344 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
3345
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003346 /* Reposition to search from the start of the map / array */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003347 QCBORDecode_Private_RewindMapOrArray(pMe);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003348
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003349 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003350 Loop over all the items in the map or array. Each item
3351 could be a map or array, but label matching is only at
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003352 the main level. This handles definite- and indefinite-
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003353 length maps and arrays. The only reason this is ever
3354 called on arrays is to find their end position.
3355
3356 This will always run over all items in order to do
3357 duplicate detection.
3358
3359 This will exit with failure if it encounters an
3360 unrecoverable error, but continue on for recoverable
3361 errors.
3362
3363 If a recoverable error occurs on a matched item, then
3364 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003365 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07003366 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003367 if(pInfo) {
3368 pInfo->uItemCount = 0;
3369 }
Máté Tóth-Pál2f2aa5f2021-05-17 21:35:09 +02003370 uint8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003371 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003372 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07003373 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003374
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003375 /* Get the item */
3376 QCBORItem Item;
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07003377 /* QCBORDecode_Private_GetNextTagContent() rather than GetNext()
3378 * because a label match is performed on recoverable errors to
3379 * be able to return the the error code for the found item. */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003380 QCBORError uResult = QCBORDecode_Private_GetNextTagContent(pMe, &Item);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003381 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003382 /* The map/array can't be decoded when unrecoverable errors occur */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003383 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003384 goto Done;
3385 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003386 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003387 /* Unexpected end of map or array. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003388 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003389 goto Done;
3390 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003391
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003392 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003393 bool bMatched = false;
3394 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003395 if(QCBORItem_MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003396 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003397 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
3398 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003399 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003400 }
Laurence Lundblade63926052021-03-29 16:05:51 -07003401 if(uResult != QCBOR_SUCCESS) {
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003402 /* The label matches, but the data item is in error.
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07003403 * It is OK to have recoverable errors on items that
3404 * are not matched. */
Laurence Lundblade63926052021-03-29 16:05:51 -07003405 uReturn = uResult;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003406 goto Done;
3407 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003408 if(!QCBORItem_MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade63926052021-03-29 16:05:51 -07003409 /* The data item is not of the type(s) requested */
3410 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003411 goto Done;
3412 }
3413
Laurence Lundblade1341c592020-04-11 14:19:05 -07003414 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003415 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003416 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003417 if(pInfo) {
3418 pInfo->uStartOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003419 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003420 bMatched = true;
3421 }
3422 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003423
3424
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003425 if(!bMatched && pCallBack != NULL) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003426 /*
3427 Call the callback on unmatched labels.
3428 (It is tempting to do duplicate detection here, but that would
3429 require dynamic memory allocation because the number of labels
3430 that might be encountered is unbounded.)
3431 */
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003432 uReturn = (*(pCallBack->pfCallback))(pCallBack->pCBContext, &Item);
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003433 if(uReturn != QCBOR_SUCCESS) {
3434 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003435 }
3436 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003437
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003438 /*
3439 Consume the item whether matched or not. This
3440 does the work of traversing maps and array and
3441 everything in them. In this loop only the
3442 items at the current nesting level are examined
3443 to match the labels.
3444 */
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003445 uReturn = QCBORDecode_Private_ConsumeItem(pMe, &Item, NULL, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003446 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003447 goto Done;
3448 }
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003449
3450 if(pInfo) {
3451 pInfo->uItemCount++;
3452 }
3453
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003454 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003455
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003456 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003457
3458 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003459
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003460 // Check here makes sure that this won't accidentally be
3461 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003462 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003463 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
3464 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003465 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
3466 goto Done;
3467 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003468 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
3469 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003470
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003471 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003472 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundblade11654912024-05-09 11:49:24 -07003473 UsefulInputBuf_Seek(&(pMe->InBuf), uSavePos);
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003474
3475 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003476 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07003477 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003478 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003479 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
3480 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003481 }
3482 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003483
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003484 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003485}
3486
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003487
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003488/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003489 * Public function, see header qcbor/qcbor_decode.h file
3490 */
3491void
Laurence Lundblade721b56e2024-10-22 03:02:04 -07003492QCBORDecode_SeekToLabelN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003493{
Laurence Lundblade721b56e2024-10-22 03:02:04 -07003494 MapSearchInfo Info;
3495 QCBORItem OneItemSeach[2];
3496
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003497 if(pMe->uLastError != QCBOR_SUCCESS) {
3498 return;
3499 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003500
Laurence Lundblade721b56e2024-10-22 03:02:04 -07003501 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3502 OneItemSeach[0].label.int64 = nLabel;
3503 OneItemSeach[0].uDataType = QCBOR_TYPE_ANY;
3504 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
3505
3506 pMe->uLastError = (uint8_t)QCBORDecode_Private_MapSearch(pMe, OneItemSeach, &Info, NULL);
3507 if(pMe->uLastError == QCBOR_SUCCESS) {
3508 UsefulInputBuf_Seek(&(pMe->InBuf), Info.uStartOffset);
3509 }
3510}
3511
3512
3513void
3514QCBORDecode_SeekToLabelSZ(QCBORDecodeContext *pMe, const char *szLabel)
3515{
3516#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
3517 MapSearchInfo Info;
3518 QCBORItem OneItemSeach[2];
3519
3520 if(pMe->uLastError != QCBOR_SUCCESS) {
3521 return;
3522 }
3523
3524 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3525 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3526 OneItemSeach[0].uDataType = QCBOR_TYPE_ANY;
3527 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
3528
3529 pMe->uLastError = (uint8_t)QCBORDecode_Private_MapSearch(pMe, OneItemSeach, &Info, NULL);
3530 if(pMe->uLastError == QCBOR_SUCCESS) {
3531 UsefulInputBuf_Seek(&(pMe->InBuf), Info.uStartOffset);
3532 }
3533#else
3534 (void)pMe;
3535 (void)szLabel;
3536 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
3537#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
3538}
3539
3540
3541void
3542QCBORDecode_Private_GetItemInMapNoCheck(QCBORDecodeContext *pMe,
3543 QCBORItem *OneItemSeach,
3544 QCBORItem *pItem,
3545 size_t *puOffset)
3546{
3547 QCBORError uErr;
3548 MapSearchInfo SearchInfo;
3549
3550 if(pMe->uLastError != QCBOR_SUCCESS) {
3551 return;
3552 }
3553
3554 uErr = QCBORDecode_Private_MapSearch(pMe, OneItemSeach, &SearchInfo, NULL);
3555
3556 if(uErr == QCBOR_SUCCESS && OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
3557 uErr = QCBOR_ERR_LABEL_NOT_FOUND;
3558 }
3559 *pItem = OneItemSeach[0];
3560 *puOffset = SearchInfo.uStartOffset;
3561
3562 if(uErr == QCBOR_SUCCESS) {
3563 QCBORDecode_Private_SaveTagNumbers(pMe, pItem);
3564 }
3565
3566 pMe->uLastError = (uint8_t)uErr;
3567}
3568
3569
3570static void
3571QCBORDecode_Private_GetItemInMap(QCBORDecodeContext *pMe, QCBORItem *OneItemSeach, QCBORItem *pItem)
3572{
3573 QCBORError uErr;
3574 size_t uOffset;
3575
3576 QCBORDecode_Private_GetItemInMapNoCheck(pMe, OneItemSeach, pItem, &uOffset);
3577
3578 uErr = QCBORDecode_Private_GetItemChecks(pMe, pMe->uLastError, uOffset, pItem);
3579 if(uErr != QCBOR_SUCCESS) {
3580 goto Done;
3581 }
3582
3583 QCBORDecode_Private_SaveTagNumbers(pMe, pItem);
3584
3585Done:
3586 pMe->uLastError = (uint8_t)uErr;
3587}
3588
3589
3590/*
3591 * Public function, see header qcbor/qcbor_decode.h file
3592 */
3593void
3594QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
3595 const int64_t nLabel,
3596 const uint8_t uQcborType,
3597 QCBORItem *pItem)
3598{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003599 QCBORItem OneItemSeach[2];
Laurence Lundblade721b56e2024-10-22 03:02:04 -07003600
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003601 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3602 OneItemSeach[0].label.int64 = nLabel;
3603 OneItemSeach[0].uDataType = uQcborType;
3604 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003605
Laurence Lundblade721b56e2024-10-22 03:02:04 -07003606 QCBORDecode_Private_GetItemInMap(pMe, OneItemSeach, pItem);
3607}
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003608
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07003609
Laurence Lundblade721b56e2024-10-22 03:02:04 -07003610/**
3611 * @brief Get an item by label by type.
3612 *
3613 * @param[in] pMe The decode context.
3614 * @param[in] nLabel The label to search map for.
3615 * @param[in] uQcborType The QCBOR type to look for.
3616 * @param[out] pItem The item found.
3617 * @param[out] puOffset The offset of item for tag consumption check.
3618 *
3619 * This finds the item with the given label in currently open
3620 * map. This does not call QCBORDecode_Private_GetItemChecks()
3621 * to check tag number consumption or decode conformance.
3622 */
3623static void
3624QCBORDecode_GetItemInMapNoCheckN(QCBORDecodeContext *pMe,
3625 const int64_t nLabel,
3626 const uint8_t uQcborType,
3627 QCBORItem *pItem,
3628 size_t *puOffset)
3629{
3630 QCBORItem OneItemSeach[2];
Laurence Lundblade1341c592020-04-11 14:19:05 -07003631
Laurence Lundblade721b56e2024-10-22 03:02:04 -07003632 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3633 OneItemSeach[0].label.int64 = nLabel;
3634 OneItemSeach[0].uDataType = uQcborType;
3635 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07003636
Laurence Lundblade721b56e2024-10-22 03:02:04 -07003637 QCBORDecode_Private_GetItemInMapNoCheck(pMe, OneItemSeach, pItem, puOffset);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003638}
3639
3640
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003641/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003642 * Public function, see header qcbor/qcbor_decode.h file
3643 */
3644void
3645QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
3646 const char *szLabel,
Laurence Lundblade721b56e2024-10-22 03:02:04 -07003647 const uint8_t uQcborType,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003648 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003649{
Laurence Lundbladeec290b82024-06-10 11:10:54 -07003650#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003651 QCBORItem OneItemSeach[2];
Laurence Lundblade721b56e2024-10-22 03:02:04 -07003652
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003653 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3654 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3655 OneItemSeach[0].uDataType = uQcborType;
3656 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003657
Laurence Lundblade721b56e2024-10-22 03:02:04 -07003658 QCBORDecode_Private_GetItemInMap(pMe, OneItemSeach, pItem);
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003659
Laurence Lundbladeec290b82024-06-10 11:10:54 -07003660#else
3661 (void)pMe;
3662 (void)szLabel;
3663 (void)uQcborType;
3664 (void)pItem;
Laurence Lundblade721b56e2024-10-22 03:02:04 -07003665 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07003666#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003667}
3668
Laurence Lundblade721b56e2024-10-22 03:02:04 -07003669/**
3670 * @brief Get an item by string label of a particular type
3671 *
3672 * @param[in] pMe The decode context.
3673 * @param[in] szLabel The label to search map for.
3674 * @param[in] uQcborType The QCBOR type to look for.
3675 * @param[out] pItem The item found.
3676 * @param[out] puOffset The offset of item for tag consumption check.
3677 *
3678 * This finds the item with the given label in currently open
3679 * map. This does not call QCBORDecode_Private_GetItemChecks()
3680 * to check tag number consumption or decode conformance.
3681 */
3682static void
3683QCBORDecode_GetItemInMapNoCheckSZ(QCBORDecodeContext *pMe,
3684 const char *szLabel,
3685 const uint8_t uQcborType,
3686 QCBORItem *pItem,
3687 size_t *puOffset)
3688{
3689#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
3690 QCBORItem OneItemSeach[2];
3691
3692 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3693 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3694 OneItemSeach[0].uDataType = uQcborType;
3695 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
3696
3697 QCBORDecode_Private_GetItemInMapNoCheck(pMe, OneItemSeach, pItem, puOffset);
3698
3699#else
3700 (void)pMe;
3701 (void)szLabel;
3702 (void)uQcborType;
3703 (void)pItem;
3704 (void)puOffset;
3705 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
3706#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
3707}
3708
3709
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003710
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003711
3712/**
3713 * @brief Semi-private. Get pointer, length and item for an array or map.
3714 *
3715 * @param[in] pMe The decode context.
3716 * @param[in] uType CBOR major type, either array/map.
3717 * @param[out] pItem The item for the array/map.
3718 * @param[out] pEncodedCBOR Pointer and length of the encoded map or array.
3719 *
Laurence Lundblade88ba5662024-11-03 02:10:24 -08003720 * The next item to be decoded must be a map or array as specified by @c uType.
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003721 *
Laurence Lundblade88ba5662024-11-03 02:10:24 -08003722 * @c pItem will be filled in with the label and tags of the array or map
3723 * in addition to @c pEncodedCBOR giving the pointer and length of the
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003724 * encoded CBOR.
3725 *
3726 * When this is complete, the traversal cursor is at the end of the array or
3727 * map that was retrieved.
3728 */
3729void
3730QCBORDecode_Private_GetArrayOrMap(QCBORDecodeContext *pMe,
3731 const uint8_t uType,
3732 QCBORItem *pItem,
3733 UsefulBufC *pEncodedCBOR)
3734{
3735 QCBORError uErr;
3736 uint8_t uNestLevel;
3737 size_t uStartingCursor;
3738 size_t uStartOfReturned;
3739 size_t uEndOfReturned;
3740 size_t uTempSaveCursor;
3741 bool bInMap;
3742 QCBORItem LabelItem;
3743 bool EndedByBreak;
3744
3745 uStartingCursor = UsefulInputBuf_Tell(&(pMe->InBuf));
3746 bInMap = DecodeNesting_IsCurrentTypeMap(&(pMe->nesting));
3747
3748 /* Could call GetNext here, but don't need to because this
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07003749 * is only interested in arrays and maps. TODO: switch to GetNext()? */
3750 uErr = QCBORDecode_Private_GetNextMapOrArray(pMe, NULL, pItem, NULL);
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003751 if(uErr != QCBOR_SUCCESS) {
3752 pMe->uLastError = (uint8_t)uErr;
3753 return;
3754 }
3755
Laurence Lundblade5db34da2024-05-30 03:14:35 -07003756 uint8_t uItemDataType = pItem->uDataType;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07003757#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
Laurence Lundblade5db34da2024-05-30 03:14:35 -07003758 if(uItemDataType == QCBOR_TYPE_MAP_AS_ARRAY) {
3759 uItemDataType = QCBOR_TYPE_ARRAY;
3760 }
Laurence Lundbladeec290b82024-06-10 11:10:54 -07003761#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
Laurence Lundblade5db34da2024-05-30 03:14:35 -07003762
3763 if(uItemDataType != uType) {
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003764 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
3765 return;
3766 }
3767
3768 if(bInMap) {
3769 /* If the item is in a map, the start of the array/map
3770 * itself, not the label, must be found. Do this by
3771 * rewinding to the starting position and fetching
3772 * just the label data item. QCBORDecode_Private_GetNextTagNumber()
3773 * doesn't do any of the array/map item counting or nesting
3774 * level tracking. Used here it will just fetech the label
3775 * data item.
3776 *
3777 * Have to save the cursor and put it back to the position
3778 * after the full item once the label as been fetched by
3779 * itself.
3780 */
3781 uTempSaveCursor = UsefulInputBuf_Tell(&(pMe->InBuf));
3782 UsefulInputBuf_Seek(&(pMe->InBuf), uStartingCursor);
3783
3784 /* Item has been fetched once so safe to ignore error */
3785 (void)QCBORDecode_Private_GetNextTagNumber(pMe, &LabelItem);
3786
3787 uStartOfReturned = UsefulInputBuf_Tell(&(pMe->InBuf));
3788 UsefulInputBuf_Seek(&(pMe->InBuf), uTempSaveCursor);
3789 } else {
3790 uStartOfReturned = uStartingCursor;
3791 }
3792
3793 /* Consume the entire array/map to find the end */
3794 uErr = QCBORDecode_Private_ConsumeItem(pMe, pItem, &EndedByBreak, &uNestLevel);
3795 if(uErr != QCBOR_SUCCESS) {
3796 pMe->uLastError = (uint8_t)uErr;
3797 goto Done;
3798 }
3799
3800 /* Fill in returned values */
3801 uEndOfReturned = UsefulInputBuf_Tell(&(pMe->InBuf));
3802 if(EndedByBreak) {
3803 /* When ascending nesting levels, a break for the level above
3804 * was consumed. That break is not a part of what is consumed here. */
3805 uEndOfReturned--;
3806 }
3807 pEncodedCBOR->ptr = UsefulInputBuf_OffsetToPointer(&(pMe->InBuf), uStartOfReturned);
3808 pEncodedCBOR->len = uEndOfReturned - uStartOfReturned;
3809
3810Done:
3811 return;
3812}
3813
3814
3815/**
3816 * @brief Semi-private. Get pointer, length and item count of an array or map.
3817 *
3818 * @param[in] pMe The decode context.
3819 * @param[in] pTarget The label and type of the array or map to retrieve.
3820 * @param[out] pItem The item for the array/map.
3821 * @param[out] pEncodedCBOR Pointer and length of the encoded map or array.
3822 *
Laurence Lundblade88ba5662024-11-03 02:10:24 -08003823 * The next item to be decoded must be a map or array as specified by @c uType.
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003824 *
3825 * When this is complete, the traversal cursor is unchanged.
3826 */void
3827QCBORDecode_Private_SearchAndGetArrayOrMap(QCBORDecodeContext *pMe,
3828 QCBORItem *pTarget,
3829 QCBORItem *pItem,
3830 UsefulBufC *pEncodedCBOR)
3831{
3832 MapSearchInfo Info;
3833 QCBORDecodeNesting SaveNesting;
3834 size_t uSaveCursor;
3835
3836 pMe->uLastError = (uint8_t)QCBORDecode_Private_MapSearch(pMe, pTarget, &Info, NULL);
3837 if(pMe->uLastError != QCBOR_SUCCESS) {
3838 return;
3839 }
Laurence Lundblade721b56e2024-10-22 03:02:04 -07003840 pMe->uLastError = (uint8_t)QCBORDecode_Private_GetItemChecks(pMe, pMe->uLastError, Info.uStartOffset, pItem);
3841 if(pMe->uLastError != QCBOR_SUCCESS) {
3842 return;
3843 }
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003844
3845 /* Save the whole position of things so they can be restored.
3846 * so the cursor position is unchanged by this operation, like
3847 * all the other GetXxxxInMap() operations. */
3848 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
3849 uSaveCursor = UsefulInputBuf_Tell(&(pMe->InBuf));
3850
3851 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3852 UsefulInputBuf_Seek(&(pMe->InBuf), Info.uStartOffset);
3853 QCBORDecode_Private_GetArrayOrMap(pMe, pTarget[0].uDataType, pItem, pEncodedCBOR);
3854
3855 UsefulInputBuf_Seek(&(pMe->InBuf), uSaveCursor);
3856 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
3857}
3858
3859
3860
3861
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003862static void
Laurence Lundblade721b56e2024-10-22 03:02:04 -07003863QCBORDecode_Private_ProcessTagOne(QCBORDecodeContext *pMe,
3864 QCBORItem *pItem,
3865 const uint8_t uTagRequirement,
3866 const uint8_t uQCBORType,
3867 const uint64_t uTagNumber,
3868 QCBORTagContentCallBack *pfCB,
3869 size_t uOffset);
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003870
3871/**
3872 * @brief Semi-private to get an string by label to match a tag specification.
3873 *
Laurence Lundblade721b56e2024-10-22 03:02:04 -07003874 * @param[in] pMe The decode context.
3875 * @param[in] nLabel Label to search map for.
3876 * @param[in] uTagRequirement Whether or not tag number is required.
3877 * See @ref QCBOR_TAG_REQUIREMENT_TAG.
3878 * @param[in] uQCBOR_Type QCBOR type to search for.
3879 * @param[in] uTagNumber Tag number to match.
3880 * @param[out] pString The string found.
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003881 *
3882 * This finds the string with the given label in currently open
3883 * map. Then checks that its tag number and types matches the tag
3884 * specification. If not, an error is set in the decode context.
3885 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003886void
Laurence Lundblade721b56e2024-10-22 03:02:04 -07003887QCBORDecode_Private_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
3888 const int64_t nLabel,
3889 const uint8_t uTagRequirement,
3890 const uint8_t uQCBOR_Type,
3891 const uint64_t uTagNumber,
3892 UsefulBufC *pString)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003893{
Laurence Lundblade721b56e2024-10-22 03:02:04 -07003894 QCBORItem Item;
3895 size_t uOffset;
3896
3897 QCBORDecode_GetItemInMapNoCheckN(pMe, nLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
3898 QCBORDecode_Private_ProcessTagOne(pMe,
3899 &Item,
3900 uTagRequirement,
3901 uQCBOR_Type,
3902 uTagNumber,
3903 QCBORDecode_StringsTagCB,
3904 uOffset);
3905
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003906 if(pMe->uLastError == QCBOR_SUCCESS) {
3907 *pString = Item.val.string;
3908 }
3909}
3910
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003911
3912/**
3913 * @brief Semi-private to get an string by label to match a tag specification.
3914 *
Laurence Lundblade721b56e2024-10-22 03:02:04 -07003915 * @param[in] pMe The decode context.
3916 * @param[in] szLabel Label to search map for.
3917 * @param[in] uTagRequirement Whether or not tag number is required.
3918 * See @ref QCBOR_TAG_REQUIREMENT_TAG.
3919 * @param[in] uQCBOR_Type QCBOR type to search for.
3920 * @param[in] uTagNumber Tag number to match.
3921 * @param[out] pString The string found.
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003922 *
3923 * This finds the string with the given label in currently open
3924 * map. Then checks that its tag number and types matches the tag
3925 * specification. If not, an error is set in the decode context.
Laurence Lundblade721b56e2024-10-22 03:02:04 -07003926 */
3927void
3928QCBORDecode_Private_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
3929 const char *szLabel,
3930 uint8_t uTagRequirement,
3931 uint8_t uQCBOR_Type,
3932 uint64_t uTagNumber,
3933 UsefulBufC *pString)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003934{
3935 QCBORItem Item;
Laurence Lundblade721b56e2024-10-22 03:02:04 -07003936 size_t uOffset;
3937
3938 QCBORDecode_GetItemInMapNoCheckSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
3939 QCBORDecode_Private_ProcessTagOne(pMe,
3940 &Item,
3941 uTagRequirement,
3942 uQCBOR_Type,
3943 uTagNumber,
3944 QCBORDecode_StringsTagCB,
3945 uOffset);
3946
3947
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003948 if(pMe->uLastError == QCBOR_SUCCESS) {
3949 *pString = Item.val.string;
3950 }
3951}
Laurence Lundblade1341c592020-04-11 14:19:05 -07003952
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003953
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003954/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003955 * Public function, see header qcbor/qcbor_decode.h file
3956 */
3957void
3958QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003959{
Laurence Lundblade721b56e2024-10-22 03:02:04 -07003960 pMe->uLastError = (uint8_t)QCBORDecode_Private_MapSearch(pMe, pItemList, NULL, NULL);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003961}
3962
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003963/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003964 * Public function, see header qcbor/qcbor_decode.h file
3965 */
3966void
3967QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3968 QCBORItem *pItemList,
3969 void *pCallbackCtx,
3970 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003971{
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003972 MapSearchCallBack CallBack;
Laurence Lundblade721b56e2024-10-22 03:02:04 -07003973
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07003974 CallBack.pCBContext = pCallbackCtx;
3975 CallBack.pfCallback = pfCB;
3976
Laurence Lundblade721b56e2024-10-22 03:02:04 -07003977 pMe->uLastError = (uint8_t)QCBORDecode_Private_MapSearch(pMe, pItemList, NULL, &CallBack);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003978}
3979
3980
Laurence Lundblade721b56e2024-10-22 03:02:04 -07003981#ifndef QCBOR_DISABLE_TAGS
3982/*
3983 * Public function, see header qcbor/qcbor_decode.h file
3984 */
3985QCBORError
3986QCBORDecode_GetNextTagNumberInMapN(QCBORDecodeContext *pMe, const int64_t nLabel, uint64_t *puTagNumber)
3987{
3988 size_t uOffset;
3989 MapSearchInfo Info;
3990 QCBORItem OneItemSeach[2];
3991
3992 if(pMe->uLastError != QCBOR_SUCCESS) {
3993 return pMe->uLastError;
3994 }
3995
3996 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3997 OneItemSeach[0].label.int64 = nLabel;
3998 OneItemSeach[0].uDataType = QCBOR_TYPE_ANY;
3999 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
4000
4001 QCBORError uReturn = QCBORDecode_Private_MapSearch(pMe, OneItemSeach, &Info, NULL);
4002
4003 uOffset = Info.uStartOffset;
4004 if(uOffset == pMe->uTagNumberCheckOffset) {
4005 pMe->uTagNumberIndex++;
4006 } else {
4007 pMe->uTagNumberIndex = 0;
4008 }
4009
4010 *puTagNumber = CBOR_TAG_INVALID64;
4011
4012 *puTagNumber = QCBORDecode_GetNthTagNumber(pMe, &OneItemSeach[0], pMe->uTagNumberIndex);
4013 if(*puTagNumber == CBOR_TAG_INVALID64 ||
4014 QCBORDecode_GetNthTagNumber(pMe, &OneItemSeach[0], pMe->uTagNumberIndex+1) == CBOR_TAG_INVALID64 ) {
4015 pMe->uTagNumberIndex = QCBOR_ALL_TAGS_PROCESSED;
4016 }
4017 pMe->uTagNumberCheckOffset = uOffset;
4018
4019 return uReturn;
4020}
4021
4022
4023/*
4024 * Public function, see header qcbor/qcbor_decode.h file
4025 */
4026QCBORError
4027QCBORDecode_GetNextTagNumberInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint64_t *puTagNumber)
4028{
4029#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
4030 size_t uOffset;
4031 MapSearchInfo Info;
4032 QCBORItem OneItemSeach[2];
4033
4034 if(pMe->uLastError != QCBOR_SUCCESS) {
4035 return pMe->uLastError;
4036 }
4037
4038 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
4039 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
4040 OneItemSeach[0].uDataType = QCBOR_TYPE_ANY;
4041 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
4042
4043 QCBORError uReturn = QCBORDecode_Private_MapSearch(pMe, OneItemSeach, &Info, NULL);
4044
4045
4046 uOffset = Info.uStartOffset;
4047 if(uOffset == pMe->uTagNumberCheckOffset) {
4048 pMe->uTagNumberIndex++;
4049 } else {
4050 pMe->uTagNumberIndex = 0;
4051 }
4052
4053 *puTagNumber = CBOR_TAG_INVALID64;
4054
4055 *puTagNumber = QCBORDecode_GetNthTagNumber(pMe, &OneItemSeach[0], pMe->uTagNumberIndex);
4056 if(*puTagNumber == CBOR_TAG_INVALID64 ||
4057 QCBORDecode_GetNthTagNumber(pMe, &OneItemSeach[0], pMe->uTagNumberIndex+1) == CBOR_TAG_INVALID64 ) {
4058 pMe->uTagNumberIndex = 255; /* All tags clear for this item */
4059 }
4060 pMe->uTagNumberCheckOffset = uOffset;
4061
4062 return uReturn;
4063#else
4064 (void)pMe;
4065 (void)szLabel;
4066 (void)puTagNumber;
4067 return QCBOR_ERR_LABEL_NOT_FOUND;
4068#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
4069}
4070#endif /* ! QCBOR_DISABLE_TAGS */
4071
4072
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08004073/**
4074 * @brief Search for a map/array by label and enter it
4075 *
4076 * @param[in] pMe The decode context.
4077 * @param[in] pSearch The map/array to search for.
4078 *
4079 * @c pSearch is expected to contain one item of type map or array
4080 * with the label specified. The current bounded map will be searched for
4081 * this and if found will be entered.
4082 *
4083 * If the label is not found, or the item found is not a map or array,
4084 * the error state is set.
4085 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004086static void
4087QCBORDecode_Private_SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07004088{
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004089 QCBORError uErr;
4090 MapSearchInfo SearchInfo;
4091
Laurence Lundblade323f8a92020-09-06 19:43:09 -07004092 // The first item in pSearch is the one that is to be
4093 // entered. It should be the only one filled in. Any other
4094 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07004095 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07004096 return;
4097 }
4098
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004099 uErr = QCBORDecode_Private_MapSearch(pMe, pSearch, &SearchInfo, NULL);
4100
4101 pMe->uLastError = (uint8_t)QCBORDecode_Private_GetItemChecks(pMe, uErr, SearchInfo.uStartOffset, pSearch);
4102
Laurence Lundblade34691b92020-05-18 22:25:25 -07004103 if(pMe->uLastError != QCBOR_SUCCESS) {
4104 return;
4105 }
4106
Laurence Lundblade9b334962020-08-27 10:55:53 -07004107 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07004108 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07004109 return;
4110 }
4111
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004112
4113 /* The map or array was found. Now enter it.
4114 *
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08004115 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
4116 * next item for the pre-order traversal cursor to be the map/array
4117 * found by MapSearch(). The next few lines of code force the
4118 * cursor to that.
4119 *
4120 * There is no need to retain the old cursor because
4121 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
4122 * beginning of the map/array being entered.
4123 *
4124 * The cursor is forced by: 1) setting the input buffer position to
4125 * the item offset found by MapSearch(), 2) setting the map/array
4126 * counter to the total in the map/array, 3) setting the nesting
4127 * level. Setting the map/array counter to the total is not
4128 * strictly correct, but this is OK because this cursor only needs
4129 * to be used to get one item and MapSearch() has already found it
4130 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004131 */
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004132 UsefulInputBuf_Seek(&(pMe->InBuf), SearchInfo.uStartOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004133
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08004134 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
4135
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004136 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07004137
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004138 QCBORDecode_Private_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004139}
4140
4141
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004142/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004143 * Public function, see header qcbor/qcbor_decode.h file
4144 */
4145void
4146QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004147{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07004148 QCBORItem OneItemSeach[2];
4149 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
4150 OneItemSeach[0].label.int64 = nLabel;
4151 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
4152 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07004153
Laurence Lundblade9b334962020-08-27 10:55:53 -07004154 /* The map to enter was found, now finish off entering it. */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004155 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004156}
4157
4158
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004159/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004160 * Public function, see header qcbor/qcbor_decode.h file
4161 */
4162void
4163QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004164{
Laurence Lundbladeec290b82024-06-10 11:10:54 -07004165#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07004166 QCBORItem OneItemSeach[2];
4167 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
4168 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
4169 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
4170 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07004171
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004172 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladeec290b82024-06-10 11:10:54 -07004173#else
4174 (void)szLabel;
4175 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
4176#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004177}
4178
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004179/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004180 * Public function, see header qcbor/qcbor_decode.h file
4181 */
4182void
4183QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07004184{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07004185 QCBORItem OneItemSeach[2];
4186 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
4187 OneItemSeach[0].label.int64 = nLabel;
4188 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
4189 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07004190
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004191 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07004192}
4193
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004194/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004195 * Public function, see header qcbor/qcbor_decode.h file
4196 */
4197void
4198QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundblade34691b92020-05-18 22:25:25 -07004199{
Laurence Lundbladeec290b82024-06-10 11:10:54 -07004200#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07004201 QCBORItem OneItemSeach[2];
4202 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
4203 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
4204 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
4205 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07004206
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004207 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladeec290b82024-06-10 11:10:54 -07004208#else
4209 (void)szLabel;
4210 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
4211#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
Laurence Lundblade1341c592020-04-11 14:19:05 -07004212}
4213
4214
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004215/**
4216 * @brief Semi-private to do the the work for EnterMap() and EnterArray().
4217 *
4218 * @param[in] pMe The decode context
4219 * @param[in] uType QCBOR_TYPE_MAP or QCBOR_TYPE_ARRAY.
4220 * @param[out] pItem The data item for the map or array entered.
4221 *
4222 * The next item in the traversal must be a map or array. This
4223 * consumes that item and does the book keeping to enter the map or
4224 * array.
4225 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004226void
4227QCBORDecode_Private_EnterBoundedMapOrArray(QCBORDecodeContext *pMe,
4228 const uint8_t uType,
4229 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004230{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07004231 QCBORError uErr;
4232
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004233 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07004234 if(pMe->uLastError != QCBOR_SUCCESS) {
4235 // Already in error state; do nothing.
4236 return;
4237 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07004238
Laurence Lundbladed40951e2020-08-28 11:11:14 -07004239 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004240 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07004241 uErr = QCBORDecode_GetNext(pMe, &Item);
4242 if(uErr != QCBOR_SUCCESS) {
4243 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07004244 }
Laurence Lundblade5db34da2024-05-30 03:14:35 -07004245
4246 uint8_t uItemDataType = Item.uDataType;
Laurence Lundbladeec290b82024-06-10 11:10:54 -07004247
4248#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
Laurence Lundblade5db34da2024-05-30 03:14:35 -07004249 if(uItemDataType == QCBOR_TYPE_MAP_AS_ARRAY ) {
4250 uItemDataType = QCBOR_TYPE_ARRAY;
4251 }
Laurence Lundbladeec290b82024-06-10 11:10:54 -07004252#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
4253
Laurence Lundblade5db34da2024-05-30 03:14:35 -07004254 if(uItemDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07004255 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
4256 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07004257 }
4258
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004259 QCBORDecode_Private_SaveTagNumbers(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07004260
4261
Laurence Lundbladef0499502020-08-01 11:55:57 -07004262 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07004263 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004264 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
4265 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07004266 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004267 pMe->nesting.pCurrent->u.ma.uCountCursor++;
4268 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07004269 // Special case to increment nesting level for zero-length maps
4270 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07004271 DecodeNesting_Descend(&(pMe->nesting), uType);
4272 }
4273
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07004274 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004275
Laurence Lundbladec45b5672020-07-25 23:16:36 -07004276 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
4277 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004278
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07004279 if(pItem != NULL) {
4280 *pItem = Item;
4281 }
4282
Laurence Lundbladec45b5672020-07-25 23:16:36 -07004283Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004284 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004285}
4286
Laurence Lundblade02625d42020-06-25 14:41:41 -07004287
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004288/**
4289 * @brief Exit a bounded map, array or bstr (semi-private).
4290 *
4291 * @param[in] pMe Decode context.
4292 * @param[in] uEndOffset The input buffer offset of the end of item exited.
4293 *
4294 * @returns QCBOR_SUCCESS or an error code.
4295 *
4296 * This is the common work for exiting a level that is a bounded map,
4297 * array or bstr wrapped CBOR.
4298 *
4299 * One chunk of work is to set up the pre-order traversal so it is at
4300 * the item just after the bounded map, array or bstr that is being
4301 * exited. This is somewhat complex.
4302 *
4303 * The other work is to level-up the bounded mode to next higest
4304 * bounded mode or the top level if there isn't one.
Laurence Lundblade02625d42020-06-25 14:41:41 -07004305 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004306static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004307QCBORDecode_Private_ExitBoundedLevel(QCBORDecodeContext *pMe,
4308 const uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004309{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004310 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004311
Laurence Lundblade02625d42020-06-25 14:41:41 -07004312 /*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004313 * First the pre-order-traversal byte offset is positioned to the
4314 * item just after the bounded mode item that was just consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07004315 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004316 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
4317
Laurence Lundblade02625d42020-06-25 14:41:41 -07004318 /*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004319 * Next, set the current nesting level to one above the bounded
4320 * level that was just exited.
4321 *
4322 * DecodeNesting_CheckBoundedType() is always called before this
4323 * and makes sure pCurrentBounded is valid.
Laurence Lundblade02625d42020-06-25 14:41:41 -07004324 */
4325 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
4326
4327 /*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004328 * This does the complex work of leveling up the pre-order
4329 * traversal when the end of a map or array or another bounded
4330 * level is reached. It may do nothing, or ascend all the way to
4331 * the top level.
Laurence Lundblade02625d42020-06-25 14:41:41 -07004332 */
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07004333 uErr = QCBORDecode_Private_NestLevelAscender(pMe, NULL, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004334 if(uErr != QCBOR_SUCCESS) {
4335 goto Done;
4336 }
4337
Laurence Lundblade02625d42020-06-25 14:41:41 -07004338 /*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004339 * This makes the next highest bounded level the current bounded
4340 * level. If there is no next highest level, then no bounded mode
4341 * is in effect.
Laurence Lundblade02625d42020-06-25 14:41:41 -07004342 */
4343 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004344
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07004345 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004346
4347Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004348 return uErr;
4349}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004350
Laurence Lundblade02625d42020-06-25 14:41:41 -07004351
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004352/**
4353 * @brief Get started exiting a map or array (semi-private)
4354 *
4355 * @param[in] pMe The decode context
4356 * @param[in] uType QCBOR_TYPE_ARRAY or QCBOR_TYPE_MAP
4357 *
4358 * This does some work for map and array exiting (but not
4359 * bstr exiting). Then QCBORDecode_Private_ExitBoundedLevel()
4360 * is called to do the rest.
4361 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004362void
4363QCBORDecode_Private_ExitBoundedMapOrArray(QCBORDecodeContext *pMe,
4364 const uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004365{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004366 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07004367 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004368 return;
4369 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004370
Laurence Lundblade02625d42020-06-25 14:41:41 -07004371 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004372
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07004373 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07004374 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004375 goto Done;
4376 }
4377
Laurence Lundblade02625d42020-06-25 14:41:41 -07004378 /*
4379 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004380 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07004381 from previous map search, then do a dummy search.
4382 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07004383 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004384 QCBORItem Dummy;
4385 Dummy.uLabelType = QCBOR_TYPE_NONE;
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07004386 uErr = QCBORDecode_Private_MapSearch(pMe, &Dummy, NULL, NULL);
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004387 if(uErr != QCBOR_SUCCESS) {
4388 goto Done;
4389 }
4390 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004391
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004392 uErr = QCBORDecode_Private_ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004393
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004394Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004395 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004396}
4397
4398
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004399// TODO: re order this file with tags stuff last. bstr is a tag thing
4400static QCBORError
4401QCBORDecode_Private_CheckTagNType(QCBORDecodeContext *pMe,
4402 const QCBORItem *pItem,
4403 const size_t uOffset,
4404 const uint8_t *uQCBORTypes,
4405 const uint64_t *uTagNumbers,
4406 const uint8_t uTagRequirement,
4407 bool *bTypeMatched);
4408
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004409/**
4410 * @brief The main work of entering some byte-string wrapped CBOR.
4411 *
4412 * @param[in] pMe The decode context.
4413 * @param[in] pItem The byte string item.
4414 * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX
4415 * @param[out] pBstr Pointer and length of byte string entered.
4416 *
4417 * This is called once the byte string item has been decoded to do all
4418 * the book keeping work for descending a nesting level into the
4419 * nested CBOR.
4420 *
4421 * See QCBORDecode_EnterBstrWrapped() for details on uTagRequirement.
4422 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07004423static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004424QCBORDecode_Private_EnterBstrWrapped(QCBORDecodeContext *pMe,
4425 const QCBORItem *pItem,
4426 const uint8_t uTagRequirement,
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004427 const size_t uOffset,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004428 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004429{
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004430 bool bTypeMatched;
4431 QCBORError uError;
4432
4433 const uint8_t uTypes[] = {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE};
4434 const uint64_t uTagNumbers[] = {CBOR_TAG_CBOR, CBOR_TAG_CBOR_SEQUENCE, CBOR_TAG_INVALID64};
4435
4436
Laurence Lundbladec45b5672020-07-25 23:16:36 -07004437 if(pBstr) {
4438 *pBstr = NULLUsefulBufC;
4439 }
4440
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004441 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004442 return pMe->uLastError;
4443 }
4444
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004445 if(pItem->uDataAlloc) {
4446 return QCBOR_ERR_CANNOT_ENTER_ALLOCATED_STRING;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004447 }
4448
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004449 uError = QCBORDecode_Private_CheckTagNType(pMe,
4450 pItem,
4451 uOffset,
4452 uTypes, // TODO: maybe this should be empty
4453 uTagNumbers,
4454 uTagRequirement,
4455 &bTypeMatched);
4456
4457 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
4458 uError = QCBOR_ERR_BAD_TAG_CONTENT; // TODO: error
4459 }
4460
4461
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004462 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004463 /* Reverse the decrement done by GetNext() for the bstr so the
4464 * increment in QCBORDecode_NestLevelAscender() called by
4465 * ExitBoundedLevel() will work right.
4466 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004467 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07004468 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004469
4470 if(pBstr) {
4471 *pBstr = pItem->val.string;
4472 }
4473
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004474 /* This saves the current length of the UsefulInputBuf and then
4475 * narrows the UsefulInputBuf to start and length of the wrapped
4476 * CBOR that is being entered.
4477 *
4478 * Most of these calls are simple inline accessors so this doesn't
4479 * amount to much code.
4480 */
4481
Laurence Lundbladea4308a82020-10-03 18:08:57 -07004482 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004483 /* This check makes the cast of uPreviousLength to uint32_t below safe. */
4484 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07004485 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07004486 goto Done;
4487 }
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004488
4489 const size_t uStartOfBstr = UsefulInputBuf_PointerToOffset(&(pMe->InBuf),
4490 pItem->val.string.ptr);
4491 /* This check makes the cast of uStartOfBstr to uint32_t below safe. */
4492 if(uStartOfBstr == SIZE_MAX || uStartOfBstr > QCBOR_MAX_DECODE_INPUT_SIZE) {
4493 /* This should never happen because pItem->val.string.ptr should
4494 * always be valid since it was just returned.
4495 */
4496 uError = QCBOR_ERR_INPUT_TOO_LARGE;
4497 goto Done;
4498 }
4499
4500 const size_t uEndOfBstr = uStartOfBstr + pItem->val.string.len;
4501
4502 UsefulInputBuf_Seek(&(pMe->InBuf), uStartOfBstr);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07004503 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004504
Laurence Lundblade02625d42020-06-25 14:41:41 -07004505 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07004506 (uint32_t)uPreviousLength,
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004507 (uint32_t)uStartOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004508Done:
4509 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004510}
4511
4512
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004513static void
4514QCBORDecode_Private_GetAndTell(QCBORDecodeContext *pMe, QCBORItem *Item, size_t *uOffset)
4515{
4516#ifndef QCBOR_DISABLE_TAGS
4517 if(pMe->uLastError != QCBOR_SUCCESS) {
4518 return;
4519 }
4520
4521 *uOffset = QCBORDecode_Tell(pMe);
4522#else
4523 *uOffset = SIZE_MAX;
4524
4525#endif /* ! QCBOR_DISABLE_TAGS */
4526 pMe->uLastError = (uint8_t)QCBORDecode_Private_GetNextTagContent(pMe, Item);
4527}
4528
4529
Laurence Lundblade02625d42020-06-25 14:41:41 -07004530/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004531 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07004532 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004533void
4534QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
4535 const uint8_t uTagRequirement,
4536 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07004537{
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004538 QCBORItem Item;
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004539 size_t uOffset;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07004540
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004541 QCBORDecode_Private_GetAndTell(pMe, &Item, &uOffset);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004542 pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
4543 &Item,
4544 uTagRequirement,
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004545 uOffset,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004546 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07004547}
4548
4549
Laurence Lundblade02625d42020-06-25 14:41:41 -07004550/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004551 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07004552 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004553void
4554QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
4555 const int64_t nLabel,
4556 const uint8_t uTagRequirement,
4557 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004558{
4559 QCBORItem Item;
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004560 size_t uOffset;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004561
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004562 QCBORDecode_GetItemInMapNoCheckN(pMe, nLabel, QCBOR_TYPE_BYTE_STRING, &Item, &uOffset);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004563 pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
4564 &Item,
4565 uTagRequirement,
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004566 uOffset,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004567 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004568}
4569
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004570
Laurence Lundblade02625d42020-06-25 14:41:41 -07004571/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004572 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07004573 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004574void
4575QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
4576 const char *szLabel,
4577 const uint8_t uTagRequirement,
4578 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004579{
4580 QCBORItem Item;
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004581 size_t uOffset;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004582
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004583 QCBORDecode_GetItemInMapNoCheckSZ(pMe, szLabel, QCBOR_TYPE_BYTE_STRING, &Item, &uOffset);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004584 pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
4585 &Item,
4586 uTagRequirement,
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004587 uOffset,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004588 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004589}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004590
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004591
Laurence Lundblade02625d42020-06-25 14:41:41 -07004592/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004593 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07004594 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004595void
4596QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004597{
Laurence Lundblade02625d42020-06-25 14:41:41 -07004598 if(pMe->uLastError != QCBOR_SUCCESS) {
4599 // Already in error state; do nothing.
4600 return;
4601 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004602
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07004603 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07004604 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07004605 return;
4606 }
4607
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004608 const uint32_t uEndOfBstr = (uint32_t)UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
4609
Laurence Lundblade02625d42020-06-25 14:41:41 -07004610 /*
4611 Reset the length of the UsefulInputBuf to what it was before
4612 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004613 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07004614 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004615 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004616
4617
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004618 QCBORError uErr = QCBORDecode_Private_ExitBoundedLevel(pMe, uEndOfBstr);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004619 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004620}
4621
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004622
Laurence Lundbladee6430642020-03-14 21:15:44 -07004623
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004624/**
4625 * @brief Process simple type true and false, a boolean
4626 *
4627 * @param[in] pMe The decode context.
4628 * @param[in] pItem The item with either true or false.
4629 * @param[out] pBool The boolean value output.
4630 *
4631 * Sets the internal error if the item isn't a true or a false. Also
4632 * records any tag numbers as the tag numbers of the last item.
4633 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004634static void
4635QCBORDecode_Private_ProcessBool(QCBORDecodeContext *pMe,
4636 const QCBORItem *pItem,
4637 bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004638{
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004639 if(pMe->uLastError != QCBOR_SUCCESS) {
4640 /* Already in error state, do nothing */
4641 return;
4642 }
4643
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004644 switch(pItem->uDataType) {
4645 case QCBOR_TYPE_TRUE:
4646 *pBool = true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004647 break;
4648
4649 case QCBOR_TYPE_FALSE:
4650 *pBool = false;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004651 break;
4652
4653 default:
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004654 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004655 break;
4656 }
4657}
Laurence Lundbladee6430642020-03-14 21:15:44 -07004658
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004659
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004660/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004661 * Public function, see header qcbor/qcbor_decode.h file
4662 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004663void
4664QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004665{
Laurence Lundbladec4537442020-04-14 18:53:22 -07004666 QCBORItem Item;
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07004667 QCBORDecode_VGetNext(pMe, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004668 QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004669}
4670
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004671
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004672/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004673 * Public function, see header qcbor/qcbor_decode.h file
4674 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004675void
4676QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe,
4677 const int64_t nLabel,
4678 bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004679{
4680 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004681 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004682 QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004683}
4684
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004685
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004686/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004687 * Public function, see header qcbor/qcbor_decode.h file
4688 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004689void
4690QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe,
4691 const char *szLabel,
4692 bool *pValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004693{
4694 QCBORItem Item;
4695 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004696 QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004697}
4698
4699
Laurence Lundblade3888f002024-06-12 21:20:56 -07004700/**
4701 * @brief Process simple values.
4702 *
4703 * @param[in] pMe The decode context.
4704 * @param[in] pItem The item with the simple value.
4705 * @param[out] puSimple The simple value output.
4706 *
4707 * Sets the internal error if the item isn't a true or a false. Also
4708 * records any tag numbers as the tag numbers of the last item.
4709 */
4710static void
4711QCBORDecode_Private_ProcessSimple(QCBORDecodeContext *pMe,
4712 const QCBORItem *pItem,
4713 uint8_t *puSimple)
4714{
4715 if(pMe->uLastError != QCBOR_SUCCESS) {
4716 return;
4717 }
4718
4719 /* It's kind of lame to remap true...undef back to simple values, but
4720 * this function isn't used much and to not do it would require
4721 * changing GetNext() behavior in an incompatible way.
4722 */
4723 switch(pItem->uDataType) {
4724 case QCBOR_TYPE_UKNOWN_SIMPLE:
4725 *puSimple = pItem->val.uSimple;
4726 break;
4727
4728 case QCBOR_TYPE_TRUE:
4729 *puSimple = CBOR_SIMPLEV_TRUE;
4730 break;
4731
4732 case QCBOR_TYPE_FALSE:
4733 *puSimple = CBOR_SIMPLEV_FALSE;
4734 break;
4735
4736 case QCBOR_TYPE_NULL:
4737 *puSimple = CBOR_SIMPLEV_NULL;
4738 break;
4739
4740 case QCBOR_TYPE_UNDEF:
4741 *puSimple = CBOR_SIMPLEV_UNDEF;
4742 break;
4743
4744 default:
4745 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
4746 return;
4747 }
Laurence Lundblade3888f002024-06-12 21:20:56 -07004748}
4749
4750/*
4751 * Public function, see header qcbor/qcbor_decode.h file
4752 */
4753void
4754QCBORDecode_GetSimple(QCBORDecodeContext *pMe, uint8_t *puSimple)
4755{
4756 QCBORItem Item;
Laurence Lundblade3888f002024-06-12 21:20:56 -07004757 QCBORDecode_VGetNext(pMe, &Item);
4758 QCBORDecode_Private_ProcessSimple(pMe, &Item, puSimple);
4759}
4760
4761/*
4762 * Public function, see header qcbor/qcbor_decode.h file
4763 */
4764void
4765QCBORDecode_GetSimpleInMapN(QCBORDecodeContext *pMe,
4766 int64_t nLabel,
4767 uint8_t *puSimpleValue)
4768{
4769 QCBORItem Item;
4770 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3888f002024-06-12 21:20:56 -07004771 QCBORDecode_Private_ProcessSimple(pMe, &Item, puSimpleValue);
4772}
4773
4774/*
4775 * Public function, see header qcbor/qcbor_decode.h file
4776 */
4777void
4778QCBORDecode_GetSimpleInMapSZ(QCBORDecodeContext *pMe,
4779 const char *szLabel,
4780 uint8_t *puSimpleValue)
4781{
4782 QCBORItem Item;
4783 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3888f002024-06-12 21:20:56 -07004784 QCBORDecode_Private_ProcessSimple(pMe, &Item, puSimpleValue);
4785}
4786
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004787
Laurence Lundbladec7114722020-08-13 05:11:40 -07004788
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004789
4790#ifndef QCBOR_DISABLE_TAGS
4791// TODO: uTagNumber might be better a list than calling this multiple times
4792static QCBORError
4793QCBORDecode_Private_Check1TagNumber(const QCBORDecodeContext *pMe,
4794 const QCBORItem *pItem,
4795 const uint64_t uTagNumber,
4796 const size_t uOffset)
Laurence Lundbladec7114722020-08-13 05:11:40 -07004797{
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004798 if(pItem->auTagNumbers[0] == CBOR_TAG_INVALID16) {
4799 /* There are no tag numbers at all, so no unprocessed */
4800 return QCBOR_SUCCESS;
4801 }
4802
4803 /* There are some tag numbers, so keep checking. This check passes
4804 * if there is one and only one tag number that matches uTagNumber
4805 */
4806
4807 // TODO: behave different in v1 and v2?
4808
4809 const uint64_t uInnerTag = QCBORDecode_GetNthTagNumber(pMe, pItem, 0);
4810
4811 if(uInnerTag == uTagNumber && pItem->auTagNumbers[1] == CBOR_TAG_INVALID16 ) {
4812 /* The only tag number is the one we are processing so no unprocessed */
4813 return QCBOR_SUCCESS;
4814 }
4815
4816 if(uOffset != pMe->uTagNumberCheckOffset) {
4817 /* processed tag numbers are for some other item, not us */
4818 return QCBOR_ERR_UNPROCESSED_TAG_NUMBER;
4819 }
4820
4821 if(pMe->uTagNumberIndex != 1) {
4822 return QCBOR_ERR_UNPROCESSED_TAG_NUMBER;
4823 }
4824
4825 return QCBOR_SUCCESS;
4826}
4827#endif
4828
4829
4830static QCBORError
4831QCBORDecode_Private_CheckTagNType(QCBORDecodeContext *pMe,
4832 const QCBORItem *pItem,
4833 const size_t uOffset,
4834 const uint8_t *uQCBORTypes,
4835 const uint64_t *uTagNumbers,
4836 const uint8_t uTagRequirement,
4837 bool *bTypeMatched)
4838{
4839 const int nTagReq = uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
4840
4841 *bTypeMatched = false;
4842 for(const uint8_t *pTNum = uQCBORTypes; *pTNum != QCBOR_TYPE_NONE; pTNum++) {
4843 if(pItem->uDataType == *pTNum) {
4844 *bTypeMatched = true;
4845 break;
4846 }
4847 }
4848
4849#ifndef QCBOR_DISABLE_TAGS
4850 bool bTagNumberMatched;
4851 QCBORError uErr;
4852 const uint64_t uInnerTag = QCBORDecode_GetNthTagNumber(pMe, pItem, 0);
4853
4854 bTagNumberMatched = false;
4855 for(const uint64_t *pQType = uTagNumbers; *pQType != CBOR_TAG_INVALID64; pQType++) {
4856 if(uInnerTag == *pQType) {
4857 bTagNumberMatched = true;
4858 break;
4859 }
4860 }
4861
4862
4863 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
4864 /* There must be a tag number */
4865 if(!bTagNumberMatched && !*bTypeMatched) {
4866 return QCBOR_ERR_UNEXPECTED_TYPE; // TODO: error code
4867 }
4868
4869 } else if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
4870 if(bTagNumberMatched || *bTypeMatched) {
4871 return QCBOR_ERR_UNEXPECTED_TYPE; // TODO: error code
4872 }
4873
4874 } else if(nTagReq == QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG) {
4875 /* No check necessary */
4876 }
4877
4878 /* Now check if there are extra tags and if there's an error in them */
4879 if(!(uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS)) {
4880 /* The flag to ignore extra is not set, so keep checking */
4881 for(const uint64_t *pTNum = uTagNumbers; *pTNum != CBOR_TAG_INVALID64; pTNum++) {
4882 uErr = QCBORDecode_Private_Check1TagNumber(pMe, pItem, *pTNum, uOffset);
4883 if(uErr != QCBOR_SUCCESS) {
4884 return uErr;
4885 }
4886 }
4887 }
4888
4889 return QCBOR_SUCCESS;
4890#else
4891 (void)pMe;
4892 (void)uOffset;
4893 (void)uTagNumbers;
4894
4895 if(nTagReq != QCBOR_TAG_REQUIREMENT_TAG && bTypeMatched) {
4896 return QCBOR_SUCCESS;
4897 } else {
4898 return QCBOR_ERR_UNEXPECTED_TYPE;
4899 }
4900
4901#endif
4902
4903}
4904
4905
Laurence Lundblade68769332024-11-03 13:09:20 -08004906static void
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004907QCBORDecode_Private_ProcessTagItemMulti(QCBORDecodeContext *pMe,
4908 QCBORItem *pItem,
4909 const uint8_t uTagRequirement,
4910 const uint8_t uQCBORTypes[],
4911 const uint64_t uTagNumbers[],
4912 QCBORTagContentCallBack *pfCB,
4913 size_t uOffset)
4914{
4915 QCBORError uErr;
4916 bool bTypeMatched;
4917
Laurence Lundbladec7114722020-08-13 05:11:40 -07004918 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07004919 return;
4920 }
4921
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004922 uErr = QCBORDecode_Private_CheckTagNType(pMe,
4923 pItem,
4924 uOffset,
4925 uQCBORTypes,
4926 uTagNumbers,
4927 uTagRequirement,
4928 &bTypeMatched);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004929 if(uErr != QCBOR_SUCCESS) {
4930 goto Done;
4931 }
4932
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004933 if(!bTypeMatched) {
4934 /* Tag content wasn't previously processed, do it now */
4935 uErr = (*pfCB)(pMe, NULL, uTagNumbers[0], pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004936 if(uErr != QCBOR_SUCCESS) {
4937 goto Done;
4938 }
4939 }
4940
Laurence Lundbladec7114722020-08-13 05:11:40 -07004941Done:
4942 pMe->uLastError = (uint8_t)uErr;
4943}
4944
4945
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004946/*
4947 **/
Laurence Lundblade68769332024-11-03 13:09:20 -08004948static void
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004949QCBORDecode_Private_ProcessTagItem(QCBORDecodeContext *pMe,
4950 QCBORItem *pItem,
4951 const uint8_t uTagRequirement,
4952 const uint8_t uQCBORTypes[],
4953 const uint64_t uTagNumber,
4954 QCBORTagContentCallBack *pfCB,
4955 size_t uOffset)
4956{
4957 uint64_t auTagNumbers[2];
4958
4959 auTagNumbers[0] = uTagNumber;
4960 auTagNumbers[1] = CBOR_TAG_INVALID64;
4961
4962 QCBORDecode_Private_ProcessTagItemMulti(pMe,
4963 pItem,
4964 uTagRequirement,
4965 uQCBORTypes,
4966 auTagNumbers,
4967 pfCB,
4968 uOffset);
4969}
4970
4971
4972static void
Laurence Lundblade68769332024-11-03 13:09:20 -08004973QCBORDecode_Private_ProcessTagOne(QCBORDecodeContext *pMe,
4974 QCBORItem *pItem,
4975 const uint8_t uTagRequirement,
4976 const uint8_t uQCBORType,
4977 const uint64_t uTagNumber,
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004978 QCBORTagContentCallBack *pfCB,
Laurence Lundblade68769332024-11-03 13:09:20 -08004979 const size_t uOffset)
Laurence Lundblade721b56e2024-10-22 03:02:04 -07004980{
4981 uint8_t auQCBORType[2];
4982
4983 auQCBORType[0] = uQCBORType;
4984 auQCBORType[1] = QCBOR_TYPE_NONE;
4985
4986 QCBORDecode_Private_ProcessTagItem(pMe,
4987 pItem,
4988 uTagRequirement,
4989 auQCBORType,
4990 uTagNumber,
4991 pfCB,
4992 uOffset);
4993}
4994
4995
4996
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004997
4998/*
4999 * Public function, see header qcbor/qcbor_spiffy_decode.h file
5000 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005001void
5002QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
5003 uint8_t uTagRequirement,
5004 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07005005{
Laurence Lundbladec7114722020-08-13 05:11:40 -07005006 QCBORItem Item;
Laurence Lundblade721b56e2024-10-22 03:02:04 -07005007 size_t uOffset;
5008
5009 QCBORDecode_Private_GetAndTell(pMe, &Item, &uOffset);
5010 QCBORDecode_Private_ProcessTagOne(pMe,
5011 &Item,
5012 uTagRequirement,
5013 QCBOR_TYPE_DATE_EPOCH,
5014 CBOR_TAG_DATE_EPOCH,
5015 QCBORDecode_DateEpochTagCB,
5016 uOffset);
5017 *pnTime = Item.val.epochDate.nSeconds;
Laurence Lundbladec7114722020-08-13 05:11:40 -07005018}
5019
5020
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005021/*
5022 * Public function, see header qcbor/qcbor_spiffy_decode.h file
5023 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07005024void
5025QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
5026 int64_t nLabel,
5027 uint8_t uTagRequirement,
5028 int64_t *pnTime)
5029{
5030 QCBORItem Item;
Laurence Lundblade721b56e2024-10-22 03:02:04 -07005031 size_t uOffset;
5032
5033 QCBORDecode_GetItemInMapNoCheckN(pMe, nLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
5034 QCBORDecode_Private_ProcessTagOne(pMe,
5035 &Item,
5036 uTagRequirement,
5037 QCBOR_TYPE_DATE_EPOCH,
5038 CBOR_TAG_DATE_EPOCH,
5039 QCBORDecode_DateEpochTagCB,
5040 uOffset);
5041 *pnTime = Item.val.epochDate.nSeconds;
Laurence Lundbladec7114722020-08-13 05:11:40 -07005042}
5043
5044
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005045/*
5046 * Public function, see header qcbor/qcbor_spiffy_decode.h file
5047 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07005048void
5049QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
5050 const char *szLabel,
5051 uint8_t uTagRequirement,
5052 int64_t *pnTime)
5053{
5054 QCBORItem Item;
Laurence Lundblade721b56e2024-10-22 03:02:04 -07005055 size_t uOffset;
Laurence Lundbladec7114722020-08-13 05:11:40 -07005056
Laurence Lundblade721b56e2024-10-22 03:02:04 -07005057 QCBORDecode_GetItemInMapNoCheckSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
5058 QCBORDecode_Private_ProcessTagOne(pMe,
5059 &Item,
5060 uTagRequirement,
5061 QCBOR_TYPE_DATE_EPOCH,
5062 CBOR_TAG_DATE_EPOCH,
5063 QCBORDecode_DateEpochTagCB,
5064 uOffset);
5065 *pnTime = Item.val.epochDate.nSeconds;
Laurence Lundblade46d63e92021-05-13 11:37:10 -07005066}
5067
5068
5069/*
5070 * Public function, see header qcbor/qcbor_decode.h
5071 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005072void
5073QCBORDecode_GetEpochDays(QCBORDecodeContext *pMe,
5074 uint8_t uTagRequirement,
5075 int64_t *pnDays)
Laurence Lundblade46d63e92021-05-13 11:37:10 -07005076{
Laurence Lundblade46d63e92021-05-13 11:37:10 -07005077 QCBORItem Item;
Laurence Lundblade721b56e2024-10-22 03:02:04 -07005078 size_t uOffset;
5079
5080 QCBORDecode_Private_GetAndTell(pMe, &Item, &uOffset);
5081 QCBORDecode_Private_ProcessTagOne(pMe,
5082 &Item,
5083 uTagRequirement,
5084 QCBOR_TYPE_DAYS_EPOCH,
5085 CBOR_TAG_DAYS_EPOCH,
5086 QCBORDecode_DaysEpochTagCB,
5087 uOffset);
5088 *pnDays = Item.val.epochDays;
Laurence Lundblade46d63e92021-05-13 11:37:10 -07005089}
5090
5091
5092/*
5093 * Public function, see header qcbor/qcbor_decode.h
5094 */
5095void
5096QCBORDecode_GetEpochDaysInMapN(QCBORDecodeContext *pMe,
5097 int64_t nLabel,
5098 uint8_t uTagRequirement,
5099 int64_t *pnDays)
5100{
5101 QCBORItem Item;
Laurence Lundblade721b56e2024-10-22 03:02:04 -07005102 size_t uOffset;
5103
5104 QCBORDecode_GetItemInMapNoCheckN(pMe, nLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
5105 QCBORDecode_Private_ProcessTagOne(pMe,
5106 &Item,
5107 uTagRequirement,
5108 QCBOR_TYPE_DAYS_EPOCH,
5109 CBOR_TAG_DAYS_EPOCH,
5110 QCBORDecode_DaysEpochTagCB,
5111 uOffset);
5112 *pnDays = Item.val.epochDays;
Laurence Lundblade46d63e92021-05-13 11:37:10 -07005113}
5114
5115
5116/*
5117 * Public function, see header qcbor/qcbor_decode.h
5118 */
5119void
5120QCBORDecode_GetEpochDaysInMapSZ(QCBORDecodeContext *pMe,
5121 const char *szLabel,
5122 uint8_t uTagRequirement,
5123 int64_t *pnDays)
5124{
5125 QCBORItem Item;
Laurence Lundblade721b56e2024-10-22 03:02:04 -07005126 size_t uOffset;
5127
5128 QCBORDecode_GetItemInMapNoCheckSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
5129 QCBORDecode_Private_ProcessTagOne(pMe,
5130 &Item,
5131 uTagRequirement,
5132 QCBOR_TYPE_DAYS_EPOCH,
5133 CBOR_TAG_DAYS_EPOCH,
5134 QCBORDecode_DaysEpochTagCB,
5135 uOffset);
5136 *pnDays = Item.val.epochDays;
Laurence Lundblade46d63e92021-05-13 11:37:10 -07005137}
5138
5139
5140
Laurence Lundblade721b56e2024-10-22 03:02:04 -07005141
Laurence Lundblade37286c02022-09-03 10:05:02 -07005142void
Laurence Lundblade721b56e2024-10-22 03:02:04 -07005143QCBORDecode_Private_GetTaggedString(QCBORDecodeContext *pMe,
5144 const uint8_t uTagRequirement,
5145 const uint8_t uQCBOR_Type,
5146 const uint64_t uTagNumber,
5147 UsefulBufC *pStr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07005148{
Laurence Lundbladec4537442020-04-14 18:53:22 -07005149 QCBORItem Item;
Laurence Lundblade721b56e2024-10-22 03:02:04 -07005150 size_t uOffset;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005151
Laurence Lundblade721b56e2024-10-22 03:02:04 -07005152 QCBORDecode_Private_GetAndTell(pMe, &Item, &uOffset);
5153 QCBORDecode_Private_ProcessTagOne(pMe,
5154 &Item,
5155 uTagRequirement,
5156 uQCBOR_Type,
5157 uTagNumber,
5158 QCBORDecode_StringsTagCB,
5159 uOffset);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005160
5161 if(pMe->uLastError == QCBOR_SUCCESS) {
Laurence Lundblade721b56e2024-10-22 03:02:04 -07005162 *pStr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07005163 } else {
Laurence Lundblade721b56e2024-10-22 03:02:04 -07005164 *pStr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005165 }
5166}
5167
Laurence Lundbladec4537442020-04-14 18:53:22 -07005168
5169
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005170
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005171/**
5172 * @brief Common processing for a big number tag.
5173 *
5174 * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX.
5175 * @param[in] pItem The item with the date.
Laurence Lundblade68769332024-11-03 13:09:20 -08005176 * @param[out] pBignumber The returned big number
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005177 * @param[out] pbIsNegative The returned sign of the big number.
5178 *
5179 * Common processing for the big number tag. Mostly make sure
5180 * the tag content is correct and copy forward any further other tag
5181 * numbers.
5182 */
Laurence Lundblade721b56e2024-10-22 03:02:04 -07005183static void
Laurence Lundblade68769332024-11-03 13:09:20 -08005184QCBORDecode_Private_BigNumberRawMain(QCBORDecodeContext *pMe,
5185 const uint8_t uTagRequirement,
5186 QCBORItem *pItem,
5187 UsefulBufC *pBignumber,
5188 bool *pbIsNegative,
5189 size_t uOffset)
Laurence Lundbladec4537442020-04-14 18:53:22 -07005190{
Laurence Lundblade68769332024-11-03 13:09:20 -08005191 // TODO: refer to the static const ones instead
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005192
Laurence Lundblade721b56e2024-10-22 03:02:04 -07005193 const uint8_t puTypes[] = {QCBOR_TYPE_POSBIGNUM,QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE};
5194
5195 const uint64_t puTNs[] = {CBOR_TAG_POS_BIGNUM, CBOR_TAG_NEG_BIGNUM, CBOR_TAG_INVALID64};
5196
5197 QCBORDecode_Private_ProcessTagItemMulti(pMe,
5198 pItem,
5199 uTagRequirement,
5200 puTypes,
Laurence Lundblade68769332024-11-03 13:09:20 -08005201 puTNs,
5202 QCBORDecode_StringsTagCB,
5203 uOffset);
Laurence Lundblade721b56e2024-10-22 03:02:04 -07005204 if(pMe->uLastError) {
5205 return;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005206 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005207
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005208 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
5209 *pbIsNegative = false;
5210 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
5211 *pbIsNegative = true;
5212 }
Laurence Lundblade68769332024-11-03 13:09:20 -08005213 *pBignumber = pItem->val.bigNum;
Laurence Lundblade721b56e2024-10-22 03:02:04 -07005214}
5215
5216
5217static void
5218QCBORDecode_Private_GetMIME(QCBORDecodeContext *pMe,
5219 const uint8_t uTagRequirement,
5220 QCBORItem *pItem,
5221 UsefulBufC *pValue,
5222 bool *pbIsTag257,
5223 size_t uOffset)
5224{
5225 QCBORError uErr;
5226
5227 const uint8_t puTypes[] = {QCBOR_TYPE_MIME, QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE};
5228
5229 const uint64_t puTNs[] = {CBOR_TAG_MIME, CBOR_TAG_BINARY_MIME, CBOR_TAG_INVALID64};
5230
5231 QCBORDecode_Private_ProcessTagItemMulti(pMe,
5232 pItem,
5233 uTagRequirement,
5234 puTypes,
5235 puTNs,
5236 QCBORDecode_MIMETagCB,
5237 uOffset);
5238 if(pMe->uLastError) {
5239 return;
5240 }
5241
5242 if(pItem->uDataType == QCBOR_TYPE_MIME) {
5243 *pbIsTag257 = false;
5244 } else if(pItem->uDataType == QCBOR_TYPE_BINARY_MIME) {
5245 *pbIsTag257 = true;
5246 }
5247 *pValue = pItem->val.string;
5248
5249
5250 uErr = QCBOR_SUCCESS;
5251
5252 pMe->uLastError = (uint8_t)uErr;
5253}
5254
5255
5256void
5257QCBORDecode_GetMIMEMessage(QCBORDecodeContext *pMe,
5258 const uint8_t uTagRequirement,
5259 UsefulBufC *pMessage,
5260 bool *pbIsTag257)
5261{
5262 QCBORItem Item;
5263 size_t uOffset;
5264
5265 QCBORDecode_Private_GetAndTell(pMe, &Item, &uOffset);
5266 QCBORDecode_Private_GetMIME(pMe,
5267 uTagRequirement,
5268 &Item,
5269 pMessage,
5270 pbIsTag257,
5271 uOffset);
5272}
5273
5274void
5275QCBORDecode_GetMIMEMessageInMapN(QCBORDecodeContext *pMe,
5276 const int64_t nLabel,
5277 const uint8_t uTagRequirement,
5278 UsefulBufC *pMessage,
5279 bool *pbIsTag257)
5280{
5281 QCBORItem Item;
5282 size_t uOffset;
5283
5284 QCBORDecode_GetItemInMapNoCheckN(pMe, nLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
5285 QCBORDecode_Private_GetMIME(pMe,
5286 uTagRequirement,
5287 &Item,
5288 pMessage,
5289 pbIsTag257,
5290 uOffset);
5291}
5292
5293void
5294QCBORDecode_GetMIMEMessageInMapSZ(QCBORDecodeContext *pMe,
5295 const char *szLabel,
5296 const uint8_t uTagRequirement,
5297 UsefulBufC *pMessage,
5298 bool *pbIsTag257)
5299{
5300 QCBORItem Item;
5301 size_t uOffset;
5302
5303 QCBORDecode_GetItemInMapNoCheckSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
5304 QCBORDecode_Private_GetMIME(pMe,
5305 uTagRequirement,
5306 &Item,
5307 pMessage,
5308 pbIsTag257,
5309 uOffset);
Laurence Lundbladec4537442020-04-14 18:53:22 -07005310}
5311
5312
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07005313/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005314 * Public function, see header qcbor/qcbor_spiffy_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005315 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005316void
Laurence Lundblade68769332024-11-03 13:09:20 -08005317QCBORDecode_GetTBigNumberRaw(QCBORDecodeContext *pMe,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005318 const uint8_t uTagRequirement,
Laurence Lundblade68769332024-11-03 13:09:20 -08005319 UsefulBufC *pBignumber,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005320 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005321{
Laurence Lundblade721b56e2024-10-22 03:02:04 -07005322 QCBORItem Item;
5323 size_t uOffset;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005324
Laurence Lundblade68769332024-11-03 13:09:20 -08005325 QCBORDecode_Private_GetAndTell(pMe, &Item, &uOffset);
5326 QCBORDecode_Private_BigNumberRawMain(pMe,
5327 uTagRequirement,
5328 &Item,
5329 pBignumber,
5330 pbIsNegative,
5331 uOffset);
5332}
5333
5334/*
5335 * Public function, see header qcbor/qcbor_spiffy_decode.h
5336 */
5337void
5338QCBORDecode_GetTBigNumberRawInMapN(QCBORDecodeContext *pMe,
5339 const int64_t nLabel,
5340 const uint8_t uTagRequirement,
5341 UsefulBufC *pBigNumber,
5342 bool *pbIsNegative)
5343{
5344 QCBORItem Item;
5345 size_t uOffset;
5346
5347 QCBORDecode_GetItemInMapNoCheckN(pMe, nLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
5348 QCBORDecode_Private_BigNumberRawMain(pMe,
5349 uTagRequirement,
5350 &Item,
5351 pBigNumber,
5352 pbIsNegative,
5353 uOffset);
5354}
5355
5356/*
5357 * Public function, see header qcbor/qcbor_spiffy_decode.h
5358 */
5359void
5360QCBORDecode_GetTBigNumberRawInMapSZ(QCBORDecodeContext *pMe,
5361 const char *szLabel,
5362 const uint8_t uTagRequirement,
5363 UsefulBufC *pBigNumber,
5364 bool *pbIsNegative)
5365{
5366 QCBORItem Item;
5367 size_t uOffset;
5368
Laurence Lundblade721b56e2024-10-22 03:02:04 -07005369 QCBORDecode_GetItemInMapNoCheckSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
Laurence Lundblade68769332024-11-03 13:09:20 -08005370 QCBORDecode_Private_BigNumberRawMain(pMe,
5371 uTagRequirement,
5372 &Item,
5373 pBigNumber,
5374 pbIsNegative,
5375 uOffset);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005376}
5377
5378
5379
Laurence Lundblade93d89472020-10-03 22:30:50 -07005380// Improvement: add methods for wrapped CBOR, a simple alternate
5381// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07005382
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005383
5384
5385
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005386#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07005387
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005388/**
5389 * @brief Prototype for conversion of exponent and mantissa to unsigned integer.
5390 *
5391 * @param[in] uMantissa The mantissa.
5392 * @param[in] nExponent The exponent.
5393 * @param[out] puResult The resulting integer.
5394 *
5395 * Concrete implementations of this are for exponent base 10 and 2 supporting
5396 * decimal fractions and big floats.
5397 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005398typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005399
5400
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005401/**
5402 * @brief Base 10 exponentiate a mantissa and exponent into an unsigned 64-bit integer.
5403 *
5404 * @param[in] uMantissa The unsigned integer mantissa.
5405 * @param[in] nExponent The signed integer exponent.
5406 * @param[out] puResult Place to return the unsigned integer result.
5407 *
5408 * This computes: mantissa * 10 ^^ exponent as for a decimal fraction. The output is a 64-bit
5409 * unsigned integer.
5410 *
5411 * There are many inputs for which the result will not fit in the
Laurence Lundblade88ba5662024-11-03 02:10:24 -08005412 * 64-bit integer and @ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005413 * be returned.
5414 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07005415static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005416QCBOR_Private_Exponentitate10(const uint64_t uMantissa,
5417 int64_t nExponent,
5418 uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07005419{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005420 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005421
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005422 if(uResult != 0) {
5423 /* This loop will run a maximum of 19 times because
5424 * UINT64_MAX < 10 ^^ 19. More than that will cause
5425 * exit with the overflow error
5426 */
5427 for(; nExponent > 0; nExponent--) {
5428 if(uResult > UINT64_MAX / 10) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005429 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005430 }
5431 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005432 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005433
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005434 for(; nExponent < 0; nExponent++) {
5435 uResult = uResult / 10;
5436 if(uResult == 0) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005437 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005438 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005439 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005440 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005441 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07005442
5443 *puResult = uResult;
5444
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005445 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005446}
5447
5448
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005449/**
5450 * @brief Base 2 exponentiate a mantissa and exponent into an unsigned 64-bit integer.
5451 *
5452 * @param[in] uMantissa The unsigned integer mantissa.
5453 * @param[in] nExponent The signed integer exponent.
5454 * @param[out] puResult Place to return the unsigned integer result.
5455 *
5456 * This computes: mantissa * 2 ^^ exponent as for a big float. The
5457 * output is a 64-bit unsigned integer.
5458 *
5459 * There are many inputs for which the result will not fit in the
Laurence Lundblade88ba5662024-11-03 02:10:24 -08005460 * 64-bit integer and @ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005461 * be returned.
5462 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07005463static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005464QCBOR_Private_Exponentitate2(const uint64_t uMantissa,
5465 int64_t nExponent,
5466 uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005467{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005468 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005469
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005470 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005471
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005472 /* This loop will run a maximum of 64 times because INT64_MAX <
5473 * 2^31. More than that will cause exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07005474 */
5475 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005476 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005477 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005478 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005479 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005480 nExponent--;
5481 }
5482
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005483 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005484 if(uResult == 0) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005485 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005486 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005487 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005488 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005489 }
5490
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005491 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005492
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005493 return QCBOR_SUCCESS;
5494}
5495
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005496
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005497/**
5498 * @brief Exponentiate a signed mantissa and signed exponent to produce a signed result.
5499 *
5500 * @param[in] nMantissa Signed integer mantissa.
5501 * @param[in] nExponent Signed integer exponent.
5502 * @param[out] pnResult Place to put the signed integer result.
5503 * @param[in] pfExp Exponentiation function.
5504 *
5505 * @returns Error code
5506 *
Laurence Lundblade88ba5662024-11-03 02:10:24 -08005507 * @c pfExp performs exponentiation on and unsigned mantissa and
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005508 * produces an unsigned result. This converts the mantissa from signed
5509 * and converts the result to signed. The exponentiation function is
5510 * either for base 2 or base 10 (and could be other if needed).
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005511 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005512static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005513QCBOR_Private_ExponentiateNN(const int64_t nMantissa,
5514 const int64_t nExponent,
5515 int64_t *pnResult,
5516 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005517{
5518 uint64_t uResult;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005519 uint64_t uMantissa;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005520
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005521 /* Take the absolute value and put it into an unsigned. */
5522 if(nMantissa >= 0) {
5523 /* Positive case is straightforward */
5524 uMantissa = (uint64_t)nMantissa;
5525 } else if(nMantissa != INT64_MIN) {
5526 /* The common negative case. See next. */
5527 uMantissa = (uint64_t)-nMantissa;
5528 } else {
5529 /* int64_t and uint64_t are always two's complement per the
5530 * C standard (and since QCBOR uses these it only works with
5531 * two's complement, which is pretty much universal these
5532 * days). The range of a negative two's complement integer is
5533 * one more that than a positive, so the simple code above might
5534 * not work all the time because you can't simply negate the
5535 * value INT64_MIN because it can't be represented in an
5536 * int64_t. -INT64_MIN can however be represented in a
5537 * uint64_t. Some compilers seem to recognize this case for the
5538 * above code and put the correct value in uMantissa, however
5539 * they are not required to do this by the C standard. This next
5540 * line does however work for all compilers.
5541 *
5542 * This does assume two's complement where -INT64_MIN ==
5543 * INT64_MAX + 1 (which wouldn't be true for one's complement or
5544 * sign and magnitude (but we know we're using two's complement
5545 * because int64_t requires it)).
5546 *
5547 * See these, particularly the detailed commentary:
5548 * https://stackoverflow.com/questions/54915742/does-c99-mandate-a-int64-t-type-be-available-always
5549 * https://stackoverflow.com/questions/37301078/is-negating-int-min-undefined-behaviour
5550 */
5551 uMantissa = (uint64_t)INT64_MAX+1;
5552 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005553
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005554 /* Call the exponentiator passed for either base 2 or base 10.
5555 * Here is where most of the overflow errors are caught. */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005556 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
5557 if(uReturn) {
5558 return uReturn;
5559 }
5560
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005561 /* Convert back to the sign of the original mantissa */
5562 if(nMantissa >= 0) {
5563 if(uResult > INT64_MAX) {
5564 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5565 }
5566 *pnResult = (int64_t)uResult;
5567 } else {
5568 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
5569 * of INT64_MIN. This assumes two's compliment representation
5570 * where INT64_MIN is one increment farther from 0 than
5571 * INT64_MAX. Trying to write -INT64_MIN doesn't work to get
5572 * this because the compiler makes it an int64_t which can't
5573 * represent -INT64_MIN. Also see above.
5574 */
5575 if(uResult > (uint64_t)INT64_MAX+1) {
5576 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5577 }
5578 *pnResult = -(int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005579 }
5580
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005581 return QCBOR_SUCCESS;
5582}
5583
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005584
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005585/**
5586 * @brief Exponentiate an unsigned mantissa and signed exponent to produce an unsigned result.
5587 *
5588 * @param[in] nMantissa Signed integer mantissa.
5589 * @param[in] nExponent Signed integer exponent.
5590 * @param[out] puResult Place to put the signed integer result.
5591 * @param[in] pfExp Exponentiation function.
5592 *
5593 * @returns Error code
5594 *
Laurence Lundblade88ba5662024-11-03 02:10:24 -08005595 * @c pfExp performs exponentiation on and unsigned mantissa and
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005596 * produces an unsigned result. This errors out if the mantissa
5597 * is negative because the output is unsigned.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005598 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005599static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005600QCBOR_Private_ExponentitateNU(const int64_t nMantissa,
5601 const int64_t nExponent,
5602 uint64_t *puResult,
5603 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005604{
5605 if(nMantissa < 0) {
5606 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5607 }
5608
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005609 /* Cast to unsigned is OK because of check for negative.
5610 * Cast to unsigned is OK because UINT64_MAX > INT64_MAX.
5611 * Exponentiation is straight forward
5612 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005613 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
5614}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005615
5616
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005617/**
5618 * @brief Exponentiate an usnigned mantissa and unsigned exponent to produce an unsigned result.
5619 *
5620 * @param[in] uMantissa Unsigned integer mantissa.
5621 * @param[in] nExponent Unsigned integer exponent.
5622 * @param[out] puResult Place to put the unsigned integer result.
5623 * @param[in] pfExp Exponentiation function.
5624 *
5625 * @returns Error code
5626 *
Laurence Lundblade88ba5662024-11-03 02:10:24 -08005627 * @c pfExp performs exponentiation on and unsigned mantissa and
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005628 * produces an unsigned result so this is just a wrapper that does
5629 * nothing (and is likely inlined).
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005630 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005631static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005632QCBOR_Private_ExponentitateUU(const uint64_t uMantissa,
5633 const int64_t nExponent,
5634 uint64_t *puResult,
5635 fExponentiator pfExp)
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005636{
5637 return (*pfExp)(uMantissa, nExponent, puResult);
5638}
5639
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005640#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005641
5642
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005643
5644
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005645/**
5646 * @brief Convert a CBOR big number to a uint64_t.
5647 *
5648 * @param[in] BigNum Bytes of the big number to convert.
5649 * @param[in] uMax Maximum value allowed for the result.
5650 * @param[out] pResult Place to put the unsigned integer result.
5651 *
5652 * @returns Error code
5653 *
5654 * Many values will overflow because a big num can represent a much
5655 * larger range than uint64_t.
5656 */
5657static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005658QCBOR_Private_ConvertBigNumToUnsigned(const UsefulBufC BigNum,
5659 const uint64_t uMax,
5660 uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005661{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005662 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005663
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005664 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005665 const uint8_t *pByte = BigNum.ptr;
5666 size_t uLen = BigNum.len;
5667 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07005668 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07005669 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005670 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07005671 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005672 }
5673
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005674 *pResult = uResult;
5675 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005676}
5677
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005678
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005679/**
5680 * @brief Convert a CBOR postive big number to a uint64_t.
5681 *
5682 * @param[in] BigNum Bytes of the big number to convert.
5683 * @param[out] pResult Place to put the unsigned integer result.
5684 *
5685 * @returns Error code
5686 *
5687 * Many values will overflow because a big num can represent a much
5688 * larger range than uint64_t.
5689 */
5690static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005691QCBOR_Private_ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum,
5692 uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005693{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005694 return QCBOR_Private_ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005695}
5696
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005697
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005698/**
5699 * @brief Convert a CBOR positive big number to an int64_t.
5700 *
5701 * @param[in] BigNum Bytes of the big number to convert.
5702 * @param[out] pResult Place to put the signed integer result.
5703 *
5704 * @returns Error code
5705 *
5706 * Many values will overflow because a big num can represent a much
5707 * larger range than int64_t.
5708 */
5709static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005710QCBOR_Private_ConvertPositiveBigNumToSigned(const UsefulBufC BigNum,
5711 int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005712{
5713 uint64_t uResult;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005714 QCBORError uError = QCBOR_Private_ConvertBigNumToUnsigned(BigNum,
5715 INT64_MAX,
5716 &uResult);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005717 if(uError) {
5718 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005719 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005720 /* Cast is safe because ConvertBigNumToUnsigned limits to INT64_MAX */
Laurence Lundbladee6430642020-03-14 21:15:44 -07005721 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005722 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005723}
5724
5725
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005726/**
5727 * @brief Convert a CBOR negative big number to an int64_t.
5728 *
5729 * @param[in] BigNum Bytes of the big number to convert.
5730 * @param[out] pnResult Place to put the signed integer result.
5731 *
5732 * @returns Error code
5733 *
5734 * Many values will overflow because a big num can represent a much
5735 * larger range than int64_t.
5736 */
5737static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005738QCBOR_Private_ConvertNegativeBigNumToSigned(const UsefulBufC BigNum,
5739 int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005740{
5741 uint64_t uResult;
Laurence Lundblade68769332024-11-03 13:09:20 -08005742 QCBORError uError;
5743
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005744 /* The negative integer furthest from zero for a C int64_t is
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005745 * INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
5746 * negative number in CBOR is computed as -n - 1 where n is the
5747 * encoded integer, where n is what is in the variable BigNum. When
5748 * converting BigNum to a uint64_t, the maximum value is thus
5749 * INT64_MAX, so that when it -n - 1 is applied to it the result
5750 * will never be further from 0 than INT64_MIN.
5751 *
5752 * -n - 1 <= INT64_MIN.
5753 * -n - 1 <= -INT64_MAX - 1
5754 * n <= INT64_MAX.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005755 */
Laurence Lundblade68769332024-11-03 13:09:20 -08005756 uError = QCBOR_Private_ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005757 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005758 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005759 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005760
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005761 /* Now apply -n - 1. The cast is safe because
5762 * ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
5763 * is the largest positive integer that an int64_t can
5764 * represent. */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005765 *pnResult = -(int64_t)uResult - 1;
5766
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005767 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005768}
5769
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005770
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005771
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005772
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005773/**
5774 * @brief Convert integers and floats to an int64_t.
5775 *
5776 * @param[in] pItem The item to convert.
5777 * @param[in] uConvertTypes Bit mask list of conversion options.
5778 * @param[out] pnValue The resulting converted value.
5779 *
5780 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
5781 * in uConvertTypes.
5782 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
5783 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
5784 * or too small.
5785 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07005786static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005787QCBOR_Private_ConvertInt64(const QCBORItem *pItem,
5788 const uint32_t uConvertTypes,
5789 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005790{
5791 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005792 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005793 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005794#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005795 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005796 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
5797 http://www.cplusplus.com/reference/cmath/llround/
5798 */
5799 // Not interested in FE_INEXACT
5800 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005801 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
5802 *pnValue = llround(pItem->val.dfnum);
5803 } else {
5804 *pnValue = lroundf(pItem->val.fnum);
5805 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005806 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
5807 // llround() shouldn't result in divide by zero, but catch
5808 // it here in case it unexpectedly does. Don't try to
5809 // distinguish between the various exceptions because it seems
5810 // they vary by CPU, compiler and OS.
5811 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005812 }
5813 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005814 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005815 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005816#else
5817 return QCBOR_ERR_HW_FLOAT_DISABLED;
5818#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005819 break;
5820
5821 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005822 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005823 *pnValue = pItem->val.int64;
5824 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005825 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005826 }
5827 break;
5828
5829 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005830 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005831 if(pItem->val.uint64 < INT64_MAX) {
5832 *pnValue = pItem->val.int64;
5833 } else {
5834 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5835 }
5836 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005837 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005838 }
5839 break;
5840
Laurence Lundblade2d493002024-02-01 11:09:17 -07005841 case QCBOR_TYPE_65BIT_NEG_INT:
5842 /* This type occurs if the value won't fit into int64_t
5843 * so this is always an error. */
5844 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5845 break;
5846
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005847 default:
5848 return QCBOR_ERR_UNEXPECTED_TYPE;
5849 }
5850 return QCBOR_SUCCESS;
5851}
5852
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005853
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005854/**
5855 * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
5856 *
5857 * @param[in] pMe The decode context.
5858 * @param[in] uConvertTypes Bit mask list of conversion options.
5859 * @param[out] pnValue Result of the conversion.
5860 * @param[in,out] pItem Temporary space to store Item, returned item.
5861 *
5862 * See QCBORDecode_GetInt64Convert().
5863 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005864void
5865QCBORDecode_Private_GetInt64Convert(QCBORDecodeContext *pMe,
5866 uint32_t uConvertTypes,
5867 int64_t *pnValue,
5868 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005869{
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07005870 QCBORDecode_VGetNext(pMe, pItem);
5871 if(pMe->uLastError) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07005872 return;
5873 }
5874
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005875 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005876 uConvertTypes,
5877 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005878}
5879
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005880/**
5881 * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
5882 *
5883 * @param[in] pMe The decode context.
5884 * @param[in] nLabel Label to find in map.
5885 * @param[in] uConvertTypes Bit mask list of conversion options.
5886 * @param[out] pnValue Result of the conversion.
5887 * @param[in,out] pItem Temporary space to store Item, returned item.
5888 *
5889 * See QCBORDecode_GetInt64ConvertInMapN().
5890 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005891void
5892QCBORDecode_Private_GetInt64ConvertInMapN(QCBORDecodeContext *pMe,
5893 int64_t nLabel,
5894 uint32_t uConvertTypes,
5895 int64_t *pnValue,
5896 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005897{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005898 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005899 if(pMe->uLastError != QCBOR_SUCCESS) {
5900 return;
5901 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005902
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005903 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
5904 uConvertTypes,
5905 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005906}
5907
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005908/**
5909 * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
5910 *
5911 * @param[in] pMe The decode context.
5912 * @param[in] szLabel Label to find in map.
5913 * @param[in] uConvertTypes Bit mask list of conversion options.
5914 * @param[out] pnValue Result of the conversion.
5915 * @param[in,out] pItem Temporary space to store Item, returned item.
5916 *
5917 * See QCBORDecode_GetInt64ConvertInMapSZ().
5918 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005919void
5920QCBORDecode_Private_GetInt64ConvertInMapSZ(QCBORDecodeContext *pMe,
5921 const char * szLabel,
5922 uint32_t uConvertTypes,
5923 int64_t *pnValue,
5924 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005925{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005926 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005927 if(pMe->uLastError != QCBOR_SUCCESS) {
5928 return;
5929 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005930
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005931 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
5932 uConvertTypes,
5933 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005934}
5935
5936
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005937/**
5938 * @brief Convert many number types to an int64_t.
5939 *
5940 * @param[in] pItem The item to convert.
5941 * @param[in] uConvertTypes Bit mask list of conversion options.
5942 * @param[out] pnValue The resulting converted value.
5943 *
5944 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
5945 * in uConvertTypes.
5946 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
5947 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
5948 * or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005949 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07005950static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005951QCBOR_Private_Int64ConvertAll(const QCBORItem *pItem,
5952 const uint32_t uConvertTypes,
5953 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005954{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005955 switch(pItem->uDataType) {
5956
5957 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005958 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005959 return QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005960 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005961 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005962 }
5963 break;
5964
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005965 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005966 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005967 return QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005968 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005969 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005970 }
5971 break;
5972
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005973#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005974 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005975 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005976 return QCBOR_Private_ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005977 pItem->val.expAndMantissa.nExponent,
5978 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005979 &QCBOR_Private_Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005980 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005981 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005982 }
5983 break;
5984
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005985 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005986 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005987 return QCBOR_Private_ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005988 pItem->val.expAndMantissa.nExponent,
5989 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005990 QCBOR_Private_Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005991 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005992 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005993 }
5994 break;
5995
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005996 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005997 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005998 int64_t nMantissa;
5999 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006000 uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07006001 if(uErr) {
6002 return uErr;
6003 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006004 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07006005 pItem->val.expAndMantissa.nExponent,
6006 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006007 QCBOR_Private_Exponentitate10);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07006008 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006009 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07006010 }
6011 break;
6012
6013 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006014 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006015 int64_t nMantissa;
6016 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006017 uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07006018 if(uErr) {
6019 return uErr;
6020 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006021 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07006022 pItem->val.expAndMantissa.nExponent,
6023 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006024 QCBOR_Private_Exponentitate10);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07006025 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006026 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07006027 }
6028 break;
6029
6030 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006031 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006032 int64_t nMantissa;
6033 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006034 uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07006035 if(uErr) {
6036 return uErr;
6037 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006038 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07006039 pItem->val.expAndMantissa.nExponent,
6040 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006041 QCBOR_Private_Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07006042 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006043 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07006044 }
6045 break;
6046
6047 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006048 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006049 int64_t nMantissa;
6050 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006051 uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07006052 if(uErr) {
6053 return uErr;
6054 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006055 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07006056 pItem->val.expAndMantissa.nExponent,
6057 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006058 QCBOR_Private_Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07006059 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006060 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07006061 }
6062 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006063#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006064
Laurence Lundbladee6430642020-03-14 21:15:44 -07006065
Laurence Lundbladec4537442020-04-14 18:53:22 -07006066 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006067 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07006068}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006069
6070
Laurence Lundbladec4537442020-04-14 18:53:22 -07006071/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006072 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07006073 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006074void
6075QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe,
6076 const uint32_t uConvertTypes,
6077 int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07006078{
6079 QCBORItem Item;
6080
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006081 QCBORDecode_Private_GetInt64Convert(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07006082
Laurence Lundblade9c905e82020-04-25 11:31:38 -07006083 if(pMe->uLastError == QCBOR_SUCCESS) {
6084 // The above conversion succeeded
6085 return;
6086 }
6087
Laurence Lundbladef6c86662020-05-12 02:08:00 -07006088 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07006089 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07006090 return;
6091 }
6092
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006093 pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
6094 uConvertTypes,
6095 pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07006096}
6097
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006098
6099/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006100 * Public function, see header qcbor/qcbor_decode.h file
6101 */
6102void
6103QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
6104 const int64_t nLabel,
6105 const uint32_t uConvertTypes,
6106 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07006107{
6108 QCBORItem Item;
6109
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006110 QCBORDecode_Private_GetInt64ConvertInMapN(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07006111 nLabel,
6112 uConvertTypes,
6113 pnValue,
6114 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07006115
6116 if(pMe->uLastError == QCBOR_SUCCESS) {
6117 // The above conversion succeeded
6118 return;
6119 }
6120
6121 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6122 // The above conversion failed in a way that code below can't correct
6123 return;
6124 }
6125
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006126 pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
6127 uConvertTypes,
6128 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07006129}
6130
6131
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006132/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006133 * Public function, see header qcbor/qcbor_decode.h file
6134 */
6135void
6136QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
6137 const char *szLabel,
6138 const uint32_t uConvertTypes,
6139 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07006140{
6141 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006142 QCBORDecode_Private_GetInt64ConvertInMapSZ(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07006143 szLabel,
6144 uConvertTypes,
6145 pnValue,
6146 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07006147
6148 if(pMe->uLastError == QCBOR_SUCCESS) {
6149 // The above conversion succeeded
6150 return;
6151 }
6152
6153 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6154 // The above conversion failed in a way that code below can't correct
6155 return;
6156 }
6157
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006158 pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
6159 uConvertTypes,
6160 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07006161}
6162
6163
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006164/**
6165 * @brief Convert many number types to an uint64_t.
6166 *
6167 * @param[in] pItem The item to convert.
6168 * @param[in] uConvertTypes Bit mask list of conversion options.
6169 * @param[out] puValue The resulting converted value.
6170 *
6171 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
6172 * in uConvertTypes.
6173 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
6174 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
6175 * or too small.
6176 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006177static QCBORError
6178QCBOR_Private_ConvertUInt64(const QCBORItem *pItem,
6179 const uint32_t uConvertTypes,
6180 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006181{
6182 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006183 case QCBOR_TYPE_DOUBLE:
6184 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006185#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006186 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07006187 // Can't use llround here because it will not convert values
6188 // greater than INT64_MAX and less than UINT64_MAX that
6189 // need to be converted so it is more complicated.
6190 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
6191 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
6192 if(isnan(pItem->val.dfnum)) {
6193 return QCBOR_ERR_FLOAT_EXCEPTION;
6194 } else if(pItem->val.dfnum < 0) {
6195 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
6196 } else {
6197 double dRounded = round(pItem->val.dfnum);
6198 // See discussion in DecodeDateEpoch() for
6199 // explanation of - 0x7ff
6200 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
6201 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
6202 }
6203 *puValue = (uint64_t)dRounded;
6204 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006205 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07006206 if(isnan(pItem->val.fnum)) {
6207 return QCBOR_ERR_FLOAT_EXCEPTION;
6208 } else if(pItem->val.fnum < 0) {
6209 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
6210 } else {
6211 float fRounded = roundf(pItem->val.fnum);
6212 // See discussion in DecodeDateEpoch() for
6213 // explanation of - 0x7ff
6214 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
6215 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
6216 }
6217 *puValue = (uint64_t)fRounded;
6218 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006219 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07006220 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
6221 // round() and roundf() shouldn't result in exceptions here, but
6222 // catch them to be robust and thorough. Don't try to
6223 // distinguish between the various exceptions because it seems
6224 // they vary by CPU, compiler and OS.
6225 return QCBOR_ERR_FLOAT_EXCEPTION;
6226 }
6227
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006228 } else {
6229 return QCBOR_ERR_UNEXPECTED_TYPE;
6230 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006231#else
6232 return QCBOR_ERR_HW_FLOAT_DISABLED;
6233#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006234 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07006235
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006236 case QCBOR_TYPE_INT64:
6237 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
6238 if(pItem->val.int64 >= 0) {
6239 *puValue = (uint64_t)pItem->val.int64;
6240 } else {
6241 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
6242 }
6243 } else {
6244 return QCBOR_ERR_UNEXPECTED_TYPE;
6245 }
6246 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006247
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006248 case QCBOR_TYPE_UINT64:
6249 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade2d493002024-02-01 11:09:17 -07006250 *puValue = pItem->val.uint64;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006251 } else {
6252 return QCBOR_ERR_UNEXPECTED_TYPE;
6253 }
6254 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006255
Laurence Lundblade2d493002024-02-01 11:09:17 -07006256 case QCBOR_TYPE_65BIT_NEG_INT:
6257 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
6258
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006259 default:
6260 return QCBOR_ERR_UNEXPECTED_TYPE;
6261 }
6262
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006263 return QCBOR_SUCCESS;
6264}
Laurence Lundbladec4537442020-04-14 18:53:22 -07006265
6266
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006267/**
6268 * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
6269 *
6270 * @param[in] pMe The decode context.
6271 * @param[in] uConvertTypes Bit mask list of conversion options.
6272 * @param[out] puValue Result of the conversion.
6273 * @param[in,out] pItem Temporary space to store Item, returned item.
6274 *
6275 * See QCBORDecode_GetUInt64Convert().
6276 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006277void
6278QCBORDecode_Private_GetUInt64Convert(QCBORDecodeContext *pMe,
6279 const uint32_t uConvertTypes,
6280 uint64_t *puValue,
6281 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07006282{
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07006283 QCBORDecode_VGetNext(pMe, pItem);
6284 if(pMe->uLastError) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07006285 return;
6286 }
6287
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07006288 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006289 uConvertTypes,
6290 puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07006291}
6292
Laurence Lundblade9c905e82020-04-25 11:31:38 -07006293
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006294/**
6295 * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
6296 *
6297 * @param[in] pMe The decode context.
6298 * @param[in] nLabel Label to find in map.
6299 * @param[in] uConvertTypes Bit mask list of conversion options.
6300 * @param[out] puValue Result of the conversion.
6301 * @param[in,out] pItem Temporary space to store Item, returned item.
6302 *
6303 * See QCBORDecode_GetUInt64ConvertInMapN().
6304 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006305void
6306QCBORDecode_Private_GetUInt64ConvertInMapN(QCBORDecodeContext *pMe,
6307 const int64_t nLabel,
6308 const uint32_t uConvertTypes,
6309 uint64_t *puValue,
6310 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006311{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006312 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07006313 if(pMe->uLastError != QCBOR_SUCCESS) {
6314 return;
6315 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006316
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006317 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
6318 uConvertTypes,
6319 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006320}
6321
6322
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006323/**
6324 * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
6325 *
6326 * @param[in] pMe The decode context.
6327 * @param[in] szLabel Label to find in map.
6328 * @param[in] uConvertTypes Bit mask list of conversion options.
6329 * @param[out] puValue Result of the conversion.
6330 * @param[in,out] pItem Temporary space to store Item, returned item.
6331 *
6332 * See QCBORDecode_GetUInt64ConvertInMapSZ().
6333 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006334void
6335QCBORDecode_Private_GetUInt64ConvertInMapSZ(QCBORDecodeContext *pMe,
6336 const char *szLabel,
6337 const uint32_t uConvertTypes,
6338 uint64_t *puValue,
6339 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006340{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006341 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07006342 if(pMe->uLastError != QCBOR_SUCCESS) {
6343 return;
6344 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006345
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006346 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
6347 uConvertTypes,
6348 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006349}
6350
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006351
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006352/**
6353 * @brief Convert many number types to an unt64_t.
6354 *
6355 * @param[in] pItem The item to convert.
6356 * @param[in] uConvertTypes Bit mask list of conversion options.
6357 * @param[out] puValue The resulting converted value.
6358 *
6359 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
6360 * in uConvertTypes.
6361 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
6362 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
6363 * or too small.
6364 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07006365static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006366QCBOR_Private_UInt64ConvertAll(const QCBORItem *pItem,
6367 const uint32_t uConvertTypes,
6368 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006369{
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08006370 switch(pItem->uDataType) { /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006371
6372 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006373 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006374 return QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006375 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006376 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006377 }
6378 break;
6379
6380 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006381 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006382 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
6383 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006384 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006385 }
6386 break;
6387
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006388#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006389
6390 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006391 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006392 return QCBOR_Private_ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006393 pItem->val.expAndMantissa.nExponent,
6394 puValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006395 QCBOR_Private_Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006396 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006397 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006398 }
6399 break;
6400
6401 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006402 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006403 return QCBOR_Private_ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006404 pItem->val.expAndMantissa.nExponent,
6405 puValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006406 QCBOR_Private_Exponentitate2);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006407 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006408 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006409 }
6410 break;
6411
6412 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006413 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006414 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006415 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006416 uErr = QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006417 if(uErr != QCBOR_SUCCESS) {
6418 return uErr;
6419 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006420 return QCBOR_Private_ExponentitateUU(uMantissa,
6421 pItem->val.expAndMantissa.nExponent,
6422 puValue,
6423 QCBOR_Private_Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006424 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006425 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006426 }
6427 break;
6428
6429 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006430 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006431 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
6432 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006433 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006434 }
6435 break;
6436
6437 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006438 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006439 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006440 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006441 uErr = QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum,
6442 &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006443 if(uErr != QCBOR_SUCCESS) {
6444 return uErr;
6445 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006446 return QCBOR_Private_ExponentitateUU(uMantissa,
6447 pItem->val.expAndMantissa.nExponent,
6448 puValue,
6449 QCBOR_Private_Exponentitate2);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006450 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006451 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006452 }
6453 break;
6454
6455 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006456 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006457 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
6458 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006459 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006460 }
6461 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006462#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006463 default:
6464 return QCBOR_ERR_UNEXPECTED_TYPE;
6465 }
6466}
6467
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006468
Laurence Lundblade4e2da002020-06-13 23:08:31 -07006469/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006470 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07006471 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006472void
6473QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe,
6474 const uint32_t uConvertTypes,
6475 uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07006476{
6477 QCBORItem Item;
6478
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006479 QCBORDecode_Private_GetUInt64Convert(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07006480
Laurence Lundbladef6c86662020-05-12 02:08:00 -07006481 if(pMe->uLastError == QCBOR_SUCCESS) {
6482 // The above conversion succeeded
6483 return;
6484 }
6485
6486 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6487 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07006488 return;
6489 }
6490
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006491 pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
6492 uConvertTypes,
6493 puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07006494}
6495
Laurence Lundbladec4537442020-04-14 18:53:22 -07006496
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006497/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006498 * Public function, see header qcbor/qcbor_decode.h file
6499 */
6500void
6501QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
6502 const int64_t nLabel,
6503 const uint32_t uConvertTypes,
6504 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006505{
6506 QCBORItem Item;
6507
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006508 QCBORDecode_Private_GetUInt64ConvertInMapN(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07006509 nLabel,
6510 uConvertTypes,
6511 puValue,
6512 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006513
6514 if(pMe->uLastError == QCBOR_SUCCESS) {
6515 // The above conversion succeeded
6516 return;
6517 }
6518
6519 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6520 // The above conversion failed in a way that code below can't correct
6521 return;
6522 }
6523
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006524 pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
6525 uConvertTypes,
6526 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006527}
6528
6529
6530/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006531 * Public function, see header qcbor/qcbor_decode.h file
6532 */
6533void
6534QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
6535 const char *szLabel,
6536 const uint32_t uConvertTypes,
6537 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006538{
6539 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006540 QCBORDecode_Private_GetUInt64ConvertInMapSZ(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07006541 szLabel,
6542 uConvertTypes,
6543 puValue,
6544 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006545
6546 if(pMe->uLastError == QCBOR_SUCCESS) {
6547 // The above conversion succeeded
6548 return;
6549 }
6550
6551 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6552 // The above conversion failed in a way that code below can't correct
6553 return;
6554 }
6555
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006556 pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
6557 uConvertTypes,
6558 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006559}
6560
6561
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07006562
6563
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02006564#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006565/**
6566 * @brief Basic conversions to a double.
6567 *
6568 * @param[in] pItem The item to convert
6569 * @param[in] uConvertTypes Bit flags indicating source types for conversion
6570 * @param[out] pdValue The value converted to a double
6571 *
6572 * This does the conversions that don't need much object code,
6573 * the conversions from int, uint and float to double.
6574 *
6575 * See QCBOR_Private_DoubleConvertAll() for the full set
6576 * of conversions.
6577 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006578static QCBORError
6579QCBOR_Private_ConvertDouble(const QCBORItem *pItem,
6580 const uint32_t uConvertTypes,
6581 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006582{
6583 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006584 case QCBOR_TYPE_FLOAT:
6585#ifndef QCBOR_DISABLE_FLOAT_HW_USE
6586 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
6587 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07006588 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006589 *pdValue = (double)pItem->val.fnum;
6590 } else {
6591 return QCBOR_ERR_UNEXPECTED_TYPE;
6592 }
6593 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08006594#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006595 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08006596#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006597 break;
6598
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006599 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006600 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
6601 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006602 *pdValue = pItem->val.dfnum;
6603 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006604 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006605 }
6606 }
6607 break;
6608
6609 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006610#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006611 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07006612 // A simple cast seems to do the job with no worry of exceptions.
6613 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006614 *pdValue = (double)pItem->val.int64;
6615
6616 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006617 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006618 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006619#else
6620 return QCBOR_ERR_HW_FLOAT_DISABLED;
6621#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006622 break;
6623
6624 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006625#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006626 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07006627 // A simple cast seems to do the job with no worry of exceptions.
6628 // There will be precision loss for some values.
6629 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006630 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006631 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006632 }
6633 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006634#else
6635 return QCBOR_ERR_HW_FLOAT_DISABLED;
6636#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006637
Laurence Lundblade2d493002024-02-01 11:09:17 -07006638 case QCBOR_TYPE_65BIT_NEG_INT:
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -08006639#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade14ce2282024-07-24 22:13:35 -07006640 // TODO: don't use float HW. We have the function to do it.
Laurence Lundblade2d493002024-02-01 11:09:17 -07006641 *pdValue = -(double)pItem->val.uint64 - 1;
6642 break;
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -08006643#else
6644 return QCBOR_ERR_HW_FLOAT_DISABLED;
6645#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade2d493002024-02-01 11:09:17 -07006646
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006647 default:
6648 return QCBOR_ERR_UNEXPECTED_TYPE;
6649 }
6650
6651 return QCBOR_SUCCESS;
6652}
6653
6654
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006655/**
6656 * @brief Almost-public method to decode a number and convert to double (semi-private).
6657 *
6658 * @param[in] pMe The decode context.
6659 * @param[in] uConvertTypes Bit mask list of conversion options
6660 * @param[out] pdValue The output of the conversion.
6661 * @param[in,out] pItem Temporary space to store Item, returned item.
6662 *
6663 * See QCBORDecode_GetDoubleConvert().
6664 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006665void
6666QCBORDecode_Private_GetDoubleConvert(QCBORDecodeContext *pMe,
6667 const uint32_t uConvertTypes,
6668 double *pdValue,
6669 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07006670{
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07006671 QCBORDecode_VGetNext(pMe, pItem);
6672 if(pMe->uLastError) {
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006673 return;
6674 }
6675
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006676 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006677 uConvertTypes,
6678 pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006679}
Laurence Lundbladec4537442020-04-14 18:53:22 -07006680
Laurence Lundbladec4537442020-04-14 18:53:22 -07006681
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006682/**
6683 * @brief Almost-public method to decode a number and convert to double (semi-private).
6684 *
6685 * @param[in] pMe The decode context.
6686 * @param[in] nLabel Label to find in map.
6687 * @param[in] uConvertTypes Bit mask list of conversion options
6688 * @param[out] pdValue The output of the conversion.
6689 * @param[in,out] pItem Temporary space to store Item, returned item.
6690 *
6691 * See QCBORDecode_GetDoubleConvertInMapN().
6692 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006693void
6694QCBORDecode_Private_GetDoubleConvertInMapN(QCBORDecodeContext *pMe,
6695 const int64_t nLabel,
6696 const uint32_t uConvertTypes,
6697 double *pdValue,
6698 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006699{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006700 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07006701 if(pMe->uLastError != QCBOR_SUCCESS) {
6702 return;
6703 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006704
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006705 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
6706 uConvertTypes,
6707 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006708}
6709
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006710
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006711/**
6712 * @brief Almost-public method to decode a number and convert to double (semi-private).
6713 *
6714 * @param[in] pMe The decode context.
6715 * @param[in] szLabel Label to find in map.
6716 * @param[in] uConvertTypes Bit mask list of conversion options
6717 * @param[out] pdValue The output of the conversion.
6718 * @param[in,out] pItem Temporary space to store Item, returned item.
6719 *
6720 * See QCBORDecode_GetDoubleConvertInMapSZ().
6721 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006722void
6723QCBORDecode_Private_GetDoubleConvertInMapSZ(QCBORDecodeContext *pMe,
6724 const char *szLabel,
6725 const uint32_t uConvertTypes,
6726 double *pdValue,
6727 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006728{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006729 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07006730 if(pMe->uLastError != QCBOR_SUCCESS) {
6731 return;
6732 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006733
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006734 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
6735 uConvertTypes,
6736 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006737}
6738
6739
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006740#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006741/**
6742 * @brief Convert a big number to double-precision float.
6743 *
6744 * @param[in] BigNum The big number to convert
6745 *
6746 * @returns The double value.
6747 *
6748 * This will always succeed. It will lose precision for larger
6749 * numbers. If the big number is too large to fit (more than
6750 * 1.7976931348623157E+308) infinity will be returned. NaN is never
6751 * returned.
6752 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006753static double
6754QCBOR_Private_ConvertBigNumToDouble(const UsefulBufC BigNum)
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07006755{
6756 double dResult;
6757
6758 dResult = 0.0;
6759 const uint8_t *pByte = BigNum.ptr;
6760 size_t uLen = BigNum.len;
6761 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006762 * is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07006763 while(uLen--) {
6764 dResult = (dResult * 256.0) + (double)*pByte++;
6765 }
6766
6767 return dResult;
6768}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006769#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
6770
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07006771
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006772
6773
6774/**
6775 * @brief Convert many number types to a double.
6776 *
6777 * @param[in] pItem The item to convert.
6778 * @param[in] uConvertTypes Bit mask list of conversion options.
6779 * @param[out] pdValue The resulting converted value.
6780 *
6781 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
6782 * in uConvertTypes.
6783 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
6784 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
6785 * or too small.
6786 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07006787static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006788QCBOR_Private_DoubleConvertAll(const QCBORItem *pItem,
6789 const uint32_t uConvertTypes,
6790 double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006791{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006792#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07006793 /*
Laurence Lundblade16a207a2021-09-18 17:22:46 -07006794 * What Every Computer Scientist Should Know About Floating-Point Arithmetic
6795 * https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
6796 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006797 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07006798
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006799#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006800 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006801 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07006802 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006803 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
6804 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
6805 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006806 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006807 }
6808 break;
6809
6810 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006811 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07006812 // Underflow gives 0, overflow gives infinity
6813 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
6814 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006815 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006816 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006817 }
6818 break;
Laurence Lundblade20fba4f2024-10-30 07:52:33 -07006819#endif /* ! QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006820
6821 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006822 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006823 *pdValue = QCBOR_Private_ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006824 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006825 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006826 }
6827 break;
6828
6829 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006830 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006831 *pdValue = -1-QCBOR_Private_ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006832 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006833 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006834 }
6835 break;
6836
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006837#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006838 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006839 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006840 double dMantissa = QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006841 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
6842 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006843 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006844 }
6845 break;
6846
6847 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade20fba4f2024-10-30 07:52:33 -07006848 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
6849 /* Must subtract 1 for CBOR negative integer offset */
6850 double dMantissa = -1-QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
6851 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006852 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006853 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006854 }
6855 break;
6856
6857 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade20fba4f2024-10-30 07:52:33 -07006858 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
6859 double dMantissa = QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
6860 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006861 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006862 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006863 }
6864 break;
6865
6866 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade20fba4f2024-10-30 07:52:33 -07006867 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
6868 double dMantissa = -1-QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
6869 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006870 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006871 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006872 }
6873 break;
Laurence Lundblade20fba4f2024-10-30 07:52:33 -07006874#endif /* ! QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade410c7e02020-06-25 23:35:29 -07006875
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006876 default:
6877 return QCBOR_ERR_UNEXPECTED_TYPE;
6878 }
6879
6880 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006881
6882#else
6883 (void)pItem;
6884 (void)uConvertTypes;
6885 (void)pdValue;
6886 return QCBOR_ERR_HW_FLOAT_DISABLED;
6887#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
6888
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006889}
6890
6891
6892/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006893 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006894 */
6895void
6896QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
6897 const uint32_t uConvertTypes,
6898 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006899{
6900
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006901 QCBORItem Item;
6902
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006903 QCBORDecode_Private_GetDoubleConvert(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006904
6905 if(pMe->uLastError == QCBOR_SUCCESS) {
6906 // The above conversion succeeded
6907 return;
6908 }
6909
6910 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6911 // The above conversion failed in a way that code below can't correct
6912 return;
6913 }
6914
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006915 pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
6916 uConvertTypes,
6917 pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07006918}
6919
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006920
6921/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006922 * Public function, see header qcbor/qcbor_decode.h file
6923 */
6924void
6925QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
6926 const int64_t nLabel,
6927 const uint32_t uConvertTypes,
6928 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006929{
6930 QCBORItem Item;
6931
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006932 QCBORDecode_Private_GetDoubleConvertInMapN(pMe,
6933 nLabel,
6934 uConvertTypes,
6935 pdValue,
6936 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006937
6938 if(pMe->uLastError == QCBOR_SUCCESS) {
6939 // The above conversion succeeded
6940 return;
6941 }
6942
6943 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6944 // The above conversion failed in a way that code below can't correct
6945 return;
6946 }
6947
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006948 pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
6949 uConvertTypes,
6950 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006951}
6952
6953
6954/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006955 * Public function, see header qcbor/qcbor_decode.h file
6956 */
6957void
6958QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
6959 const char *szLabel,
6960 const uint32_t uConvertTypes,
6961 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006962{
6963 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006964 QCBORDecode_Private_GetDoubleConvertInMapSZ(pMe,
6965 szLabel,
6966 uConvertTypes,
6967 pdValue,
6968 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006969
6970 if(pMe->uLastError == QCBOR_SUCCESS) {
6971 // The above conversion succeeded
6972 return;
6973 }
6974
6975 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6976 // The above conversion failed in a way that code below can't correct
6977 return;
6978 }
6979
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006980 pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
6981 uConvertTypes,
6982 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006983}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02006984#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006985
6986
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006987
6988
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006989#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006990/**
6991 * @brief Convert an integer to a big number
6992 *
6993 * @param[in] uInt The integer to convert.
6994 * @param[in] Buffer The buffer to output the big number to.
6995 *
6996 * @returns The big number or NULLUsefulBufC is the buffer is to small.
6997 *
6998 * This always succeeds unless the buffer is too small.
6999 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007000static UsefulBufC
7001QCBOR_Private_ConvertIntToBigNum(uint64_t uInt, const UsefulBuf Buffer)
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07007002{
7003 while((uInt & 0xff00000000000000UL) == 0) {
7004 uInt = uInt << 8;
7005 };
7006
7007 UsefulOutBuf UOB;
7008
7009 UsefulOutBuf_Init(&UOB, Buffer);
7010
7011 while(uInt) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07007012 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
7013 uInt = uInt << 8;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07007014 }
7015
7016 return UsefulOutBuf_OutUBuf(&UOB);
7017}
7018
Laurence Lundblade37286c02022-09-03 10:05:02 -07007019/* Some notes from the work to disable tags.
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007020 * Some are out of date since tag refactoring.
Laurence Lundblade37286c02022-09-03 10:05:02 -07007021 *
7022 * The API for big floats and decimal fractions seems good.
7023 * If there's any issue with it it's that the code size to
7024 * implement is a bit large because of the conversion
7025 * to/from int and bignum that is required. There is no API
7026 * that doesn't do the conversion so dead stripping will never
7027 * leave that code out.
7028 *
7029 * The implementation itself seems correct, but not as clean
7030 * and neat as it could be. It could probably be smaller too.
7031 *
7032 * The implementation has three main parts / functions
7033 * - The decoding of the array of two
7034 * - All the tag and type checking for the various API functions
7035 * - Conversion to/from bignum and int
7036 *
7037 * The type checking seems like it wastes the most code for
7038 * what it needs to do.
7039 *
7040 * The inlining for the conversion is probably making the
7041 * overall code base larger.
7042 *
7043 * The tests cases could be organized a lot better and be
7044 * more thorough.
7045 *
7046 * Seems also like there could be more common code in the
7047 * first tier part of the public API. Some functions only
7048 * vary by a TagSpec.
7049 */
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07007050
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007051
7052static const uint8_t QCBORDecode_Private_DecimalFractionTypes[] = {
7053 QCBOR_TYPE_DECIMAL_FRACTION,
7054 QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
7055 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM,
Laurence Lundblade68769332024-11-03 13:09:20 -08007056 QCBOR_TYPE_DECIMAL_FRACTION_POS_U64,
7057 QCBOR_TYPE_DECIMAL_FRACTION_NEG_U64,
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007058 QCBOR_TYPE_NONE};
7059
7060static const uint8_t QCBORDecode_Private_BigFloatTypes[] = {
7061 QCBOR_TYPE_BIGFLOAT,
7062 QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
7063 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM,
Laurence Lundblade68769332024-11-03 13:09:20 -08007064 QCBOR_TYPE_BIGFLOAT_POS_U64,
7065 QCBOR_TYPE_BIGFLOAT_NEG_U64,
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007066 QCBOR_TYPE_NONE};
7067
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07007068/**
Laurence Lundblade68769332024-11-03 13:09:20 -08007069 * @brief Common processor for exponent and int64_t mantissa.
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07007070 *
7071 * @param[in] pMe The decode context.
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007072 * @param[in] uTagRequirement Whether tag number must be present or not.
7073 * @param[in] uTagNumber The tag number for which content is expected.
7074 * @param[in] uOffset Cursor offset for tag number consumption checking.
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07007075 * @param[in] pItem The data item to process.
7076 * @param[out] pnMantissa The returned mantissa as an int64_t.
7077 * @param[out] pnExponent The returned exponent as an int64_t.
7078 *
7079 * This handles exponent and mantissa for base 2 and 10. This
7080 * is limited to a mantissa that is an int64_t. See also
7081 * QCBORDecode_Private_ProcessExpMantissaBig().
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007082 *
7083 * On output, the item is always a fully decoded decimal fraction or
7084 * big float.
7085 *
Laurence Lundblade68769332024-11-03 13:09:20 -08007086 * This errors out if the input tag and type aren't as required.
7087 *
7088 * This always provides the correctly offset mantissa, even when the
7089 * input CBOR is a negative big number. This works the
7090 * same in QCBOR v1 and v2.
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07007091 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007092static void
Laurence Lundblade68769332024-11-03 13:09:20 -08007093QCBORDecode_Private_ExpIntMantissaMain(QCBORDecodeContext *pMe,
7094 const uint8_t uTagRequirement,
7095 const uint64_t uTagNumber,
7096 const size_t uOffset,
7097 QCBORItem *pItem,
7098 int64_t *pnMantissa,
7099 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07007100{
Laurence Lundblade68769332024-11-03 13:09:20 -08007101 QCBORError uErr;
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007102 const uint8_t *qTypes;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007103
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07007104 if(pMe->uLastError) {
7105 return;
7106 }
7107
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007108 if(uTagNumber == CBOR_TAG_BIGFLOAT) {
7109 qTypes = QCBORDecode_Private_BigFloatTypes;
7110 } else {
7111 qTypes = QCBORDecode_Private_DecimalFractionTypes;
7112 }
7113
7114 QCBORDecode_Private_ProcessTagItem(pMe,
7115 pItem,
7116 uTagRequirement,
7117 qTypes,
7118 uTagNumber,
7119 QCBORDecode_ExpMantissaTagCB,
7120 uOffset);
7121
7122 if(pMe->uLastError != QCBOR_SUCCESS) {
7123 return;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07007124 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07007125
Laurence Lundblade68769332024-11-03 13:09:20 -08007126 uErr = QCBOR_SUCCESS;
Laurence Lundblade9b334962020-08-27 10:55:53 -07007127 switch (pItem->uDataType) {
7128
7129 case QCBOR_TYPE_DECIMAL_FRACTION:
7130 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade9b334962020-08-27 10:55:53 -07007131 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade37286c02022-09-03 10:05:02 -07007132 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
Laurence Lundblade9b334962020-08-27 10:55:53 -07007133 break;
7134
Laurence Lundblade37286c02022-09-03 10:05:02 -07007135#ifndef QCBOR_DISABLE_TAGS
7136 /* If tags are disabled, mantissas can never be big nums */
Laurence Lundblade9b334962020-08-27 10:55:53 -07007137 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
7138 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
7139 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007140 uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
Laurence Lundblade9b334962020-08-27 10:55:53 -07007141 break;
7142
7143 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
7144 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
7145 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007146 uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
Laurence Lundblade9b334962020-08-27 10:55:53 -07007147 break;
Laurence Lundblade37286c02022-09-03 10:05:02 -07007148#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade9b334962020-08-27 10:55:53 -07007149
Laurence Lundblade68769332024-11-03 13:09:20 -08007150 case QCBOR_TYPE_BIGFLOAT_NEG_U64:
7151 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_U64:
7152 case QCBOR_TYPE_BIGFLOAT_POS_U64:
7153 case QCBOR_TYPE_DECIMAL_FRACTION_POS_U64:
7154 uErr = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
7155 break;
7156
Laurence Lundblade9b334962020-08-27 10:55:53 -07007157 default:
7158 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
7159 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007160
Laurence Lundblade68769332024-11-03 13:09:20 -08007161 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07007162}
7163
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007164static void
Laurence Lundblade68769332024-11-03 13:09:20 -08007165QCBORDecode_Private_ExpBigMantissaRawMain(QCBORDecodeContext *pMe,
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007166 const uint8_t uTagRequirement,
7167 const uint64_t uTagNumber,
7168 const size_t uOffset,
7169 QCBORItem *pItem,
7170 const UsefulBuf BufferForMantissa,
7171 UsefulBufC *pMantissa,
7172 bool *pbIsNegative,
7173 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007174{
Laurence Lundblade033574f2024-11-03 17:42:35 -08007175 QCBORError uErr;
7176 uint64_t uMantissa;
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007177 const uint8_t *qTypes;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007178
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007179 if(pMe->uLastError) {
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07007180 return;
7181 }
7182
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007183 if(uTagNumber == CBOR_TAG_BIGFLOAT) {
7184 qTypes = QCBORDecode_Private_BigFloatTypes;
7185 } else {
7186 qTypes = QCBORDecode_Private_DecimalFractionTypes;
7187 }
7188
7189 QCBORDecode_Private_ProcessTagItem(pMe,
7190 pItem,
7191 uTagRequirement,
7192 qTypes,
7193 uTagNumber,
7194 QCBORDecode_ExpMantissaTagCB,
7195 uOffset);
7196
7197 if(pMe->uLastError != QCBOR_SUCCESS) {
7198 return;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007199 }
7200
Laurence Lundblade68769332024-11-03 13:09:20 -08007201 uErr = QCBOR_SUCCESS;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007202
7203 switch (pItem->uDataType) {
7204
7205 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007206 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007207 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
7208 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
7209 *pbIsNegative = false;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07007210 } else {
Laurence Lundblade68769332024-11-03 13:09:20 -08007211 if(pItem->val.expAndMantissa.Mantissa.nInt != INT64_MIN) {
7212 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
7213 } else {
7214 /* Can't negate like above when int64_t is INT64_MIN because it
7215 * will overflow. See ExponentNN() */
7216 uMantissa = (uint64_t)INT64_MAX+1;
7217 }
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07007218 *pbIsNegative = true;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007219 }
Laurence Lundblade68769332024-11-03 13:09:20 -08007220 /* Reverse the offset by 1 for type 1 negative value to be consistent
7221 * with big num case below which don't offset because it requires
7222 * big number arithmetic. This is a bug fix for QCBOR v1.5.
7223 */
7224 uMantissa--;
7225 *pMantissa = QCBOR_Private_ConvertIntToBigNum(uMantissa, BufferForMantissa);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007226 *pnExponent = pItem->val.expAndMantissa.nExponent;
7227 break;
7228
Laurence Lundblade37286c02022-09-03 10:05:02 -07007229#ifndef QCBOR_DISABLE_TAGS
7230 /* If tags are disabled, mantissas can never be big nums */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007231 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007232 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007233 *pnExponent = pItem->val.expAndMantissa.nExponent;
7234 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
7235 *pbIsNegative = false;
7236 break;
7237
7238 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007239 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007240 *pnExponent = pItem->val.expAndMantissa.nExponent;
7241 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
7242 *pbIsNegative = true;
7243 break;
Laurence Lundblade37286c02022-09-03 10:05:02 -07007244#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007245
7246 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007247 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007248 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007249
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007250 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007251}
7252
7253
Laurence Lundblade68769332024-11-03 13:09:20 -08007254/**
7255 * @brief Decode exponent and mantissa into a big number with negative offset of 1.
7256 *
7257 * @param[in] pMe The decode context.
7258 * @param[in] uTagRequirement Whether a tag number must be present or not.
7259 * @param[in] pItem Item to decode and convert.
7260 * @param[in] BufferForMantissa Buffer to output mantissa into.
7261 * @param[out] pMantissa The output mantissa.
7262 * @param[out] pbIsNegative The sign of the output.
7263 * @param[out] pnExponent The mantissa of the output.
7264 *
7265 * This is the common processing of a decimal fraction or a big float
7266 * into a big number. This will decode and consume all the CBOR items
7267 * that make up the decimal fraction or big float.
7268 *
7269 * This performs the subtraction of 1 from the negative value so the
7270 * caller doesn't need to. This links more object code than QCBORDecode_Private_ProcessExpMantissaBig().
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007271 */
Laurence Lundblade68769332024-11-03 13:09:20 -08007272static void
7273QCBORDecode_Private_ExpBigMantissaMain(QCBORDecodeContext *pMe,
7274 const uint8_t uTagRequirement,
7275 const uint64_t uTagNumber,
7276 const size_t uOffset,
7277 QCBORItem *pItem,
7278 const UsefulBuf BufferForMantissa,
7279 UsefulBufC *pMantissa,
7280 bool *pbIsNegative,
7281 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007282{
Laurence Lundblade68769332024-11-03 13:09:20 -08007283 QCBORError uErr;
7284 QCBORItem TempMantissa;
7285 const uint8_t *qTypes;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007286
Laurence Lundblade68769332024-11-03 13:09:20 -08007287 if(pMe->uLastError) {
7288 return;
7289 }
7290
7291 if(uTagNumber == CBOR_TAG_BIGFLOAT) {
7292 qTypes = QCBORDecode_Private_BigFloatTypes;
7293 } else {
7294 qTypes = QCBORDecode_Private_DecimalFractionTypes;
7295 }
7296
7297 QCBORDecode_Private_ProcessTagItem(pMe,
7298 pItem,
7299 uTagRequirement,
7300 qTypes,
7301 uTagNumber,
7302 QCBORDecode_ExpMantissaTagCB,
7303 uOffset);
7304
7305 if(pMe->uLastError != QCBOR_SUCCESS) {
7306 return;
7307 }
7308
7309 memset(&TempMantissa, 0, sizeof(TempMantissa));
7310
7311 switch (pItem->uDataType) {
7312
7313 case QCBOR_TYPE_DECIMAL_FRACTION:
7314 case QCBOR_TYPE_BIGFLOAT:
7315 TempMantissa.uDataType = QCBOR_TYPE_INT64;
7316 TempMantissa.val.int64 = pItem->val.expAndMantissa.Mantissa.nInt;
7317 break;
7318
7319 case QCBOR_TYPE_DECIMAL_FRACTION_POS_U64:
7320 case QCBOR_TYPE_BIGFLOAT_POS_U64:
7321 TempMantissa.uDataType = QCBOR_TYPE_UINT64;
7322 TempMantissa.val.uint64 = pItem->val.expAndMantissa.Mantissa.uInt;
7323 break;
7324
7325 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_U64:
7326 case QCBOR_TYPE_BIGFLOAT_NEG_U64:
7327 TempMantissa.uDataType = QCBOR_TYPE_65BIT_NEG_INT;
7328 TempMantissa.val.uint64 = pItem->val.expAndMantissa.Mantissa.uInt;
7329 break;
7330
7331#ifndef QCBOR_DISABLE_TAGS
7332 /* If tags are disabled, mantissas can never be big nums */
7333 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
7334 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
7335 TempMantissa.uDataType = QCBOR_TYPE_BYTE_STRING;
7336 TempMantissa.val.bigNum = pItem->val.expAndMantissa.Mantissa.bigNum;
7337 *pbIsNegative = false;
7338 break;
7339
7340 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
7341 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
7342 TempMantissa.uDataType = QCBOR_TYPE_BYTE_STRING;
7343 TempMantissa.val.bigNum = pItem->val.expAndMantissa.Mantissa.bigNum;
7344 *pbIsNegative = true;
7345 break;
7346#endif /* ! QCBOR_DISABLE_TAGS */
7347 }
7348
7349 *pnExponent = pItem->val.expAndMantissa.nExponent;
7350 uErr = QCBORDecode_ProcessBigNumber(TempMantissa, BufferForMantissa, pMantissa, pbIsNegative);
7351
7352 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007353}
7354
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007355
7356/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007357 * Public function, see header qcbor/qcbor_decode.h file
7358 */
7359void
Laurence Lundblade68769332024-11-03 13:09:20 -08007360QCBORDecode_GetTDecimalFraction(QCBORDecodeContext *pMe,
7361 const uint8_t uTagRequirement,
7362 int64_t *pnMantissa,
7363 int64_t *pnExponent)
7364{
7365 QCBORItem Item;
7366 size_t uOffset;
7367
7368 QCBORDecode_Private_GetAndTell(pMe, &Item, &uOffset);
7369 QCBORDecode_Private_ExpIntMantissaMain(pMe,
7370 uTagRequirement,
7371 CBOR_TAG_DECIMAL_FRACTION,
7372 uOffset,
7373 &Item,
7374 pnMantissa,
7375 pnExponent);
7376}
7377
7378
7379/*
7380 * Public function, see header qcbor/qcbor_decode.h file
7381 */
7382void
7383QCBORDecode_GetTDecimalFractionInMapN(QCBORDecodeContext *pMe,
7384 const int64_t nLabel,
7385 const uint8_t uTagRequirement,
7386 int64_t *pnMantissa,
7387 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007388{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007389 QCBORItem Item;
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007390 size_t uOffset;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007391
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007392 QCBORDecode_GetItemInMapNoCheckN(pMe, nLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
Laurence Lundblade68769332024-11-03 13:09:20 -08007393 QCBORDecode_Private_ExpIntMantissaMain(pMe,
7394 uTagRequirement,
7395 CBOR_TAG_DECIMAL_FRACTION,
7396 uOffset,
7397 &Item,
7398 pnMantissa,
7399 pnExponent);
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007400
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007401}
7402
7403
7404/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007405 * Public function, see header qcbor/qcbor_decode.h file
7406 */
7407void
Laurence Lundblade68769332024-11-03 13:09:20 -08007408QCBORDecode_GetTDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
7409 const char *szLabel,
7410 const uint8_t uTagRequirement,
7411 int64_t *pnMantissa,
7412 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007413{
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007414 QCBORItem Item;
7415 size_t uOffset;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007416
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007417 QCBORDecode_GetItemInMapNoCheckSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
Laurence Lundblade68769332024-11-03 13:09:20 -08007418 QCBORDecode_Private_ExpIntMantissaMain(pMe,
7419 uTagRequirement,
7420 CBOR_TAG_DECIMAL_FRACTION,
7421 uOffset,
7422 &Item,
7423 pnMantissa,
7424 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007425}
7426
7427
7428/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007429 * Public function, see header qcbor/qcbor_decode.h file
7430 */
7431void
Laurence Lundblade68769332024-11-03 13:09:20 -08007432QCBORDecode_GetTDecimalFractionBigMantissa(QCBORDecodeContext *pMe,
7433 const uint8_t uTagRequirement,
7434 const UsefulBuf MantissaBuffer,
7435 UsefulBufC *pMantissa,
7436 bool *pbMantissaIsNegative,
7437 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007438{
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007439 QCBORItem Item;
7440 size_t uOffset;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007441
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007442 QCBORDecode_Private_GetAndTell(pMe, &Item, &uOffset);
Laurence Lundblade68769332024-11-03 13:09:20 -08007443 QCBORDecode_Private_ExpBigMantissaMain(pMe,
7444 uTagRequirement,
7445 CBOR_TAG_DECIMAL_FRACTION,
7446 uOffset,
7447 &Item,
7448 MantissaBuffer,
7449 pMantissa,
7450 pbMantissaIsNegative,
7451 pnExponent);
7452}
7453
7454
7455/*
7456 * Public function, see header qcbor/qcbor_decode.h file
7457 */
7458void
7459QCBORDecode_GetTDecimalFractionBigMantissaInMapN(QCBORDecodeContext *pMe,
7460 const int64_t nLabel,
7461 const uint8_t uTagRequirement,
7462 const UsefulBuf BufferForMantissa,
7463 UsefulBufC *pMantissa,
7464 bool *pbIsNegative,
7465 int64_t *pnExponent)
7466{
7467 QCBORItem Item;
7468 size_t uOffset;
7469
7470 QCBORDecode_GetItemInMapNoCheckN(pMe, nLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
7471 QCBORDecode_Private_ExpBigMantissaMain(pMe,
7472 uTagRequirement,
7473 CBOR_TAG_DECIMAL_FRACTION,
7474 uOffset,
7475 &Item,
7476 BufferForMantissa,
7477 pMantissa,
7478 pbIsNegative,
7479 pnExponent);
7480}
7481
7482
7483/*
7484 * Public function, see header qcbor/qcbor_decode.h file
7485 */
7486void
7487QCBORDecode_GetTDecimalFractionBigMantissaInMapSZ(QCBORDecodeContext *pMe,
7488 const char *szLabel,
7489 const uint8_t uTagRequirement,
7490 const UsefulBuf BufferForMantissa,
7491 UsefulBufC *pMantissa,
7492 bool *pbIsNegative,
7493 int64_t *pnExponent)
7494{
7495 QCBORItem Item;
7496 size_t uOffset;
7497
7498 QCBORDecode_GetItemInMapNoCheckSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
7499 QCBORDecode_Private_ExpBigMantissaMain(pMe,
7500 uTagRequirement,
7501 CBOR_TAG_DECIMAL_FRACTION,
7502 uOffset,
7503 &Item,
7504 BufferForMantissa,
7505 pMantissa,
7506 pbIsNegative,
7507 pnExponent);
7508}
7509
7510/*
7511 * Public function, see header qcbor/qcbor_decode.h file
7512 */
7513void
7514QCBORDecode_GetTDecimalFractionBigMantissaRaw(QCBORDecodeContext *pMe,
7515 const uint8_t uTagRequirement,
7516 const UsefulBuf MantissaBuffer,
7517 UsefulBufC *pMantissa,
7518 bool *pbMantissaIsNegative,
7519 int64_t *pnExponent)
7520{
7521 QCBORItem Item;
7522 size_t uOffset;
7523
7524 QCBORDecode_Private_GetAndTell(pMe, &Item, &uOffset);
7525 QCBORDecode_Private_ExpBigMantissaRawMain(pMe,
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007526 uTagRequirement,
7527 CBOR_TAG_DECIMAL_FRACTION,
7528 uOffset,
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07007529 &Item,
7530 MantissaBuffer,
7531 pMantissa,
7532 pbMantissaIsNegative,
7533 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007534}
7535
7536
7537/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007538 * Public function, see header qcbor/qcbor_decode.h file
7539 */
7540void
Laurence Lundblade68769332024-11-03 13:09:20 -08007541QCBORDecode_GetTDecimalFractionBigMantissaRawInMapN(QCBORDecodeContext *pMe,
7542 const int64_t nLabel,
7543 const uint8_t uTagRequirement,
7544 const UsefulBuf BufferForMantissa,
7545 UsefulBufC *pMantissa,
7546 bool *pbIsNegative,
7547 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07007548{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007549 QCBORItem Item;
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007550 size_t uOffset;
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07007551
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007552 QCBORDecode_GetItemInMapNoCheckN(pMe, nLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
Laurence Lundblade68769332024-11-03 13:09:20 -08007553 QCBORDecode_Private_ExpBigMantissaRawMain(pMe,
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007554 uTagRequirement,
7555 CBOR_TAG_DECIMAL_FRACTION,
7556 uOffset,
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07007557 &Item,
7558 BufferForMantissa,
7559 pMantissa,
7560 pbIsNegative,
7561 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007562}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07007563
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007564
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007565/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007566 * Public function, see header qcbor/qcbor_decode.h file
7567 */
7568void
Laurence Lundblade68769332024-11-03 13:09:20 -08007569QCBORDecode_GetTDecimalFractionBigMantissaRawInMapSZ(QCBORDecodeContext *pMe,
7570 const char *szLabel,
7571 const uint8_t uTagRequirement,
7572 const UsefulBuf BufferForMantissa,
7573 UsefulBufC *pMantissa,
7574 bool *pbIsNegative,
7575 int64_t *pnExponent)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007576{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007577 QCBORItem Item;
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007578 size_t uOffset;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007579
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007580 QCBORDecode_GetItemInMapNoCheckSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
Laurence Lundblade68769332024-11-03 13:09:20 -08007581 QCBORDecode_Private_ExpBigMantissaRawMain(pMe,
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007582 uTagRequirement,
7583 CBOR_TAG_DECIMAL_FRACTION,
7584 uOffset,
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07007585 &Item,
7586 BufferForMantissa,
7587 pMantissa,
7588 pbIsNegative,
7589 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007590}
7591
7592
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007593/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007594 * Public function, see header qcbor/qcbor_decode.h file
7595 */
7596void
Laurence Lundblade68769332024-11-03 13:09:20 -08007597QCBORDecode_GetTBigFloat(QCBORDecodeContext *pMe,
7598 const uint8_t uTagRequirement,
7599 int64_t *pnMantissa,
7600 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007601{
Laurence Lundblade68769332024-11-03 13:09:20 -08007602 QCBORItem Item;
7603 size_t uOffset;
Laurence Lundbladecdbbc192024-06-28 15:13:04 -07007604
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007605 QCBORDecode_Private_GetAndTell(pMe, &Item, &uOffset);
Laurence Lundblade68769332024-11-03 13:09:20 -08007606 QCBORDecode_Private_ExpIntMantissaMain(pMe,
7607 uTagRequirement,
7608 CBOR_TAG_BIGFLOAT,
7609 uOffset,
7610 &Item,
7611 pnMantissa,
7612 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007613}
7614
7615
7616/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007617 * Public function, see header qcbor/qcbor_decode.h file
7618 */
7619void
Laurence Lundblade68769332024-11-03 13:09:20 -08007620QCBORDecode_GetTBigFloatInMapN(QCBORDecodeContext *pMe,
7621 const int64_t nLabel,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007622 const uint8_t uTagRequirement,
7623 int64_t *pnMantissa,
7624 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007625{
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007626 QCBORItem Item;
7627 size_t uOffset;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007628
Laurence Lundblade68769332024-11-03 13:09:20 -08007629 QCBORDecode_GetItemInMapNoCheckN(pMe, nLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
7630 QCBORDecode_Private_ExpIntMantissaMain(pMe,
7631 uTagRequirement,
7632 CBOR_TAG_BIGFLOAT,
7633 uOffset,
7634 &Item,
7635 pnMantissa,
7636 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007637}
7638
7639
7640/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007641 * Public function, see header qcbor/qcbor_decode.h file
7642 */
7643void
Laurence Lundblade68769332024-11-03 13:09:20 -08007644QCBORDecode_GetTBigFloatInMapSZ(QCBORDecodeContext *pMe,
7645 const char *szLabel,
7646 const uint8_t uTagRequirement,
7647 int64_t *pnMantissa,
7648 int64_t *pnExponent)
7649{
7650 QCBORItem Item;
7651 size_t uOffset;
7652
7653 QCBORDecode_GetItemInMapNoCheckSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
7654 QCBORDecode_Private_ExpIntMantissaMain(pMe,
7655 uTagRequirement,
7656 CBOR_TAG_BIGFLOAT,
7657 uOffset,
7658 &Item,
7659 pnMantissa,
7660 pnExponent);
7661}
7662
7663
7664/*
7665 * Public function, see header qcbor/qcbor_decode.h file
7666 */
7667void
7668QCBORDecode_GetTBigFloatBigMantissa(QCBORDecodeContext *pMe,
7669 const uint8_t uTagRequirement,
7670 const UsefulBuf MantissaBuffer,
7671 UsefulBufC *pMantissa,
7672 bool *pbMantissaIsNegative,
7673 int64_t *pnExponent)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007674{
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007675 QCBORItem Item;
7676 size_t uOffset;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007677
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007678 QCBORDecode_Private_GetAndTell(pMe, &Item, &uOffset);
Laurence Lundblade68769332024-11-03 13:09:20 -08007679 QCBORDecode_Private_ExpBigMantissaMain(pMe,
7680 uTagRequirement,
7681 CBOR_TAG_BIGFLOAT,
7682 uOffset,
7683 &Item,
7684 MantissaBuffer,
7685 pMantissa,
7686 pbMantissaIsNegative,
7687 pnExponent);
7688}
7689
7690
7691
7692/*
7693 * Public function, see header qcbor/qcbor_decode.h file
7694 */
7695void
7696QCBORDecode_GetTBigFloatBigMantissaInMapN(QCBORDecodeContext *pMe,
7697 const int64_t nLabel,
7698 const uint8_t uTagRequirement,
7699 const UsefulBuf BufferForMantissa,
7700 UsefulBufC *pMantissa,
7701 bool *pbIsNegative,
7702 int64_t *pnExponent)
7703{
7704 QCBORItem Item;
7705 size_t uOffset;
7706
7707 QCBORDecode_GetItemInMapNoCheckN(pMe, nLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
7708 QCBORDecode_Private_ExpBigMantissaMain(pMe,
7709 uTagRequirement,
7710 CBOR_TAG_BIGFLOAT,
7711 uOffset,
7712 &Item,
7713 BufferForMantissa,
7714 pMantissa,
7715 pbIsNegative,
7716 pnExponent);
7717}
7718
7719
7720/*
7721 * Public function, see header qcbor/qcbor_decode.h file
7722 */
7723void
7724QCBORDecode_GetTBigFloatBigMantissaInMapSZ(QCBORDecodeContext *pMe,
7725 const char *szLabel,
7726 const uint8_t uTagRequirement,
7727 const UsefulBuf BufferForMantissa,
7728 UsefulBufC *pMantissa,
7729 bool *pbIsNegative,
7730 int64_t *pnExponent)
7731{
7732 QCBORItem Item;
7733 size_t uOffset;
7734
7735 QCBORDecode_GetItemInMapNoCheckSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
7736 QCBORDecode_Private_ExpBigMantissaMain(pMe,
7737 uTagRequirement,
7738 CBOR_TAG_BIGFLOAT,
7739 uOffset,
7740 &Item,
7741 BufferForMantissa,
7742 pMantissa,
7743 pbIsNegative,
7744 pnExponent);
7745}
7746
7747
7748void
7749QCBORDecode_GetTBigFloatBigMantissaRaw(QCBORDecodeContext *pMe,
7750 const uint8_t uTagRequirement,
7751 const UsefulBuf MantissaBuffer,
7752 UsefulBufC *pMantissa,
7753 bool *pbMantissaIsNegative,
7754 int64_t *pnExponent)
7755{
7756 QCBORItem Item;
7757 size_t uOffset;
7758
7759 QCBORDecode_Private_GetAndTell(pMe, &Item, &uOffset);
7760 QCBORDecode_Private_ExpBigMantissaRawMain(pMe,
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007761 uTagRequirement,
7762 CBOR_TAG_BIGFLOAT,
7763 uOffset,
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07007764 &Item,
7765 MantissaBuffer,
7766 pMantissa,
7767 pbMantissaIsNegative,
7768 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007769}
7770
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007771
Laurence Lundblade68769332024-11-03 13:09:20 -08007772
7773
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007774/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007775 * Public function, see header qcbor/qcbor_decode.h file
7776 */
7777void
Laurence Lundblade68769332024-11-03 13:09:20 -08007778QCBORDecode_GetTBigFloatBigMantissaRawInMapN(QCBORDecodeContext *pMe,
7779 const int64_t nLabel,
7780 const uint8_t uTagRequirement,
7781 const UsefulBuf BufferForMantissa,
7782 UsefulBufC *pMantissa,
7783 bool *pbIsNegative,
7784 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007785{
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007786 QCBORItem Item;
7787 size_t uOffset;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007788
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007789 QCBORDecode_GetItemInMapNoCheckN(pMe, nLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
Laurence Lundblade68769332024-11-03 13:09:20 -08007790 QCBORDecode_Private_ExpBigMantissaRawMain(pMe,
7791 uTagRequirement,
7792 CBOR_TAG_BIGFLOAT,
7793 uOffset,
7794 &Item,
7795 BufferForMantissa,
7796 pMantissa,
7797 pbIsNegative,
7798 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007799}
7800
7801
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007802/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007803 * Public function, see header qcbor/qcbor_decode.h file
7804 */
7805void
Laurence Lundblade68769332024-11-03 13:09:20 -08007806QCBORDecode_GetTBigFloatBigMantissaRawInMapSZ(QCBORDecodeContext *pMe,
7807 const char *szLabel,
7808 const uint8_t uTagRequirement,
7809 const UsefulBuf BufferForMantissa,
7810 UsefulBufC *pMantissa,
7811 bool *pbIsNegative,
7812 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007813{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007814 QCBORItem Item;
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007815 size_t uOffset;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07007816
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007817 QCBORDecode_GetItemInMapNoCheckSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
Laurence Lundblade68769332024-11-03 13:09:20 -08007818 QCBORDecode_Private_ExpBigMantissaRawMain(pMe,
7819 uTagRequirement,
7820 CBOR_TAG_BIGFLOAT,
7821 uOffset,
7822 &Item,
7823 BufferForMantissa,
7824 pMantissa,
7825 pbIsNegative,
7826 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07007827}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007828
Laurence Lundblade68769332024-11-03 13:09:20 -08007829
7830#endif /* ! QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladed883ad32024-03-23 22:37:37 -07007831
7832
7833#if !defined(USEFULBUF_DISABLE_ALL_FLOAT) && !defined(QCBOR_DISABLE_PREFERRED_FLOAT)
7834/*
7835 * Public function, see header qcbor/qcbor_spiffy_decode.h file
7836 */
7837void
7838QCBORDecode_GetNumberConvertPrecisely(QCBORDecodeContext *pMe,
7839 QCBORItem *pNumber)
7840{
7841 QCBORItem Item;
7842 struct IEEE754_ToInt ToInt;
Laurence Lundblade14ce2282024-07-24 22:13:35 -07007843 double dNum;
Laurence Lundbladed883ad32024-03-23 22:37:37 -07007844 QCBORError uError;
7845
7846 if(pMe->uLastError != QCBOR_SUCCESS) {
7847 return;
7848 }
7849
Laurence Lundblade14ce2282024-07-24 22:13:35 -07007850 // TODO:VGetNext?
Laurence Lundbladed883ad32024-03-23 22:37:37 -07007851 uError = QCBORDecode_GetNext(pMe, &Item);
7852 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade14ce2282024-07-24 22:13:35 -07007853 *pNumber = Item;
Laurence Lundbladed883ad32024-03-23 22:37:37 -07007854 pMe->uLastError = (uint8_t)uError;
7855 return;
7856 }
7857
7858 switch(Item.uDataType) {
7859 case QCBOR_TYPE_INT64:
7860 case QCBOR_TYPE_UINT64:
7861 *pNumber = Item;
7862 break;
7863
7864 case QCBOR_TYPE_DOUBLE:
7865 ToInt = IEEE754_DoubleToInt(Item.val.dfnum);
7866 if(ToInt.type == IEEE754_ToInt_IS_INT) {
7867 pNumber->uDataType = QCBOR_TYPE_INT64;
7868 pNumber->val.int64 = ToInt.integer.is_signed;
7869 } else if(ToInt.type == IEEE754_ToInt_IS_UINT) {
7870 if(ToInt.integer.un_signed <= INT64_MAX) {
7871 /* Do the same as base QCBOR integer decoding */
7872 pNumber->uDataType = QCBOR_TYPE_INT64;
7873 pNumber->val.int64 = (int64_t)ToInt.integer.un_signed;
7874 } else {
7875 pNumber->uDataType = QCBOR_TYPE_UINT64;
7876 pNumber->val.uint64 = ToInt.integer.un_signed;
7877 }
7878 } else {
7879 *pNumber = Item;
7880 }
7881 break;
7882
7883 case QCBOR_TYPE_FLOAT:
7884 ToInt = IEEE754_SingleToInt(Item.val.fnum);
7885 if(ToInt.type == IEEE754_ToInt_IS_INT) {
7886 pNumber->uDataType = QCBOR_TYPE_INT64;
7887 pNumber->val.int64 = ToInt.integer.is_signed;
7888 } else if(ToInt.type == IEEE754_ToInt_IS_UINT) {
7889 if(ToInt.integer.un_signed <= INT64_MAX) {
7890 /* Do the same as base QCBOR integer decoding */
7891 pNumber->uDataType = QCBOR_TYPE_INT64;
7892 pNumber->val.int64 = (int64_t)ToInt.integer.un_signed;
7893 } else {
7894 pNumber->uDataType = QCBOR_TYPE_UINT64;
7895 pNumber->val.uint64 = ToInt.integer.un_signed;
7896 }
7897 } else {
7898 *pNumber = Item;
7899 }
7900 break;
7901
Laurence Lundbladed883ad32024-03-23 22:37:37 -07007902 case QCBOR_TYPE_65BIT_NEG_INT:
Laurence Lundblade14ce2282024-07-24 22:13:35 -07007903 if(Item.val.uint64 == UINT64_MAX) {
7904 /* The value -18446744073709551616 is encoded as an
7905 * unsigned 18446744073709551615. It's a whole number that
7906 * needs to be returned as a double. It can't be handled
7907 * by IEEE754_UintToDouble because 18446744073709551616
7908 * doesn't fit into a uint64_t. You can't get it by adding
7909 * 1 to 18446744073709551615.
7910 */
7911 pNumber->val.dfnum = -18446744073709551616.0;
Laurence Lundbladed883ad32024-03-23 22:37:37 -07007912 pNumber->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade14ce2282024-07-24 22:13:35 -07007913 } else {
7914 dNum = IEEE754_UintToDouble(Item.val.uint64 + 1, 1);
7915 if(dNum == IEEE754_UINT_TO_DOUBLE_OOB) {
7916 *pNumber = Item;
7917 } else {
7918 pNumber->val.dfnum = dNum;
7919 pNumber->uDataType = QCBOR_TYPE_DOUBLE;
7920 }
Laurence Lundbladed883ad32024-03-23 22:37:37 -07007921 }
7922 break;
7923
7924 default:
7925 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
7926 pNumber->uDataType = QCBOR_TYPE_NONE;
7927 break;
7928 }
7929}
7930
7931#endif /* ! USEFULBUF_DISABLE_ALL_FLOAT && ! QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade14ce2282024-07-24 22:13:35 -07007932
7933
Laurence Lundblade68769332024-11-03 13:09:20 -08007934
7935
Laurence Lundblade14ce2282024-07-24 22:13:35 -07007936static UsefulBufC
Laurence Lundblade68769332024-11-03 13:09:20 -08007937QCBORDecode_IntToBigNumber(uint64_t uNum,
7938 const UsefulBuf BigNumberBuf)
Laurence Lundblade14ce2282024-07-24 22:13:35 -07007939{
7940 UsefulOutBuf OB;
7941
7942 /* With a UsefulOutBuf, there's no pointer math here. */
Laurence Lundblade68769332024-11-03 13:09:20 -08007943 UsefulOutBuf_Init(&OB, BigNumberBuf);
Laurence Lundblade14ce2282024-07-24 22:13:35 -07007944
7945 /* Must copy one byte even if zero. The loop, mask and shift
7946 * algorithm provides endian conversion.
7947 */
7948 do {
7949 UsefulOutBuf_InsertByte(&OB, uNum & 0xff, 0);
7950 uNum >>= 8;
7951 } while(uNum);
7952
7953 return UsefulOutBuf_OutUBuf(&OB);
7954}
7955
7956
Laurence Lundblade14ce2282024-07-24 22:13:35 -07007957/* Add one to the big number and put the result in a new UsefulBufC
7958 * from storage in UsefulBuf.
7959 *
7960 * Leading zeros must be removed before calling this.
7961 *
7962 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
7963 */
7964static UsefulBufC
Laurence Lundblade68769332024-11-03 13:09:20 -08007965QCBORDecode_BigNumberCopyPlusOne(UsefulBufC BigNumber,
7966 UsefulBuf BigNumberBuf)
Laurence Lundblade14ce2282024-07-24 22:13:35 -07007967{
7968 uint8_t uCarry;
7969 uint8_t uSourceValue;
7970 const uint8_t *pSource;
7971 uint8_t *pDest;
7972 ptrdiff_t uDestBytesLeft;
7973
7974 /* Start adding at the LSB */
Laurence Lundblade68769332024-11-03 13:09:20 -08007975 pSource = &((const uint8_t *)BigNumber.ptr)[BigNumber.len-1];
7976 pDest = &((uint8_t *)BigNumberBuf.ptr)[BigNumberBuf.len-1];
Laurence Lundblade14ce2282024-07-24 22:13:35 -07007977
7978 uCarry = 1; /* Gets set back to zero if add the next line doesn't wrap */
7979 *pDest = *pSource + 1;
7980 while(1) {
7981 /* Wrap around from 0xff to 0 is a defined operation for
Laurence Lundblade721b56e2024-10-22 03:02:04 -07007982 * unsigned addition in C.*/
Laurence Lundblade14ce2282024-07-24 22:13:35 -07007983 if(*pDest != 0) {
7984 /* The add operation didn't wrap so no more carry. This
7985 * funciton only adds one, so when there is no more carry,
7986 * carrying is over to the end.
7987 */
7988 uCarry = 0;
7989 }
7990
Laurence Lundblade68769332024-11-03 13:09:20 -08007991 uDestBytesLeft = pDest - (uint8_t *)BigNumberBuf.ptr;
7992 if(pSource <= (const uint8_t *)BigNumber.ptr && uCarry == 0) {
Laurence Lundblade14ce2282024-07-24 22:13:35 -07007993 break; /* Successful exit */
7994 }
Laurence Lundblade68769332024-11-03 13:09:20 -08007995 if(pSource > (const uint8_t *)BigNumber.ptr) {
Laurence Lundblade14ce2282024-07-24 22:13:35 -07007996 uSourceValue = *--pSource;
7997 } else {
7998 /* All source bytes processed, but not the last carry */
7999 uSourceValue = 0;
8000 }
8001
8002 pDest--;
8003 if(uDestBytesLeft < 0) {
8004 return NULLUsefulBufC; /* Not enough space in destination buffer */
8005 }
8006
8007 *pDest = uSourceValue + uCarry;
8008 }
8009
Laurence Lundblade68769332024-11-03 13:09:20 -08008010 return (UsefulBufC){pDest, BigNumberBuf.len - (size_t)uDestBytesLeft};
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008011}
8012
8013
8014/* This returns 1 when uNum is 0 */
8015static size_t
8016QCBORDecode_Private_CountNonZeroBytes(uint64_t uNum)
8017{
8018 size_t uCount = 0;
8019 do {
8020 uCount++;
8021 uNum >>= 8;
8022 } while(uNum);
8023
8024 return uCount;
8025}
8026
8027
Laurence Lundblade721b56e2024-10-22 03:02:04 -07008028
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008029/*
8030 * Public function, see header qcbor/qcbor_decode.h
8031 */
8032QCBORError
Laurence Lundblade68769332024-11-03 13:09:20 -08008033QCBORDecode_ProcessBigNumberNoPreferred(const QCBORItem Item,
8034 const UsefulBuf BigNumberBuf,
8035 UsefulBufC *pBigNumber,
8036 bool *pbIsNegative)
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008037{
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008038 size_t uLen;
Laurence Lundblade68769332024-11-03 13:09:20 -08008039 UsefulBufC BigNumber;
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008040 int uType;
8041
8042 uType = Item.uDataType;
8043 if(uType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade68769332024-11-03 13:09:20 -08008044 uType = *pbIsNegative ? QCBOR_TYPE_NEGBIGNUM : QCBOR_TYPE_POSBIGNUM;
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008045 }
8046
8047 static const uint8_t Zero[] = {0x00};
Laurence Lundblade68769332024-11-03 13:09:20 -08008048 BigNumber = UsefulBuf_SkipLeading(Item.val.bigNum, 0);
8049 if(BigNumber.len == 0) {
8050 BigNumber = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(Zero);
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008051 }
8052
8053 /* Compute required length so it can be returned if buffer is too small */
8054 switch(uType) {
Laurence Lundblade68769332024-11-03 13:09:20 -08008055
8056 case QCBOR_TYPE_POSBIGNUM:
8057 uLen = BigNumber.len;
8058 break;
8059
8060 case QCBOR_TYPE_NEGBIGNUM:
8061 uLen = BigNumber.len;
8062 if(UsefulBuf_IsValue(UsefulBuf_SkipLeading(BigNumber, 0), 0xff) == SIZE_MAX) {
8063 uLen++;
8064 }
8065 break;
8066
8067 default:
8068 return QCBOR_ERR_UNEXPECTED_TYPE;
8069 }
8070
8071 *pBigNumber = (UsefulBufC){NULL, uLen};
8072
8073 if(BigNumberBuf.len < uLen || uLen == 0 || BigNumberBuf.ptr == NULL) {
8074 return BigNumberBuf.ptr == NULL ? QCBOR_SUCCESS : QCBOR_ERR_BUFFER_TOO_SMALL;
8075 /* Buffer is too short or type is wrong */
8076 }
8077
8078
8079 if(uType == QCBOR_TYPE_POSBIGNUM) {
8080 *pBigNumber = UsefulBuf_Copy(BigNumberBuf, BigNumber);
8081 *pbIsNegative = false;
8082 } else if(uType == QCBOR_TYPE_NEGBIGNUM) {
8083 /* The messy one. Take the stuff in the buffer and copy it to
8084 * the new buffer, adding one to it. This might be one byte
8085 * bigger than the original because of the carry from adding
8086 * one.*/
8087 *pbIsNegative = true;
8088 *pBigNumber = QCBORDecode_BigNumberCopyPlusOne(BigNumber, BigNumberBuf);
8089 }
8090
8091 return QCBOR_SUCCESS;
8092}
8093
8094
8095/*
8096 * Public function, see header qcbor/qcbor_decode.h
8097 */
8098QCBORError
8099QCBORDecode_ProcessBigNumber(const QCBORItem Item,
8100 UsefulBuf BigNumberBuf,
8101 UsefulBufC *pBigNumber,
8102 bool *pbIsNegative)
8103{
8104 QCBORError uResult;
8105 size_t uLen;
8106 int uType;
8107
8108 uType = Item.uDataType;
8109
8110 switch(uType) {
8111 case QCBOR_TYPE_POSBIGNUM:
8112 case QCBOR_TYPE_NEGBIGNUM:
8113 case QCBOR_TYPE_BYTE_STRING:
8114 return QCBORDecode_ProcessBigNumberNoPreferred(Item, BigNumberBuf, pBigNumber, pbIsNegative);
8115 break;
8116
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008117 case QCBOR_TYPE_INT64:
Laurence Lundblade721b56e2024-10-22 03:02:04 -07008118 uLen = QCBORDecode_Private_CountNonZeroBytes((uint64_t)ABSOLUTE_VALUE(Item.val.int64));
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008119 break;
8120
8121 case QCBOR_TYPE_UINT64:
8122 uLen = QCBORDecode_Private_CountNonZeroBytes(Item.val.uint64);
8123 break;
8124
8125 case QCBOR_TYPE_65BIT_NEG_INT:
Laurence Lundblade68769332024-11-03 13:09:20 -08008126 uLen = Item.val.uint64 == UINT64_MAX ? 9 : QCBORDecode_Private_CountNonZeroBytes(Item.val.uint64);
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008127 break;
8128
8129 default:
Laurence Lundblade68769332024-11-03 13:09:20 -08008130 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008131 }
8132
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008133
Laurence Lundblade68769332024-11-03 13:09:20 -08008134 *pBigNumber = (UsefulBufC){NULL, uLen};
8135
8136 if(BigNumberBuf.len < uLen || uLen == 0 || BigNumberBuf.ptr == NULL) {
8137 return BigNumberBuf.ptr == NULL ? QCBOR_SUCCESS : QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008138 /* Buffer is too short or type is wrong */
8139 }
8140
8141 uResult = QCBOR_SUCCESS;
8142
Laurence Lundblade68769332024-11-03 13:09:20 -08008143 if(uType == QCBOR_TYPE_UINT64) {
8144 *pBigNumber = QCBORDecode_IntToBigNumber(Item.val.uint64, BigNumberBuf);
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008145 *pbIsNegative = false;
8146 } else if(uType == QCBOR_TYPE_INT64) {
Laurence Lundblade68769332024-11-03 13:09:20 -08008147 /* Offset of 1 for negative numbers already performed */
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008148 *pbIsNegative = Item.val.int64 < 0;
Laurence Lundblade68769332024-11-03 13:09:20 -08008149 *pBigNumber = QCBORDecode_IntToBigNumber((uint64_t)(*pbIsNegative ? -Item.val.int64 : Item.val.int64), BigNumberBuf);
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008150 } else if(uType == QCBOR_TYPE_65BIT_NEG_INT) {
Laurence Lundblade68769332024-11-03 13:09:20 -08008151 /* Offset of 1 for negative numbers NOT already performed */
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008152 *pbIsNegative = true;
8153 if(Item.val.uint64 == UINT64_MAX) {
8154 /* The one value that can't be done with a computation
Laurence Lundblade68769332024-11-03 13:09:20 -08008155 * because it would overflow a uint64_t */
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008156 static const uint8_t TwoToThe64[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
Laurence Lundblade68769332024-11-03 13:09:20 -08008157 *pBigNumber = UsefulBuf_Copy(BigNumberBuf, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(TwoToThe64));
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008158 } else {
Laurence Lundblade68769332024-11-03 13:09:20 -08008159 // TODO: why + 1; test it; document it
8160 *pBigNumber = QCBORDecode_IntToBigNumber(Item.val.uint64 + 1, BigNumberBuf);
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008161 }
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008162 }
8163
8164 return uResult;
8165}
8166
8167
Laurence Lundblade68769332024-11-03 13:09:20 -08008168static const uint64_t QCBORDecode_Private_BigNumberTagNumbers[] = {
8169 CBOR_TAG_POS_BIGNUM,
8170 CBOR_TAG_NEG_BIGNUM,
8171 CBOR_TAG_INVALID64};
8172
8173static const uint8_t QCBORDecode_Private_BigNumberTypes[] = {
8174 QCBOR_TYPE_INT64,
8175 QCBOR_TYPE_UINT64,
8176 QCBOR_TYPE_65BIT_NEG_INT,
8177 QCBOR_TYPE_POSBIGNUM,
8178 QCBOR_TYPE_NEGBIGNUM,
8179 QCBOR_TYPE_NONE};
8180
8181#define QCBORDecode_Private_BigNumberTypesNoPreferred &QCBORDecode_Private_BigNumberTypes[3]
Laurence Lundblade721b56e2024-10-22 03:02:04 -07008182
8183
8184static void
Laurence Lundblade68769332024-11-03 13:09:20 -08008185QCBORDecode_Private_BigNumberNoPreferredMain(QCBORDecodeContext *pMe,
8186 const uint8_t uTagRequirement,
8187 QCBORItem *pItem,
8188 const size_t uOffset,
8189 UsefulBuf BigNumberBuf,
8190 UsefulBufC *pBigNumber,
8191 bool *pbIsNegative)
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008192{
Laurence Lundblade721b56e2024-10-22 03:02:04 -07008193 QCBORDecode_Private_ProcessTagItemMulti(pMe,
8194 pItem,
8195 uTagRequirement,
Laurence Lundblade68769332024-11-03 13:09:20 -08008196 QCBORDecode_Private_BigNumberTypesNoPreferred,
8197 QCBORDecode_Private_BigNumberTagNumbers,
Laurence Lundblade721b56e2024-10-22 03:02:04 -07008198 QCBORDecode_StringsTagCB,
8199 uOffset);
Laurence Lundblade721b56e2024-10-22 03:02:04 -07008200 if(pMe->uLastError) {
8201 return;
8202 }
8203
Laurence Lundblade68769332024-11-03 13:09:20 -08008204 pMe->uLastError = (uint8_t)QCBORDecode_ProcessBigNumberNoPreferred(*pItem, BigNumberBuf, pBigNumber, pbIsNegative);
8205}
8206
8207
8208static void
8209QCBORDecode_Private_BigNumberMain(QCBORDecodeContext *pMe,
8210 const uint8_t uTagRequirement,
8211 QCBORItem *pItem,
8212 const size_t uOffset,
8213 UsefulBuf BigNumberBuf,
8214 UsefulBufC *pBigNumber,
8215 bool *pbIsNegative)
8216{
8217 QCBORDecode_Private_ProcessTagItemMulti(pMe,
8218 pItem,
8219 uTagRequirement,
8220 QCBORDecode_Private_BigNumberTypes,
8221 QCBORDecode_Private_BigNumberTagNumbers,
8222 QCBORDecode_StringsTagCB,
8223 uOffset);
8224 if(pMe->uLastError) {
8225 return;
8226 }
8227
8228 pMe->uLastError = (uint8_t)QCBORDecode_ProcessBigNumber(*pItem, BigNumberBuf, pBigNumber, pbIsNegative);
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008229}
8230
8231
8232/*
8233 * Public function, see header qcbor/qcbor_decode.h
8234 */
8235void
Laurence Lundblade68769332024-11-03 13:09:20 -08008236QCBORDecode_GetTBigNumber(QCBORDecodeContext *pMe,
8237 const uint8_t uTagRequirement,
8238 UsefulBuf BigNumberBuf,
8239 UsefulBufC *pBigNumber,
8240 bool *pbIsNegative)
Laurence Lundblade721b56e2024-10-22 03:02:04 -07008241{
8242 QCBORItem Item;
8243 size_t uOffset;
8244
8245 QCBORDecode_Private_GetAndTell(pMe, &Item, &uOffset);
Laurence Lundblade68769332024-11-03 13:09:20 -08008246 QCBORDecode_Private_BigNumberMain(pMe, uTagRequirement, &Item, uOffset, BigNumberBuf, pBigNumber, pbIsNegative);
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008247}
8248
8249
Laurence Lundblade68769332024-11-03 13:09:20 -08008250
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008251/*
8252 * Public function, see header qcbor/qcbor_decode.h
8253 */
8254void
Laurence Lundblade68769332024-11-03 13:09:20 -08008255QCBORDecode_GetTBigNumberInMapN(QCBORDecodeContext *pMe,
8256 const int64_t nLabel,
8257 const uint8_t uTagRequirement,
8258 UsefulBuf BigNumberBuf,
8259 UsefulBufC *pBigNumber,
8260 bool *pbIsNegative)
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008261{
Laurence Lundblade721b56e2024-10-22 03:02:04 -07008262 QCBORItem Item;
8263 size_t uOffset;
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008264
Laurence Lundblade721b56e2024-10-22 03:02:04 -07008265 QCBORDecode_GetItemInMapNoCheckN(pMe, nLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
Laurence Lundblade68769332024-11-03 13:09:20 -08008266 QCBORDecode_Private_BigNumberMain(pMe,
8267 uTagRequirement,
8268 &Item,
8269 uOffset,
8270 BigNumberBuf,
8271 pBigNumber,
8272 pbIsNegative);
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008273}
8274
8275/*
8276 * Public function, see header qcbor/qcbor_decode.h
8277 */
8278void
Laurence Lundblade68769332024-11-03 13:09:20 -08008279QCBORDecode_GetTBigNumberInMapSZ(QCBORDecodeContext *pMe,
8280 const char *szLabel,
8281 const uint8_t uTagRequirement,
8282 UsefulBuf BigNumberBuf,
8283 UsefulBufC *pBigNumber,
8284 bool *pbIsNegative)
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008285{
Laurence Lundblade721b56e2024-10-22 03:02:04 -07008286 QCBORItem Item;
8287 size_t uOffset;
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008288
Laurence Lundblade721b56e2024-10-22 03:02:04 -07008289 QCBORDecode_GetItemInMapNoCheckSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
Laurence Lundblade68769332024-11-03 13:09:20 -08008290 QCBORDecode_Private_BigNumberMain(pMe,
8291 uTagRequirement,
8292 &Item,
8293 uOffset,
8294 BigNumberBuf,
8295 pBigNumber,
8296 pbIsNegative);
8297}
8298
8299
8300/*
8301 * Public function, see header qcbor/qcbor_decode.h
8302 */
8303void
8304QCBORDecode_GetTBigNumberNoPreferred(QCBORDecodeContext *pMe,
8305 const uint8_t uTagRequirement,
8306 UsefulBuf BigNumberBuf,
8307 UsefulBufC *pBigNumber,
8308 bool *pbIsNegative)
8309{
8310 QCBORItem Item;
8311 size_t uOffset;
8312
8313 QCBORDecode_Private_GetAndTell(pMe, &Item, &uOffset);
8314 QCBORDecode_Private_BigNumberNoPreferredMain(pMe, uTagRequirement, &Item, uOffset, BigNumberBuf, pBigNumber, pbIsNegative);
8315}
8316
8317/*
8318 * Public function, see header qcbor/qcbor_decode.h
8319 */
8320void
8321QCBORDecode_GetTBigNumberNoPreferredInMapN(QCBORDecodeContext *pMe,
8322 const int64_t nLabel,
8323 const uint8_t uTagRequirement,
8324 UsefulBuf BigNumberBuf,
8325 UsefulBufC *pBigNumber,
8326 bool *pbIsNegative)
8327{
8328 QCBORItem Item;
8329 size_t uOffset;
8330
8331 QCBORDecode_GetItemInMapNoCheckN(pMe, nLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
8332 QCBORDecode_Private_BigNumberNoPreferredMain(pMe, uTagRequirement, &Item, uOffset, BigNumberBuf, pBigNumber, pbIsNegative);
8333
8334}
8335
8336/*
8337 * Public function, see header qcbor/qcbor_decode.h
8338 */
8339void
8340QCBORDecode_GetTBigNumberNoPreferredInMapSZ(QCBORDecodeContext *pMe,
8341 const char *szLabel,
8342 const uint8_t uTagRequirement,
8343 UsefulBuf BigNumberBuf,
8344 UsefulBufC *pBigNumber,
8345 bool *pbIsNegative)
8346{
8347 QCBORItem Item;
8348 size_t uOffset;
8349
8350 QCBORDecode_GetItemInMapNoCheckSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item, &uOffset);
8351 QCBORDecode_Private_BigNumberNoPreferredMain(pMe, uTagRequirement, &Item, uOffset, BigNumberBuf, pBigNumber, pbIsNegative);
Laurence Lundblade14ce2282024-07-24 22:13:35 -07008352}
8353
Laurence Lundblade721b56e2024-10-22 03:02:04 -07008354// TODO: re order above functions in tag number order