blob: a0730098ab4da3cd6e416fad9c82184385c1b794 [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 Lundblade2d493002024-02-01 11:09:17 -0700887 pDecodedItem->val.uint64 = uArgument;
888 pDecodedItem->uDataType = QCBOR_TYPE_65BIT_NEG_INT;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700889 }
890 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800891
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800892 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700893}
894
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800895
896/* Make sure #define value line up as DecodeSimple counts on this. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700897#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
898#error QCBOR_TYPE_FALSE macro value wrong
899#endif
900
901#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
902#error QCBOR_TYPE_TRUE macro value wrong
903#endif
904
905#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
906#error QCBOR_TYPE_NULL macro value wrong
907#endif
908
909#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
910#error QCBOR_TYPE_UNDEF macro value wrong
911#endif
912
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700913#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
914#error QCBOR_TYPE_BREAK macro value wrong
915#endif
916
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700917#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
918#error QCBOR_TYPE_DOUBLE macro value wrong
919#endif
920
921#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
922#error QCBOR_TYPE_FLOAT macro value wrong
923#endif
924
Laurence Lundblade9b334962020-08-27 10:55:53 -0700925
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800926/**
927 * @brief Decode major type 7 -- true, false, floating-point, break...
928 *
929 * @param[in] nAdditionalInfo The lower five bits from the initial byte.
930 * @param[in] uArgument The argument from the head.
931 * @param[out] pDecodedItem The filled in decoded item.
932 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -0700933 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
934 * of half-precision disabled
935 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all float
936 * decode is disabled.
937 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of simple
938 * type in input.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700939 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700940static QCBORError
941QCBOR_Private_DecodeType7(const int nAdditionalInfo,
942 const uint64_t uArgument,
943 QCBORItem *pDecodedItem)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800944{
945 QCBORError uReturn = QCBOR_SUCCESS;
946
947 /* uAdditionalInfo is 5 bits from the initial byte. Compile time
948 * checks above make sure uAdditionalInfo values line up with
949 * uDataType values. DecodeHead() never returns an AdditionalInfo
950 * > 0x1f so cast is safe.
951 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800952 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800953
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800954 switch(nAdditionalInfo) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800955 /* No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they
956 * are caught before this is called.
957 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800958
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800959 case HALF_PREC_FLOAT: /* 25 */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700960#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800961 /* Half-precision is returned as a double. The cast to
962 * uint16_t is safe because the encoded value was 16 bits. It
963 * was widened to 64 bits to be passed in here.
964 */
965 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700966 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800967#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200968 uReturn = FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700969 break;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800970 case SINGLE_PREC_FLOAT: /* 26 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200971#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800972 /* Single precision is normally returned as a double since
973 * double is widely supported, there is no loss of precision,
974 * it makes it easy for the caller in most cases and it can
975 * be converted back to single with no loss of precision
976 *
977 * The cast to uint32_t is safe because the encoded value was
978 * 32 bits. It was widened to 64 bits to be passed in here.
979 */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700980 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800981 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uArgument);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700982#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800983 /* In the normal case, use HW to convert float to
984 * double. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700985 pDecodedItem->val.dfnum = (double)f;
986 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800987#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800988 /* Use of float HW is disabled, return as a float. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700989 pDecodedItem->val.fnum = f;
990 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
991
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800992 /* IEEE754_FloatToDouble() could be used here to return as
993 * a double, but it adds object code and most likely
994 * anyone disabling FLOAT HW use doesn't care about floats
995 * and wants to save object code.
996 */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800997#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700998 }
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200999#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1000 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -07001001 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001002
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001003 case DOUBLE_PREC_FLOAT: /* 27 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001004#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001005 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +07001006 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001007#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1008 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -07001009 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001010
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001011 case CBOR_SIMPLEV_FALSE: /* 20 */
1012 case CBOR_SIMPLEV_TRUE: /* 21 */
1013 case CBOR_SIMPLEV_NULL: /* 22 */
1014 case CBOR_SIMPLEV_UNDEF: /* 23 */
1015 case CBOR_SIMPLE_BREAK: /* 31 */
1016 break; /* nothing to do */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001017
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001018 case CBOR_SIMPLEV_ONEBYTE: /* 24 */
1019 if(uArgument <= CBOR_SIMPLE_BREAK) {
1020 /* This takes out f8 00 ... f8 1f which should be encoded
1021 * as e0 … f7
1022 */
1023 uReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001024 goto Done;
1025 }
Laurence Lundblade5e390822019-01-06 12:35:01 -08001026 /* FALLTHROUGH */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001027
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001028 default: /* 0-19 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001029 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001030 /* DecodeHead() will make uArgument equal to
1031 * nAdditionalInfo when nAdditionalInfo is < 24. This cast is
1032 * safe because the 2, 4 and 8 byte lengths of uNumber are in
1033 * the double/float cases above
Laurence Lundbladeee851742020-01-08 08:37:05 -08001034 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001035 pDecodedItem->val.uSimple = (uint8_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001036 break;
1037 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001038
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001039Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001040 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001041}
1042
1043
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001044/**
1045 * @brief Decode text and byte strings
1046 *
1047 * @param[in] pAllocator The string allocator or NULL.
1048 * @param[in] uStrLen The length of the string.
1049 * @param[in] pUInBuf The surce from which to read the string's bytes.
1050 * @param[out] pDecodedItem The filled in decoded item.
1051 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001052 * @retval QCBOR_ERR_HIT_END Unexpected end of input.
1053 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1054 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001055 *
1056 * The reads @c uStrlen bytes from @c pUInBuf and fills in @c
1057 * pDecodedItem. If @c pAllocator is not NULL then memory for the
1058 * string is allocated.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001059 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001060static QCBORError
1061QCBOR_Private_DecodeBytes(const QCBORInternalAllocator *pAllocator,
1062 const uint64_t uStrLen,
1063 UsefulInputBuf *pUInBuf,
1064 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001065{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001066 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001067
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001068 /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
1069 * CPUs. This check makes the casts to size_t below safe.
1070 *
1071 * The max is 4 bytes less than the largest sizeof() so this can be
1072 * tested by putting a SIZE_MAX length in the CBOR test input (no
1073 * one will care the limit on strings is 4 bytes shorter).
1074 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001075 if(uStrLen > SIZE_MAX-4) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001076 uReturn = QCBOR_ERR_STRING_TOO_LONG;
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001077 goto Done;
1078 }
1079
1080 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301081 if(UsefulBuf_IsNULLC(Bytes)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001082 /* Failed to get the bytes for this string item */
1083 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301084 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001085 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301086
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001087#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001088 /* Note that this is not where allocation to coalesce
1089 * indefinite-length strings is done. This is for when the caller
1090 * has requested all strings be allocated. Disabling indefinite
1091 * length strings also disables this allocate-all option.
1092 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001093 if(pAllocator) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001094 /* request to use the string allocator to make a copy */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001095 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301096 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001097 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301098 goto Done;
1099 }
1100 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001101 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001102 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301103 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001104#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1105 (void)pAllocator;
1106#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1107
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001108 /* Normal case with no string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001109 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001110
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301111Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001112 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001113}
1114
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001115
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001116/**
1117 * @brief Map the CBOR major types for strings to the QCBOR types.
1118 *
1119 * @param[in] nCBORMajorType The CBOR major type to convert.
1120 * @retturns QCBOR type number.
1121 *
1122 * This only works for the two string types.
1123 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001124static uint8_t
1125QCBOR_Private_ConvertStringMajorTypes(int nCBORMajorType)
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001126{
1127 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
1128 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
1129 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001130
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001131 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
1132 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
1133 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001134
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001135 return (uint8_t)(nCBORMajorType + 4);
1136}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001137
1138
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001139/**
1140 * @brief Map the CBOR major types for arrays/maps to the QCBOR types.
1141 *
1142 * @param[in] nCBORMajorType The CBOR major type to convert.
1143 * @retturns QCBOR type number.
1144 *
1145 * This only works for the two aggregate types.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001146 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001147static uint8_t
1148QCBORDecode_Private_ConvertArrayOrMapType(int nCBORMajorType)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001149{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001150 #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
1151 #error QCBOR_TYPE_ARRAY value not lined up with major type
1152 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001153
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001154 #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
1155 #error QCBOR_TYPE_MAP value not lined up with major type
1156 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001157
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001158 return (uint8_t)(nCBORMajorType);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001159}
1160
1161
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001162/**
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001163 * @brief Decode a single primitive data item (decode layer 6).
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001164 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001165 * @param[in] pUInBuf Input buffer to read data item from.
1166 * @param[out] pDecodedItem The filled-in decoded item.
1167 * @param[in] pAllocator The allocator to use for strings or NULL.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001168 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001169 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1170 * features
1171 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1172 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1173 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1174 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
1175 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1176 * of half-precision disabled
1177 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1178 * float decode is disabled.
1179 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1180 * simple type in input.
1181 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1182 * in input, but indefinite
1183 * lengths disabled.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001184 *
1185 * This decodes the most primitive / atomic data item. It does
1186 * no combing of data items.
1187 */
1188static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001189QCBOR_Private_DecodeAtomicDataItem(UsefulInputBuf *pUInBuf,
1190 QCBORItem *pDecodedItem,
1191 const QCBORInternalAllocator *pAllocator)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001192{
1193 QCBORError uReturn;
1194
1195 /* Get the major type and the argument. The argument could be
1196 * length of more bytes or the value depending on the major
1197 * type. nAdditionalInfo is an encoding of the length of the
1198 * uNumber and is needed to decode floats and doubles.
1199 */
1200 int nMajorType = 0;
1201 uint64_t uArgument = 0;
1202 int nAdditionalInfo = 0;
1203
1204 memset(pDecodedItem, 0, sizeof(QCBORItem));
1205
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001206 uReturn = QCBOR_Private_DecodeHead(pUInBuf, &nMajorType, &uArgument, &nAdditionalInfo);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001207 if(uReturn) {
1208 goto Done;
1209 }
1210
1211 /* At this point the major type and the argument are valid. We've
1212 * got the type and the argument that starts every CBOR data item.
1213 */
1214 switch (nMajorType) {
1215 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1216 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
1217 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1218 uReturn = QCBOR_ERR_BAD_INT;
1219 } else {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001220 uReturn = QCBOR_Private_DecodeInteger(nMajorType, uArgument, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001221 }
1222 break;
1223
1224 case CBOR_MAJOR_TYPE_BYTE_STRING: /* Major type 2 */
1225 case CBOR_MAJOR_TYPE_TEXT_STRING: /* Major type 3 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001226 pDecodedItem->uDataType = QCBOR_Private_ConvertStringMajorTypes(nMajorType);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001227 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1228 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
1229 } else {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001230 uReturn = QCBOR_Private_DecodeBytes(pAllocator, uArgument, pUInBuf, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001231 }
1232 break;
1233
1234 case CBOR_MAJOR_TYPE_ARRAY: /* Major type 4 */
1235 case CBOR_MAJOR_TYPE_MAP: /* Major type 5 */
1236 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1237 /* Indefinite-length string. */
1238#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
1239 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
1240#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1241 uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
1242 break;
1243#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1244 } else {
1245 /* Definite-length string. */
1246 if(uArgument > QCBOR_MAX_ITEMS_IN_ARRAY) {
1247 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
1248 goto Done;
1249 }
1250 /* cast OK because of check above */
1251 pDecodedItem->val.uCount = (uint16_t)uArgument;
1252 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001253 pDecodedItem->uDataType = QCBORDecode_Private_ConvertArrayOrMapType(nMajorType);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001254 break;
1255
1256 case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */
Laurence Lundblade37286c02022-09-03 10:05:02 -07001257#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001258 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1259 uReturn = QCBOR_ERR_BAD_INT;
1260 } else {
1261 pDecodedItem->val.uTagV = uArgument;
1262 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
1263 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07001264#else /* QCBOR_DISABLE_TAGS */
1265 uReturn = QCBOR_ERR_TAGS_DISABLED;
1266#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001267 break;
1268
1269 case CBOR_MAJOR_TYPE_SIMPLE:
1270 /* Major type 7: float, double, true, false, null... */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001271 uReturn = QCBOR_Private_DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001272 break;
1273
1274 default:
1275 /* Never happens because DecodeHead() should never return > 7 */
1276 uReturn = QCBOR_ERR_UNSUPPORTED;
1277 break;
1278 }
1279
1280Done:
1281 return uReturn;
1282}
1283
1284
1285/**
1286 * @brief Process indefinite-length strings (decode layer 5).
1287 *
1288 * @param[in] pMe Decoder context
1289 * @param[out] pDecodedItem The decoded item that work is done on.
1290 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001291 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1292 * features
1293 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1294 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1295 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1296 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
1297 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1298 * of half-precision disabled
1299 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1300 * float decode is disabled.
1301 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1302 * simple type in input.
1303 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1304 * in input, but indefinite
1305 * lengths disabled.
1306 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Indefinite-length string in input,
1307 * but no string allocator.
1308 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK Error in indefinite-length string.
1309 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED Indefinite-length string in
1310 * input, but indefinite-length
1311 * strings are disabled.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001312 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001313 * If @c pDecodedItem is not an indefinite-length string, this does nothing.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001314 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001315 * If it is, this loops getting the subsequent chunk data items that
1316 * make up the string. The string allocator is used to make a
1317 * contiguous buffer for the chunks. When this completes @c
1318 * pDecodedItem contains the put-together string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001319 *
1320 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001321 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001322static QCBORError
1323QCBORDecode_Private_GetNextFullString(QCBORDecodeContext *pMe,
1324 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001325{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001326 /* Aproximate stack usage
1327 * 64-bit 32-bit
1328 * local vars 32 16
1329 * 2 UsefulBufs 32 16
1330 * QCBORItem 56 52
1331 * TOTAL 120 74
1332 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001333
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001334 /* The string allocator is used here for two purposes: 1)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001335 * coalescing the chunks of an indefinite-length string, 2)
1336 * allocating storage for every string returned when requested.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001337 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001338 * The first use is below in this function. Indefinite-length
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001339 * strings cannot be processed at all without a string allocator.
1340 *
1341 * The second used is in DecodeBytes() which is called by
1342 * GetNext_Item() below. This second use unneccessary for most use
1343 * and only happens when requested in the call to
1344 * QCBORDecode_SetMemPool(). If the second use not requested then
1345 * NULL is passed for the string allocator to GetNext_Item().
1346 *
1347 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1348 * allocator altogether and thus both of these uses. It reduced the
1349 * decoder object code by about 400 bytes.
1350 */
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001351 const QCBORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001352
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001353#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001354 const QCBORInternalAllocator *pAllocator = NULL;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001355
1356 if(pMe->StringAllocator.pfAllocator) {
1357 pAllocator = &(pMe->StringAllocator);
1358 if(pMe->bStringAllocateAll) {
1359 pAllocatorForGetNext = pAllocator;
1360 }
1361 }
1362#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1363
1364 QCBORError uReturn;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001365 uReturn = QCBOR_Private_DecodeAtomicDataItem(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001366 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001367 goto Done;
1368 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001369
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001370 /* Only do indefinite-length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001371 const uint8_t uStringType = pDecodedItem->uDataType;
1372 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001373 goto Done;
1374 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001375
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001376 /* Is this a string with an indefinite length? */
1377 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1378 goto Done;
1379 }
1380
1381#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001382 /* Can't decode indefinite-length strings without a string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001383 if(pAllocator == NULL) {
1384 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1385 goto Done;
1386 }
1387
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001388 /* Loop getting chunks of the indefinite-length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001389 UsefulBufC FullString = NULLUsefulBufC;
1390
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001391 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001392 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001393 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001394 /* Pass a NULL string allocator to GetNext_Item() because the
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001395 * individual string chunks in an indefinite-length should not
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001396 * be allocated. They are always copied in the the contiguous
1397 * buffer allocated here.
1398 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001399 uReturn = QCBOR_Private_DecodeAtomicDataItem(&(pMe->InBuf), &StringChunkItem, NULL);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001400 if(uReturn) {
1401 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001402 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001403
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001404 /* Is item is the marker for end of the indefinite-length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001405 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001406 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001407 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301408 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001409 break;
1410 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001411
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001412 /* All chunks must be of the same type, the type of the item
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001413 * that introduces the indefinite-length string. This also
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001414 * catches errors where the chunk is not a string at all and an
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001415 * indefinite-length string inside an indefinite-length string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001416 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001417 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001418 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1419 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001420 break;
1421 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001422
David Navarro9123e5b2022-03-28 16:04:03 +02001423 if (StringChunkItem.val.string.len > 0) {
1424 /* The first time throurgh FullString.ptr is NULL and this is
1425 * equivalent to StringAllocator_Allocate(). Subsequently it is
1426 * not NULL and a reallocation happens.
1427 */
1428 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1429 FullString.ptr,
1430 FullString.len + StringChunkItem.val.string.len);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001431
David Navarro9123e5b2022-03-28 16:04:03 +02001432 if(UsefulBuf_IsNULL(NewMem)) {
1433 uReturn = QCBOR_ERR_STRING_ALLOCATE;
1434 break;
1435 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001436
David Navarro9123e5b2022-03-28 16:04:03 +02001437 /* Copy new string chunk to the end of accumulated string */
1438 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001439 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001440 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001441
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001442 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1443 /* Getting the item failed, clean up the allocated memory */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001444 StringAllocator_Free(pAllocator, FullString.ptr);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001445 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001446#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1447 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1448#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001449
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001450Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001451 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001452}
1453
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001454
Laurence Lundblade37286c02022-09-03 10:05:02 -07001455#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001456/**
1457 * @brief This converts a tag number to a shorter mapped value for storage.
1458 *
1459 * @param[in] pMe The decode context.
1460 * @param[in] uUnMappedTag The tag number to map
1461 * @param[out] puMappedTagNumer The stored tag number.
1462 *
1463 * @return error code.
1464 *
1465 * The main point of mapping tag numbers is make QCBORItem
1466 * smaller. With this mapping storage of 4 tags takes up 8
1467 * bytes. Without, it would take up 32 bytes.
1468 *
1469 * This maps tag numbers greater than QCBOR_LAST_UNMAPPED_TAG.
1470 * QCBOR_LAST_UNMAPPED_TAG is a little smaller than MAX_UINT16.
1471 *
1472 * See also UnMapTagNumber() and @ref QCBORItem.
1473 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001474static QCBORError
1475QCBORDecode_Private_MapTagNumber(QCBORDecodeContext *pMe,
1476 const uint64_t uUnMappedTag,
1477 uint16_t *puMappedTagNumer)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001478{
1479 if(uUnMappedTag > QCBOR_LAST_UNMAPPED_TAG) {
1480 unsigned uTagMapIndex;
1481 /* Is there room in the tag map, or is it in it already? */
1482 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
1483 if(pMe->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID64) {
1484 break;
1485 }
1486 if(pMe->auMappedTags[uTagMapIndex] == uUnMappedTag) {
1487 break;
1488 }
1489 }
1490 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1491 return QCBOR_ERR_TOO_MANY_TAGS;
1492 }
1493
1494 /* Covers the cases where tag is new and were it is already in the map */
1495 pMe->auMappedTags[uTagMapIndex] = uUnMappedTag;
1496 *puMappedTagNumer = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
1497
1498 } else {
1499 *puMappedTagNumer = (uint16_t)uUnMappedTag;
1500 }
1501
1502 return QCBOR_SUCCESS;
1503}
1504
1505
1506/**
1507 * @brief This converts a mapped tag number to the actual tag number.
1508 *
1509 * @param[in] pMe The decode context.
1510 * @param[in] uMappedTagNumber The stored tag number.
1511 *
1512 * @return The actual tag number is returned or
1513 * @ref CBOR_TAG_INVALID64 on error.
1514 *
1515 * This is the reverse of MapTagNumber()
1516 */
1517static uint64_t
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001518QCBORDecode_Private_UnMapTagNumber(const QCBORDecodeContext *pMe,
1519 const uint16_t uMappedTagNumber)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001520{
1521 if(uMappedTagNumber <= QCBOR_LAST_UNMAPPED_TAG) {
1522 return uMappedTagNumber;
1523 } else if(uMappedTagNumber == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001524 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001525 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001526 /* This won't be negative because of code below in
1527 * MapTagNumber()
1528 */
1529 const unsigned uIndex = uMappedTagNumber - (QCBOR_LAST_UNMAPPED_TAG + 1);
1530 return pMe->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001531 }
1532}
Laurence Lundblade37286c02022-09-03 10:05:02 -07001533#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001534
Laurence Lundblade9b334962020-08-27 10:55:53 -07001535
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001536/**
1537 * @brief Aggregate all tags wrapping a data item (decode layer 4).
1538 *
1539 * @param[in] pMe Decoder context
1540 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001541 *
1542 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1543 * features
1544 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1545 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1546 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1547 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
1548 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1549 * of half-precision disabled
1550 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1551 * float decode is disabled.
1552 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1553 * simple type in input.
1554 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1555 * in input, but indefinite
1556 * lengths disabled.
1557 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Indefinite-length string in input,
1558 * but no string allocator.
1559 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK Error in indefinite-length string.
1560 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED Indefinite-length string in
1561 * input, but indefinite-length
1562 * strings are disabled.
1563 * @retval QCBOR_ERR_TOO_MANY_TAGS Too many tag numbers on item.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001564 *
1565 * This loops getting atomic data items until one is not a tag
1566 * number. Usually this is largely pass-through because most
1567 * item are not tag numbers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001568 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001569static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001570QCBORDecode_Private_GetNextTagNumber(QCBORDecodeContext *pMe,
1571 QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001572{
Laurence Lundblade37286c02022-09-03 10:05:02 -07001573#ifndef QCBOR_DISABLE_TAGS
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001574 /* Accummulate the tags from multiple items here and then copy them
1575 * into the last item, the non-tag item.
1576 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001577 uint16_t auItemsTags[QCBOR_MAX_TAGS_PER_ITEM];
1578
1579 /* Initialize to CBOR_TAG_INVALID16 */
1580 #if CBOR_TAG_INVALID16 != 0xffff
1581 /* Be sure the memset does the right thing. */
1582 #err CBOR_TAG_INVALID16 tag not defined as expected
1583 #endif
1584 memset(auItemsTags, 0xff, sizeof(auItemsTags));
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001585
Laurence Lundblade9b334962020-08-27 10:55:53 -07001586 QCBORError uReturn = QCBOR_SUCCESS;
1587
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001588 /* Loop fetching data items until the item fetched is not a tag */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001589 for(;;) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001590 QCBORError uErr = QCBORDecode_Private_GetNextFullString(pMe, pDecodedItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07001591 if(uErr != QCBOR_SUCCESS) {
1592 uReturn = uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001593 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001594 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001595
Laurence Lundblade9b334962020-08-27 10:55:53 -07001596 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001597 /* Successful exit from loop; maybe got some tags, maybe not */
1598 memcpy(pDecodedItem->uTags, auItemsTags, sizeof(auItemsTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001599 break;
1600 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001601
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001602 if(auItemsTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1603 /* No room in the tag list */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001604 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001605 /* Continue on to get all tags wrapping this item even though
1606 * it is erroring out in the end. This allows decoding to
1607 * continue. This is a resource limit error, not a problem
1608 * with being well-formed CBOR.
1609 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001610 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001611 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001612 /* Slide tags over one in the array to make room at index 0.
1613 * Must use memmove because the move source and destination
1614 * overlap.
1615 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001616 memmove(&auItemsTags[1],
1617 auItemsTags,
1618 sizeof(auItemsTags) - sizeof(auItemsTags[0]));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001619
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001620 /* Map the tag */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001621 uint16_t uMappedTagNumber = 0;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001622 uReturn = QCBORDecode_Private_MapTagNumber(pMe, pDecodedItem->val.uTagV, &uMappedTagNumber);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001623 /* Continue even on error so as to consume all tags wrapping
1624 * this data item so decoding can go on. If MapTagNumber()
1625 * errors once it will continue to error.
1626 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001627 auItemsTags[0] = uMappedTagNumber;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001628 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001629
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001630Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001631 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001632
Laurence Lundblade37286c02022-09-03 10:05:02 -07001633#else /* QCBOR_DISABLE_TAGS */
1634
1635 return QCBORDecode_GetNextFullString(pMe, pDecodedItem);
1636
1637#endif /* QCBOR_DISABLE_TAGS */
1638}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001639
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001640
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001641/**
1642 * @brief Combine a map entry label and value into one item (decode layer 3).
1643 *
1644 * @param[in] pMe Decoder context
1645 * @param[out] pDecodedItem The decoded item that work is done on.
1646 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001647 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1648 * features
1649 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1650 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1651 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1652 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
1653 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1654 * of half-precision disabled
1655 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1656 * float decode is disabled.
1657 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1658 * simple type in input.
1659 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1660 * in input, but indefinite
1661 * lengths disabled.
1662 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Indefinite-length string in input,
1663 * but no string allocator.
1664 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK Error in indefinite-length string.
1665 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED Indefinite-length string in
1666 * input, but indefinite-length
1667 * strings are disabled.
1668 * @retval QCBOR_ERR_TOO_MANY_TAGS Too many tag numbers on item.
1669 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG Too many items in array.
1670 * @retval QCBOR_ERR_MAP_LABEL_TYPE Map label not string or integer.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001671 *
1672 * If a the current nesting level is a map, then this
1673 * combines pairs of items into one data item with a label
1674 * and value.
1675 *
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07001676 * This is passthrough if the current nesting level is
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001677 * not a map.
1678 *
1679 * This also implements maps-as-array mode where a map
1680 * is treated like an array to allow caller to do their
1681 * own label processing.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001682 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001683static QCBORError
1684QCBORDecode_Private_GetNextMapEntry(QCBORDecodeContext *pMe,
1685 QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001686{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001687 QCBORError uReturn = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001688 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001689 goto Done;
1690 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001691
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001692 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
1693 /* Break can't be a map entry */
1694 goto Done;
1695 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001696
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001697 if(pMe->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1698 /* Normal decoding of maps -- combine label and value into one item. */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001699
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001700 if(DecodeNesting_IsCurrentTypeMap(&(pMe->nesting))) {
1701 /* Save label in pDecodedItem and get the next which will
1702 * be the real data item.
1703 */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001704 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001705 uReturn = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001706 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001707 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001708 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001709
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301710 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001711
1712 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001713 /* strings are always good labels */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001714 pDecodedItem->label.string = LabelItem.val.string;
1715 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001716 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == pMe->uDecodeMode) {
1717 /* It's not a string and we only want strings */
1718 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001719 goto Done;
1720 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1721 pDecodedItem->label.int64 = LabelItem.val.int64;
1722 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1723 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1724 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1725 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1726 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1727 pDecodedItem->label.string = LabelItem.val.string;
1728 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1729 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1730 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001731 /* label is not an int or a string. It is an arrray
1732 * or a float or such and this implementation doesn't handle that.
1733 * Also, tags on labels are ignored.
1734 */
1735 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001736 goto Done;
1737 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001738 }
1739 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001740 /* Decoding of maps as arrays to let the caller decide what to do
1741 * about labels, particularly lables that are not integers or
1742 * strings.
1743 */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001744 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001745 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001746 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001747 goto Done;
1748 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001749 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001750 /* Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2.
1751 * Cast is needed because of integer promotion.
1752 */
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001753 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001754 }
1755 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001756
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001757Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001758 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001759}
1760
1761
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001762#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001763/**
1764 * @brief Peek and see if next data item is a break;
1765 *
1766 * @param[in] pUIB UsefulInputBuf to read from.
1767 * @param[out] pbNextIsBreak Indicate if next was a break or not.
1768 *
1769 * @return Any decoding error.
1770 *
1771 * See if next item is a CBOR break. If it is, it is consumed,
1772 * if not it is not consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001773*/
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001774static QCBORError
1775QCBOR_Private_NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001776{
1777 *pbNextIsBreak = false;
1778 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001779 QCBORItem Peek;
1780 size_t uPeek = UsefulInputBuf_Tell(pUIB);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001781 QCBORError uReturn = QCBOR_Private_DecodeAtomicDataItem(pUIB, &Peek, NULL);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001782 if(uReturn != QCBOR_SUCCESS) {
1783 return uReturn;
1784 }
1785 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001786 /* It is not a break, rewind so it can be processed normally. */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001787 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001788 } else {
1789 *pbNextIsBreak = true;
1790 }
1791 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001792
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001793 return QCBOR_SUCCESS;
1794}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001795#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001796
1797
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001798/**
1799 * @brief Ascend up nesting levels if all items in them have been consumed.
1800 *
1801 * @param[in] pMe The decode context.
1802 * @param[in] bMarkEnd If true mark end of maps/arrays with count of zero.
1803 *
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001804 * An item was just consumed, now figure out if it was the
1805 * end of an array/map map that can be closed out. That
1806 * may in turn close out the above array/map...
Laurence Lundblade642282a2020-06-23 12:00:33 -07001807*/
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001808static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001809QCBORDecode_Private_NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001810{
1811 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001812
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001813 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001814 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1815
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001816 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1817 /* Nesting level is bstr-wrapped CBOR */
1818
1819 /* Ascent for bstr-wrapped CBOR is always by explicit call
1820 * so no further ascending can happen.
1821 */
1822 break;
1823
1824 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1825 /* Level is a definite-length array/map */
1826
1827 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001828 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1829 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001830 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001831 break;
1832 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001833 /* All items in a definite-length array were consumed so it
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001834 * is time to ascend one level. This happens below.
1835 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001836
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001837#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001838 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001839 /* Level is an indefinite-length array/map. */
1840
1841 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001842 bool bIsBreak = false;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001843 uReturn = QCBOR_Private_NextIsBreak(&(pMe->InBuf), &bIsBreak);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001844 if(uReturn != QCBOR_SUCCESS) {
1845 goto Done;
1846 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001847
1848 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001849 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001850 break;
1851 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001852
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001853 /* It was a break in an indefinitelength map / array so
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001854 * it is time to ascend one level.
1855 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001856
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001857#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001858 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001859
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001860
1861 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001862
Laurence Lundblade93d89472020-10-03 22:30:50 -07001863 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001864 * QCBORDecode_ExitBoundedMode().
1865 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001866 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001867 /* Set the count to zero for definite-length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001868 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001869 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001870 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001871 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001872
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001873 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001874 break;
1875 }
1876
1877 /* Finally, actually ascend one level. */
1878 DecodeNesting_Ascend(&(pMe->nesting));
1879 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001880
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001881 uReturn = QCBOR_SUCCESS;
1882
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001883#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001884Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001885#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1886
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001887 return uReturn;
1888}
1889
1890
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001891/**
1892 * @brief Ascending & Descending out of nesting levels (decode layer 2).
1893 *
1894 * @param[in] pMe Decoder context
1895 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001896
1897 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1898 * features
1899 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1900 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1901 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1902 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
1903 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1904 * of half-precision disabled
1905 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1906 * float decode is disabled.
1907 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1908 * simple type in input.
1909 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1910 * in input, but indefinite
1911 * lengths disabled.
1912 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Indefinite-length string in input,
1913 * but no string allocator.
1914 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK Error in indefinite-length string.
1915 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED Indefinite-length string in
1916 * input, but indefinite-length
1917 * strings are disabled.
1918 * @retval QCBOR_ERR_TOO_MANY_TAGS Too many tag numbers on item.
1919 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG Too many items in array.
1920 * @retval QCBOR_ERR_MAP_LABEL_TYPE Map label not string or integer.
1921 * @retval QCBOR_ERR_NO_MORE_ITEMS Need more items for map or array.
1922 * @retval QCBOR_ERR_BAD_BREAK Indefinite-length break in wrong
1923 * place.
1924 * @retval QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP Nesting deeper than QCBOR
1925 * can handle.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001926 *
1927 * This handles the traversal descending into and asecnding out of
1928 * maps, arrays and bstr-wrapped CBOR. It figures out the ends of
1929 * definite- and indefinte-length maps and arrays by looking at the
1930 * item count or finding CBOR breaks. It detects the ends of the
1931 * top-level sequence and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001932 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001933static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001934QCBORDecode_Private_GetNextMapOrArray(QCBORDecodeContext *pMe,
1935 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001936{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001937 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001938 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001939
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001940 /* If out of bytes to consume, it is either the end of the
1941 * top-level sequence of some bstr-wrapped CBOR that was entered.
1942 *
1943 * In the case of bstr-wrapped CBOR, the length of the
1944 * UsefulInputBuf was set to that of the bstr-wrapped CBOR. When
1945 * the bstr-wrapped CBOR is exited, the length is set back to the
1946 * top-level's length or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001947 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001948 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001949 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001950 goto Done;
1951 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001952
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001953 /* Check to see if at the end of a bounded definite-length map or
1954 * array. The check for a break ending indefinite-length array is
1955 * later in QCBORDecode_NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001956 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001957 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001958 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001959 goto Done;
1960 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001961
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001962 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001963 uReturn = QCBORDecode_Private_GetNextMapEntry(pMe, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001964 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1965 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001966 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001967 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301968
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001969 /* Breaks ending arrays/maps are processed later in the call to
1970 * QCBORDecode_NestLevelAscender(). They should never show up here.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001971 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301972 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001973 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301974 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301975 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001976
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001977 /* Record the nesting level for this data item before processing
1978 * any of decrementing and descending.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001979 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001980 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001981
Laurence Lundblade642282a2020-06-23 12:00:33 -07001982
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001983 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001984 if(QCBORItem_IsMapOrArray(*pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001985 /* If the new item is a map or array, descend.
1986 *
1987 * Empty indefinite-length maps and arrays are descended into,
1988 * but then ascended out of in the next chunk of code.
1989 *
1990 * Maps and arrays do count as items in the map/array that
1991 * encloses them so a decrement needs to be done for them too,
1992 * but that is done only when all the items in them have been
1993 * processed, not when they are opened with the exception of an
1994 * empty map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001995 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001996 QCBORError uDescendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001997 uDescendErr = DecodeNesting_DescendMapOrArray(&(pMe->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001998 pDecodedItem->uDataType,
1999 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002000 if(uDescendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002001 /* This error is probably a traversal error and it overrides
2002 * the non-traversal error.
2003 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002004 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002005 goto Done;
2006 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07002007 }
2008
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002009 if(!QCBORItem_IsMapOrArray(*pDecodedItem) ||
2010 QCBORItem_IsEmptyDefiniteLengthMapOrArray(*pDecodedItem) ||
2011 QCBORItem_IsIndefiniteLengthMapOrArray(*pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002012 /* The following cases are handled here:
2013 * - A non-aggregate item like an integer or string
2014 * - An empty definite-length map or array
2015 * - An indefinite-length map or array that might be empty or might not.
2016 *
2017 * QCBORDecode_NestLevelAscender() does the work of decrementing the count
2018 * for an definite-length map/array and break detection for an
2019 * indefinite-0length map/array. If the end of the map/array was
2020 * reached, then it ascends nesting levels, possibly all the way
2021 * to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002022 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002023 QCBORError uAscendErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002024 uAscendErr = QCBORDecode_Private_NestLevelAscender(pMe, true);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002025 if(uAscendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002026 /* This error is probably a traversal error and it overrides
2027 * the non-traversal error.
2028 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002029 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002030 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07002031 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05302032 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002033
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07002034 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002035 /* Tell the caller what level is next. This tells them what
2036 * maps/arrays were closed out and makes it possible for them to
2037 * reconstruct the tree with just the information returned in a
2038 * QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07002039 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002040 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07002041 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002042 pDecodedItem->uNextNestLevel = 0;
2043 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002044 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002045 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002046
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002047Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002048 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002049}
2050
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002051
Laurence Lundblade37286c02022-09-03 10:05:02 -07002052#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002053/**
2054 * @brief Shift 0th tag out of the tag list.
2055 *
2056 * pDecodedItem[in,out] The data item to convert.
2057 *
2058 * The 0th tag is discarded. \ref CBOR_TAG_INVALID16 is
2059 * shifted into empty slot at the end of the tag list.
2060 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002061static void
2062QCBOR_Private_ShiftTags(QCBORItem *pDecodedItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002063{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002064 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM-1; i++) {
2065 pDecodedItem->uTags[i] = pDecodedItem->uTags[i+1];
2066 }
2067 pDecodedItem->uTags[QCBOR_MAX_TAGS_PER_ITEM-1] = CBOR_TAG_INVALID16;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002068}
Laurence Lundblade37286c02022-09-03 10:05:02 -07002069#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002070
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07002071
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002072/**
2073 * @brief Convert different epoch date formats in to the QCBOR epoch date format
2074 *
2075 * pDecodedItem[in,out] The data item to convert.
2076 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07002077 * @retval QCBOR_ERR_DATE_OVERFLOW 65-bit negative integer.
2078 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED Float-point date in input,
2079 * floating-point date disabled.
2080 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point date in input,
2081 * all floating-point disabled.
2082 * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT Unexpected and unrecoverable
2083 * error decoding date.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002084 *
2085 * The epoch date tag defined in QCBOR allows for floating-point
2086 * dates. It even allows a protocol to flop between date formats when
2087 * ever it wants. Floating-point dates aren't that useful as they are
2088 * only needed for dates beyond the age of the earth.
2089 *
2090 * This converts all the date formats into one format of an unsigned
2091 * integer plus a floating-point fraction.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002092 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002093static QCBORError
2094QCBOR_Private_DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002095{
Laurence Lundbladec7114722020-08-13 05:11:40 -07002096 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002097
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002098#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade59289e52019-12-30 13:44:37 -08002099 pDecodedItem->val.epochDate.fSecondsFraction = 0;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002100#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002101
2102 switch (pDecodedItem->uDataType) {
2103
2104 case QCBOR_TYPE_INT64:
2105 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
2106 break;
2107
2108 case QCBOR_TYPE_UINT64:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002109 /* This only happens for CBOR type 0 > INT64_MAX so it is
2110 * always an overflow.
2111 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002112 uReturn = QCBOR_ERR_DATE_OVERFLOW;
2113 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002114 break;
2115
2116 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07002117 case QCBOR_TYPE_FLOAT:
2118#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08002119 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002120 /* Convert working value to double if input was a float */
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07002121 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002122 pDecodedItem->val.dfnum :
2123 (double)pDecodedItem->val.fnum;
2124
2125 /* The conversion from float to integer requires overflow
2126 * detection since floats can be much larger than integers.
2127 * This implementation errors out on these large float values
2128 * since they are beyond the age of the earth.
2129 *
2130 * These constants for the overflow check are computed by the
2131 * compiler. They are not computed at run time.
2132 *
2133 * The factor of 0x7ff is added/subtracted to avoid a
2134 * rounding error in the wrong direction when the compiler
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002135 * computes these constants. There is rounding because a
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002136 * 64-bit integer has 63 bits of precision where a double
2137 * only has 53 bits. Without the 0x7ff factor, the compiler
2138 * may round up and produce a double for the bounds check
2139 * that is larger than can be stored in a 64-bit integer. The
2140 * amount of 0x7ff is picked because it has 11 bits set.
2141 *
2142 * Without the 0x7ff there is a ~30 minute range of time
2143 * values 10 billion years in the past and in the future
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002144 * where this code could go wrong. Some compilers
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002145 * generate a warning or error without the 0x7ff.
2146 */
2147 const double dDateMax = (double)(INT64_MAX - 0x7ff);
2148 const double dDateMin = (double)(INT64_MIN + 0x7ff);
2149
2150 if(isnan(d) || d > dDateMax || d < dDateMin) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07002151 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002152 goto Done;
2153 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002154
2155 /* The actual conversion */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002156 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07002157 pDecodedItem->val.epochDate.fSecondsFraction =
2158 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002159 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002160#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade4b270642020-08-14 12:53:07 -07002161
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002162 uReturn = QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07002163 goto Done;
2164
Laurence Lundblade9682a532020-06-06 18:33:04 -07002165#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002166 break;
2167
2168 default:
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002169 /* It's the arrays and maps that are unrecoverable because
2170 * they are not consumed here. Since this is just an error
2171 * condition, no extra code is added here to make the error
2172 * recoverable for non-arrays and maps like strings. */
2173 uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002174 goto Done;
2175 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002176
Laurence Lundblade59289e52019-12-30 13:44:37 -08002177 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
2178
2179Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07002180 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002181}
2182
2183
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002184/**
2185 * @brief Convert the days epoch date.
2186 *
2187 * pDecodedItem[in,out] The data item to convert.
2188 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07002189 * @retval QCBOR_ERR_DATE_OVERFLOW 65-bit negative integer.
2190 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED Float-point date in input,
2191 * floating-point date disabled.
2192 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point date in input,
2193 * all floating-point disabled.
2194 * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT Unexpected and unrecoverable
2195 * error decoding date.
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002196 *
2197 * This is much simpler than the other epoch date format because
2198 * floating-porint is not allowed. This is mostly a simple type check.
2199 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002200static QCBORError
2201QCBOR_Private_DecodeDaysEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002202{
2203 QCBORError uReturn = QCBOR_SUCCESS;
2204
2205 switch (pDecodedItem->uDataType) {
2206
2207 case QCBOR_TYPE_INT64:
2208 pDecodedItem->val.epochDays = pDecodedItem->val.int64;
2209 break;
2210
2211 case QCBOR_TYPE_UINT64:
2212 /* This only happens for CBOR type 0 > INT64_MAX so it is
2213 * always an overflow.
2214 */
2215 uReturn = QCBOR_ERR_DATE_OVERFLOW;
2216 goto Done;
2217 break;
2218
2219 default:
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002220 /* It's the arrays and maps that are unrecoverable because
2221 * they are not consumed here. Since this is just an error
2222 * condition, no extra code is added here to make the error
2223 * recoverable for non-arrays and maps like strings. */
2224 uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002225 goto Done;
2226 break;
2227 }
2228
2229 pDecodedItem->uDataType = QCBOR_TYPE_DAYS_EPOCH;
2230
2231Done:
2232 return uReturn;
2233}
2234
2235
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002236#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade37286c02022-09-03 10:05:02 -07002237
2238/* Forward declaration is necessary for
2239 * QCBORDecode_MantissaAndExponent(). to be able to decode bignum
2240 * tags in the mantissa. If the mantissa is a decimal fraction or big
2241 * float in error, this will result in a recurive call to
2242 * QCBORDecode_MantissaAndExponent(), but the recursion will unwined
2243 * correctly and the correct error is returned.
2244 */
2245static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002246QCBORDecode_Private_GetNextTagContent(QCBORDecodeContext *pMe,
2247 QCBORItem *pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07002248
2249
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002250/**
2251 * @brief Decode decimal fractions and big floats.
2252 *
2253 * @param[in] pMe The decode context.
2254 * @param[in,out] pDecodedItem On input the array data item that
2255 * holds the mantissa and exponent. On
2256 * output the decoded mantissa and
2257 * exponent.
2258 *
2259 * @returns Decoding errors from getting primitive data items or
2260 * \ref QCBOR_ERR_BAD_EXP_AND_MANTISSA.
2261 *
Laurence Lundblade37286c02022-09-03 10:05:02 -07002262 * When called pDecodedItem must be the array with two members, the
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002263 * exponent and mantissa.
2264 *
2265 * This will fetch and decode the exponent and mantissa and put the
2266 * result back into pDecodedItem.
Laurence Lundblade37286c02022-09-03 10:05:02 -07002267 *
2268 * This does no checking or processing of tag numbers. That is to be
2269 * done by the code that calls this.
2270 *
2271 * This stuffs the type of the mantissa into pDecodedItem with the expectation
2272 * the caller will process it.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002273 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07002274static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002275QCBORDecode_Private_ExpMantissa(QCBORDecodeContext *pMe,
2276 QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002277{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002278 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002279
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002280 /* --- Make sure it is an array; track nesting level of members --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002281 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002282 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002283 goto Done;
2284 }
2285
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002286 /* A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundblade37286c02022-09-03 10:05:02 -07002287 * definite-length arrays, but not for indefinite. Instead remember
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002288 * the nesting level the two integers must be at, which is one
2289 * deeper than that of the array.
2290 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002291 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
2292
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002293 /* --- Get the exponent --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002294 QCBORItem exponentItem;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002295 uReturn = QCBORDecode_Private_GetNextMapOrArray(pMe, &exponentItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002296 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002297 goto Done;
2298 }
2299 if(exponentItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002300 /* Array is empty or a map/array encountered when expecting an int */
2301 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002302 goto Done;
2303 }
2304 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002305 /* Data arriving as an unsigned int < INT64_MAX has been
2306 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2307 * also means that the only data arriving here of type
2308 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2309 * and thus an error that will get handled in the next else.
2310 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002311 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
2312 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002313 /* Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX */
2314 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002315 goto Done;
2316 }
2317
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002318 /* --- Get the mantissa --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002319 QCBORItem mantissaItem;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002320 uReturn = QCBORDecode_Private_GetNextTagContent(pMe, &mantissaItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002321 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002322 goto Done;
2323 }
2324 if(mantissaItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002325 /* Mantissa missing or map/array encountered when expecting number */
2326 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002327 goto Done;
2328 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002329 /* Stuff the mantissa data type into the item to send it up to the
2330 * the next level. */
2331 pDecodedItem->uDataType = mantissaItem.uDataType;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002332 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002333 /* Data arriving as an unsigned int < INT64_MAX has been
2334 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2335 * also means that the only data arriving here of type
2336 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2337 * and thus an error that will get handled in an else below.
2338 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002339 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002340#ifndef QCBOR_DISABLE_TAGS
2341 /* With tags fully disabled a big number mantissa will error out
2342 * in the call to QCBORDecode_GetNextWithTags() because it has
2343 * a tag number.
2344 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002345 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
2346 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002347 /* Got a good big num mantissa */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002348 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002349#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002350 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002351 /* Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX */
2352 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002353 goto Done;
2354 }
2355
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002356 /* --- Check that array only has the two numbers --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002357 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002358 /* Extra items in the decimal fraction / big float */
Laurence Lundblade37286c02022-09-03 10:05:02 -07002359 /* Improvement: this should probably be an unrecoverable error. */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002360 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002361 goto Done;
2362 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002363 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002364
2365Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002366 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002367}
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002368#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002369
2370
Laurence Lundblade37286c02022-09-03 10:05:02 -07002371#ifndef QCBOR_DISABLE_TAGS
2372
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002373#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002374/**
2375 * @brief Decode the MIME type tag
2376 *
2377 * @param[in,out] pDecodedItem The item to decode.
2378 *
2379 * Handle the text and binary MIME type tags. Slightly too complicated
2380 * f or ProcessTaggedString() because the RFC 7049 MIME type was
2381 * incorreclty text-only.
2382 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002383static QCBORError
2384QCBOR_Private_DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002385{
2386 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
2387 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07002388 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002389 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
2390 } else {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002391 /* It's the arrays and maps that are unrecoverable because
2392 * they are not consumed here. Since this is just an error
2393 * condition, no extra code is added here to make the error
2394 * recoverable for non-arrays and maps like strings. */
2395 return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002396 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002397
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002398 return QCBOR_SUCCESS;
2399}
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002400#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002401
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002402/**
Laurence Lundblade99615302020-11-29 11:19:47 -08002403 * Table of CBOR tags whose content is either a text string or a byte
2404 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
2405 * of uQCBORtype indicates the content should be a byte string rather
2406 * than a text string
2407 */
2408struct StringTagMapEntry {
2409 uint16_t uTagNumber;
2410 uint8_t uQCBORtype;
2411};
2412
2413#define IS_BYTE_STRING_BIT 0x80
2414#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
2415
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002416static const struct StringTagMapEntry QCBOR_Private_StringTagMap[] = {
Laurence Lundblade99615302020-11-29 11:19:47 -08002417 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002418 {CBOR_TAG_DAYS_STRING, QCBOR_TYPE_DAYS_STRING},
Laurence Lundblade99615302020-11-29 11:19:47 -08002419 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
2420 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
2421 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
2422 {CBOR_TAG_URI, QCBOR_TYPE_URI},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002423#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002424 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
2425 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
2426 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
2427 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002428#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade99615302020-11-29 11:19:47 -08002429 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
2430 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
2431};
2432
2433
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002434/**
2435 * @brief Process standard CBOR tags whose content is a string
2436 *
2437 * @param[in] uTag The tag.
2438 * @param[in,out] pDecodedItem The data item.
2439 *
2440 * @returns This returns QCBOR_SUCCESS if the tag was procssed,
2441 * \ref QCBOR_ERR_UNSUPPORTED if the tag was not processed and
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002442 * \ref QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT if the content type was wrong for the tag.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002443 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002444 * Process the CBOR tags that whose content is a byte string or a text
2445 * string and for which the string is just passed on to the caller.
2446 *
2447 * This maps the CBOR tag to the QCBOR type and checks the content
2448 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08002449 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08002450 * possible.
Laurence Lundblade99615302020-11-29 11:19:47 -08002451 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002452static QCBORError
2453QCBOR_Private_ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002454{
Laurence Lundblade99615302020-11-29 11:19:47 -08002455 /* This only works on tags that were not mapped; no need for other yet */
2456 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
2457 return QCBOR_ERR_UNSUPPORTED;
2458 }
2459
2460 unsigned uIndex;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002461 for(uIndex = 0; QCBOR_Private_StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
2462 if(QCBOR_Private_StringTagMap[uIndex].uTagNumber == uTag) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002463 break;
2464 }
2465 }
2466
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002467 const uint8_t uQCBORType = QCBOR_Private_StringTagMap[uIndex].uQCBORtype;
Laurence Lundblade99615302020-11-29 11:19:47 -08002468 if(uQCBORType == QCBOR_TYPE_NONE) {
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002469 /* repurpose this error to mean not handled here */
Laurence Lundblade99615302020-11-29 11:19:47 -08002470 return QCBOR_ERR_UNSUPPORTED;
2471 }
2472
2473 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
2474 if(uQCBORType & IS_BYTE_STRING_BIT) {
2475 uExpectedType = QCBOR_TYPE_BYTE_STRING;
2476 }
2477
2478 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002479 /* It's the arrays and maps that are unrecoverable because
2480 * they are not consumed here. Since this is just an error
2481 * condition, no extra code is added here to make the error
2482 * recoverable for non-arrays and maps like strings. */
2483 return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002484 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002485
Laurence Lundblade99615302020-11-29 11:19:47 -08002486 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002487 return QCBOR_SUCCESS;
2488}
Laurence Lundblade37286c02022-09-03 10:05:02 -07002489#endif /* QCBOR_DISABLE_TAGS */
2490
2491
2492#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07002493/**
2494 * @brief Figures out data type for exponent mantissa tags.
2495 *
2496 * @param[in] uTagToProcess Either @ref CBOR_TAG_DECIMAL_FRACTION or
2497 * @ref CBOR_TAG_BIG_FLOAT.
2498 * @param[in] pDecodedItem Item being decoded.
2499 *
2500 * @returns One of the 6 values between \ref QCBOR_TYPE_DECIMAL_FRACTION
2501 * and @ref QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM.
2502 *
2503 * Does mapping between a CBOR tag number and a QCBOR type. with a
2504 * little bit of logic and arithmatic.
2505 *
2506 * Used in serveral contexts. Does the work where sometimes the data
2507 * item is explicitly tagged and sometimes not.
Laurence Lundblade37286c02022-09-03 10:05:02 -07002508 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002509static uint8_t
2510QCBOR_Private_ExpMantissaDataType(const uint16_t uTagToProcess,
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07002511 const QCBORItem *pDecodedItem)
Laurence Lundblade37286c02022-09-03 10:05:02 -07002512{
2513 uint8_t uBase = uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ?
2514 QCBOR_TYPE_DECIMAL_FRACTION :
2515 QCBOR_TYPE_BIGFLOAT;
2516 if(pDecodedItem->uDataType != QCBOR_TYPE_INT64) {
2517 uBase = (uint8_t)(uBase + pDecodedItem->uDataType - QCBOR_TYPE_POSBIGNUM + 1);
2518 }
2519 return uBase;
2520}
2521#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002522
2523
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002524/**
2525 * @brief Decode tag content for select tags (decoding layer 1).
2526 *
2527 * @param[in] pMe The decode context.
2528 * @param[out] pDecodedItem The decoded item.
2529 *
2530 * @return Decoding error code.
2531 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002532 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
2533 * but the whole tag was not decoded. Here, the whole tags (tag number
2534 * and tag content) that are supported by QCBOR are decoded. This is a
2535 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002536 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002537static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002538QCBORDecode_Private_GetNextTagContent(QCBORDecodeContext *pMe,
2539 QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002540{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002541 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002542
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002543 uReturn = QCBORDecode_Private_GetNextMapOrArray(pMe, pDecodedItem);
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002544 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002545 goto Done;
2546 }
2547
Laurence Lundblade37286c02022-09-03 10:05:02 -07002548#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002549 /* When there are no tag numbers for the item, this exits first
2550 * thing and effectively does nothing.
2551 *
2552 * This loops over all the tag numbers accumulated for this item
2553 * trying to decode and interpret them. This stops at the end of
2554 * the list or at the first tag number that can't be interpreted by
2555 * this code. This is effectively a recursive processing of the
2556 * tags number list that handles nested tags.
2557 */
2558 while(1) {
2559 /* Don't bother to unmap tags via QCBORITem.uTags since this
2560 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2561 */
2562 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002563
Laurence Lundblade99615302020-11-29 11:19:47 -08002564 if(uTagToProcess == CBOR_TAG_INVALID16) {
2565 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002566 break;
2567
Laurence Lundblade99615302020-11-29 11:19:47 -08002568 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002569 uReturn = QCBOR_Private_DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002570
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002571 } else if(uTagToProcess == CBOR_TAG_DAYS_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002572 uReturn = QCBOR_Private_DecodeDaysEpoch(pDecodedItem);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002573
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002574#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002575 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2576 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002577 uReturn = QCBORDecode_Private_ExpMantissa(pMe, pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07002578 /* --- Which is it, decimal fraction or a bigfloat? --- */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002579 pDecodedItem->uDataType = QCBOR_Private_ExpMantissaDataType(uTagToProcess, pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07002580
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002581#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002582#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002583 } else if(uTagToProcess == CBOR_TAG_MIME ||
2584 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002585 uReturn = QCBOR_Private_DecodeMIME(pDecodedItem);
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002586#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002587
Laurence Lundblade99615302020-11-29 11:19:47 -08002588 } else {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002589 /* See if it is a passthrough byte/text string tag; process if so */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002590 uReturn = QCBOR_Private_ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002591
Laurence Lundblade99615302020-11-29 11:19:47 -08002592 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002593 /* It wasn't a passthrough byte/text string tag so it is
Laurence Lundblade99615302020-11-29 11:19:47 -08002594 * an unknown tag. This is the exit from the loop on the
2595 * first unknown tag. It is a successful exit.
2596 */
2597 uReturn = QCBOR_SUCCESS;
2598 break;
2599 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002600 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002601
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002602 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002603 /* Error exit from the loop */
2604 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002605 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002606
2607 /* A tag was successfully processed, shift it out of the list of
2608 * tags returned. This is the loop increment.
2609 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002610 QCBOR_Private_ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002611 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002612#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002613
2614Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002615 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002616}
2617
2618
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002619/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002620 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002621 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002622QCBORError
2623QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2624{
2625 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002626 uErr = QCBORDecode_Private_GetNextTagContent(pMe, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002627 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002628 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2629 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2630 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002631 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002632}
2633
2634
2635/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002636 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002637 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002638QCBORError
2639QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2640{
2641 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2642 const UsefulInputBuf Save = pMe->InBuf;
2643
2644 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2645
2646 pMe->nesting = SaveNesting;
2647 pMe->InBuf = Save;
2648
2649 return uErr;
2650}
2651
2652
2653/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002654 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002655 */
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002656void
2657QCBORDecode_VPeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2658{
2659 if(pMe->uLastError != QCBOR_SUCCESS) {
2660 return;
2661 }
2662
2663 pMe->uLastError = (uint8_t)QCBORDecode_PeekNext(pMe, pDecodedItem);
2664}
2665
2666
2667/*
2668 * Public function, see header qcbor/qcbor_decode.h file
2669 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002670void
2671QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002672{
2673 if(pMe->uLastError != QCBOR_SUCCESS) {
2674 return;
2675 }
2676
2677 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2678}
2679
2680
2681/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002682 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002683 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002684QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002685QCBORDecode_GetNextWithTags(QCBORDecodeContext *pMe,
2686 QCBORItem *pDecodedItem,
2687 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002688{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002689#ifndef QCBOR_DISABLE_TAGS
2690
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002691 QCBORError uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002692
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002693 uReturn = QCBORDecode_GetNext(pMe, pDecodedItem);
2694 if(uReturn != QCBOR_SUCCESS) {
2695 return uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002696 }
2697
2698 if(pTags != NULL) {
2699 pTags->uNumUsed = 0;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002700 /* Reverse the order because pTags is reverse of QCBORItem.uTags. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002701 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2702 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002703 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002704 }
2705 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2706 return QCBOR_ERR_TOO_MANY_TAGS;
2707 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002708 pTags->puTags[pTags->uNumUsed] = QCBORDecode_Private_UnMapTagNumber(pMe,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002709 pTags->uNumUsed++;
2710 }
2711 }
2712
2713 return QCBOR_SUCCESS;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002714
2715#else /* QCBOR_DISABLE_TAGS */
2716 (void)pMe;
2717 (void)pDecodedItem;
2718 (void)pTags;
2719 return QCBOR_ERR_TAGS_DISABLED;
2720#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002721}
2722
2723
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002724/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002725 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302726 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002727bool
2728QCBORDecode_IsTagged(QCBORDecodeContext *pMe,
2729 const QCBORItem *pItem,
2730 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002731{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002732#ifndef QCBOR_DISABLE_TAGS
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002733 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2734 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002735 break;
2736 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002737 if(QCBORDecode_Private_UnMapTagNumber(pMe, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002738 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002739 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002740 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002741#else /* QCBOR_TAGS_DISABLED */
2742 (void)pMe;
2743 (void)pItem;
2744 (void)uTag;
2745#endif /* QCBOR_TAGS_DISABLED */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002746
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002747 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002748}
2749
2750
2751/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002752 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002753 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002754QCBORError
2755QCBORDecode_PartialFinish(QCBORDecodeContext *pMe, size_t *puConsumed)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002756{
Laurence Lundblade87495732021-02-26 10:05:55 -07002757 if(puConsumed != NULL) {
2758 *puConsumed = pMe->InBuf.cursor;
2759 }
2760
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002761 QCBORError uReturn = pMe->uLastError;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002762
2763 if(uReturn != QCBOR_SUCCESS) {
2764 goto Done;
2765 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002766
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002767 /* Error out if all the maps/arrays are not closed out */
2768 if(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002769 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002770 goto Done;
2771 }
2772
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002773 /* Error out if not all the bytes are consumed */
2774 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002775 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002776 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002777
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002778Done:
Laurence Lundblade87495732021-02-26 10:05:55 -07002779 return uReturn;
2780}
2781
2782
2783/*
2784 * Public function, see header qcbor/qcbor_decode.h file
2785 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002786QCBORError
2787QCBORDecode_Finish(QCBORDecodeContext *pMe)
Laurence Lundblade87495732021-02-26 10:05:55 -07002788{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002789#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002790 /* Call the destructor for the string allocator if there is one.
2791 * Always called, even if there are errors; always have to clean up.
2792 */
2793 StringAllocator_Destruct(&(pMe->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002794#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002795
Laurence Lundblade87495732021-02-26 10:05:55 -07002796 return QCBORDecode_PartialFinish(pMe, NULL);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002797}
2798
2799
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002800/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002801 * Public function, see header qcbor/qcbor_decode.h file
2802 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002803uint64_t
2804QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2805 const QCBORItem *pItem,
2806 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002807{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002808#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002809 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2810 return CBOR_TAG_INVALID64;
2811 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002812 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2813 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002814 } else {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002815 return QCBORDecode_Private_UnMapTagNumber(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002816 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002817#else /* QCBOR_DISABLE_TAGS */
2818 (void)pMe;
2819 (void)pItem;
2820 (void)uIndex;
2821
2822 return CBOR_TAG_INVALID64;
2823#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002824}
2825
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002826
Laurence Lundblade9b334962020-08-27 10:55:53 -07002827/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002828 * Public function, see header qcbor/qcbor_decode.h file
2829 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002830uint64_t
2831QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2832 uint32_t uIndex)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002833{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002834#ifndef QCBOR_DISABLE_TAGS
2835
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002836 if(pMe->uLastError != QCBOR_SUCCESS) {
2837 return CBOR_TAG_INVALID64;
2838 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002839 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2840 return CBOR_TAG_INVALID64;
2841 } else {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002842 return QCBORDecode_Private_UnMapTagNumber(pMe, pMe->uLastTags[uIndex]);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002843 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002844#else /* QCBOR_DISABLE_TAGS */
2845 (void)pMe;
2846 (void)uIndex;
2847
2848 return CBOR_TAG_INVALID64;
2849#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002850}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002851
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002852
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002853
2854
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002855#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002856
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002857/* ===========================================================================
2858 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002859
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002860 This implements a simple sting allocator for indefinite-length
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002861 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2862 implements the function type QCBORStringAllocate and allows easy
2863 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002864
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002865 This particular allocator is built-in for convenience. The caller
2866 can implement their own. All of this following code will get
2867 dead-stripped if QCBORDecode_SetMemPool() is not called.
2868
2869 This is a very primitive memory allocator. It does not track
2870 individual allocations, only a high-water mark. A free or
2871 reallocation must be of the last chunk allocated.
2872
2873 The size of the pool and offset to free memory are packed into the
2874 first 8 bytes of the memory pool so we don't have to keep them in
2875 the decode context. Since the address of the pool may not be
2876 aligned, they have to be packed and unpacked as if they were
2877 serialized data of the wire or such.
2878
2879 The sizes packed in are uint32_t to be the same on all CPU types
2880 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002881 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002882
2883
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002884static int
Laurence Lundbladeee851742020-01-08 08:37:05 -08002885MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002886{
2887 // Use of UsefulInputBuf is overkill, but it is convenient.
2888 UsefulInputBuf UIB;
2889
Laurence Lundbladeee851742020-01-08 08:37:05 -08002890 // Just assume the size here. It was checked during SetUp so
2891 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002892 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002893 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2894 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2895 return UsefulInputBuf_GetError(&UIB);
2896}
2897
2898
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002899static int
Laurence Lundbladeee851742020-01-08 08:37:05 -08002900MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002901{
2902 // Use of UsefulOutBuf is overkill, but convenient. The
2903 // length check performed here is useful.
2904 UsefulOutBuf UOB;
2905
2906 UsefulOutBuf_Init(&UOB, Pool);
2907 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2908 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2909 return UsefulOutBuf_GetError(&UOB);
2910}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002911
2912
2913/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002914 Internal function for an allocation, reallocation free and destuct.
2915
2916 Having only one function rather than one each per mode saves space in
2917 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002918
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002919 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2920 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002921static UsefulBuf
2922MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002923{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002924 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002925
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002926 uint32_t uPoolSize;
2927 uint32_t uFreeOffset;
2928
2929 if(uNewSize > UINT32_MAX) {
2930 // This allocator is only good up to 4GB. This check should
2931 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2932 goto Done;
2933 }
2934 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2935
2936 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2937 goto Done;
2938 }
2939
2940 if(uNewSize) {
2941 if(pMem) {
2942 // REALLOCATION MODE
2943 // Calculate pointer to the end of the memory pool. It is
2944 // assumed that pPool + uPoolSize won't wrap around by
2945 // assuming the caller won't pass a pool buffer in that is
2946 // not in legitimate memory space.
2947 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2948
2949 // Check that the pointer for reallocation is in the range of the
2950 // pool. This also makes sure that pointer math further down
2951 // doesn't wrap under or over.
2952 if(pMem >= pPool && pMem < pPoolEnd) {
2953 // Offset to start of chunk for reallocation. This won't
2954 // wrap under because of check that pMem >= pPool. Cast
2955 // is safe because the pool is always less than UINT32_MAX
2956 // because of check in QCBORDecode_SetMemPool().
2957 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2958
2959 // Check to see if the allocation will fit. uPoolSize -
2960 // uMemOffset will not wrap under because of check that
2961 // pMem is in the range of the uPoolSize by check above.
2962 if(uNewSize <= uPoolSize - uMemOffset) {
2963 ReturnValue.ptr = pMem;
2964 ReturnValue.len = uNewSize;
2965
2966 // Addition won't wrap around over because uNewSize was
2967 // checked to be sure it is less than the pool size.
2968 uFreeOffset = uMemOffset + uNewSize32;
2969 }
2970 }
2971 } else {
2972 // ALLOCATION MODE
2973 // uPoolSize - uFreeOffset will not underflow because this
2974 // pool implementation makes sure uFreeOffset is always
2975 // smaller than uPoolSize through this check here and
2976 // reallocation case.
2977 if(uNewSize <= uPoolSize - uFreeOffset) {
2978 ReturnValue.len = uNewSize;
2979 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002980 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002981 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002982 }
2983 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002984 if(pMem) {
2985 // FREE MODE
2986 // Cast is safe because of limit on pool size in
2987 // QCBORDecode_SetMemPool()
2988 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2989 } else {
2990 // DESTRUCT MODE
2991 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002992 }
2993 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002994
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002995 UsefulBuf Pool = {pPool, uPoolSize};
2996 MemPool_Pack(Pool, uFreeOffset);
2997
2998Done:
2999 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003000}
3001
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003002
Laurence Lundbladef6531662018-12-04 10:42:22 +09003003/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003004 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09003005 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003006QCBORError
3007QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
3008 UsefulBuf Pool,
3009 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003010{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003011 // The pool size and free mem offset are packed into the beginning
Dave Thaler93c01182022-08-06 15:08:35 -04003012 // of the pool memory. This compile time check makes sure the
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003013 // constant in the header is correct. This check should optimize
3014 // down to nothing.
Dave Thaler93c01182022-08-06 15:08:35 -04003015#ifdef _MSC_VER
3016#pragma warning(push)
3017#pragma warning(disable:4127) // conditional expression is constant
3018#endif
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003019 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003020 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003021 }
Dave Thaler93c01182022-08-06 15:08:35 -04003022#ifdef _MSC_VER
3023#pragma warning(pop)
3024#endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003025
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003026 // The pool size and free offset packed in to the beginning of pool
3027 // memory are only 32-bits. This check will optimize out on 32-bit
3028 // machines.
3029 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003030 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003031 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003032
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003033 // This checks that the pool buffer given is big enough.
3034 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003035 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003036 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003037
Laurence Lundblade3427dee2021-06-20 11:11:24 -07003038 QCBORDecode_SetUpAllocator(pMe, MemPool_Function, Pool.ptr, bAllStrings);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003039
Laurence Lundblade30816f22018-11-10 13:40:22 +07003040 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003041}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08003042#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003043
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003044
3045
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003046static void
3047QCBORDecode_Private_CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07003048{
Laurence Lundblade37286c02022-09-03 10:05:02 -07003049#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade9b334962020-08-27 10:55:53 -07003050 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
Laurence Lundblade37286c02022-09-03 10:05:02 -07003051#else
3052 (void)pMe;
3053 (void)pItem;
3054#endif
Laurence Lundblade9b334962020-08-27 10:55:53 -07003055}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003056
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003057
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003058/**
3059 * @brief Consume an entire map or array including its contents.
3060 *
3061 * @param[in] pMe The decoder context.
3062 * @param[in] pItemToConsume The array/map whose contents are to be
3063 * consumed.
3064 * @param[out] puNextNestLevel The next nesting level after the item was
3065 * fully consumed.
3066 *
3067 * This may be called when @c pItemToConsume is not an array or
3068 * map. In that case, this is just a pass through for @c puNextNestLevel
3069 * since there is nothing to do.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003070 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003071static QCBORError
3072QCBORDecode_Private_ConsumeItem(QCBORDecodeContext *pMe,
3073 const QCBORItem *pItemToConsume,
3074 uint8_t *puNextNestLevel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003075{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003076 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003077 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003078
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003079 /* If it is a map or array, this will tell if it is empty. */
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003080 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
3081
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003082 if(QCBORItem_IsMapOrArray(*pItemToConsume) && !bIsEmpty) {
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003083 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003084
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003085 /* This works for definite- and indefinite-length maps and
3086 * arrays by using the nesting level
Laurence Lundblade1341c592020-04-11 14:19:05 -07003087 */
3088 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003089 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003090 if(QCBORDecode_IsUnrecoverableError(uReturn) ||
3091 uReturn == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003092 goto Done;
3093 }
3094 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003095
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003096 *puNextNestLevel = Item.uNextNestLevel;
3097
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003098 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003099
Laurence Lundblade1341c592020-04-11 14:19:05 -07003100 } else {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003101 /* pItemToConsume is not a map or array. Just pass the nesting
3102 * level through. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003103 *puNextNestLevel = pItemToConsume->uNextNestLevel;
3104
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003105 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003106 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003107
3108Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003109 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003110}
3111
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003112
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003113/*
3114 * Public function, see header qcbor/qcbor_decode.h file
3115 */
3116void
3117QCBORDecode_VGetNextConsume(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003118{
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003119 QCBORDecode_VGetNext(pMe, pDecodedItem);
3120
3121 if(pMe->uLastError == QCBOR_SUCCESS) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003122 pMe->uLastError = (uint8_t)QCBORDecode_Private_ConsumeItem(pMe, pDecodedItem,
Máté Tóth-Pálc6d59682021-05-26 18:55:30 +02003123 &pDecodedItem->uNextNestLevel);
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003124 }
3125}
3126
3127
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003128/**
3129 * @brief Rewind cursor to start as if map or array were just entered.
3130 *
3131 * @param[in] pMe The decoding context
3132 *
3133 * This affects the nesting tracking and the UsefulInputBuf.
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003134 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003135static void
3136QCBORDecode_Private_RewindMapOrArray(QCBORDecodeContext *pMe)
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003137{
3138 /* Reset nesting tracking to the deepest bounded level */
3139 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
3140
3141 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3142
3143 /* Reposition traversal cursor to the start of the map/array */
3144 UsefulInputBuf_Seek(&(pMe->InBuf),
3145 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
3146}
3147
3148
3149/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003150 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003151 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003152void
3153QCBORDecode_Rewind(QCBORDecodeContext *pMe)
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003154{
3155 if(pMe->nesting.pCurrentBounded != NULL) {
3156 /* In a bounded map, array or bstr-wrapped CBOR */
3157
3158 if(DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
3159 /* In bstr-wrapped CBOR. */
3160
3161 /* Reposition traversal cursor to start of wrapping byte string */
3162 UsefulInputBuf_Seek(&(pMe->InBuf),
3163 pMe->nesting.pCurrentBounded->u.bs.uBstrStartOffset);
3164 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
3165
3166 } else {
3167 /* In a map or array */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003168 QCBORDecode_Private_RewindMapOrArray(pMe);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003169 }
3170
3171 } else {
3172 /* Not in anything bounded */
3173
3174 /* Reposition traversal cursor to the start of input CBOR */
3175 UsefulInputBuf_Seek(&(pMe->InBuf), 0ULL);
3176
3177 /* Reset nesting tracking to beginning of input. */
3178 DecodeNesting_Init(&(pMe->nesting));
3179 }
3180
3181 pMe->uLastError = QCBOR_SUCCESS;
3182}
3183
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003184
Laurence Lundblade9b334962020-08-27 10:55:53 -07003185
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003186
3187
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003188/**
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003189 * @brief Search a map for a set of items.
3190 *
3191 * @param[in] pMe The decode context to search.
3192 * @param[in,out] pItemArray The items to search for and the items found.
3193 * @param[out] puOffset Byte offset of last item matched.
3194 * @param[in] pCBContext Context for the not-found item call back.
3195 * @param[in] pfCallback Function to call on items not matched in pItemArray.
3196 *
3197 * @retval QCBOR_ERR_NOT_ENTERED Trying to search without entering a map.
3198 *
3199 * @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
3200 * were found for one of the labels being
3201 * search for. This duplicate detection is
3202 * only performed for items in pItemArray,
3203 * not every item in the map.
3204 *
3205 * @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
3206 * wrong for the matchd label.
3207 *
3208 * @retval Also errors returned by QCBORDecode_GetNext().
3209 *
3210 * On input, \c pItemArray contains a list of labels and data types of
3211 * items to be found.
3212 *
3213 * On output, the fully retrieved items are filled in with values and
3214 * such. The label was matched, so it never changes.
3215 *
3216 * If an item was not found, its data type is set to @ref QCBOR_TYPE_NONE.
3217 *
3218 * This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003219 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003220static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003221QCBORDecode_Private_MapSearch(QCBORDecodeContext *pMe,
3222 QCBORItem *pItemArray,
3223 size_t *puOffset,
3224 void *pCBContext,
3225 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003226{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003227 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003228 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07003229
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003230 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003231 uReturn = pMe->uLastError;
3232 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003233 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003234
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003235 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003236 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
3237 /* QCBOR_TYPE_NONE as first item indicates just looking
3238 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003239 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
3240 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003241 }
3242
Laurence Lundblade085d7952020-07-24 10:26:30 -07003243 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
3244 // It is an empty bounded array or map
3245 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
3246 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003247 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07003248 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003249 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003250 // Nothing is ever found in an empty array or map. All items
3251 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07003252 uReturn = QCBOR_SUCCESS;
3253 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003254 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003255 }
3256
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003257 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003258 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
3259
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003260 /* Reposition to search from the start of the map / array */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003261 QCBORDecode_Private_RewindMapOrArray(pMe);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003262
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003263 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003264 Loop over all the items in the map or array. Each item
3265 could be a map or array, but label matching is only at
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003266 the main level. This handles definite- and indefinite-
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003267 length maps and arrays. The only reason this is ever
3268 called on arrays is to find their end position.
3269
3270 This will always run over all items in order to do
3271 duplicate detection.
3272
3273 This will exit with failure if it encounters an
3274 unrecoverable error, but continue on for recoverable
3275 errors.
3276
3277 If a recoverable error occurs on a matched item, then
3278 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003279 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07003280 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Máté Tóth-Pál2f2aa5f2021-05-17 21:35:09 +02003281 uint8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003282 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003283 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07003284 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003285
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003286 /* Get the item */
3287 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003288 QCBORError uResult = QCBORDecode_Private_GetNextTagContent(pMe, &Item);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003289 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003290 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003291 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003292 goto Done;
3293 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003294 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003295 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003296 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003297 goto Done;
3298 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003299
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003300 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003301 bool bMatched = false;
3302 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003303 if(QCBORItem_MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003304 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003305 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
3306 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003307 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003308 }
Laurence Lundblade63926052021-03-29 16:05:51 -07003309 if(uResult != QCBOR_SUCCESS) {
3310 /* The label matches, but the data item is in error */
3311 uReturn = uResult;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003312 goto Done;
3313 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003314 if(!QCBORItem_MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade63926052021-03-29 16:05:51 -07003315 /* The data item is not of the type(s) requested */
3316 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003317 goto Done;
3318 }
3319
Laurence Lundblade1341c592020-04-11 14:19:05 -07003320 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003321 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003322 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003323 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003324 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003325 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003326 bMatched = true;
3327 }
3328 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003329
3330
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003331 if(!bMatched && pfCallback != NULL) {
3332 /*
3333 Call the callback on unmatched labels.
3334 (It is tempting to do duplicate detection here, but that would
3335 require dynamic memory allocation because the number of labels
3336 that might be encountered is unbounded.)
3337 */
3338 uReturn = (*pfCallback)(pCBContext, &Item);
3339 if(uReturn != QCBOR_SUCCESS) {
3340 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003341 }
3342 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003343
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003344 /*
3345 Consume the item whether matched or not. This
3346 does the work of traversing maps and array and
3347 everything in them. In this loop only the
3348 items at the current nesting level are examined
3349 to match the labels.
3350 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003351 uReturn = QCBORDecode_Private_ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003352 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003353 goto Done;
3354 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003355 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003356
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003357 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003358
3359 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003360
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003361 // Check here makes sure that this won't accidentally be
3362 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003363 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003364 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
3365 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003366 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
3367 goto Done;
3368 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003369 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
3370 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003371
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003372 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003373 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
3374
3375 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003376 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07003377 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003378 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003379 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
3380 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003381 }
3382 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003383
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003384 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003385}
3386
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003387
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003388/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003389 * Public function, see header qcbor/qcbor_decode.h file
3390 */
3391void
3392QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
3393 int64_t nLabel,
3394 uint8_t uQcborType,
3395 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003396{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003397 if(pMe->uLastError != QCBOR_SUCCESS) {
3398 return;
3399 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003400
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003401 QCBORItem OneItemSeach[2];
3402 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3403 OneItemSeach[0].label.int64 = nLabel;
3404 OneItemSeach[0].uDataType = uQcborType;
3405 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003406
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003407 QCBORError uReturn = QCBORDecode_Private_MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003408
3409 *pItem = OneItemSeach[0];
3410
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003411 if(uReturn != QCBOR_SUCCESS) {
3412 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003413 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003414 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003415 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003416 }
3417
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003418 Done:
3419 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003420}
3421
3422
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003423/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003424 * Public function, see header qcbor/qcbor_decode.h file
3425 */
3426void
3427QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
3428 const char *szLabel,
3429 uint8_t uQcborType,
3430 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003431{
Laurence Lundbladeda095972020-06-06 18:35:33 -07003432 if(pMe->uLastError != QCBOR_SUCCESS) {
3433 return;
3434 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003435
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003436 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003437 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3438 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3439 OneItemSeach[0].uDataType = uQcborType;
3440 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003441
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003442 QCBORError uReturn = QCBORDecode_Private_MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003443 if(uReturn != QCBOR_SUCCESS) {
3444 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003445 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003446 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003447 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003448 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003449 }
3450
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003451 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003452
3453Done:
3454 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003455}
3456
3457
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003458/**
3459 * @brief Is a QCBOR_TYPE in the type list?
3460 *
3461 * @param[in] uDataType Type to check for.
3462 * @param[in] puTypeList List to check.
3463 *
3464 * @retval QCBOR_SUCCESS If in the list.
3465 * @retval QCBOR_ERR_UNEXPECTED_TYPE Not in the list.
3466 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07003467static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003468QCBOR_Private_CheckTypeList(const int uDataType,
3469 const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003470{
3471 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08003472 if(uDataType == puTypeList[i]) { /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003473 return QCBOR_SUCCESS;
3474 }
3475 }
3476 return QCBOR_ERR_UNEXPECTED_TYPE;
3477}
3478
Laurence Lundblade67257dc2020-07-27 03:33:37 -07003479
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003480/**
Laurence Lundblade37286c02022-09-03 10:05:02 -07003481 * Match a tag/type specification against the type of the item.
3482 *
3483 * @param[in] TagSpec Specification for matching tags.
3484 * @param[in] pItem The item to check.
3485 *
3486 * @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
3487 * @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
3488 *
3489 * This checks the item data type of untagged items as well as of
3490 * tagged items against a specification to see if decoding should
3491 * proceed.
3492 *
3493 * This relies on the automatic tag decoding done by QCBOR that turns
3494 * tag numbers into particular QCBOR_TYPEs so there is no actual
3495 * comparsion of tag numbers, just of QCBOR_TYPEs.
3496 *
3497 * This checks the data item type as possibly representing the tag
3498 * number or as the tag content type.
3499 *
3500 * If QCBOR_DISABLE_TAGS is #defined, this primarily checks the item
3501 * data type against the allowed tag content types. It will also error out
3502 * if the caller tries to require a tag because there is no way that can
3503 * ever be fulfilled.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003504 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07003505static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003506QCBOR_Private_CheckTagRequirement(const QCBOR_Private_TagSpec TagSpec,
3507 const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07003508{
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08003509 const int nItemType = pItem->uDataType; /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade37286c02022-09-03 10:05:02 -07003510 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
3511
3512#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08003513 /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003514 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
3515 pItem->uTags[0] != CBOR_TAG_INVALID16) {
3516 /* There are tags that QCBOR couldn't process on this item and
Laurence Lundblade37286c02022-09-03 10:05:02 -07003517 * the caller has told us there should not be.
3518 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003519 return QCBOR_ERR_UNEXPECTED_TYPE;
3520 }
3521
Laurence Lundblade9b334962020-08-27 10:55:53 -07003522 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
Laurence Lundblade37286c02022-09-03 10:05:02 -07003523 /* Must match the tag number and only the tag */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003524 return QCBOR_Private_CheckTypeList(nItemType, TagSpec.uTaggedTypes);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003525 }
3526
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003527 QCBORError uReturn = QCBOR_Private_CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003528 if(uReturn == QCBOR_SUCCESS) {
3529 return QCBOR_SUCCESS;
3530 }
3531
3532 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
3533 /* Must match the content type and only the content type.
Laurence Lundblade37286c02022-09-03 10:05:02 -07003534 * There was no match just above so it is a fail. */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003535 return QCBOR_ERR_UNEXPECTED_TYPE;
3536 }
3537
Laurence Lundblade37286c02022-09-03 10:05:02 -07003538 /* QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG: If here it can match either the tag or the content
3539 * and it hasn't matched the content, so the end
3540 * result is whether it matches the tag. This is
3541 * the tag optional case that the CBOR standard discourages.
3542 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003543
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003544 return QCBOR_Private_CheckTypeList(nItemType, TagSpec.uTaggedTypes);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003545
Laurence Lundblade37286c02022-09-03 10:05:02 -07003546#else /* QCBOR_DISABLE_TAGS */
3547 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
3548 return QCBOR_ERR_UNEXPECTED_TYPE;
3549 }
3550
3551 return CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
3552
3553#endif /* QCBOR_DISABLE_TAGS */
3554}
Laurence Lundblade9b334962020-08-27 10:55:53 -07003555
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003556
3557/**
3558 * @brief Get an item by label to match a tag specification.
3559 *
3560 * @param[in] pMe The decode context.
3561 * @param[in] nLabel The label to search map for.
3562 * @param[in] TagSpec The tag number specification to match.
3563 * @param[out] pItem The item found.
3564 *
3565 * This finds the item with the given label in currently open
3566 * map. Then checks that its tag number and types matches the tag
3567 * specification. If not, an error is set in the decode context.
3568 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003569static void
3570QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
3571 const int64_t nLabel,
3572 const QCBOR_Private_TagSpec TagSpec,
3573 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003574{
3575 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
3576 if(pMe->uLastError != QCBOR_SUCCESS) {
3577 return;
3578 }
3579
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003580 pMe->uLastError = (uint8_t)QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003581}
3582
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003583
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003584/**
3585 * @brief Get an item by label to match a tag specification.
3586 *
3587 * @param[in] pMe The decode context.
3588 * @param[in] szLabel The label to search map for.
3589 * @param[in] TagSpec The tag number specification to match.
3590 * @param[out] pItem The item found.
3591 *
3592 * This finds the item with the given label in currently open
3593 * map. Then checks that its tag number and types matches the tag
3594 * specification. If not, an error is set in the decode context.
3595 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003596static void
3597QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
3598 const char *szLabel,
3599 const QCBOR_Private_TagSpec TagSpec,
3600 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003601{
3602 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
3603 if(pMe->uLastError != QCBOR_SUCCESS) {
3604 return;
3605 }
3606
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003607 pMe->uLastError = (uint8_t)QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003608}
3609
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003610
3611/**
3612 * @brief Semi-private to get an string by label to match a tag specification.
3613 *
3614 * @param[in] pMe The decode context.
3615 * @param[in] nLabel The label to search map for.
3616 * @param[in] TagSpec The tag number specification to match.
3617 * @param[out] pString The string found.
3618 *
3619 * This finds the string with the given label in currently open
3620 * map. Then checks that its tag number and types matches the tag
3621 * specification. If not, an error is set in the decode context.
3622 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003623void
3624QCBORDecode_Private_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
3625 const int64_t nLabel,
3626 const QCBOR_Private_TagSpec TagSpec,
3627 UsefulBufC *pString)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003628{
3629 QCBORItem Item;
3630 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
3631 if(pMe->uLastError == QCBOR_SUCCESS) {
3632 *pString = Item.val.string;
3633 }
3634}
3635
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003636
3637/**
3638 * @brief Semi-private to get an string by label to match a tag specification.
3639 *
3640 * @param[in] pMe The decode context.
3641 * @param[in] szLabel The label to search map for.
3642 * @param[in] TagSpec The tag number specification to match.
3643 * @param[out] pString The string found.
3644 *
3645 * This finds the string with the given label in currently open
3646 * map. Then checks that its tag number and types matches the tag
3647 * specification. If not, an error is set in the decode context.
3648 */void
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003649QCBORDecode_Private_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
3650 const char * szLabel,
3651 const QCBOR_Private_TagSpec TagSpec,
3652 UsefulBufC *pString)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003653{
3654 QCBORItem Item;
3655 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
3656 if(pMe->uLastError == QCBOR_SUCCESS) {
3657 *pString = Item.val.string;
3658 }
3659}
Laurence Lundblade1341c592020-04-11 14:19:05 -07003660
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003661
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003662/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003663 * Public function, see header qcbor/qcbor_decode.h file
3664 */
3665void
3666QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003667{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003668 QCBORError uErr = QCBORDecode_Private_MapSearch(pMe, pItemList, NULL, NULL, NULL);
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003669 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003670}
3671
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003672/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003673 * Public function, see header qcbor/qcbor_decode.h file
3674 */
3675void
3676QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3677 QCBORItem *pItemList,
3678 void *pCallbackCtx,
3679 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003680{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003681 QCBORError uErr = QCBORDecode_Private_MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003682 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003683}
3684
3685
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003686/**
3687 * @brief Search for a map/array by label and enter it
3688 *
3689 * @param[in] pMe The decode context.
3690 * @param[in] pSearch The map/array to search for.
3691 *
3692 * @c pSearch is expected to contain one item of type map or array
3693 * with the label specified. The current bounded map will be searched for
3694 * this and if found will be entered.
3695 *
3696 * If the label is not found, or the item found is not a map or array,
3697 * the error state is set.
3698 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003699static void
3700QCBORDecode_Private_SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003701{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003702 // The first item in pSearch is the one that is to be
3703 // entered. It should be the only one filled in. Any other
3704 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003705 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003706 return;
3707 }
3708
3709 size_t uOffset;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003710 pMe->uLastError = (uint8_t)QCBORDecode_Private_MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003711 if(pMe->uLastError != QCBOR_SUCCESS) {
3712 return;
3713 }
3714
Laurence Lundblade9b334962020-08-27 10:55:53 -07003715 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003716 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003717 return;
3718 }
3719
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003720
3721 /* The map or array was found. Now enter it.
3722 *
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003723 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3724 * next item for the pre-order traversal cursor to be the map/array
3725 * found by MapSearch(). The next few lines of code force the
3726 * cursor to that.
3727 *
3728 * There is no need to retain the old cursor because
3729 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3730 * beginning of the map/array being entered.
3731 *
3732 * The cursor is forced by: 1) setting the input buffer position to
3733 * the item offset found by MapSearch(), 2) setting the map/array
3734 * counter to the total in the map/array, 3) setting the nesting
3735 * level. Setting the map/array counter to the total is not
3736 * strictly correct, but this is OK because this cursor only needs
3737 * to be used to get one item and MapSearch() has already found it
3738 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003739 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003740 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003741
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003742 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3743
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003744 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003745
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003746 QCBORDecode_Private_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003747}
3748
3749
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003750/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003751 * Public function, see header qcbor/qcbor_decode.h file
3752 */
3753void
3754QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003755{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003756 QCBORItem OneItemSeach[2];
3757 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3758 OneItemSeach[0].label.int64 = nLabel;
3759 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3760 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003761
Laurence Lundblade9b334962020-08-27 10:55:53 -07003762 /* The map to enter was found, now finish off entering it. */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003763 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003764}
3765
3766
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003767/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003768 * Public function, see header qcbor/qcbor_decode.h file
3769 */
3770void
3771QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003772{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003773 QCBORItem OneItemSeach[2];
3774 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3775 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3776 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3777 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003778
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003779 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003780}
3781
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003782/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003783 * Public function, see header qcbor/qcbor_decode.h file
3784 */
3785void
3786QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003787{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003788 QCBORItem OneItemSeach[2];
3789 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3790 OneItemSeach[0].label.int64 = nLabel;
3791 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3792 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003793
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003794 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003795}
3796
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003797/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003798 * Public function, see header qcbor/qcbor_decode.h file
3799 */
3800void
3801QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundblade34691b92020-05-18 22:25:25 -07003802{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003803 QCBORItem OneItemSeach[2];
3804 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3805 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3806 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3807 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003808
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003809 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003810}
3811
3812
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003813/**
3814 * @brief Semi-private to do the the work for EnterMap() and EnterArray().
3815 *
3816 * @param[in] pMe The decode context
3817 * @param[in] uType QCBOR_TYPE_MAP or QCBOR_TYPE_ARRAY.
3818 * @param[out] pItem The data item for the map or array entered.
3819 *
3820 * The next item in the traversal must be a map or array. This
3821 * consumes that item and does the book keeping to enter the map or
3822 * array.
3823 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003824void
3825QCBORDecode_Private_EnterBoundedMapOrArray(QCBORDecodeContext *pMe,
3826 const uint8_t uType,
3827 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003828{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003829 QCBORError uErr;
3830
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003831 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003832 if(pMe->uLastError != QCBOR_SUCCESS) {
3833 // Already in error state; do nothing.
3834 return;
3835 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003836
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003837 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003838 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003839 uErr = QCBORDecode_GetNext(pMe, &Item);
3840 if(uErr != QCBOR_SUCCESS) {
3841 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003842 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003843 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003844 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3845 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003846 }
3847
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003848 QCBORDecode_Private_CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003849
3850
Laurence Lundbladef0499502020-08-01 11:55:57 -07003851 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003852 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003853 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3854 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003855 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003856 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3857 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003858 // Special case to increment nesting level for zero-length maps
3859 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003860 DecodeNesting_Descend(&(pMe->nesting), uType);
3861 }
3862
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003863 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003864
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003865 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3866 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003867
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003868 if(pItem != NULL) {
3869 *pItem = Item;
3870 }
3871
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003872Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003873 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003874}
3875
Laurence Lundblade02625d42020-06-25 14:41:41 -07003876
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003877/**
3878 * @brief Exit a bounded map, array or bstr (semi-private).
3879 *
3880 * @param[in] pMe Decode context.
3881 * @param[in] uEndOffset The input buffer offset of the end of item exited.
3882 *
3883 * @returns QCBOR_SUCCESS or an error code.
3884 *
3885 * This is the common work for exiting a level that is a bounded map,
3886 * array or bstr wrapped CBOR.
3887 *
3888 * One chunk of work is to set up the pre-order traversal so it is at
3889 * the item just after the bounded map, array or bstr that is being
3890 * exited. This is somewhat complex.
3891 *
3892 * The other work is to level-up the bounded mode to next higest
3893 * bounded mode or the top level if there isn't one.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003894 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003895static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003896QCBORDecode_Private_ExitBoundedLevel(QCBORDecodeContext *pMe,
3897 const uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003898{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003899 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003900
Laurence Lundblade02625d42020-06-25 14:41:41 -07003901 /*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003902 * First the pre-order-traversal byte offset is positioned to the
3903 * item just after the bounded mode item that was just consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003904 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003905 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3906
Laurence Lundblade02625d42020-06-25 14:41:41 -07003907 /*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003908 * Next, set the current nesting level to one above the bounded
3909 * level that was just exited.
3910 *
3911 * DecodeNesting_CheckBoundedType() is always called before this
3912 * and makes sure pCurrentBounded is valid.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003913 */
3914 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3915
3916 /*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003917 * This does the complex work of leveling up the pre-order
3918 * traversal when the end of a map or array or another bounded
3919 * level is reached. It may do nothing, or ascend all the way to
3920 * the top level.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003921 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003922 uErr = QCBORDecode_Private_NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003923 if(uErr != QCBOR_SUCCESS) {
3924 goto Done;
3925 }
3926
Laurence Lundblade02625d42020-06-25 14:41:41 -07003927 /*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003928 * This makes the next highest bounded level the current bounded
3929 * level. If there is no next highest level, then no bounded mode
3930 * is in effect.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003931 */
3932 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003933
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003934 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003935
3936Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003937 return uErr;
3938}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003939
Laurence Lundblade02625d42020-06-25 14:41:41 -07003940
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003941/**
3942 * @brief Get started exiting a map or array (semi-private)
3943 *
3944 * @param[in] pMe The decode context
3945 * @param[in] uType QCBOR_TYPE_ARRAY or QCBOR_TYPE_MAP
3946 *
3947 * This does some work for map and array exiting (but not
3948 * bstr exiting). Then QCBORDecode_Private_ExitBoundedLevel()
3949 * is called to do the rest.
3950 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003951void
3952QCBORDecode_Private_ExitBoundedMapOrArray(QCBORDecodeContext *pMe,
3953 const uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003954{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003955 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003956 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003957 return;
3958 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003959
Laurence Lundblade02625d42020-06-25 14:41:41 -07003960 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003961
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003962 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003963 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003964 goto Done;
3965 }
3966
Laurence Lundblade02625d42020-06-25 14:41:41 -07003967 /*
3968 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003969 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003970 from previous map search, then do a dummy search.
3971 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003972 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003973 QCBORItem Dummy;
3974 Dummy.uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003975 uErr = QCBORDecode_Private_MapSearch(pMe, &Dummy, NULL, NULL, NULL);
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003976 if(uErr != QCBOR_SUCCESS) {
3977 goto Done;
3978 }
3979 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003980
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003981 uErr = QCBORDecode_Private_ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003982
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003983Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003984 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003985}
3986
3987
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003988/**
3989 * @brief The main work of entering some byte-string wrapped CBOR.
3990 *
3991 * @param[in] pMe The decode context.
3992 * @param[in] pItem The byte string item.
3993 * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX
3994 * @param[out] pBstr Pointer and length of byte string entered.
3995 *
3996 * This is called once the byte string item has been decoded to do all
3997 * the book keeping work for descending a nesting level into the
3998 * nested CBOR.
3999 *
4000 * See QCBORDecode_EnterBstrWrapped() for details on uTagRequirement.
4001 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07004002static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004003QCBORDecode_Private_EnterBstrWrapped(QCBORDecodeContext *pMe,
4004 const QCBORItem *pItem,
4005 const uint8_t uTagRequirement,
4006 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004007{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07004008 if(pBstr) {
4009 *pBstr = NULLUsefulBufC;
4010 }
4011
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004012 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004013 /* Already in error state; do nothing. */
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004014 return pMe->uLastError;
4015 }
4016
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004017 QCBORError uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004018
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004019 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004020 {
4021 uTagRequirement,
4022 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
4023 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4024 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004025
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004026 uError = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004027 if(uError != QCBOR_SUCCESS) {
4028 goto Done;
4029 }
4030
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004031 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004032 /* Reverse the decrement done by GetNext() for the bstr so the
4033 * increment in QCBORDecode_NestLevelAscender() called by
4034 * ExitBoundedLevel() will work right.
4035 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004036 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07004037 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004038
4039 if(pBstr) {
4040 *pBstr = pItem->val.string;
4041 }
4042
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004043 /* This saves the current length of the UsefulInputBuf and then
4044 * narrows the UsefulInputBuf to start and length of the wrapped
4045 * CBOR that is being entered.
4046 *
4047 * Most of these calls are simple inline accessors so this doesn't
4048 * amount to much code.
4049 */
4050
Laurence Lundbladea4308a82020-10-03 18:08:57 -07004051 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004052 /* This check makes the cast of uPreviousLength to uint32_t below safe. */
4053 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07004054 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07004055 goto Done;
4056 }
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004057
4058 const size_t uStartOfBstr = UsefulInputBuf_PointerToOffset(&(pMe->InBuf),
4059 pItem->val.string.ptr);
4060 /* This check makes the cast of uStartOfBstr to uint32_t below safe. */
4061 if(uStartOfBstr == SIZE_MAX || uStartOfBstr > QCBOR_MAX_DECODE_INPUT_SIZE) {
4062 /* This should never happen because pItem->val.string.ptr should
4063 * always be valid since it was just returned.
4064 */
4065 uError = QCBOR_ERR_INPUT_TOO_LARGE;
4066 goto Done;
4067 }
4068
4069 const size_t uEndOfBstr = uStartOfBstr + pItem->val.string.len;
4070
4071 UsefulInputBuf_Seek(&(pMe->InBuf), uStartOfBstr);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07004072 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004073
Laurence Lundblade02625d42020-06-25 14:41:41 -07004074 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07004075 (uint32_t)uPreviousLength,
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004076 (uint32_t)uStartOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004077Done:
4078 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004079}
4080
4081
Laurence Lundblade02625d42020-06-25 14:41:41 -07004082/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004083 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07004084 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004085void
4086QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
4087 const uint8_t uTagRequirement,
4088 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07004089{
4090 if(pMe->uLastError != QCBOR_SUCCESS) {
4091 // Already in error state; do nothing.
4092 return;
4093 }
4094
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004095 /* Get the data item that is the byte string being entered */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004096 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07004097 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4098 if(pMe->uLastError != QCBOR_SUCCESS) {
4099 return;
4100 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07004101
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004102 pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
4103 &Item,
4104 uTagRequirement,
4105 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07004106}
4107
4108
Laurence Lundblade02625d42020-06-25 14:41:41 -07004109/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004110 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07004111 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004112void
4113QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
4114 const int64_t nLabel,
4115 const uint8_t uTagRequirement,
4116 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004117{
4118 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004119 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004120
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004121 pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
4122 &Item,
4123 uTagRequirement,
4124 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004125}
4126
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004127
Laurence Lundblade02625d42020-06-25 14:41:41 -07004128/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004129 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07004130 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004131void
4132QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
4133 const char *szLabel,
4134 const uint8_t uTagRequirement,
4135 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004136{
4137 QCBORItem Item;
4138 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4139
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004140 pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
4141 &Item,
4142 uTagRequirement,
4143 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004144}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004145
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004146
Laurence Lundblade02625d42020-06-25 14:41:41 -07004147/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004148 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07004149 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004150void
4151QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004152{
Laurence Lundblade02625d42020-06-25 14:41:41 -07004153 if(pMe->uLastError != QCBOR_SUCCESS) {
4154 // Already in error state; do nothing.
4155 return;
4156 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004157
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07004158 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07004159 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07004160 return;
4161 }
4162
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004163 const uint32_t uEndOfBstr = (uint32_t)UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
4164
Laurence Lundblade02625d42020-06-25 14:41:41 -07004165 /*
4166 Reset the length of the UsefulInputBuf to what it was before
4167 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004168 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07004169 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004170 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004171
4172
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004173 QCBORError uErr = QCBORDecode_Private_ExitBoundedLevel(pMe, uEndOfBstr);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004174 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004175}
4176
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004177
Laurence Lundbladee6430642020-03-14 21:15:44 -07004178
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004179/**
4180 * @brief Process simple type true and false, a boolean
4181 *
4182 * @param[in] pMe The decode context.
4183 * @param[in] pItem The item with either true or false.
4184 * @param[out] pBool The boolean value output.
4185 *
4186 * Sets the internal error if the item isn't a true or a false. Also
4187 * records any tag numbers as the tag numbers of the last item.
4188 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004189static void
4190QCBORDecode_Private_ProcessBool(QCBORDecodeContext *pMe,
4191 const QCBORItem *pItem,
4192 bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004193{
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004194 if(pMe->uLastError != QCBOR_SUCCESS) {
4195 /* Already in error state, do nothing */
4196 return;
4197 }
4198
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004199 switch(pItem->uDataType) {
4200 case QCBOR_TYPE_TRUE:
4201 *pBool = true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004202 break;
4203
4204 case QCBOR_TYPE_FALSE:
4205 *pBool = false;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004206 break;
4207
4208 default:
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004209 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004210 break;
4211 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004212 QCBORDecode_Private_CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004213}
Laurence Lundbladee6430642020-03-14 21:15:44 -07004214
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004215
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004216/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004217 * Public function, see header qcbor/qcbor_decode.h file
4218 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004219void
4220QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004221{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004222 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004223 /* Already in error state, do nothing */
Laurence Lundbladee6430642020-03-14 21:15:44 -07004224 return;
4225 }
4226
Laurence Lundbladec4537442020-04-14 18:53:22 -07004227 QCBORItem Item;
4228
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004229 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4230
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004231 QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004232}
4233
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004234
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004235/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004236 * Public function, see header qcbor/qcbor_decode.h file
4237 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004238void
4239QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe,
4240 const int64_t nLabel,
4241 bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004242{
4243 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004244 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004245
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004246 QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004247}
4248
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004249
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004250/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004251 * Public function, see header qcbor/qcbor_decode.h file
4252 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004253void
4254QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe,
4255 const char *szLabel,
4256 bool *pValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004257{
4258 QCBORItem Item;
4259 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4260
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004261 QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004262}
4263
4264
4265
Laurence Lundbladec7114722020-08-13 05:11:40 -07004266
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004267/**
4268 * @brief Common processing for an epoch date.
4269 *
4270 * @param[in] pMe The decode context.
4271 * @param[in] pItem The item with the date.
4272 * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX.
4273 * @param[out] pnTime The returned date.
4274 *
4275 * Common processing for the date tag. Mostly make sure the tag
4276 * content is correct and copy forward any further other tag numbers.
4277 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004278static void
4279QCBORDecode_Private_ProcessEpochDate(QCBORDecodeContext *pMe,
4280 QCBORItem *pItem,
4281 const uint8_t uTagRequirement,
4282 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07004283{
4284 if(pMe->uLastError != QCBOR_SUCCESS) {
4285 // Already in error state, do nothing
4286 return;
4287 }
4288
4289 QCBORError uErr;
4290
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004291 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladec7114722020-08-13 05:11:40 -07004292 {
4293 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004294 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4295 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07004296 };
4297
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004298 uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004299 if(uErr != QCBOR_SUCCESS) {
4300 goto Done;
4301 }
4302
4303 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004304 uErr = QCBOR_Private_DecodeDateEpoch(pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004305 if(uErr != QCBOR_SUCCESS) {
4306 goto Done;
4307 }
4308 }
4309
Laurence Lundblade9b334962020-08-27 10:55:53 -07004310 // Save the tags in the last item's tags in the decode context
4311 // for QCBORDecode_GetNthTagOfLast()
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004312 QCBORDecode_Private_CopyTags(pMe, pItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07004313
Laurence Lundbladec7114722020-08-13 05:11:40 -07004314 *pnTime = pItem->val.epochDate.nSeconds;
4315
4316Done:
4317 pMe->uLastError = (uint8_t)uErr;
4318}
4319
4320
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004321
4322/*
4323 * Public function, see header qcbor/qcbor_spiffy_decode.h file
4324 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004325void
4326QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
4327 uint8_t uTagRequirement,
4328 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07004329{
4330 if(pMe->uLastError != QCBOR_SUCCESS) {
4331 // Already in error state, do nothing
4332 return;
4333 }
4334
4335 QCBORItem Item;
4336 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4337
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004338 QCBORDecode_Private_ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004339}
4340
4341
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004342/*
4343 * Public function, see header qcbor/qcbor_spiffy_decode.h file
4344 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07004345void
4346QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
4347 int64_t nLabel,
4348 uint8_t uTagRequirement,
4349 int64_t *pnTime)
4350{
4351 QCBORItem Item;
4352 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004353 QCBORDecode_Private_ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004354}
4355
4356
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004357/*
4358 * Public function, see header qcbor/qcbor_spiffy_decode.h file
4359 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07004360void
4361QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
4362 const char *szLabel,
4363 uint8_t uTagRequirement,
4364 int64_t *pnTime)
4365{
4366 QCBORItem Item;
4367 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004368 QCBORDecode_Private_ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004369}
4370
4371
4372
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004373/**
4374 * @brief Common processing for an epoch date.
4375 *
4376 * @param[in] pMe The decode context.
4377 * @param[in] pItem The item with the date.
4378 * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX.
4379 * @param[out] pnDays The returned day count.
4380 *
4381 * Common processing for the RFC 8943 day-count tag. Mostly make sure
4382 * the tag content is correct and copy forward any further other tag
4383 * numbers.
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004384 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004385static void
4386QCBORDecode_Private_ProcessEpochDays(QCBORDecodeContext *pMe,
4387 QCBORItem *pItem,
4388 uint8_t uTagRequirement,
4389 int64_t *pnDays)
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004390{
4391 if(pMe->uLastError != QCBOR_SUCCESS) {
4392 /* Already in error state, do nothing */
4393 return;
4394 }
4395
4396 QCBORError uErr;
4397
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004398 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004399 {
4400 uTagRequirement,
4401 {QCBOR_TYPE_DAYS_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4402 {QCBOR_TYPE_INT64, QCBOR_TYPE_UINT64, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4403 };
4404
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004405 uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004406 if(uErr != QCBOR_SUCCESS) {
4407 goto Done;
4408 }
4409
4410 if(pItem->uDataType != QCBOR_TYPE_DAYS_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004411 uErr = QCBOR_Private_DecodeDaysEpoch(pItem);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004412 if(uErr != QCBOR_SUCCESS) {
4413 goto Done;
4414 }
4415 }
4416
4417 /* Save the tags in the last item's tags in the decode context
4418 * for QCBORDecode_GetNthTagOfLast()
4419 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004420 QCBORDecode_Private_CopyTags(pMe, pItem);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004421
4422 *pnDays = pItem->val.epochDays;
4423
4424Done:
4425 pMe->uLastError = (uint8_t)uErr;
4426}
4427
4428
4429/*
4430 * Public function, see header qcbor/qcbor_decode.h
4431 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004432void
4433QCBORDecode_GetEpochDays(QCBORDecodeContext *pMe,
4434 uint8_t uTagRequirement,
4435 int64_t *pnDays)
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004436{
4437 if(pMe->uLastError != QCBOR_SUCCESS) {
4438 /* Already in error state, do nothing */
4439 return;
4440 }
4441
4442 QCBORItem Item;
4443 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4444
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004445 QCBORDecode_Private_ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004446}
4447
4448
4449/*
4450 * Public function, see header qcbor/qcbor_decode.h
4451 */
4452void
4453QCBORDecode_GetEpochDaysInMapN(QCBORDecodeContext *pMe,
4454 int64_t nLabel,
4455 uint8_t uTagRequirement,
4456 int64_t *pnDays)
4457{
4458 QCBORItem Item;
4459 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004460 QCBORDecode_Private_ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004461}
4462
4463
4464/*
4465 * Public function, see header qcbor/qcbor_decode.h
4466 */
4467void
4468QCBORDecode_GetEpochDaysInMapSZ(QCBORDecodeContext *pMe,
4469 const char *szLabel,
4470 uint8_t uTagRequirement,
4471 int64_t *pnDays)
4472{
4473 QCBORItem Item;
4474 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004475 QCBORDecode_Private_ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004476}
4477
4478
4479
Laurence Lundblade37286c02022-09-03 10:05:02 -07004480/*
4481 * @brief Get a string that matches the type/tag specification.
4482 */
4483void
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004484QCBORDecode_Private_GetTaggedString(QCBORDecodeContext *pMe,
4485 const QCBOR_Private_TagSpec TagSpec,
4486 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004487{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004488 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade37286c02022-09-03 10:05:02 -07004489 /* Already in error state, do nothing */
Laurence Lundbladec4537442020-04-14 18:53:22 -07004490 return;
4491 }
4492
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004493 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004494 QCBORItem Item;
4495
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004496 uError = QCBORDecode_GetNext(pMe, &Item);
4497 if(uError != QCBOR_SUCCESS) {
4498 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004499 return;
4500 }
4501
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004502 pMe->uLastError = (uint8_t)QCBOR_Private_CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004503
4504 if(pMe->uLastError == QCBOR_SUCCESS) {
4505 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07004506 } else {
4507 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004508 }
4509}
4510
Laurence Lundbladec4537442020-04-14 18:53:22 -07004511
4512
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004513
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004514/**
4515 * @brief Common processing for a big number tag.
4516 *
4517 * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX.
4518 * @param[in] pItem The item with the date.
4519 * @param[out] pValue The returned big number
4520 * @param[out] pbIsNegative The returned sign of the big number.
4521 *
4522 * Common processing for the big number tag. Mostly make sure
4523 * the tag content is correct and copy forward any further other tag
4524 * numbers.
4525 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07004526static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004527QCBOR_Private_ProcessBigNum(const uint8_t uTagRequirement,
4528 const QCBORItem *pItem,
4529 UsefulBufC *pValue,
4530 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004531{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004532 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004533 {
4534 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004535 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4536 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004537 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004538
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004539 QCBORError uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004540 if(uErr != QCBOR_SUCCESS) {
4541 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004542 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004543
4544 *pValue = pItem->val.string;
4545
4546 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
4547 *pbIsNegative = false;
4548 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
4549 *pbIsNegative = true;
4550 }
4551
4552 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004553}
4554
4555
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004556/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004557 * Public function, see header qcbor/qcbor_spiffy_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004558 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004559void
4560QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
4561 const uint8_t uTagRequirement,
4562 UsefulBufC *pValue,
4563 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004564{
4565 if(pMe->uLastError != QCBOR_SUCCESS) {
4566 // Already in error state, do nothing
4567 return;
4568 }
4569
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004570 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004571 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4572 if(uError != QCBOR_SUCCESS) {
4573 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004574 return;
4575 }
4576
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004577 pMe->uLastError = (uint8_t)QCBOR_Private_ProcessBigNum(uTagRequirement,
4578 &Item,
4579 pValue,
4580 pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004581}
4582
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004583
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004584/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004585 * Public function, see header qcbor/qcbor_spiffy_decode.h
4586 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004587void
4588QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
4589 const int64_t nLabel,
4590 const uint8_t uTagRequirement,
4591 UsefulBufC *pValue,
4592 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004593{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004594 QCBORItem Item;
4595 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004596 if(pMe->uLastError != QCBOR_SUCCESS) {
4597 return;
4598 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004599
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004600 pMe->uLastError = (uint8_t)QCBOR_Private_ProcessBigNum(uTagRequirement,
4601 &Item,
4602 pValue,
4603 pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004604}
4605
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004606
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004607/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004608 * Public function, see header qcbor/qcbor_spiffy_decode.h
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004609 */
4610void
4611QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
4612 const char *szLabel,
4613 const uint8_t uTagRequirement,
4614 UsefulBufC *pValue,
4615 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004616{
4617 QCBORItem Item;
4618 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004619 if(pMe->uLastError != QCBOR_SUCCESS) {
4620 return;
4621 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004622
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004623 pMe->uLastError = (uint8_t)QCBOR_Private_ProcessBigNum(uTagRequirement,
4624 &Item,
4625 pValue,
4626 pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004627}
4628
4629
4630
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004631/**
4632 * @brief Common processing for MIME tag (semi-private).
4633 *
4634 * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX.
4635 * @param[in] pItem The item with the date.
4636 * @param[out] pMessage The returned MIME message.
4637 * @param[out] pbIsTag257 If true, binary MIME, if not, text MIME.
4638 *
4639 * Common processing for the MIME tag. Mostly make sure the tag
4640 * content is correct and copy forward any further other tag
4641 * numbers. See QCBORDecode_GetMIMEMessage().
4642 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07004643QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004644QCBORDecode_Private_GetMIME(const uint8_t uTagRequirement,
Laurence Lundblade37286c02022-09-03 10:05:02 -07004645 const QCBORItem *pItem,
4646 UsefulBufC *pMessage,
4647 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004648{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004649 const QCBOR_Private_TagSpec TagSpecText =
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004650 {
4651 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004652 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4653 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004654 };
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004655 const QCBOR_Private_TagSpec TagSpecBinary =
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004656 {
4657 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004658 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4659 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004660 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004661
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004662 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07004663
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004664 if(QCBOR_Private_CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004665 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004666 if(pbIsTag257 != NULL) {
4667 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004668 }
4669 uReturn = QCBOR_SUCCESS;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004670 } else if(QCBOR_Private_CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004671 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004672 if(pbIsTag257 != NULL) {
4673 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004674 }
4675 uReturn = QCBOR_SUCCESS;
4676
4677 } else {
4678 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
4679 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07004680
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004681 return uReturn;
4682}
4683
Laurence Lundblade93d89472020-10-03 22:30:50 -07004684// Improvement: add methods for wrapped CBOR, a simple alternate
4685// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004686
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004687
4688
4689
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004690#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07004691
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004692/**
4693 * @brief Prototype for conversion of exponent and mantissa to unsigned integer.
4694 *
4695 * @param[in] uMantissa The mantissa.
4696 * @param[in] nExponent The exponent.
4697 * @param[out] puResult The resulting integer.
4698 *
4699 * Concrete implementations of this are for exponent base 10 and 2 supporting
4700 * decimal fractions and big floats.
4701 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004702typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004703
4704
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004705/**
4706 * @brief Base 10 exponentiate a mantissa and exponent into an unsigned 64-bit integer.
4707 *
4708 * @param[in] uMantissa The unsigned integer mantissa.
4709 * @param[in] nExponent The signed integer exponent.
4710 * @param[out] puResult Place to return the unsigned integer result.
4711 *
4712 * This computes: mantissa * 10 ^^ exponent as for a decimal fraction. The output is a 64-bit
4713 * unsigned integer.
4714 *
4715 * There are many inputs for which the result will not fit in the
4716 * 64-bit integer and \ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will
4717 * be returned.
4718 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004719static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004720QCBOR_Private_Exponentitate10(const uint64_t uMantissa,
4721 int64_t nExponent,
4722 uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004723{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004724 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004725
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004726 if(uResult != 0) {
4727 /* This loop will run a maximum of 19 times because
4728 * UINT64_MAX < 10 ^^ 19. More than that will cause
4729 * exit with the overflow error
4730 */
4731 for(; nExponent > 0; nExponent--) {
4732 if(uResult > UINT64_MAX / 10) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004733 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004734 }
4735 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004736 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004737
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004738 for(; nExponent < 0; nExponent++) {
4739 uResult = uResult / 10;
4740 if(uResult == 0) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004741 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004742 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004743 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004744 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004745 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07004746
4747 *puResult = uResult;
4748
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004749 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004750}
4751
4752
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004753/**
4754 * @brief Base 2 exponentiate a mantissa and exponent into an unsigned 64-bit integer.
4755 *
4756 * @param[in] uMantissa The unsigned integer mantissa.
4757 * @param[in] nExponent The signed integer exponent.
4758 * @param[out] puResult Place to return the unsigned integer result.
4759 *
4760 * This computes: mantissa * 2 ^^ exponent as for a big float. The
4761 * output is a 64-bit unsigned integer.
4762 *
4763 * There are many inputs for which the result will not fit in the
4764 * 64-bit integer and \ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will
4765 * be returned.
4766 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004767static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004768QCBOR_Private_Exponentitate2(const uint64_t uMantissa,
4769 int64_t nExponent,
4770 uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004771{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004772 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004773
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004774 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004775
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004776 /* This loop will run a maximum of 64 times because INT64_MAX <
4777 * 2^31. More than that will cause exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07004778 */
4779 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004780 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004781 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004782 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004783 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004784 nExponent--;
4785 }
4786
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004787 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004788 if(uResult == 0) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004789 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004790 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004791 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004792 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004793 }
4794
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004795 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004796
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004797 return QCBOR_SUCCESS;
4798}
4799
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004800
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004801/**
4802 * @brief Exponentiate a signed mantissa and signed exponent to produce a signed result.
4803 *
4804 * @param[in] nMantissa Signed integer mantissa.
4805 * @param[in] nExponent Signed integer exponent.
4806 * @param[out] pnResult Place to put the signed integer result.
4807 * @param[in] pfExp Exponentiation function.
4808 *
4809 * @returns Error code
4810 *
4811 * \c pfExp performs exponentiation on and unsigned mantissa and
4812 * produces an unsigned result. This converts the mantissa from signed
4813 * and converts the result to signed. The exponentiation function is
4814 * either for base 2 or base 10 (and could be other if needed).
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004815 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004816static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004817QCBOR_Private_ExponentiateNN(const int64_t nMantissa,
4818 const int64_t nExponent,
4819 int64_t *pnResult,
4820 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004821{
4822 uint64_t uResult;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004823 uint64_t uMantissa;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004824
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004825 /* Take the absolute value and put it into an unsigned. */
4826 if(nMantissa >= 0) {
4827 /* Positive case is straightforward */
4828 uMantissa = (uint64_t)nMantissa;
4829 } else if(nMantissa != INT64_MIN) {
4830 /* The common negative case. See next. */
4831 uMantissa = (uint64_t)-nMantissa;
4832 } else {
4833 /* int64_t and uint64_t are always two's complement per the
4834 * C standard (and since QCBOR uses these it only works with
4835 * two's complement, which is pretty much universal these
4836 * days). The range of a negative two's complement integer is
4837 * one more that than a positive, so the simple code above might
4838 * not work all the time because you can't simply negate the
4839 * value INT64_MIN because it can't be represented in an
4840 * int64_t. -INT64_MIN can however be represented in a
4841 * uint64_t. Some compilers seem to recognize this case for the
4842 * above code and put the correct value in uMantissa, however
4843 * they are not required to do this by the C standard. This next
4844 * line does however work for all compilers.
4845 *
4846 * This does assume two's complement where -INT64_MIN ==
4847 * INT64_MAX + 1 (which wouldn't be true for one's complement or
4848 * sign and magnitude (but we know we're using two's complement
4849 * because int64_t requires it)).
4850 *
4851 * See these, particularly the detailed commentary:
4852 * https://stackoverflow.com/questions/54915742/does-c99-mandate-a-int64-t-type-be-available-always
4853 * https://stackoverflow.com/questions/37301078/is-negating-int-min-undefined-behaviour
4854 */
4855 uMantissa = (uint64_t)INT64_MAX+1;
4856 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004857
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004858 /* Call the exponentiator passed for either base 2 or base 10.
4859 * Here is where most of the overflow errors are caught. */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004860 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
4861 if(uReturn) {
4862 return uReturn;
4863 }
4864
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004865 /* Convert back to the sign of the original mantissa */
4866 if(nMantissa >= 0) {
4867 if(uResult > INT64_MAX) {
4868 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4869 }
4870 *pnResult = (int64_t)uResult;
4871 } else {
4872 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
4873 * of INT64_MIN. This assumes two's compliment representation
4874 * where INT64_MIN is one increment farther from 0 than
4875 * INT64_MAX. Trying to write -INT64_MIN doesn't work to get
4876 * this because the compiler makes it an int64_t which can't
4877 * represent -INT64_MIN. Also see above.
4878 */
4879 if(uResult > (uint64_t)INT64_MAX+1) {
4880 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4881 }
4882 *pnResult = -(int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004883 }
4884
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004885 return QCBOR_SUCCESS;
4886}
4887
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004888
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004889/**
4890 * @brief Exponentiate an unsigned mantissa and signed exponent to produce an unsigned result.
4891 *
4892 * @param[in] nMantissa Signed integer mantissa.
4893 * @param[in] nExponent Signed integer exponent.
4894 * @param[out] puResult Place to put the signed integer result.
4895 * @param[in] pfExp Exponentiation function.
4896 *
4897 * @returns Error code
4898 *
4899 * \c pfExp performs exponentiation on and unsigned mantissa and
4900 * produces an unsigned result. This errors out if the mantissa
4901 * is negative because the output is unsigned.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004902 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004903static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004904QCBOR_Private_ExponentitateNU(const int64_t nMantissa,
4905 const int64_t nExponent,
4906 uint64_t *puResult,
4907 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004908{
4909 if(nMantissa < 0) {
4910 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4911 }
4912
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004913 /* Cast to unsigned is OK because of check for negative.
4914 * Cast to unsigned is OK because UINT64_MAX > INT64_MAX.
4915 * Exponentiation is straight forward
4916 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004917 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
4918}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004919
4920
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004921/**
4922 * @brief Exponentiate an usnigned mantissa and unsigned exponent to produce an unsigned result.
4923 *
4924 * @param[in] uMantissa Unsigned integer mantissa.
4925 * @param[in] nExponent Unsigned integer exponent.
4926 * @param[out] puResult Place to put the unsigned integer result.
4927 * @param[in] pfExp Exponentiation function.
4928 *
4929 * @returns Error code
4930 *
4931 * \c pfExp performs exponentiation on and unsigned mantissa and
4932 * produces an unsigned result so this is just a wrapper that does
4933 * nothing (and is likely inlined).
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004934 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004935static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004936QCBOR_Private_ExponentitateUU(const uint64_t uMantissa,
4937 const int64_t nExponent,
4938 uint64_t *puResult,
4939 fExponentiator pfExp)
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004940{
4941 return (*pfExp)(uMantissa, nExponent, puResult);
4942}
4943
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004944#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004945
4946
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004947
4948
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004949/**
4950 * @brief Convert a CBOR big number to a uint64_t.
4951 *
4952 * @param[in] BigNum Bytes of the big number to convert.
4953 * @param[in] uMax Maximum value allowed for the result.
4954 * @param[out] pResult Place to put the unsigned integer result.
4955 *
4956 * @returns Error code
4957 *
4958 * Many values will overflow because a big num can represent a much
4959 * larger range than uint64_t.
4960 */
4961static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004962QCBOR_Private_ConvertBigNumToUnsigned(const UsefulBufC BigNum,
4963 const uint64_t uMax,
4964 uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004965{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004966 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004967
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004968 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004969 const uint8_t *pByte = BigNum.ptr;
4970 size_t uLen = BigNum.len;
4971 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07004972 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004973 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004974 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07004975 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004976 }
4977
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004978 *pResult = uResult;
4979 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004980}
4981
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004982
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004983/**
4984 * @brief Convert a CBOR postive big number to a uint64_t.
4985 *
4986 * @param[in] BigNum Bytes of the big number to convert.
4987 * @param[out] pResult Place to put the unsigned integer result.
4988 *
4989 * @returns Error code
4990 *
4991 * Many values will overflow because a big num can represent a much
4992 * larger range than uint64_t.
4993 */
4994static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004995QCBOR_Private_ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum,
4996 uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004997{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004998 return QCBOR_Private_ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004999}
5000
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005001
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005002/**
5003 * @brief Convert a CBOR positive big number to an int64_t.
5004 *
5005 * @param[in] BigNum Bytes of the big number to convert.
5006 * @param[out] pResult Place to put the signed integer result.
5007 *
5008 * @returns Error code
5009 *
5010 * Many values will overflow because a big num can represent a much
5011 * larger range than int64_t.
5012 */
5013static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005014QCBOR_Private_ConvertPositiveBigNumToSigned(const UsefulBufC BigNum,
5015 int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005016{
5017 uint64_t uResult;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005018 QCBORError uError = QCBOR_Private_ConvertBigNumToUnsigned(BigNum,
5019 INT64_MAX,
5020 &uResult);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005021 if(uError) {
5022 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005023 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005024 /* Cast is safe because ConvertBigNumToUnsigned limits to INT64_MAX */
Laurence Lundbladee6430642020-03-14 21:15:44 -07005025 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005026 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005027}
5028
5029
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005030/**
5031 * @brief Convert a CBOR negative big number to an int64_t.
5032 *
5033 * @param[in] BigNum Bytes of the big number to convert.
5034 * @param[out] pnResult Place to put the signed integer result.
5035 *
5036 * @returns Error code
5037 *
5038 * Many values will overflow because a big num can represent a much
5039 * larger range than int64_t.
5040 */
5041static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005042QCBOR_Private_ConvertNegativeBigNumToSigned(const UsefulBufC BigNum,
5043 int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005044{
5045 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005046 /* The negative integer furthest from zero for a C int64_t is
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005047 * INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
5048 * negative number in CBOR is computed as -n - 1 where n is the
5049 * encoded integer, where n is what is in the variable BigNum. When
5050 * converting BigNum to a uint64_t, the maximum value is thus
5051 * INT64_MAX, so that when it -n - 1 is applied to it the result
5052 * will never be further from 0 than INT64_MIN.
5053 *
5054 * -n - 1 <= INT64_MIN.
5055 * -n - 1 <= -INT64_MAX - 1
5056 * n <= INT64_MAX.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005057 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005058 QCBORError uError = QCBOR_Private_ConvertBigNumToUnsigned(BigNum,
5059 INT64_MAX,
5060 &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005061 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005062 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005063 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005064
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005065 /* Now apply -n - 1. The cast is safe because
5066 * ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
5067 * is the largest positive integer that an int64_t can
5068 * represent. */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005069 *pnResult = -(int64_t)uResult - 1;
5070
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005071 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005072}
5073
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005074
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005075
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005076
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005077/**
5078 * @brief Convert integers and floats to an int64_t.
5079 *
5080 * @param[in] pItem The item to convert.
5081 * @param[in] uConvertTypes Bit mask list of conversion options.
5082 * @param[out] pnValue The resulting converted value.
5083 *
5084 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
5085 * in uConvertTypes.
5086 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
5087 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
5088 * or too small.
5089 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07005090static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005091QCBOR_Private_ConvertInt64(const QCBORItem *pItem,
5092 const uint32_t uConvertTypes,
5093 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005094{
5095 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005096 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005097 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005098#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005099 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005100 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
5101 http://www.cplusplus.com/reference/cmath/llround/
5102 */
5103 // Not interested in FE_INEXACT
5104 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005105 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
5106 *pnValue = llround(pItem->val.dfnum);
5107 } else {
5108 *pnValue = lroundf(pItem->val.fnum);
5109 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005110 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
5111 // llround() shouldn't result in divide by zero, but catch
5112 // it here in case it unexpectedly does. Don't try to
5113 // distinguish between the various exceptions because it seems
5114 // they vary by CPU, compiler and OS.
5115 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005116 }
5117 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005118 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005119 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005120#else
5121 return QCBOR_ERR_HW_FLOAT_DISABLED;
5122#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005123 break;
5124
5125 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005126 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005127 *pnValue = pItem->val.int64;
5128 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005129 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005130 }
5131 break;
5132
5133 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005134 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005135 if(pItem->val.uint64 < INT64_MAX) {
5136 *pnValue = pItem->val.int64;
5137 } else {
5138 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5139 }
5140 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005141 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005142 }
5143 break;
5144
Laurence Lundblade2d493002024-02-01 11:09:17 -07005145 case QCBOR_TYPE_65BIT_NEG_INT:
5146 /* This type occurs if the value won't fit into int64_t
5147 * so this is always an error. */
5148 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5149 break;
5150
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005151 default:
5152 return QCBOR_ERR_UNEXPECTED_TYPE;
5153 }
5154 return QCBOR_SUCCESS;
5155}
5156
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005157
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005158/**
5159 * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
5160 *
5161 * @param[in] pMe The decode context.
5162 * @param[in] uConvertTypes Bit mask list of conversion options.
5163 * @param[out] pnValue Result of the conversion.
5164 * @param[in,out] pItem Temporary space to store Item, returned item.
5165 *
5166 * See QCBORDecode_GetInt64Convert().
5167 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005168void
5169QCBORDecode_Private_GetInt64Convert(QCBORDecodeContext *pMe,
5170 uint32_t uConvertTypes,
5171 int64_t *pnValue,
5172 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005173{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07005174 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07005175 return;
5176 }
5177
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005178 QCBORError uError = QCBORDecode_GetNext(pMe, pItem);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005179 if(uError) {
5180 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005181 return;
5182 }
5183
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005184 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005185 uConvertTypes,
5186 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005187}
5188
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005189/**
5190 * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
5191 *
5192 * @param[in] pMe The decode context.
5193 * @param[in] nLabel Label to find in map.
5194 * @param[in] uConvertTypes Bit mask list of conversion options.
5195 * @param[out] pnValue Result of the conversion.
5196 * @param[in,out] pItem Temporary space to store Item, returned item.
5197 *
5198 * See QCBORDecode_GetInt64ConvertInMapN().
5199 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005200void
5201QCBORDecode_Private_GetInt64ConvertInMapN(QCBORDecodeContext *pMe,
5202 int64_t nLabel,
5203 uint32_t uConvertTypes,
5204 int64_t *pnValue,
5205 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005206{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005207 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005208 if(pMe->uLastError != QCBOR_SUCCESS) {
5209 return;
5210 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005211
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005212 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
5213 uConvertTypes,
5214 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005215}
5216
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005217/**
5218 * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
5219 *
5220 * @param[in] pMe The decode context.
5221 * @param[in] szLabel Label to find in map.
5222 * @param[in] uConvertTypes Bit mask list of conversion options.
5223 * @param[out] pnValue Result of the conversion.
5224 * @param[in,out] pItem Temporary space to store Item, returned item.
5225 *
5226 * See QCBORDecode_GetInt64ConvertInMapSZ().
5227 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005228void
5229QCBORDecode_Private_GetInt64ConvertInMapSZ(QCBORDecodeContext *pMe,
5230 const char * szLabel,
5231 uint32_t uConvertTypes,
5232 int64_t *pnValue,
5233 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005234{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005235 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005236 if(pMe->uLastError != QCBOR_SUCCESS) {
5237 return;
5238 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005239
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005240 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
5241 uConvertTypes,
5242 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005243}
5244
5245
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005246/**
5247 * @brief Convert many number types to an int64_t.
5248 *
5249 * @param[in] pItem The item to convert.
5250 * @param[in] uConvertTypes Bit mask list of conversion options.
5251 * @param[out] pnValue The resulting converted value.
5252 *
5253 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
5254 * in uConvertTypes.
5255 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
5256 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
5257 * or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005258 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07005259static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005260QCBOR_Private_Int64ConvertAll(const QCBORItem *pItem,
5261 const uint32_t uConvertTypes,
5262 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005263{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005264 switch(pItem->uDataType) {
5265
5266 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005267 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005268 return QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005269 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005270 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005271 }
5272 break;
5273
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005274 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005275 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005276 return QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005277 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005278 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005279 }
5280 break;
5281
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005282#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005283 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005284 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005285 return QCBOR_Private_ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005286 pItem->val.expAndMantissa.nExponent,
5287 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005288 &QCBOR_Private_Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005289 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005290 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005291 }
5292 break;
5293
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005294 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005295 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005296 return QCBOR_Private_ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005297 pItem->val.expAndMantissa.nExponent,
5298 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005299 QCBOR_Private_Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005300 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005301 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005302 }
5303 break;
5304
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005305 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005306 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005307 int64_t nMantissa;
5308 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005309 uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005310 if(uErr) {
5311 return uErr;
5312 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005313 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005314 pItem->val.expAndMantissa.nExponent,
5315 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005316 QCBOR_Private_Exponentitate10);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005317 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005318 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005319 }
5320 break;
5321
5322 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005323 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005324 int64_t nMantissa;
5325 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005326 uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005327 if(uErr) {
5328 return uErr;
5329 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005330 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005331 pItem->val.expAndMantissa.nExponent,
5332 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005333 QCBOR_Private_Exponentitate10);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005334 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005335 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005336 }
5337 break;
5338
5339 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005340 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005341 int64_t nMantissa;
5342 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005343 uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005344 if(uErr) {
5345 return uErr;
5346 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005347 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005348 pItem->val.expAndMantissa.nExponent,
5349 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005350 QCBOR_Private_Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005351 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005352 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005353 }
5354 break;
5355
5356 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005357 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005358 int64_t nMantissa;
5359 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005360 uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005361 if(uErr) {
5362 return uErr;
5363 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005364 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005365 pItem->val.expAndMantissa.nExponent,
5366 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005367 QCBOR_Private_Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005368 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005369 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005370 }
5371 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005372#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005373
Laurence Lundbladee6430642020-03-14 21:15:44 -07005374
Laurence Lundbladec4537442020-04-14 18:53:22 -07005375 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005376 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005377}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005378
5379
Laurence Lundbladec4537442020-04-14 18:53:22 -07005380/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005381 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005382 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005383void
5384QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe,
5385 const uint32_t uConvertTypes,
5386 int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07005387{
5388 QCBORItem Item;
5389
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005390 QCBORDecode_Private_GetInt64Convert(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07005391
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005392 if(pMe->uLastError == QCBOR_SUCCESS) {
5393 // The above conversion succeeded
5394 return;
5395 }
5396
Laurence Lundbladef6c86662020-05-12 02:08:00 -07005397 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005398 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07005399 return;
5400 }
5401
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005402 pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
5403 uConvertTypes,
5404 pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005405}
5406
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005407
5408/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005409 * Public function, see header qcbor/qcbor_decode.h file
5410 */
5411void
5412QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
5413 const int64_t nLabel,
5414 const uint32_t uConvertTypes,
5415 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005416{
5417 QCBORItem Item;
5418
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005419 QCBORDecode_Private_GetInt64ConvertInMapN(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07005420 nLabel,
5421 uConvertTypes,
5422 pnValue,
5423 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005424
5425 if(pMe->uLastError == QCBOR_SUCCESS) {
5426 // The above conversion succeeded
5427 return;
5428 }
5429
5430 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5431 // The above conversion failed in a way that code below can't correct
5432 return;
5433 }
5434
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005435 pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
5436 uConvertTypes,
5437 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005438}
5439
5440
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005441/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005442 * Public function, see header qcbor/qcbor_decode.h file
5443 */
5444void
5445QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
5446 const char *szLabel,
5447 const uint32_t uConvertTypes,
5448 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005449{
5450 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005451 QCBORDecode_Private_GetInt64ConvertInMapSZ(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07005452 szLabel,
5453 uConvertTypes,
5454 pnValue,
5455 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005456
5457 if(pMe->uLastError == QCBOR_SUCCESS) {
5458 // The above conversion succeeded
5459 return;
5460 }
5461
5462 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5463 // The above conversion failed in a way that code below can't correct
5464 return;
5465 }
5466
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005467 pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
5468 uConvertTypes,
5469 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005470}
5471
5472
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005473/**
5474 * @brief Convert many number types to an uint64_t.
5475 *
5476 * @param[in] pItem The item to convert.
5477 * @param[in] uConvertTypes Bit mask list of conversion options.
5478 * @param[out] puValue The resulting converted value.
5479 *
5480 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
5481 * in uConvertTypes.
5482 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
5483 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
5484 * or too small.
5485 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005486static QCBORError
5487QCBOR_Private_ConvertUInt64(const QCBORItem *pItem,
5488 const uint32_t uConvertTypes,
5489 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005490{
5491 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005492 case QCBOR_TYPE_DOUBLE:
5493 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005494#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005495 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005496 // Can't use llround here because it will not convert values
5497 // greater than INT64_MAX and less than UINT64_MAX that
5498 // need to be converted so it is more complicated.
5499 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
5500 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
5501 if(isnan(pItem->val.dfnum)) {
5502 return QCBOR_ERR_FLOAT_EXCEPTION;
5503 } else if(pItem->val.dfnum < 0) {
5504 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5505 } else {
5506 double dRounded = round(pItem->val.dfnum);
5507 // See discussion in DecodeDateEpoch() for
5508 // explanation of - 0x7ff
5509 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
5510 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5511 }
5512 *puValue = (uint64_t)dRounded;
5513 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005514 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005515 if(isnan(pItem->val.fnum)) {
5516 return QCBOR_ERR_FLOAT_EXCEPTION;
5517 } else if(pItem->val.fnum < 0) {
5518 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5519 } else {
5520 float fRounded = roundf(pItem->val.fnum);
5521 // See discussion in DecodeDateEpoch() for
5522 // explanation of - 0x7ff
5523 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
5524 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5525 }
5526 *puValue = (uint64_t)fRounded;
5527 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005528 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005529 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
5530 // round() and roundf() shouldn't result in exceptions here, but
5531 // catch them to be robust and thorough. Don't try to
5532 // distinguish between the various exceptions because it seems
5533 // they vary by CPU, compiler and OS.
5534 return QCBOR_ERR_FLOAT_EXCEPTION;
5535 }
5536
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005537 } else {
5538 return QCBOR_ERR_UNEXPECTED_TYPE;
5539 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005540#else
5541 return QCBOR_ERR_HW_FLOAT_DISABLED;
5542#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005543 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005544
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005545 case QCBOR_TYPE_INT64:
5546 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
5547 if(pItem->val.int64 >= 0) {
5548 *puValue = (uint64_t)pItem->val.int64;
5549 } else {
5550 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5551 }
5552 } else {
5553 return QCBOR_ERR_UNEXPECTED_TYPE;
5554 }
5555 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005556
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005557 case QCBOR_TYPE_UINT64:
5558 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade2d493002024-02-01 11:09:17 -07005559 *puValue = pItem->val.uint64;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005560 } else {
5561 return QCBOR_ERR_UNEXPECTED_TYPE;
5562 }
5563 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005564
Laurence Lundblade2d493002024-02-01 11:09:17 -07005565 case QCBOR_TYPE_65BIT_NEG_INT:
5566 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5567
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005568 default:
5569 return QCBOR_ERR_UNEXPECTED_TYPE;
5570 }
5571
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005572 return QCBOR_SUCCESS;
5573}
Laurence Lundbladec4537442020-04-14 18:53:22 -07005574
5575
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005576/**
5577 * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
5578 *
5579 * @param[in] pMe The decode context.
5580 * @param[in] uConvertTypes Bit mask list of conversion options.
5581 * @param[out] puValue Result of the conversion.
5582 * @param[in,out] pItem Temporary space to store Item, returned item.
5583 *
5584 * See QCBORDecode_GetUInt64Convert().
5585 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005586void
5587QCBORDecode_Private_GetUInt64Convert(QCBORDecodeContext *pMe,
5588 const uint32_t uConvertTypes,
5589 uint64_t *puValue,
5590 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07005591{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005592 if(pMe->uLastError != QCBOR_SUCCESS) {
5593 return;
5594 }
5595
Laurence Lundbladec4537442020-04-14 18:53:22 -07005596 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005597
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005598 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5599 if(uError) {
5600 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005601 return;
5602 }
5603
Laurence Lundbladea826c502020-05-10 21:07:00 -07005604 if(pItem) {
5605 *pItem = Item;
5606 }
5607
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005608 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(&Item,
5609 uConvertTypes,
5610 puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07005611}
5612
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005613
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005614/**
5615 * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
5616 *
5617 * @param[in] pMe The decode context.
5618 * @param[in] nLabel Label to find in map.
5619 * @param[in] uConvertTypes Bit mask list of conversion options.
5620 * @param[out] puValue Result of the conversion.
5621 * @param[in,out] pItem Temporary space to store Item, returned item.
5622 *
5623 * See QCBORDecode_GetUInt64ConvertInMapN().
5624 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005625void
5626QCBORDecode_Private_GetUInt64ConvertInMapN(QCBORDecodeContext *pMe,
5627 const int64_t nLabel,
5628 const uint32_t uConvertTypes,
5629 uint64_t *puValue,
5630 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005631{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005632 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005633 if(pMe->uLastError != QCBOR_SUCCESS) {
5634 return;
5635 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005636
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005637 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
5638 uConvertTypes,
5639 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005640}
5641
5642
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005643/**
5644 * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
5645 *
5646 * @param[in] pMe The decode context.
5647 * @param[in] szLabel Label to find in map.
5648 * @param[in] uConvertTypes Bit mask list of conversion options.
5649 * @param[out] puValue Result of the conversion.
5650 * @param[in,out] pItem Temporary space to store Item, returned item.
5651 *
5652 * See QCBORDecode_GetUInt64ConvertInMapSZ().
5653 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005654void
5655QCBORDecode_Private_GetUInt64ConvertInMapSZ(QCBORDecodeContext *pMe,
5656 const char *szLabel,
5657 const uint32_t uConvertTypes,
5658 uint64_t *puValue,
5659 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005660{
5661 if(pMe->uLastError != QCBOR_SUCCESS) {
5662 return;
5663 }
5664
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005665 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005666 if(pMe->uLastError != QCBOR_SUCCESS) {
5667 return;
5668 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005669
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005670 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
5671 uConvertTypes,
5672 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005673}
5674
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005675
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005676/**
5677 * @brief Convert many number types to an unt64_t.
5678 *
5679 * @param[in] pItem The item to convert.
5680 * @param[in] uConvertTypes Bit mask list of conversion options.
5681 * @param[out] puValue The resulting converted value.
5682 *
5683 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
5684 * in uConvertTypes.
5685 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
5686 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
5687 * or too small.
5688 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07005689static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005690QCBOR_Private_UInt64ConvertAll(const QCBORItem *pItem,
5691 const uint32_t uConvertTypes,
5692 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005693{
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08005694 switch(pItem->uDataType) { /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005695
5696 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005697 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005698 return QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005699 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005700 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005701 }
5702 break;
5703
5704 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005705 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005706 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5707 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005708 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005709 }
5710 break;
5711
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005712#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005713
5714 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005715 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005716 return QCBOR_Private_ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005717 pItem->val.expAndMantissa.nExponent,
5718 puValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005719 QCBOR_Private_Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005720 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005721 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005722 }
5723 break;
5724
5725 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005726 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005727 return QCBOR_Private_ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005728 pItem->val.expAndMantissa.nExponent,
5729 puValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005730 QCBOR_Private_Exponentitate2);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005731 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005732 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005733 }
5734 break;
5735
5736 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005737 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005738 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005739 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005740 uErr = QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005741 if(uErr != QCBOR_SUCCESS) {
5742 return uErr;
5743 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005744 return QCBOR_Private_ExponentitateUU(uMantissa,
5745 pItem->val.expAndMantissa.nExponent,
5746 puValue,
5747 QCBOR_Private_Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005748 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005749 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005750 }
5751 break;
5752
5753 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005754 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005755 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5756 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005757 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005758 }
5759 break;
5760
5761 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005762 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005763 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005764 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005765 uErr = QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum,
5766 &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005767 if(uErr != QCBOR_SUCCESS) {
5768 return uErr;
5769 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005770 return QCBOR_Private_ExponentitateUU(uMantissa,
5771 pItem->val.expAndMantissa.nExponent,
5772 puValue,
5773 QCBOR_Private_Exponentitate2);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005774 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005775 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005776 }
5777 break;
5778
5779 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005780 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005781 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5782 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005783 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005784 }
5785 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005786#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005787 default:
5788 return QCBOR_ERR_UNEXPECTED_TYPE;
5789 }
5790}
5791
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005792
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005793/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005794 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005795 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005796void
5797QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe,
5798 const uint32_t uConvertTypes,
5799 uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005800{
5801 QCBORItem Item;
5802
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005803 QCBORDecode_Private_GetUInt64Convert(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005804
Laurence Lundbladef6c86662020-05-12 02:08:00 -07005805 if(pMe->uLastError == QCBOR_SUCCESS) {
5806 // The above conversion succeeded
5807 return;
5808 }
5809
5810 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5811 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07005812 return;
5813 }
5814
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005815 pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
5816 uConvertTypes,
5817 puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005818}
5819
Laurence Lundbladec4537442020-04-14 18:53:22 -07005820
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005821/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005822 * Public function, see header qcbor/qcbor_decode.h file
5823 */
5824void
5825QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
5826 const int64_t nLabel,
5827 const uint32_t uConvertTypes,
5828 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005829{
5830 QCBORItem Item;
5831
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005832 QCBORDecode_Private_GetUInt64ConvertInMapN(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07005833 nLabel,
5834 uConvertTypes,
5835 puValue,
5836 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005837
5838 if(pMe->uLastError == QCBOR_SUCCESS) {
5839 // The above conversion succeeded
5840 return;
5841 }
5842
5843 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5844 // The above conversion failed in a way that code below can't correct
5845 return;
5846 }
5847
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005848 pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
5849 uConvertTypes,
5850 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005851}
5852
5853
5854/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005855 * Public function, see header qcbor/qcbor_decode.h file
5856 */
5857void
5858QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
5859 const char *szLabel,
5860 const uint32_t uConvertTypes,
5861 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005862{
5863 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005864 QCBORDecode_Private_GetUInt64ConvertInMapSZ(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07005865 szLabel,
5866 uConvertTypes,
5867 puValue,
5868 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005869
5870 if(pMe->uLastError == QCBOR_SUCCESS) {
5871 // The above conversion succeeded
5872 return;
5873 }
5874
5875 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5876 // The above conversion failed in a way that code below can't correct
5877 return;
5878 }
5879
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005880 pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
5881 uConvertTypes,
5882 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005883}
5884
5885
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005886
5887
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02005888#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005889/**
5890 * @brief Basic conversions to a double.
5891 *
5892 * @param[in] pItem The item to convert
5893 * @param[in] uConvertTypes Bit flags indicating source types for conversion
5894 * @param[out] pdValue The value converted to a double
5895 *
5896 * This does the conversions that don't need much object code,
5897 * the conversions from int, uint and float to double.
5898 *
5899 * See QCBOR_Private_DoubleConvertAll() for the full set
5900 * of conversions.
5901 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005902static QCBORError
5903QCBOR_Private_ConvertDouble(const QCBORItem *pItem,
5904 const uint32_t uConvertTypes,
5905 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005906{
5907 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005908 case QCBOR_TYPE_FLOAT:
5909#ifndef QCBOR_DISABLE_FLOAT_HW_USE
5910 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5911 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005912 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005913 *pdValue = (double)pItem->val.fnum;
5914 } else {
5915 return QCBOR_ERR_UNEXPECTED_TYPE;
5916 }
5917 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005918#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005919 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005920#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005921 break;
5922
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005923 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005924 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5925 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005926 *pdValue = pItem->val.dfnum;
5927 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005928 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005929 }
5930 }
5931 break;
5932
5933 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005934#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005935 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005936 // A simple cast seems to do the job with no worry of exceptions.
5937 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005938 *pdValue = (double)pItem->val.int64;
5939
5940 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005941 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005942 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005943#else
5944 return QCBOR_ERR_HW_FLOAT_DISABLED;
5945#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005946 break;
5947
5948 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005949#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005950 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005951 // A simple cast seems to do the job with no worry of exceptions.
5952 // There will be precision loss for some values.
5953 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005954 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005955 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005956 }
5957 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005958#else
5959 return QCBOR_ERR_HW_FLOAT_DISABLED;
5960#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005961
Laurence Lundblade2d493002024-02-01 11:09:17 -07005962 case QCBOR_TYPE_65BIT_NEG_INT:
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -08005963#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade2d493002024-02-01 11:09:17 -07005964 *pdValue = -(double)pItem->val.uint64 - 1;
5965 break;
Laurence Lundbladeeb3cdef2024-02-17 20:38:55 -08005966#else
5967 return QCBOR_ERR_HW_FLOAT_DISABLED;
5968#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade2d493002024-02-01 11:09:17 -07005969
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005970 default:
5971 return QCBOR_ERR_UNEXPECTED_TYPE;
5972 }
5973
5974 return QCBOR_SUCCESS;
5975}
5976
5977
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005978/**
5979 * @brief Almost-public method to decode a number and convert to double (semi-private).
5980 *
5981 * @param[in] pMe The decode context.
5982 * @param[in] uConvertTypes Bit mask list of conversion options
5983 * @param[out] pdValue The output of the conversion.
5984 * @param[in,out] pItem Temporary space to store Item, returned item.
5985 *
5986 * See QCBORDecode_GetDoubleConvert().
5987 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005988void
5989QCBORDecode_Private_GetDoubleConvert(QCBORDecodeContext *pMe,
5990 const uint32_t uConvertTypes,
5991 double *pdValue,
5992 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005993{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005994 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07005995 return;
5996 }
5997
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005998 QCBORError uError = QCBORDecode_GetNext(pMe, pItem);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005999 if(uError) {
6000 pMe->uLastError = (uint8_t)uError;
6001 return;
6002 }
6003
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006004 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006005 uConvertTypes,
6006 pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006007}
Laurence Lundbladec4537442020-04-14 18:53:22 -07006008
Laurence Lundbladec4537442020-04-14 18:53:22 -07006009
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006010/**
6011 * @brief Almost-public method to decode a number and convert to double (semi-private).
6012 *
6013 * @param[in] pMe The decode context.
6014 * @param[in] nLabel Label to find in map.
6015 * @param[in] uConvertTypes Bit mask list of conversion options
6016 * @param[out] pdValue The output of the conversion.
6017 * @param[in,out] pItem Temporary space to store Item, returned item.
6018 *
6019 * See QCBORDecode_GetDoubleConvertInMapN().
6020 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006021void
6022QCBORDecode_Private_GetDoubleConvertInMapN(QCBORDecodeContext *pMe,
6023 const int64_t nLabel,
6024 const uint32_t uConvertTypes,
6025 double *pdValue,
6026 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006027{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006028 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07006029 if(pMe->uLastError != QCBOR_SUCCESS) {
6030 return;
6031 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006032
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006033 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
6034 uConvertTypes,
6035 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006036}
6037
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006038
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006039/**
6040 * @brief Almost-public method to decode a number and convert to double (semi-private).
6041 *
6042 * @param[in] pMe The decode context.
6043 * @param[in] szLabel Label to find in map.
6044 * @param[in] uConvertTypes Bit mask list of conversion options
6045 * @param[out] pdValue The output of the conversion.
6046 * @param[in,out] pItem Temporary space to store Item, returned item.
6047 *
6048 * See QCBORDecode_GetDoubleConvertInMapSZ().
6049 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006050void
6051QCBORDecode_Private_GetDoubleConvertInMapSZ(QCBORDecodeContext *pMe,
6052 const char *szLabel,
6053 const uint32_t uConvertTypes,
6054 double *pdValue,
6055 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006056{
6057 if(pMe->uLastError != QCBOR_SUCCESS) {
6058 return;
6059 }
6060
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006061 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07006062 if(pMe->uLastError != QCBOR_SUCCESS) {
6063 return;
6064 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006065
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006066 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
6067 uConvertTypes,
6068 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006069}
6070
6071
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006072#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006073/**
6074 * @brief Convert a big number to double-precision float.
6075 *
6076 * @param[in] BigNum The big number to convert
6077 *
6078 * @returns The double value.
6079 *
6080 * This will always succeed. It will lose precision for larger
6081 * numbers. If the big number is too large to fit (more than
6082 * 1.7976931348623157E+308) infinity will be returned. NaN is never
6083 * returned.
6084 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006085static double
6086QCBOR_Private_ConvertBigNumToDouble(const UsefulBufC BigNum)
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07006087{
6088 double dResult;
6089
6090 dResult = 0.0;
6091 const uint8_t *pByte = BigNum.ptr;
6092 size_t uLen = BigNum.len;
6093 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006094 * is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07006095 while(uLen--) {
6096 dResult = (dResult * 256.0) + (double)*pByte++;
6097 }
6098
6099 return dResult;
6100}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006101#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
6102
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07006103
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006104
6105
6106/**
6107 * @brief Convert many number types to a double.
6108 *
6109 * @param[in] pItem The item to convert.
6110 * @param[in] uConvertTypes Bit mask list of conversion options.
6111 * @param[out] pdValue The resulting converted value.
6112 *
6113 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
6114 * in uConvertTypes.
6115 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
6116 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
6117 * or too small.
6118 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07006119static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006120QCBOR_Private_DoubleConvertAll(const QCBORItem *pItem,
6121 const uint32_t uConvertTypes,
6122 double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006123{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006124#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07006125 /*
Laurence Lundblade16a207a2021-09-18 17:22:46 -07006126 * What Every Computer Scientist Should Know About Floating-Point Arithmetic
6127 * https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
6128 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006129 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07006130
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006131#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006132 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006133 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07006134 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006135 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
6136 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
6137 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006138 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006139 }
6140 break;
6141
6142 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006143 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07006144 // Underflow gives 0, overflow gives infinity
6145 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
6146 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006147 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006148 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006149 }
6150 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006151#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006152
6153 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006154 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006155 *pdValue = QCBOR_Private_ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006156 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006157 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006158 }
6159 break;
6160
6161 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006162 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006163 *pdValue = -1-QCBOR_Private_ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006164 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006165 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006166 }
6167 break;
6168
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006169#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006170 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006171 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006172 double dMantissa = QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006173 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
6174 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006175 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006176 }
6177 break;
6178
6179 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006180 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006181 double dMantissa = -QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006182 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
6183 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006184 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006185 }
6186 break;
6187
6188 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006189 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006190 double dMantissa = QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006191 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
6192 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006193 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006194 }
6195 break;
6196
6197 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006198 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006199 double dMantissa = -1-QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006200 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
6201 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006202 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006203 }
6204 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006205#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade410c7e02020-06-25 23:35:29 -07006206
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006207 default:
6208 return QCBOR_ERR_UNEXPECTED_TYPE;
6209 }
6210
6211 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006212
6213#else
6214 (void)pItem;
6215 (void)uConvertTypes;
6216 (void)pdValue;
6217 return QCBOR_ERR_HW_FLOAT_DISABLED;
6218#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
6219
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006220}
6221
6222
6223/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006224 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006225 */
6226void
6227QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
6228 const uint32_t uConvertTypes,
6229 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006230{
6231
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006232 QCBORItem Item;
6233
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006234 QCBORDecode_Private_GetDoubleConvert(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006235
6236 if(pMe->uLastError == QCBOR_SUCCESS) {
6237 // The above conversion succeeded
6238 return;
6239 }
6240
6241 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6242 // The above conversion failed in a way that code below can't correct
6243 return;
6244 }
6245
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006246 pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
6247 uConvertTypes,
6248 pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07006249}
6250
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006251
6252/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006253 * Public function, see header qcbor/qcbor_decode.h file
6254 */
6255void
6256QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
6257 const int64_t nLabel,
6258 const uint32_t uConvertTypes,
6259 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006260{
6261 QCBORItem Item;
6262
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006263 QCBORDecode_Private_GetDoubleConvertInMapN(pMe,
6264 nLabel,
6265 uConvertTypes,
6266 pdValue,
6267 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006268
6269 if(pMe->uLastError == QCBOR_SUCCESS) {
6270 // The above conversion succeeded
6271 return;
6272 }
6273
6274 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6275 // The above conversion failed in a way that code below can't correct
6276 return;
6277 }
6278
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006279 pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
6280 uConvertTypes,
6281 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006282}
6283
6284
6285/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006286 * Public function, see header qcbor/qcbor_decode.h file
6287 */
6288void
6289QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
6290 const char *szLabel,
6291 const uint32_t uConvertTypes,
6292 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006293{
6294 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006295 QCBORDecode_Private_GetDoubleConvertInMapSZ(pMe,
6296 szLabel,
6297 uConvertTypes,
6298 pdValue,
6299 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006300
6301 if(pMe->uLastError == QCBOR_SUCCESS) {
6302 // The above conversion succeeded
6303 return;
6304 }
6305
6306 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6307 // The above conversion failed in a way that code below can't correct
6308 return;
6309 }
6310
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006311 pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
6312 uConvertTypes,
6313 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006314}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02006315#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006316
6317
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006318
6319
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006320#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006321/**
6322 * @brief Convert an integer to a big number
6323 *
6324 * @param[in] uInt The integer to convert.
6325 * @param[in] Buffer The buffer to output the big number to.
6326 *
6327 * @returns The big number or NULLUsefulBufC is the buffer is to small.
6328 *
6329 * This always succeeds unless the buffer is too small.
6330 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006331static UsefulBufC
6332QCBOR_Private_ConvertIntToBigNum(uint64_t uInt, const UsefulBuf Buffer)
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006333{
6334 while((uInt & 0xff00000000000000UL) == 0) {
6335 uInt = uInt << 8;
6336 };
6337
6338 UsefulOutBuf UOB;
6339
6340 UsefulOutBuf_Init(&UOB, Buffer);
6341
6342 while(uInt) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006343 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
6344 uInt = uInt << 8;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006345 }
6346
6347 return UsefulOutBuf_OutUBuf(&UOB);
6348}
6349
6350
Laurence Lundblade37286c02022-09-03 10:05:02 -07006351/**
6352 * @brief Check and/or complete mantissa and exponent item.
6353 *
6354 * @param[in] pMe The decoder context
6355 * @param[in] TagSpec Expected type(s)
6356 * @param[in,out] pItem See below
6357 *
6358 * This is for decimal fractions and big floats, both of which are a
6359 * mantissa and exponent.
6360 *
6361 * The input item is either a fully decoded decimal faction or big
6362 * float, or a just the decoded first item of a decimal fraction or
6363 * big float.
6364 *
6365 * On output, the item is always a fully decoded decimal fraction or
6366 * big float.
6367 *
6368 * This errors out if the input type does not meet the TagSpec.
6369 */
6370// TODO: document and see tests for the bug that was fixed by this rewrite
6371static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006372QCBOR_Private_ExpMantissaTypeHandler(QCBORDecodeContext *pMe,
6373 const QCBOR_Private_TagSpec TagSpec,
6374 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006375{
6376 QCBORError uErr;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006377
Laurence Lundblade37286c02022-09-03 10:05:02 -07006378 /* pItem could either be an auto-decoded mantissa and exponent or
6379 * the opening array of an undecoded mantissa and exponent. This
6380 * check will succeed on either, but doesn't say which it was.
6381 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006382 uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07006383 if(uErr != QCBOR_SUCCESS) {
6384 goto Done;
6385 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006386
Laurence Lundblade37286c02022-09-03 10:05:02 -07006387 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
6388 /* The item is an array, which means is is an undecoded mantissa
6389 * and exponent. This call consumes the items in the array and
6390 * results in a decoded mantissa and exponent in pItem. This is
6391 * the case where there was no tag.
6392 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006393 uErr = QCBORDecode_Private_ExpMantissa(pMe, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006394 if(uErr != QCBOR_SUCCESS) {
6395 goto Done;
6396 }
6397
Laurence Lundblade37286c02022-09-03 10:05:02 -07006398 /* The above decode didn't determine whether it is a decimal
6399 * fraction or big num. Which of these two depends on what the
6400 * caller wants it decoded as since there is no tag, so fish the
6401 * type out of the TagSpec. */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006402 pItem->uDataType = QCBOR_Private_ExpMantissaDataType(TagSpec.uTaggedTypes[0], pItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07006403
6404 /* No need to check the type again. All that we need to know was
6405 * that it decoded correctly as a mantissa and exponent. The
6406 * QCBOR type is set out by what was requested.
6407 */
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006408 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07006409
6410 /* If the item was not an array and the check passed, then
6411 * it is a fully decoded big float or decimal fraction and
6412 * matches what is requested.
6413 */
6414
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006415Done:
6416 return uErr;
6417}
6418
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006419
Laurence Lundblade37286c02022-09-03 10:05:02 -07006420/* Some notes from the work to disable tags.
6421 *
6422 * The API for big floats and decimal fractions seems good.
6423 * If there's any issue with it it's that the code size to
6424 * implement is a bit large because of the conversion
6425 * to/from int and bignum that is required. There is no API
6426 * that doesn't do the conversion so dead stripping will never
6427 * leave that code out.
6428 *
6429 * The implementation itself seems correct, but not as clean
6430 * and neat as it could be. It could probably be smaller too.
6431 *
6432 * The implementation has three main parts / functions
6433 * - The decoding of the array of two
6434 * - All the tag and type checking for the various API functions
6435 * - Conversion to/from bignum and int
6436 *
6437 * The type checking seems like it wastes the most code for
6438 * what it needs to do.
6439 *
6440 * The inlining for the conversion is probably making the
6441 * overall code base larger.
6442 *
6443 * The tests cases could be organized a lot better and be
6444 * more thorough.
6445 *
6446 * Seems also like there could be more common code in the
6447 * first tier part of the public API. Some functions only
6448 * vary by a TagSpec.
6449 */
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006450
6451/**
6452 * @brief Common processor for exponent and mantissa.
6453 *
6454 * @param[in] pMe The decode context.
6455 * @param[in] TagSpec The expected/allowed tags.
6456 * @param[in] pItem The data item to process.
6457 * @param[out] pnMantissa The returned mantissa as an int64_t.
6458 * @param[out] pnExponent The returned exponent as an int64_t.
6459 *
6460 * This handles exponent and mantissa for base 2 and 10. This
6461 * is limited to a mantissa that is an int64_t. See also
6462 * QCBORDecode_Private_ProcessExpMantissaBig().
6463 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006464static void
6465QCBOR_Private_ProcessExpMantissa(QCBORDecodeContext *pMe,
6466 const QCBOR_Private_TagSpec TagSpec,
6467 QCBORItem *pItem,
6468 int64_t *pnMantissa,
6469 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006470{
6471 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006472
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006473 uErr = QCBOR_Private_ExpMantissaTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006474 if(uErr != QCBOR_SUCCESS) {
6475 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006476 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006477
Laurence Lundblade9b334962020-08-27 10:55:53 -07006478 switch (pItem->uDataType) {
6479
6480 case QCBOR_TYPE_DECIMAL_FRACTION:
6481 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade9b334962020-08-27 10:55:53 -07006482 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade37286c02022-09-03 10:05:02 -07006483 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
Laurence Lundblade9b334962020-08-27 10:55:53 -07006484 break;
6485
Laurence Lundblade37286c02022-09-03 10:05:02 -07006486#ifndef QCBOR_DISABLE_TAGS
6487 /* If tags are disabled, mantissas can never be big nums */
Laurence Lundblade9b334962020-08-27 10:55:53 -07006488 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
6489 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
6490 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006491 uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
Laurence Lundblade9b334962020-08-27 10:55:53 -07006492 break;
6493
6494 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
6495 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
6496 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006497 uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
Laurence Lundblade9b334962020-08-27 10:55:53 -07006498 break;
Laurence Lundblade37286c02022-09-03 10:05:02 -07006499#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade9b334962020-08-27 10:55:53 -07006500
6501 default:
6502 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
6503 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006504
6505 Done:
6506 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006507}
6508
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006509
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006510/**
6511 * @brief Decode exponent and mantissa into a big number.
6512 *
6513 * @param[in] pMe The decode context.
6514 * @param[in] TagSpec The expected/allowed tags.
6515 * @param[in] pItem Item to decode and convert.
6516 * @param[in] BufferForMantissa Buffer to output mantissa into.
6517 * @param[out] pMantissa The output mantissa.
6518 * @param[out] pbIsNegative The sign of the output.
6519 * @param[out] pnExponent The mantissa of the output.
6520 *
6521 * This is the common processing of a decimal fraction or a big float
6522 * into a big number. This will decode and consume all the CBOR items
6523 * that make up the decimal fraction or big float.
6524 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006525static void
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006526QCBORDecode_Private_ProcessExpMantissaBig(QCBORDecodeContext *pMe,
6527 const QCBOR_Private_TagSpec TagSpec,
6528 QCBORItem *pItem,
6529 const UsefulBuf BufferForMantissa,
6530 UsefulBufC *pMantissa,
6531 bool *pbIsNegative,
6532 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006533{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006534 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006535
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006536 uErr = QCBOR_Private_ExpMantissaTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006537 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006538 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006539 }
6540
6541 uint64_t uMantissa;
6542
6543 switch (pItem->uDataType) {
6544
6545 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006546 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07006547 /* See comments in ExponentiateNN() on handling INT64_MIN */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006548 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
6549 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
6550 *pbIsNegative = false;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07006551 } else if(pItem->val.expAndMantissa.Mantissa.nInt != INT64_MIN) {
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006552 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
6553 *pbIsNegative = true;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07006554 } else {
6555 uMantissa = (uint64_t)INT64_MAX+1;
6556 *pbIsNegative = true;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006557 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006558 *pMantissa = QCBOR_Private_ConvertIntToBigNum(uMantissa,
6559 BufferForMantissa);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006560 *pnExponent = pItem->val.expAndMantissa.nExponent;
6561 break;
6562
Laurence Lundblade37286c02022-09-03 10:05:02 -07006563#ifndef QCBOR_DISABLE_TAGS
6564 /* If tags are disabled, mantissas can never be big nums */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006565 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006566 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006567 *pnExponent = pItem->val.expAndMantissa.nExponent;
6568 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
6569 *pbIsNegative = false;
6570 break;
6571
6572 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006573 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006574 *pnExponent = pItem->val.expAndMantissa.nExponent;
6575 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
6576 *pbIsNegative = true;
6577 break;
Laurence Lundblade37286c02022-09-03 10:05:02 -07006578#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006579
6580 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006581 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006582 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006583
6584Done:
6585 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006586}
6587
6588
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006589/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006590 * Public function, see header qcbor/qcbor_decode.h file
6591 */
6592void
6593QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
6594 const uint8_t uTagRequirement,
6595 int64_t *pnMantissa,
6596 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006597{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006598 if(pMe->uLastError != QCBOR_SUCCESS) {
6599 return;
6600 }
6601
6602 QCBORItem Item;
6603 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6604 if(uError) {
6605 pMe->uLastError = (uint8_t)uError;
6606 return;
6607 }
6608
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006609 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006610 {
6611 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006612 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6613 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6614 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006615 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006616
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006617 QCBOR_Private_ProcessExpMantissa(pMe,
6618 TagSpec,
6619 &Item,
6620 pnMantissa,
6621 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006622}
6623
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006624
6625/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006626 * Public function, see header qcbor/qcbor_decode.h file
6627 */
6628void
6629QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
6630 const int64_t nLabel,
6631 const uint8_t uTagRequirement,
6632 int64_t *pnMantissa,
6633 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006634{
6635 if(pMe->uLastError != QCBOR_SUCCESS) {
6636 return;
6637 }
6638
6639 QCBORItem Item;
6640 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
6641
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006642 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006643 {
6644 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006645 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6646 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6647 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006648 };
6649
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006650 QCBOR_Private_ProcessExpMantissa(pMe,
6651 TagSpec,
6652 &Item,
6653 pnMantissa,
6654 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006655}
6656
6657
6658/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006659 * Public function, see header qcbor/qcbor_decode.h file
6660 */
6661void
6662QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
6663 const char *szLabel,
6664 const uint8_t uTagRequirement,
6665 int64_t *pnMantissa,
6666 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006667{
6668 if(pMe->uLastError != QCBOR_SUCCESS) {
6669 return;
6670 }
6671
6672 QCBORItem Item;
6673 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6674
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006675 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006676 {
6677 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006678 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6679 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6680 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006681 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07006682
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006683 QCBOR_Private_ProcessExpMantissa(pMe,
6684 TagSpec,
6685 &Item,
6686 pnMantissa,
6687 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006688}
6689
6690
6691/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006692 * Public function, see header qcbor/qcbor_decode.h file
6693 */
6694void
6695QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
6696 const uint8_t uTagRequirement,
6697 const UsefulBuf MantissaBuffer,
6698 UsefulBufC *pMantissa,
6699 bool *pbMantissaIsNegative,
6700 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006701{
6702 if(pMe->uLastError != QCBOR_SUCCESS) {
6703 return;
6704 }
6705
6706 QCBORItem Item;
6707 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6708 if(uError) {
6709 pMe->uLastError = (uint8_t)uError;
6710 return;
6711 }
6712
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006713 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006714 {
6715 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006716 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6717 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6718 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006719 };
6720
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006721 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
6722 TagSpec,
6723 &Item,
6724 MantissaBuffer,
6725 pMantissa,
6726 pbMantissaIsNegative,
6727 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006728}
6729
6730
6731/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006732 * Public function, see header qcbor/qcbor_decode.h file
6733 */
6734void
6735QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
6736 const int64_t nLabel,
6737 const uint8_t uTagRequirement,
6738 const UsefulBuf BufferForMantissa,
6739 UsefulBufC *pMantissa,
6740 bool *pbIsNegative,
6741 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006742{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006743 if(pMe->uLastError != QCBOR_SUCCESS) {
6744 return;
6745 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006746
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006747 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006748 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006749 if(pMe->uLastError != QCBOR_SUCCESS) {
6750 return;
6751 }
6752
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006753 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006754 {
6755 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006756 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6757 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6758 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006759 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006760
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006761 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
6762 TagSpec,
6763 &Item,
6764 BufferForMantissa,
6765 pMantissa,
6766 pbIsNegative,
6767 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006768}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006769
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006770
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006771/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006772 * Public function, see header qcbor/qcbor_decode.h file
6773 */
6774void
6775QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
6776 const char *szLabel,
6777 const uint8_t uTagRequirement,
6778 const UsefulBuf BufferForMantissa,
6779 UsefulBufC *pMantissa,
6780 bool *pbIsNegative,
6781 int64_t *pnExponent)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006782{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006783 if(pMe->uLastError != QCBOR_SUCCESS) {
6784 return;
6785 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006786
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006787 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006788 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6789 if(pMe->uLastError != QCBOR_SUCCESS) {
6790 return;
6791 }
6792
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006793 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006794 {
6795 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006796 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6797 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6798 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006799 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006800
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006801 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
6802 TagSpec,
6803 &Item,
6804 BufferForMantissa,
6805 pMantissa,
6806 pbIsNegative,
6807 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006808}
6809
6810
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006811/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006812 * Public function, see header qcbor/qcbor_decode.h file
6813 */
6814void
6815QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
6816 const uint8_t uTagRequirement,
6817 int64_t *pnMantissa,
6818 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006819{
6820 if(pMe->uLastError != QCBOR_SUCCESS) {
6821 return;
6822 }
6823
6824 QCBORItem Item;
6825 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6826 if(uError) {
6827 pMe->uLastError = (uint8_t)uError;
6828 return;
6829 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006830 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006831 {
6832 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006833 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6834 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6835 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006836 };
6837
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006838 QCBOR_Private_ProcessExpMantissa(pMe,
6839 TagSpec,
6840 &Item,
6841 pnMantissa,
6842 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006843}
6844
6845
6846/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006847 * Public function, see header qcbor/qcbor_decode.h file
6848 */
6849void
6850QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
6851 const int64_t nLabel,
6852 const uint8_t uTagRequirement,
6853 int64_t *pnMantissa,
6854 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006855{
6856 if(pMe->uLastError != QCBOR_SUCCESS) {
6857 return;
6858 }
6859
6860 QCBORItem Item;
6861 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
6862 if(pMe->uLastError != QCBOR_SUCCESS) {
6863 return;
6864 }
6865
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006866 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006867 {
6868 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006869 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6870 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6871 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006872 };
6873
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006874 QCBOR_Private_ProcessExpMantissa(pMe,
6875 TagSpec,
6876 &Item,
6877 pnMantissa,
6878 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006879}
6880
6881
6882/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006883 * Public function, see header qcbor/qcbor_decode.h file
6884 */
6885void
6886QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
6887 const char *szLabel,
6888 const uint8_t uTagRequirement,
6889 int64_t *pnMantissa,
6890 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006891{
6892 if(pMe->uLastError != QCBOR_SUCCESS) {
6893 return;
6894 }
6895
6896 QCBORItem Item;
6897 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6898 if(pMe->uLastError != QCBOR_SUCCESS) {
6899 return;
6900 }
6901
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006902 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006903 {
6904 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006905 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6906 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6907 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006908 };
6909
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006910 QCBOR_Private_ProcessExpMantissa(pMe,
6911 TagSpec,
6912 &Item,
6913 pnMantissa,
6914 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006915}
6916
6917
6918/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006919 * Public function, see header qcbor/qcbor_decode.h file
6920 */
6921void
6922QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
6923 const uint8_t uTagRequirement,
6924 const UsefulBuf MantissaBuffer,
6925 UsefulBufC *pMantissa,
6926 bool *pbMantissaIsNegative,
6927 int64_t *pnExponent)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006928{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006929 if(pMe->uLastError != QCBOR_SUCCESS) {
6930 return;
6931 }
6932
6933 QCBORItem Item;
6934 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6935 if(uError) {
6936 pMe->uLastError = (uint8_t)uError;
6937 return;
6938 }
6939
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006940 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006941 {
6942 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006943 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6944 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6945 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006946 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006947
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006948 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
6949 TagSpec,
6950 &Item,
6951 MantissaBuffer,
6952 pMantissa,
6953 pbMantissaIsNegative,
6954 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006955}
6956
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006957
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006958/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006959 * Public function, see header qcbor/qcbor_decode.h file
6960 */
6961void
6962QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
6963 const int64_t nLabel,
6964 const uint8_t uTagRequirement,
6965 const UsefulBuf BufferForMantissa,
6966 UsefulBufC *pMantissa,
6967 bool *pbIsNegative,
6968 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006969{
6970 if(pMe->uLastError != QCBOR_SUCCESS) {
6971 return;
6972 }
6973
6974 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006975 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
6976 if(pMe->uLastError != QCBOR_SUCCESS) {
6977 return;
6978 }
6979
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006980 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006981 {
6982 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006983 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6984 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6985 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006986 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006987
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006988 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
6989 TagSpec,
6990 &Item,
6991 BufferForMantissa,
6992 pMantissa,
6993 pbIsNegative,
6994 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006995}
6996
6997
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006998/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006999 * Public function, see header qcbor/qcbor_decode.h file
7000 */
7001void
7002QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
7003 const char *szLabel,
7004 const uint8_t uTagRequirement,
7005 const UsefulBuf BufferForMantissa,
7006 UsefulBufC *pMantissa,
7007 bool *pbIsNegative,
7008 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007009{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007010 if(pMe->uLastError != QCBOR_SUCCESS) {
7011 return;
7012 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007013
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007014 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007015 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
7016 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07007017 return;
7018 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07007019
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007020 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007021 {
7022 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07007023 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
7024 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
7025 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007026 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007027
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07007028 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
7029 TagSpec,
7030 &Item,
7031 BufferForMantissa,
7032 pMantissa,
7033 pbIsNegative,
7034 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07007035}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007036
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07007037#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */