blob: 2dfaff1b6f904fe0b604617a4abae84df74ea495 [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
Laurence Lundbladed92a6162018-11-01 11:38:35 +07002 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003 Copyright (c) 2018-2024, Laurence Lundblade.
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02004 Copyright (c) 2021, Arm Limited.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07005 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08006
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07007Redistribution and use in source and binary forms, with or without
8modification, are permitted provided that the following conditions are
9met:
10 * Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above
13 copyright notice, this list of conditions and the following
14 disclaimer in the documentation and/or other materials provided
15 with the distribution.
16 * Neither the name of The Linux Foundation nor the names of its
17 contributors, nor the name "Laurence Lundblade" may be used to
18 endorse or promote products derived from this software without
19 specific prior written permission.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080020
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070021THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
22WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
24ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
25BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
30OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080032 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070033
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080034
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080035#include "qcbor/qcbor_decode.h"
Laurence Lundblade67257dc2020-07-27 03:33:37 -070036#include "qcbor/qcbor_spiffy_decode.h"
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080037#include "ieee754.h" /* Does not use math.h */
Laurence Lundbladec7114722020-08-13 05:11:40 -070038
39#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080040
41#include <math.h> /* For isnan(), llround(), llroudf(), round(), roundf(),
42 * pow(), exp2()
43 */
44#include <fenv.h> /* feclearexcept(), fetestexcept() */
45
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080046#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070047
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070048
Laurence Lundblade68cb61c2023-02-12 13:21:44 -080049#if (defined(__GNUC__) && !defined(__clang__))
Laurence Lundblade8e36f812024-01-26 10:59:29 -070050/*
Laurence Lundblade68cb61c2023-02-12 13:21:44 -080051 * This is how the -Wmaybe-uninitialized compiler warning is
52 * handled. It can’t be ignored because some version of gcc enable it
53 * with -Wall which is a common and useful gcc warning option. It also
54 * can’t be ignored because it is the goal of QCBOR to compile clean
55 * out of the box in all environments.
56 *
57 * The big problem with -Wmaybe-uninitialized is that it generates
58 * false positives. It complains things are uninitialized when they
59 * are not. This is because it is not a thorough static analyzer. This
60 * is why “maybe” is in its name. The problem is it is just not
61 * thorough enough to understand all the code (and someone saw fit to
62 * put it in gcc and worse to enable it with -Wall).
63 *
64 * One solution would be to change the code so -Wmaybe-uninitialized
65 * doesn’t get confused, for example adding an unnecessary extra
66 * initialization to zero. (If variables were truly uninitialized, the
67 * correct path is to understand the code thoroughly and set them to
68 * the correct value at the correct time; in essence this is already
69 * done; -Wmaybe-uninitialized just can’t tell). This path is not
70 * taken because it makes the code bigger and is kind of the tail
71 * wagging the dog.
72 *
73 * The solution here is to just use a pragma to disable it for the
74 * whole file. Disabling it for each line makes the code fairly ugly
75 * requiring #pragma to push, pop and ignore. Another reason is the
76 * warnings issues vary by version of gcc and which optimization
77 * optimizations are selected. Another reason is that compilers other
78 * than gcc don’t have -Wmaybe-uninitialized.
79 *
80 * One may ask how to be sure these warnings are false positives and
81 * not real issues. 1) The code has been read carefully to check. 2)
82 * Testing is pretty thorough. 3) This code has been run through
83 * thorough high-quality static analyzers.
84 *
85 * In particularly, most of the warnings are about
86 * Item.Item->uDataType being uninitialized. QCBORDecode_GetNext()
87 * *always* sets this value and test case confirm
88 * this. -Wmaybe-uninitialized just can't tell.
89 *
90 * https://stackoverflow.com/questions/5080848/disable-gcc-may-be-used-uninitialized-on-a-particular-variable
91 */
92#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
Laurence Lundblade8e36f812024-01-26 10:59:29 -070093#endif
Laurence Lundblade68cb61c2023-02-12 13:21:44 -080094
95
96
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080097
Laurence Lundbladea9489f82020-09-12 13:50:56 -070098#define SIZEOF_C_ARRAY(array,type) (sizeof(array)/sizeof(type))
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070099
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700100
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800101
102
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700103static bool
104QCBORItem_IsMapOrArray(const QCBORItem Item)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700105{
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700106 const uint8_t uDataType = Item.uDataType;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700107 return uDataType == QCBOR_TYPE_MAP ||
108 uDataType == QCBOR_TYPE_ARRAY ||
109 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
110}
111
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700112static bool
113QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem Item)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700114{
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700115 if(!QCBORItem_IsMapOrArray(Item)){
Laurence Lundblade02625d42020-06-25 14:41:41 -0700116 return false;
117 }
118
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700119 if(Item.val.uCount != 0) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700120 return false;
121 }
122 return true;
123}
124
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700125static bool
126QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem Item)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700127{
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800128#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700129 if(!QCBORItem_IsMapOrArray(Item)){
Laurence Lundblade02625d42020-06-25 14:41:41 -0700130 return false;
131 }
132
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700133 if(Item.val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700134 return false;
135 }
136 return true;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800137#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700138 (void)Item;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800139 return false;
140#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700141}
142
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700143/* Return true if the labels in Item1 and Item2 are the same.
144 Works only for integer and string labels. Returns false
145 for any other type. */
146static bool
147QCBORItem_MatchLabel(const QCBORItem Item1, const QCBORItem Item2)
148{
149 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
150 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
151 return true;
152 }
153 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
154 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
155 return true;
156 }
157 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
158 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
159 return true;
160 }
161 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
162 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
163 return true;
164 }
165 }
166
167 /* Other label types are never matched */
168 return false;
169}
170
171
172/*
173 Returns true if Item1 and Item2 are the same type
174 or if either are of QCBOR_TYPE_ANY.
175 */
176static bool
177QCBORItem_MatchType(const QCBORItem Item1, const QCBORItem Item2)
178{
179 if(Item1.uDataType == Item2.uDataType) {
180 return true;
181 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
182 return true;
183 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
184 return true;
185 }
186 return false;
187}
188
Laurence Lundblade02625d42020-06-25 14:41:41 -0700189
Laurence Lundbladeee851742020-01-08 08:37:05 -0800190/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700191 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -0800192 ===========================================================================*/
193
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700194/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800195 * See comments about and typedef of QCBORDecodeNesting in qcbor_private.h,
196 * the data structure all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700197 */
198
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700199
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700200static uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700201DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700202{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700203 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800204 /* Limit in DecodeNesting_Descend against more than
205 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700206 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700207 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700208}
209
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700210
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700211static uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700212DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700213{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700214 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800215 /* Limit in DecodeNesting_Descend against more than
216 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700217 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700218 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700219}
220
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700221
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700222static uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700223DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700224{
225 return pNesting->pCurrentBounded->u.ma.uStartOffset;
226}
227
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700228
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700229static bool
Laurence Lundblade085d7952020-07-24 10:26:30 -0700230DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
231{
232 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
233 return true;
234 } else {
235 return false;
236 }
237}
238
239
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700240static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700241DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700242{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700243 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700244 return true;
245 } else {
246 return false;
247 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700248}
249
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700250
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700251static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700252DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700253{
254 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800255 /* Not a map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700256 return false;
257 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800258
259#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700260 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800261 /* Is indefinite */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700262 return false;
263 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800264
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800265#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
266
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800267 /* All checks passed; is a definte length map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700268 return true;
269}
270
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700271static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700272DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700273{
274 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800275 /* is a byte string */
Laurence Lundblade642282a2020-06-23 12:00:33 -0700276 return true;
277 }
278 return false;
279}
280
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700281
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700282static bool
283DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700284{
285 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
286 return true;
287 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700288 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700289 return true;
290 }
291 return false;
292}
293
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700294
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700295static void
296DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700297{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800298 /* Should be only called on maps and arrays */
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700299 /*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800300 * DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
301 * larger than DecodeNesting_EnterBoundedMode which keeps it less than
302 * uin32_t so the cast is safe.
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700303 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700304 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700305
306 if(bIsEmpty) {
307 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
308 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700309}
310
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700311
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700312static void
313DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700314{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700315 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700316}
317
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700318
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700319static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700320DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700321{
322 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800323 /* No bounded map or array set up */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700324 return false;
325 }
326 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800327 /* Not a map or array; end of those is by byte count */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700328 return false;
329 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700330 if(!DecodeNesting_IsCurrentBounded(pNesting)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800331 /* In a traveral at a level deeper than the bounded level */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700332 return false;
333 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800334 /* Works for both definite- and indefinitelength maps/arrays */
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800335 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0 &&
336 pNesting->pCurrentBounded->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800337 /* Count is not zero, still unconsumed item */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700338 return false;
339 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800340 /* All checks passed, got to the end of an array or map*/
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700341 return true;
342}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700343
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700344
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700345static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700346DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700347{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800348 /* Must only be called on map / array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700349 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
350 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700351 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700352 return false;
353 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700354}
355
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700356
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700357static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700358DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700359{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700360 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
361 return true;
362 } else {
363 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700364 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700365}
366
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700367
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700368static bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700369DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700370{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700371 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700372 return false;
373 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700374
375 if(pNesting->pCurrentBounded->uLevelType != uType) {
376 return false;
377 }
378
379 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700380}
381
Laurence Lundblade02625d42020-06-25 14:41:41 -0700382
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700383static void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700384DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700385{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800386 /* Only call on a definite-length array / map */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700387 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700388}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700389
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700390
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700391static void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700392DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
393{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800394 /* Only call on a definite-length array / map */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700395 pNesting->pCurrent->u.ma.uCountCursor++;
396}
397
398
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700399static void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700400DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
401{
402 pNesting->pCurrent--;
403}
404
Laurence Lundblade02625d42020-06-25 14:41:41 -0700405
406static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700407DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700408{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800409 /* Error out if nesting is too deep */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700410 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700411 return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700412 }
413
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800414 /* The actual descend */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700415 pNesting->pCurrent++;
416
417 pNesting->pCurrent->uLevelType = uType;
418
419 return QCBOR_SUCCESS;
420}
421
422
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700423static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800424DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting,
425 bool bIsEmpty,
426 size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700427{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700428 /*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800429 * Should only be called on map/array.
430 *
431 * Have descended into this before this is called. The job here is
432 * just to mark it in bounded mode.
433 *
434 * Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
435 * uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET.
436 *
437 * Cast of uOffset to uint32_t for cases where SIZE_MAX < UINT32_MAX.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700438 */
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -0800439 if((uint32_t)uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700440 return QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700441 }
442
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700443 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700444
445 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700446
447 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700448}
449
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700450
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700451static QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700452DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700453 uint8_t uQCBORType,
454 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700455{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700456 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700457
458 if(uCount == 0) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800459 /* Nothing to do for empty definite-length arrays. They are just are
460 * effectively the same as an item that is not a map or array.
461 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700462 goto Done;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800463 /* Empty indefinite-length maps and arrays are handled elsewhere */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700464 }
465
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800466 /* Error out if arrays is too long to handle */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700467 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
468 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700469 uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700470 goto Done;
471 }
472
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700473 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700474 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700475 goto Done;
476 }
477
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800478 /* Fill in the new map/array level. Check above makes casts OK. */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700479 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
480 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700481
482 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700483
484Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700485 return uError;;
486}
487
488
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700489static void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700490DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
491{
492 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
493}
494
495
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700496static void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700497DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
498{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700499 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700500 pNesting->pCurrentBounded--;
501 if(DecodeNesting_IsCurrentBounded(pNesting)) {
502 break;
503 }
504 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700505}
506
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800507
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700508static void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700509DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
510{
511 pNesting->pCurrent = pNesting->pCurrentBounded;
512}
513
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700514
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700515static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700516DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700517 uint32_t uEndOffset,
518 uint32_t uStartOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700519{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700520 QCBORError uError;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700521
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700522 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700523 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700524 goto Done;
525 }
526
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800527 /* Fill in the new byte string level */
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700528 pNesting->pCurrent->u.bs.uSavedEndOffset = uEndOffset;
529 pNesting->pCurrent->u.bs.uBstrStartOffset = uStartOffset;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700530
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800531 /* Bstr wrapped levels are always bounded */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700532 pNesting->pCurrentBounded = pNesting->pCurrent;
533
534Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700535 return uError;;
536}
537
Laurence Lundbladed0304932020-06-27 10:59:38 -0700538
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700539static void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700540DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700541{
542 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700543}
544
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700545
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700546static void
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800547DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
548{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700549 if(pNesting->pCurrent->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
550 pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
551 }
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800552}
553
554
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700555static void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700556DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700557{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700558 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700559 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
560 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700561}
562
563
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700564static void
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800565DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting,
566 QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700567{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700568 *pSave = *pNesting;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700569}
570
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700571
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700572static void
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800573DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting,
574 const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700575{
576 *pNesting = *pSave;
577}
578
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700579
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700580static uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700581DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700582{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700583 return pMe->pCurrentBounded->u.bs.uSavedEndOffset;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700584}
585
586
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800587
588
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800589#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladeee851742020-01-08 08:37:05 -0800590/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800591 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
592
593 The following four functions are pretty wrappers for invocation of
594 the string allocator supplied by the caller.
595
Laurence Lundbladeee851742020-01-08 08:37:05 -0800596 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800597
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700598static void
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800599StringAllocator_Free(const QCBORInternalAllocator *pMe, const void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800600{
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300601 /* This cast to uintptr_t suppresses the "-Wcast-qual" warnings.
602 * This is the one place where the const needs to be cast away so const can
603 * be use in the rest of the code.
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800604 */
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300605 (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)(uintptr_t)pMem, 0);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800606}
607
Laurence Lundbladeee851742020-01-08 08:37:05 -0800608// StringAllocator_Reallocate called with pMem NULL is
609// equal to StringAllocator_Allocate()
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700610static UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800611StringAllocator_Reallocate(const QCBORInternalAllocator *pMe,
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800612 const void *pMem,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800613 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800614{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800615 /* See comment in StringAllocator_Free() */
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300616 return (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)(uintptr_t)pMem, uSize);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800617}
618
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700619static UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800620StringAllocator_Allocate(const QCBORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800621{
622 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
623}
624
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700625static void
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800626StringAllocator_Destruct(const QCBORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800627{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800628 /* See comment in StringAllocator_Free() */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800629 if(pMe->pfAllocator) {
630 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
631 }
632}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800633#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800634
635
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800636
637
Laurence Lundbladeee851742020-01-08 08:37:05 -0800638/*===========================================================================
639 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700640
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800641 See qcbor/qcbor_decode.h for definition of the object
642 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800643 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700644/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800645 * Public function, see header file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700646 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700647void
648QCBORDecode_Init(QCBORDecodeContext *pMe,
649 UsefulBufC EncodedCBOR,
650 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700651{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800652 memset(pMe, 0, sizeof(QCBORDecodeContext));
653 UsefulInputBuf_Init(&(pMe->InBuf), EncodedCBOR);
654 /* Don't bother with error check on decode mode. If a bad value is
655 * passed it will just act as if the default normal mode of 0 was set.
656 */
657 pMe->uDecodeMode = (uint8_t)nDecodeMode;
658 DecodeNesting_Init(&(pMe->nesting));
659
660 /* Inialize me->auMappedTags to CBOR_TAG_INVALID16. See
661 * GetNext_TaggedItem() and MapTagNumber(). */
662 memset(pMe->auMappedTags, 0xff, sizeof(pMe->auMappedTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700663}
664
665
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800666#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
667
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700668/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800669 * Public function, see header file
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700670 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700671void
672QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
673 QCBORStringAllocate pfAllocateFunction,
674 void *pAllocateContext,
675 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700676{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800677 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
678 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
679 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700680}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800681#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700682
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800683
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800684
685
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800686/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800687 * Deprecated public function, see header file
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800688 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700689void
690QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
691 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700692{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800693 /* This does nothing now. It is retained for backwards compatibility */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700694 (void)pMe;
695 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700696}
697
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700698
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800699
700
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700701/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800702 * Decoding items is done in six layers, one calling the next one
703 * down. If a layer has no work to do for a particular item, it
704 * returns quickly.
705 *
706 * 1. QCBORDecode_GetNextTagContent - The top layer processes tagged
707 * data items, turning them into the local C representation. For the
708 * most simple it is just associating a QCBOR_TYPE with the data. For
709 * the complex ones that an aggregate of data items, there is some
710 * further decoding and some limited recursion.
711 *
712 * 2. QCBORDecode_GetNextMapOrArray - This manages the beginnings and
713 * ends of maps and arrays. It tracks descending into and ascending
714 * out of maps/arrays. It processes breaks that terminate
715 * indefinite-length maps and arrays.
716 *
717 * 3. QCBORDecode_GetNextMapEntry - This handles the combining of two
718 * items, the label and the data, that make up a map entry. It only
719 * does work on maps. It combines the label and data items into one
720 * labeled item.
721 *
722 * 4. QCBORDecode_GetNextTagNumber - This decodes type 6 tag
723 * numbers. It turns the tag numbers into bit flags associated with
724 * the data item. No actual decoding of the contents of the tag is
725 * performed here.
726 *
727 * 5. QCBORDecode_GetNextFullString - This assembles the sub-items
728 * that make up an indefinite-length string into one string item. It
729 * uses the string allocator to create contiguous space for the
730 * item. It processes all breaks that are part of indefinite-length
731 * strings.
732 *
733 * 6. DecodeAtomicDataItem - This decodes the atomic data items in
734 * CBOR. Each atomic data item has a "major type", an integer
735 * "argument" and optionally some content. For text and byte strings,
736 * the content is the bytes that make up the string. These are the
737 * smallest data items that are considered to be well-formed. The
738 * content may also be other data items in the case of aggregate
739 * types. They are not handled in this layer.
740 *
741 * Roughly this takes 300 bytes of stack for vars. TODO: evaluate this
742 * more carefully and correctly.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700743 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800744
745
746/*
747 * Note about use of int and unsigned variables.
748 *
749 * See http://www.unix.org/whitepapers/64bit.html for reasons int is
750 * used carefully here, and in particular why it isn't used in the
751 * public interface. Also see
752 * https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
753 *
754 * Int is used for values that need less than 16-bits and would be
755 * subject to integer promotion and result in complaining from static
756 * analyzers.
757 */
758
759
760/**
761 * @brief Decode the CBOR head, the type and argument.
762 *
763 * @param[in] pUInBuf The input buffer to read from.
764 * @param[out] pnMajorType The decoded major type.
765 * @param[out] puArgument The decoded argument.
766 * @param[out] pnAdditionalInfo The decoded Lower 5 bits of initial byte.
767 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -0700768 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved features
769 * @retval QCBOR_ERR_HIT_END Unexpected end of input
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800770 *
771 * This decodes the CBOR "head" that every CBOR data item has. See
772 * longer explaination of the head in documentation for
773 * QCBOREncode_EncodeHead().
774 *
775 * This does the network->host byte order conversion. The conversion
776 * here also results in the conversion for floats in addition to that
777 * for lengths, tags and integer values.
778 *
779 * The int type is preferred to uint8_t for some variables as this
780 * avoids integer promotions, can reduce code size and makes static
781 * analyzers happier.
782 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700783static QCBORError
784QCBOR_Private_DecodeHead(UsefulInputBuf *pUInBuf,
785 int *pnMajorType,
786 uint64_t *puArgument,
787 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700788{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800789 QCBORError uReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800790
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800791 /* Get the initial byte that every CBOR data item has and break it
792 * down. */
793 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800794 const int nTmpMajorType = nInitialByte >> 5;
795 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800796
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800797 /* Where the argument accumulates */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800798 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800799
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800800 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800801 /* Need to get 1,2,4 or 8 additional argument bytes. Map
802 * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
803 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800804 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800805
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800806 /* Loop getting all the bytes in the argument */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800807 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800808 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800809 /* This shift and add gives the endian conversion. */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800810 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
811 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800812 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800813 /* The reserved and thus-far unused additional info values */
814 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800815 goto Done;
816 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800817 /* Less than 24, additional info is argument or 31, an
818 * indefinite-length. No more bytes to get.
819 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800820 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700821 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800822
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700823 if(UsefulInputBuf_GetError(pUInBuf)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800824 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700825 goto Done;
826 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800827
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800828 /* All successful if arrived here. */
829 uReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800830 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800831 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800832 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800833
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700834Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800835 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700836}
837
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800838
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800839/**
840 * @brief Decode integer types, major types 0 and 1.
841 *
842 * @param[in] nMajorType The CBOR major type (0 or 1).
843 * @param[in] uArgument The argument from the head.
844 * @param[out] pDecodedItem The filled in decoded item.
845 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -0700846 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800847 *
848 * Must only be called when major type is 0 or 1.
849 *
850 * CBOR doesn't explicitly specify two's compliment for integers but
851 * all CPUs use it these days and the test vectors in the RFC are
852 * so. All integers in the CBOR structure are positive and the major
853 * type indicates positive or negative. CBOR can express positive
854 * integers up to 2^x - 1 where x is the number of bits and negative
855 * integers down to 2^x. Note that negative numbers can be one more
856 * away from zero than positive. Stdint, as far as I can tell, uses
857 * two's compliment to represent negative integers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700858 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700859static QCBORError
860QCBOR_Private_DecodeInteger(const int nMajorType,
861 const uint64_t uArgument,
862 QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700863{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800864 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800865
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700866 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800867 if (uArgument <= INT64_MAX) {
868 pDecodedItem->val.int64 = (int64_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700869 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800870
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700871 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800872 pDecodedItem->val.uint64 = uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700873 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700874 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800875
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700876 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800877 if(uArgument <= INT64_MAX) {
878 /* CBOR's representation of negative numbers lines up with
879 * the two-compliment representation. A negative integer has
880 * one more in range than a positive integer. INT64_MIN is
881 * equal to (-INT64_MAX) - 1.
882 */
883 pDecodedItem->val.int64 = (-(int64_t)uArgument) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700884 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800885
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700886 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800887 /* C can't represent a negative integer in this range so it
888 * is an error.
889 */
890 uReturn = QCBOR_ERR_INT_OVERFLOW;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700891 }
892 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800893
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800894 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700895}
896
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800897
898/* Make sure #define value line up as DecodeSimple counts on this. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700899#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
900#error QCBOR_TYPE_FALSE macro value wrong
901#endif
902
903#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
904#error QCBOR_TYPE_TRUE macro value wrong
905#endif
906
907#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
908#error QCBOR_TYPE_NULL macro value wrong
909#endif
910
911#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
912#error QCBOR_TYPE_UNDEF macro value wrong
913#endif
914
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700915#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
916#error QCBOR_TYPE_BREAK macro value wrong
917#endif
918
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700919#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
920#error QCBOR_TYPE_DOUBLE macro value wrong
921#endif
922
923#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
924#error QCBOR_TYPE_FLOAT macro value wrong
925#endif
926
Laurence Lundblade9b334962020-08-27 10:55:53 -0700927
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800928/**
929 * @brief Decode major type 7 -- true, false, floating-point, break...
930 *
931 * @param[in] nAdditionalInfo The lower five bits from the initial byte.
932 * @param[in] uArgument The argument from the head.
933 * @param[out] pDecodedItem The filled in decoded item.
934 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -0700935 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
936 * of half-precision disabled
937 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all float
938 * decode is disabled.
939 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of simple
940 * type in input.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700941 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700942static QCBORError
943QCBOR_Private_DecodeType7(const int nAdditionalInfo,
944 const uint64_t uArgument,
945 QCBORItem *pDecodedItem)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800946{
947 QCBORError uReturn = QCBOR_SUCCESS;
948
949 /* uAdditionalInfo is 5 bits from the initial byte. Compile time
950 * checks above make sure uAdditionalInfo values line up with
951 * uDataType values. DecodeHead() never returns an AdditionalInfo
952 * > 0x1f so cast is safe.
953 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800954 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800955
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800956 switch(nAdditionalInfo) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800957 /* No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they
958 * are caught before this is called.
959 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800960
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800961 case HALF_PREC_FLOAT: /* 25 */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700962#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800963 /* Half-precision is returned as a double. The cast to
964 * uint16_t is safe because the encoded value was 16 bits. It
965 * was widened to 64 bits to be passed in here.
966 */
967 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700968 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800969#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200970 uReturn = FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700971 break;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800972 case SINGLE_PREC_FLOAT: /* 26 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200973#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800974 /* Single precision is normally returned as a double since
975 * double is widely supported, there is no loss of precision,
976 * it makes it easy for the caller in most cases and it can
977 * be converted back to single with no loss of precision
978 *
979 * The cast to uint32_t is safe because the encoded value was
980 * 32 bits. It was widened to 64 bits to be passed in here.
981 */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700982 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800983 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uArgument);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700984#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800985 /* In the normal case, use HW to convert float to
986 * double. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700987 pDecodedItem->val.dfnum = (double)f;
988 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800989#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800990 /* Use of float HW is disabled, return as a float. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700991 pDecodedItem->val.fnum = f;
992 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
993
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800994 /* IEEE754_FloatToDouble() could be used here to return as
995 * a double, but it adds object code and most likely
996 * anyone disabling FLOAT HW use doesn't care about floats
997 * and wants to save object code.
998 */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800999#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001000 }
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001001#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1002 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -07001003 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001004
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001005 case DOUBLE_PREC_FLOAT: /* 27 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001006#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001007 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +07001008 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001009#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1010 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -07001011 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001012
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001013 case CBOR_SIMPLEV_FALSE: /* 20 */
1014 case CBOR_SIMPLEV_TRUE: /* 21 */
1015 case CBOR_SIMPLEV_NULL: /* 22 */
1016 case CBOR_SIMPLEV_UNDEF: /* 23 */
1017 case CBOR_SIMPLE_BREAK: /* 31 */
1018 break; /* nothing to do */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001019
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001020 case CBOR_SIMPLEV_ONEBYTE: /* 24 */
1021 if(uArgument <= CBOR_SIMPLE_BREAK) {
1022 /* This takes out f8 00 ... f8 1f which should be encoded
1023 * as e0 … f7
1024 */
1025 uReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001026 goto Done;
1027 }
Laurence Lundblade5e390822019-01-06 12:35:01 -08001028 /* FALLTHROUGH */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001029
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001030 default: /* 0-19 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001031 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001032 /* DecodeHead() will make uArgument equal to
1033 * nAdditionalInfo when nAdditionalInfo is < 24. This cast is
1034 * safe because the 2, 4 and 8 byte lengths of uNumber are in
1035 * the double/float cases above
Laurence Lundbladeee851742020-01-08 08:37:05 -08001036 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001037 pDecodedItem->val.uSimple = (uint8_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001038 break;
1039 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001040
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001041Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001042 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001043}
1044
1045
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001046/**
1047 * @brief Decode text and byte strings
1048 *
1049 * @param[in] pAllocator The string allocator or NULL.
1050 * @param[in] uStrLen The length of the string.
1051 * @param[in] pUInBuf The surce from which to read the string's bytes.
1052 * @param[out] pDecodedItem The filled in decoded item.
1053 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001054 * @retval QCBOR_ERR_HIT_END Unexpected end of input.
1055 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1056 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001057 *
1058 * The reads @c uStrlen bytes from @c pUInBuf and fills in @c
1059 * pDecodedItem. If @c pAllocator is not NULL then memory for the
1060 * string is allocated.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001061 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001062static QCBORError
1063QCBOR_Private_DecodeBytes(const QCBORInternalAllocator *pAllocator,
1064 const uint64_t uStrLen,
1065 UsefulInputBuf *pUInBuf,
1066 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001067{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001068 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001069
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001070 /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
1071 * CPUs. This check makes the casts to size_t below safe.
1072 *
1073 * The max is 4 bytes less than the largest sizeof() so this can be
1074 * tested by putting a SIZE_MAX length in the CBOR test input (no
1075 * one will care the limit on strings is 4 bytes shorter).
1076 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001077 if(uStrLen > SIZE_MAX-4) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001078 uReturn = QCBOR_ERR_STRING_TOO_LONG;
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001079 goto Done;
1080 }
1081
1082 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301083 if(UsefulBuf_IsNULLC(Bytes)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001084 /* Failed to get the bytes for this string item */
1085 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301086 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001087 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301088
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001089#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001090 /* Note that this is not where allocation to coalesce
1091 * indefinite-length strings is done. This is for when the caller
1092 * has requested all strings be allocated. Disabling indefinite
1093 * length strings also disables this allocate-all option.
1094 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001095 if(pAllocator) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001096 /* request to use the string allocator to make a copy */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001097 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301098 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001099 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301100 goto Done;
1101 }
1102 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001103 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001104 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301105 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001106#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1107 (void)pAllocator;
1108#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1109
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001110 /* Normal case with no string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001111 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001112
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301113Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001114 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001115}
1116
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001117
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001118/**
1119 * @brief Map the CBOR major types for strings to the QCBOR types.
1120 *
1121 * @param[in] nCBORMajorType The CBOR major type to convert.
1122 * @retturns QCBOR type number.
1123 *
1124 * This only works for the two string types.
1125 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001126static uint8_t
1127QCBOR_Private_ConvertStringMajorTypes(int nCBORMajorType)
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001128{
1129 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
1130 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
1131 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001132
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001133 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
1134 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
1135 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001136
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001137 return (uint8_t)(nCBORMajorType + 4);
1138}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001139
1140
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001141/**
1142 * @brief Map the CBOR major types for arrays/maps to the QCBOR types.
1143 *
1144 * @param[in] nCBORMajorType The CBOR major type to convert.
1145 * @retturns QCBOR type number.
1146 *
1147 * This only works for the two aggregate types.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001148 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001149static uint8_t
1150QCBORDecode_Private_ConvertArrayOrMapType(int nCBORMajorType)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001151{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001152 #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
1153 #error QCBOR_TYPE_ARRAY value not lined up with major type
1154 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001155
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001156 #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
1157 #error QCBOR_TYPE_MAP value not lined up with major type
1158 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001159
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001160 return (uint8_t)(nCBORMajorType);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001161}
1162
1163
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001164/**
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001165 * @brief Decode a single primitive data item (decode layer 6).
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001166 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001167 * @param[in] pUInBuf Input buffer to read data item from.
1168 * @param[out] pDecodedItem The filled-in decoded item.
1169 * @param[in] pAllocator The allocator to use for strings or NULL.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001170 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001171 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1172 * features
1173 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1174 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1175 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1176 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
1177 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1178 * of half-precision disabled
1179 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1180 * float decode is disabled.
1181 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1182 * simple type in input.
1183 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1184 * in input, but indefinite
1185 * lengths disabled.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001186 *
1187 * This decodes the most primitive / atomic data item. It does
1188 * no combing of data items.
1189 */
1190static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001191QCBOR_Private_DecodeAtomicDataItem(UsefulInputBuf *pUInBuf,
1192 QCBORItem *pDecodedItem,
1193 const QCBORInternalAllocator *pAllocator)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001194{
1195 QCBORError uReturn;
1196
1197 /* Get the major type and the argument. The argument could be
1198 * length of more bytes or the value depending on the major
1199 * type. nAdditionalInfo is an encoding of the length of the
1200 * uNumber and is needed to decode floats and doubles.
1201 */
1202 int nMajorType = 0;
1203 uint64_t uArgument = 0;
1204 int nAdditionalInfo = 0;
1205
1206 memset(pDecodedItem, 0, sizeof(QCBORItem));
1207
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001208 uReturn = QCBOR_Private_DecodeHead(pUInBuf, &nMajorType, &uArgument, &nAdditionalInfo);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001209 if(uReturn) {
1210 goto Done;
1211 }
1212
1213 /* At this point the major type and the argument are valid. We've
1214 * got the type and the argument that starts every CBOR data item.
1215 */
1216 switch (nMajorType) {
1217 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1218 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
1219 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1220 uReturn = QCBOR_ERR_BAD_INT;
1221 } else {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001222 uReturn = QCBOR_Private_DecodeInteger(nMajorType, uArgument, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001223 }
1224 break;
1225
1226 case CBOR_MAJOR_TYPE_BYTE_STRING: /* Major type 2 */
1227 case CBOR_MAJOR_TYPE_TEXT_STRING: /* Major type 3 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001228 pDecodedItem->uDataType = QCBOR_Private_ConvertStringMajorTypes(nMajorType);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001229 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1230 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
1231 } else {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001232 uReturn = QCBOR_Private_DecodeBytes(pAllocator, uArgument, pUInBuf, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001233 }
1234 break;
1235
1236 case CBOR_MAJOR_TYPE_ARRAY: /* Major type 4 */
1237 case CBOR_MAJOR_TYPE_MAP: /* Major type 5 */
1238 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1239 /* Indefinite-length string. */
1240#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
1241 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
1242#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1243 uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
1244 break;
1245#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1246 } else {
1247 /* Definite-length string. */
1248 if(uArgument > QCBOR_MAX_ITEMS_IN_ARRAY) {
1249 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
1250 goto Done;
1251 }
1252 /* cast OK because of check above */
1253 pDecodedItem->val.uCount = (uint16_t)uArgument;
1254 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001255 pDecodedItem->uDataType = QCBORDecode_Private_ConvertArrayOrMapType(nMajorType);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001256 break;
1257
1258 case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */
Laurence Lundblade37286c02022-09-03 10:05:02 -07001259#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001260 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1261 uReturn = QCBOR_ERR_BAD_INT;
1262 } else {
1263 pDecodedItem->val.uTagV = uArgument;
1264 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
1265 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07001266#else /* QCBOR_DISABLE_TAGS */
1267 uReturn = QCBOR_ERR_TAGS_DISABLED;
1268#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001269 break;
1270
1271 case CBOR_MAJOR_TYPE_SIMPLE:
1272 /* Major type 7: float, double, true, false, null... */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001273 uReturn = QCBOR_Private_DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001274 break;
1275
1276 default:
1277 /* Never happens because DecodeHead() should never return > 7 */
1278 uReturn = QCBOR_ERR_UNSUPPORTED;
1279 break;
1280 }
1281
1282Done:
1283 return uReturn;
1284}
1285
1286
1287/**
1288 * @brief Process indefinite-length strings (decode layer 5).
1289 *
1290 * @param[in] pMe Decoder context
1291 * @param[out] pDecodedItem The decoded item that work is done on.
1292 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001293 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1294 * features
1295 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1296 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1297 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1298 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
1299 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1300 * of half-precision disabled
1301 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1302 * float decode is disabled.
1303 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1304 * simple type in input.
1305 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1306 * in input, but indefinite
1307 * lengths disabled.
1308 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Indefinite-length string in input,
1309 * but no string allocator.
1310 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK Error in indefinite-length string.
1311 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED Indefinite-length string in
1312 * input, but indefinite-length
1313 * strings are disabled.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001314 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001315 * If @c pDecodedItem is not an indefinite-length string, this does nothing.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001316 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001317 * If it is, this loops getting the subsequent chunk data items that
1318 * make up the string. The string allocator is used to make a
1319 * contiguous buffer for the chunks. When this completes @c
1320 * pDecodedItem contains the put-together string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001321 *
1322 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001323 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001324static QCBORError
1325QCBORDecode_Private_GetNextFullString(QCBORDecodeContext *pMe,
1326 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001327{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001328 /* Aproximate stack usage
1329 * 64-bit 32-bit
1330 * local vars 32 16
1331 * 2 UsefulBufs 32 16
1332 * QCBORItem 56 52
1333 * TOTAL 120 74
1334 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001335
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001336 /* The string allocator is used here for two purposes: 1)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001337 * coalescing the chunks of an indefinite-length string, 2)
1338 * allocating storage for every string returned when requested.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001339 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001340 * The first use is below in this function. Indefinite-length
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001341 * strings cannot be processed at all without a string allocator.
1342 *
1343 * The second used is in DecodeBytes() which is called by
1344 * GetNext_Item() below. This second use unneccessary for most use
1345 * and only happens when requested in the call to
1346 * QCBORDecode_SetMemPool(). If the second use not requested then
1347 * NULL is passed for the string allocator to GetNext_Item().
1348 *
1349 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1350 * allocator altogether and thus both of these uses. It reduced the
1351 * decoder object code by about 400 bytes.
1352 */
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001353 const QCBORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001354
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001355#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001356 const QCBORInternalAllocator *pAllocator = NULL;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001357
1358 if(pMe->StringAllocator.pfAllocator) {
1359 pAllocator = &(pMe->StringAllocator);
1360 if(pMe->bStringAllocateAll) {
1361 pAllocatorForGetNext = pAllocator;
1362 }
1363 }
1364#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1365
1366 QCBORError uReturn;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001367 uReturn = QCBOR_Private_DecodeAtomicDataItem(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001368 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001369 goto Done;
1370 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001371
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001372 /* Only do indefinite-length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001373 const uint8_t uStringType = pDecodedItem->uDataType;
1374 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001375 goto Done;
1376 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001377
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001378 /* Is this a string with an indefinite length? */
1379 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1380 goto Done;
1381 }
1382
1383#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001384 /* Can't decode indefinite-length strings without a string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001385 if(pAllocator == NULL) {
1386 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1387 goto Done;
1388 }
1389
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001390 /* Loop getting chunks of the indefinite-length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001391 UsefulBufC FullString = NULLUsefulBufC;
1392
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001393 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001394 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001395 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001396 /* Pass a NULL string allocator to GetNext_Item() because the
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001397 * individual string chunks in an indefinite-length should not
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001398 * be allocated. They are always copied in the the contiguous
1399 * buffer allocated here.
1400 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001401 uReturn = QCBOR_Private_DecodeAtomicDataItem(&(pMe->InBuf), &StringChunkItem, NULL);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001402 if(uReturn) {
1403 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001404 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001405
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001406 /* Is item is the marker for end of the indefinite-length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001407 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001408 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001409 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301410 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001411 break;
1412 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001413
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001414 /* All chunks must be of the same type, the type of the item
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001415 * that introduces the indefinite-length string. This also
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001416 * catches errors where the chunk is not a string at all and an
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001417 * indefinite-length string inside an indefinite-length string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001418 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001419 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001420 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1421 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001422 break;
1423 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001424
David Navarro9123e5b2022-03-28 16:04:03 +02001425 if (StringChunkItem.val.string.len > 0) {
1426 /* The first time throurgh FullString.ptr is NULL and this is
1427 * equivalent to StringAllocator_Allocate(). Subsequently it is
1428 * not NULL and a reallocation happens.
1429 */
1430 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1431 FullString.ptr,
1432 FullString.len + StringChunkItem.val.string.len);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001433
David Navarro9123e5b2022-03-28 16:04:03 +02001434 if(UsefulBuf_IsNULL(NewMem)) {
1435 uReturn = QCBOR_ERR_STRING_ALLOCATE;
1436 break;
1437 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001438
David Navarro9123e5b2022-03-28 16:04:03 +02001439 /* Copy new string chunk to the end of accumulated string */
1440 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001441 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001442 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001443
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001444 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1445 /* Getting the item failed, clean up the allocated memory */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001446 StringAllocator_Free(pAllocator, FullString.ptr);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001447 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001448#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1449 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1450#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001451
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001452Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001453 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001454}
1455
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001456
Laurence Lundblade37286c02022-09-03 10:05:02 -07001457#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001458/**
1459 * @brief This converts a tag number to a shorter mapped value for storage.
1460 *
1461 * @param[in] pMe The decode context.
1462 * @param[in] uUnMappedTag The tag number to map
1463 * @param[out] puMappedTagNumer The stored tag number.
1464 *
1465 * @return error code.
1466 *
1467 * The main point of mapping tag numbers is make QCBORItem
1468 * smaller. With this mapping storage of 4 tags takes up 8
1469 * bytes. Without, it would take up 32 bytes.
1470 *
1471 * This maps tag numbers greater than QCBOR_LAST_UNMAPPED_TAG.
1472 * QCBOR_LAST_UNMAPPED_TAG is a little smaller than MAX_UINT16.
1473 *
1474 * See also UnMapTagNumber() and @ref QCBORItem.
1475 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001476static QCBORError
1477QCBORDecode_Private_MapTagNumber(QCBORDecodeContext *pMe,
1478 const uint64_t uUnMappedTag,
1479 uint16_t *puMappedTagNumer)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001480{
1481 if(uUnMappedTag > QCBOR_LAST_UNMAPPED_TAG) {
1482 unsigned uTagMapIndex;
1483 /* Is there room in the tag map, or is it in it already? */
1484 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
1485 if(pMe->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID64) {
1486 break;
1487 }
1488 if(pMe->auMappedTags[uTagMapIndex] == uUnMappedTag) {
1489 break;
1490 }
1491 }
1492 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1493 return QCBOR_ERR_TOO_MANY_TAGS;
1494 }
1495
1496 /* Covers the cases where tag is new and were it is already in the map */
1497 pMe->auMappedTags[uTagMapIndex] = uUnMappedTag;
1498 *puMappedTagNumer = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
1499
1500 } else {
1501 *puMappedTagNumer = (uint16_t)uUnMappedTag;
1502 }
1503
1504 return QCBOR_SUCCESS;
1505}
1506
1507
1508/**
1509 * @brief This converts a mapped tag number to the actual tag number.
1510 *
1511 * @param[in] pMe The decode context.
1512 * @param[in] uMappedTagNumber The stored tag number.
1513 *
1514 * @return The actual tag number is returned or
1515 * @ref CBOR_TAG_INVALID64 on error.
1516 *
1517 * This is the reverse of MapTagNumber()
1518 */
1519static uint64_t
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001520QCBORDecode_Private_UnMapTagNumber(const QCBORDecodeContext *pMe,
1521 const uint16_t uMappedTagNumber)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001522{
1523 if(uMappedTagNumber <= QCBOR_LAST_UNMAPPED_TAG) {
1524 return uMappedTagNumber;
1525 } else if(uMappedTagNumber == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001526 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001527 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001528 /* This won't be negative because of code below in
1529 * MapTagNumber()
1530 */
1531 const unsigned uIndex = uMappedTagNumber - (QCBOR_LAST_UNMAPPED_TAG + 1);
1532 return pMe->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001533 }
1534}
Laurence Lundblade37286c02022-09-03 10:05:02 -07001535#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001536
Laurence Lundblade9b334962020-08-27 10:55:53 -07001537
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001538/**
1539 * @brief Aggregate all tags wrapping a data item (decode layer 4).
1540 *
1541 * @param[in] pMe Decoder context
1542 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001543 *
1544 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1545 * features
1546 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1547 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1548 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1549 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
1550 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1551 * of half-precision disabled
1552 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1553 * float decode is disabled.
1554 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1555 * simple type in input.
1556 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1557 * in input, but indefinite
1558 * lengths disabled.
1559 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Indefinite-length string in input,
1560 * but no string allocator.
1561 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK Error in indefinite-length string.
1562 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED Indefinite-length string in
1563 * input, but indefinite-length
1564 * strings are disabled.
1565 * @retval QCBOR_ERR_TOO_MANY_TAGS Too many tag numbers on item.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001566 *
1567 * This loops getting atomic data items until one is not a tag
1568 * number. Usually this is largely pass-through because most
1569 * item are not tag numbers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001570 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001571static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001572QCBORDecode_Private_GetNextTagNumber(QCBORDecodeContext *pMe,
1573 QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001574{
Laurence Lundblade37286c02022-09-03 10:05:02 -07001575#ifndef QCBOR_DISABLE_TAGS
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001576 /* Accummulate the tags from multiple items here and then copy them
1577 * into the last item, the non-tag item.
1578 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001579 uint16_t auItemsTags[QCBOR_MAX_TAGS_PER_ITEM];
1580
1581 /* Initialize to CBOR_TAG_INVALID16 */
1582 #if CBOR_TAG_INVALID16 != 0xffff
1583 /* Be sure the memset does the right thing. */
1584 #err CBOR_TAG_INVALID16 tag not defined as expected
1585 #endif
1586 memset(auItemsTags, 0xff, sizeof(auItemsTags));
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001587
Laurence Lundblade9b334962020-08-27 10:55:53 -07001588 QCBORError uReturn = QCBOR_SUCCESS;
1589
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001590 /* Loop fetching data items until the item fetched is not a tag */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001591 for(;;) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001592 QCBORError uErr = QCBORDecode_Private_GetNextFullString(pMe, pDecodedItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07001593 if(uErr != QCBOR_SUCCESS) {
1594 uReturn = uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001595 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001596 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001597
Laurence Lundblade9b334962020-08-27 10:55:53 -07001598 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001599 /* Successful exit from loop; maybe got some tags, maybe not */
1600 memcpy(pDecodedItem->uTags, auItemsTags, sizeof(auItemsTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001601 break;
1602 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001603
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001604 if(auItemsTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1605 /* No room in the tag list */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001606 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001607 /* Continue on to get all tags wrapping this item even though
1608 * it is erroring out in the end. This allows decoding to
1609 * continue. This is a resource limit error, not a problem
1610 * with being well-formed CBOR.
1611 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001612 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001613 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001614 /* Slide tags over one in the array to make room at index 0.
1615 * Must use memmove because the move source and destination
1616 * overlap.
1617 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001618 memmove(&auItemsTags[1],
1619 auItemsTags,
1620 sizeof(auItemsTags) - sizeof(auItemsTags[0]));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001621
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001622 /* Map the tag */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001623 uint16_t uMappedTagNumber = 0;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001624 uReturn = QCBORDecode_Private_MapTagNumber(pMe, pDecodedItem->val.uTagV, &uMappedTagNumber);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001625 /* Continue even on error so as to consume all tags wrapping
1626 * this data item so decoding can go on. If MapTagNumber()
1627 * errors once it will continue to error.
1628 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001629 auItemsTags[0] = uMappedTagNumber;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001630 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001631
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001632Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001633 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001634
Laurence Lundblade37286c02022-09-03 10:05:02 -07001635#else /* QCBOR_DISABLE_TAGS */
1636
1637 return QCBORDecode_GetNextFullString(pMe, pDecodedItem);
1638
1639#endif /* QCBOR_DISABLE_TAGS */
1640}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001641
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001642
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001643/**
1644 * @brief Combine a map entry label and value into one item (decode layer 3).
1645 *
1646 * @param[in] pMe Decoder context
1647 * @param[out] pDecodedItem The decoded item that work is done on.
1648 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001649 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1650 * features
1651 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1652 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1653 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1654 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
1655 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1656 * of half-precision disabled
1657 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1658 * float decode is disabled.
1659 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1660 * simple type in input.
1661 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1662 * in input, but indefinite
1663 * lengths disabled.
1664 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Indefinite-length string in input,
1665 * but no string allocator.
1666 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK Error in indefinite-length string.
1667 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED Indefinite-length string in
1668 * input, but indefinite-length
1669 * strings are disabled.
1670 * @retval QCBOR_ERR_TOO_MANY_TAGS Too many tag numbers on item.
1671 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG Too many items in array.
1672 * @retval QCBOR_ERR_MAP_LABEL_TYPE Map label not string or integer.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001673 *
1674 * If a the current nesting level is a map, then this
1675 * combines pairs of items into one data item with a label
1676 * and value.
1677 *
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07001678 * This is passthrough if the current nesting level is
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001679 * not a map.
1680 *
1681 * This also implements maps-as-array mode where a map
1682 * is treated like an array to allow caller to do their
1683 * own label processing.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001684 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001685static QCBORError
1686QCBORDecode_Private_GetNextMapEntry(QCBORDecodeContext *pMe,
1687 QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001688{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001689 QCBORError uReturn = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001690 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001691 goto Done;
1692 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001693
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001694 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
1695 /* Break can't be a map entry */
1696 goto Done;
1697 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001698
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001699 if(pMe->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1700 /* Normal decoding of maps -- combine label and value into one item. */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001701
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001702 if(DecodeNesting_IsCurrentTypeMap(&(pMe->nesting))) {
1703 /* Save label in pDecodedItem and get the next which will
1704 * be the real data item.
1705 */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001706 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001707 uReturn = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001708 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001709 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001710 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001711
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301712 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001713
1714 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001715 /* strings are always good labels */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001716 pDecodedItem->label.string = LabelItem.val.string;
1717 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001718 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == pMe->uDecodeMode) {
1719 /* It's not a string and we only want strings */
1720 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001721 goto Done;
1722 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1723 pDecodedItem->label.int64 = LabelItem.val.int64;
1724 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1725 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1726 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1727 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1728 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1729 pDecodedItem->label.string = LabelItem.val.string;
1730 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1731 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1732 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001733 /* label is not an int or a string. It is an arrray
1734 * or a float or such and this implementation doesn't handle that.
1735 * Also, tags on labels are ignored.
1736 */
1737 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001738 goto Done;
1739 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001740 }
1741 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001742 /* Decoding of maps as arrays to let the caller decide what to do
1743 * about labels, particularly lables that are not integers or
1744 * strings.
1745 */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001746 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001747 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001748 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001749 goto Done;
1750 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001751 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001752 /* Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2.
1753 * Cast is needed because of integer promotion.
1754 */
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001755 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001756 }
1757 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001758
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001759Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001760 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001761}
1762
1763
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001764#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001765/**
1766 * @brief Peek and see if next data item is a break;
1767 *
1768 * @param[in] pUIB UsefulInputBuf to read from.
1769 * @param[out] pbNextIsBreak Indicate if next was a break or not.
1770 *
1771 * @return Any decoding error.
1772 *
1773 * See if next item is a CBOR break. If it is, it is consumed,
1774 * if not it is not consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001775*/
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001776static QCBORError
1777QCBOR_Private_NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001778{
1779 *pbNextIsBreak = false;
1780 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001781 QCBORItem Peek;
1782 size_t uPeek = UsefulInputBuf_Tell(pUIB);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001783 QCBORError uReturn = QCBOR_Private_DecodeAtomicDataItem(pUIB, &Peek, NULL);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001784 if(uReturn != QCBOR_SUCCESS) {
1785 return uReturn;
1786 }
1787 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001788 /* It is not a break, rewind so it can be processed normally. */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001789 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001790 } else {
1791 *pbNextIsBreak = true;
1792 }
1793 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001794
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001795 return QCBOR_SUCCESS;
1796}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001797#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001798
1799
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001800/**
1801 * @brief Ascend up nesting levels if all items in them have been consumed.
1802 *
1803 * @param[in] pMe The decode context.
1804 * @param[in] bMarkEnd If true mark end of maps/arrays with count of zero.
1805 *
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001806 * An item was just consumed, now figure out if it was the
1807 * end of an array/map map that can be closed out. That
1808 * may in turn close out the above array/map...
Laurence Lundblade642282a2020-06-23 12:00:33 -07001809*/
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001810static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001811QCBORDecode_Private_NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001812{
1813 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001814
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001815 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001816 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1817
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001818 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1819 /* Nesting level is bstr-wrapped CBOR */
1820
1821 /* Ascent for bstr-wrapped CBOR is always by explicit call
1822 * so no further ascending can happen.
1823 */
1824 break;
1825
1826 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1827 /* Level is a definite-length array/map */
1828
1829 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001830 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1831 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001832 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001833 break;
1834 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001835 /* All items in a definite-length array were consumed so it
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001836 * is time to ascend one level. This happens below.
1837 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001838
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001839#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001840 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001841 /* Level is an indefinite-length array/map. */
1842
1843 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001844 bool bIsBreak = false;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001845 uReturn = QCBOR_Private_NextIsBreak(&(pMe->InBuf), &bIsBreak);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001846 if(uReturn != QCBOR_SUCCESS) {
1847 goto Done;
1848 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001849
1850 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001851 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001852 break;
1853 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001854
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001855 /* It was a break in an indefinitelength map / array so
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001856 * it is time to ascend one level.
1857 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001858
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001859#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001860 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001861
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001862
1863 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001864
Laurence Lundblade93d89472020-10-03 22:30:50 -07001865 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001866 * QCBORDecode_ExitBoundedMode().
1867 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001868 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001869 /* Set the count to zero for definite-length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001870 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001871 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001872 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001873 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001874
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001875 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001876 break;
1877 }
1878
1879 /* Finally, actually ascend one level. */
1880 DecodeNesting_Ascend(&(pMe->nesting));
1881 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001882
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001883 uReturn = QCBOR_SUCCESS;
1884
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001885#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001886Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001887#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1888
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001889 return uReturn;
1890}
1891
1892
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001893/**
1894 * @brief Ascending & Descending out of nesting levels (decode layer 2).
1895 *
1896 * @param[in] pMe Decoder context
1897 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001898
1899 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1900 * features
1901 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1902 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1903 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1904 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
1905 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1906 * of half-precision disabled
1907 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1908 * float decode is disabled.
1909 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1910 * simple type in input.
1911 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1912 * in input, but indefinite
1913 * lengths disabled.
1914 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Indefinite-length string in input,
1915 * but no string allocator.
1916 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK Error in indefinite-length string.
1917 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED Indefinite-length string in
1918 * input, but indefinite-length
1919 * strings are disabled.
1920 * @retval QCBOR_ERR_TOO_MANY_TAGS Too many tag numbers on item.
1921 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG Too many items in array.
1922 * @retval QCBOR_ERR_MAP_LABEL_TYPE Map label not string or integer.
1923 * @retval QCBOR_ERR_NO_MORE_ITEMS Need more items for map or array.
1924 * @retval QCBOR_ERR_BAD_BREAK Indefinite-length break in wrong
1925 * place.
1926 * @retval QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP Nesting deeper than QCBOR
1927 * can handle.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001928 *
1929 * This handles the traversal descending into and asecnding out of
1930 * maps, arrays and bstr-wrapped CBOR. It figures out the ends of
1931 * definite- and indefinte-length maps and arrays by looking at the
1932 * item count or finding CBOR breaks. It detects the ends of the
1933 * top-level sequence and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001934 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001935static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001936QCBORDecode_Private_GetNextMapOrArray(QCBORDecodeContext *pMe,
1937 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001938{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001939 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001940 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001941
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001942 /* If out of bytes to consume, it is either the end of the
1943 * top-level sequence of some bstr-wrapped CBOR that was entered.
1944 *
1945 * In the case of bstr-wrapped CBOR, the length of the
1946 * UsefulInputBuf was set to that of the bstr-wrapped CBOR. When
1947 * the bstr-wrapped CBOR is exited, the length is set back to the
1948 * top-level's length or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001949 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001950 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001951 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001952 goto Done;
1953 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001954
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001955 /* Check to see if at the end of a bounded definite-length map or
1956 * array. The check for a break ending indefinite-length array is
1957 * later in QCBORDecode_NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001958 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001959 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001960 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001961 goto Done;
1962 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001963
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001964 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001965 uReturn = QCBORDecode_Private_GetNextMapEntry(pMe, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001966 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1967 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001968 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001969 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301970
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001971 /* Breaks ending arrays/maps are processed later in the call to
1972 * QCBORDecode_NestLevelAscender(). They should never show up here.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001973 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301974 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001975 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301976 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301977 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001978
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001979 /* Record the nesting level for this data item before processing
1980 * any of decrementing and descending.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001981 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001982 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001983
Laurence Lundblade642282a2020-06-23 12:00:33 -07001984
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001985 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001986 if(QCBORItem_IsMapOrArray(*pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001987 /* If the new item is a map or array, descend.
1988 *
1989 * Empty indefinite-length maps and arrays are descended into,
1990 * but then ascended out of in the next chunk of code.
1991 *
1992 * Maps and arrays do count as items in the map/array that
1993 * encloses them so a decrement needs to be done for them too,
1994 * but that is done only when all the items in them have been
1995 * processed, not when they are opened with the exception of an
1996 * empty map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001997 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001998 QCBORError uDescendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001999 uDescendErr = DecodeNesting_DescendMapOrArray(&(pMe->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07002000 pDecodedItem->uDataType,
2001 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002002 if(uDescendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002003 /* This error is probably a traversal error and it overrides
2004 * the non-traversal error.
2005 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002006 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002007 goto Done;
2008 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07002009 }
2010
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002011 if(!QCBORItem_IsMapOrArray(*pDecodedItem) ||
2012 QCBORItem_IsEmptyDefiniteLengthMapOrArray(*pDecodedItem) ||
2013 QCBORItem_IsIndefiniteLengthMapOrArray(*pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002014 /* The following cases are handled here:
2015 * - A non-aggregate item like an integer or string
2016 * - An empty definite-length map or array
2017 * - An indefinite-length map or array that might be empty or might not.
2018 *
2019 * QCBORDecode_NestLevelAscender() does the work of decrementing the count
2020 * for an definite-length map/array and break detection for an
2021 * indefinite-0length map/array. If the end of the map/array was
2022 * reached, then it ascends nesting levels, possibly all the way
2023 * to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002024 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002025 QCBORError uAscendErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002026 uAscendErr = QCBORDecode_Private_NestLevelAscender(pMe, true);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002027 if(uAscendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002028 /* This error is probably a traversal error and it overrides
2029 * the non-traversal error.
2030 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002031 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002032 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07002033 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05302034 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002035
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07002036 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002037 /* Tell the caller what level is next. This tells them what
2038 * maps/arrays were closed out and makes it possible for them to
2039 * reconstruct the tree with just the information returned in a
2040 * QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07002041 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002042 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07002043 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002044 pDecodedItem->uNextNestLevel = 0;
2045 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002046 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002047 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002048
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002049Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002050 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002051}
2052
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002053
Laurence Lundblade37286c02022-09-03 10:05:02 -07002054#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002055/**
2056 * @brief Shift 0th tag out of the tag list.
2057 *
2058 * pDecodedItem[in,out] The data item to convert.
2059 *
2060 * The 0th tag is discarded. \ref CBOR_TAG_INVALID16 is
2061 * shifted into empty slot at the end of the tag list.
2062 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002063static void
2064QCBOR_Private_ShiftTags(QCBORItem *pDecodedItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002065{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002066 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM-1; i++) {
2067 pDecodedItem->uTags[i] = pDecodedItem->uTags[i+1];
2068 }
2069 pDecodedItem->uTags[QCBOR_MAX_TAGS_PER_ITEM-1] = CBOR_TAG_INVALID16;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002070}
Laurence Lundblade37286c02022-09-03 10:05:02 -07002071#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002072
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07002073
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002074/**
2075 * @brief Convert different epoch date formats in to the QCBOR epoch date format
2076 *
2077 * pDecodedItem[in,out] The data item to convert.
2078 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07002079 * @retval QCBOR_ERR_DATE_OVERFLOW 65-bit negative integer.
2080 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED Float-point date in input,
2081 * floating-point date disabled.
2082 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point date in input,
2083 * all floating-point disabled.
2084 * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT Unexpected and unrecoverable
2085 * error decoding date.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002086 *
2087 * The epoch date tag defined in QCBOR allows for floating-point
2088 * dates. It even allows a protocol to flop between date formats when
2089 * ever it wants. Floating-point dates aren't that useful as they are
2090 * only needed for dates beyond the age of the earth.
2091 *
2092 * This converts all the date formats into one format of an unsigned
2093 * integer plus a floating-point fraction.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002094 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002095static QCBORError
2096QCBOR_Private_DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002097{
Laurence Lundbladec7114722020-08-13 05:11:40 -07002098 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002099
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002100#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade59289e52019-12-30 13:44:37 -08002101 pDecodedItem->val.epochDate.fSecondsFraction = 0;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002102#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002103
2104 switch (pDecodedItem->uDataType) {
2105
2106 case QCBOR_TYPE_INT64:
2107 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
2108 break;
2109
2110 case QCBOR_TYPE_UINT64:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002111 /* This only happens for CBOR type 0 > INT64_MAX so it is
2112 * always an overflow.
2113 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002114 uReturn = QCBOR_ERR_DATE_OVERFLOW;
2115 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002116 break;
2117
2118 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07002119 case QCBOR_TYPE_FLOAT:
2120#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08002121 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002122 /* Convert working value to double if input was a float */
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07002123 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002124 pDecodedItem->val.dfnum :
2125 (double)pDecodedItem->val.fnum;
2126
2127 /* The conversion from float to integer requires overflow
2128 * detection since floats can be much larger than integers.
2129 * This implementation errors out on these large float values
2130 * since they are beyond the age of the earth.
2131 *
2132 * These constants for the overflow check are computed by the
2133 * compiler. They are not computed at run time.
2134 *
2135 * The factor of 0x7ff is added/subtracted to avoid a
2136 * rounding error in the wrong direction when the compiler
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002137 * computes these constants. There is rounding because a
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002138 * 64-bit integer has 63 bits of precision where a double
2139 * only has 53 bits. Without the 0x7ff factor, the compiler
2140 * may round up and produce a double for the bounds check
2141 * that is larger than can be stored in a 64-bit integer. The
2142 * amount of 0x7ff is picked because it has 11 bits set.
2143 *
2144 * Without the 0x7ff there is a ~30 minute range of time
2145 * values 10 billion years in the past and in the future
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002146 * where this code could go wrong. Some compilers
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002147 * generate a warning or error without the 0x7ff.
2148 */
2149 const double dDateMax = (double)(INT64_MAX - 0x7ff);
2150 const double dDateMin = (double)(INT64_MIN + 0x7ff);
2151
2152 if(isnan(d) || d > dDateMax || d < dDateMin) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07002153 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002154 goto Done;
2155 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002156
2157 /* The actual conversion */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002158 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07002159 pDecodedItem->val.epochDate.fSecondsFraction =
2160 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002161 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002162#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade4b270642020-08-14 12:53:07 -07002163
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002164 uReturn = QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07002165 goto Done;
2166
Laurence Lundblade9682a532020-06-06 18:33:04 -07002167#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002168 break;
2169
2170 default:
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002171 /* It's the arrays and maps that are unrecoverable because
2172 * they are not consumed here. Since this is just an error
2173 * condition, no extra code is added here to make the error
2174 * recoverable for non-arrays and maps like strings. */
2175 uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002176 goto Done;
2177 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002178
Laurence Lundblade59289e52019-12-30 13:44:37 -08002179 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
2180
2181Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07002182 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002183}
2184
2185
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002186/**
2187 * @brief Convert the days epoch date.
2188 *
2189 * pDecodedItem[in,out] The data item to convert.
2190 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07002191 * @retval QCBOR_ERR_DATE_OVERFLOW 65-bit negative integer.
2192 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED Float-point date in input,
2193 * floating-point date disabled.
2194 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point date in input,
2195 * all floating-point disabled.
2196 * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT Unexpected and unrecoverable
2197 * error decoding date.
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002198 *
2199 * This is much simpler than the other epoch date format because
2200 * floating-porint is not allowed. This is mostly a simple type check.
2201 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002202static QCBORError
2203QCBOR_Private_DecodeDaysEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002204{
2205 QCBORError uReturn = QCBOR_SUCCESS;
2206
2207 switch (pDecodedItem->uDataType) {
2208
2209 case QCBOR_TYPE_INT64:
2210 pDecodedItem->val.epochDays = pDecodedItem->val.int64;
2211 break;
2212
2213 case QCBOR_TYPE_UINT64:
2214 /* This only happens for CBOR type 0 > INT64_MAX so it is
2215 * always an overflow.
2216 */
2217 uReturn = QCBOR_ERR_DATE_OVERFLOW;
2218 goto Done;
2219 break;
2220
2221 default:
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002222 /* It's the arrays and maps that are unrecoverable because
2223 * they are not consumed here. Since this is just an error
2224 * condition, no extra code is added here to make the error
2225 * recoverable for non-arrays and maps like strings. */
2226 uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002227 goto Done;
2228 break;
2229 }
2230
2231 pDecodedItem->uDataType = QCBOR_TYPE_DAYS_EPOCH;
2232
2233Done:
2234 return uReturn;
2235}
2236
2237
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002238#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade37286c02022-09-03 10:05:02 -07002239
2240/* Forward declaration is necessary for
2241 * QCBORDecode_MantissaAndExponent(). to be able to decode bignum
2242 * tags in the mantissa. If the mantissa is a decimal fraction or big
2243 * float in error, this will result in a recurive call to
2244 * QCBORDecode_MantissaAndExponent(), but the recursion will unwined
2245 * correctly and the correct error is returned.
2246 */
2247static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002248QCBORDecode_Private_GetNextTagContent(QCBORDecodeContext *pMe,
2249 QCBORItem *pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07002250
2251
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002252/**
2253 * @brief Decode decimal fractions and big floats.
2254 *
2255 * @param[in] pMe The decode context.
2256 * @param[in,out] pDecodedItem On input the array data item that
2257 * holds the mantissa and exponent. On
2258 * output the decoded mantissa and
2259 * exponent.
2260 *
2261 * @returns Decoding errors from getting primitive data items or
2262 * \ref QCBOR_ERR_BAD_EXP_AND_MANTISSA.
2263 *
Laurence Lundblade37286c02022-09-03 10:05:02 -07002264 * When called pDecodedItem must be the array with two members, the
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002265 * exponent and mantissa.
2266 *
2267 * This will fetch and decode the exponent and mantissa and put the
2268 * result back into pDecodedItem.
Laurence Lundblade37286c02022-09-03 10:05:02 -07002269 *
2270 * This does no checking or processing of tag numbers. That is to be
2271 * done by the code that calls this.
2272 *
2273 * This stuffs the type of the mantissa into pDecodedItem with the expectation
2274 * the caller will process it.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002275 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07002276static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002277QCBORDecode_Private_ExpMantissa(QCBORDecodeContext *pMe,
2278 QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002279{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002280 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002281
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002282 /* --- Make sure it is an array; track nesting level of members --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002283 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002284 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002285 goto Done;
2286 }
2287
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002288 /* A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundblade37286c02022-09-03 10:05:02 -07002289 * definite-length arrays, but not for indefinite. Instead remember
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002290 * the nesting level the two integers must be at, which is one
2291 * deeper than that of the array.
2292 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002293 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
2294
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002295 /* --- Get the exponent --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002296 QCBORItem exponentItem;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002297 uReturn = QCBORDecode_Private_GetNextMapOrArray(pMe, &exponentItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002298 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002299 goto Done;
2300 }
2301 if(exponentItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002302 /* Array is empty or a map/array encountered when expecting an int */
2303 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002304 goto Done;
2305 }
2306 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002307 /* Data arriving as an unsigned int < INT64_MAX has been
2308 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2309 * also means that the only data arriving here of type
2310 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2311 * and thus an error that will get handled in the next else.
2312 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002313 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
2314 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002315 /* Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX */
2316 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002317 goto Done;
2318 }
2319
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002320 /* --- Get the mantissa --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002321 QCBORItem mantissaItem;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002322 uReturn = QCBORDecode_Private_GetNextTagContent(pMe, &mantissaItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002323 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002324 goto Done;
2325 }
2326 if(mantissaItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002327 /* Mantissa missing or map/array encountered when expecting number */
2328 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002329 goto Done;
2330 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002331 /* Stuff the mantissa data type into the item to send it up to the
2332 * the next level. */
2333 pDecodedItem->uDataType = mantissaItem.uDataType;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002334 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002335 /* Data arriving as an unsigned int < INT64_MAX has been
2336 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2337 * also means that the only data arriving here of type
2338 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2339 * and thus an error that will get handled in an else below.
2340 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002341 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002342#ifndef QCBOR_DISABLE_TAGS
2343 /* With tags fully disabled a big number mantissa will error out
2344 * in the call to QCBORDecode_GetNextWithTags() because it has
2345 * a tag number.
2346 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002347 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
2348 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002349 /* Got a good big num mantissa */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002350 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002351#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002352 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002353 /* Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX */
2354 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002355 goto Done;
2356 }
2357
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002358 /* --- Check that array only has the two numbers --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002359 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002360 /* Extra items in the decimal fraction / big float */
Laurence Lundblade37286c02022-09-03 10:05:02 -07002361 /* Improvement: this should probably be an unrecoverable error. */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002362 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002363 goto Done;
2364 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002365 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002366
2367Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002368 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002369}
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002370#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002371
2372
Laurence Lundblade37286c02022-09-03 10:05:02 -07002373#ifndef QCBOR_DISABLE_TAGS
2374
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002375#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002376/**
2377 * @brief Decode the MIME type tag
2378 *
2379 * @param[in,out] pDecodedItem The item to decode.
2380 *
2381 * Handle the text and binary MIME type tags. Slightly too complicated
2382 * f or ProcessTaggedString() because the RFC 7049 MIME type was
2383 * incorreclty text-only.
2384 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002385static QCBORError
2386QCBOR_Private_DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002387{
2388 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
2389 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07002390 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002391 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
2392 } else {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002393 /* It's the arrays and maps that are unrecoverable because
2394 * they are not consumed here. Since this is just an error
2395 * condition, no extra code is added here to make the error
2396 * recoverable for non-arrays and maps like strings. */
2397 return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002398 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002399
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002400 return QCBOR_SUCCESS;
2401}
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002402#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002403
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002404/**
Laurence Lundblade99615302020-11-29 11:19:47 -08002405 * Table of CBOR tags whose content is either a text string or a byte
2406 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
2407 * of uQCBORtype indicates the content should be a byte string rather
2408 * than a text string
2409 */
2410struct StringTagMapEntry {
2411 uint16_t uTagNumber;
2412 uint8_t uQCBORtype;
2413};
2414
2415#define IS_BYTE_STRING_BIT 0x80
2416#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
2417
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002418static const struct StringTagMapEntry QCBOR_Private_StringTagMap[] = {
Laurence Lundblade99615302020-11-29 11:19:47 -08002419 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002420 {CBOR_TAG_DAYS_STRING, QCBOR_TYPE_DAYS_STRING},
Laurence Lundblade99615302020-11-29 11:19:47 -08002421 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
2422 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
2423 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
2424 {CBOR_TAG_URI, QCBOR_TYPE_URI},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002425#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002426 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
2427 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
2428 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
2429 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002430#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade99615302020-11-29 11:19:47 -08002431 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
2432 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
2433};
2434
2435
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002436/**
2437 * @brief Process standard CBOR tags whose content is a string
2438 *
2439 * @param[in] uTag The tag.
2440 * @param[in,out] pDecodedItem The data item.
2441 *
2442 * @returns This returns QCBOR_SUCCESS if the tag was procssed,
2443 * \ref QCBOR_ERR_UNSUPPORTED if the tag was not processed and
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002444 * \ref QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT if the content type was wrong for the tag.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002445 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002446 * Process the CBOR tags that whose content is a byte string or a text
2447 * string and for which the string is just passed on to the caller.
2448 *
2449 * This maps the CBOR tag to the QCBOR type and checks the content
2450 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08002451 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08002452 * possible.
Laurence Lundblade99615302020-11-29 11:19:47 -08002453 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002454static QCBORError
2455QCBOR_Private_ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002456{
Laurence Lundblade99615302020-11-29 11:19:47 -08002457 /* This only works on tags that were not mapped; no need for other yet */
2458 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
2459 return QCBOR_ERR_UNSUPPORTED;
2460 }
2461
2462 unsigned uIndex;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002463 for(uIndex = 0; QCBOR_Private_StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
2464 if(QCBOR_Private_StringTagMap[uIndex].uTagNumber == uTag) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002465 break;
2466 }
2467 }
2468
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002469 const uint8_t uQCBORType = QCBOR_Private_StringTagMap[uIndex].uQCBORtype;
Laurence Lundblade99615302020-11-29 11:19:47 -08002470 if(uQCBORType == QCBOR_TYPE_NONE) {
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002471 /* repurpose this error to mean not handled here */
Laurence Lundblade99615302020-11-29 11:19:47 -08002472 return QCBOR_ERR_UNSUPPORTED;
2473 }
2474
2475 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
2476 if(uQCBORType & IS_BYTE_STRING_BIT) {
2477 uExpectedType = QCBOR_TYPE_BYTE_STRING;
2478 }
2479
2480 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002481 /* It's the arrays and maps that are unrecoverable because
2482 * they are not consumed here. Since this is just an error
2483 * condition, no extra code is added here to make the error
2484 * recoverable for non-arrays and maps like strings. */
2485 return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002486 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002487
Laurence Lundblade99615302020-11-29 11:19:47 -08002488 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002489 return QCBOR_SUCCESS;
2490}
Laurence Lundblade37286c02022-09-03 10:05:02 -07002491#endif /* QCBOR_DISABLE_TAGS */
2492
2493
2494#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07002495/**
2496 * @brief Figures out data type for exponent mantissa tags.
2497 *
2498 * @param[in] uTagToProcess Either @ref CBOR_TAG_DECIMAL_FRACTION or
2499 * @ref CBOR_TAG_BIG_FLOAT.
2500 * @param[in] pDecodedItem Item being decoded.
2501 *
2502 * @returns One of the 6 values between \ref QCBOR_TYPE_DECIMAL_FRACTION
2503 * and @ref QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM.
2504 *
2505 * Does mapping between a CBOR tag number and a QCBOR type. with a
2506 * little bit of logic and arithmatic.
2507 *
2508 * Used in serveral contexts. Does the work where sometimes the data
2509 * item is explicitly tagged and sometimes not.
Laurence Lundblade37286c02022-09-03 10:05:02 -07002510 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002511static uint8_t
2512QCBOR_Private_ExpMantissaDataType(const uint16_t uTagToProcess,
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07002513 const QCBORItem *pDecodedItem)
Laurence Lundblade37286c02022-09-03 10:05:02 -07002514{
2515 uint8_t uBase = uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ?
2516 QCBOR_TYPE_DECIMAL_FRACTION :
2517 QCBOR_TYPE_BIGFLOAT;
2518 if(pDecodedItem->uDataType != QCBOR_TYPE_INT64) {
2519 uBase = (uint8_t)(uBase + pDecodedItem->uDataType - QCBOR_TYPE_POSBIGNUM + 1);
2520 }
2521 return uBase;
2522}
2523#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002524
2525
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002526/**
2527 * @brief Decode tag content for select tags (decoding layer 1).
2528 *
2529 * @param[in] pMe The decode context.
2530 * @param[out] pDecodedItem The decoded item.
2531 *
2532 * @return Decoding error code.
2533 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002534 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
2535 * but the whole tag was not decoded. Here, the whole tags (tag number
2536 * and tag content) that are supported by QCBOR are decoded. This is a
2537 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002538 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002539static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002540QCBORDecode_Private_GetNextTagContent(QCBORDecodeContext *pMe,
2541 QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002542{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002543 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002544
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002545 uReturn = QCBORDecode_Private_GetNextMapOrArray(pMe, pDecodedItem);
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002546 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002547 goto Done;
2548 }
2549
Laurence Lundblade37286c02022-09-03 10:05:02 -07002550#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002551 /* When there are no tag numbers for the item, this exits first
2552 * thing and effectively does nothing.
2553 *
2554 * This loops over all the tag numbers accumulated for this item
2555 * trying to decode and interpret them. This stops at the end of
2556 * the list or at the first tag number that can't be interpreted by
2557 * this code. This is effectively a recursive processing of the
2558 * tags number list that handles nested tags.
2559 */
2560 while(1) {
2561 /* Don't bother to unmap tags via QCBORITem.uTags since this
2562 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2563 */
2564 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002565
Laurence Lundblade99615302020-11-29 11:19:47 -08002566 if(uTagToProcess == CBOR_TAG_INVALID16) {
2567 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002568 break;
2569
Laurence Lundblade99615302020-11-29 11:19:47 -08002570 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002571 uReturn = QCBOR_Private_DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002572
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002573 } else if(uTagToProcess == CBOR_TAG_DAYS_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002574 uReturn = QCBOR_Private_DecodeDaysEpoch(pDecodedItem);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002575
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002576#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002577 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2578 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002579 uReturn = QCBORDecode_Private_ExpMantissa(pMe, pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07002580 /* --- Which is it, decimal fraction or a bigfloat? --- */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002581 pDecodedItem->uDataType = QCBOR_Private_ExpMantissaDataType(uTagToProcess, pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07002582
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002583#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002584#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002585 } else if(uTagToProcess == CBOR_TAG_MIME ||
2586 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002587 uReturn = QCBOR_Private_DecodeMIME(pDecodedItem);
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002588#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002589
Laurence Lundblade99615302020-11-29 11:19:47 -08002590 } else {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002591 /* See if it is a passthrough byte/text string tag; process if so */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002592 uReturn = QCBOR_Private_ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002593
Laurence Lundblade99615302020-11-29 11:19:47 -08002594 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002595 /* It wasn't a passthrough byte/text string tag so it is
Laurence Lundblade99615302020-11-29 11:19:47 -08002596 * an unknown tag. This is the exit from the loop on the
2597 * first unknown tag. It is a successful exit.
2598 */
2599 uReturn = QCBOR_SUCCESS;
2600 break;
2601 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002602 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002603
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002604 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002605 /* Error exit from the loop */
2606 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002607 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002608
2609 /* A tag was successfully processed, shift it out of the list of
2610 * tags returned. This is the loop increment.
2611 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002612 QCBOR_Private_ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002613 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002614#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002615
2616Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002617 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002618}
2619
2620
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002621/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002622 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002623 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002624QCBORError
2625QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2626{
2627 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002628 uErr = QCBORDecode_Private_GetNextTagContent(pMe, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002629 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002630 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2631 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2632 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002633 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002634}
2635
2636
2637/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002638 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002639 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002640QCBORError
2641QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2642{
2643 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2644 const UsefulInputBuf Save = pMe->InBuf;
2645
2646 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2647
2648 pMe->nesting = SaveNesting;
2649 pMe->InBuf = Save;
2650
2651 return uErr;
2652}
2653
2654
2655/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002656 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002657 */
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002658void
2659QCBORDecode_VPeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2660{
2661 if(pMe->uLastError != QCBOR_SUCCESS) {
2662 return;
2663 }
2664
2665 pMe->uLastError = (uint8_t)QCBORDecode_PeekNext(pMe, pDecodedItem);
2666}
2667
2668
2669/*
2670 * Public function, see header qcbor/qcbor_decode.h file
2671 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002672void
2673QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002674{
2675 if(pMe->uLastError != QCBOR_SUCCESS) {
2676 return;
2677 }
2678
2679 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2680}
2681
2682
2683/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002684 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002685 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002686QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002687QCBORDecode_GetNextWithTags(QCBORDecodeContext *pMe,
2688 QCBORItem *pDecodedItem,
2689 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002690{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002691#ifndef QCBOR_DISABLE_TAGS
2692
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002693 QCBORError uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002694
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002695 uReturn = QCBORDecode_GetNext(pMe, pDecodedItem);
2696 if(uReturn != QCBOR_SUCCESS) {
2697 return uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002698 }
2699
2700 if(pTags != NULL) {
2701 pTags->uNumUsed = 0;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002702 /* Reverse the order because pTags is reverse of QCBORItem.uTags. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002703 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2704 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002705 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002706 }
2707 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2708 return QCBOR_ERR_TOO_MANY_TAGS;
2709 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002710 pTags->puTags[pTags->uNumUsed] = QCBORDecode_Private_UnMapTagNumber(pMe,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002711 pTags->uNumUsed++;
2712 }
2713 }
2714
2715 return QCBOR_SUCCESS;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002716
2717#else /* QCBOR_DISABLE_TAGS */
2718 (void)pMe;
2719 (void)pDecodedItem;
2720 (void)pTags;
2721 return QCBOR_ERR_TAGS_DISABLED;
2722#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002723}
2724
2725
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002726/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002727 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302728 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002729bool
2730QCBORDecode_IsTagged(QCBORDecodeContext *pMe,
2731 const QCBORItem *pItem,
2732 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002733{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002734#ifndef QCBOR_DISABLE_TAGS
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002735 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2736 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002737 break;
2738 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002739 if(QCBORDecode_Private_UnMapTagNumber(pMe, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002740 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002741 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002742 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002743#else /* QCBOR_TAGS_DISABLED */
2744 (void)pMe;
2745 (void)pItem;
2746 (void)uTag;
2747#endif /* QCBOR_TAGS_DISABLED */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002748
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002749 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002750}
2751
2752
2753/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002754 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002755 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002756QCBORError
2757QCBORDecode_PartialFinish(QCBORDecodeContext *pMe, size_t *puConsumed)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002758{
Laurence Lundblade87495732021-02-26 10:05:55 -07002759 if(puConsumed != NULL) {
2760 *puConsumed = pMe->InBuf.cursor;
2761 }
2762
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002763 QCBORError uReturn = pMe->uLastError;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002764
2765 if(uReturn != QCBOR_SUCCESS) {
2766 goto Done;
2767 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002768
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002769 /* Error out if all the maps/arrays are not closed out */
2770 if(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002771 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002772 goto Done;
2773 }
2774
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002775 /* Error out if not all the bytes are consumed */
2776 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002777 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002778 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002779
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002780Done:
Laurence Lundblade87495732021-02-26 10:05:55 -07002781 return uReturn;
2782}
2783
2784
2785/*
2786 * Public function, see header qcbor/qcbor_decode.h file
2787 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002788QCBORError
2789QCBORDecode_Finish(QCBORDecodeContext *pMe)
Laurence Lundblade87495732021-02-26 10:05:55 -07002790{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002791#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002792 /* Call the destructor for the string allocator if there is one.
2793 * Always called, even if there are errors; always have to clean up.
2794 */
2795 StringAllocator_Destruct(&(pMe->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002796#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002797
Laurence Lundblade87495732021-02-26 10:05:55 -07002798 return QCBORDecode_PartialFinish(pMe, NULL);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002799}
2800
2801
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002802/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002803 * Public function, see header qcbor/qcbor_decode.h file
2804 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002805uint64_t
2806QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2807 const QCBORItem *pItem,
2808 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002809{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002810#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002811 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2812 return CBOR_TAG_INVALID64;
2813 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002814 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2815 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002816 } else {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002817 return QCBORDecode_Private_UnMapTagNumber(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002818 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002819#else /* QCBOR_DISABLE_TAGS */
2820 (void)pMe;
2821 (void)pItem;
2822 (void)uIndex;
2823
2824 return CBOR_TAG_INVALID64;
2825#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002826}
2827
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002828
Laurence Lundblade9b334962020-08-27 10:55:53 -07002829/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002830 * Public function, see header qcbor/qcbor_decode.h file
2831 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002832uint64_t
2833QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2834 uint32_t uIndex)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002835{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002836#ifndef QCBOR_DISABLE_TAGS
2837
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002838 if(pMe->uLastError != QCBOR_SUCCESS) {
2839 return CBOR_TAG_INVALID64;
2840 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002841 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2842 return CBOR_TAG_INVALID64;
2843 } else {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002844 return QCBORDecode_Private_UnMapTagNumber(pMe, pMe->uLastTags[uIndex]);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002845 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002846#else /* QCBOR_DISABLE_TAGS */
2847 (void)pMe;
2848 (void)uIndex;
2849
2850 return CBOR_TAG_INVALID64;
2851#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002852}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002853
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002854
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002855
2856
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002857#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002858
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002859/* ===========================================================================
2860 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002861
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002862 This implements a simple sting allocator for indefinite-length
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002863 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2864 implements the function type QCBORStringAllocate and allows easy
2865 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002866
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002867 This particular allocator is built-in for convenience. The caller
2868 can implement their own. All of this following code will get
2869 dead-stripped if QCBORDecode_SetMemPool() is not called.
2870
2871 This is a very primitive memory allocator. It does not track
2872 individual allocations, only a high-water mark. A free or
2873 reallocation must be of the last chunk allocated.
2874
2875 The size of the pool and offset to free memory are packed into the
2876 first 8 bytes of the memory pool so we don't have to keep them in
2877 the decode context. Since the address of the pool may not be
2878 aligned, they have to be packed and unpacked as if they were
2879 serialized data of the wire or such.
2880
2881 The sizes packed in are uint32_t to be the same on all CPU types
2882 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002883 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002884
2885
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002886static int
Laurence Lundbladeee851742020-01-08 08:37:05 -08002887MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002888{
2889 // Use of UsefulInputBuf is overkill, but it is convenient.
2890 UsefulInputBuf UIB;
2891
Laurence Lundbladeee851742020-01-08 08:37:05 -08002892 // Just assume the size here. It was checked during SetUp so
2893 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002894 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002895 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2896 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2897 return UsefulInputBuf_GetError(&UIB);
2898}
2899
2900
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002901static int
Laurence Lundbladeee851742020-01-08 08:37:05 -08002902MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002903{
2904 // Use of UsefulOutBuf is overkill, but convenient. The
2905 // length check performed here is useful.
2906 UsefulOutBuf UOB;
2907
2908 UsefulOutBuf_Init(&UOB, Pool);
2909 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2910 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2911 return UsefulOutBuf_GetError(&UOB);
2912}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002913
2914
2915/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002916 Internal function for an allocation, reallocation free and destuct.
2917
2918 Having only one function rather than one each per mode saves space in
2919 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002920
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002921 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2922 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002923static UsefulBuf
2924MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002925{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002926 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002927
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002928 uint32_t uPoolSize;
2929 uint32_t uFreeOffset;
2930
2931 if(uNewSize > UINT32_MAX) {
2932 // This allocator is only good up to 4GB. This check should
2933 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2934 goto Done;
2935 }
2936 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2937
2938 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2939 goto Done;
2940 }
2941
2942 if(uNewSize) {
2943 if(pMem) {
2944 // REALLOCATION MODE
2945 // Calculate pointer to the end of the memory pool. It is
2946 // assumed that pPool + uPoolSize won't wrap around by
2947 // assuming the caller won't pass a pool buffer in that is
2948 // not in legitimate memory space.
2949 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2950
2951 // Check that the pointer for reallocation is in the range of the
2952 // pool. This also makes sure that pointer math further down
2953 // doesn't wrap under or over.
2954 if(pMem >= pPool && pMem < pPoolEnd) {
2955 // Offset to start of chunk for reallocation. This won't
2956 // wrap under because of check that pMem >= pPool. Cast
2957 // is safe because the pool is always less than UINT32_MAX
2958 // because of check in QCBORDecode_SetMemPool().
2959 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2960
2961 // Check to see if the allocation will fit. uPoolSize -
2962 // uMemOffset will not wrap under because of check that
2963 // pMem is in the range of the uPoolSize by check above.
2964 if(uNewSize <= uPoolSize - uMemOffset) {
2965 ReturnValue.ptr = pMem;
2966 ReturnValue.len = uNewSize;
2967
2968 // Addition won't wrap around over because uNewSize was
2969 // checked to be sure it is less than the pool size.
2970 uFreeOffset = uMemOffset + uNewSize32;
2971 }
2972 }
2973 } else {
2974 // ALLOCATION MODE
2975 // uPoolSize - uFreeOffset will not underflow because this
2976 // pool implementation makes sure uFreeOffset is always
2977 // smaller than uPoolSize through this check here and
2978 // reallocation case.
2979 if(uNewSize <= uPoolSize - uFreeOffset) {
2980 ReturnValue.len = uNewSize;
2981 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002982 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002983 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002984 }
2985 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002986 if(pMem) {
2987 // FREE MODE
2988 // Cast is safe because of limit on pool size in
2989 // QCBORDecode_SetMemPool()
2990 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2991 } else {
2992 // DESTRUCT MODE
2993 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002994 }
2995 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002996
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002997 UsefulBuf Pool = {pPool, uPoolSize};
2998 MemPool_Pack(Pool, uFreeOffset);
2999
3000Done:
3001 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003002}
3003
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003004
Laurence Lundbladef6531662018-12-04 10:42:22 +09003005/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003006 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09003007 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003008QCBORError
3009QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
3010 UsefulBuf Pool,
3011 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003012{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003013 // The pool size and free mem offset are packed into the beginning
Dave Thaler93c01182022-08-06 15:08:35 -04003014 // of the pool memory. This compile time check makes sure the
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003015 // constant in the header is correct. This check should optimize
3016 // down to nothing.
Dave Thaler93c01182022-08-06 15:08:35 -04003017#ifdef _MSC_VER
3018#pragma warning(push)
3019#pragma warning(disable:4127) // conditional expression is constant
3020#endif
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003021 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003022 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003023 }
Dave Thaler93c01182022-08-06 15:08:35 -04003024#ifdef _MSC_VER
3025#pragma warning(pop)
3026#endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003027
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003028 // The pool size and free offset packed in to the beginning of pool
3029 // memory are only 32-bits. This check will optimize out on 32-bit
3030 // machines.
3031 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003032 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003033 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003034
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003035 // This checks that the pool buffer given is big enough.
3036 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003037 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003038 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003039
Laurence Lundblade3427dee2021-06-20 11:11:24 -07003040 QCBORDecode_SetUpAllocator(pMe, MemPool_Function, Pool.ptr, bAllStrings);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003041
Laurence Lundblade30816f22018-11-10 13:40:22 +07003042 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003043}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08003044#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003045
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003046
3047
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003048static void
3049QCBORDecode_Private_CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07003050{
Laurence Lundblade37286c02022-09-03 10:05:02 -07003051#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade9b334962020-08-27 10:55:53 -07003052 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
Laurence Lundblade37286c02022-09-03 10:05:02 -07003053#else
3054 (void)pMe;
3055 (void)pItem;
3056#endif
Laurence Lundblade9b334962020-08-27 10:55:53 -07003057}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003058
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003059
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003060/**
3061 * @brief Consume an entire map or array including its contents.
3062 *
3063 * @param[in] pMe The decoder context.
3064 * @param[in] pItemToConsume The array/map whose contents are to be
3065 * consumed.
3066 * @param[out] puNextNestLevel The next nesting level after the item was
3067 * fully consumed.
3068 *
3069 * This may be called when @c pItemToConsume is not an array or
3070 * map. In that case, this is just a pass through for @c puNextNestLevel
3071 * since there is nothing to do.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003072 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003073static QCBORError
3074QCBORDecode_Private_ConsumeItem(QCBORDecodeContext *pMe,
3075 const QCBORItem *pItemToConsume,
3076 uint8_t *puNextNestLevel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003077{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003078 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003079 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003080
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003081 /* If it is a map or array, this will tell if it is empty. */
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003082 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
3083
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003084 if(QCBORItem_IsMapOrArray(*pItemToConsume) && !bIsEmpty) {
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003085 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003086
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003087 /* This works for definite- and indefinite-length maps and
3088 * arrays by using the nesting level
Laurence Lundblade1341c592020-04-11 14:19:05 -07003089 */
3090 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003091 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003092 if(QCBORDecode_IsUnrecoverableError(uReturn) ||
3093 uReturn == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003094 goto Done;
3095 }
3096 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003097
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003098 *puNextNestLevel = Item.uNextNestLevel;
3099
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003100 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003101
Laurence Lundblade1341c592020-04-11 14:19:05 -07003102 } else {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003103 /* pItemToConsume is not a map or array. Just pass the nesting
3104 * level through. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003105 *puNextNestLevel = pItemToConsume->uNextNestLevel;
3106
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003107 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003108 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003109
3110Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003111 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003112}
3113
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003114
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003115/*
3116 * Public function, see header qcbor/qcbor_decode.h file
3117 */
3118void
3119QCBORDecode_VGetNextConsume(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003120{
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003121 QCBORDecode_VGetNext(pMe, pDecodedItem);
3122
3123 if(pMe->uLastError == QCBOR_SUCCESS) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003124 pMe->uLastError = (uint8_t)QCBORDecode_Private_ConsumeItem(pMe, pDecodedItem,
Máté Tóth-Pálc6d59682021-05-26 18:55:30 +02003125 &pDecodedItem->uNextNestLevel);
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003126 }
3127}
3128
3129
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003130/**
3131 * @brief Rewind cursor to start as if map or array were just entered.
3132 *
3133 * @param[in] pMe The decoding context
3134 *
3135 * This affects the nesting tracking and the UsefulInputBuf.
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003136 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003137static void
3138QCBORDecode_Private_RewindMapOrArray(QCBORDecodeContext *pMe)
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003139{
3140 /* Reset nesting tracking to the deepest bounded level */
3141 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
3142
3143 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3144
3145 /* Reposition traversal cursor to the start of the map/array */
3146 UsefulInputBuf_Seek(&(pMe->InBuf),
3147 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
3148}
3149
3150
3151/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003152 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003153 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003154void
3155QCBORDecode_Rewind(QCBORDecodeContext *pMe)
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003156{
3157 if(pMe->nesting.pCurrentBounded != NULL) {
3158 /* In a bounded map, array or bstr-wrapped CBOR */
3159
3160 if(DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
3161 /* In bstr-wrapped CBOR. */
3162
3163 /* Reposition traversal cursor to start of wrapping byte string */
3164 UsefulInputBuf_Seek(&(pMe->InBuf),
3165 pMe->nesting.pCurrentBounded->u.bs.uBstrStartOffset);
3166 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
3167
3168 } else {
3169 /* In a map or array */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003170 QCBORDecode_Private_RewindMapOrArray(pMe);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003171 }
3172
3173 } else {
3174 /* Not in anything bounded */
3175
3176 /* Reposition traversal cursor to the start of input CBOR */
3177 UsefulInputBuf_Seek(&(pMe->InBuf), 0ULL);
3178
3179 /* Reset nesting tracking to beginning of input. */
3180 DecodeNesting_Init(&(pMe->nesting));
3181 }
3182
3183 pMe->uLastError = QCBOR_SUCCESS;
3184}
3185
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003186
Laurence Lundblade9b334962020-08-27 10:55:53 -07003187
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003188
3189
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003190/**
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003191 * @brief Search a map for a set of items.
3192 *
3193 * @param[in] pMe The decode context to search.
3194 * @param[in,out] pItemArray The items to search for and the items found.
3195 * @param[out] puOffset Byte offset of last item matched.
3196 * @param[in] pCBContext Context for the not-found item call back.
3197 * @param[in] pfCallback Function to call on items not matched in pItemArray.
3198 *
3199 * @retval QCBOR_ERR_NOT_ENTERED Trying to search without entering a map.
3200 *
3201 * @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
3202 * were found for one of the labels being
3203 * search for. This duplicate detection is
3204 * only performed for items in pItemArray,
3205 * not every item in the map.
3206 *
3207 * @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
3208 * wrong for the matchd label.
3209 *
3210 * @retval Also errors returned by QCBORDecode_GetNext().
3211 *
3212 * On input, \c pItemArray contains a list of labels and data types of
3213 * items to be found.
3214 *
3215 * On output, the fully retrieved items are filled in with values and
3216 * such. The label was matched, so it never changes.
3217 *
3218 * If an item was not found, its data type is set to @ref QCBOR_TYPE_NONE.
3219 *
3220 * This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003221 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003222static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003223QCBORDecode_Private_MapSearch(QCBORDecodeContext *pMe,
3224 QCBORItem *pItemArray,
3225 size_t *puOffset,
3226 void *pCBContext,
3227 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003228{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003229 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003230 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07003231
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003232 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003233 uReturn = pMe->uLastError;
3234 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003235 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003236
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003237 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003238 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
3239 /* QCBOR_TYPE_NONE as first item indicates just looking
3240 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003241 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
3242 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003243 }
3244
Laurence Lundblade085d7952020-07-24 10:26:30 -07003245 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
3246 // It is an empty bounded array or map
3247 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
3248 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003249 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07003250 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003251 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003252 // Nothing is ever found in an empty array or map. All items
3253 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07003254 uReturn = QCBOR_SUCCESS;
3255 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003256 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003257 }
3258
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003259 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003260 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
3261
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003262 /* Reposition to search from the start of the map / array */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003263 QCBORDecode_Private_RewindMapOrArray(pMe);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003264
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003265 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003266 Loop over all the items in the map or array. Each item
3267 could be a map or array, but label matching is only at
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003268 the main level. This handles definite- and indefinite-
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003269 length maps and arrays. The only reason this is ever
3270 called on arrays is to find their end position.
3271
3272 This will always run over all items in order to do
3273 duplicate detection.
3274
3275 This will exit with failure if it encounters an
3276 unrecoverable error, but continue on for recoverable
3277 errors.
3278
3279 If a recoverable error occurs on a matched item, then
3280 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003281 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07003282 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Máté Tóth-Pál2f2aa5f2021-05-17 21:35:09 +02003283 uint8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003284 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003285 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07003286 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003287
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003288 /* Get the item */
3289 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003290 QCBORError uResult = QCBORDecode_Private_GetNextTagContent(pMe, &Item);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003291 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003292 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003293 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003294 goto Done;
3295 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003296 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003297 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003298 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003299 goto Done;
3300 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003301
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003302 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003303 bool bMatched = false;
3304 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003305 if(QCBORItem_MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003306 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003307 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
3308 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003309 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003310 }
Laurence Lundblade63926052021-03-29 16:05:51 -07003311 if(uResult != QCBOR_SUCCESS) {
3312 /* The label matches, but the data item is in error */
3313 uReturn = uResult;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003314 goto Done;
3315 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003316 if(!QCBORItem_MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade63926052021-03-29 16:05:51 -07003317 /* The data item is not of the type(s) requested */
3318 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003319 goto Done;
3320 }
3321
Laurence Lundblade1341c592020-04-11 14:19:05 -07003322 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003323 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003324 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003325 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003326 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003327 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003328 bMatched = true;
3329 }
3330 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003331
3332
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003333 if(!bMatched && pfCallback != NULL) {
3334 /*
3335 Call the callback on unmatched labels.
3336 (It is tempting to do duplicate detection here, but that would
3337 require dynamic memory allocation because the number of labels
3338 that might be encountered is unbounded.)
3339 */
3340 uReturn = (*pfCallback)(pCBContext, &Item);
3341 if(uReturn != QCBOR_SUCCESS) {
3342 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003343 }
3344 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003345
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003346 /*
3347 Consume the item whether matched or not. This
3348 does the work of traversing maps and array and
3349 everything in them. In this loop only the
3350 items at the current nesting level are examined
3351 to match the labels.
3352 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003353 uReturn = QCBORDecode_Private_ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003354 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003355 goto Done;
3356 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003357 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003358
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003359 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003360
3361 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003362
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003363 // Check here makes sure that this won't accidentally be
3364 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003365 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003366 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
3367 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003368 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
3369 goto Done;
3370 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003371 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
3372 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003373
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003374 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003375 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
3376
3377 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003378 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07003379 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003380 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003381 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
3382 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003383 }
3384 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003385
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003386 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003387}
3388
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003389
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003390/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003391 * Public function, see header qcbor/qcbor_decode.h file
3392 */
3393void
3394QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
3395 int64_t nLabel,
3396 uint8_t uQcborType,
3397 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003398{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003399 if(pMe->uLastError != QCBOR_SUCCESS) {
3400 return;
3401 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003402
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003403 QCBORItem OneItemSeach[2];
3404 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3405 OneItemSeach[0].label.int64 = nLabel;
3406 OneItemSeach[0].uDataType = uQcborType;
3407 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003408
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003409 QCBORError uReturn = QCBORDecode_Private_MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003410
3411 *pItem = OneItemSeach[0];
3412
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003413 if(uReturn != QCBOR_SUCCESS) {
3414 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003415 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003416 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003417 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003418 }
3419
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003420 Done:
3421 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003422}
3423
3424
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003425/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003426 * Public function, see header qcbor/qcbor_decode.h file
3427 */
3428void
3429QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
3430 const char *szLabel,
3431 uint8_t uQcborType,
3432 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003433{
Laurence Lundbladeda095972020-06-06 18:35:33 -07003434 if(pMe->uLastError != QCBOR_SUCCESS) {
3435 return;
3436 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003437
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003438 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003439 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3440 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3441 OneItemSeach[0].uDataType = uQcborType;
3442 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003443
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003444 QCBORError uReturn = QCBORDecode_Private_MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003445 if(uReturn != QCBOR_SUCCESS) {
3446 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003447 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003448 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003449 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003450 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003451 }
3452
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003453 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003454
3455Done:
3456 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003457}
3458
3459
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003460/**
3461 * @brief Is a QCBOR_TYPE in the type list?
3462 *
3463 * @param[in] uDataType Type to check for.
3464 * @param[in] puTypeList List to check.
3465 *
3466 * @retval QCBOR_SUCCESS If in the list.
3467 * @retval QCBOR_ERR_UNEXPECTED_TYPE Not in the list.
3468 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07003469static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003470QCBOR_Private_CheckTypeList(const int uDataType,
3471 const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003472{
3473 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08003474 if(uDataType == puTypeList[i]) { /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003475 return QCBOR_SUCCESS;
3476 }
3477 }
3478 return QCBOR_ERR_UNEXPECTED_TYPE;
3479}
3480
Laurence Lundblade67257dc2020-07-27 03:33:37 -07003481
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003482/**
Laurence Lundblade37286c02022-09-03 10:05:02 -07003483 * Match a tag/type specification against the type of the item.
3484 *
3485 * @param[in] TagSpec Specification for matching tags.
3486 * @param[in] pItem The item to check.
3487 *
3488 * @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
3489 * @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
3490 *
3491 * This checks the item data type of untagged items as well as of
3492 * tagged items against a specification to see if decoding should
3493 * proceed.
3494 *
3495 * This relies on the automatic tag decoding done by QCBOR that turns
3496 * tag numbers into particular QCBOR_TYPEs so there is no actual
3497 * comparsion of tag numbers, just of QCBOR_TYPEs.
3498 *
3499 * This checks the data item type as possibly representing the tag
3500 * number or as the tag content type.
3501 *
3502 * If QCBOR_DISABLE_TAGS is #defined, this primarily checks the item
3503 * data type against the allowed tag content types. It will also error out
3504 * if the caller tries to require a tag because there is no way that can
3505 * ever be fulfilled.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003506 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07003507static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003508QCBOR_Private_CheckTagRequirement(const QCBOR_Private_TagSpec TagSpec,
3509 const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07003510{
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08003511 const int nItemType = pItem->uDataType; /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade37286c02022-09-03 10:05:02 -07003512 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
3513
3514#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08003515 /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003516 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
3517 pItem->uTags[0] != CBOR_TAG_INVALID16) {
3518 /* There are tags that QCBOR couldn't process on this item and
Laurence Lundblade37286c02022-09-03 10:05:02 -07003519 * the caller has told us there should not be.
3520 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003521 return QCBOR_ERR_UNEXPECTED_TYPE;
3522 }
3523
Laurence Lundblade9b334962020-08-27 10:55:53 -07003524 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
Laurence Lundblade37286c02022-09-03 10:05:02 -07003525 /* Must match the tag number and only the tag */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003526 return QCBOR_Private_CheckTypeList(nItemType, TagSpec.uTaggedTypes);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003527 }
3528
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003529 QCBORError uReturn = QCBOR_Private_CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003530 if(uReturn == QCBOR_SUCCESS) {
3531 return QCBOR_SUCCESS;
3532 }
3533
3534 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
3535 /* Must match the content type and only the content type.
Laurence Lundblade37286c02022-09-03 10:05:02 -07003536 * There was no match just above so it is a fail. */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003537 return QCBOR_ERR_UNEXPECTED_TYPE;
3538 }
3539
Laurence Lundblade37286c02022-09-03 10:05:02 -07003540 /* QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG: If here it can match either the tag or the content
3541 * and it hasn't matched the content, so the end
3542 * result is whether it matches the tag. This is
3543 * the tag optional case that the CBOR standard discourages.
3544 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003545
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003546 return QCBOR_Private_CheckTypeList(nItemType, TagSpec.uTaggedTypes);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003547
Laurence Lundblade37286c02022-09-03 10:05:02 -07003548#else /* QCBOR_DISABLE_TAGS */
3549 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
3550 return QCBOR_ERR_UNEXPECTED_TYPE;
3551 }
3552
3553 return CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
3554
3555#endif /* QCBOR_DISABLE_TAGS */
3556}
Laurence Lundblade9b334962020-08-27 10:55:53 -07003557
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003558
3559/**
3560 * @brief Get an item by label to match a tag specification.
3561 *
3562 * @param[in] pMe The decode context.
3563 * @param[in] nLabel The label to search map for.
3564 * @param[in] TagSpec The tag number specification to match.
3565 * @param[out] pItem The item found.
3566 *
3567 * This finds the item with the given label in currently open
3568 * map. Then checks that its tag number and types matches the tag
3569 * specification. If not, an error is set in the decode context.
3570 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003571static void
3572QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
3573 const int64_t nLabel,
3574 const QCBOR_Private_TagSpec TagSpec,
3575 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003576{
3577 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
3578 if(pMe->uLastError != QCBOR_SUCCESS) {
3579 return;
3580 }
3581
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003582 pMe->uLastError = (uint8_t)QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003583}
3584
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003585
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003586/**
3587 * @brief Get an item by label to match a tag specification.
3588 *
3589 * @param[in] pMe The decode context.
3590 * @param[in] szLabel The label to search map for.
3591 * @param[in] TagSpec The tag number specification to match.
3592 * @param[out] pItem The item found.
3593 *
3594 * This finds the item with the given label in currently open
3595 * map. Then checks that its tag number and types matches the tag
3596 * specification. If not, an error is set in the decode context.
3597 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003598static void
3599QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
3600 const char *szLabel,
3601 const QCBOR_Private_TagSpec TagSpec,
3602 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003603{
3604 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
3605 if(pMe->uLastError != QCBOR_SUCCESS) {
3606 return;
3607 }
3608
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003609 pMe->uLastError = (uint8_t)QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003610}
3611
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003612
3613/**
3614 * @brief Semi-private to get an string by label to match a tag specification.
3615 *
3616 * @param[in] pMe The decode context.
3617 * @param[in] nLabel The label to search map for.
3618 * @param[in] TagSpec The tag number specification to match.
3619 * @param[out] pString The string found.
3620 *
3621 * This finds the string with the given label in currently open
3622 * map. Then checks that its tag number and types matches the tag
3623 * specification. If not, an error is set in the decode context.
3624 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003625void
3626QCBORDecode_Private_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
3627 const int64_t nLabel,
3628 const QCBOR_Private_TagSpec TagSpec,
3629 UsefulBufC *pString)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003630{
3631 QCBORItem Item;
3632 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
3633 if(pMe->uLastError == QCBOR_SUCCESS) {
3634 *pString = Item.val.string;
3635 }
3636}
3637
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003638
3639/**
3640 * @brief Semi-private to get an string by label to match a tag specification.
3641 *
3642 * @param[in] pMe The decode context.
3643 * @param[in] szLabel The label to search map for.
3644 * @param[in] TagSpec The tag number specification to match.
3645 * @param[out] pString The string found.
3646 *
3647 * This finds the string with the given label in currently open
3648 * map. Then checks that its tag number and types matches the tag
3649 * specification. If not, an error is set in the decode context.
3650 */void
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003651QCBORDecode_Private_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
3652 const char * szLabel,
3653 const QCBOR_Private_TagSpec TagSpec,
3654 UsefulBufC *pString)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003655{
3656 QCBORItem Item;
3657 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
3658 if(pMe->uLastError == QCBOR_SUCCESS) {
3659 *pString = Item.val.string;
3660 }
3661}
Laurence Lundblade1341c592020-04-11 14:19:05 -07003662
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003663
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003664/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003665 * Public function, see header qcbor/qcbor_decode.h file
3666 */
3667void
3668QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003669{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003670 QCBORError uErr = QCBORDecode_Private_MapSearch(pMe, pItemList, NULL, NULL, NULL);
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003671 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003672}
3673
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003674/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003675 * Public function, see header qcbor/qcbor_decode.h file
3676 */
3677void
3678QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3679 QCBORItem *pItemList,
3680 void *pCallbackCtx,
3681 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003682{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003683 QCBORError uErr = QCBORDecode_Private_MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003684 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003685}
3686
3687
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003688/**
3689 * @brief Search for a map/array by label and enter it
3690 *
3691 * @param[in] pMe The decode context.
3692 * @param[in] pSearch The map/array to search for.
3693 *
3694 * @c pSearch is expected to contain one item of type map or array
3695 * with the label specified. The current bounded map will be searched for
3696 * this and if found will be entered.
3697 *
3698 * If the label is not found, or the item found is not a map or array,
3699 * the error state is set.
3700 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003701static void
3702QCBORDecode_Private_SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003703{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003704 // The first item in pSearch is the one that is to be
3705 // entered. It should be the only one filled in. Any other
3706 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003707 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003708 return;
3709 }
3710
3711 size_t uOffset;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003712 pMe->uLastError = (uint8_t)QCBORDecode_Private_MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003713 if(pMe->uLastError != QCBOR_SUCCESS) {
3714 return;
3715 }
3716
Laurence Lundblade9b334962020-08-27 10:55:53 -07003717 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003718 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003719 return;
3720 }
3721
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003722
3723 /* The map or array was found. Now enter it.
3724 *
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003725 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3726 * next item for the pre-order traversal cursor to be the map/array
3727 * found by MapSearch(). The next few lines of code force the
3728 * cursor to that.
3729 *
3730 * There is no need to retain the old cursor because
3731 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3732 * beginning of the map/array being entered.
3733 *
3734 * The cursor is forced by: 1) setting the input buffer position to
3735 * the item offset found by MapSearch(), 2) setting the map/array
3736 * counter to the total in the map/array, 3) setting the nesting
3737 * level. Setting the map/array counter to the total is not
3738 * strictly correct, but this is OK because this cursor only needs
3739 * to be used to get one item and MapSearch() has already found it
3740 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003741 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003742 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003743
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003744 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3745
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003746 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003747
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003748 QCBORDecode_Private_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003749}
3750
3751
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003752/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003753 * Public function, see header qcbor/qcbor_decode.h file
3754 */
3755void
3756QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003757{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003758 QCBORItem OneItemSeach[2];
3759 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3760 OneItemSeach[0].label.int64 = nLabel;
3761 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3762 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003763
Laurence Lundblade9b334962020-08-27 10:55:53 -07003764 /* The map to enter was found, now finish off entering it. */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003765 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003766}
3767
3768
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003769/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003770 * Public function, see header qcbor/qcbor_decode.h file
3771 */
3772void
3773QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003774{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003775 QCBORItem OneItemSeach[2];
3776 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3777 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3778 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3779 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003780
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003781 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003782}
3783
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003784/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003785 * Public function, see header qcbor/qcbor_decode.h file
3786 */
3787void
3788QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003789{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003790 QCBORItem OneItemSeach[2];
3791 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3792 OneItemSeach[0].label.int64 = nLabel;
3793 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3794 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003795
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003796 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003797}
3798
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003799/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003800 * Public function, see header qcbor/qcbor_decode.h file
3801 */
3802void
3803QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundblade34691b92020-05-18 22:25:25 -07003804{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003805 QCBORItem OneItemSeach[2];
3806 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3807 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3808 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3809 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003810
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003811 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003812}
3813
3814
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003815/**
3816 * @brief Semi-private to do the the work for EnterMap() and EnterArray().
3817 *
3818 * @param[in] pMe The decode context
3819 * @param[in] uType QCBOR_TYPE_MAP or QCBOR_TYPE_ARRAY.
3820 * @param[out] pItem The data item for the map or array entered.
3821 *
3822 * The next item in the traversal must be a map or array. This
3823 * consumes that item and does the book keeping to enter the map or
3824 * array.
3825 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003826void
3827QCBORDecode_Private_EnterBoundedMapOrArray(QCBORDecodeContext *pMe,
3828 const uint8_t uType,
3829 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003830{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003831 QCBORError uErr;
3832
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003833 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003834 if(pMe->uLastError != QCBOR_SUCCESS) {
3835 // Already in error state; do nothing.
3836 return;
3837 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003838
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003839 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003840 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003841 uErr = QCBORDecode_GetNext(pMe, &Item);
3842 if(uErr != QCBOR_SUCCESS) {
3843 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003844 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003845 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003846 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3847 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003848 }
3849
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003850 QCBORDecode_Private_CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003851
3852
Laurence Lundbladef0499502020-08-01 11:55:57 -07003853 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003854 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003855 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3856 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003857 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003858 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3859 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003860 // Special case to increment nesting level for zero-length maps
3861 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003862 DecodeNesting_Descend(&(pMe->nesting), uType);
3863 }
3864
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003865 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003866
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003867 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3868 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003869
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003870 if(pItem != NULL) {
3871 *pItem = Item;
3872 }
3873
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003874Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003875 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003876}
3877
Laurence Lundblade02625d42020-06-25 14:41:41 -07003878
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003879/**
3880 * @brief Exit a bounded map, array or bstr (semi-private).
3881 *
3882 * @param[in] pMe Decode context.
3883 * @param[in] uEndOffset The input buffer offset of the end of item exited.
3884 *
3885 * @returns QCBOR_SUCCESS or an error code.
3886 *
3887 * This is the common work for exiting a level that is a bounded map,
3888 * array or bstr wrapped CBOR.
3889 *
3890 * One chunk of work is to set up the pre-order traversal so it is at
3891 * the item just after the bounded map, array or bstr that is being
3892 * exited. This is somewhat complex.
3893 *
3894 * The other work is to level-up the bounded mode to next higest
3895 * bounded mode or the top level if there isn't one.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003896 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003897static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003898QCBORDecode_Private_ExitBoundedLevel(QCBORDecodeContext *pMe,
3899 const uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003900{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003901 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003902
Laurence Lundblade02625d42020-06-25 14:41:41 -07003903 /*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003904 * First the pre-order-traversal byte offset is positioned to the
3905 * item just after the bounded mode item that was just consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003906 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003907 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3908
Laurence Lundblade02625d42020-06-25 14:41:41 -07003909 /*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003910 * Next, set the current nesting level to one above the bounded
3911 * level that was just exited.
3912 *
3913 * DecodeNesting_CheckBoundedType() is always called before this
3914 * and makes sure pCurrentBounded is valid.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003915 */
3916 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3917
3918 /*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003919 * This does the complex work of leveling up the pre-order
3920 * traversal when the end of a map or array or another bounded
3921 * level is reached. It may do nothing, or ascend all the way to
3922 * the top level.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003923 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003924 uErr = QCBORDecode_Private_NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003925 if(uErr != QCBOR_SUCCESS) {
3926 goto Done;
3927 }
3928
Laurence Lundblade02625d42020-06-25 14:41:41 -07003929 /*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003930 * This makes the next highest bounded level the current bounded
3931 * level. If there is no next highest level, then no bounded mode
3932 * is in effect.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003933 */
3934 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003935
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003936 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003937
3938Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003939 return uErr;
3940}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003941
Laurence Lundblade02625d42020-06-25 14:41:41 -07003942
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003943/**
3944 * @brief Get started exiting a map or array (semi-private)
3945 *
3946 * @param[in] pMe The decode context
3947 * @param[in] uType QCBOR_TYPE_ARRAY or QCBOR_TYPE_MAP
3948 *
3949 * This does some work for map and array exiting (but not
3950 * bstr exiting). Then QCBORDecode_Private_ExitBoundedLevel()
3951 * is called to do the rest.
3952 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003953void
3954QCBORDecode_Private_ExitBoundedMapOrArray(QCBORDecodeContext *pMe,
3955 const uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003956{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003957 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003958 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003959 return;
3960 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003961
Laurence Lundblade02625d42020-06-25 14:41:41 -07003962 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003963
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003964 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003965 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003966 goto Done;
3967 }
3968
Laurence Lundblade02625d42020-06-25 14:41:41 -07003969 /*
3970 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003971 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003972 from previous map search, then do a dummy search.
3973 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003974 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003975 QCBORItem Dummy;
3976 Dummy.uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003977 uErr = QCBORDecode_Private_MapSearch(pMe, &Dummy, NULL, NULL, NULL);
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003978 if(uErr != QCBOR_SUCCESS) {
3979 goto Done;
3980 }
3981 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003982
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003983 uErr = QCBORDecode_Private_ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003984
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003985Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003986 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003987}
3988
3989
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003990/**
3991 * @brief The main work of entering some byte-string wrapped CBOR.
3992 *
3993 * @param[in] pMe The decode context.
3994 * @param[in] pItem The byte string item.
3995 * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX
3996 * @param[out] pBstr Pointer and length of byte string entered.
3997 *
3998 * This is called once the byte string item has been decoded to do all
3999 * the book keeping work for descending a nesting level into the
4000 * nested CBOR.
4001 *
4002 * See QCBORDecode_EnterBstrWrapped() for details on uTagRequirement.
4003 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07004004static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004005QCBORDecode_Private_EnterBstrWrapped(QCBORDecodeContext *pMe,
4006 const QCBORItem *pItem,
4007 const uint8_t uTagRequirement,
4008 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004009{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07004010 if(pBstr) {
4011 *pBstr = NULLUsefulBufC;
4012 }
4013
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004014 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004015 /* Already in error state; do nothing. */
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004016 return pMe->uLastError;
4017 }
4018
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004019 QCBORError uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004020
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004021 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004022 {
4023 uTagRequirement,
4024 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
4025 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4026 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004027
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004028 uError = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004029 if(uError != QCBOR_SUCCESS) {
4030 goto Done;
4031 }
4032
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004033 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004034 /* Reverse the decrement done by GetNext() for the bstr so the
4035 * increment in QCBORDecode_NestLevelAscender() called by
4036 * ExitBoundedLevel() will work right.
4037 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004038 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07004039 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004040
4041 if(pBstr) {
4042 *pBstr = pItem->val.string;
4043 }
4044
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004045 /* This saves the current length of the UsefulInputBuf and then
4046 * narrows the UsefulInputBuf to start and length of the wrapped
4047 * CBOR that is being entered.
4048 *
4049 * Most of these calls are simple inline accessors so this doesn't
4050 * amount to much code.
4051 */
4052
Laurence Lundbladea4308a82020-10-03 18:08:57 -07004053 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004054 /* This check makes the cast of uPreviousLength to uint32_t below safe. */
4055 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07004056 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07004057 goto Done;
4058 }
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004059
4060 const size_t uStartOfBstr = UsefulInputBuf_PointerToOffset(&(pMe->InBuf),
4061 pItem->val.string.ptr);
4062 /* This check makes the cast of uStartOfBstr to uint32_t below safe. */
4063 if(uStartOfBstr == SIZE_MAX || uStartOfBstr > QCBOR_MAX_DECODE_INPUT_SIZE) {
4064 /* This should never happen because pItem->val.string.ptr should
4065 * always be valid since it was just returned.
4066 */
4067 uError = QCBOR_ERR_INPUT_TOO_LARGE;
4068 goto Done;
4069 }
4070
4071 const size_t uEndOfBstr = uStartOfBstr + pItem->val.string.len;
4072
4073 UsefulInputBuf_Seek(&(pMe->InBuf), uStartOfBstr);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07004074 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004075
Laurence Lundblade02625d42020-06-25 14:41:41 -07004076 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07004077 (uint32_t)uPreviousLength,
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004078 (uint32_t)uStartOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004079Done:
4080 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004081}
4082
4083
Laurence Lundblade02625d42020-06-25 14:41:41 -07004084/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004085 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07004086 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004087void
4088QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
4089 const uint8_t uTagRequirement,
4090 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07004091{
4092 if(pMe->uLastError != QCBOR_SUCCESS) {
4093 // Already in error state; do nothing.
4094 return;
4095 }
4096
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004097 /* Get the data item that is the byte string being entered */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004098 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07004099 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4100 if(pMe->uLastError != QCBOR_SUCCESS) {
4101 return;
4102 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07004103
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004104 pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
4105 &Item,
4106 uTagRequirement,
4107 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07004108}
4109
4110
Laurence Lundblade02625d42020-06-25 14:41:41 -07004111/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004112 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07004113 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004114void
4115QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
4116 const int64_t nLabel,
4117 const uint8_t uTagRequirement,
4118 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004119{
4120 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004121 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004122
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004123 pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
4124 &Item,
4125 uTagRequirement,
4126 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004127}
4128
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004129
Laurence Lundblade02625d42020-06-25 14:41:41 -07004130/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004131 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07004132 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004133void
4134QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
4135 const char *szLabel,
4136 const uint8_t uTagRequirement,
4137 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004138{
4139 QCBORItem Item;
4140 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4141
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004142 pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
4143 &Item,
4144 uTagRequirement,
4145 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004146}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004147
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004148
Laurence Lundblade02625d42020-06-25 14:41:41 -07004149/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004150 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07004151 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004152void
4153QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004154{
Laurence Lundblade02625d42020-06-25 14:41:41 -07004155 if(pMe->uLastError != QCBOR_SUCCESS) {
4156 // Already in error state; do nothing.
4157 return;
4158 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004159
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07004160 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07004161 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07004162 return;
4163 }
4164
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004165 const uint32_t uEndOfBstr = (uint32_t)UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
4166
Laurence Lundblade02625d42020-06-25 14:41:41 -07004167 /*
4168 Reset the length of the UsefulInputBuf to what it was before
4169 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004170 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07004171 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004172 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004173
4174
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004175 QCBORError uErr = QCBORDecode_Private_ExitBoundedLevel(pMe, uEndOfBstr);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004176 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004177}
4178
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004179
Laurence Lundbladee6430642020-03-14 21:15:44 -07004180
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004181/**
4182 * @brief Process simple type true and false, a boolean
4183 *
4184 * @param[in] pMe The decode context.
4185 * @param[in] pItem The item with either true or false.
4186 * @param[out] pBool The boolean value output.
4187 *
4188 * Sets the internal error if the item isn't a true or a false. Also
4189 * records any tag numbers as the tag numbers of the last item.
4190 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004191static void
4192QCBORDecode_Private_ProcessBool(QCBORDecodeContext *pMe,
4193 const QCBORItem *pItem,
4194 bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004195{
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004196 if(pMe->uLastError != QCBOR_SUCCESS) {
4197 /* Already in error state, do nothing */
4198 return;
4199 }
4200
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004201 switch(pItem->uDataType) {
4202 case QCBOR_TYPE_TRUE:
4203 *pBool = true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004204 break;
4205
4206 case QCBOR_TYPE_FALSE:
4207 *pBool = false;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004208 break;
4209
4210 default:
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004211 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004212 break;
4213 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004214 QCBORDecode_Private_CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004215}
Laurence Lundbladee6430642020-03-14 21:15:44 -07004216
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004217
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004218/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004219 * Public function, see header qcbor/qcbor_decode.h file
4220 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004221void
4222QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004223{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004224 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004225 /* Already in error state, do nothing */
Laurence Lundbladee6430642020-03-14 21:15:44 -07004226 return;
4227 }
4228
Laurence Lundbladec4537442020-04-14 18:53:22 -07004229 QCBORItem Item;
4230
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004231 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4232
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004233 QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004234}
4235
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004236
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004237/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004238 * Public function, see header qcbor/qcbor_decode.h file
4239 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004240void
4241QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe,
4242 const int64_t nLabel,
4243 bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004244{
4245 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004246 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004247
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004248 QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004249}
4250
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004251
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004252/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004253 * Public function, see header qcbor/qcbor_decode.h file
4254 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004255void
4256QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe,
4257 const char *szLabel,
4258 bool *pValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004259{
4260 QCBORItem Item;
4261 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4262
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004263 QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004264}
4265
4266
4267
Laurence Lundbladec7114722020-08-13 05:11:40 -07004268
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004269/**
4270 * @brief Common processing for an epoch date.
4271 *
4272 * @param[in] pMe The decode context.
4273 * @param[in] pItem The item with the date.
4274 * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX.
4275 * @param[out] pnTime The returned date.
4276 *
4277 * Common processing for the date tag. Mostly make sure the tag
4278 * content is correct and copy forward any further other tag numbers.
4279 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004280static void
4281QCBORDecode_Private_ProcessEpochDate(QCBORDecodeContext *pMe,
4282 QCBORItem *pItem,
4283 const uint8_t uTagRequirement,
4284 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07004285{
4286 if(pMe->uLastError != QCBOR_SUCCESS) {
4287 // Already in error state, do nothing
4288 return;
4289 }
4290
4291 QCBORError uErr;
4292
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004293 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladec7114722020-08-13 05:11:40 -07004294 {
4295 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004296 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4297 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07004298 };
4299
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004300 uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004301 if(uErr != QCBOR_SUCCESS) {
4302 goto Done;
4303 }
4304
4305 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004306 uErr = QCBOR_Private_DecodeDateEpoch(pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004307 if(uErr != QCBOR_SUCCESS) {
4308 goto Done;
4309 }
4310 }
4311
Laurence Lundblade9b334962020-08-27 10:55:53 -07004312 // Save the tags in the last item's tags in the decode context
4313 // for QCBORDecode_GetNthTagOfLast()
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004314 QCBORDecode_Private_CopyTags(pMe, pItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07004315
Laurence Lundbladec7114722020-08-13 05:11:40 -07004316 *pnTime = pItem->val.epochDate.nSeconds;
4317
4318Done:
4319 pMe->uLastError = (uint8_t)uErr;
4320}
4321
4322
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004323
4324/*
4325 * Public function, see header qcbor/qcbor_spiffy_decode.h file
4326 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004327void
4328QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
4329 uint8_t uTagRequirement,
4330 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07004331{
4332 if(pMe->uLastError != QCBOR_SUCCESS) {
4333 // Already in error state, do nothing
4334 return;
4335 }
4336
4337 QCBORItem Item;
4338 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4339
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004340 QCBORDecode_Private_ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004341}
4342
4343
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004344/*
4345 * Public function, see header qcbor/qcbor_spiffy_decode.h file
4346 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07004347void
4348QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
4349 int64_t nLabel,
4350 uint8_t uTagRequirement,
4351 int64_t *pnTime)
4352{
4353 QCBORItem Item;
4354 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004355 QCBORDecode_Private_ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004356}
4357
4358
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004359/*
4360 * Public function, see header qcbor/qcbor_spiffy_decode.h file
4361 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07004362void
4363QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
4364 const char *szLabel,
4365 uint8_t uTagRequirement,
4366 int64_t *pnTime)
4367{
4368 QCBORItem Item;
4369 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004370 QCBORDecode_Private_ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004371}
4372
4373
4374
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004375/**
4376 * @brief Common processing for an epoch date.
4377 *
4378 * @param[in] pMe The decode context.
4379 * @param[in] pItem The item with the date.
4380 * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX.
4381 * @param[out] pnDays The returned day count.
4382 *
4383 * Common processing for the RFC 8943 day-count tag. Mostly make sure
4384 * the tag content is correct and copy forward any further other tag
4385 * numbers.
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004386 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004387static void
4388QCBORDecode_Private_ProcessEpochDays(QCBORDecodeContext *pMe,
4389 QCBORItem *pItem,
4390 uint8_t uTagRequirement,
4391 int64_t *pnDays)
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004392{
4393 if(pMe->uLastError != QCBOR_SUCCESS) {
4394 /* Already in error state, do nothing */
4395 return;
4396 }
4397
4398 QCBORError uErr;
4399
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004400 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004401 {
4402 uTagRequirement,
4403 {QCBOR_TYPE_DAYS_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4404 {QCBOR_TYPE_INT64, QCBOR_TYPE_UINT64, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4405 };
4406
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004407 uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004408 if(uErr != QCBOR_SUCCESS) {
4409 goto Done;
4410 }
4411
4412 if(pItem->uDataType != QCBOR_TYPE_DAYS_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004413 uErr = QCBOR_Private_DecodeDaysEpoch(pItem);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004414 if(uErr != QCBOR_SUCCESS) {
4415 goto Done;
4416 }
4417 }
4418
4419 /* Save the tags in the last item's tags in the decode context
4420 * for QCBORDecode_GetNthTagOfLast()
4421 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004422 QCBORDecode_Private_CopyTags(pMe, pItem);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004423
4424 *pnDays = pItem->val.epochDays;
4425
4426Done:
4427 pMe->uLastError = (uint8_t)uErr;
4428}
4429
4430
4431/*
4432 * Public function, see header qcbor/qcbor_decode.h
4433 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004434void
4435QCBORDecode_GetEpochDays(QCBORDecodeContext *pMe,
4436 uint8_t uTagRequirement,
4437 int64_t *pnDays)
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004438{
4439 if(pMe->uLastError != QCBOR_SUCCESS) {
4440 /* Already in error state, do nothing */
4441 return;
4442 }
4443
4444 QCBORItem Item;
4445 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4446
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004447 QCBORDecode_Private_ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004448}
4449
4450
4451/*
4452 * Public function, see header qcbor/qcbor_decode.h
4453 */
4454void
4455QCBORDecode_GetEpochDaysInMapN(QCBORDecodeContext *pMe,
4456 int64_t nLabel,
4457 uint8_t uTagRequirement,
4458 int64_t *pnDays)
4459{
4460 QCBORItem Item;
4461 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004462 QCBORDecode_Private_ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004463}
4464
4465
4466/*
4467 * Public function, see header qcbor/qcbor_decode.h
4468 */
4469void
4470QCBORDecode_GetEpochDaysInMapSZ(QCBORDecodeContext *pMe,
4471 const char *szLabel,
4472 uint8_t uTagRequirement,
4473 int64_t *pnDays)
4474{
4475 QCBORItem Item;
4476 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004477 QCBORDecode_Private_ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004478}
4479
4480
4481
Laurence Lundblade37286c02022-09-03 10:05:02 -07004482/*
4483 * @brief Get a string that matches the type/tag specification.
4484 */
4485void
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004486QCBORDecode_Private_GetTaggedString(QCBORDecodeContext *pMe,
4487 const QCBOR_Private_TagSpec TagSpec,
4488 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004489{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004490 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade37286c02022-09-03 10:05:02 -07004491 /* Already in error state, do nothing */
Laurence Lundbladec4537442020-04-14 18:53:22 -07004492 return;
4493 }
4494
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004495 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004496 QCBORItem Item;
4497
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004498 uError = QCBORDecode_GetNext(pMe, &Item);
4499 if(uError != QCBOR_SUCCESS) {
4500 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004501 return;
4502 }
4503
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004504 pMe->uLastError = (uint8_t)QCBOR_Private_CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004505
4506 if(pMe->uLastError == QCBOR_SUCCESS) {
4507 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07004508 } else {
4509 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004510 }
4511}
4512
Laurence Lundbladec4537442020-04-14 18:53:22 -07004513
4514
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004515
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004516/**
4517 * @brief Common processing for a big number tag.
4518 *
4519 * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX.
4520 * @param[in] pItem The item with the date.
4521 * @param[out] pValue The returned big number
4522 * @param[out] pbIsNegative The returned sign of the big number.
4523 *
4524 * Common processing for the big number tag. Mostly make sure
4525 * the tag content is correct and copy forward any further other tag
4526 * numbers.
4527 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07004528static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004529QCBOR_Private_ProcessBigNum(const uint8_t uTagRequirement,
4530 const QCBORItem *pItem,
4531 UsefulBufC *pValue,
4532 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004533{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004534 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004535 {
4536 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004537 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4538 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004539 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004540
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004541 QCBORError uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004542 if(uErr != QCBOR_SUCCESS) {
4543 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004544 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004545
4546 *pValue = pItem->val.string;
4547
4548 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
4549 *pbIsNegative = false;
4550 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
4551 *pbIsNegative = true;
4552 }
4553
4554 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004555}
4556
4557
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004558/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004559 * Public function, see header qcbor/qcbor_spiffy_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004560 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004561void
4562QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
4563 const uint8_t uTagRequirement,
4564 UsefulBufC *pValue,
4565 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004566{
4567 if(pMe->uLastError != QCBOR_SUCCESS) {
4568 // Already in error state, do nothing
4569 return;
4570 }
4571
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004572 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004573 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4574 if(uError != QCBOR_SUCCESS) {
4575 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004576 return;
4577 }
4578
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004579 pMe->uLastError = (uint8_t)QCBOR_Private_ProcessBigNum(uTagRequirement,
4580 &Item,
4581 pValue,
4582 pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004583}
4584
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004585
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004586/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004587 * Public function, see header qcbor/qcbor_spiffy_decode.h
4588 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004589void
4590QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
4591 const int64_t nLabel,
4592 const uint8_t uTagRequirement,
4593 UsefulBufC *pValue,
4594 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004595{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004596 QCBORItem Item;
4597 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004598 if(pMe->uLastError != QCBOR_SUCCESS) {
4599 return;
4600 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004601
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004602 pMe->uLastError = (uint8_t)QCBOR_Private_ProcessBigNum(uTagRequirement,
4603 &Item,
4604 pValue,
4605 pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004606}
4607
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004608
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004609/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004610 * Public function, see header qcbor/qcbor_spiffy_decode.h
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004611 */
4612void
4613QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
4614 const char *szLabel,
4615 const uint8_t uTagRequirement,
4616 UsefulBufC *pValue,
4617 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004618{
4619 QCBORItem Item;
4620 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004621 if(pMe->uLastError != QCBOR_SUCCESS) {
4622 return;
4623 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004624
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004625 pMe->uLastError = (uint8_t)QCBOR_Private_ProcessBigNum(uTagRequirement,
4626 &Item,
4627 pValue,
4628 pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004629}
4630
4631
4632
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004633/**
4634 * @brief Common processing for MIME tag (semi-private).
4635 *
4636 * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX.
4637 * @param[in] pItem The item with the date.
4638 * @param[out] pMessage The returned MIME message.
4639 * @param[out] pbIsTag257 If true, binary MIME, if not, text MIME.
4640 *
4641 * Common processing for the MIME tag. Mostly make sure the tag
4642 * content is correct and copy forward any further other tag
4643 * numbers. See QCBORDecode_GetMIMEMessage().
4644 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07004645QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004646QCBORDecode_Private_GetMIME(const uint8_t uTagRequirement,
Laurence Lundblade37286c02022-09-03 10:05:02 -07004647 const QCBORItem *pItem,
4648 UsefulBufC *pMessage,
4649 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004650{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004651 const QCBOR_Private_TagSpec TagSpecText =
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004652 {
4653 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004654 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4655 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004656 };
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004657 const QCBOR_Private_TagSpec TagSpecBinary =
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004658 {
4659 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004660 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4661 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004662 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004663
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004664 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07004665
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004666 if(QCBOR_Private_CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004667 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004668 if(pbIsTag257 != NULL) {
4669 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004670 }
4671 uReturn = QCBOR_SUCCESS;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004672 } else if(QCBOR_Private_CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004673 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004674 if(pbIsTag257 != NULL) {
4675 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004676 }
4677 uReturn = QCBOR_SUCCESS;
4678
4679 } else {
4680 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
4681 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07004682
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004683 return uReturn;
4684}
4685
Laurence Lundblade93d89472020-10-03 22:30:50 -07004686// Improvement: add methods for wrapped CBOR, a simple alternate
4687// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004688
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004689
4690
4691
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004692#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07004693
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004694/**
4695 * @brief Prototype for conversion of exponent and mantissa to unsigned integer.
4696 *
4697 * @param[in] uMantissa The mantissa.
4698 * @param[in] nExponent The exponent.
4699 * @param[out] puResult The resulting integer.
4700 *
4701 * Concrete implementations of this are for exponent base 10 and 2 supporting
4702 * decimal fractions and big floats.
4703 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004704typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004705
4706
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004707/**
4708 * @brief Base 10 exponentiate a mantissa and exponent into an unsigned 64-bit integer.
4709 *
4710 * @param[in] uMantissa The unsigned integer mantissa.
4711 * @param[in] nExponent The signed integer exponent.
4712 * @param[out] puResult Place to return the unsigned integer result.
4713 *
4714 * This computes: mantissa * 10 ^^ exponent as for a decimal fraction. The output is a 64-bit
4715 * unsigned integer.
4716 *
4717 * There are many inputs for which the result will not fit in the
4718 * 64-bit integer and \ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will
4719 * be returned.
4720 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004721static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004722QCBOR_Private_Exponentitate10(const uint64_t uMantissa,
4723 int64_t nExponent,
4724 uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004725{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004726 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004727
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004728 if(uResult != 0) {
4729 /* This loop will run a maximum of 19 times because
4730 * UINT64_MAX < 10 ^^ 19. More than that will cause
4731 * exit with the overflow error
4732 */
4733 for(; nExponent > 0; nExponent--) {
4734 if(uResult > UINT64_MAX / 10) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004735 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004736 }
4737 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004738 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004739
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004740 for(; nExponent < 0; nExponent++) {
4741 uResult = uResult / 10;
4742 if(uResult == 0) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004743 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004744 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004745 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004746 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004747 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07004748
4749 *puResult = uResult;
4750
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004751 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004752}
4753
4754
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004755/**
4756 * @brief Base 2 exponentiate a mantissa and exponent into an unsigned 64-bit integer.
4757 *
4758 * @param[in] uMantissa The unsigned integer mantissa.
4759 * @param[in] nExponent The signed integer exponent.
4760 * @param[out] puResult Place to return the unsigned integer result.
4761 *
4762 * This computes: mantissa * 2 ^^ exponent as for a big float. The
4763 * output is a 64-bit unsigned integer.
4764 *
4765 * There are many inputs for which the result will not fit in the
4766 * 64-bit integer and \ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will
4767 * be returned.
4768 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004769static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004770QCBOR_Private_Exponentitate2(const uint64_t uMantissa,
4771 int64_t nExponent,
4772 uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004773{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004774 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004775
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004776 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004777
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004778 /* This loop will run a maximum of 64 times because INT64_MAX <
4779 * 2^31. More than that will cause exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07004780 */
4781 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004782 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004783 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004784 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004785 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004786 nExponent--;
4787 }
4788
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004789 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004790 if(uResult == 0) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004791 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004792 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004793 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004794 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004795 }
4796
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004797 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004798
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004799 return QCBOR_SUCCESS;
4800}
4801
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004802
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004803/**
4804 * @brief Exponentiate a signed mantissa and signed exponent to produce a signed result.
4805 *
4806 * @param[in] nMantissa Signed integer mantissa.
4807 * @param[in] nExponent Signed integer exponent.
4808 * @param[out] pnResult Place to put the signed integer result.
4809 * @param[in] pfExp Exponentiation function.
4810 *
4811 * @returns Error code
4812 *
4813 * \c pfExp performs exponentiation on and unsigned mantissa and
4814 * produces an unsigned result. This converts the mantissa from signed
4815 * and converts the result to signed. The exponentiation function is
4816 * either for base 2 or base 10 (and could be other if needed).
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004817 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004818static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004819QCBOR_Private_ExponentiateNN(const int64_t nMantissa,
4820 const int64_t nExponent,
4821 int64_t *pnResult,
4822 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004823{
4824 uint64_t uResult;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004825 uint64_t uMantissa;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004826
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004827 /* Take the absolute value and put it into an unsigned. */
4828 if(nMantissa >= 0) {
4829 /* Positive case is straightforward */
4830 uMantissa = (uint64_t)nMantissa;
4831 } else if(nMantissa != INT64_MIN) {
4832 /* The common negative case. See next. */
4833 uMantissa = (uint64_t)-nMantissa;
4834 } else {
4835 /* int64_t and uint64_t are always two's complement per the
4836 * C standard (and since QCBOR uses these it only works with
4837 * two's complement, which is pretty much universal these
4838 * days). The range of a negative two's complement integer is
4839 * one more that than a positive, so the simple code above might
4840 * not work all the time because you can't simply negate the
4841 * value INT64_MIN because it can't be represented in an
4842 * int64_t. -INT64_MIN can however be represented in a
4843 * uint64_t. Some compilers seem to recognize this case for the
4844 * above code and put the correct value in uMantissa, however
4845 * they are not required to do this by the C standard. This next
4846 * line does however work for all compilers.
4847 *
4848 * This does assume two's complement where -INT64_MIN ==
4849 * INT64_MAX + 1 (which wouldn't be true for one's complement or
4850 * sign and magnitude (but we know we're using two's complement
4851 * because int64_t requires it)).
4852 *
4853 * See these, particularly the detailed commentary:
4854 * https://stackoverflow.com/questions/54915742/does-c99-mandate-a-int64-t-type-be-available-always
4855 * https://stackoverflow.com/questions/37301078/is-negating-int-min-undefined-behaviour
4856 */
4857 uMantissa = (uint64_t)INT64_MAX+1;
4858 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004859
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004860 /* Call the exponentiator passed for either base 2 or base 10.
4861 * Here is where most of the overflow errors are caught. */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004862 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
4863 if(uReturn) {
4864 return uReturn;
4865 }
4866
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004867 /* Convert back to the sign of the original mantissa */
4868 if(nMantissa >= 0) {
4869 if(uResult > INT64_MAX) {
4870 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4871 }
4872 *pnResult = (int64_t)uResult;
4873 } else {
4874 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
4875 * of INT64_MIN. This assumes two's compliment representation
4876 * where INT64_MIN is one increment farther from 0 than
4877 * INT64_MAX. Trying to write -INT64_MIN doesn't work to get
4878 * this because the compiler makes it an int64_t which can't
4879 * represent -INT64_MIN. Also see above.
4880 */
4881 if(uResult > (uint64_t)INT64_MAX+1) {
4882 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4883 }
4884 *pnResult = -(int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004885 }
4886
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004887 return QCBOR_SUCCESS;
4888}
4889
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004890
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004891/**
4892 * @brief Exponentiate an unsigned mantissa and signed exponent to produce an unsigned result.
4893 *
4894 * @param[in] nMantissa Signed integer mantissa.
4895 * @param[in] nExponent Signed integer exponent.
4896 * @param[out] puResult Place to put the signed integer result.
4897 * @param[in] pfExp Exponentiation function.
4898 *
4899 * @returns Error code
4900 *
4901 * \c pfExp performs exponentiation on and unsigned mantissa and
4902 * produces an unsigned result. This errors out if the mantissa
4903 * is negative because the output is unsigned.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004904 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004905static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004906QCBOR_Private_ExponentitateNU(const int64_t nMantissa,
4907 const int64_t nExponent,
4908 uint64_t *puResult,
4909 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004910{
4911 if(nMantissa < 0) {
4912 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4913 }
4914
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004915 /* Cast to unsigned is OK because of check for negative.
4916 * Cast to unsigned is OK because UINT64_MAX > INT64_MAX.
4917 * Exponentiation is straight forward
4918 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004919 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
4920}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004921
4922
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004923/**
4924 * @brief Exponentiate an usnigned mantissa and unsigned exponent to produce an unsigned result.
4925 *
4926 * @param[in] uMantissa Unsigned integer mantissa.
4927 * @param[in] nExponent Unsigned integer exponent.
4928 * @param[out] puResult Place to put the unsigned integer result.
4929 * @param[in] pfExp Exponentiation function.
4930 *
4931 * @returns Error code
4932 *
4933 * \c pfExp performs exponentiation on and unsigned mantissa and
4934 * produces an unsigned result so this is just a wrapper that does
4935 * nothing (and is likely inlined).
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004936 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004937static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004938QCBOR_Private_ExponentitateUU(const uint64_t uMantissa,
4939 const int64_t nExponent,
4940 uint64_t *puResult,
4941 fExponentiator pfExp)
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004942{
4943 return (*pfExp)(uMantissa, nExponent, puResult);
4944}
4945
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004946#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004947
4948
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004949
4950
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004951/**
4952 * @brief Convert a CBOR big number to a uint64_t.
4953 *
4954 * @param[in] BigNum Bytes of the big number to convert.
4955 * @param[in] uMax Maximum value allowed for the result.
4956 * @param[out] pResult Place to put the unsigned integer result.
4957 *
4958 * @returns Error code
4959 *
4960 * Many values will overflow because a big num can represent a much
4961 * larger range than uint64_t.
4962 */
4963static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004964QCBOR_Private_ConvertBigNumToUnsigned(const UsefulBufC BigNum,
4965 const uint64_t uMax,
4966 uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004967{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004968 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004969
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004970 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004971 const uint8_t *pByte = BigNum.ptr;
4972 size_t uLen = BigNum.len;
4973 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07004974 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004975 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004976 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07004977 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004978 }
4979
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004980 *pResult = uResult;
4981 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004982}
4983
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004984
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004985/**
4986 * @brief Convert a CBOR postive big number to a uint64_t.
4987 *
4988 * @param[in] BigNum Bytes of the big number to convert.
4989 * @param[out] pResult Place to put the unsigned integer result.
4990 *
4991 * @returns Error code
4992 *
4993 * Many values will overflow because a big num can represent a much
4994 * larger range than uint64_t.
4995 */
4996static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004997QCBOR_Private_ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum,
4998 uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004999{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005000 return QCBOR_Private_ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005001}
5002
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005003
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005004/**
5005 * @brief Convert a CBOR positive big number to an int64_t.
5006 *
5007 * @param[in] BigNum Bytes of the big number to convert.
5008 * @param[out] pResult Place to put the signed integer result.
5009 *
5010 * @returns Error code
5011 *
5012 * Many values will overflow because a big num can represent a much
5013 * larger range than int64_t.
5014 */
5015static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005016QCBOR_Private_ConvertPositiveBigNumToSigned(const UsefulBufC BigNum,
5017 int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005018{
5019 uint64_t uResult;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005020 QCBORError uError = QCBOR_Private_ConvertBigNumToUnsigned(BigNum,
5021 INT64_MAX,
5022 &uResult);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005023 if(uError) {
5024 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005025 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005026 /* Cast is safe because ConvertBigNumToUnsigned limits to INT64_MAX */
Laurence Lundbladee6430642020-03-14 21:15:44 -07005027 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005028 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005029}
5030
5031
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005032/**
5033 * @brief Convert a CBOR negative big number to an int64_t.
5034 *
5035 * @param[in] BigNum Bytes of the big number to convert.
5036 * @param[out] pnResult Place to put the signed integer result.
5037 *
5038 * @returns Error code
5039 *
5040 * Many values will overflow because a big num can represent a much
5041 * larger range than int64_t.
5042 */
5043static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005044QCBOR_Private_ConvertNegativeBigNumToSigned(const UsefulBufC BigNum,
5045 int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005046{
5047 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005048 /* The negative integer furthest from zero for a C int64_t is
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005049 * INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
5050 * negative number in CBOR is computed as -n - 1 where n is the
5051 * encoded integer, where n is what is in the variable BigNum. When
5052 * converting BigNum to a uint64_t, the maximum value is thus
5053 * INT64_MAX, so that when it -n - 1 is applied to it the result
5054 * will never be further from 0 than INT64_MIN.
5055 *
5056 * -n - 1 <= INT64_MIN.
5057 * -n - 1 <= -INT64_MAX - 1
5058 * n <= INT64_MAX.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005059 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005060 QCBORError uError = QCBOR_Private_ConvertBigNumToUnsigned(BigNum,
5061 INT64_MAX,
5062 &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005063 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005064 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005065 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005066
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005067 /* Now apply -n - 1. The cast is safe because
5068 * ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
5069 * is the largest positive integer that an int64_t can
5070 * represent. */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005071 *pnResult = -(int64_t)uResult - 1;
5072
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005073 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005074}
5075
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005076
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005077
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005078
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005079/**
5080 * @brief Convert integers and floats to an int64_t.
5081 *
5082 * @param[in] pItem The item to convert.
5083 * @param[in] uConvertTypes Bit mask list of conversion options.
5084 * @param[out] pnValue The resulting converted value.
5085 *
5086 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
5087 * in uConvertTypes.
5088 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
5089 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
5090 * or too small.
5091 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07005092static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005093QCBOR_Private_ConvertInt64(const QCBORItem *pItem,
5094 const uint32_t uConvertTypes,
5095 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005096{
5097 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005098 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005099 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005100#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005101 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005102 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
5103 http://www.cplusplus.com/reference/cmath/llround/
5104 */
5105 // Not interested in FE_INEXACT
5106 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005107 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
5108 *pnValue = llround(pItem->val.dfnum);
5109 } else {
5110 *pnValue = lroundf(pItem->val.fnum);
5111 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005112 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
5113 // llround() shouldn't result in divide by zero, but catch
5114 // it here in case it unexpectedly does. Don't try to
5115 // distinguish between the various exceptions because it seems
5116 // they vary by CPU, compiler and OS.
5117 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005118 }
5119 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005120 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005121 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005122#else
5123 return QCBOR_ERR_HW_FLOAT_DISABLED;
5124#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005125 break;
5126
5127 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005128 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005129 *pnValue = pItem->val.int64;
5130 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005131 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005132 }
5133 break;
5134
5135 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005136 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005137 if(pItem->val.uint64 < INT64_MAX) {
5138 *pnValue = pItem->val.int64;
5139 } else {
5140 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5141 }
5142 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005143 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005144 }
5145 break;
5146
5147 default:
5148 return QCBOR_ERR_UNEXPECTED_TYPE;
5149 }
5150 return QCBOR_SUCCESS;
5151}
5152
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005153
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005154/**
5155 * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
5156 *
5157 * @param[in] pMe The decode context.
5158 * @param[in] uConvertTypes Bit mask list of conversion options.
5159 * @param[out] pnValue Result of the conversion.
5160 * @param[in,out] pItem Temporary space to store Item, returned item.
5161 *
5162 * See QCBORDecode_GetInt64Convert().
5163 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005164void
5165QCBORDecode_Private_GetInt64Convert(QCBORDecodeContext *pMe,
5166 uint32_t uConvertTypes,
5167 int64_t *pnValue,
5168 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005169{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07005170 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07005171 return;
5172 }
5173
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005174 QCBORError uError = QCBORDecode_GetNext(pMe, pItem);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005175 if(uError) {
5176 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005177 return;
5178 }
5179
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005180 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005181 uConvertTypes,
5182 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005183}
5184
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005185/**
5186 * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
5187 *
5188 * @param[in] pMe The decode context.
5189 * @param[in] nLabel Label to find in map.
5190 * @param[in] uConvertTypes Bit mask list of conversion options.
5191 * @param[out] pnValue Result of the conversion.
5192 * @param[in,out] pItem Temporary space to store Item, returned item.
5193 *
5194 * See QCBORDecode_GetInt64ConvertInMapN().
5195 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005196void
5197QCBORDecode_Private_GetInt64ConvertInMapN(QCBORDecodeContext *pMe,
5198 int64_t nLabel,
5199 uint32_t uConvertTypes,
5200 int64_t *pnValue,
5201 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005202{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005203 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005204 if(pMe->uLastError != QCBOR_SUCCESS) {
5205 return;
5206 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005207
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005208 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
5209 uConvertTypes,
5210 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005211}
5212
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005213/**
5214 * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
5215 *
5216 * @param[in] pMe The decode context.
5217 * @param[in] szLabel Label to find in map.
5218 * @param[in] uConvertTypes Bit mask list of conversion options.
5219 * @param[out] pnValue Result of the conversion.
5220 * @param[in,out] pItem Temporary space to store Item, returned item.
5221 *
5222 * See QCBORDecode_GetInt64ConvertInMapSZ().
5223 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005224void
5225QCBORDecode_Private_GetInt64ConvertInMapSZ(QCBORDecodeContext *pMe,
5226 const char * szLabel,
5227 uint32_t uConvertTypes,
5228 int64_t *pnValue,
5229 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005230{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005231 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005232 if(pMe->uLastError != QCBOR_SUCCESS) {
5233 return;
5234 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005235
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005236 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
5237 uConvertTypes,
5238 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005239}
5240
5241
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005242/**
5243 * @brief Convert many number types to an int64_t.
5244 *
5245 * @param[in] pItem The item to convert.
5246 * @param[in] uConvertTypes Bit mask list of conversion options.
5247 * @param[out] pnValue The resulting converted value.
5248 *
5249 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
5250 * in uConvertTypes.
5251 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
5252 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
5253 * or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005254 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07005255static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005256QCBOR_Private_Int64ConvertAll(const QCBORItem *pItem,
5257 const uint32_t uConvertTypes,
5258 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005259{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005260 switch(pItem->uDataType) {
5261
5262 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005263 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005264 return QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005265 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005266 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005267 }
5268 break;
5269
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005270 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005271 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005272 return QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005273 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005274 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005275 }
5276 break;
5277
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005278#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005279 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005280 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005281 return QCBOR_Private_ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005282 pItem->val.expAndMantissa.nExponent,
5283 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005284 &QCBOR_Private_Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005285 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005286 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005287 }
5288 break;
5289
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005290 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005291 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005292 return QCBOR_Private_ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005293 pItem->val.expAndMantissa.nExponent,
5294 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005295 QCBOR_Private_Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005296 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005297 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005298 }
5299 break;
5300
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005301 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005302 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005303 int64_t nMantissa;
5304 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005305 uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005306 if(uErr) {
5307 return uErr;
5308 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005309 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005310 pItem->val.expAndMantissa.nExponent,
5311 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005312 QCBOR_Private_Exponentitate10);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005313 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005314 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005315 }
5316 break;
5317
5318 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005319 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005320 int64_t nMantissa;
5321 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005322 uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005323 if(uErr) {
5324 return uErr;
5325 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005326 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005327 pItem->val.expAndMantissa.nExponent,
5328 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005329 QCBOR_Private_Exponentitate10);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005330 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005331 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005332 }
5333 break;
5334
5335 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005336 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005337 int64_t nMantissa;
5338 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005339 uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005340 if(uErr) {
5341 return uErr;
5342 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005343 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005344 pItem->val.expAndMantissa.nExponent,
5345 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005346 QCBOR_Private_Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005347 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005348 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005349 }
5350 break;
5351
5352 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005353 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005354 int64_t nMantissa;
5355 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005356 uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005357 if(uErr) {
5358 return uErr;
5359 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005360 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005361 pItem->val.expAndMantissa.nExponent,
5362 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005363 QCBOR_Private_Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005364 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005365 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005366 }
5367 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005368#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005369
Laurence Lundbladee6430642020-03-14 21:15:44 -07005370
Laurence Lundbladec4537442020-04-14 18:53:22 -07005371 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005372 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005373}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005374
5375
Laurence Lundbladec4537442020-04-14 18:53:22 -07005376/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005377 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005378 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005379void
5380QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe,
5381 const uint32_t uConvertTypes,
5382 int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07005383{
5384 QCBORItem Item;
5385
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005386 QCBORDecode_Private_GetInt64Convert(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07005387
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005388 if(pMe->uLastError == QCBOR_SUCCESS) {
5389 // The above conversion succeeded
5390 return;
5391 }
5392
Laurence Lundbladef6c86662020-05-12 02:08:00 -07005393 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005394 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07005395 return;
5396 }
5397
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005398 pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
5399 uConvertTypes,
5400 pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005401}
5402
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005403
5404/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005405 * Public function, see header qcbor/qcbor_decode.h file
5406 */
5407void
5408QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
5409 const int64_t nLabel,
5410 const uint32_t uConvertTypes,
5411 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005412{
5413 QCBORItem Item;
5414
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005415 QCBORDecode_Private_GetInt64ConvertInMapN(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07005416 nLabel,
5417 uConvertTypes,
5418 pnValue,
5419 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005420
5421 if(pMe->uLastError == QCBOR_SUCCESS) {
5422 // The above conversion succeeded
5423 return;
5424 }
5425
5426 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5427 // The above conversion failed in a way that code below can't correct
5428 return;
5429 }
5430
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005431 pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
5432 uConvertTypes,
5433 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005434}
5435
5436
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005437/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005438 * Public function, see header qcbor/qcbor_decode.h file
5439 */
5440void
5441QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
5442 const char *szLabel,
5443 const uint32_t uConvertTypes,
5444 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005445{
5446 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005447 QCBORDecode_Private_GetInt64ConvertInMapSZ(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07005448 szLabel,
5449 uConvertTypes,
5450 pnValue,
5451 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005452
5453 if(pMe->uLastError == QCBOR_SUCCESS) {
5454 // The above conversion succeeded
5455 return;
5456 }
5457
5458 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5459 // The above conversion failed in a way that code below can't correct
5460 return;
5461 }
5462
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005463 pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
5464 uConvertTypes,
5465 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005466}
5467
5468
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005469/**
5470 * @brief Convert many number types to an uint64_t.
5471 *
5472 * @param[in] pItem The item to convert.
5473 * @param[in] uConvertTypes Bit mask list of conversion options.
5474 * @param[out] puValue The resulting converted value.
5475 *
5476 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
5477 * in uConvertTypes.
5478 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
5479 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
5480 * or too small.
5481 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005482static QCBORError
5483QCBOR_Private_ConvertUInt64(const QCBORItem *pItem,
5484 const uint32_t uConvertTypes,
5485 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005486{
5487 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005488 case QCBOR_TYPE_DOUBLE:
5489 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005490#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005491 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005492 // Can't use llround here because it will not convert values
5493 // greater than INT64_MAX and less than UINT64_MAX that
5494 // need to be converted so it is more complicated.
5495 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
5496 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
5497 if(isnan(pItem->val.dfnum)) {
5498 return QCBOR_ERR_FLOAT_EXCEPTION;
5499 } else if(pItem->val.dfnum < 0) {
5500 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5501 } else {
5502 double dRounded = round(pItem->val.dfnum);
5503 // See discussion in DecodeDateEpoch() for
5504 // explanation of - 0x7ff
5505 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
5506 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5507 }
5508 *puValue = (uint64_t)dRounded;
5509 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005510 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005511 if(isnan(pItem->val.fnum)) {
5512 return QCBOR_ERR_FLOAT_EXCEPTION;
5513 } else if(pItem->val.fnum < 0) {
5514 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5515 } else {
5516 float fRounded = roundf(pItem->val.fnum);
5517 // See discussion in DecodeDateEpoch() for
5518 // explanation of - 0x7ff
5519 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
5520 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5521 }
5522 *puValue = (uint64_t)fRounded;
5523 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005524 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005525 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
5526 // round() and roundf() shouldn't result in exceptions here, but
5527 // catch them to be robust and thorough. Don't try to
5528 // distinguish between the various exceptions because it seems
5529 // they vary by CPU, compiler and OS.
5530 return QCBOR_ERR_FLOAT_EXCEPTION;
5531 }
5532
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005533 } else {
5534 return QCBOR_ERR_UNEXPECTED_TYPE;
5535 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005536#else
5537 return QCBOR_ERR_HW_FLOAT_DISABLED;
5538#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005539 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005540
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005541 case QCBOR_TYPE_INT64:
5542 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
5543 if(pItem->val.int64 >= 0) {
5544 *puValue = (uint64_t)pItem->val.int64;
5545 } else {
5546 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5547 }
5548 } else {
5549 return QCBOR_ERR_UNEXPECTED_TYPE;
5550 }
5551 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005552
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005553 case QCBOR_TYPE_UINT64:
5554 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
5555 *puValue = pItem->val.uint64;
5556 } else {
5557 return QCBOR_ERR_UNEXPECTED_TYPE;
5558 }
5559 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005560
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005561 default:
5562 return QCBOR_ERR_UNEXPECTED_TYPE;
5563 }
5564
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005565 return QCBOR_SUCCESS;
5566}
Laurence Lundbladec4537442020-04-14 18:53:22 -07005567
5568
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005569/**
5570 * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
5571 *
5572 * @param[in] pMe The decode context.
5573 * @param[in] uConvertTypes Bit mask list of conversion options.
5574 * @param[out] puValue Result of the conversion.
5575 * @param[in,out] pItem Temporary space to store Item, returned item.
5576 *
5577 * See QCBORDecode_GetUInt64Convert().
5578 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005579void
5580QCBORDecode_Private_GetUInt64Convert(QCBORDecodeContext *pMe,
5581 const uint32_t uConvertTypes,
5582 uint64_t *puValue,
5583 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07005584{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005585 if(pMe->uLastError != QCBOR_SUCCESS) {
5586 return;
5587 }
5588
Laurence Lundbladec4537442020-04-14 18:53:22 -07005589 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005590
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005591 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5592 if(uError) {
5593 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005594 return;
5595 }
5596
Laurence Lundbladea826c502020-05-10 21:07:00 -07005597 if(pItem) {
5598 *pItem = Item;
5599 }
5600
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005601 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(&Item,
5602 uConvertTypes,
5603 puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07005604}
5605
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005606
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005607/**
5608 * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
5609 *
5610 * @param[in] pMe The decode context.
5611 * @param[in] nLabel Label to find in map.
5612 * @param[in] uConvertTypes Bit mask list of conversion options.
5613 * @param[out] puValue Result of the conversion.
5614 * @param[in,out] pItem Temporary space to store Item, returned item.
5615 *
5616 * See QCBORDecode_GetUInt64ConvertInMapN().
5617 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005618void
5619QCBORDecode_Private_GetUInt64ConvertInMapN(QCBORDecodeContext *pMe,
5620 const int64_t nLabel,
5621 const uint32_t uConvertTypes,
5622 uint64_t *puValue,
5623 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005624{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005625 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005626 if(pMe->uLastError != QCBOR_SUCCESS) {
5627 return;
5628 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005629
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005630 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
5631 uConvertTypes,
5632 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005633}
5634
5635
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005636/**
5637 * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
5638 *
5639 * @param[in] pMe The decode context.
5640 * @param[in] szLabel Label to find in map.
5641 * @param[in] uConvertTypes Bit mask list of conversion options.
5642 * @param[out] puValue Result of the conversion.
5643 * @param[in,out] pItem Temporary space to store Item, returned item.
5644 *
5645 * See QCBORDecode_GetUInt64ConvertInMapSZ().
5646 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005647void
5648QCBORDecode_Private_GetUInt64ConvertInMapSZ(QCBORDecodeContext *pMe,
5649 const char *szLabel,
5650 const uint32_t uConvertTypes,
5651 uint64_t *puValue,
5652 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005653{
5654 if(pMe->uLastError != QCBOR_SUCCESS) {
5655 return;
5656 }
5657
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005658 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005659 if(pMe->uLastError != QCBOR_SUCCESS) {
5660 return;
5661 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005662
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005663 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
5664 uConvertTypes,
5665 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005666}
5667
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005668
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005669/**
5670 * @brief Convert many number types to an unt64_t.
5671 *
5672 * @param[in] pItem The item to convert.
5673 * @param[in] uConvertTypes Bit mask list of conversion options.
5674 * @param[out] puValue The resulting converted value.
5675 *
5676 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
5677 * in uConvertTypes.
5678 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
5679 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
5680 * or too small.
5681 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07005682static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005683QCBOR_Private_UInt64ConvertAll(const QCBORItem *pItem,
5684 const uint32_t uConvertTypes,
5685 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005686{
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08005687 switch(pItem->uDataType) { /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005688
5689 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005690 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005691 return QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005692 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005693 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005694 }
5695 break;
5696
5697 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005698 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005699 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5700 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005701 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005702 }
5703 break;
5704
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005705#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005706
5707 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005708 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005709 return QCBOR_Private_ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005710 pItem->val.expAndMantissa.nExponent,
5711 puValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005712 QCBOR_Private_Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005713 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005714 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005715 }
5716 break;
5717
5718 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005719 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005720 return QCBOR_Private_ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005721 pItem->val.expAndMantissa.nExponent,
5722 puValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005723 QCBOR_Private_Exponentitate2);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005724 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005725 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005726 }
5727 break;
5728
5729 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005730 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005731 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005732 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005733 uErr = QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005734 if(uErr != QCBOR_SUCCESS) {
5735 return uErr;
5736 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005737 return QCBOR_Private_ExponentitateUU(uMantissa,
5738 pItem->val.expAndMantissa.nExponent,
5739 puValue,
5740 QCBOR_Private_Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005741 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005742 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005743 }
5744 break;
5745
5746 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005747 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005748 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5749 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005750 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005751 }
5752 break;
5753
5754 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005755 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005756 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005757 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005758 uErr = QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum,
5759 &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005760 if(uErr != QCBOR_SUCCESS) {
5761 return uErr;
5762 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005763 return QCBOR_Private_ExponentitateUU(uMantissa,
5764 pItem->val.expAndMantissa.nExponent,
5765 puValue,
5766 QCBOR_Private_Exponentitate2);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005767 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005768 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005769 }
5770 break;
5771
5772 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005773 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005774 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5775 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005776 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005777 }
5778 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005779#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005780 default:
5781 return QCBOR_ERR_UNEXPECTED_TYPE;
5782 }
5783}
5784
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005785
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005786/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005787 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005788 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005789void
5790QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe,
5791 const uint32_t uConvertTypes,
5792 uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005793{
5794 QCBORItem Item;
5795
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005796 QCBORDecode_Private_GetUInt64Convert(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005797
Laurence Lundbladef6c86662020-05-12 02:08:00 -07005798 if(pMe->uLastError == QCBOR_SUCCESS) {
5799 // The above conversion succeeded
5800 return;
5801 }
5802
5803 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5804 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07005805 return;
5806 }
5807
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005808 pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
5809 uConvertTypes,
5810 puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005811}
5812
Laurence Lundbladec4537442020-04-14 18:53:22 -07005813
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005814/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005815 * Public function, see header qcbor/qcbor_decode.h file
5816 */
5817void
5818QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
5819 const int64_t nLabel,
5820 const uint32_t uConvertTypes,
5821 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005822{
5823 QCBORItem Item;
5824
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005825 QCBORDecode_Private_GetUInt64ConvertInMapN(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07005826 nLabel,
5827 uConvertTypes,
5828 puValue,
5829 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005830
5831 if(pMe->uLastError == QCBOR_SUCCESS) {
5832 // The above conversion succeeded
5833 return;
5834 }
5835
5836 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5837 // The above conversion failed in a way that code below can't correct
5838 return;
5839 }
5840
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005841 pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
5842 uConvertTypes,
5843 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005844}
5845
5846
5847/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005848 * Public function, see header qcbor/qcbor_decode.h file
5849 */
5850void
5851QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
5852 const char *szLabel,
5853 const uint32_t uConvertTypes,
5854 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005855{
5856 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005857 QCBORDecode_Private_GetUInt64ConvertInMapSZ(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07005858 szLabel,
5859 uConvertTypes,
5860 puValue,
5861 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005862
5863 if(pMe->uLastError == QCBOR_SUCCESS) {
5864 // The above conversion succeeded
5865 return;
5866 }
5867
5868 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5869 // The above conversion failed in a way that code below can't correct
5870 return;
5871 }
5872
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005873 pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
5874 uConvertTypes,
5875 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005876}
5877
5878
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005879
5880
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02005881#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005882/**
5883 * @brief Basic conversions to a double.
5884 *
5885 * @param[in] pItem The item to convert
5886 * @param[in] uConvertTypes Bit flags indicating source types for conversion
5887 * @param[out] pdValue The value converted to a double
5888 *
5889 * This does the conversions that don't need much object code,
5890 * the conversions from int, uint and float to double.
5891 *
5892 * See QCBOR_Private_DoubleConvertAll() for the full set
5893 * of conversions.
5894 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005895static QCBORError
5896QCBOR_Private_ConvertDouble(const QCBORItem *pItem,
5897 const uint32_t uConvertTypes,
5898 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005899{
5900 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005901 case QCBOR_TYPE_FLOAT:
5902#ifndef QCBOR_DISABLE_FLOAT_HW_USE
5903 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5904 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005905 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005906 *pdValue = (double)pItem->val.fnum;
5907 } else {
5908 return QCBOR_ERR_UNEXPECTED_TYPE;
5909 }
5910 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005911#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005912 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005913#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005914 break;
5915
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005916 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005917 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5918 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005919 *pdValue = pItem->val.dfnum;
5920 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005921 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005922 }
5923 }
5924 break;
5925
5926 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005927#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005928 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005929 // A simple cast seems to do the job with no worry of exceptions.
5930 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005931 *pdValue = (double)pItem->val.int64;
5932
5933 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005934 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005935 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005936#else
5937 return QCBOR_ERR_HW_FLOAT_DISABLED;
5938#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005939 break;
5940
5941 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005942#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005943 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005944 // A simple cast seems to do the job with no worry of exceptions.
5945 // There will be precision loss for some values.
5946 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005947 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005948 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005949 }
5950 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005951#else
5952 return QCBOR_ERR_HW_FLOAT_DISABLED;
5953#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005954
5955 default:
5956 return QCBOR_ERR_UNEXPECTED_TYPE;
5957 }
5958
5959 return QCBOR_SUCCESS;
5960}
5961
5962
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005963/**
5964 * @brief Almost-public method to decode a number and convert to double (semi-private).
5965 *
5966 * @param[in] pMe The decode context.
5967 * @param[in] uConvertTypes Bit mask list of conversion options
5968 * @param[out] pdValue The output of the conversion.
5969 * @param[in,out] pItem Temporary space to store Item, returned item.
5970 *
5971 * See QCBORDecode_GetDoubleConvert().
5972 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005973void
5974QCBORDecode_Private_GetDoubleConvert(QCBORDecodeContext *pMe,
5975 const uint32_t uConvertTypes,
5976 double *pdValue,
5977 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005978{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005979 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07005980 return;
5981 }
5982
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005983 QCBORError uError = QCBORDecode_GetNext(pMe, pItem);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005984 if(uError) {
5985 pMe->uLastError = (uint8_t)uError;
5986 return;
5987 }
5988
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005989 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005990 uConvertTypes,
5991 pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005992}
Laurence Lundbladec4537442020-04-14 18:53:22 -07005993
Laurence Lundbladec4537442020-04-14 18:53:22 -07005994
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005995/**
5996 * @brief Almost-public method to decode a number and convert to double (semi-private).
5997 *
5998 * @param[in] pMe The decode context.
5999 * @param[in] nLabel Label to find in map.
6000 * @param[in] uConvertTypes Bit mask list of conversion options
6001 * @param[out] pdValue The output of the conversion.
6002 * @param[in,out] pItem Temporary space to store Item, returned item.
6003 *
6004 * See QCBORDecode_GetDoubleConvertInMapN().
6005 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006006void
6007QCBORDecode_Private_GetDoubleConvertInMapN(QCBORDecodeContext *pMe,
6008 const int64_t nLabel,
6009 const uint32_t uConvertTypes,
6010 double *pdValue,
6011 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006012{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006013 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07006014 if(pMe->uLastError != QCBOR_SUCCESS) {
6015 return;
6016 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006017
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006018 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
6019 uConvertTypes,
6020 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006021}
6022
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006023
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006024/**
6025 * @brief Almost-public method to decode a number and convert to double (semi-private).
6026 *
6027 * @param[in] pMe The decode context.
6028 * @param[in] szLabel Label to find in map.
6029 * @param[in] uConvertTypes Bit mask list of conversion options
6030 * @param[out] pdValue The output of the conversion.
6031 * @param[in,out] pItem Temporary space to store Item, returned item.
6032 *
6033 * See QCBORDecode_GetDoubleConvertInMapSZ().
6034 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006035void
6036QCBORDecode_Private_GetDoubleConvertInMapSZ(QCBORDecodeContext *pMe,
6037 const char *szLabel,
6038 const uint32_t uConvertTypes,
6039 double *pdValue,
6040 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006041{
6042 if(pMe->uLastError != QCBOR_SUCCESS) {
6043 return;
6044 }
6045
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006046 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07006047 if(pMe->uLastError != QCBOR_SUCCESS) {
6048 return;
6049 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006050
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006051 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
6052 uConvertTypes,
6053 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006054}
6055
6056
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006057#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006058/**
6059 * @brief Convert a big number to double-precision float.
6060 *
6061 * @param[in] BigNum The big number to convert
6062 *
6063 * @returns The double value.
6064 *
6065 * This will always succeed. It will lose precision for larger
6066 * numbers. If the big number is too large to fit (more than
6067 * 1.7976931348623157E+308) infinity will be returned. NaN is never
6068 * returned.
6069 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006070static double
6071QCBOR_Private_ConvertBigNumToDouble(const UsefulBufC BigNum)
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07006072{
6073 double dResult;
6074
6075 dResult = 0.0;
6076 const uint8_t *pByte = BigNum.ptr;
6077 size_t uLen = BigNum.len;
6078 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006079 * is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07006080 while(uLen--) {
6081 dResult = (dResult * 256.0) + (double)*pByte++;
6082 }
6083
6084 return dResult;
6085}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006086#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
6087
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07006088
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006089
6090
6091/**
6092 * @brief Convert many number types to a double.
6093 *
6094 * @param[in] pItem The item to convert.
6095 * @param[in] uConvertTypes Bit mask list of conversion options.
6096 * @param[out] pdValue The resulting converted value.
6097 *
6098 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
6099 * in uConvertTypes.
6100 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
6101 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
6102 * or too small.
6103 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07006104static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006105QCBOR_Private_DoubleConvertAll(const QCBORItem *pItem,
6106 const uint32_t uConvertTypes,
6107 double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006108{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006109#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07006110 /*
Laurence Lundblade16a207a2021-09-18 17:22:46 -07006111 * What Every Computer Scientist Should Know About Floating-Point Arithmetic
6112 * https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
6113 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006114 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07006115
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006116#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006117 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006118 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07006119 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006120 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
6121 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
6122 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006123 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006124 }
6125 break;
6126
6127 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006128 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07006129 // Underflow gives 0, overflow gives infinity
6130 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
6131 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006132 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006133 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006134 }
6135 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006136#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006137
6138 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006139 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006140 *pdValue = QCBOR_Private_ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006141 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006142 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006143 }
6144 break;
6145
6146 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006147 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006148 *pdValue = -1-QCBOR_Private_ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006149 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006150 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006151 }
6152 break;
6153
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006154#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006155 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006156 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006157 double dMantissa = QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006158 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
6159 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006160 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006161 }
6162 break;
6163
6164 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006165 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006166 double dMantissa = -QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006167 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
6168 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006169 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006170 }
6171 break;
6172
6173 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006174 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006175 double dMantissa = QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006176 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
6177 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006178 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006179 }
6180 break;
6181
6182 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006183 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006184 double dMantissa = -1-QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006185 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
6186 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006187 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006188 }
6189 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006190#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade410c7e02020-06-25 23:35:29 -07006191
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006192 default:
6193 return QCBOR_ERR_UNEXPECTED_TYPE;
6194 }
6195
6196 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006197
6198#else
6199 (void)pItem;
6200 (void)uConvertTypes;
6201 (void)pdValue;
6202 return QCBOR_ERR_HW_FLOAT_DISABLED;
6203#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
6204
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006205}
6206
6207
6208/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006209 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006210 */
6211void
6212QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
6213 const uint32_t uConvertTypes,
6214 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006215{
6216
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006217 QCBORItem Item;
6218
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006219 QCBORDecode_Private_GetDoubleConvert(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006220
6221 if(pMe->uLastError == QCBOR_SUCCESS) {
6222 // The above conversion succeeded
6223 return;
6224 }
6225
6226 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6227 // The above conversion failed in a way that code below can't correct
6228 return;
6229 }
6230
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006231 pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
6232 uConvertTypes,
6233 pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07006234}
6235
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006236
6237/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006238 * Public function, see header qcbor/qcbor_decode.h file
6239 */
6240void
6241QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
6242 const int64_t nLabel,
6243 const uint32_t uConvertTypes,
6244 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006245{
6246 QCBORItem Item;
6247
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006248 QCBORDecode_Private_GetDoubleConvertInMapN(pMe,
6249 nLabel,
6250 uConvertTypes,
6251 pdValue,
6252 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006253
6254 if(pMe->uLastError == QCBOR_SUCCESS) {
6255 // The above conversion succeeded
6256 return;
6257 }
6258
6259 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6260 // The above conversion failed in a way that code below can't correct
6261 return;
6262 }
6263
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006264 pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
6265 uConvertTypes,
6266 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006267}
6268
6269
6270/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006271 * Public function, see header qcbor/qcbor_decode.h file
6272 */
6273void
6274QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
6275 const char *szLabel,
6276 const uint32_t uConvertTypes,
6277 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006278{
6279 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006280 QCBORDecode_Private_GetDoubleConvertInMapSZ(pMe,
6281 szLabel,
6282 uConvertTypes,
6283 pdValue,
6284 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006285
6286 if(pMe->uLastError == QCBOR_SUCCESS) {
6287 // The above conversion succeeded
6288 return;
6289 }
6290
6291 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6292 // The above conversion failed in a way that code below can't correct
6293 return;
6294 }
6295
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006296 pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
6297 uConvertTypes,
6298 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006299}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02006300#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006301
6302
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006303
6304
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006305#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006306/**
6307 * @brief Convert an integer to a big number
6308 *
6309 * @param[in] uInt The integer to convert.
6310 * @param[in] Buffer The buffer to output the big number to.
6311 *
6312 * @returns The big number or NULLUsefulBufC is the buffer is to small.
6313 *
6314 * This always succeeds unless the buffer is too small.
6315 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006316static UsefulBufC
6317QCBOR_Private_ConvertIntToBigNum(uint64_t uInt, const UsefulBuf Buffer)
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006318{
6319 while((uInt & 0xff00000000000000UL) == 0) {
6320 uInt = uInt << 8;
6321 };
6322
6323 UsefulOutBuf UOB;
6324
6325 UsefulOutBuf_Init(&UOB, Buffer);
6326
6327 while(uInt) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006328 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
6329 uInt = uInt << 8;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006330 }
6331
6332 return UsefulOutBuf_OutUBuf(&UOB);
6333}
6334
6335
Laurence Lundblade37286c02022-09-03 10:05:02 -07006336/**
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006337 * @brief Check and/or complete exponent and mantissa item.
Laurence Lundblade37286c02022-09-03 10:05:02 -07006338 *
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006339 * @param[in] pMe The decoder context.
6340 * @param[in] TagSpec Expected type(s).
6341 * @param[in,out] pItem See below.
Laurence Lundblade37286c02022-09-03 10:05:02 -07006342 *
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006343 * This is for decimal fractions and big floats, both of which are an
6344 * exponent and mantissa.
Laurence Lundblade37286c02022-09-03 10:05:02 -07006345 *
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006346 * If the item item had a tag number indicating it was a
6347 * decimal fraction or big float, then the input @c pItem will
6348 * have been decoded as exponent and mantissa. If there was
6349 * no tag number, the caller is asking this be decoded as a
6350 * big float or decimal fraction and @c pItem just has the
6351 * first item in an exponent and mantissa.
Laurence Lundblade37286c02022-09-03 10:05:02 -07006352 *
6353 * On output, the item is always a fully decoded decimal fraction or
6354 * big float.
6355 *
6356 * This errors out if the input type does not meet the TagSpec.
6357 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07006358static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006359QCBOR_Private_ExpMantissaTypeHandler(QCBORDecodeContext *pMe,
6360 const QCBOR_Private_TagSpec TagSpec,
6361 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006362{
6363 QCBORError uErr;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006364
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006365 /* pItem could either be a decoded exponent and mantissa or
6366 * the opening array of an undecoded exponent and mantissa. This
Laurence Lundblade37286c02022-09-03 10:05:02 -07006367 * check will succeed on either, but doesn't say which it was.
6368 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006369 uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07006370 if(uErr != QCBOR_SUCCESS) {
6371 goto Done;
6372 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006373
Laurence Lundblade37286c02022-09-03 10:05:02 -07006374 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006375 /* The item is an array, which means is is an undecoded exponent
6376 * and mantissa. This call consumes the items in the array and
6377 * results in a decoded exponent and mantissa in pItem. This is
Laurence Lundblade37286c02022-09-03 10:05:02 -07006378 * the case where there was no tag.
6379 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006380 uErr = QCBORDecode_Private_ExpMantissa(pMe, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006381 if(uErr != QCBOR_SUCCESS) {
6382 goto Done;
6383 }
6384
Laurence Lundblade37286c02022-09-03 10:05:02 -07006385 /* The above decode didn't determine whether it is a decimal
6386 * fraction or big num. Which of these two depends on what the
6387 * caller wants it decoded as since there is no tag, so fish the
6388 * type out of the TagSpec. */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006389 pItem->uDataType = QCBOR_Private_ExpMantissaDataType(TagSpec.uTaggedTypes[0], pItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07006390
6391 /* No need to check the type again. All that we need to know was
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006392 * that it decoded correctly as a exponent and mantissa. The
Laurence Lundblade37286c02022-09-03 10:05:02 -07006393 * QCBOR type is set out by what was requested.
6394 */
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006395 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07006396
6397 /* If the item was not an array and the check passed, then
6398 * it is a fully decoded big float or decimal fraction and
6399 * matches what is requested.
6400 */
6401
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006402Done:
6403 return uErr;
6404}
6405
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006406
Laurence Lundblade37286c02022-09-03 10:05:02 -07006407/* Some notes from the work to disable tags.
6408 *
6409 * The API for big floats and decimal fractions seems good.
6410 * If there's any issue with it it's that the code size to
6411 * implement is a bit large because of the conversion
6412 * to/from int and bignum that is required. There is no API
6413 * that doesn't do the conversion so dead stripping will never
6414 * leave that code out.
6415 *
6416 * The implementation itself seems correct, but not as clean
6417 * and neat as it could be. It could probably be smaller too.
6418 *
6419 * The implementation has three main parts / functions
6420 * - The decoding of the array of two
6421 * - All the tag and type checking for the various API functions
6422 * - Conversion to/from bignum and int
6423 *
6424 * The type checking seems like it wastes the most code for
6425 * what it needs to do.
6426 *
6427 * The inlining for the conversion is probably making the
6428 * overall code base larger.
6429 *
6430 * The tests cases could be organized a lot better and be
6431 * more thorough.
6432 *
6433 * Seems also like there could be more common code in the
6434 * first tier part of the public API. Some functions only
6435 * vary by a TagSpec.
6436 */
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006437
6438/**
6439 * @brief Common processor for exponent and mantissa.
6440 *
6441 * @param[in] pMe The decode context.
6442 * @param[in] TagSpec The expected/allowed tags.
6443 * @param[in] pItem The data item to process.
6444 * @param[out] pnMantissa The returned mantissa as an int64_t.
6445 * @param[out] pnExponent The returned exponent as an int64_t.
6446 *
6447 * This handles exponent and mantissa for base 2 and 10. This
6448 * is limited to a mantissa that is an int64_t. See also
6449 * QCBORDecode_Private_ProcessExpMantissaBig().
6450 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006451static void
6452QCBOR_Private_ProcessExpMantissa(QCBORDecodeContext *pMe,
6453 const QCBOR_Private_TagSpec TagSpec,
6454 QCBORItem *pItem,
6455 int64_t *pnMantissa,
6456 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006457{
6458 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006459
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006460 uErr = QCBOR_Private_ExpMantissaTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006461 if(uErr != QCBOR_SUCCESS) {
6462 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006463 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006464
Laurence Lundblade9b334962020-08-27 10:55:53 -07006465 switch (pItem->uDataType) {
6466
6467 case QCBOR_TYPE_DECIMAL_FRACTION:
6468 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade9b334962020-08-27 10:55:53 -07006469 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade37286c02022-09-03 10:05:02 -07006470 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
Laurence Lundblade9b334962020-08-27 10:55:53 -07006471 break;
6472
Laurence Lundblade37286c02022-09-03 10:05:02 -07006473#ifndef QCBOR_DISABLE_TAGS
6474 /* If tags are disabled, mantissas can never be big nums */
Laurence Lundblade9b334962020-08-27 10:55:53 -07006475 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
6476 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
6477 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006478 uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
Laurence Lundblade9b334962020-08-27 10:55:53 -07006479 break;
6480
6481 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
6482 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
6483 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006484 uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
Laurence Lundblade9b334962020-08-27 10:55:53 -07006485 break;
Laurence Lundblade37286c02022-09-03 10:05:02 -07006486#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade9b334962020-08-27 10:55:53 -07006487
6488 default:
6489 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
6490 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006491
6492 Done:
6493 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006494}
6495
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006496
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006497/**
6498 * @brief Decode exponent and mantissa into a big number.
6499 *
6500 * @param[in] pMe The decode context.
6501 * @param[in] TagSpec The expected/allowed tags.
6502 * @param[in] pItem Item to decode and convert.
6503 * @param[in] BufferForMantissa Buffer to output mantissa into.
6504 * @param[out] pMantissa The output mantissa.
6505 * @param[out] pbIsNegative The sign of the output.
6506 * @param[out] pnExponent The mantissa of the output.
6507 *
6508 * This is the common processing of a decimal fraction or a big float
6509 * into a big number. This will decode and consume all the CBOR items
6510 * that make up the decimal fraction or big float.
6511 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006512static void
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006513QCBORDecode_Private_ProcessExpMantissaBig(QCBORDecodeContext *pMe,
6514 const QCBOR_Private_TagSpec TagSpec,
6515 QCBORItem *pItem,
6516 const UsefulBuf BufferForMantissa,
6517 UsefulBufC *pMantissa,
6518 bool *pbIsNegative,
6519 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006520{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006521 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006522
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006523 uErr = QCBOR_Private_ExpMantissaTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006524 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006525 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006526 }
6527
6528 uint64_t uMantissa;
6529
6530 switch (pItem->uDataType) {
6531
6532 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006533 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07006534 /* See comments in ExponentiateNN() on handling INT64_MIN */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006535 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
6536 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
6537 *pbIsNegative = false;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07006538 } else if(pItem->val.expAndMantissa.Mantissa.nInt != INT64_MIN) {
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006539 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
6540 *pbIsNegative = true;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07006541 } else {
6542 uMantissa = (uint64_t)INT64_MAX+1;
6543 *pbIsNegative = true;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006544 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006545 *pMantissa = QCBOR_Private_ConvertIntToBigNum(uMantissa,
6546 BufferForMantissa);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006547 *pnExponent = pItem->val.expAndMantissa.nExponent;
6548 break;
6549
Laurence Lundblade37286c02022-09-03 10:05:02 -07006550#ifndef QCBOR_DISABLE_TAGS
6551 /* If tags are disabled, mantissas can never be big nums */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006552 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006553 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006554 *pnExponent = pItem->val.expAndMantissa.nExponent;
6555 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
6556 *pbIsNegative = false;
6557 break;
6558
6559 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006560 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006561 *pnExponent = pItem->val.expAndMantissa.nExponent;
6562 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
6563 *pbIsNegative = true;
6564 break;
Laurence Lundblade37286c02022-09-03 10:05:02 -07006565#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006566
6567 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006568 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006569 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006570
6571Done:
6572 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006573}
6574
6575
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006576/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006577 * Public function, see header qcbor/qcbor_decode.h file
6578 */
6579void
6580QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
6581 const uint8_t uTagRequirement,
6582 int64_t *pnMantissa,
6583 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006584{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006585 if(pMe->uLastError != QCBOR_SUCCESS) {
6586 return;
6587 }
6588
6589 QCBORItem Item;
6590 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6591 if(uError) {
6592 pMe->uLastError = (uint8_t)uError;
6593 return;
6594 }
6595
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006596 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006597 {
6598 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006599 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6600 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6601 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006602 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006603
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006604 QCBOR_Private_ProcessExpMantissa(pMe,
6605 TagSpec,
6606 &Item,
6607 pnMantissa,
6608 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006609}
6610
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006611
6612/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006613 * Public function, see header qcbor/qcbor_decode.h file
6614 */
6615void
6616QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
6617 const int64_t nLabel,
6618 const uint8_t uTagRequirement,
6619 int64_t *pnMantissa,
6620 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006621{
6622 if(pMe->uLastError != QCBOR_SUCCESS) {
6623 return;
6624 }
6625
6626 QCBORItem Item;
6627 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
6628
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006629 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006630 {
6631 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006632 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6633 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6634 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006635 };
6636
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006637 QCBOR_Private_ProcessExpMantissa(pMe,
6638 TagSpec,
6639 &Item,
6640 pnMantissa,
6641 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006642}
6643
6644
6645/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006646 * Public function, see header qcbor/qcbor_decode.h file
6647 */
6648void
6649QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
6650 const char *szLabel,
6651 const uint8_t uTagRequirement,
6652 int64_t *pnMantissa,
6653 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006654{
6655 if(pMe->uLastError != QCBOR_SUCCESS) {
6656 return;
6657 }
6658
6659 QCBORItem Item;
6660 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6661
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006662 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006663 {
6664 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006665 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6666 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6667 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006668 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07006669
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006670 QCBOR_Private_ProcessExpMantissa(pMe,
6671 TagSpec,
6672 &Item,
6673 pnMantissa,
6674 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006675}
6676
6677
6678/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006679 * Public function, see header qcbor/qcbor_decode.h file
6680 */
6681void
6682QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
6683 const uint8_t uTagRequirement,
6684 const UsefulBuf MantissaBuffer,
6685 UsefulBufC *pMantissa,
6686 bool *pbMantissaIsNegative,
6687 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006688{
6689 if(pMe->uLastError != QCBOR_SUCCESS) {
6690 return;
6691 }
6692
6693 QCBORItem Item;
6694 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6695 if(uError) {
6696 pMe->uLastError = (uint8_t)uError;
6697 return;
6698 }
6699
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006700 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006701 {
6702 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006703 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6704 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6705 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006706 };
6707
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006708 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
6709 TagSpec,
6710 &Item,
6711 MantissaBuffer,
6712 pMantissa,
6713 pbMantissaIsNegative,
6714 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006715}
6716
6717
6718/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006719 * Public function, see header qcbor/qcbor_decode.h file
6720 */
6721void
6722QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
6723 const int64_t nLabel,
6724 const uint8_t uTagRequirement,
6725 const UsefulBuf BufferForMantissa,
6726 UsefulBufC *pMantissa,
6727 bool *pbIsNegative,
6728 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006729{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006730 if(pMe->uLastError != QCBOR_SUCCESS) {
6731 return;
6732 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006733
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006734 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006735 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006736 if(pMe->uLastError != QCBOR_SUCCESS) {
6737 return;
6738 }
6739
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006740 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006741 {
6742 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006743 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6744 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6745 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006746 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006747
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006748 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
6749 TagSpec,
6750 &Item,
6751 BufferForMantissa,
6752 pMantissa,
6753 pbIsNegative,
6754 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006755}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006756
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006757
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006758/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006759 * Public function, see header qcbor/qcbor_decode.h file
6760 */
6761void
6762QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
6763 const char *szLabel,
6764 const uint8_t uTagRequirement,
6765 const UsefulBuf BufferForMantissa,
6766 UsefulBufC *pMantissa,
6767 bool *pbIsNegative,
6768 int64_t *pnExponent)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006769{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006770 if(pMe->uLastError != QCBOR_SUCCESS) {
6771 return;
6772 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006773
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006774 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006775 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6776 if(pMe->uLastError != QCBOR_SUCCESS) {
6777 return;
6778 }
6779
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006780 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006781 {
6782 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006783 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6784 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6785 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006786 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006787
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006788 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
6789 TagSpec,
6790 &Item,
6791 BufferForMantissa,
6792 pMantissa,
6793 pbIsNegative,
6794 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006795}
6796
6797
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006798/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006799 * Public function, see header qcbor/qcbor_decode.h file
6800 */
6801void
6802QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
6803 const uint8_t uTagRequirement,
6804 int64_t *pnMantissa,
6805 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006806{
6807 if(pMe->uLastError != QCBOR_SUCCESS) {
6808 return;
6809 }
6810
6811 QCBORItem Item;
6812 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6813 if(uError) {
6814 pMe->uLastError = (uint8_t)uError;
6815 return;
6816 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006817 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006818 {
6819 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006820 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6821 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6822 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006823 };
6824
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006825 QCBOR_Private_ProcessExpMantissa(pMe,
6826 TagSpec,
6827 &Item,
6828 pnMantissa,
6829 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006830}
6831
6832
6833/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006834 * Public function, see header qcbor/qcbor_decode.h file
6835 */
6836void
6837QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
6838 const int64_t nLabel,
6839 const uint8_t uTagRequirement,
6840 int64_t *pnMantissa,
6841 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006842{
6843 if(pMe->uLastError != QCBOR_SUCCESS) {
6844 return;
6845 }
6846
6847 QCBORItem Item;
6848 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
6849 if(pMe->uLastError != QCBOR_SUCCESS) {
6850 return;
6851 }
6852
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006853 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006854 {
6855 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006856 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6857 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6858 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006859 };
6860
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006861 QCBOR_Private_ProcessExpMantissa(pMe,
6862 TagSpec,
6863 &Item,
6864 pnMantissa,
6865 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006866}
6867
6868
6869/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006870 * Public function, see header qcbor/qcbor_decode.h file
6871 */
6872void
6873QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
6874 const char *szLabel,
6875 const uint8_t uTagRequirement,
6876 int64_t *pnMantissa,
6877 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006878{
6879 if(pMe->uLastError != QCBOR_SUCCESS) {
6880 return;
6881 }
6882
6883 QCBORItem Item;
6884 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6885 if(pMe->uLastError != QCBOR_SUCCESS) {
6886 return;
6887 }
6888
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006889 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006890 {
6891 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006892 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6893 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6894 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006895 };
6896
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006897 QCBOR_Private_ProcessExpMantissa(pMe,
6898 TagSpec,
6899 &Item,
6900 pnMantissa,
6901 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006902}
6903
6904
6905/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006906 * Public function, see header qcbor/qcbor_decode.h file
6907 */
6908void
6909QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
6910 const uint8_t uTagRequirement,
6911 const UsefulBuf MantissaBuffer,
6912 UsefulBufC *pMantissa,
6913 bool *pbMantissaIsNegative,
6914 int64_t *pnExponent)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006915{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006916 if(pMe->uLastError != QCBOR_SUCCESS) {
6917 return;
6918 }
6919
6920 QCBORItem Item;
6921 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6922 if(uError) {
6923 pMe->uLastError = (uint8_t)uError;
6924 return;
6925 }
6926
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006927 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006928 {
6929 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006930 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6931 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6932 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006933 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006934
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006935 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
6936 TagSpec,
6937 &Item,
6938 MantissaBuffer,
6939 pMantissa,
6940 pbMantissaIsNegative,
6941 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006942}
6943
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006944
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006945/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006946 * Public function, see header qcbor/qcbor_decode.h file
6947 */
6948void
6949QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
6950 const int64_t nLabel,
6951 const uint8_t uTagRequirement,
6952 const UsefulBuf BufferForMantissa,
6953 UsefulBufC *pMantissa,
6954 bool *pbIsNegative,
6955 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006956{
6957 if(pMe->uLastError != QCBOR_SUCCESS) {
6958 return;
6959 }
6960
6961 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006962 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
6963 if(pMe->uLastError != QCBOR_SUCCESS) {
6964 return;
6965 }
6966
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006967 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006968 {
6969 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006970 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6971 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6972 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006973 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006974
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006975 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
6976 TagSpec,
6977 &Item,
6978 BufferForMantissa,
6979 pMantissa,
6980 pbIsNegative,
6981 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006982}
6983
6984
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006985/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006986 * Public function, see header qcbor/qcbor_decode.h file
6987 */
6988void
6989QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
6990 const char *szLabel,
6991 const uint8_t uTagRequirement,
6992 const UsefulBuf BufferForMantissa,
6993 UsefulBufC *pMantissa,
6994 bool *pbIsNegative,
6995 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006996{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006997 if(pMe->uLastError != QCBOR_SUCCESS) {
6998 return;
6999 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007000
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007001 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007002 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
7003 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07007004 return;
7005 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07007006
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007007 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007008 {
7009 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07007010 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
7011 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
7012 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007013 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007014
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07007015 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
7016 TagSpec,
7017 &Item,
7018 BufferForMantissa,
7019 pMantissa,
7020 pbIsNegative,
7021 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07007022}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007023
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07007024#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */