blob: 799fff25b90a41e654c279e28fc4c6e5ae563d5a [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 *
Laurence Lundblade0f01ac62024-02-18 23:07:07 -0700706 * 1. QCBORDecode_Private_GetNextTagContent - The top layer processes
707 * tagged data items, turning them into the local C representation.
708 * For the most simple it is just associating a QCBOR_TYPE with the
709 * data. For the complex ones that an aggregate of data items, there
710 * is some further decoding and some limited recursion.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800711 *
Laurence Lundblade0f01ac62024-02-18 23:07:07 -0700712 * 2. QCBORDecode_Private_GetNextMapOrArray - This manages the
713 * beginnings and ends of maps and arrays. It tracks descending into
714 * and ascending out of maps/arrays. It processes breaks that
715 * terminate indefinite-length maps and arrays.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800716 *
Laurence Lundblade0f01ac62024-02-18 23:07:07 -0700717 * 3. QCBORDecode_Private_GetNextMapEntry - This handles the combining
718 * of two items, the label and the data, that make up a map entry. It
719 * only does work on maps. It combines the label and data items into
720 * one labeled item.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800721 *
Laurence Lundblade0f01ac62024-02-18 23:07:07 -0700722 * 4. QCBORDecode_Private_GetNextTagNumber - This decodes type 6 tag
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800723 * 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 *
Laurence Lundblade0f01ac62024-02-18 23:07:07 -0700727 * 5. QCBORDecode_Private_GetNextFullString - This assembles the
728 * sub-items that make up an indefinite-length string into one string
729 * item. It uses the string allocator to create contiguous space for
730 * the item. It processes all breaks that are part of
731 * indefinite-length strings.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800732 *
Laurence Lundblade0f01ac62024-02-18 23:07:07 -0700733 * 6. QCBOR_Private_DecodeAtomicDataItem - This decodes the atomic
734 * data items in CBOR. Each atomic data item has a "major type", an
735 * integer "argument" and optionally some content. For text and byte
736 * strings, the content is the bytes that make up the string. These
737 * are the smallest data items that are considered to be well-formed.
738 * The content may also be other data items in the case of aggregate
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800739 * types. They are not handled in this layer.
740 *
Laurence Lundblade0f01ac62024-02-18 23:07:07 -0700741 * This uses about 350 bytes of stack. This number comes from
742 * instrumenting (printf address of stack variables) the code on x86
743 * compiled for size optimization.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700744 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800745
746
747/*
748 * Note about use of int and unsigned variables.
749 *
750 * See http://www.unix.org/whitepapers/64bit.html for reasons int is
751 * used carefully here, and in particular why it isn't used in the
752 * public interface. Also see
753 * https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
754 *
755 * Int is used for values that need less than 16-bits and would be
756 * subject to integer promotion and result in complaining from static
757 * analyzers.
758 */
759
760
761/**
762 * @brief Decode the CBOR head, the type and argument.
763 *
764 * @param[in] pUInBuf The input buffer to read from.
765 * @param[out] pnMajorType The decoded major type.
766 * @param[out] puArgument The decoded argument.
767 * @param[out] pnAdditionalInfo The decoded Lower 5 bits of initial byte.
768 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -0700769 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved features
770 * @retval QCBOR_ERR_HIT_END Unexpected end of input
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800771 *
772 * This decodes the CBOR "head" that every CBOR data item has. See
773 * longer explaination of the head in documentation for
774 * QCBOREncode_EncodeHead().
775 *
776 * This does the network->host byte order conversion. The conversion
777 * here also results in the conversion for floats in addition to that
778 * for lengths, tags and integer values.
779 *
780 * The int type is preferred to uint8_t for some variables as this
781 * avoids integer promotions, can reduce code size and makes static
782 * analyzers happier.
783 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700784static QCBORError
785QCBOR_Private_DecodeHead(UsefulInputBuf *pUInBuf,
786 int *pnMajorType,
787 uint64_t *puArgument,
788 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700789{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800790 QCBORError uReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800791
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800792 /* Get the initial byte that every CBOR data item has and break it
793 * down. */
794 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800795 const int nTmpMajorType = nInitialByte >> 5;
796 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800797
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800798 /* Where the argument accumulates */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800799 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800800
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800801 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800802 /* Need to get 1,2,4 or 8 additional argument bytes. Map
803 * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
804 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800805 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800806
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800807 /* Loop getting all the bytes in the argument */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800808 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800809 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800810 /* This shift and add gives the endian conversion. */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800811 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
812 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800813 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800814 /* The reserved and thus-far unused additional info values */
815 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800816 goto Done;
817 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800818 /* Less than 24, additional info is argument or 31, an
819 * indefinite-length. No more bytes to get.
820 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800821 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700822 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800823
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700824 if(UsefulInputBuf_GetError(pUInBuf)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800825 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700826 goto Done;
827 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800828
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800829 /* All successful if arrived here. */
830 uReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800831 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800832 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800833 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800834
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700835Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800836 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700837}
838
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800839
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800840/**
841 * @brief Decode integer types, major types 0 and 1.
842 *
843 * @param[in] nMajorType The CBOR major type (0 or 1).
844 * @param[in] uArgument The argument from the head.
845 * @param[out] pDecodedItem The filled in decoded item.
846 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -0700847 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800848 *
849 * Must only be called when major type is 0 or 1.
850 *
851 * CBOR doesn't explicitly specify two's compliment for integers but
852 * all CPUs use it these days and the test vectors in the RFC are
853 * so. All integers in the CBOR structure are positive and the major
854 * type indicates positive or negative. CBOR can express positive
855 * integers up to 2^x - 1 where x is the number of bits and negative
856 * integers down to 2^x. Note that negative numbers can be one more
857 * away from zero than positive. Stdint, as far as I can tell, uses
858 * two's compliment to represent negative integers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700859 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700860static QCBORError
861QCBOR_Private_DecodeInteger(const int nMajorType,
862 const uint64_t uArgument,
863 QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700864{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800865 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800866
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700867 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800868 if (uArgument <= INT64_MAX) {
869 pDecodedItem->val.int64 = (int64_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700870 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800871
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700872 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800873 pDecodedItem->val.uint64 = uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700874 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700875 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800876
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700877 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800878 if(uArgument <= INT64_MAX) {
879 /* CBOR's representation of negative numbers lines up with
880 * the two-compliment representation. A negative integer has
881 * one more in range than a positive integer. INT64_MIN is
882 * equal to (-INT64_MAX) - 1.
883 */
884 pDecodedItem->val.int64 = (-(int64_t)uArgument) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700885 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800886
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700887 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800888 /* C can't represent a negative integer in this range so it
889 * is an error.
890 */
891 uReturn = QCBOR_ERR_INT_OVERFLOW;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700892 }
893 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800894
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800895 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700896}
897
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800898
899/* Make sure #define value line up as DecodeSimple counts on this. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700900#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
901#error QCBOR_TYPE_FALSE macro value wrong
902#endif
903
904#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
905#error QCBOR_TYPE_TRUE macro value wrong
906#endif
907
908#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
909#error QCBOR_TYPE_NULL macro value wrong
910#endif
911
912#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
913#error QCBOR_TYPE_UNDEF macro value wrong
914#endif
915
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700916#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
917#error QCBOR_TYPE_BREAK macro value wrong
918#endif
919
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700920#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
921#error QCBOR_TYPE_DOUBLE macro value wrong
922#endif
923
924#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
925#error QCBOR_TYPE_FLOAT macro value wrong
926#endif
927
Laurence Lundblade9b334962020-08-27 10:55:53 -0700928
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800929/**
930 * @brief Decode major type 7 -- true, false, floating-point, break...
931 *
932 * @param[in] nAdditionalInfo The lower five bits from the initial byte.
933 * @param[in] uArgument The argument from the head.
934 * @param[out] pDecodedItem The filled in decoded item.
935 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -0700936 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
937 * of half-precision disabled
938 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all float
939 * decode is disabled.
940 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of simple
941 * type in input.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700942 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700943static QCBORError
944QCBOR_Private_DecodeType7(const int nAdditionalInfo,
945 const uint64_t uArgument,
946 QCBORItem *pDecodedItem)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800947{
948 QCBORError uReturn = QCBOR_SUCCESS;
949
950 /* uAdditionalInfo is 5 bits from the initial byte. Compile time
951 * checks above make sure uAdditionalInfo values line up with
952 * uDataType values. DecodeHead() never returns an AdditionalInfo
953 * > 0x1f so cast is safe.
954 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800955 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800956
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800957 switch(nAdditionalInfo) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800958 /* No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they
959 * are caught before this is called.
960 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800961
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800962 case HALF_PREC_FLOAT: /* 25 */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700963#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800964 /* Half-precision is returned as a double. The cast to
965 * uint16_t is safe because the encoded value was 16 bits. It
966 * was widened to 64 bits to be passed in here.
967 */
968 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700969 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800970#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200971 uReturn = FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700972 break;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800973 case SINGLE_PREC_FLOAT: /* 26 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200974#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800975 /* Single precision is normally returned as a double since
976 * double is widely supported, there is no loss of precision,
977 * it makes it easy for the caller in most cases and it can
978 * be converted back to single with no loss of precision
979 *
980 * The cast to uint32_t is safe because the encoded value was
981 * 32 bits. It was widened to 64 bits to be passed in here.
982 */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700983 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800984 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uArgument);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700985#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800986 /* In the normal case, use HW to convert float to
987 * double. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700988 pDecodedItem->val.dfnum = (double)f;
989 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800990#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800991 /* Use of float HW is disabled, return as a float. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700992 pDecodedItem->val.fnum = f;
993 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
994
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800995 /* IEEE754_FloatToDouble() could be used here to return as
996 * a double, but it adds object code and most likely
997 * anyone disabling FLOAT HW use doesn't care about floats
998 * and wants to save object code.
999 */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001000#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001001 }
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001002#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1003 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -07001004 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001005
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001006 case DOUBLE_PREC_FLOAT: /* 27 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001007#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001008 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +07001009 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001010#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1011 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -07001012 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001013
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001014 case CBOR_SIMPLEV_FALSE: /* 20 */
1015 case CBOR_SIMPLEV_TRUE: /* 21 */
1016 case CBOR_SIMPLEV_NULL: /* 22 */
1017 case CBOR_SIMPLEV_UNDEF: /* 23 */
1018 case CBOR_SIMPLE_BREAK: /* 31 */
1019 break; /* nothing to do */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001020
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001021 case CBOR_SIMPLEV_ONEBYTE: /* 24 */
1022 if(uArgument <= CBOR_SIMPLE_BREAK) {
1023 /* This takes out f8 00 ... f8 1f which should be encoded
1024 * as e0 … f7
1025 */
1026 uReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001027 goto Done;
1028 }
Laurence Lundblade5e390822019-01-06 12:35:01 -08001029 /* FALLTHROUGH */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001030
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001031 default: /* 0-19 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001032 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001033 /* DecodeHead() will make uArgument equal to
1034 * nAdditionalInfo when nAdditionalInfo is < 24. This cast is
1035 * safe because the 2, 4 and 8 byte lengths of uNumber are in
1036 * the double/float cases above
Laurence Lundbladeee851742020-01-08 08:37:05 -08001037 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001038 pDecodedItem->val.uSimple = (uint8_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001039 break;
1040 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001041
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001042Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001043 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001044}
1045
1046
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001047/**
1048 * @brief Decode text and byte strings
1049 *
1050 * @param[in] pAllocator The string allocator or NULL.
1051 * @param[in] uStrLen The length of the string.
1052 * @param[in] pUInBuf The surce from which to read the string's bytes.
1053 * @param[out] pDecodedItem The filled in decoded item.
1054 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001055 * @retval QCBOR_ERR_HIT_END Unexpected end of input.
1056 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1057 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001058 *
1059 * The reads @c uStrlen bytes from @c pUInBuf and fills in @c
1060 * pDecodedItem. If @c pAllocator is not NULL then memory for the
1061 * string is allocated.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001062 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001063static QCBORError
1064QCBOR_Private_DecodeBytes(const QCBORInternalAllocator *pAllocator,
1065 const uint64_t uStrLen,
1066 UsefulInputBuf *pUInBuf,
1067 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001068{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001069 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001070
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001071 /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
1072 * CPUs. This check makes the casts to size_t below safe.
1073 *
1074 * The max is 4 bytes less than the largest sizeof() so this can be
1075 * tested by putting a SIZE_MAX length in the CBOR test input (no
1076 * one will care the limit on strings is 4 bytes shorter).
1077 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001078 if(uStrLen > SIZE_MAX-4) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001079 uReturn = QCBOR_ERR_STRING_TOO_LONG;
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001080 goto Done;
1081 }
1082
1083 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301084 if(UsefulBuf_IsNULLC(Bytes)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001085 /* Failed to get the bytes for this string item */
1086 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301087 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001088 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301089
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001090#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001091 /* Note that this is not where allocation to coalesce
1092 * indefinite-length strings is done. This is for when the caller
1093 * has requested all strings be allocated. Disabling indefinite
1094 * length strings also disables this allocate-all option.
1095 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001096 if(pAllocator) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001097 /* request to use the string allocator to make a copy */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001098 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301099 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001100 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301101 goto Done;
1102 }
1103 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001104 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001105 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301106 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001107#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1108 (void)pAllocator;
1109#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1110
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001111 /* Normal case with no string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001112 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001113
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301114Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001115 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001116}
1117
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001118
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001119/**
1120 * @brief Map the CBOR major types for strings to the QCBOR types.
1121 *
1122 * @param[in] nCBORMajorType The CBOR major type to convert.
1123 * @retturns QCBOR type number.
1124 *
1125 * This only works for the two string types.
1126 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001127static uint8_t
1128QCBOR_Private_ConvertStringMajorTypes(int nCBORMajorType)
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001129{
1130 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
1131 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
1132 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001133
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001134 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
1135 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
1136 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001137
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001138 return (uint8_t)(nCBORMajorType + 4);
1139}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001140
1141
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001142/**
1143 * @brief Map the CBOR major types for arrays/maps to the QCBOR types.
1144 *
1145 * @param[in] nCBORMajorType The CBOR major type to convert.
1146 * @retturns QCBOR type number.
1147 *
1148 * This only works for the two aggregate types.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001149 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001150static uint8_t
1151QCBORDecode_Private_ConvertArrayOrMapType(int nCBORMajorType)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001152{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001153 #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
1154 #error QCBOR_TYPE_ARRAY value not lined up with major type
1155 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001156
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001157 #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
1158 #error QCBOR_TYPE_MAP value not lined up with major type
1159 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001160
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001161 return (uint8_t)(nCBORMajorType);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001162}
1163
1164
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001165/**
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001166 * @brief Decode a single primitive data item (decode layer 6).
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001167 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001168 * @param[in] pUInBuf Input buffer to read data item from.
1169 * @param[out] pDecodedItem The filled-in decoded item.
1170 * @param[in] pAllocator The allocator to use for strings or NULL.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001171 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001172 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1173 * features
1174 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1175 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1176 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1177 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
1178 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1179 * of half-precision disabled
1180 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1181 * float decode is disabled.
1182 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1183 * simple type in input.
1184 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1185 * in input, but indefinite
1186 * lengths disabled.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001187 *
1188 * This decodes the most primitive / atomic data item. It does
1189 * no combing of data items.
1190 */
1191static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001192QCBOR_Private_DecodeAtomicDataItem(UsefulInputBuf *pUInBuf,
1193 QCBORItem *pDecodedItem,
1194 const QCBORInternalAllocator *pAllocator)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001195{
1196 QCBORError uReturn;
1197
1198 /* Get the major type and the argument. The argument could be
1199 * length of more bytes or the value depending on the major
1200 * type. nAdditionalInfo is an encoding of the length of the
1201 * uNumber and is needed to decode floats and doubles.
1202 */
1203 int nMajorType = 0;
1204 uint64_t uArgument = 0;
1205 int nAdditionalInfo = 0;
1206
1207 memset(pDecodedItem, 0, sizeof(QCBORItem));
1208
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001209 uReturn = QCBOR_Private_DecodeHead(pUInBuf, &nMajorType, &uArgument, &nAdditionalInfo);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001210 if(uReturn) {
1211 goto Done;
1212 }
1213
1214 /* At this point the major type and the argument are valid. We've
1215 * got the type and the argument that starts every CBOR data item.
1216 */
1217 switch (nMajorType) {
1218 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1219 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
1220 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1221 uReturn = QCBOR_ERR_BAD_INT;
1222 } else {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001223 uReturn = QCBOR_Private_DecodeInteger(nMajorType, uArgument, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001224 }
1225 break;
1226
1227 case CBOR_MAJOR_TYPE_BYTE_STRING: /* Major type 2 */
1228 case CBOR_MAJOR_TYPE_TEXT_STRING: /* Major type 3 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001229 pDecodedItem->uDataType = QCBOR_Private_ConvertStringMajorTypes(nMajorType);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001230 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1231 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
1232 } else {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001233 uReturn = QCBOR_Private_DecodeBytes(pAllocator, uArgument, pUInBuf, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001234 }
1235 break;
1236
1237 case CBOR_MAJOR_TYPE_ARRAY: /* Major type 4 */
1238 case CBOR_MAJOR_TYPE_MAP: /* Major type 5 */
1239 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1240 /* Indefinite-length string. */
1241#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
1242 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
1243#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1244 uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
1245 break;
1246#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1247 } else {
1248 /* Definite-length string. */
1249 if(uArgument > QCBOR_MAX_ITEMS_IN_ARRAY) {
1250 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
1251 goto Done;
1252 }
1253 /* cast OK because of check above */
1254 pDecodedItem->val.uCount = (uint16_t)uArgument;
1255 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001256 pDecodedItem->uDataType = QCBORDecode_Private_ConvertArrayOrMapType(nMajorType);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001257 break;
1258
1259 case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */
Laurence Lundblade37286c02022-09-03 10:05:02 -07001260#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001261 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1262 uReturn = QCBOR_ERR_BAD_INT;
1263 } else {
1264 pDecodedItem->val.uTagV = uArgument;
1265 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
1266 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07001267#else /* QCBOR_DISABLE_TAGS */
1268 uReturn = QCBOR_ERR_TAGS_DISABLED;
1269#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001270 break;
1271
1272 case CBOR_MAJOR_TYPE_SIMPLE:
1273 /* Major type 7: float, double, true, false, null... */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001274 uReturn = QCBOR_Private_DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001275 break;
1276
1277 default:
1278 /* Never happens because DecodeHead() should never return > 7 */
1279 uReturn = QCBOR_ERR_UNSUPPORTED;
1280 break;
1281 }
1282
1283Done:
1284 return uReturn;
1285}
1286
1287
1288/**
1289 * @brief Process indefinite-length strings (decode layer 5).
1290 *
1291 * @param[in] pMe Decoder context
1292 * @param[out] pDecodedItem The decoded item that work is done on.
1293 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001294 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1295 * features
1296 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1297 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1298 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1299 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
1300 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1301 * of half-precision disabled
1302 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1303 * float decode is disabled.
1304 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1305 * simple type in input.
1306 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1307 * in input, but indefinite
1308 * lengths disabled.
1309 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Indefinite-length string in input,
1310 * but no string allocator.
1311 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK Error in indefinite-length string.
1312 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED Indefinite-length string in
1313 * input, but indefinite-length
1314 * strings are disabled.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001315 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001316 * If @c pDecodedItem is not an indefinite-length string, this does nothing.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001317 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001318 * If it is, this loops getting the subsequent chunk data items that
1319 * make up the string. The string allocator is used to make a
1320 * contiguous buffer for the chunks. When this completes @c
1321 * pDecodedItem contains the put-together string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001322 *
1323 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001324 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001325static QCBORError
1326QCBORDecode_Private_GetNextFullString(QCBORDecodeContext *pMe,
1327 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001328{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001329 /* Aproximate stack usage
1330 * 64-bit 32-bit
1331 * local vars 32 16
1332 * 2 UsefulBufs 32 16
1333 * QCBORItem 56 52
1334 * TOTAL 120 74
1335 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001336
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001337 /* The string allocator is used here for two purposes: 1)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001338 * coalescing the chunks of an indefinite-length string, 2)
1339 * allocating storage for every string returned when requested.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001340 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001341 * The first use is below in this function. Indefinite-length
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001342 * strings cannot be processed at all without a string allocator.
1343 *
1344 * The second used is in DecodeBytes() which is called by
1345 * GetNext_Item() below. This second use unneccessary for most use
1346 * and only happens when requested in the call to
1347 * QCBORDecode_SetMemPool(). If the second use not requested then
1348 * NULL is passed for the string allocator to GetNext_Item().
1349 *
1350 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1351 * allocator altogether and thus both of these uses. It reduced the
1352 * decoder object code by about 400 bytes.
1353 */
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001354 const QCBORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001355
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001356#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001357 const QCBORInternalAllocator *pAllocator = NULL;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001358
1359 if(pMe->StringAllocator.pfAllocator) {
1360 pAllocator = &(pMe->StringAllocator);
1361 if(pMe->bStringAllocateAll) {
1362 pAllocatorForGetNext = pAllocator;
1363 }
1364 }
1365#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1366
1367 QCBORError uReturn;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001368 uReturn = QCBOR_Private_DecodeAtomicDataItem(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001369 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001370 goto Done;
1371 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001372
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001373 /* Only do indefinite-length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001374 const uint8_t uStringType = pDecodedItem->uDataType;
1375 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001376 goto Done;
1377 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001378
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001379 /* Is this a string with an indefinite length? */
1380 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1381 goto Done;
1382 }
1383
1384#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001385 /* Can't decode indefinite-length strings without a string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001386 if(pAllocator == NULL) {
1387 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1388 goto Done;
1389 }
1390
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001391 /* Loop getting chunks of the indefinite-length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001392 UsefulBufC FullString = NULLUsefulBufC;
1393
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001394 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001395 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001396 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001397 /* Pass a NULL string allocator to GetNext_Item() because the
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001398 * individual string chunks in an indefinite-length should not
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001399 * be allocated. They are always copied in the the contiguous
1400 * buffer allocated here.
1401 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001402 uReturn = QCBOR_Private_DecodeAtomicDataItem(&(pMe->InBuf), &StringChunkItem, NULL);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001403 if(uReturn) {
1404 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001405 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001406
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001407 /* Is item is the marker for end of the indefinite-length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001408 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001409 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001410 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301411 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001412 break;
1413 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001414
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001415 /* All chunks must be of the same type, the type of the item
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001416 * that introduces the indefinite-length string. This also
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001417 * catches errors where the chunk is not a string at all and an
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001418 * indefinite-length string inside an indefinite-length string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001419 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001420 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001421 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1422 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001423 break;
1424 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001425
David Navarro9123e5b2022-03-28 16:04:03 +02001426 if (StringChunkItem.val.string.len > 0) {
1427 /* The first time throurgh FullString.ptr is NULL and this is
1428 * equivalent to StringAllocator_Allocate(). Subsequently it is
1429 * not NULL and a reallocation happens.
1430 */
1431 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1432 FullString.ptr,
1433 FullString.len + StringChunkItem.val.string.len);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001434
David Navarro9123e5b2022-03-28 16:04:03 +02001435 if(UsefulBuf_IsNULL(NewMem)) {
1436 uReturn = QCBOR_ERR_STRING_ALLOCATE;
1437 break;
1438 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001439
David Navarro9123e5b2022-03-28 16:04:03 +02001440 /* Copy new string chunk to the end of accumulated string */
1441 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001442 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001443 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001444
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001445 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1446 /* Getting the item failed, clean up the allocated memory */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001447 StringAllocator_Free(pAllocator, FullString.ptr);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001448 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001449#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1450 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1451#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001452
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001453Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001454 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001455}
1456
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001457
Laurence Lundblade37286c02022-09-03 10:05:02 -07001458#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001459/**
1460 * @brief This converts a tag number to a shorter mapped value for storage.
1461 *
1462 * @param[in] pMe The decode context.
1463 * @param[in] uUnMappedTag The tag number to map
1464 * @param[out] puMappedTagNumer The stored tag number.
1465 *
1466 * @return error code.
1467 *
1468 * The main point of mapping tag numbers is make QCBORItem
1469 * smaller. With this mapping storage of 4 tags takes up 8
1470 * bytes. Without, it would take up 32 bytes.
1471 *
1472 * This maps tag numbers greater than QCBOR_LAST_UNMAPPED_TAG.
1473 * QCBOR_LAST_UNMAPPED_TAG is a little smaller than MAX_UINT16.
1474 *
1475 * See also UnMapTagNumber() and @ref QCBORItem.
1476 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001477static QCBORError
1478QCBORDecode_Private_MapTagNumber(QCBORDecodeContext *pMe,
1479 const uint64_t uUnMappedTag,
1480 uint16_t *puMappedTagNumer)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001481{
1482 if(uUnMappedTag > QCBOR_LAST_UNMAPPED_TAG) {
1483 unsigned uTagMapIndex;
1484 /* Is there room in the tag map, or is it in it already? */
1485 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
1486 if(pMe->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID64) {
1487 break;
1488 }
1489 if(pMe->auMappedTags[uTagMapIndex] == uUnMappedTag) {
1490 break;
1491 }
1492 }
1493 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1494 return QCBOR_ERR_TOO_MANY_TAGS;
1495 }
1496
1497 /* Covers the cases where tag is new and were it is already in the map */
1498 pMe->auMappedTags[uTagMapIndex] = uUnMappedTag;
1499 *puMappedTagNumer = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
1500
1501 } else {
1502 *puMappedTagNumer = (uint16_t)uUnMappedTag;
1503 }
1504
1505 return QCBOR_SUCCESS;
1506}
1507
1508
1509/**
1510 * @brief This converts a mapped tag number to the actual tag number.
1511 *
1512 * @param[in] pMe The decode context.
1513 * @param[in] uMappedTagNumber The stored tag number.
1514 *
1515 * @return The actual tag number is returned or
1516 * @ref CBOR_TAG_INVALID64 on error.
1517 *
1518 * This is the reverse of MapTagNumber()
1519 */
1520static uint64_t
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001521QCBORDecode_Private_UnMapTagNumber(const QCBORDecodeContext *pMe,
1522 const uint16_t uMappedTagNumber)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001523{
1524 if(uMappedTagNumber <= QCBOR_LAST_UNMAPPED_TAG) {
1525 return uMappedTagNumber;
1526 } else if(uMappedTagNumber == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001527 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001528 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001529 /* This won't be negative because of code below in
1530 * MapTagNumber()
1531 */
1532 const unsigned uIndex = uMappedTagNumber - (QCBOR_LAST_UNMAPPED_TAG + 1);
1533 return pMe->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001534 }
1535}
Laurence Lundblade37286c02022-09-03 10:05:02 -07001536#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001537
Laurence Lundblade9b334962020-08-27 10:55:53 -07001538
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001539/**
1540 * @brief Aggregate all tags wrapping a data item (decode layer 4).
1541 *
1542 * @param[in] pMe Decoder context
1543 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001544 *
1545 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1546 * features
1547 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1548 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1549 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1550 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
1551 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1552 * of half-precision disabled
1553 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1554 * float decode is disabled.
1555 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1556 * simple type in input.
1557 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1558 * in input, but indefinite
1559 * lengths disabled.
1560 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Indefinite-length string in input,
1561 * but no string allocator.
1562 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK Error in indefinite-length string.
1563 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED Indefinite-length string in
1564 * input, but indefinite-length
1565 * strings are disabled.
1566 * @retval QCBOR_ERR_TOO_MANY_TAGS Too many tag numbers on item.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001567 *
1568 * This loops getting atomic data items until one is not a tag
1569 * number. Usually this is largely pass-through because most
1570 * item are not tag numbers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001571 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001572static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001573QCBORDecode_Private_GetNextTagNumber(QCBORDecodeContext *pMe,
1574 QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001575{
Laurence Lundblade37286c02022-09-03 10:05:02 -07001576#ifndef QCBOR_DISABLE_TAGS
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001577 /* Accummulate the tags from multiple items here and then copy them
1578 * into the last item, the non-tag item.
1579 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001580 uint16_t auItemsTags[QCBOR_MAX_TAGS_PER_ITEM];
1581
1582 /* Initialize to CBOR_TAG_INVALID16 */
1583 #if CBOR_TAG_INVALID16 != 0xffff
1584 /* Be sure the memset does the right thing. */
1585 #err CBOR_TAG_INVALID16 tag not defined as expected
1586 #endif
1587 memset(auItemsTags, 0xff, sizeof(auItemsTags));
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001588
Laurence Lundblade9b334962020-08-27 10:55:53 -07001589 QCBORError uReturn = QCBOR_SUCCESS;
1590
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001591 /* Loop fetching data items until the item fetched is not a tag */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001592 for(;;) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001593 QCBORError uErr = QCBORDecode_Private_GetNextFullString(pMe, pDecodedItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07001594 if(uErr != QCBOR_SUCCESS) {
1595 uReturn = uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001596 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001597 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001598
Laurence Lundblade9b334962020-08-27 10:55:53 -07001599 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001600 /* Successful exit from loop; maybe got some tags, maybe not */
1601 memcpy(pDecodedItem->uTags, auItemsTags, sizeof(auItemsTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001602 break;
1603 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001604
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001605 if(auItemsTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1606 /* No room in the tag list */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001607 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001608 /* Continue on to get all tags wrapping this item even though
1609 * it is erroring out in the end. This allows decoding to
1610 * continue. This is a resource limit error, not a problem
1611 * with being well-formed CBOR.
1612 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001613 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001614 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001615 /* Slide tags over one in the array to make room at index 0.
1616 * Must use memmove because the move source and destination
1617 * overlap.
1618 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001619 memmove(&auItemsTags[1],
1620 auItemsTags,
1621 sizeof(auItemsTags) - sizeof(auItemsTags[0]));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001622
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001623 /* Map the tag */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001624 uint16_t uMappedTagNumber = 0;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001625 uReturn = QCBORDecode_Private_MapTagNumber(pMe, pDecodedItem->val.uTagV, &uMappedTagNumber);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001626 /* Continue even on error so as to consume all tags wrapping
1627 * this data item so decoding can go on. If MapTagNumber()
1628 * errors once it will continue to error.
1629 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001630 auItemsTags[0] = uMappedTagNumber;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001631 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001632
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001633Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001634 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001635
Laurence Lundblade37286c02022-09-03 10:05:02 -07001636#else /* QCBOR_DISABLE_TAGS */
1637
Laurence Lundblade0f01ac62024-02-18 23:07:07 -07001638 return QCBORDecode_Private_GetNextFullString(pMe, pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07001639
1640#endif /* QCBOR_DISABLE_TAGS */
1641}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001642
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001643
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001644/**
1645 * @brief Combine a map entry label and value into one item (decode layer 3).
1646 *
1647 * @param[in] pMe Decoder context
1648 * @param[out] pDecodedItem The decoded item that work is done on.
1649 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001650 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1651 * features
1652 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1653 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1654 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1655 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
1656 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1657 * of half-precision disabled
1658 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1659 * float decode is disabled.
1660 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1661 * simple type in input.
1662 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1663 * in input, but indefinite
1664 * lengths disabled.
1665 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Indefinite-length string in input,
1666 * but no string allocator.
1667 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK Error in indefinite-length string.
1668 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED Indefinite-length string in
1669 * input, but indefinite-length
1670 * strings are disabled.
1671 * @retval QCBOR_ERR_TOO_MANY_TAGS Too many tag numbers on item.
1672 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG Too many items in array.
1673 * @retval QCBOR_ERR_MAP_LABEL_TYPE Map label not string or integer.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001674 *
1675 * If a the current nesting level is a map, then this
1676 * combines pairs of items into one data item with a label
1677 * and value.
1678 *
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07001679 * This is passthrough if the current nesting level is
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001680 * not a map.
1681 *
1682 * This also implements maps-as-array mode where a map
1683 * is treated like an array to allow caller to do their
1684 * own label processing.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001685 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001686static QCBORError
1687QCBORDecode_Private_GetNextMapEntry(QCBORDecodeContext *pMe,
1688 QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001689{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001690 QCBORError uReturn = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001691 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001692 goto Done;
1693 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001694
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001695 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
1696 /* Break can't be a map entry */
1697 goto Done;
1698 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001699
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001700 if(pMe->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1701 /* Normal decoding of maps -- combine label and value into one item. */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001702
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001703 if(DecodeNesting_IsCurrentTypeMap(&(pMe->nesting))) {
1704 /* Save label in pDecodedItem and get the next which will
1705 * be the real data item.
1706 */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001707 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001708 uReturn = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001709 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001710 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001711 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001712
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301713 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001714
1715 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001716 /* strings are always good labels */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001717 pDecodedItem->label.string = LabelItem.val.string;
1718 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001719 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == pMe->uDecodeMode) {
1720 /* It's not a string and we only want strings */
1721 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001722 goto Done;
1723 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1724 pDecodedItem->label.int64 = LabelItem.val.int64;
1725 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1726 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1727 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1728 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1729 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1730 pDecodedItem->label.string = LabelItem.val.string;
1731 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1732 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1733 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001734 /* label is not an int or a string. It is an arrray
1735 * or a float or such and this implementation doesn't handle that.
1736 * Also, tags on labels are ignored.
1737 */
1738 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001739 goto Done;
1740 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001741 }
1742 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001743 /* Decoding of maps as arrays to let the caller decide what to do
1744 * about labels, particularly lables that are not integers or
1745 * strings.
1746 */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001747 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001748 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001749 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001750 goto Done;
1751 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001752 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001753 /* Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2.
1754 * Cast is needed because of integer promotion.
1755 */
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001756 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001757 }
1758 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001759
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001760Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001761 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001762}
1763
1764
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001765#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001766/**
1767 * @brief Peek and see if next data item is a break;
1768 *
1769 * @param[in] pUIB UsefulInputBuf to read from.
1770 * @param[out] pbNextIsBreak Indicate if next was a break or not.
1771 *
1772 * @return Any decoding error.
1773 *
1774 * See if next item is a CBOR break. If it is, it is consumed,
1775 * if not it is not consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001776*/
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001777static QCBORError
1778QCBOR_Private_NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001779{
1780 *pbNextIsBreak = false;
1781 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001782 QCBORItem Peek;
1783 size_t uPeek = UsefulInputBuf_Tell(pUIB);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001784 QCBORError uReturn = QCBOR_Private_DecodeAtomicDataItem(pUIB, &Peek, NULL);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001785 if(uReturn != QCBOR_SUCCESS) {
1786 return uReturn;
1787 }
1788 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001789 /* It is not a break, rewind so it can be processed normally. */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001790 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001791 } else {
1792 *pbNextIsBreak = true;
1793 }
1794 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001795
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001796 return QCBOR_SUCCESS;
1797}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001798#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001799
1800
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001801/**
1802 * @brief Ascend up nesting levels if all items in them have been consumed.
1803 *
1804 * @param[in] pMe The decode context.
1805 * @param[in] bMarkEnd If true mark end of maps/arrays with count of zero.
1806 *
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001807 * An item was just consumed, now figure out if it was the
1808 * end of an array/map map that can be closed out. That
1809 * may in turn close out the above array/map...
Laurence Lundblade642282a2020-06-23 12:00:33 -07001810*/
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001811static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001812QCBORDecode_Private_NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001813{
1814 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001815
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001816 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001817 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1818
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001819 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1820 /* Nesting level is bstr-wrapped CBOR */
1821
1822 /* Ascent for bstr-wrapped CBOR is always by explicit call
1823 * so no further ascending can happen.
1824 */
1825 break;
1826
1827 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1828 /* Level is a definite-length array/map */
1829
1830 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001831 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1832 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001833 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001834 break;
1835 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001836 /* All items in a definite-length array were consumed so it
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001837 * is time to ascend one level. This happens below.
1838 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001839
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001840#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001841 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001842 /* Level is an indefinite-length array/map. */
1843
1844 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001845 bool bIsBreak = false;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001846 uReturn = QCBOR_Private_NextIsBreak(&(pMe->InBuf), &bIsBreak);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001847 if(uReturn != QCBOR_SUCCESS) {
1848 goto Done;
1849 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001850
1851 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001852 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001853 break;
1854 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001855
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001856 /* It was a break in an indefinitelength map / array so
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001857 * it is time to ascend one level.
1858 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001859
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001860#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001861 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001862
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001863
1864 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001865
Laurence Lundblade93d89472020-10-03 22:30:50 -07001866 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001867 * QCBORDecode_ExitBoundedMode().
1868 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001869 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001870 /* Set the count to zero for definite-length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001871 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001872 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001873 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001874 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001875
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001876 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001877 break;
1878 }
1879
1880 /* Finally, actually ascend one level. */
1881 DecodeNesting_Ascend(&(pMe->nesting));
1882 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001883
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001884 uReturn = QCBOR_SUCCESS;
1885
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001886#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001887Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001888#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1889
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001890 return uReturn;
1891}
1892
1893
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001894/**
1895 * @brief Ascending & Descending out of nesting levels (decode layer 2).
1896 *
1897 * @param[in] pMe Decoder context
1898 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07001899
1900 * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved
1901 * features
1902 * @retval QCBOR_ERR_HIT_END Unexpected end of input
1903 * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
1904 * @retval QCBOR_ERR_STRING_ALLOCATE Out of memory.
1905 * @retval QCBOR_ERR_STRING_TOO_LONG String longer than SIZE_MAX - 4.
1906 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
1907 * of half-precision disabled
1908 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point in input, but all
1909 * float decode is disabled.
1910 * @retval QCBOR_ERR_BAD_TYPE_7 Not-allowed representation of
1911 * simple type in input.
1912 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinite length map/array
1913 * in input, but indefinite
1914 * lengths disabled.
1915 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR Indefinite-length string in input,
1916 * but no string allocator.
1917 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK Error in indefinite-length string.
1918 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED Indefinite-length string in
1919 * input, but indefinite-length
1920 * strings are disabled.
1921 * @retval QCBOR_ERR_TOO_MANY_TAGS Too many tag numbers on item.
1922 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG Too many items in array.
1923 * @retval QCBOR_ERR_MAP_LABEL_TYPE Map label not string or integer.
1924 * @retval QCBOR_ERR_NO_MORE_ITEMS Need more items for map or array.
1925 * @retval QCBOR_ERR_BAD_BREAK Indefinite-length break in wrong
1926 * place.
1927 * @retval QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP Nesting deeper than QCBOR
1928 * can handle.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001929 *
1930 * This handles the traversal descending into and asecnding out of
1931 * maps, arrays and bstr-wrapped CBOR. It figures out the ends of
1932 * definite- and indefinte-length maps and arrays by looking at the
1933 * item count or finding CBOR breaks. It detects the ends of the
1934 * top-level sequence and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001935 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001936static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001937QCBORDecode_Private_GetNextMapOrArray(QCBORDecodeContext *pMe,
1938 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001939{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001940 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001941 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001942
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001943 /* If out of bytes to consume, it is either the end of the
1944 * top-level sequence of some bstr-wrapped CBOR that was entered.
1945 *
1946 * In the case of bstr-wrapped CBOR, the length of the
1947 * UsefulInputBuf was set to that of the bstr-wrapped CBOR. When
1948 * the bstr-wrapped CBOR is exited, the length is set back to the
1949 * top-level's length or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001950 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001951 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001952 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001953 goto Done;
1954 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001955
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001956 /* Check to see if at the end of a bounded definite-length map or
1957 * array. The check for a break ending indefinite-length array is
1958 * later in QCBORDecode_NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001959 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001960 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001961 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001962 goto Done;
1963 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001964
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001965 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001966 uReturn = QCBORDecode_Private_GetNextMapEntry(pMe, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001967 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1968 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001969 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001970 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301971
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001972 /* Breaks ending arrays/maps are processed later in the call to
1973 * QCBORDecode_NestLevelAscender(). They should never show up here.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001974 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301975 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001976 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301977 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301978 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001979
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001980 /* Record the nesting level for this data item before processing
1981 * any of decrementing and descending.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001982 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001983 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001984
Laurence Lundblade642282a2020-06-23 12:00:33 -07001985
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001986 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001987 if(QCBORItem_IsMapOrArray(*pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001988 /* If the new item is a map or array, descend.
1989 *
1990 * Empty indefinite-length maps and arrays are descended into,
1991 * but then ascended out of in the next chunk of code.
1992 *
1993 * Maps and arrays do count as items in the map/array that
1994 * encloses them so a decrement needs to be done for them too,
1995 * but that is done only when all the items in them have been
1996 * processed, not when they are opened with the exception of an
1997 * empty map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001998 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001999 QCBORError uDescendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002000 uDescendErr = DecodeNesting_DescendMapOrArray(&(pMe->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07002001 pDecodedItem->uDataType,
2002 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002003 if(uDescendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002004 /* This error is probably a traversal error and it overrides
2005 * the non-traversal error.
2006 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002007 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002008 goto Done;
2009 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07002010 }
2011
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002012 if(!QCBORItem_IsMapOrArray(*pDecodedItem) ||
2013 QCBORItem_IsEmptyDefiniteLengthMapOrArray(*pDecodedItem) ||
2014 QCBORItem_IsIndefiniteLengthMapOrArray(*pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002015 /* The following cases are handled here:
2016 * - A non-aggregate item like an integer or string
2017 * - An empty definite-length map or array
2018 * - An indefinite-length map or array that might be empty or might not.
2019 *
2020 * QCBORDecode_NestLevelAscender() does the work of decrementing the count
2021 * for an definite-length map/array and break detection for an
2022 * indefinite-0length map/array. If the end of the map/array was
2023 * reached, then it ascends nesting levels, possibly all the way
2024 * to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002025 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002026 QCBORError uAscendErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002027 uAscendErr = QCBORDecode_Private_NestLevelAscender(pMe, true);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002028 if(uAscendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002029 /* This error is probably a traversal error and it overrides
2030 * the non-traversal error.
2031 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002032 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002033 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07002034 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05302035 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002036
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07002037 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002038 /* Tell the caller what level is next. This tells them what
2039 * maps/arrays were closed out and makes it possible for them to
2040 * reconstruct the tree with just the information returned in a
2041 * QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07002042 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002043 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07002044 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002045 pDecodedItem->uNextNestLevel = 0;
2046 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002047 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002048 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002049
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002050Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002051 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002052}
2053
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002054
Laurence Lundblade37286c02022-09-03 10:05:02 -07002055#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002056/**
2057 * @brief Shift 0th tag out of the tag list.
2058 *
2059 * pDecodedItem[in,out] The data item to convert.
2060 *
2061 * The 0th tag is discarded. \ref CBOR_TAG_INVALID16 is
2062 * shifted into empty slot at the end of the tag list.
2063 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002064static void
2065QCBOR_Private_ShiftTags(QCBORItem *pDecodedItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002066{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002067 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM-1; i++) {
2068 pDecodedItem->uTags[i] = pDecodedItem->uTags[i+1];
2069 }
2070 pDecodedItem->uTags[QCBOR_MAX_TAGS_PER_ITEM-1] = CBOR_TAG_INVALID16;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002071}
Laurence Lundblade37286c02022-09-03 10:05:02 -07002072#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002073
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07002074
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002075/**
2076 * @brief Convert different epoch date formats in to the QCBOR epoch date format
2077 *
2078 * pDecodedItem[in,out] The data item to convert.
2079 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07002080 * @retval QCBOR_ERR_DATE_OVERFLOW 65-bit negative integer.
2081 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED Float-point date in input,
2082 * floating-point date disabled.
2083 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point date in input,
2084 * all floating-point disabled.
2085 * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT Unexpected and unrecoverable
2086 * error decoding date.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002087 *
2088 * The epoch date tag defined in QCBOR allows for floating-point
2089 * dates. It even allows a protocol to flop between date formats when
2090 * ever it wants. Floating-point dates aren't that useful as they are
2091 * only needed for dates beyond the age of the earth.
2092 *
2093 * This converts all the date formats into one format of an unsigned
2094 * integer plus a floating-point fraction.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002095 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002096static QCBORError
2097QCBOR_Private_DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002098{
Laurence Lundbladec7114722020-08-13 05:11:40 -07002099 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002100
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002101#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade59289e52019-12-30 13:44:37 -08002102 pDecodedItem->val.epochDate.fSecondsFraction = 0;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002103#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002104
2105 switch (pDecodedItem->uDataType) {
2106
2107 case QCBOR_TYPE_INT64:
2108 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
2109 break;
2110
2111 case QCBOR_TYPE_UINT64:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002112 /* This only happens for CBOR type 0 > INT64_MAX so it is
2113 * always an overflow.
2114 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002115 uReturn = QCBOR_ERR_DATE_OVERFLOW;
2116 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002117 break;
2118
2119 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07002120 case QCBOR_TYPE_FLOAT:
2121#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08002122 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002123 /* Convert working value to double if input was a float */
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07002124 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002125 pDecodedItem->val.dfnum :
2126 (double)pDecodedItem->val.fnum;
2127
2128 /* The conversion from float to integer requires overflow
2129 * detection since floats can be much larger than integers.
2130 * This implementation errors out on these large float values
2131 * since they are beyond the age of the earth.
2132 *
2133 * These constants for the overflow check are computed by the
2134 * compiler. They are not computed at run time.
2135 *
2136 * The factor of 0x7ff is added/subtracted to avoid a
2137 * rounding error in the wrong direction when the compiler
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002138 * computes these constants. There is rounding because a
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002139 * 64-bit integer has 63 bits of precision where a double
2140 * only has 53 bits. Without the 0x7ff factor, the compiler
2141 * may round up and produce a double for the bounds check
2142 * that is larger than can be stored in a 64-bit integer. The
2143 * amount of 0x7ff is picked because it has 11 bits set.
2144 *
2145 * Without the 0x7ff there is a ~30 minute range of time
2146 * values 10 billion years in the past and in the future
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002147 * where this code could go wrong. Some compilers
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002148 * generate a warning or error without the 0x7ff.
2149 */
2150 const double dDateMax = (double)(INT64_MAX - 0x7ff);
2151 const double dDateMin = (double)(INT64_MIN + 0x7ff);
2152
2153 if(isnan(d) || d > dDateMax || d < dDateMin) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07002154 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002155 goto Done;
2156 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002157
2158 /* The actual conversion */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002159 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07002160 pDecodedItem->val.epochDate.fSecondsFraction =
2161 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002162 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002163#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade4b270642020-08-14 12:53:07 -07002164
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002165 uReturn = QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07002166 goto Done;
2167
Laurence Lundblade9682a532020-06-06 18:33:04 -07002168#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002169 break;
2170
2171 default:
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002172 /* It's the arrays and maps that are unrecoverable because
2173 * they are not consumed here. Since this is just an error
2174 * condition, no extra code is added here to make the error
2175 * recoverable for non-arrays and maps like strings. */
2176 uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002177 goto Done;
2178 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002179
Laurence Lundblade59289e52019-12-30 13:44:37 -08002180 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
2181
2182Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07002183 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002184}
2185
2186
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002187/**
2188 * @brief Convert the days epoch date.
2189 *
2190 * pDecodedItem[in,out] The data item to convert.
2191 *
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07002192 * @retval QCBOR_ERR_DATE_OVERFLOW 65-bit negative integer.
2193 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED Float-point date in input,
2194 * floating-point date disabled.
2195 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED Float-point date in input,
2196 * all floating-point disabled.
2197 * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT Unexpected and unrecoverable
2198 * error decoding date.
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002199 *
2200 * This is much simpler than the other epoch date format because
2201 * floating-porint is not allowed. This is mostly a simple type check.
2202 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002203static QCBORError
2204QCBOR_Private_DecodeDaysEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002205{
2206 QCBORError uReturn = QCBOR_SUCCESS;
2207
2208 switch (pDecodedItem->uDataType) {
2209
2210 case QCBOR_TYPE_INT64:
2211 pDecodedItem->val.epochDays = pDecodedItem->val.int64;
2212 break;
2213
2214 case QCBOR_TYPE_UINT64:
2215 /* This only happens for CBOR type 0 > INT64_MAX so it is
2216 * always an overflow.
2217 */
2218 uReturn = QCBOR_ERR_DATE_OVERFLOW;
2219 goto Done;
2220 break;
2221
2222 default:
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002223 /* It's the arrays and maps that are unrecoverable because
2224 * they are not consumed here. Since this is just an error
2225 * condition, no extra code is added here to make the error
2226 * recoverable for non-arrays and maps like strings. */
2227 uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002228 goto Done;
2229 break;
2230 }
2231
2232 pDecodedItem->uDataType = QCBOR_TYPE_DAYS_EPOCH;
2233
2234Done:
2235 return uReturn;
2236}
2237
2238
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002239#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade37286c02022-09-03 10:05:02 -07002240
2241/* Forward declaration is necessary for
2242 * QCBORDecode_MantissaAndExponent(). to be able to decode bignum
2243 * tags in the mantissa. If the mantissa is a decimal fraction or big
2244 * float in error, this will result in a recurive call to
2245 * QCBORDecode_MantissaAndExponent(), but the recursion will unwined
2246 * correctly and the correct error is returned.
2247 */
2248static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002249QCBORDecode_Private_GetNextTagContent(QCBORDecodeContext *pMe,
2250 QCBORItem *pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07002251
2252
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002253/**
2254 * @brief Decode decimal fractions and big floats.
2255 *
2256 * @param[in] pMe The decode context.
2257 * @param[in,out] pDecodedItem On input the array data item that
2258 * holds the mantissa and exponent. On
2259 * output the decoded mantissa and
2260 * exponent.
2261 *
2262 * @returns Decoding errors from getting primitive data items or
2263 * \ref QCBOR_ERR_BAD_EXP_AND_MANTISSA.
2264 *
Laurence Lundblade37286c02022-09-03 10:05:02 -07002265 * When called pDecodedItem must be the array with two members, the
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002266 * exponent and mantissa.
2267 *
2268 * This will fetch and decode the exponent and mantissa and put the
2269 * result back into pDecodedItem.
Laurence Lundblade37286c02022-09-03 10:05:02 -07002270 *
2271 * This does no checking or processing of tag numbers. That is to be
2272 * done by the code that calls this.
2273 *
2274 * This stuffs the type of the mantissa into pDecodedItem with the expectation
2275 * the caller will process it.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002276 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07002277static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002278QCBORDecode_Private_ExpMantissa(QCBORDecodeContext *pMe,
2279 QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002280{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002281 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002282
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002283 /* --- Make sure it is an array; track nesting level of members --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002284 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002285 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002286 goto Done;
2287 }
2288
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002289 /* A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundblade37286c02022-09-03 10:05:02 -07002290 * definite-length arrays, but not for indefinite. Instead remember
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002291 * the nesting level the two integers must be at, which is one
2292 * deeper than that of the array.
2293 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002294 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
2295
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002296 /* --- Get the exponent --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002297 QCBORItem exponentItem;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002298 uReturn = QCBORDecode_Private_GetNextMapOrArray(pMe, &exponentItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002299 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002300 goto Done;
2301 }
2302 if(exponentItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002303 /* Array is empty or a map/array encountered when expecting an int */
2304 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002305 goto Done;
2306 }
2307 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002308 /* Data arriving as an unsigned int < INT64_MAX has been
2309 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2310 * also means that the only data arriving here of type
2311 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2312 * and thus an error that will get handled in the next else.
2313 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002314 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
2315 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002316 /* Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX */
2317 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002318 goto Done;
2319 }
2320
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002321 /* --- Get the mantissa --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002322 QCBORItem mantissaItem;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002323 uReturn = QCBORDecode_Private_GetNextTagContent(pMe, &mantissaItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002324 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002325 goto Done;
2326 }
2327 if(mantissaItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002328 /* Mantissa missing or map/array encountered when expecting number */
2329 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002330 goto Done;
2331 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002332 /* Stuff the mantissa data type into the item to send it up to the
2333 * the next level. */
2334 pDecodedItem->uDataType = mantissaItem.uDataType;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002335 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002336 /* Data arriving as an unsigned int < INT64_MAX has been
2337 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2338 * also means that the only data arriving here of type
2339 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2340 * and thus an error that will get handled in an else below.
2341 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002342 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002343#ifndef QCBOR_DISABLE_TAGS
2344 /* With tags fully disabled a big number mantissa will error out
2345 * in the call to QCBORDecode_GetNextWithTags() because it has
2346 * a tag number.
2347 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002348 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
2349 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002350 /* Got a good big num mantissa */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002351 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002352#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002353 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002354 /* Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX */
2355 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002356 goto Done;
2357 }
2358
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002359 /* --- Check that array only has the two numbers --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002360 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002361 /* Extra items in the decimal fraction / big float */
Laurence Lundblade37286c02022-09-03 10:05:02 -07002362 /* Improvement: this should probably be an unrecoverable error. */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002363 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002364 goto Done;
2365 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002366 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002367
2368Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002369 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002370}
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002371#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002372
2373
Laurence Lundblade37286c02022-09-03 10:05:02 -07002374#ifndef QCBOR_DISABLE_TAGS
2375
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002376#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002377/**
2378 * @brief Decode the MIME type tag
2379 *
2380 * @param[in,out] pDecodedItem The item to decode.
2381 *
2382 * Handle the text and binary MIME type tags. Slightly too complicated
2383 * f or ProcessTaggedString() because the RFC 7049 MIME type was
2384 * incorreclty text-only.
2385 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002386static QCBORError
2387QCBOR_Private_DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002388{
2389 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
2390 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07002391 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002392 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
2393 } else {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002394 /* It's the arrays and maps that are unrecoverable because
2395 * they are not consumed here. Since this is just an error
2396 * condition, no extra code is added here to make the error
2397 * recoverable for non-arrays and maps like strings. */
2398 return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002399 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002400
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002401 return QCBOR_SUCCESS;
2402}
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002403#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002404
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002405/**
Laurence Lundblade99615302020-11-29 11:19:47 -08002406 * Table of CBOR tags whose content is either a text string or a byte
2407 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
2408 * of uQCBORtype indicates the content should be a byte string rather
2409 * than a text string
2410 */
2411struct StringTagMapEntry {
2412 uint16_t uTagNumber;
2413 uint8_t uQCBORtype;
2414};
2415
2416#define IS_BYTE_STRING_BIT 0x80
2417#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
2418
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002419static const struct StringTagMapEntry QCBOR_Private_StringTagMap[] = {
Laurence Lundblade99615302020-11-29 11:19:47 -08002420 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002421 {CBOR_TAG_DAYS_STRING, QCBOR_TYPE_DAYS_STRING},
Laurence Lundblade99615302020-11-29 11:19:47 -08002422 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
2423 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
2424 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
2425 {CBOR_TAG_URI, QCBOR_TYPE_URI},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002426#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002427 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
2428 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
2429 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
2430 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002431#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade99615302020-11-29 11:19:47 -08002432 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
2433 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
2434};
2435
2436
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002437/**
2438 * @brief Process standard CBOR tags whose content is a string
2439 *
2440 * @param[in] uTag The tag.
2441 * @param[in,out] pDecodedItem The data item.
2442 *
2443 * @returns This returns QCBOR_SUCCESS if the tag was procssed,
2444 * \ref QCBOR_ERR_UNSUPPORTED if the tag was not processed and
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002445 * \ref QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT if the content type was wrong for the tag.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002446 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002447 * Process the CBOR tags that whose content is a byte string or a text
2448 * string and for which the string is just passed on to the caller.
2449 *
2450 * This maps the CBOR tag to the QCBOR type and checks the content
2451 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08002452 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08002453 * possible.
Laurence Lundblade99615302020-11-29 11:19:47 -08002454 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002455static QCBORError
2456QCBOR_Private_ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002457{
Laurence Lundblade99615302020-11-29 11:19:47 -08002458 /* This only works on tags that were not mapped; no need for other yet */
2459 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
2460 return QCBOR_ERR_UNSUPPORTED;
2461 }
2462
2463 unsigned uIndex;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002464 for(uIndex = 0; QCBOR_Private_StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
2465 if(QCBOR_Private_StringTagMap[uIndex].uTagNumber == uTag) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002466 break;
2467 }
2468 }
2469
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002470 const uint8_t uQCBORType = QCBOR_Private_StringTagMap[uIndex].uQCBORtype;
Laurence Lundblade99615302020-11-29 11:19:47 -08002471 if(uQCBORType == QCBOR_TYPE_NONE) {
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002472 /* repurpose this error to mean not handled here */
Laurence Lundblade99615302020-11-29 11:19:47 -08002473 return QCBOR_ERR_UNSUPPORTED;
2474 }
2475
2476 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
2477 if(uQCBORType & IS_BYTE_STRING_BIT) {
2478 uExpectedType = QCBOR_TYPE_BYTE_STRING;
2479 }
2480
2481 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002482 /* It's the arrays and maps that are unrecoverable because
2483 * they are not consumed here. Since this is just an error
2484 * condition, no extra code is added here to make the error
2485 * recoverable for non-arrays and maps like strings. */
2486 return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002487 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002488
Laurence Lundblade99615302020-11-29 11:19:47 -08002489 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002490 return QCBOR_SUCCESS;
2491}
Laurence Lundblade37286c02022-09-03 10:05:02 -07002492#endif /* QCBOR_DISABLE_TAGS */
2493
2494
2495#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07002496/**
2497 * @brief Figures out data type for exponent mantissa tags.
2498 *
2499 * @param[in] uTagToProcess Either @ref CBOR_TAG_DECIMAL_FRACTION or
2500 * @ref CBOR_TAG_BIG_FLOAT.
2501 * @param[in] pDecodedItem Item being decoded.
2502 *
2503 * @returns One of the 6 values between \ref QCBOR_TYPE_DECIMAL_FRACTION
2504 * and @ref QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM.
2505 *
2506 * Does mapping between a CBOR tag number and a QCBOR type. with a
2507 * little bit of logic and arithmatic.
2508 *
2509 * Used in serveral contexts. Does the work where sometimes the data
2510 * item is explicitly tagged and sometimes not.
Laurence Lundblade37286c02022-09-03 10:05:02 -07002511 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002512static uint8_t
2513QCBOR_Private_ExpMantissaDataType(const uint16_t uTagToProcess,
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07002514 const QCBORItem *pDecodedItem)
Laurence Lundblade37286c02022-09-03 10:05:02 -07002515{
2516 uint8_t uBase = uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ?
2517 QCBOR_TYPE_DECIMAL_FRACTION :
2518 QCBOR_TYPE_BIGFLOAT;
2519 if(pDecodedItem->uDataType != QCBOR_TYPE_INT64) {
2520 uBase = (uint8_t)(uBase + pDecodedItem->uDataType - QCBOR_TYPE_POSBIGNUM + 1);
2521 }
2522 return uBase;
2523}
2524#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002525
2526
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002527/**
2528 * @brief Decode tag content for select tags (decoding layer 1).
2529 *
2530 * @param[in] pMe The decode context.
2531 * @param[out] pDecodedItem The decoded item.
2532 *
2533 * @return Decoding error code.
2534 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002535 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
2536 * but the whole tag was not decoded. Here, the whole tags (tag number
2537 * and tag content) that are supported by QCBOR are decoded. This is a
2538 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002539 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002540static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002541QCBORDecode_Private_GetNextTagContent(QCBORDecodeContext *pMe,
2542 QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002543{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002544 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002545
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002546 uReturn = QCBORDecode_Private_GetNextMapOrArray(pMe, pDecodedItem);
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002547 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002548 goto Done;
2549 }
2550
Laurence Lundblade37286c02022-09-03 10:05:02 -07002551#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002552 /* When there are no tag numbers for the item, this exits first
2553 * thing and effectively does nothing.
2554 *
2555 * This loops over all the tag numbers accumulated for this item
2556 * trying to decode and interpret them. This stops at the end of
2557 * the list or at the first tag number that can't be interpreted by
2558 * this code. This is effectively a recursive processing of the
2559 * tags number list that handles nested tags.
2560 */
2561 while(1) {
2562 /* Don't bother to unmap tags via QCBORITem.uTags since this
2563 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2564 */
2565 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002566
Laurence Lundblade99615302020-11-29 11:19:47 -08002567 if(uTagToProcess == CBOR_TAG_INVALID16) {
2568 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002569 break;
2570
Laurence Lundblade99615302020-11-29 11:19:47 -08002571 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002572 uReturn = QCBOR_Private_DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002573
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002574 } else if(uTagToProcess == CBOR_TAG_DAYS_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002575 uReturn = QCBOR_Private_DecodeDaysEpoch(pDecodedItem);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002576
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002577#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002578 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2579 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002580 uReturn = QCBORDecode_Private_ExpMantissa(pMe, pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07002581 /* --- Which is it, decimal fraction or a bigfloat? --- */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002582 pDecodedItem->uDataType = QCBOR_Private_ExpMantissaDataType(uTagToProcess, pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07002583
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002584#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002585#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002586 } else if(uTagToProcess == CBOR_TAG_MIME ||
2587 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002588 uReturn = QCBOR_Private_DecodeMIME(pDecodedItem);
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002589#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002590
Laurence Lundblade99615302020-11-29 11:19:47 -08002591 } else {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002592 /* See if it is a passthrough byte/text string tag; process if so */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002593 uReturn = QCBOR_Private_ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002594
Laurence Lundblade99615302020-11-29 11:19:47 -08002595 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002596 /* It wasn't a passthrough byte/text string tag so it is
Laurence Lundblade99615302020-11-29 11:19:47 -08002597 * an unknown tag. This is the exit from the loop on the
2598 * first unknown tag. It is a successful exit.
2599 */
2600 uReturn = QCBOR_SUCCESS;
2601 break;
2602 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002603 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002604
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002605 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002606 /* Error exit from the loop */
2607 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002608 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002609
2610 /* A tag was successfully processed, shift it out of the list of
2611 * tags returned. This is the loop increment.
2612 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002613 QCBOR_Private_ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002614 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002615#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002616
2617Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002618 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002619}
2620
2621
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002622/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002623 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002624 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002625QCBORError
2626QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2627{
2628 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002629 uErr = QCBORDecode_Private_GetNextTagContent(pMe, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002630 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002631 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2632 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2633 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002634 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002635}
2636
2637
2638/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002639 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002640 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002641QCBORError
2642QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2643{
2644 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2645 const UsefulInputBuf Save = pMe->InBuf;
2646
2647 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2648
2649 pMe->nesting = SaveNesting;
2650 pMe->InBuf = Save;
2651
2652 return uErr;
2653}
2654
2655
2656/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002657 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002658 */
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002659void
2660QCBORDecode_VPeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2661{
2662 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladef00b8be2024-03-08 10:34:33 -08002663 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2664 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002665 return;
2666 }
2667
2668 pMe->uLastError = (uint8_t)QCBORDecode_PeekNext(pMe, pDecodedItem);
2669}
2670
2671
2672/*
2673 * Public function, see header qcbor/qcbor_decode.h file
2674 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002675void
2676QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002677{
2678 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladef00b8be2024-03-08 10:34:33 -08002679 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2680 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002681 return;
2682 }
2683
2684 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2685}
2686
2687
2688/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002689 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002690 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002691QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002692QCBORDecode_GetNextWithTags(QCBORDecodeContext *pMe,
2693 QCBORItem *pDecodedItem,
2694 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002695{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002696#ifndef QCBOR_DISABLE_TAGS
2697
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002698 QCBORError uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002699
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002700 uReturn = QCBORDecode_GetNext(pMe, pDecodedItem);
2701 if(uReturn != QCBOR_SUCCESS) {
2702 return uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002703 }
2704
2705 if(pTags != NULL) {
2706 pTags->uNumUsed = 0;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002707 /* Reverse the order because pTags is reverse of QCBORItem.uTags. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002708 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2709 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002710 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002711 }
2712 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2713 return QCBOR_ERR_TOO_MANY_TAGS;
2714 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002715 pTags->puTags[pTags->uNumUsed] = QCBORDecode_Private_UnMapTagNumber(pMe,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002716 pTags->uNumUsed++;
2717 }
2718 }
2719
2720 return QCBOR_SUCCESS;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002721
2722#else /* QCBOR_DISABLE_TAGS */
2723 (void)pMe;
2724 (void)pDecodedItem;
2725 (void)pTags;
2726 return QCBOR_ERR_TAGS_DISABLED;
2727#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002728}
2729
2730
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002731/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002732 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302733 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002734bool
2735QCBORDecode_IsTagged(QCBORDecodeContext *pMe,
2736 const QCBORItem *pItem,
2737 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002738{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002739#ifndef QCBOR_DISABLE_TAGS
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002740 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2741 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002742 break;
2743 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002744 if(QCBORDecode_Private_UnMapTagNumber(pMe, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002745 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002746 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002747 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002748#else /* QCBOR_TAGS_DISABLED */
2749 (void)pMe;
2750 (void)pItem;
2751 (void)uTag;
2752#endif /* QCBOR_TAGS_DISABLED */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002753
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002754 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002755}
2756
2757
2758/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002759 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002760 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002761QCBORError
2762QCBORDecode_PartialFinish(QCBORDecodeContext *pMe, size_t *puConsumed)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002763{
Laurence Lundblade87495732021-02-26 10:05:55 -07002764 if(puConsumed != NULL) {
2765 *puConsumed = pMe->InBuf.cursor;
2766 }
2767
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002768 QCBORError uReturn = pMe->uLastError;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002769
2770 if(uReturn != QCBOR_SUCCESS) {
2771 goto Done;
2772 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002773
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002774 /* Error out if all the maps/arrays are not closed out */
2775 if(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002776 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002777 goto Done;
2778 }
2779
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002780 /* Error out if not all the bytes are consumed */
2781 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002782 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002783 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002784
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002785Done:
Laurence Lundblade87495732021-02-26 10:05:55 -07002786 return uReturn;
2787}
2788
2789
2790/*
2791 * Public function, see header qcbor/qcbor_decode.h file
2792 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002793QCBORError
2794QCBORDecode_Finish(QCBORDecodeContext *pMe)
Laurence Lundblade87495732021-02-26 10:05:55 -07002795{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002796#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002797 /* Call the destructor for the string allocator if there is one.
2798 * Always called, even if there are errors; always have to clean up.
2799 */
2800 StringAllocator_Destruct(&(pMe->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002801#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002802
Laurence Lundblade87495732021-02-26 10:05:55 -07002803 return QCBORDecode_PartialFinish(pMe, NULL);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002804}
2805
2806
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002807/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002808 * Public function, see header qcbor/qcbor_decode.h file
2809 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002810uint64_t
2811QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2812 const QCBORItem *pItem,
2813 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002814{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002815#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002816 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2817 return CBOR_TAG_INVALID64;
2818 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002819 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2820 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002821 } else {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002822 return QCBORDecode_Private_UnMapTagNumber(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002823 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002824#else /* QCBOR_DISABLE_TAGS */
2825 (void)pMe;
2826 (void)pItem;
2827 (void)uIndex;
2828
2829 return CBOR_TAG_INVALID64;
2830#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002831}
2832
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002833
Laurence Lundblade9b334962020-08-27 10:55:53 -07002834/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002835 * Public function, see header qcbor/qcbor_decode.h file
2836 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002837uint64_t
2838QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2839 uint32_t uIndex)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002840{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002841#ifndef QCBOR_DISABLE_TAGS
2842
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002843 if(pMe->uLastError != QCBOR_SUCCESS) {
2844 return CBOR_TAG_INVALID64;
2845 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002846 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2847 return CBOR_TAG_INVALID64;
2848 } else {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002849 return QCBORDecode_Private_UnMapTagNumber(pMe, pMe->uLastTags[uIndex]);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002850 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002851#else /* QCBOR_DISABLE_TAGS */
2852 (void)pMe;
2853 (void)uIndex;
2854
2855 return CBOR_TAG_INVALID64;
2856#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002857}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002858
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002859
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002860
2861
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002862#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002863
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002864/* ===========================================================================
2865 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002866
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002867 This implements a simple sting allocator for indefinite-length
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002868 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2869 implements the function type QCBORStringAllocate and allows easy
2870 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002871
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002872 This particular allocator is built-in for convenience. The caller
2873 can implement their own. All of this following code will get
2874 dead-stripped if QCBORDecode_SetMemPool() is not called.
2875
2876 This is a very primitive memory allocator. It does not track
2877 individual allocations, only a high-water mark. A free or
2878 reallocation must be of the last chunk allocated.
2879
2880 The size of the pool and offset to free memory are packed into the
2881 first 8 bytes of the memory pool so we don't have to keep them in
2882 the decode context. Since the address of the pool may not be
2883 aligned, they have to be packed and unpacked as if they were
2884 serialized data of the wire or such.
2885
2886 The sizes packed in are uint32_t to be the same on all CPU types
2887 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002888 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002889
2890
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002891static int
Laurence Lundbladeee851742020-01-08 08:37:05 -08002892MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002893{
2894 // Use of UsefulInputBuf is overkill, but it is convenient.
2895 UsefulInputBuf UIB;
2896
Laurence Lundbladeee851742020-01-08 08:37:05 -08002897 // Just assume the size here. It was checked during SetUp so
2898 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002899 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002900 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2901 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2902 return UsefulInputBuf_GetError(&UIB);
2903}
2904
2905
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002906static int
Laurence Lundbladeee851742020-01-08 08:37:05 -08002907MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002908{
2909 // Use of UsefulOutBuf is overkill, but convenient. The
2910 // length check performed here is useful.
2911 UsefulOutBuf UOB;
2912
2913 UsefulOutBuf_Init(&UOB, Pool);
2914 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2915 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2916 return UsefulOutBuf_GetError(&UOB);
2917}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002918
2919
2920/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002921 Internal function for an allocation, reallocation free and destuct.
2922
2923 Having only one function rather than one each per mode saves space in
2924 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002925
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002926 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2927 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002928static UsefulBuf
2929MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002930{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002931 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002932
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002933 uint32_t uPoolSize;
2934 uint32_t uFreeOffset;
2935
2936 if(uNewSize > UINT32_MAX) {
2937 // This allocator is only good up to 4GB. This check should
2938 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2939 goto Done;
2940 }
2941 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2942
2943 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2944 goto Done;
2945 }
2946
2947 if(uNewSize) {
2948 if(pMem) {
2949 // REALLOCATION MODE
2950 // Calculate pointer to the end of the memory pool. It is
2951 // assumed that pPool + uPoolSize won't wrap around by
2952 // assuming the caller won't pass a pool buffer in that is
2953 // not in legitimate memory space.
2954 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2955
2956 // Check that the pointer for reallocation is in the range of the
2957 // pool. This also makes sure that pointer math further down
2958 // doesn't wrap under or over.
2959 if(pMem >= pPool && pMem < pPoolEnd) {
2960 // Offset to start of chunk for reallocation. This won't
2961 // wrap under because of check that pMem >= pPool. Cast
2962 // is safe because the pool is always less than UINT32_MAX
2963 // because of check in QCBORDecode_SetMemPool().
2964 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2965
2966 // Check to see if the allocation will fit. uPoolSize -
2967 // uMemOffset will not wrap under because of check that
2968 // pMem is in the range of the uPoolSize by check above.
2969 if(uNewSize <= uPoolSize - uMemOffset) {
2970 ReturnValue.ptr = pMem;
2971 ReturnValue.len = uNewSize;
2972
2973 // Addition won't wrap around over because uNewSize was
2974 // checked to be sure it is less than the pool size.
2975 uFreeOffset = uMemOffset + uNewSize32;
2976 }
2977 }
2978 } else {
2979 // ALLOCATION MODE
2980 // uPoolSize - uFreeOffset will not underflow because this
2981 // pool implementation makes sure uFreeOffset is always
2982 // smaller than uPoolSize through this check here and
2983 // reallocation case.
2984 if(uNewSize <= uPoolSize - uFreeOffset) {
2985 ReturnValue.len = uNewSize;
2986 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002987 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002988 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002989 }
2990 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002991 if(pMem) {
2992 // FREE MODE
2993 // Cast is safe because of limit on pool size in
2994 // QCBORDecode_SetMemPool()
2995 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2996 } else {
2997 // DESTRUCT MODE
2998 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002999 }
3000 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003001
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003002 UsefulBuf Pool = {pPool, uPoolSize};
3003 MemPool_Pack(Pool, uFreeOffset);
3004
3005Done:
3006 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003007}
3008
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003009
Laurence Lundbladef6531662018-12-04 10:42:22 +09003010/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003011 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09003012 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003013QCBORError
3014QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
3015 UsefulBuf Pool,
3016 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003017{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003018 // The pool size and free mem offset are packed into the beginning
Dave Thaler93c01182022-08-06 15:08:35 -04003019 // of the pool memory. This compile time check makes sure the
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003020 // constant in the header is correct. This check should optimize
3021 // down to nothing.
Dave Thaler93c01182022-08-06 15:08:35 -04003022#ifdef _MSC_VER
3023#pragma warning(push)
3024#pragma warning(disable:4127) // conditional expression is constant
3025#endif
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003026 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003027 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003028 }
Dave Thaler93c01182022-08-06 15:08:35 -04003029#ifdef _MSC_VER
3030#pragma warning(pop)
3031#endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003032
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003033 // The pool size and free offset packed in to the beginning of pool
3034 // memory are only 32-bits. This check will optimize out on 32-bit
3035 // machines.
3036 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003037 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003038 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003039
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003040 // This checks that the pool buffer given is big enough.
3041 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003042 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08003043 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003044
Laurence Lundblade3427dee2021-06-20 11:11:24 -07003045 QCBORDecode_SetUpAllocator(pMe, MemPool_Function, Pool.ptr, bAllStrings);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003046
Laurence Lundblade30816f22018-11-10 13:40:22 +07003047 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07003048}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08003049#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003050
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003051
3052
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003053static void
3054QCBORDecode_Private_CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07003055{
Laurence Lundblade37286c02022-09-03 10:05:02 -07003056#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade9b334962020-08-27 10:55:53 -07003057 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
Laurence Lundblade37286c02022-09-03 10:05:02 -07003058#else
3059 (void)pMe;
3060 (void)pItem;
3061#endif
Laurence Lundblade9b334962020-08-27 10:55:53 -07003062}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003063
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003064
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003065/**
3066 * @brief Consume an entire map or array including its contents.
3067 *
3068 * @param[in] pMe The decoder context.
3069 * @param[in] pItemToConsume The array/map whose contents are to be
3070 * consumed.
3071 * @param[out] puNextNestLevel The next nesting level after the item was
3072 * fully consumed.
3073 *
3074 * This may be called when @c pItemToConsume is not an array or
3075 * map. In that case, this is just a pass through for @c puNextNestLevel
3076 * since there is nothing to do.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003077 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003078static QCBORError
3079QCBORDecode_Private_ConsumeItem(QCBORDecodeContext *pMe,
3080 const QCBORItem *pItemToConsume,
3081 uint8_t *puNextNestLevel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003082{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003083 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003084 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003085
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003086 /* If it is a map or array, this will tell if it is empty. */
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003087 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
3088
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003089 if(QCBORItem_IsMapOrArray(*pItemToConsume) && !bIsEmpty) {
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003090 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003091
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003092 /* This works for definite- and indefinite-length maps and
3093 * arrays by using the nesting level
Laurence Lundblade1341c592020-04-11 14:19:05 -07003094 */
3095 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003096 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003097 if(QCBORDecode_IsUnrecoverableError(uReturn) ||
3098 uReturn == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003099 goto Done;
3100 }
3101 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003102
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003103 *puNextNestLevel = Item.uNextNestLevel;
3104
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003105 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003106
Laurence Lundblade1341c592020-04-11 14:19:05 -07003107 } else {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003108 /* pItemToConsume is not a map or array. Just pass the nesting
3109 * level through. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003110 *puNextNestLevel = pItemToConsume->uNextNestLevel;
3111
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003112 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003113 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003114
3115Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003116 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003117}
3118
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003119
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003120/*
3121 * Public function, see header qcbor/qcbor_decode.h file
3122 */
3123void
3124QCBORDecode_VGetNextConsume(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003125{
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003126 QCBORDecode_VGetNext(pMe, pDecodedItem);
3127
3128 if(pMe->uLastError == QCBOR_SUCCESS) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003129 pMe->uLastError = (uint8_t)QCBORDecode_Private_ConsumeItem(pMe, pDecodedItem,
Máté Tóth-Pálc6d59682021-05-26 18:55:30 +02003130 &pDecodedItem->uNextNestLevel);
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003131 }
3132}
3133
3134
Laurence Lundblade11654912024-05-09 11:49:24 -07003135/*
3136 * Public function, see header qcbor/qcbor_decode.h file
3137 */
3138uint32_t
3139QCBORDecode_Tell(QCBORDecodeContext *pMe)
3140{
3141 size_t uCursorOffset;
3142
3143 if(pMe->uLastError != QCBOR_SUCCESS) {
3144 return UINT32_MAX;
3145 }
3146
3147 uCursorOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
3148
3149 if(uCursorOffset == UsefulInputBuf_GetBufferLength(&(pMe->InBuf))) {
3150 return UINT32_MAX;
3151 } else {
3152 /* Cast is safe because decoder input size is restricted. */
3153 return (uint32_t)uCursorOffset;
3154 }
3155}
3156
3157
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003158/**
3159 * @brief Rewind cursor to start as if map or array were just entered.
3160 *
3161 * @param[in] pMe The decoding context
3162 *
3163 * This affects the nesting tracking and the UsefulInputBuf.
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003164 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003165static void
3166QCBORDecode_Private_RewindMapOrArray(QCBORDecodeContext *pMe)
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003167{
3168 /* Reset nesting tracking to the deepest bounded level */
3169 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
3170
3171 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3172
3173 /* Reposition traversal cursor to the start of the map/array */
3174 UsefulInputBuf_Seek(&(pMe->InBuf),
3175 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
3176}
3177
3178
3179/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003180 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003181 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003182void
3183QCBORDecode_Rewind(QCBORDecodeContext *pMe)
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003184{
3185 if(pMe->nesting.pCurrentBounded != NULL) {
3186 /* In a bounded map, array or bstr-wrapped CBOR */
3187
3188 if(DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
3189 /* In bstr-wrapped CBOR. */
3190
3191 /* Reposition traversal cursor to start of wrapping byte string */
3192 UsefulInputBuf_Seek(&(pMe->InBuf),
3193 pMe->nesting.pCurrentBounded->u.bs.uBstrStartOffset);
3194 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
3195
3196 } else {
3197 /* In a map or array */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003198 QCBORDecode_Private_RewindMapOrArray(pMe);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003199 }
3200
3201 } else {
3202 /* Not in anything bounded */
3203
3204 /* Reposition traversal cursor to the start of input CBOR */
3205 UsefulInputBuf_Seek(&(pMe->InBuf), 0ULL);
3206
3207 /* Reset nesting tracking to beginning of input. */
3208 DecodeNesting_Init(&(pMe->nesting));
3209 }
3210
3211 pMe->uLastError = QCBOR_SUCCESS;
3212}
3213
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003214
Laurence Lundblade9b334962020-08-27 10:55:53 -07003215
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003216
3217
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003218/**
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003219 * @brief Search a map for a set of items.
3220 *
3221 * @param[in] pMe The decode context to search.
3222 * @param[in,out] pItemArray The items to search for and the items found.
3223 * @param[out] puOffset Byte offset of last item matched.
3224 * @param[in] pCBContext Context for the not-found item call back.
3225 * @param[in] pfCallback Function to call on items not matched in pItemArray.
3226 *
3227 * @retval QCBOR_ERR_NOT_ENTERED Trying to search without entering a map.
3228 *
3229 * @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
3230 * were found for one of the labels being
3231 * search for. This duplicate detection is
3232 * only performed for items in pItemArray,
3233 * not every item in the map.
3234 *
3235 * @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
3236 * wrong for the matchd label.
3237 *
3238 * @retval Also errors returned by QCBORDecode_GetNext().
3239 *
3240 * On input, \c pItemArray contains a list of labels and data types of
3241 * items to be found.
3242 *
3243 * On output, the fully retrieved items are filled in with values and
3244 * such. The label was matched, so it never changes.
3245 *
3246 * If an item was not found, its data type is set to @ref QCBOR_TYPE_NONE.
3247 *
3248 * This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003249 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003250static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003251QCBORDecode_Private_MapSearch(QCBORDecodeContext *pMe,
3252 QCBORItem *pItemArray,
3253 size_t *puOffset,
3254 void *pCBContext,
3255 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003256{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003257 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003258 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07003259
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003260 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003261 uReturn = pMe->uLastError;
3262 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003263 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003264
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003265 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003266 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
3267 /* QCBOR_TYPE_NONE as first item indicates just looking
3268 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003269 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
3270 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003271 }
3272
Laurence Lundblade085d7952020-07-24 10:26:30 -07003273 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
3274 // It is an empty bounded array or map
3275 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
3276 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003277 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07003278 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003279 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003280 // Nothing is ever found in an empty array or map. All items
3281 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07003282 uReturn = QCBOR_SUCCESS;
3283 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003284 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003285 }
3286
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003287 QCBORDecodeNesting SaveNesting;
Laurence Lundblade11654912024-05-09 11:49:24 -07003288 size_t uSavePos = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade085d7952020-07-24 10:26:30 -07003289 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
3290
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003291 /* Reposition to search from the start of the map / array */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003292 QCBORDecode_Private_RewindMapOrArray(pMe);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003293
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003294 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003295 Loop over all the items in the map or array. Each item
3296 could be a map or array, but label matching is only at
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003297 the main level. This handles definite- and indefinite-
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003298 length maps and arrays. The only reason this is ever
3299 called on arrays is to find their end position.
3300
3301 This will always run over all items in order to do
3302 duplicate detection.
3303
3304 This will exit with failure if it encounters an
3305 unrecoverable error, but continue on for recoverable
3306 errors.
3307
3308 If a recoverable error occurs on a matched item, then
3309 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003310 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07003311 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Máté Tóth-Pál2f2aa5f2021-05-17 21:35:09 +02003312 uint8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003313 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003314 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07003315 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003316
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003317 /* Get the item */
3318 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003319 QCBORError uResult = QCBORDecode_Private_GetNextTagContent(pMe, &Item);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003320 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003321 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003322 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003323 goto Done;
3324 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003325 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003326 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003327 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003328 goto Done;
3329 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003330
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003331 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003332 bool bMatched = false;
3333 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003334 if(QCBORItem_MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003335 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003336 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
3337 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003338 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003339 }
Laurence Lundblade63926052021-03-29 16:05:51 -07003340 if(uResult != QCBOR_SUCCESS) {
3341 /* The label matches, but the data item is in error */
3342 uReturn = uResult;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003343 goto Done;
3344 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003345 if(!QCBORItem_MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade63926052021-03-29 16:05:51 -07003346 /* The data item is not of the type(s) requested */
3347 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003348 goto Done;
3349 }
3350
Laurence Lundblade1341c592020-04-11 14:19:05 -07003351 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003352 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003353 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003354 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003355 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003356 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003357 bMatched = true;
3358 }
3359 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003360
3361
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003362 if(!bMatched && pfCallback != NULL) {
3363 /*
3364 Call the callback on unmatched labels.
3365 (It is tempting to do duplicate detection here, but that would
3366 require dynamic memory allocation because the number of labels
3367 that might be encountered is unbounded.)
3368 */
3369 uReturn = (*pfCallback)(pCBContext, &Item);
3370 if(uReturn != QCBOR_SUCCESS) {
3371 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003372 }
3373 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003374
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003375 /*
3376 Consume the item whether matched or not. This
3377 does the work of traversing maps and array and
3378 everything in them. In this loop only the
3379 items at the current nesting level are examined
3380 to match the labels.
3381 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003382 uReturn = QCBORDecode_Private_ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003383 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003384 goto Done;
3385 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003386 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003387
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003388 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003389
3390 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003391
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003392 // Check here makes sure that this won't accidentally be
3393 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003394 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003395 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
3396 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003397 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
3398 goto Done;
3399 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003400 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
3401 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003402
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003403 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003404 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
Laurence Lundblade11654912024-05-09 11:49:24 -07003405 UsefulInputBuf_Seek(&(pMe->InBuf), uSavePos);
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003406
3407 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003408 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07003409 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003410 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003411 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
3412 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003413 }
3414 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003415
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003416 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003417}
3418
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003419
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003420/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003421 * Public function, see header qcbor/qcbor_decode.h file
3422 */
3423void
3424QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
3425 int64_t nLabel,
3426 uint8_t uQcborType,
3427 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003428{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003429 if(pMe->uLastError != QCBOR_SUCCESS) {
3430 return;
3431 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003432
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003433 QCBORItem OneItemSeach[2];
3434 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3435 OneItemSeach[0].label.int64 = nLabel;
3436 OneItemSeach[0].uDataType = uQcborType;
3437 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003438
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003439 QCBORError uReturn = QCBORDecode_Private_MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003440
3441 *pItem = OneItemSeach[0];
3442
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003443 if(uReturn != QCBOR_SUCCESS) {
3444 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003445 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003446 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003447 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003448 }
3449
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003450 Done:
3451 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003452}
3453
3454
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003455/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003456 * Public function, see header qcbor/qcbor_decode.h file
3457 */
3458void
3459QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
3460 const char *szLabel,
3461 uint8_t uQcborType,
3462 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003463{
Laurence Lundbladeda095972020-06-06 18:35:33 -07003464 if(pMe->uLastError != QCBOR_SUCCESS) {
3465 return;
3466 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003467
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003468 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003469 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3470 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3471 OneItemSeach[0].uDataType = uQcborType;
3472 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003473
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003474 QCBORError uReturn = QCBORDecode_Private_MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003475 if(uReturn != QCBOR_SUCCESS) {
3476 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003477 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003478 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003479 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003480 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003481 }
3482
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003483 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003484
3485Done:
3486 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003487}
3488
3489
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003490/**
3491 * @brief Is a QCBOR_TYPE in the type list?
3492 *
3493 * @param[in] uDataType Type to check for.
3494 * @param[in] puTypeList List to check.
3495 *
3496 * @retval QCBOR_SUCCESS If in the list.
3497 * @retval QCBOR_ERR_UNEXPECTED_TYPE Not in the list.
3498 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07003499static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003500QCBOR_Private_CheckTypeList(const int uDataType,
3501 const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003502{
3503 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08003504 if(uDataType == puTypeList[i]) { /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003505 return QCBOR_SUCCESS;
3506 }
3507 }
3508 return QCBOR_ERR_UNEXPECTED_TYPE;
3509}
3510
Laurence Lundblade67257dc2020-07-27 03:33:37 -07003511
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003512/**
Laurence Lundblade37286c02022-09-03 10:05:02 -07003513 * Match a tag/type specification against the type of the item.
3514 *
3515 * @param[in] TagSpec Specification for matching tags.
3516 * @param[in] pItem The item to check.
3517 *
3518 * @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
3519 * @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
3520 *
3521 * This checks the item data type of untagged items as well as of
3522 * tagged items against a specification to see if decoding should
3523 * proceed.
3524 *
3525 * This relies on the automatic tag decoding done by QCBOR that turns
3526 * tag numbers into particular QCBOR_TYPEs so there is no actual
3527 * comparsion of tag numbers, just of QCBOR_TYPEs.
3528 *
3529 * This checks the data item type as possibly representing the tag
3530 * number or as the tag content type.
3531 *
3532 * If QCBOR_DISABLE_TAGS is #defined, this primarily checks the item
3533 * data type against the allowed tag content types. It will also error out
3534 * if the caller tries to require a tag because there is no way that can
3535 * ever be fulfilled.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003536 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07003537static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003538QCBOR_Private_CheckTagRequirement(const QCBOR_Private_TagSpec TagSpec,
3539 const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07003540{
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08003541 const int nItemType = pItem->uDataType; /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade37286c02022-09-03 10:05:02 -07003542 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
3543
3544#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08003545 /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003546 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
3547 pItem->uTags[0] != CBOR_TAG_INVALID16) {
3548 /* There are tags that QCBOR couldn't process on this item and
Laurence Lundblade37286c02022-09-03 10:05:02 -07003549 * the caller has told us there should not be.
3550 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003551 return QCBOR_ERR_UNEXPECTED_TYPE;
3552 }
3553
Laurence Lundblade9b334962020-08-27 10:55:53 -07003554 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
Laurence Lundblade37286c02022-09-03 10:05:02 -07003555 /* Must match the tag number and only the tag */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003556 return QCBOR_Private_CheckTypeList(nItemType, TagSpec.uTaggedTypes);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003557 }
3558
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003559 QCBORError uReturn = QCBOR_Private_CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003560 if(uReturn == QCBOR_SUCCESS) {
3561 return QCBOR_SUCCESS;
3562 }
3563
3564 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
3565 /* Must match the content type and only the content type.
Laurence Lundblade37286c02022-09-03 10:05:02 -07003566 * There was no match just above so it is a fail. */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003567 return QCBOR_ERR_UNEXPECTED_TYPE;
3568 }
3569
Laurence Lundblade37286c02022-09-03 10:05:02 -07003570 /* QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG: If here it can match either the tag or the content
3571 * and it hasn't matched the content, so the end
3572 * result is whether it matches the tag. This is
3573 * the tag optional case that the CBOR standard discourages.
3574 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003575
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003576 return QCBOR_Private_CheckTypeList(nItemType, TagSpec.uTaggedTypes);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003577
Laurence Lundblade37286c02022-09-03 10:05:02 -07003578#else /* QCBOR_DISABLE_TAGS */
3579 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
3580 return QCBOR_ERR_UNEXPECTED_TYPE;
3581 }
3582
Laurence Lundblade0f01ac62024-02-18 23:07:07 -07003583 return QCBOR_Private_CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
Laurence Lundblade37286c02022-09-03 10:05:02 -07003584
3585#endif /* QCBOR_DISABLE_TAGS */
3586}
Laurence Lundblade9b334962020-08-27 10:55:53 -07003587
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003588
3589/**
3590 * @brief Get an item by label to match a tag specification.
3591 *
3592 * @param[in] pMe The decode context.
3593 * @param[in] nLabel The label to search map for.
3594 * @param[in] TagSpec The tag number specification to match.
3595 * @param[out] pItem The item found.
3596 *
3597 * This finds the item with the given label in currently open
3598 * map. Then checks that its tag number and types matches the tag
3599 * specification. If not, an error is set in the decode context.
3600 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003601static void
3602QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
3603 const int64_t nLabel,
3604 const QCBOR_Private_TagSpec TagSpec,
3605 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003606{
3607 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
3608 if(pMe->uLastError != QCBOR_SUCCESS) {
3609 return;
3610 }
3611
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003612 pMe->uLastError = (uint8_t)QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003613}
3614
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003615
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003616/**
3617 * @brief Get an item by label to match a tag specification.
3618 *
3619 * @param[in] pMe The decode context.
3620 * @param[in] szLabel The label to search map for.
3621 * @param[in] TagSpec The tag number specification to match.
3622 * @param[out] pItem The item found.
3623 *
3624 * This finds the item with the given label in currently open
3625 * map. Then checks that its tag number and types matches the tag
3626 * specification. If not, an error is set in the decode context.
3627 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003628static void
3629QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
3630 const char *szLabel,
3631 const QCBOR_Private_TagSpec TagSpec,
3632 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003633{
3634 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
3635 if(pMe->uLastError != QCBOR_SUCCESS) {
3636 return;
3637 }
3638
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003639 pMe->uLastError = (uint8_t)QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003640}
3641
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003642
3643/**
3644 * @brief Semi-private to get an string by label to match a tag specification.
3645 *
3646 * @param[in] pMe The decode context.
3647 * @param[in] nLabel The label to search map for.
3648 * @param[in] TagSpec The tag number specification to match.
3649 * @param[out] pString The string found.
3650 *
3651 * This finds the string with the given label in currently open
3652 * map. Then checks that its tag number and types matches the tag
3653 * specification. If not, an error is set in the decode context.
3654 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003655void
3656QCBORDecode_Private_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
3657 const int64_t nLabel,
3658 const QCBOR_Private_TagSpec TagSpec,
3659 UsefulBufC *pString)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003660{
3661 QCBORItem Item;
3662 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
3663 if(pMe->uLastError == QCBOR_SUCCESS) {
3664 *pString = Item.val.string;
3665 }
3666}
3667
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003668
3669/**
3670 * @brief Semi-private to get an string by label to match a tag specification.
3671 *
3672 * @param[in] pMe The decode context.
3673 * @param[in] szLabel The label to search map for.
3674 * @param[in] TagSpec The tag number specification to match.
3675 * @param[out] pString The string found.
3676 *
3677 * This finds the string with the given label in currently open
3678 * map. Then checks that its tag number and types matches the tag
3679 * specification. If not, an error is set in the decode context.
3680 */void
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003681QCBORDecode_Private_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
3682 const char * szLabel,
3683 const QCBOR_Private_TagSpec TagSpec,
3684 UsefulBufC *pString)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003685{
3686 QCBORItem Item;
3687 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
3688 if(pMe->uLastError == QCBOR_SUCCESS) {
3689 *pString = Item.val.string;
3690 }
3691}
Laurence Lundblade1341c592020-04-11 14:19:05 -07003692
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003693
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003694/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003695 * Public function, see header qcbor/qcbor_decode.h file
3696 */
3697void
3698QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003699{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003700 QCBORError uErr = QCBORDecode_Private_MapSearch(pMe, pItemList, NULL, NULL, NULL);
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003701 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003702}
3703
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003704/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003705 * Public function, see header qcbor/qcbor_decode.h file
3706 */
3707void
3708QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3709 QCBORItem *pItemList,
3710 void *pCallbackCtx,
3711 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003712{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003713 QCBORError uErr = QCBORDecode_Private_MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003714 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003715}
3716
3717
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003718/**
3719 * @brief Search for a map/array by label and enter it
3720 *
3721 * @param[in] pMe The decode context.
3722 * @param[in] pSearch The map/array to search for.
3723 *
3724 * @c pSearch is expected to contain one item of type map or array
3725 * with the label specified. The current bounded map will be searched for
3726 * this and if found will be entered.
3727 *
3728 * If the label is not found, or the item found is not a map or array,
3729 * the error state is set.
3730 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003731static void
3732QCBORDecode_Private_SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003733{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003734 // The first item in pSearch is the one that is to be
3735 // entered. It should be the only one filled in. Any other
3736 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003737 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003738 return;
3739 }
3740
3741 size_t uOffset;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003742 pMe->uLastError = (uint8_t)QCBORDecode_Private_MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003743 if(pMe->uLastError != QCBOR_SUCCESS) {
3744 return;
3745 }
3746
Laurence Lundblade9b334962020-08-27 10:55:53 -07003747 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003748 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003749 return;
3750 }
3751
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003752
3753 /* The map or array was found. Now enter it.
3754 *
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003755 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3756 * next item for the pre-order traversal cursor to be the map/array
3757 * found by MapSearch(). The next few lines of code force the
3758 * cursor to that.
3759 *
3760 * There is no need to retain the old cursor because
3761 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3762 * beginning of the map/array being entered.
3763 *
3764 * The cursor is forced by: 1) setting the input buffer position to
3765 * the item offset found by MapSearch(), 2) setting the map/array
3766 * counter to the total in the map/array, 3) setting the nesting
3767 * level. Setting the map/array counter to the total is not
3768 * strictly correct, but this is OK because this cursor only needs
3769 * to be used to get one item and MapSearch() has already found it
3770 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003771 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003772 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003773
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003774 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3775
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003776 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003777
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003778 QCBORDecode_Private_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003779}
3780
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_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -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_MAP;
3792 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003793
Laurence Lundblade9b334962020-08-27 10:55:53 -07003794 /* The map to enter was found, now finish off entering it. */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003795 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003796}
3797
3798
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003799/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003800 * Public function, see header qcbor/qcbor_decode.h file
3801 */
3802void
3803QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003804{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003805 QCBORItem OneItemSeach[2];
3806 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3807 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3808 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3809 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003810
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003811 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003812}
3813
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003814/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003815 * Public function, see header qcbor/qcbor_decode.h file
3816 */
3817void
3818QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003819{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003820 QCBORItem OneItemSeach[2];
3821 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3822 OneItemSeach[0].label.int64 = nLabel;
3823 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3824 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003825
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003826 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003827}
3828
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003829/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003830 * Public function, see header qcbor/qcbor_decode.h file
3831 */
3832void
3833QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundblade34691b92020-05-18 22:25:25 -07003834{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003835 QCBORItem OneItemSeach[2];
3836 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3837 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3838 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3839 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003840
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003841 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003842}
3843
3844
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003845/**
3846 * @brief Semi-private to do the the work for EnterMap() and EnterArray().
3847 *
3848 * @param[in] pMe The decode context
3849 * @param[in] uType QCBOR_TYPE_MAP or QCBOR_TYPE_ARRAY.
3850 * @param[out] pItem The data item for the map or array entered.
3851 *
3852 * The next item in the traversal must be a map or array. This
3853 * consumes that item and does the book keeping to enter the map or
3854 * array.
3855 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003856void
3857QCBORDecode_Private_EnterBoundedMapOrArray(QCBORDecodeContext *pMe,
3858 const uint8_t uType,
3859 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003860{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003861 QCBORError uErr;
3862
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003863 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003864 if(pMe->uLastError != QCBOR_SUCCESS) {
3865 // Already in error state; do nothing.
3866 return;
3867 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003868
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003869 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003870 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003871 uErr = QCBORDecode_GetNext(pMe, &Item);
3872 if(uErr != QCBOR_SUCCESS) {
3873 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003874 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003875 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003876 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3877 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003878 }
3879
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003880 QCBORDecode_Private_CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003881
3882
Laurence Lundbladef0499502020-08-01 11:55:57 -07003883 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003884 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003885 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3886 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003887 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003888 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3889 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003890 // Special case to increment nesting level for zero-length maps
3891 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003892 DecodeNesting_Descend(&(pMe->nesting), uType);
3893 }
3894
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003895 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003896
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003897 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3898 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003899
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003900 if(pItem != NULL) {
3901 *pItem = Item;
3902 }
3903
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003904Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003905 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003906}
3907
Laurence Lundblade02625d42020-06-25 14:41:41 -07003908
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003909/**
3910 * @brief Exit a bounded map, array or bstr (semi-private).
3911 *
3912 * @param[in] pMe Decode context.
3913 * @param[in] uEndOffset The input buffer offset of the end of item exited.
3914 *
3915 * @returns QCBOR_SUCCESS or an error code.
3916 *
3917 * This is the common work for exiting a level that is a bounded map,
3918 * array or bstr wrapped CBOR.
3919 *
3920 * One chunk of work is to set up the pre-order traversal so it is at
3921 * the item just after the bounded map, array or bstr that is being
3922 * exited. This is somewhat complex.
3923 *
3924 * The other work is to level-up the bounded mode to next higest
3925 * bounded mode or the top level if there isn't one.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003926 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003927static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003928QCBORDecode_Private_ExitBoundedLevel(QCBORDecodeContext *pMe,
3929 const uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003930{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003931 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003932
Laurence Lundblade02625d42020-06-25 14:41:41 -07003933 /*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003934 * First the pre-order-traversal byte offset is positioned to the
3935 * item just after the bounded mode item that was just consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003936 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003937 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3938
Laurence Lundblade02625d42020-06-25 14:41:41 -07003939 /*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003940 * Next, set the current nesting level to one above the bounded
3941 * level that was just exited.
3942 *
3943 * DecodeNesting_CheckBoundedType() is always called before this
3944 * and makes sure pCurrentBounded is valid.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003945 */
3946 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3947
3948 /*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003949 * This does the complex work of leveling up the pre-order
3950 * traversal when the end of a map or array or another bounded
3951 * level is reached. It may do nothing, or ascend all the way to
3952 * the top level.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003953 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003954 uErr = QCBORDecode_Private_NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003955 if(uErr != QCBOR_SUCCESS) {
3956 goto Done;
3957 }
3958
Laurence Lundblade02625d42020-06-25 14:41:41 -07003959 /*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003960 * This makes the next highest bounded level the current bounded
3961 * level. If there is no next highest level, then no bounded mode
3962 * is in effect.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003963 */
3964 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003965
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003966 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003967
3968Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003969 return uErr;
3970}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003971
Laurence Lundblade02625d42020-06-25 14:41:41 -07003972
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07003973/**
3974 * @brief Get started exiting a map or array (semi-private)
3975 *
3976 * @param[in] pMe The decode context
3977 * @param[in] uType QCBOR_TYPE_ARRAY or QCBOR_TYPE_MAP
3978 *
3979 * This does some work for map and array exiting (but not
3980 * bstr exiting). Then QCBORDecode_Private_ExitBoundedLevel()
3981 * is called to do the rest.
3982 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003983void
3984QCBORDecode_Private_ExitBoundedMapOrArray(QCBORDecodeContext *pMe,
3985 const uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003986{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003987 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003988 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003989 return;
3990 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003991
Laurence Lundblade02625d42020-06-25 14:41:41 -07003992 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003993
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003994 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003995 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003996 goto Done;
3997 }
3998
Laurence Lundblade02625d42020-06-25 14:41:41 -07003999 /*
4000 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004001 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07004002 from previous map search, then do a dummy search.
4003 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07004004 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004005 QCBORItem Dummy;
4006 Dummy.uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004007 uErr = QCBORDecode_Private_MapSearch(pMe, &Dummy, NULL, NULL, NULL);
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004008 if(uErr != QCBOR_SUCCESS) {
4009 goto Done;
4010 }
4011 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004012
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004013 uErr = QCBORDecode_Private_ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004014
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004015Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07004016 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07004017}
4018
4019
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004020/**
4021 * @brief The main work of entering some byte-string wrapped CBOR.
4022 *
4023 * @param[in] pMe The decode context.
4024 * @param[in] pItem The byte string item.
4025 * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX
4026 * @param[out] pBstr Pointer and length of byte string entered.
4027 *
4028 * This is called once the byte string item has been decoded to do all
4029 * the book keeping work for descending a nesting level into the
4030 * nested CBOR.
4031 *
4032 * See QCBORDecode_EnterBstrWrapped() for details on uTagRequirement.
4033 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07004034static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004035QCBORDecode_Private_EnterBstrWrapped(QCBORDecodeContext *pMe,
4036 const QCBORItem *pItem,
4037 const uint8_t uTagRequirement,
4038 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004039{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07004040 if(pBstr) {
4041 *pBstr = NULLUsefulBufC;
4042 }
4043
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004044 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004045 /* Already in error state; do nothing. */
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004046 return pMe->uLastError;
4047 }
4048
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004049 QCBORError uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004050
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004051 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004052 {
4053 uTagRequirement,
4054 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
4055 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4056 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004057
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004058 uError = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004059 if(uError != QCBOR_SUCCESS) {
4060 goto Done;
4061 }
4062
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004063 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004064 /* Reverse the decrement done by GetNext() for the bstr so the
4065 * increment in QCBORDecode_NestLevelAscender() called by
4066 * ExitBoundedLevel() will work right.
4067 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07004068 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07004069 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004070
4071 if(pBstr) {
4072 *pBstr = pItem->val.string;
4073 }
4074
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004075 /* This saves the current length of the UsefulInputBuf and then
4076 * narrows the UsefulInputBuf to start and length of the wrapped
4077 * CBOR that is being entered.
4078 *
4079 * Most of these calls are simple inline accessors so this doesn't
4080 * amount to much code.
4081 */
4082
Laurence Lundbladea4308a82020-10-03 18:08:57 -07004083 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004084 /* This check makes the cast of uPreviousLength to uint32_t below safe. */
4085 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07004086 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07004087 goto Done;
4088 }
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004089
4090 const size_t uStartOfBstr = UsefulInputBuf_PointerToOffset(&(pMe->InBuf),
4091 pItem->val.string.ptr);
4092 /* This check makes the cast of uStartOfBstr to uint32_t below safe. */
4093 if(uStartOfBstr == SIZE_MAX || uStartOfBstr > QCBOR_MAX_DECODE_INPUT_SIZE) {
4094 /* This should never happen because pItem->val.string.ptr should
4095 * always be valid since it was just returned.
4096 */
4097 uError = QCBOR_ERR_INPUT_TOO_LARGE;
4098 goto Done;
4099 }
4100
4101 const size_t uEndOfBstr = uStartOfBstr + pItem->val.string.len;
4102
4103 UsefulInputBuf_Seek(&(pMe->InBuf), uStartOfBstr);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07004104 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004105
Laurence Lundblade02625d42020-06-25 14:41:41 -07004106 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07004107 (uint32_t)uPreviousLength,
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004108 (uint32_t)uStartOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004109Done:
4110 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004111}
4112
4113
Laurence Lundblade02625d42020-06-25 14:41:41 -07004114/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004115 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07004116 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004117void
4118QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
4119 const uint8_t uTagRequirement,
4120 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07004121{
4122 if(pMe->uLastError != QCBOR_SUCCESS) {
4123 // Already in error state; do nothing.
4124 return;
4125 }
4126
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004127 /* Get the data item that is the byte string being entered */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004128 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07004129 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4130 if(pMe->uLastError != QCBOR_SUCCESS) {
4131 return;
4132 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07004133
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004134 pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
4135 &Item,
4136 uTagRequirement,
4137 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07004138}
4139
4140
Laurence Lundblade02625d42020-06-25 14:41:41 -07004141/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004142 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07004143 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004144void
4145QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
4146 const int64_t nLabel,
4147 const uint8_t uTagRequirement,
4148 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004149{
4150 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004151 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004152
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004153 pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
4154 &Item,
4155 uTagRequirement,
4156 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004157}
4158
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004159
Laurence Lundblade02625d42020-06-25 14:41:41 -07004160/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004161 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07004162 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004163void
4164QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
4165 const char *szLabel,
4166 const uint8_t uTagRequirement,
4167 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004168{
4169 QCBORItem Item;
4170 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4171
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004172 pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
4173 &Item,
4174 uTagRequirement,
4175 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07004176}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004177
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004178
Laurence Lundblade02625d42020-06-25 14:41:41 -07004179/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004180 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07004181 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004182void
4183QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004184{
Laurence Lundblade02625d42020-06-25 14:41:41 -07004185 if(pMe->uLastError != QCBOR_SUCCESS) {
4186 // Already in error state; do nothing.
4187 return;
4188 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004189
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07004190 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07004191 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07004192 return;
4193 }
4194
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004195 const uint32_t uEndOfBstr = (uint32_t)UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
4196
Laurence Lundblade02625d42020-06-25 14:41:41 -07004197 /*
4198 Reset the length of the UsefulInputBuf to what it was before
4199 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004200 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07004201 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004202 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004203
4204
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004205 QCBORError uErr = QCBORDecode_Private_ExitBoundedLevel(pMe, uEndOfBstr);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004206 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004207}
4208
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004209
Laurence Lundbladee6430642020-03-14 21:15:44 -07004210
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004211/**
4212 * @brief Process simple type true and false, a boolean
4213 *
4214 * @param[in] pMe The decode context.
4215 * @param[in] pItem The item with either true or false.
4216 * @param[out] pBool The boolean value output.
4217 *
4218 * Sets the internal error if the item isn't a true or a false. Also
4219 * records any tag numbers as the tag numbers of the last item.
4220 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004221static void
4222QCBORDecode_Private_ProcessBool(QCBORDecodeContext *pMe,
4223 const QCBORItem *pItem,
4224 bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004225{
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004226 if(pMe->uLastError != QCBOR_SUCCESS) {
4227 /* Already in error state, do nothing */
4228 return;
4229 }
4230
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004231 switch(pItem->uDataType) {
4232 case QCBOR_TYPE_TRUE:
4233 *pBool = true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004234 break;
4235
4236 case QCBOR_TYPE_FALSE:
4237 *pBool = false;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004238 break;
4239
4240 default:
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004241 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004242 break;
4243 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004244 QCBORDecode_Private_CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004245}
Laurence Lundbladee6430642020-03-14 21:15:44 -07004246
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004247
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004248/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004249 * Public function, see header qcbor/qcbor_decode.h file
4250 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004251void
4252QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004253{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004254 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004255 /* Already in error state, do nothing */
Laurence Lundbladee6430642020-03-14 21:15:44 -07004256 return;
4257 }
4258
Laurence Lundbladec4537442020-04-14 18:53:22 -07004259 QCBORItem Item;
4260
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004261 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4262
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004263 QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004264}
4265
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004266
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004267/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004268 * Public function, see header qcbor/qcbor_decode.h file
4269 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004270void
4271QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe,
4272 const int64_t nLabel,
4273 bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004274{
4275 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004276 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004277
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004278 QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004279}
4280
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004281
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004282/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004283 * Public function, see header qcbor/qcbor_decode.h file
4284 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004285void
4286QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe,
4287 const char *szLabel,
4288 bool *pValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004289{
4290 QCBORItem Item;
4291 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4292
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004293 QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004294}
4295
4296
4297
Laurence Lundbladec7114722020-08-13 05:11:40 -07004298
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004299/**
4300 * @brief Common processing for an epoch date.
4301 *
4302 * @param[in] pMe The decode context.
4303 * @param[in] pItem The item with the date.
4304 * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX.
4305 * @param[out] pnTime The returned date.
4306 *
4307 * Common processing for the date tag. Mostly make sure the tag
4308 * content is correct and copy forward any further other tag numbers.
4309 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004310static void
4311QCBORDecode_Private_ProcessEpochDate(QCBORDecodeContext *pMe,
4312 QCBORItem *pItem,
4313 const uint8_t uTagRequirement,
4314 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07004315{
4316 if(pMe->uLastError != QCBOR_SUCCESS) {
4317 // Already in error state, do nothing
4318 return;
4319 }
4320
4321 QCBORError uErr;
4322
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004323 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladec7114722020-08-13 05:11:40 -07004324 {
4325 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004326 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4327 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07004328 };
4329
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004330 uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004331 if(uErr != QCBOR_SUCCESS) {
4332 goto Done;
4333 }
4334
4335 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004336 uErr = QCBOR_Private_DecodeDateEpoch(pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004337 if(uErr != QCBOR_SUCCESS) {
4338 goto Done;
4339 }
4340 }
4341
Laurence Lundblade9b334962020-08-27 10:55:53 -07004342 // Save the tags in the last item's tags in the decode context
4343 // for QCBORDecode_GetNthTagOfLast()
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004344 QCBORDecode_Private_CopyTags(pMe, pItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07004345
Laurence Lundbladec7114722020-08-13 05:11:40 -07004346 *pnTime = pItem->val.epochDate.nSeconds;
4347
4348Done:
4349 pMe->uLastError = (uint8_t)uErr;
4350}
4351
4352
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004353
4354/*
4355 * Public function, see header qcbor/qcbor_spiffy_decode.h file
4356 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004357void
4358QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
4359 uint8_t uTagRequirement,
4360 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07004361{
4362 if(pMe->uLastError != QCBOR_SUCCESS) {
4363 // Already in error state, do nothing
4364 return;
4365 }
4366
4367 QCBORItem Item;
4368 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4369
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004370 QCBORDecode_Private_ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004371}
4372
4373
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004374/*
4375 * Public function, see header qcbor/qcbor_spiffy_decode.h file
4376 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07004377void
4378QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
4379 int64_t nLabel,
4380 uint8_t uTagRequirement,
4381 int64_t *pnTime)
4382{
4383 QCBORItem Item;
4384 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004385 QCBORDecode_Private_ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004386}
4387
4388
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004389/*
4390 * Public function, see header qcbor/qcbor_spiffy_decode.h file
4391 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07004392void
4393QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
4394 const char *szLabel,
4395 uint8_t uTagRequirement,
4396 int64_t *pnTime)
4397{
4398 QCBORItem Item;
4399 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004400 QCBORDecode_Private_ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004401}
4402
4403
4404
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004405/**
4406 * @brief Common processing for an epoch date.
4407 *
4408 * @param[in] pMe The decode context.
4409 * @param[in] pItem The item with the date.
4410 * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX.
4411 * @param[out] pnDays The returned day count.
4412 *
4413 * Common processing for the RFC 8943 day-count tag. Mostly make sure
4414 * the tag content is correct and copy forward any further other tag
4415 * numbers.
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004416 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004417static void
4418QCBORDecode_Private_ProcessEpochDays(QCBORDecodeContext *pMe,
4419 QCBORItem *pItem,
4420 uint8_t uTagRequirement,
4421 int64_t *pnDays)
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004422{
4423 if(pMe->uLastError != QCBOR_SUCCESS) {
4424 /* Already in error state, do nothing */
4425 return;
4426 }
4427
4428 QCBORError uErr;
4429
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004430 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004431 {
4432 uTagRequirement,
4433 {QCBOR_TYPE_DAYS_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4434 {QCBOR_TYPE_INT64, QCBOR_TYPE_UINT64, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4435 };
4436
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004437 uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004438 if(uErr != QCBOR_SUCCESS) {
4439 goto Done;
4440 }
4441
4442 if(pItem->uDataType != QCBOR_TYPE_DAYS_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004443 uErr = QCBOR_Private_DecodeDaysEpoch(pItem);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004444 if(uErr != QCBOR_SUCCESS) {
4445 goto Done;
4446 }
4447 }
4448
4449 /* Save the tags in the last item's tags in the decode context
4450 * for QCBORDecode_GetNthTagOfLast()
4451 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004452 QCBORDecode_Private_CopyTags(pMe, pItem);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004453
4454 *pnDays = pItem->val.epochDays;
4455
4456Done:
4457 pMe->uLastError = (uint8_t)uErr;
4458}
4459
4460
4461/*
4462 * Public function, see header qcbor/qcbor_decode.h
4463 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004464void
4465QCBORDecode_GetEpochDays(QCBORDecodeContext *pMe,
4466 uint8_t uTagRequirement,
4467 int64_t *pnDays)
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004468{
4469 if(pMe->uLastError != QCBOR_SUCCESS) {
4470 /* Already in error state, do nothing */
4471 return;
4472 }
4473
4474 QCBORItem Item;
4475 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4476
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004477 QCBORDecode_Private_ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004478}
4479
4480
4481/*
4482 * Public function, see header qcbor/qcbor_decode.h
4483 */
4484void
4485QCBORDecode_GetEpochDaysInMapN(QCBORDecodeContext *pMe,
4486 int64_t nLabel,
4487 uint8_t uTagRequirement,
4488 int64_t *pnDays)
4489{
4490 QCBORItem Item;
4491 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004492 QCBORDecode_Private_ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004493}
4494
4495
4496/*
4497 * Public function, see header qcbor/qcbor_decode.h
4498 */
4499void
4500QCBORDecode_GetEpochDaysInMapSZ(QCBORDecodeContext *pMe,
4501 const char *szLabel,
4502 uint8_t uTagRequirement,
4503 int64_t *pnDays)
4504{
4505 QCBORItem Item;
4506 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004507 QCBORDecode_Private_ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004508}
4509
4510
4511
Laurence Lundblade37286c02022-09-03 10:05:02 -07004512/*
4513 * @brief Get a string that matches the type/tag specification.
4514 */
4515void
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004516QCBORDecode_Private_GetTaggedString(QCBORDecodeContext *pMe,
4517 const QCBOR_Private_TagSpec TagSpec,
4518 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004519{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004520 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade37286c02022-09-03 10:05:02 -07004521 /* Already in error state, do nothing */
Laurence Lundbladec4537442020-04-14 18:53:22 -07004522 return;
4523 }
4524
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004525 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004526 QCBORItem Item;
4527
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004528 uError = QCBORDecode_GetNext(pMe, &Item);
4529 if(uError != QCBOR_SUCCESS) {
4530 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004531 return;
4532 }
4533
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004534 pMe->uLastError = (uint8_t)QCBOR_Private_CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004535
4536 if(pMe->uLastError == QCBOR_SUCCESS) {
4537 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07004538 } else {
4539 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004540 }
4541}
4542
Laurence Lundbladec4537442020-04-14 18:53:22 -07004543
4544
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004545
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004546/**
4547 * @brief Common processing for a big number tag.
4548 *
4549 * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX.
4550 * @param[in] pItem The item with the date.
4551 * @param[out] pValue The returned big number
4552 * @param[out] pbIsNegative The returned sign of the big number.
4553 *
4554 * Common processing for the big number tag. Mostly make sure
4555 * the tag content is correct and copy forward any further other tag
4556 * numbers.
4557 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07004558static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004559QCBOR_Private_ProcessBigNum(const uint8_t uTagRequirement,
4560 const QCBORItem *pItem,
4561 UsefulBufC *pValue,
4562 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004563{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004564 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004565 {
4566 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004567 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4568 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004569 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004570
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004571 QCBORError uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004572 if(uErr != QCBOR_SUCCESS) {
4573 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004574 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004575
4576 *pValue = pItem->val.string;
4577
4578 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
4579 *pbIsNegative = false;
4580 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
4581 *pbIsNegative = true;
4582 }
4583
4584 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004585}
4586
4587
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004588/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004589 * Public function, see header qcbor/qcbor_spiffy_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004590 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004591void
4592QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
4593 const uint8_t uTagRequirement,
4594 UsefulBufC *pValue,
4595 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004596{
4597 if(pMe->uLastError != QCBOR_SUCCESS) {
4598 // Already in error state, do nothing
4599 return;
4600 }
4601
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004602 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004603 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4604 if(uError != QCBOR_SUCCESS) {
4605 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004606 return;
4607 }
4608
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004609 pMe->uLastError = (uint8_t)QCBOR_Private_ProcessBigNum(uTagRequirement,
4610 &Item,
4611 pValue,
4612 pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004613}
4614
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004615
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004616/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004617 * Public function, see header qcbor/qcbor_spiffy_decode.h
4618 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004619void
4620QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
4621 const int64_t nLabel,
4622 const uint8_t uTagRequirement,
4623 UsefulBufC *pValue,
4624 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004625{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004626 QCBORItem Item;
4627 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004628 if(pMe->uLastError != QCBOR_SUCCESS) {
4629 return;
4630 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004631
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004632 pMe->uLastError = (uint8_t)QCBOR_Private_ProcessBigNum(uTagRequirement,
4633 &Item,
4634 pValue,
4635 pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004636}
4637
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004638
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004639/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004640 * Public function, see header qcbor/qcbor_spiffy_decode.h
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004641 */
4642void
4643QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
4644 const char *szLabel,
4645 const uint8_t uTagRequirement,
4646 UsefulBufC *pValue,
4647 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004648{
4649 QCBORItem Item;
4650 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004651 if(pMe->uLastError != QCBOR_SUCCESS) {
4652 return;
4653 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004654
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004655 pMe->uLastError = (uint8_t)QCBOR_Private_ProcessBigNum(uTagRequirement,
4656 &Item,
4657 pValue,
4658 pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004659}
4660
4661
4662
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004663/**
4664 * @brief Common processing for MIME tag (semi-private).
4665 *
4666 * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX.
4667 * @param[in] pItem The item with the date.
4668 * @param[out] pMessage The returned MIME message.
4669 * @param[out] pbIsTag257 If true, binary MIME, if not, text MIME.
4670 *
4671 * Common processing for the MIME tag. Mostly make sure the tag
4672 * content is correct and copy forward any further other tag
4673 * numbers. See QCBORDecode_GetMIMEMessage().
4674 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07004675QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004676QCBORDecode_Private_GetMIME(const uint8_t uTagRequirement,
Laurence Lundblade37286c02022-09-03 10:05:02 -07004677 const QCBORItem *pItem,
4678 UsefulBufC *pMessage,
4679 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004680{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004681 const QCBOR_Private_TagSpec TagSpecText =
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004682 {
4683 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004684 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4685 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004686 };
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004687 const QCBOR_Private_TagSpec TagSpecBinary =
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004688 {
4689 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004690 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4691 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004692 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004693
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004694 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07004695
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004696 if(QCBOR_Private_CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004697 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004698 if(pbIsTag257 != NULL) {
4699 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004700 }
4701 uReturn = QCBOR_SUCCESS;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004702 } else if(QCBOR_Private_CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004703 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004704 if(pbIsTag257 != NULL) {
4705 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004706 }
4707 uReturn = QCBOR_SUCCESS;
4708
4709 } else {
4710 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
4711 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07004712
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004713 return uReturn;
4714}
4715
Laurence Lundblade93d89472020-10-03 22:30:50 -07004716// Improvement: add methods for wrapped CBOR, a simple alternate
4717// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004718
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004719
4720
4721
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004722#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07004723
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07004724/**
4725 * @brief Prototype for conversion of exponent and mantissa to unsigned integer.
4726 *
4727 * @param[in] uMantissa The mantissa.
4728 * @param[in] nExponent The exponent.
4729 * @param[out] puResult The resulting integer.
4730 *
4731 * Concrete implementations of this are for exponent base 10 and 2 supporting
4732 * decimal fractions and big floats.
4733 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004734typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004735
4736
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004737/**
4738 * @brief Base 10 exponentiate a mantissa and exponent into an unsigned 64-bit integer.
4739 *
4740 * @param[in] uMantissa The unsigned integer mantissa.
4741 * @param[in] nExponent The signed integer exponent.
4742 * @param[out] puResult Place to return the unsigned integer result.
4743 *
4744 * This computes: mantissa * 10 ^^ exponent as for a decimal fraction. The output is a 64-bit
4745 * unsigned integer.
4746 *
4747 * There are many inputs for which the result will not fit in the
4748 * 64-bit integer and \ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will
4749 * be returned.
4750 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004751static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004752QCBOR_Private_Exponentitate10(const uint64_t uMantissa,
4753 int64_t nExponent,
4754 uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004755{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004756 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004757
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004758 if(uResult != 0) {
4759 /* This loop will run a maximum of 19 times because
4760 * UINT64_MAX < 10 ^^ 19. More than that will cause
4761 * exit with the overflow error
4762 */
4763 for(; nExponent > 0; nExponent--) {
4764 if(uResult > UINT64_MAX / 10) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004765 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004766 }
4767 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004768 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004769
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004770 for(; nExponent < 0; nExponent++) {
4771 uResult = uResult / 10;
4772 if(uResult == 0) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004773 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004774 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004775 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004776 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004777 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07004778
4779 *puResult = uResult;
4780
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004781 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004782}
4783
4784
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004785/**
4786 * @brief Base 2 exponentiate a mantissa and exponent into an unsigned 64-bit integer.
4787 *
4788 * @param[in] uMantissa The unsigned integer mantissa.
4789 * @param[in] nExponent The signed integer exponent.
4790 * @param[out] puResult Place to return the unsigned integer result.
4791 *
4792 * This computes: mantissa * 2 ^^ exponent as for a big float. The
4793 * output is a 64-bit unsigned integer.
4794 *
4795 * There are many inputs for which the result will not fit in the
4796 * 64-bit integer and \ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will
4797 * be returned.
4798 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004799static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004800QCBOR_Private_Exponentitate2(const uint64_t uMantissa,
4801 int64_t nExponent,
4802 uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004803{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004804 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004805
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004806 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004807
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004808 /* This loop will run a maximum of 64 times because INT64_MAX <
4809 * 2^31. More than that will cause exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07004810 */
4811 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004812 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004813 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004814 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004815 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004816 nExponent--;
4817 }
4818
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004819 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004820 if(uResult == 0) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004821 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004822 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004823 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004824 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004825 }
4826
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004827 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004828
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004829 return QCBOR_SUCCESS;
4830}
4831
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004832
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004833/**
4834 * @brief Exponentiate a signed mantissa and signed exponent to produce a signed result.
4835 *
4836 * @param[in] nMantissa Signed integer mantissa.
4837 * @param[in] nExponent Signed integer exponent.
4838 * @param[out] pnResult Place to put the signed integer result.
4839 * @param[in] pfExp Exponentiation function.
4840 *
4841 * @returns Error code
4842 *
4843 * \c pfExp performs exponentiation on and unsigned mantissa and
4844 * produces an unsigned result. This converts the mantissa from signed
4845 * and converts the result to signed. The exponentiation function is
4846 * either for base 2 or base 10 (and could be other if needed).
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004847 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004848static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004849QCBOR_Private_ExponentiateNN(const int64_t nMantissa,
4850 const int64_t nExponent,
4851 int64_t *pnResult,
4852 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004853{
4854 uint64_t uResult;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004855 uint64_t uMantissa;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004856
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004857 /* Take the absolute value and put it into an unsigned. */
4858 if(nMantissa >= 0) {
4859 /* Positive case is straightforward */
4860 uMantissa = (uint64_t)nMantissa;
4861 } else if(nMantissa != INT64_MIN) {
4862 /* The common negative case. See next. */
4863 uMantissa = (uint64_t)-nMantissa;
4864 } else {
4865 /* int64_t and uint64_t are always two's complement per the
4866 * C standard (and since QCBOR uses these it only works with
4867 * two's complement, which is pretty much universal these
4868 * days). The range of a negative two's complement integer is
4869 * one more that than a positive, so the simple code above might
4870 * not work all the time because you can't simply negate the
4871 * value INT64_MIN because it can't be represented in an
4872 * int64_t. -INT64_MIN can however be represented in a
4873 * uint64_t. Some compilers seem to recognize this case for the
4874 * above code and put the correct value in uMantissa, however
4875 * they are not required to do this by the C standard. This next
4876 * line does however work for all compilers.
4877 *
4878 * This does assume two's complement where -INT64_MIN ==
4879 * INT64_MAX + 1 (which wouldn't be true for one's complement or
4880 * sign and magnitude (but we know we're using two's complement
4881 * because int64_t requires it)).
4882 *
4883 * See these, particularly the detailed commentary:
4884 * https://stackoverflow.com/questions/54915742/does-c99-mandate-a-int64-t-type-be-available-always
4885 * https://stackoverflow.com/questions/37301078/is-negating-int-min-undefined-behaviour
4886 */
4887 uMantissa = (uint64_t)INT64_MAX+1;
4888 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004889
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004890 /* Call the exponentiator passed for either base 2 or base 10.
4891 * Here is where most of the overflow errors are caught. */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004892 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
4893 if(uReturn) {
4894 return uReturn;
4895 }
4896
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004897 /* Convert back to the sign of the original mantissa */
4898 if(nMantissa >= 0) {
4899 if(uResult > INT64_MAX) {
4900 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4901 }
4902 *pnResult = (int64_t)uResult;
4903 } else {
4904 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
4905 * of INT64_MIN. This assumes two's compliment representation
4906 * where INT64_MIN is one increment farther from 0 than
4907 * INT64_MAX. Trying to write -INT64_MIN doesn't work to get
4908 * this because the compiler makes it an int64_t which can't
4909 * represent -INT64_MIN. Also see above.
4910 */
4911 if(uResult > (uint64_t)INT64_MAX+1) {
4912 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4913 }
4914 *pnResult = -(int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004915 }
4916
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004917 return QCBOR_SUCCESS;
4918}
4919
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004920
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004921/**
4922 * @brief Exponentiate an unsigned mantissa and signed exponent to produce an unsigned result.
4923 *
4924 * @param[in] nMantissa Signed integer mantissa.
4925 * @param[in] nExponent Signed integer exponent.
4926 * @param[out] puResult Place to put the signed 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. This errors out if the mantissa
4933 * is negative because the output is unsigned.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004934 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004935static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004936QCBOR_Private_ExponentitateNU(const int64_t nMantissa,
4937 const int64_t nExponent,
4938 uint64_t *puResult,
4939 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004940{
4941 if(nMantissa < 0) {
4942 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4943 }
4944
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004945 /* Cast to unsigned is OK because of check for negative.
4946 * Cast to unsigned is OK because UINT64_MAX > INT64_MAX.
4947 * Exponentiation is straight forward
4948 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004949 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
4950}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004951
4952
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004953/**
4954 * @brief Exponentiate an usnigned mantissa and unsigned exponent to produce an unsigned result.
4955 *
4956 * @param[in] uMantissa Unsigned integer mantissa.
4957 * @param[in] nExponent Unsigned integer exponent.
4958 * @param[out] puResult Place to put the unsigned integer result.
4959 * @param[in] pfExp Exponentiation function.
4960 *
4961 * @returns Error code
4962 *
4963 * \c pfExp performs exponentiation on and unsigned mantissa and
4964 * produces an unsigned result so this is just a wrapper that does
4965 * nothing (and is likely inlined).
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004966 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004967static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004968QCBOR_Private_ExponentitateUU(const uint64_t uMantissa,
4969 const int64_t nExponent,
4970 uint64_t *puResult,
4971 fExponentiator pfExp)
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004972{
4973 return (*pfExp)(uMantissa, nExponent, puResult);
4974}
4975
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004976#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004977
4978
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004979
4980
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004981/**
4982 * @brief Convert a CBOR big number to a uint64_t.
4983 *
4984 * @param[in] BigNum Bytes of the big number to convert.
4985 * @param[in] uMax Maximum value allowed for the result.
4986 * @param[out] pResult Place to put the unsigned integer result.
4987 *
4988 * @returns Error code
4989 *
4990 * Many values will overflow because a big num can represent a much
4991 * larger range than uint64_t.
4992 */
4993static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004994QCBOR_Private_ConvertBigNumToUnsigned(const UsefulBufC BigNum,
4995 const uint64_t uMax,
4996 uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004997{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004998 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004999
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005000 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005001 const uint8_t *pByte = BigNum.ptr;
5002 size_t uLen = BigNum.len;
5003 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07005004 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07005005 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005006 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07005007 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005008 }
5009
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005010 *pResult = uResult;
5011 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005012}
5013
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005014
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005015/**
5016 * @brief Convert a CBOR postive big number to a uint64_t.
5017 *
5018 * @param[in] BigNum Bytes of the big number to convert.
5019 * @param[out] pResult Place to put the unsigned integer result.
5020 *
5021 * @returns Error code
5022 *
5023 * Many values will overflow because a big num can represent a much
5024 * larger range than uint64_t.
5025 */
5026static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005027QCBOR_Private_ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum,
5028 uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005029{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005030 return QCBOR_Private_ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005031}
5032
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005033
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005034/**
5035 * @brief Convert a CBOR positive big number to an int64_t.
5036 *
5037 * @param[in] BigNum Bytes of the big number to convert.
5038 * @param[out] pResult Place to put the signed integer result.
5039 *
5040 * @returns Error code
5041 *
5042 * Many values will overflow because a big num can represent a much
5043 * larger range than int64_t.
5044 */
5045static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005046QCBOR_Private_ConvertPositiveBigNumToSigned(const UsefulBufC BigNum,
5047 int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005048{
5049 uint64_t uResult;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005050 QCBORError uError = QCBOR_Private_ConvertBigNumToUnsigned(BigNum,
5051 INT64_MAX,
5052 &uResult);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005053 if(uError) {
5054 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005055 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005056 /* Cast is safe because ConvertBigNumToUnsigned limits to INT64_MAX */
Laurence Lundbladee6430642020-03-14 21:15:44 -07005057 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005058 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005059}
5060
5061
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005062/**
5063 * @brief Convert a CBOR negative big number to an int64_t.
5064 *
5065 * @param[in] BigNum Bytes of the big number to convert.
5066 * @param[out] pnResult Place to put the signed integer result.
5067 *
5068 * @returns Error code
5069 *
5070 * Many values will overflow because a big num can represent a much
5071 * larger range than int64_t.
5072 */
5073static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005074QCBOR_Private_ConvertNegativeBigNumToSigned(const UsefulBufC BigNum,
5075 int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005076{
5077 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005078 /* The negative integer furthest from zero for a C int64_t is
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005079 * INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
5080 * negative number in CBOR is computed as -n - 1 where n is the
5081 * encoded integer, where n is what is in the variable BigNum. When
5082 * converting BigNum to a uint64_t, the maximum value is thus
5083 * INT64_MAX, so that when it -n - 1 is applied to it the result
5084 * will never be further from 0 than INT64_MIN.
5085 *
5086 * -n - 1 <= INT64_MIN.
5087 * -n - 1 <= -INT64_MAX - 1
5088 * n <= INT64_MAX.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005089 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005090 QCBORError uError = QCBOR_Private_ConvertBigNumToUnsigned(BigNum,
5091 INT64_MAX,
5092 &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005093 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005094 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005095 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005096
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005097 /* Now apply -n - 1. The cast is safe because
5098 * ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
5099 * is the largest positive integer that an int64_t can
5100 * represent. */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005101 *pnResult = -(int64_t)uResult - 1;
5102
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005103 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005104}
5105
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005106
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005107
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005108
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005109/**
5110 * @brief Convert integers and floats to an int64_t.
5111 *
5112 * @param[in] pItem The item to convert.
5113 * @param[in] uConvertTypes Bit mask list of conversion options.
5114 * @param[out] pnValue The resulting converted value.
5115 *
5116 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
5117 * in uConvertTypes.
5118 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
5119 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
5120 * or too small.
5121 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07005122static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005123QCBOR_Private_ConvertInt64(const QCBORItem *pItem,
5124 const uint32_t uConvertTypes,
5125 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005126{
5127 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005128 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005129 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005130#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005131 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005132 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
5133 http://www.cplusplus.com/reference/cmath/llround/
5134 */
5135 // Not interested in FE_INEXACT
5136 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005137 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
5138 *pnValue = llround(pItem->val.dfnum);
5139 } else {
5140 *pnValue = lroundf(pItem->val.fnum);
5141 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005142 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
5143 // llround() shouldn't result in divide by zero, but catch
5144 // it here in case it unexpectedly does. Don't try to
5145 // distinguish between the various exceptions because it seems
5146 // they vary by CPU, compiler and OS.
5147 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005148 }
5149 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005150 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005151 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005152#else
5153 return QCBOR_ERR_HW_FLOAT_DISABLED;
5154#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005155 break;
5156
5157 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005158 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005159 *pnValue = pItem->val.int64;
5160 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005161 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005162 }
5163 break;
5164
5165 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005166 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005167 if(pItem->val.uint64 < INT64_MAX) {
5168 *pnValue = pItem->val.int64;
5169 } else {
5170 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5171 }
5172 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005173 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005174 }
5175 break;
5176
5177 default:
5178 return QCBOR_ERR_UNEXPECTED_TYPE;
5179 }
5180 return QCBOR_SUCCESS;
5181}
5182
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005183
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005184/**
5185 * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
5186 *
5187 * @param[in] pMe The decode context.
5188 * @param[in] uConvertTypes Bit mask list of conversion options.
5189 * @param[out] pnValue Result of the conversion.
5190 * @param[in,out] pItem Temporary space to store Item, returned item.
5191 *
5192 * See QCBORDecode_GetInt64Convert().
5193 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005194void
5195QCBORDecode_Private_GetInt64Convert(QCBORDecodeContext *pMe,
5196 uint32_t uConvertTypes,
5197 int64_t *pnValue,
5198 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005199{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07005200 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07005201 return;
5202 }
5203
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005204 QCBORError uError = QCBORDecode_GetNext(pMe, pItem);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005205 if(uError) {
5206 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005207 return;
5208 }
5209
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005210 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005211 uConvertTypes,
5212 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005213}
5214
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005215/**
5216 * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
5217 *
5218 * @param[in] pMe The decode context.
5219 * @param[in] nLabel Label to find in map.
5220 * @param[in] uConvertTypes Bit mask list of conversion options.
5221 * @param[out] pnValue Result of the conversion.
5222 * @param[in,out] pItem Temporary space to store Item, returned item.
5223 *
5224 * See QCBORDecode_GetInt64ConvertInMapN().
5225 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005226void
5227QCBORDecode_Private_GetInt64ConvertInMapN(QCBORDecodeContext *pMe,
5228 int64_t nLabel,
5229 uint32_t uConvertTypes,
5230 int64_t *pnValue,
5231 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005232{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005233 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005234 if(pMe->uLastError != QCBOR_SUCCESS) {
5235 return;
5236 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005237
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005238 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
5239 uConvertTypes,
5240 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005241}
5242
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005243/**
5244 * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
5245 *
5246 * @param[in] pMe The decode context.
5247 * @param[in] szLabel Label to find in map.
5248 * @param[in] uConvertTypes Bit mask list of conversion options.
5249 * @param[out] pnValue Result of the conversion.
5250 * @param[in,out] pItem Temporary space to store Item, returned item.
5251 *
5252 * See QCBORDecode_GetInt64ConvertInMapSZ().
5253 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005254void
5255QCBORDecode_Private_GetInt64ConvertInMapSZ(QCBORDecodeContext *pMe,
5256 const char * szLabel,
5257 uint32_t uConvertTypes,
5258 int64_t *pnValue,
5259 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005260{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005261 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005262 if(pMe->uLastError != QCBOR_SUCCESS) {
5263 return;
5264 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005265
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005266 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
5267 uConvertTypes,
5268 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005269}
5270
5271
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005272/**
5273 * @brief Convert many number types to an int64_t.
5274 *
5275 * @param[in] pItem The item to convert.
5276 * @param[in] uConvertTypes Bit mask list of conversion options.
5277 * @param[out] pnValue The resulting converted value.
5278 *
5279 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
5280 * in uConvertTypes.
5281 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
5282 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
5283 * or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005284 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07005285static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005286QCBOR_Private_Int64ConvertAll(const QCBORItem *pItem,
5287 const uint32_t uConvertTypes,
5288 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005289{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005290 switch(pItem->uDataType) {
5291
5292 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005293 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005294 return QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005295 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005296 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005297 }
5298 break;
5299
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005300 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005301 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005302 return QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005303 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005304 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005305 }
5306 break;
5307
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005308#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005309 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005310 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005311 return QCBOR_Private_ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005312 pItem->val.expAndMantissa.nExponent,
5313 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005314 &QCBOR_Private_Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005315 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005316 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005317 }
5318 break;
5319
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005320 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005321 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005322 return QCBOR_Private_ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005323 pItem->val.expAndMantissa.nExponent,
5324 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005325 QCBOR_Private_Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005326 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005327 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005328 }
5329 break;
5330
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005331 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005332 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005333 int64_t nMantissa;
5334 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005335 uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005336 if(uErr) {
5337 return uErr;
5338 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005339 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005340 pItem->val.expAndMantissa.nExponent,
5341 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005342 QCBOR_Private_Exponentitate10);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005343 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005344 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005345 }
5346 break;
5347
5348 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005349 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005350 int64_t nMantissa;
5351 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005352 uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005353 if(uErr) {
5354 return uErr;
5355 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005356 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005357 pItem->val.expAndMantissa.nExponent,
5358 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005359 QCBOR_Private_Exponentitate10);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005360 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005361 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005362 }
5363 break;
5364
5365 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005366 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005367 int64_t nMantissa;
5368 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005369 uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005370 if(uErr) {
5371 return uErr;
5372 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005373 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005374 pItem->val.expAndMantissa.nExponent,
5375 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005376 QCBOR_Private_Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005377 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005378 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005379 }
5380 break;
5381
5382 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005383 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005384 int64_t nMantissa;
5385 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005386 uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005387 if(uErr) {
5388 return uErr;
5389 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005390 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005391 pItem->val.expAndMantissa.nExponent,
5392 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005393 QCBOR_Private_Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005394 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005395 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005396 }
5397 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005398#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005399
Laurence Lundbladee6430642020-03-14 21:15:44 -07005400
Laurence Lundbladec4537442020-04-14 18:53:22 -07005401 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005402 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005403}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005404
5405
Laurence Lundbladec4537442020-04-14 18:53:22 -07005406/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005407 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005408 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005409void
5410QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe,
5411 const uint32_t uConvertTypes,
5412 int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07005413{
5414 QCBORItem Item;
5415
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005416 QCBORDecode_Private_GetInt64Convert(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07005417
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005418 if(pMe->uLastError == QCBOR_SUCCESS) {
5419 // The above conversion succeeded
5420 return;
5421 }
5422
Laurence Lundbladef6c86662020-05-12 02:08:00 -07005423 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005424 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07005425 return;
5426 }
5427
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005428 pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
5429 uConvertTypes,
5430 pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005431}
5432
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005433
5434/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005435 * Public function, see header qcbor/qcbor_decode.h file
5436 */
5437void
5438QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
5439 const int64_t nLabel,
5440 const uint32_t uConvertTypes,
5441 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005442{
5443 QCBORItem Item;
5444
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005445 QCBORDecode_Private_GetInt64ConvertInMapN(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07005446 nLabel,
5447 uConvertTypes,
5448 pnValue,
5449 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005450
5451 if(pMe->uLastError == QCBOR_SUCCESS) {
5452 // The above conversion succeeded
5453 return;
5454 }
5455
5456 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5457 // The above conversion failed in a way that code below can't correct
5458 return;
5459 }
5460
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005461 pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
5462 uConvertTypes,
5463 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005464}
5465
5466
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005467/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005468 * Public function, see header qcbor/qcbor_decode.h file
5469 */
5470void
5471QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
5472 const char *szLabel,
5473 const uint32_t uConvertTypes,
5474 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005475{
5476 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005477 QCBORDecode_Private_GetInt64ConvertInMapSZ(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07005478 szLabel,
5479 uConvertTypes,
5480 pnValue,
5481 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005482
5483 if(pMe->uLastError == QCBOR_SUCCESS) {
5484 // The above conversion succeeded
5485 return;
5486 }
5487
5488 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5489 // The above conversion failed in a way that code below can't correct
5490 return;
5491 }
5492
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005493 pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
5494 uConvertTypes,
5495 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005496}
5497
5498
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005499/**
5500 * @brief Convert many number types to an uint64_t.
5501 *
5502 * @param[in] pItem The item to convert.
5503 * @param[in] uConvertTypes Bit mask list of conversion options.
5504 * @param[out] puValue The resulting converted value.
5505 *
5506 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
5507 * in uConvertTypes.
5508 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
5509 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
5510 * or too small.
5511 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005512static QCBORError
5513QCBOR_Private_ConvertUInt64(const QCBORItem *pItem,
5514 const uint32_t uConvertTypes,
5515 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005516{
5517 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005518 case QCBOR_TYPE_DOUBLE:
5519 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005520#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005521 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005522 // Can't use llround here because it will not convert values
5523 // greater than INT64_MAX and less than UINT64_MAX that
5524 // need to be converted so it is more complicated.
5525 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
5526 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
5527 if(isnan(pItem->val.dfnum)) {
5528 return QCBOR_ERR_FLOAT_EXCEPTION;
5529 } else if(pItem->val.dfnum < 0) {
5530 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5531 } else {
5532 double dRounded = round(pItem->val.dfnum);
5533 // See discussion in DecodeDateEpoch() for
5534 // explanation of - 0x7ff
5535 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
5536 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5537 }
5538 *puValue = (uint64_t)dRounded;
5539 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005540 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005541 if(isnan(pItem->val.fnum)) {
5542 return QCBOR_ERR_FLOAT_EXCEPTION;
5543 } else if(pItem->val.fnum < 0) {
5544 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5545 } else {
5546 float fRounded = roundf(pItem->val.fnum);
5547 // See discussion in DecodeDateEpoch() for
5548 // explanation of - 0x7ff
5549 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
5550 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5551 }
5552 *puValue = (uint64_t)fRounded;
5553 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005554 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005555 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
5556 // round() and roundf() shouldn't result in exceptions here, but
5557 // catch them to be robust and thorough. Don't try to
5558 // distinguish between the various exceptions because it seems
5559 // they vary by CPU, compiler and OS.
5560 return QCBOR_ERR_FLOAT_EXCEPTION;
5561 }
5562
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005563 } else {
5564 return QCBOR_ERR_UNEXPECTED_TYPE;
5565 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005566#else
5567 return QCBOR_ERR_HW_FLOAT_DISABLED;
5568#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005569 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005570
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005571 case QCBOR_TYPE_INT64:
5572 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
5573 if(pItem->val.int64 >= 0) {
5574 *puValue = (uint64_t)pItem->val.int64;
5575 } else {
5576 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5577 }
5578 } else {
5579 return QCBOR_ERR_UNEXPECTED_TYPE;
5580 }
5581 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005582
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005583 case QCBOR_TYPE_UINT64:
5584 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
5585 *puValue = pItem->val.uint64;
5586 } else {
5587 return QCBOR_ERR_UNEXPECTED_TYPE;
5588 }
5589 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005590
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005591 default:
5592 return QCBOR_ERR_UNEXPECTED_TYPE;
5593 }
5594
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005595 return QCBOR_SUCCESS;
5596}
Laurence Lundbladec4537442020-04-14 18:53:22 -07005597
5598
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005599/**
5600 * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
5601 *
5602 * @param[in] pMe The decode context.
5603 * @param[in] uConvertTypes Bit mask list of conversion options.
5604 * @param[out] puValue Result of the conversion.
5605 * @param[in,out] pItem Temporary space to store Item, returned item.
5606 *
5607 * See QCBORDecode_GetUInt64Convert().
5608 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005609void
5610QCBORDecode_Private_GetUInt64Convert(QCBORDecodeContext *pMe,
5611 const uint32_t uConvertTypes,
5612 uint64_t *puValue,
5613 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07005614{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005615 if(pMe->uLastError != QCBOR_SUCCESS) {
5616 return;
5617 }
5618
Laurence Lundbladec4537442020-04-14 18:53:22 -07005619 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005620
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005621 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5622 if(uError) {
5623 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005624 return;
5625 }
5626
Laurence Lundbladea826c502020-05-10 21:07:00 -07005627 if(pItem) {
5628 *pItem = Item;
5629 }
5630
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005631 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(&Item,
5632 uConvertTypes,
5633 puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07005634}
5635
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005636
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005637/**
5638 * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
5639 *
5640 * @param[in] pMe The decode context.
5641 * @param[in] nLabel Label to find in map.
5642 * @param[in] uConvertTypes Bit mask list of conversion options.
5643 * @param[out] puValue Result of the conversion.
5644 * @param[in,out] pItem Temporary space to store Item, returned item.
5645 *
5646 * See QCBORDecode_GetUInt64ConvertInMapN().
5647 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005648void
5649QCBORDecode_Private_GetUInt64ConvertInMapN(QCBORDecodeContext *pMe,
5650 const int64_t nLabel,
5651 const uint32_t uConvertTypes,
5652 uint64_t *puValue,
5653 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005654{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005655 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005656 if(pMe->uLastError != QCBOR_SUCCESS) {
5657 return;
5658 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005659
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005660 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
5661 uConvertTypes,
5662 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005663}
5664
5665
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005666/**
5667 * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
5668 *
5669 * @param[in] pMe The decode context.
5670 * @param[in] szLabel Label to find in map.
5671 * @param[in] uConvertTypes Bit mask list of conversion options.
5672 * @param[out] puValue Result of the conversion.
5673 * @param[in,out] pItem Temporary space to store Item, returned item.
5674 *
5675 * See QCBORDecode_GetUInt64ConvertInMapSZ().
5676 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005677void
5678QCBORDecode_Private_GetUInt64ConvertInMapSZ(QCBORDecodeContext *pMe,
5679 const char *szLabel,
5680 const uint32_t uConvertTypes,
5681 uint64_t *puValue,
5682 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005683{
5684 if(pMe->uLastError != QCBOR_SUCCESS) {
5685 return;
5686 }
5687
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005688 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005689 if(pMe->uLastError != QCBOR_SUCCESS) {
5690 return;
5691 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005692
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005693 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
5694 uConvertTypes,
5695 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005696}
5697
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005698
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005699/**
5700 * @brief Convert many number types to an unt64_t.
5701 *
5702 * @param[in] pItem The item to convert.
5703 * @param[in] uConvertTypes Bit mask list of conversion options.
5704 * @param[out] puValue The resulting converted value.
5705 *
5706 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
5707 * in uConvertTypes.
5708 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
5709 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
5710 * or too small.
5711 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07005712static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005713QCBOR_Private_UInt64ConvertAll(const QCBORItem *pItem,
5714 const uint32_t uConvertTypes,
5715 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005716{
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08005717 switch(pItem->uDataType) { /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005718
5719 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005720 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005721 return QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005722 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005723 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005724 }
5725 break;
5726
5727 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005728 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005729 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5730 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005731 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005732 }
5733 break;
5734
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005735#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005736
5737 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005738 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005739 return QCBOR_Private_ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005740 pItem->val.expAndMantissa.nExponent,
5741 puValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005742 QCBOR_Private_Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005743 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005744 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005745 }
5746 break;
5747
5748 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005749 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005750 return QCBOR_Private_ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005751 pItem->val.expAndMantissa.nExponent,
5752 puValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005753 QCBOR_Private_Exponentitate2);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005754 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005755 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005756 }
5757 break;
5758
5759 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005760 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005761 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005762 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005763 uErr = QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005764 if(uErr != QCBOR_SUCCESS) {
5765 return uErr;
5766 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005767 return QCBOR_Private_ExponentitateUU(uMantissa,
5768 pItem->val.expAndMantissa.nExponent,
5769 puValue,
5770 QCBOR_Private_Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005771 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005772 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005773 }
5774 break;
5775
5776 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005777 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005778 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5779 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005780 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005781 }
5782 break;
5783
5784 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005785 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005786 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005787 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005788 uErr = QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum,
5789 &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005790 if(uErr != QCBOR_SUCCESS) {
5791 return uErr;
5792 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005793 return QCBOR_Private_ExponentitateUU(uMantissa,
5794 pItem->val.expAndMantissa.nExponent,
5795 puValue,
5796 QCBOR_Private_Exponentitate2);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005797 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005798 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005799 }
5800 break;
5801
5802 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005803 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005804 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5805 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005806 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005807 }
5808 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005809#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005810 default:
5811 return QCBOR_ERR_UNEXPECTED_TYPE;
5812 }
5813}
5814
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005815
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005816/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005817 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005818 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005819void
5820QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe,
5821 const uint32_t uConvertTypes,
5822 uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005823{
5824 QCBORItem Item;
5825
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005826 QCBORDecode_Private_GetUInt64Convert(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005827
Laurence Lundbladef6c86662020-05-12 02:08:00 -07005828 if(pMe->uLastError == QCBOR_SUCCESS) {
5829 // The above conversion succeeded
5830 return;
5831 }
5832
5833 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5834 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07005835 return;
5836 }
5837
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005838 pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
5839 uConvertTypes,
5840 puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005841}
5842
Laurence Lundbladec4537442020-04-14 18:53:22 -07005843
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005844/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005845 * Public function, see header qcbor/qcbor_decode.h file
5846 */
5847void
5848QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
5849 const int64_t nLabel,
5850 const uint32_t uConvertTypes,
5851 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005852{
5853 QCBORItem Item;
5854
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005855 QCBORDecode_Private_GetUInt64ConvertInMapN(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07005856 nLabel,
5857 uConvertTypes,
5858 puValue,
5859 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005860
5861 if(pMe->uLastError == QCBOR_SUCCESS) {
5862 // The above conversion succeeded
5863 return;
5864 }
5865
5866 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5867 // The above conversion failed in a way that code below can't correct
5868 return;
5869 }
5870
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005871 pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
5872 uConvertTypes,
5873 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005874}
5875
5876
5877/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005878 * Public function, see header qcbor/qcbor_decode.h file
5879 */
5880void
5881QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
5882 const char *szLabel,
5883 const uint32_t uConvertTypes,
5884 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005885{
5886 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005887 QCBORDecode_Private_GetUInt64ConvertInMapSZ(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07005888 szLabel,
5889 uConvertTypes,
5890 puValue,
5891 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005892
5893 if(pMe->uLastError == QCBOR_SUCCESS) {
5894 // The above conversion succeeded
5895 return;
5896 }
5897
5898 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5899 // The above conversion failed in a way that code below can't correct
5900 return;
5901 }
5902
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005903 pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
5904 uConvertTypes,
5905 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005906}
5907
5908
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005909
5910
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02005911#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005912/**
5913 * @brief Basic conversions to a double.
5914 *
5915 * @param[in] pItem The item to convert
5916 * @param[in] uConvertTypes Bit flags indicating source types for conversion
5917 * @param[out] pdValue The value converted to a double
5918 *
5919 * This does the conversions that don't need much object code,
5920 * the conversions from int, uint and float to double.
5921 *
5922 * See QCBOR_Private_DoubleConvertAll() for the full set
5923 * of conversions.
5924 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005925static QCBORError
5926QCBOR_Private_ConvertDouble(const QCBORItem *pItem,
5927 const uint32_t uConvertTypes,
5928 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005929{
5930 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005931 case QCBOR_TYPE_FLOAT:
5932#ifndef QCBOR_DISABLE_FLOAT_HW_USE
5933 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5934 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005935 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005936 *pdValue = (double)pItem->val.fnum;
5937 } else {
5938 return QCBOR_ERR_UNEXPECTED_TYPE;
5939 }
5940 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005941#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005942 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005943#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005944 break;
5945
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005946 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005947 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5948 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005949 *pdValue = pItem->val.dfnum;
5950 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005951 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005952 }
5953 }
5954 break;
5955
5956 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005957#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005958 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005959 // A simple cast seems to do the job with no worry of exceptions.
5960 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005961 *pdValue = (double)pItem->val.int64;
5962
5963 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005964 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005965 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005966#else
5967 return QCBOR_ERR_HW_FLOAT_DISABLED;
5968#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005969 break;
5970
5971 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005972#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005973 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005974 // A simple cast seems to do the job with no worry of exceptions.
5975 // There will be precision loss for some values.
5976 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005977 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005978 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005979 }
5980 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005981#else
5982 return QCBOR_ERR_HW_FLOAT_DISABLED;
5983#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005984
5985 default:
5986 return QCBOR_ERR_UNEXPECTED_TYPE;
5987 }
5988
5989 return QCBOR_SUCCESS;
5990}
5991
5992
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07005993/**
5994 * @brief Almost-public method to decode a number and convert to double (semi-private).
5995 *
5996 * @param[in] pMe The decode context.
5997 * @param[in] uConvertTypes Bit mask list of conversion options
5998 * @param[out] pdValue The output of the conversion.
5999 * @param[in,out] pItem Temporary space to store Item, returned item.
6000 *
6001 * See QCBORDecode_GetDoubleConvert().
6002 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006003void
6004QCBORDecode_Private_GetDoubleConvert(QCBORDecodeContext *pMe,
6005 const uint32_t uConvertTypes,
6006 double *pdValue,
6007 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07006008{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006009 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07006010 return;
6011 }
6012
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006013 QCBORError uError = QCBORDecode_GetNext(pMe, pItem);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006014 if(uError) {
6015 pMe->uLastError = (uint8_t)uError;
6016 return;
6017 }
6018
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006019 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006020 uConvertTypes,
6021 pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006022}
Laurence Lundbladec4537442020-04-14 18:53:22 -07006023
Laurence Lundbladec4537442020-04-14 18:53:22 -07006024
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006025/**
6026 * @brief Almost-public method to decode a number and convert to double (semi-private).
6027 *
6028 * @param[in] pMe The decode context.
6029 * @param[in] nLabel Label to find in map.
6030 * @param[in] uConvertTypes Bit mask list of conversion options
6031 * @param[out] pdValue The output of the conversion.
6032 * @param[in,out] pItem Temporary space to store Item, returned item.
6033 *
6034 * See QCBORDecode_GetDoubleConvertInMapN().
6035 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006036void
6037QCBORDecode_Private_GetDoubleConvertInMapN(QCBORDecodeContext *pMe,
6038 const int64_t nLabel,
6039 const uint32_t uConvertTypes,
6040 double *pdValue,
6041 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006042{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006043 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07006044 if(pMe->uLastError != QCBOR_SUCCESS) {
6045 return;
6046 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006047
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006048 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
6049 uConvertTypes,
6050 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006051}
6052
Laurence Lundblade784b54b2020-08-10 01:24:52 -07006053
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006054/**
6055 * @brief Almost-public method to decode a number and convert to double (semi-private).
6056 *
6057 * @param[in] pMe The decode context.
6058 * @param[in] szLabel Label to find in map.
6059 * @param[in] uConvertTypes Bit mask list of conversion options
6060 * @param[out] pdValue The output of the conversion.
6061 * @param[in,out] pItem Temporary space to store Item, returned item.
6062 *
6063 * See QCBORDecode_GetDoubleConvertInMapSZ().
6064 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006065void
6066QCBORDecode_Private_GetDoubleConvertInMapSZ(QCBORDecodeContext *pMe,
6067 const char *szLabel,
6068 const uint32_t uConvertTypes,
6069 double *pdValue,
6070 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006071{
6072 if(pMe->uLastError != QCBOR_SUCCESS) {
6073 return;
6074 }
6075
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006076 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07006077 if(pMe->uLastError != QCBOR_SUCCESS) {
6078 return;
6079 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006080
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006081 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
6082 uConvertTypes,
6083 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006084}
6085
6086
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006087#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006088/**
6089 * @brief Convert a big number to double-precision float.
6090 *
6091 * @param[in] BigNum The big number to convert
6092 *
6093 * @returns The double value.
6094 *
6095 * This will always succeed. It will lose precision for larger
6096 * numbers. If the big number is too large to fit (more than
6097 * 1.7976931348623157E+308) infinity will be returned. NaN is never
6098 * returned.
6099 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006100static double
6101QCBOR_Private_ConvertBigNumToDouble(const UsefulBufC BigNum)
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07006102{
6103 double dResult;
6104
6105 dResult = 0.0;
6106 const uint8_t *pByte = BigNum.ptr;
6107 size_t uLen = BigNum.len;
6108 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006109 * is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07006110 while(uLen--) {
6111 dResult = (dResult * 256.0) + (double)*pByte++;
6112 }
6113
6114 return dResult;
6115}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006116#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
6117
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07006118
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006119
6120
6121/**
6122 * @brief Convert many number types to a double.
6123 *
6124 * @param[in] pItem The item to convert.
6125 * @param[in] uConvertTypes Bit mask list of conversion options.
6126 * @param[out] pdValue The resulting converted value.
6127 *
6128 * @retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
6129 * in uConvertTypes.
6130 * @retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
6131 * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
6132 * or too small.
6133 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07006134static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006135QCBOR_Private_DoubleConvertAll(const QCBORItem *pItem,
6136 const uint32_t uConvertTypes,
6137 double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006138{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006139#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07006140 /*
Laurence Lundblade16a207a2021-09-18 17:22:46 -07006141 * What Every Computer Scientist Should Know About Floating-Point Arithmetic
6142 * https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
6143 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006144 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07006145
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006146#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006147 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006148 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07006149 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006150 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
6151 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
6152 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006153 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006154 }
6155 break;
6156
6157 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006158 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07006159 // Underflow gives 0, overflow gives infinity
6160 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
6161 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006162 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006163 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006164 }
6165 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006166#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006167
6168 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006169 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006170 *pdValue = QCBOR_Private_ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006171 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006172 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006173 }
6174 break;
6175
6176 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006177 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006178 *pdValue = -1-QCBOR_Private_ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006179 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006180 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006181 }
6182 break;
6183
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006184#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006185 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006186 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006187 double dMantissa = QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006188 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
6189 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006190 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006191 }
6192 break;
6193
6194 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006195 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006196 double dMantissa = -QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006197 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
6198 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006199 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006200 }
6201 break;
6202
6203 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006204 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006205 double dMantissa = QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006206 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
6207 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006208 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006209 }
6210 break;
6211
6212 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006213 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006214 double dMantissa = -1-QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006215 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
6216 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07006217 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006218 }
6219 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006220#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade410c7e02020-06-25 23:35:29 -07006221
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006222 default:
6223 return QCBOR_ERR_UNEXPECTED_TYPE;
6224 }
6225
6226 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006227
6228#else
6229 (void)pItem;
6230 (void)uConvertTypes;
6231 (void)pdValue;
6232 return QCBOR_ERR_HW_FLOAT_DISABLED;
6233#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
6234
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006235}
6236
6237
6238/*
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006239 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006240 */
6241void
6242QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
6243 const uint32_t uConvertTypes,
6244 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006245{
6246
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006247 QCBORItem Item;
6248
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006249 QCBORDecode_Private_GetDoubleConvert(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07006250
6251 if(pMe->uLastError == QCBOR_SUCCESS) {
6252 // The above conversion succeeded
6253 return;
6254 }
6255
6256 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6257 // The above conversion failed in a way that code below can't correct
6258 return;
6259 }
6260
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006261 pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
6262 uConvertTypes,
6263 pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07006264}
6265
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006266
6267/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006268 * Public function, see header qcbor/qcbor_decode.h file
6269 */
6270void
6271QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
6272 const int64_t nLabel,
6273 const uint32_t uConvertTypes,
6274 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006275{
6276 QCBORItem Item;
6277
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006278 QCBORDecode_Private_GetDoubleConvertInMapN(pMe,
6279 nLabel,
6280 uConvertTypes,
6281 pdValue,
6282 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006283
6284 if(pMe->uLastError == QCBOR_SUCCESS) {
6285 // The above conversion succeeded
6286 return;
6287 }
6288
6289 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6290 // The above conversion failed in a way that code below can't correct
6291 return;
6292 }
6293
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006294 pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
6295 uConvertTypes,
6296 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006297}
6298
6299
6300/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006301 * Public function, see header qcbor/qcbor_decode.h file
6302 */
6303void
6304QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
6305 const char *szLabel,
6306 const uint32_t uConvertTypes,
6307 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006308{
6309 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006310 QCBORDecode_Private_GetDoubleConvertInMapSZ(pMe,
6311 szLabel,
6312 uConvertTypes,
6313 pdValue,
6314 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006315
6316 if(pMe->uLastError == QCBOR_SUCCESS) {
6317 // The above conversion succeeded
6318 return;
6319 }
6320
6321 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
6322 // The above conversion failed in a way that code below can't correct
6323 return;
6324 }
6325
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006326 pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
6327 uConvertTypes,
6328 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07006329}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02006330#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006331
6332
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006333
6334
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006335#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006336/**
6337 * @brief Convert an integer to a big number
6338 *
6339 * @param[in] uInt The integer to convert.
6340 * @param[in] Buffer The buffer to output the big number to.
6341 *
6342 * @returns The big number or NULLUsefulBufC is the buffer is to small.
6343 *
6344 * This always succeeds unless the buffer is too small.
6345 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006346static UsefulBufC
6347QCBOR_Private_ConvertIntToBigNum(uint64_t uInt, const UsefulBuf Buffer)
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006348{
6349 while((uInt & 0xff00000000000000UL) == 0) {
6350 uInt = uInt << 8;
6351 };
6352
6353 UsefulOutBuf UOB;
6354
6355 UsefulOutBuf_Init(&UOB, Buffer);
6356
6357 while(uInt) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006358 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
6359 uInt = uInt << 8;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07006360 }
6361
6362 return UsefulOutBuf_OutUBuf(&UOB);
6363}
6364
6365
Laurence Lundblade37286c02022-09-03 10:05:02 -07006366/**
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006367 * @brief Check and/or complete exponent and mantissa item.
Laurence Lundblade37286c02022-09-03 10:05:02 -07006368 *
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006369 * @param[in] pMe The decoder context.
6370 * @param[in] TagSpec Expected type(s).
6371 * @param[in,out] pItem See below.
Laurence Lundblade37286c02022-09-03 10:05:02 -07006372 *
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006373 * This is for decimal fractions and big floats, both of which are an
6374 * exponent and mantissa.
Laurence Lundblade37286c02022-09-03 10:05:02 -07006375 *
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006376 * If the item item had a tag number indicating it was a
6377 * decimal fraction or big float, then the input @c pItem will
6378 * have been decoded as exponent and mantissa. If there was
6379 * no tag number, the caller is asking this be decoded as a
6380 * big float or decimal fraction and @c pItem just has the
6381 * first item in an exponent and mantissa.
Laurence Lundblade37286c02022-09-03 10:05:02 -07006382 *
6383 * On output, the item is always a fully decoded decimal fraction or
6384 * big float.
6385 *
6386 * This errors out if the input type does not meet the TagSpec.
6387 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07006388static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006389QCBOR_Private_ExpMantissaTypeHandler(QCBORDecodeContext *pMe,
6390 const QCBOR_Private_TagSpec TagSpec,
6391 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006392{
6393 QCBORError uErr;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006394
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006395 /* pItem could either be a decoded exponent and mantissa or
6396 * the opening array of an undecoded exponent and mantissa. This
Laurence Lundblade37286c02022-09-03 10:05:02 -07006397 * check will succeed on either, but doesn't say which it was.
6398 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006399 uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07006400 if(uErr != QCBOR_SUCCESS) {
6401 goto Done;
6402 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006403
Laurence Lundblade37286c02022-09-03 10:05:02 -07006404 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006405 /* The item is an array, which means is is an undecoded exponent
6406 * and mantissa. This call consumes the items in the array and
6407 * results in a decoded exponent and mantissa in pItem. This is
Laurence Lundblade37286c02022-09-03 10:05:02 -07006408 * the case where there was no tag.
6409 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006410 uErr = QCBORDecode_Private_ExpMantissa(pMe, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006411 if(uErr != QCBOR_SUCCESS) {
6412 goto Done;
6413 }
6414
Laurence Lundblade37286c02022-09-03 10:05:02 -07006415 /* The above decode didn't determine whether it is a decimal
6416 * fraction or big num. Which of these two depends on what the
6417 * caller wants it decoded as since there is no tag, so fish the
6418 * type out of the TagSpec. */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006419 pItem->uDataType = QCBOR_Private_ExpMantissaDataType(TagSpec.uTaggedTypes[0], pItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07006420
6421 /* No need to check the type again. All that we need to know was
Laurence Lundblade23b4ce82024-02-18 21:28:30 -07006422 * that it decoded correctly as a exponent and mantissa. The
Laurence Lundblade37286c02022-09-03 10:05:02 -07006423 * QCBOR type is set out by what was requested.
6424 */
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006425 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07006426
6427 /* If the item was not an array and the check passed, then
6428 * it is a fully decoded big float or decimal fraction and
6429 * matches what is requested.
6430 */
6431
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006432Done:
6433 return uErr;
6434}
6435
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006436
Laurence Lundblade37286c02022-09-03 10:05:02 -07006437/* Some notes from the work to disable tags.
6438 *
6439 * The API for big floats and decimal fractions seems good.
6440 * If there's any issue with it it's that the code size to
6441 * implement is a bit large because of the conversion
6442 * to/from int and bignum that is required. There is no API
6443 * that doesn't do the conversion so dead stripping will never
6444 * leave that code out.
6445 *
6446 * The implementation itself seems correct, but not as clean
6447 * and neat as it could be. It could probably be smaller too.
6448 *
6449 * The implementation has three main parts / functions
6450 * - The decoding of the array of two
6451 * - All the tag and type checking for the various API functions
6452 * - Conversion to/from bignum and int
6453 *
6454 * The type checking seems like it wastes the most code for
6455 * what it needs to do.
6456 *
6457 * The inlining for the conversion is probably making the
6458 * overall code base larger.
6459 *
6460 * The tests cases could be organized a lot better and be
6461 * more thorough.
6462 *
6463 * Seems also like there could be more common code in the
6464 * first tier part of the public API. Some functions only
6465 * vary by a TagSpec.
6466 */
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006467
6468/**
6469 * @brief Common processor for exponent and mantissa.
6470 *
6471 * @param[in] pMe The decode context.
6472 * @param[in] TagSpec The expected/allowed tags.
6473 * @param[in] pItem The data item to process.
6474 * @param[out] pnMantissa The returned mantissa as an int64_t.
6475 * @param[out] pnExponent The returned exponent as an int64_t.
6476 *
6477 * This handles exponent and mantissa for base 2 and 10. This
6478 * is limited to a mantissa that is an int64_t. See also
6479 * QCBORDecode_Private_ProcessExpMantissaBig().
6480 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006481static void
6482QCBOR_Private_ProcessExpMantissa(QCBORDecodeContext *pMe,
6483 const QCBOR_Private_TagSpec TagSpec,
6484 QCBORItem *pItem,
6485 int64_t *pnMantissa,
6486 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006487{
6488 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006489
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006490 uErr = QCBOR_Private_ExpMantissaTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006491 if(uErr != QCBOR_SUCCESS) {
6492 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006493 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006494
Laurence Lundblade9b334962020-08-27 10:55:53 -07006495 switch (pItem->uDataType) {
6496
6497 case QCBOR_TYPE_DECIMAL_FRACTION:
6498 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade9b334962020-08-27 10:55:53 -07006499 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade37286c02022-09-03 10:05:02 -07006500 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
Laurence Lundblade9b334962020-08-27 10:55:53 -07006501 break;
6502
Laurence Lundblade37286c02022-09-03 10:05:02 -07006503#ifndef QCBOR_DISABLE_TAGS
6504 /* If tags are disabled, mantissas can never be big nums */
Laurence Lundblade9b334962020-08-27 10:55:53 -07006505 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
6506 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
6507 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006508 uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
Laurence Lundblade9b334962020-08-27 10:55:53 -07006509 break;
6510
6511 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
6512 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
6513 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006514 uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
Laurence Lundblade9b334962020-08-27 10:55:53 -07006515 break;
Laurence Lundblade37286c02022-09-03 10:05:02 -07006516#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade9b334962020-08-27 10:55:53 -07006517
6518 default:
6519 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
6520 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006521
6522 Done:
6523 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006524}
6525
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006526
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006527/**
6528 * @brief Decode exponent and mantissa into a big number.
6529 *
6530 * @param[in] pMe The decode context.
6531 * @param[in] TagSpec The expected/allowed tags.
6532 * @param[in] pItem Item to decode and convert.
6533 * @param[in] BufferForMantissa Buffer to output mantissa into.
6534 * @param[out] pMantissa The output mantissa.
6535 * @param[out] pbIsNegative The sign of the output.
6536 * @param[out] pnExponent The mantissa of the output.
6537 *
6538 * This is the common processing of a decimal fraction or a big float
6539 * into a big number. This will decode and consume all the CBOR items
6540 * that make up the decimal fraction or big float.
6541 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006542static void
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006543QCBORDecode_Private_ProcessExpMantissaBig(QCBORDecodeContext *pMe,
6544 const QCBOR_Private_TagSpec TagSpec,
6545 QCBORItem *pItem,
6546 const UsefulBuf BufferForMantissa,
6547 UsefulBufC *pMantissa,
6548 bool *pbIsNegative,
6549 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006550{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006551 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006552
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006553 uErr = QCBOR_Private_ExpMantissaTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006554 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006555 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006556 }
6557
6558 uint64_t uMantissa;
6559
6560 switch (pItem->uDataType) {
6561
6562 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006563 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07006564 /* See comments in ExponentiateNN() on handling INT64_MIN */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006565 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
6566 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
6567 *pbIsNegative = false;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07006568 } else if(pItem->val.expAndMantissa.Mantissa.nInt != INT64_MIN) {
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006569 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
6570 *pbIsNegative = true;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07006571 } else {
6572 uMantissa = (uint64_t)INT64_MAX+1;
6573 *pbIsNegative = true;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006574 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006575 *pMantissa = QCBOR_Private_ConvertIntToBigNum(uMantissa,
6576 BufferForMantissa);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006577 *pnExponent = pItem->val.expAndMantissa.nExponent;
6578 break;
6579
Laurence Lundblade37286c02022-09-03 10:05:02 -07006580#ifndef QCBOR_DISABLE_TAGS
6581 /* If tags are disabled, mantissas can never be big nums */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006582 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006583 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006584 *pnExponent = pItem->val.expAndMantissa.nExponent;
6585 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
6586 *pbIsNegative = false;
6587 break;
6588
6589 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006590 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006591 *pnExponent = pItem->val.expAndMantissa.nExponent;
6592 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
6593 *pbIsNegative = true;
6594 break;
Laurence Lundblade37286c02022-09-03 10:05:02 -07006595#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006596
6597 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006598 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006599 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006600
6601Done:
6602 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006603}
6604
6605
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006606/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006607 * Public function, see header qcbor/qcbor_decode.h file
6608 */
6609void
6610QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
6611 const uint8_t uTagRequirement,
6612 int64_t *pnMantissa,
6613 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006614{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006615 if(pMe->uLastError != QCBOR_SUCCESS) {
6616 return;
6617 }
6618
6619 QCBORItem Item;
6620 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6621 if(uError) {
6622 pMe->uLastError = (uint8_t)uError;
6623 return;
6624 }
6625
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006626 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006627 {
6628 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006629 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6630 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6631 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006632 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006633
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006634 QCBOR_Private_ProcessExpMantissa(pMe,
6635 TagSpec,
6636 &Item,
6637 pnMantissa,
6638 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006639}
6640
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006641
6642/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006643 * Public function, see header qcbor/qcbor_decode.h file
6644 */
6645void
6646QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
6647 const int64_t nLabel,
6648 const uint8_t uTagRequirement,
6649 int64_t *pnMantissa,
6650 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006651{
6652 if(pMe->uLastError != QCBOR_SUCCESS) {
6653 return;
6654 }
6655
6656 QCBORItem Item;
6657 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
6658
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006659 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006660 {
6661 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006662 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6663 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6664 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006665 };
6666
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006667 QCBOR_Private_ProcessExpMantissa(pMe,
6668 TagSpec,
6669 &Item,
6670 pnMantissa,
6671 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006672}
6673
6674
6675/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006676 * Public function, see header qcbor/qcbor_decode.h file
6677 */
6678void
6679QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
6680 const char *szLabel,
6681 const uint8_t uTagRequirement,
6682 int64_t *pnMantissa,
6683 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006684{
6685 if(pMe->uLastError != QCBOR_SUCCESS) {
6686 return;
6687 }
6688
6689 QCBORItem Item;
6690 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6691
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006692 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006693 {
6694 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006695 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6696 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6697 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006698 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07006699
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006700 QCBOR_Private_ProcessExpMantissa(pMe,
6701 TagSpec,
6702 &Item,
6703 pnMantissa,
6704 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006705}
6706
6707
6708/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006709 * Public function, see header qcbor/qcbor_decode.h file
6710 */
6711void
6712QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
6713 const uint8_t uTagRequirement,
6714 const UsefulBuf MantissaBuffer,
6715 UsefulBufC *pMantissa,
6716 bool *pbMantissaIsNegative,
6717 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006718{
6719 if(pMe->uLastError != QCBOR_SUCCESS) {
6720 return;
6721 }
6722
6723 QCBORItem Item;
6724 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6725 if(uError) {
6726 pMe->uLastError = (uint8_t)uError;
6727 return;
6728 }
6729
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006730 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006731 {
6732 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006733 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6734 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6735 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006736 };
6737
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006738 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
6739 TagSpec,
6740 &Item,
6741 MantissaBuffer,
6742 pMantissa,
6743 pbMantissaIsNegative,
6744 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006745}
6746
6747
6748/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006749 * Public function, see header qcbor/qcbor_decode.h file
6750 */
6751void
6752QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
6753 const int64_t nLabel,
6754 const uint8_t uTagRequirement,
6755 const UsefulBuf BufferForMantissa,
6756 UsefulBufC *pMantissa,
6757 bool *pbIsNegative,
6758 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006759{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006760 if(pMe->uLastError != QCBOR_SUCCESS) {
6761 return;
6762 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006763
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006764 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006765 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006766 if(pMe->uLastError != QCBOR_SUCCESS) {
6767 return;
6768 }
6769
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006770 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006771 {
6772 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006773 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6774 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6775 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006776 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006777
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006778 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
6779 TagSpec,
6780 &Item,
6781 BufferForMantissa,
6782 pMantissa,
6783 pbIsNegative,
6784 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006785}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006786
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006787
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006788/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006789 * Public function, see header qcbor/qcbor_decode.h file
6790 */
6791void
6792QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
6793 const char *szLabel,
6794 const uint8_t uTagRequirement,
6795 const UsefulBuf BufferForMantissa,
6796 UsefulBufC *pMantissa,
6797 bool *pbIsNegative,
6798 int64_t *pnExponent)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006799{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006800 if(pMe->uLastError != QCBOR_SUCCESS) {
6801 return;
6802 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006803
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006804 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006805 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6806 if(pMe->uLastError != QCBOR_SUCCESS) {
6807 return;
6808 }
6809
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006810 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006811 {
6812 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006813 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6814 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6815 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006816 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006817
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006818 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
6819 TagSpec,
6820 &Item,
6821 BufferForMantissa,
6822 pMantissa,
6823 pbIsNegative,
6824 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006825}
6826
6827
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006828/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006829 * Public function, see header qcbor/qcbor_decode.h file
6830 */
6831void
6832QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
6833 const uint8_t uTagRequirement,
6834 int64_t *pnMantissa,
6835 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006836{
6837 if(pMe->uLastError != QCBOR_SUCCESS) {
6838 return;
6839 }
6840
6841 QCBORItem Item;
6842 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6843 if(uError) {
6844 pMe->uLastError = (uint8_t)uError;
6845 return;
6846 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006847 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006848 {
6849 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006850 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6851 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6852 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006853 };
6854
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006855 QCBOR_Private_ProcessExpMantissa(pMe,
6856 TagSpec,
6857 &Item,
6858 pnMantissa,
6859 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006860}
6861
6862
6863/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006864 * Public function, see header qcbor/qcbor_decode.h file
6865 */
6866void
6867QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
6868 const int64_t nLabel,
6869 const uint8_t uTagRequirement,
6870 int64_t *pnMantissa,
6871 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006872{
6873 if(pMe->uLastError != QCBOR_SUCCESS) {
6874 return;
6875 }
6876
6877 QCBORItem Item;
6878 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
6879 if(pMe->uLastError != QCBOR_SUCCESS) {
6880 return;
6881 }
6882
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006883 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006884 {
6885 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006886 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6887 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6888 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006889 };
6890
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006891 QCBOR_Private_ProcessExpMantissa(pMe,
6892 TagSpec,
6893 &Item,
6894 pnMantissa,
6895 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006896}
6897
6898
6899/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006900 * Public function, see header qcbor/qcbor_decode.h file
6901 */
6902void
6903QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
6904 const char *szLabel,
6905 const uint8_t uTagRequirement,
6906 int64_t *pnMantissa,
6907 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006908{
6909 if(pMe->uLastError != QCBOR_SUCCESS) {
6910 return;
6911 }
6912
6913 QCBORItem Item;
6914 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6915 if(pMe->uLastError != QCBOR_SUCCESS) {
6916 return;
6917 }
6918
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006919 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006920 {
6921 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006922 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6923 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6924 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006925 };
6926
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006927 QCBOR_Private_ProcessExpMantissa(pMe,
6928 TagSpec,
6929 &Item,
6930 pnMantissa,
6931 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006932}
6933
6934
6935/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006936 * Public function, see header qcbor/qcbor_decode.h file
6937 */
6938void
6939QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
6940 const uint8_t uTagRequirement,
6941 const UsefulBuf MantissaBuffer,
6942 UsefulBufC *pMantissa,
6943 bool *pbMantissaIsNegative,
6944 int64_t *pnExponent)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006945{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006946 if(pMe->uLastError != QCBOR_SUCCESS) {
6947 return;
6948 }
6949
6950 QCBORItem Item;
6951 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6952 if(uError) {
6953 pMe->uLastError = (uint8_t)uError;
6954 return;
6955 }
6956
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006957 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006958 {
6959 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006960 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6961 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6962 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006963 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006964
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07006965 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
6966 TagSpec,
6967 &Item,
6968 MantissaBuffer,
6969 pMantissa,
6970 pbMantissaIsNegative,
6971 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006972}
6973
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006974
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006975/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006976 * Public function, see header qcbor/qcbor_decode.h file
6977 */
6978void
6979QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
6980 const int64_t nLabel,
6981 const uint8_t uTagRequirement,
6982 const UsefulBuf BufferForMantissa,
6983 UsefulBufC *pMantissa,
6984 bool *pbIsNegative,
6985 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006986{
6987 if(pMe->uLastError != QCBOR_SUCCESS) {
6988 return;
6989 }
6990
6991 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006992 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
6993 if(pMe->uLastError != QCBOR_SUCCESS) {
6994 return;
6995 }
6996
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006997 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006998 {
6999 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07007000 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
7001 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
7002 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007003 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007004
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07007005 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
7006 TagSpec,
7007 &Item,
7008 BufferForMantissa,
7009 pMantissa,
7010 pbIsNegative,
7011 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007012}
7013
7014
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007015/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007016 * Public function, see header qcbor/qcbor_decode.h file
7017 */
7018void
7019QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
7020 const char *szLabel,
7021 const uint8_t uTagRequirement,
7022 const UsefulBuf BufferForMantissa,
7023 UsefulBufC *pMantissa,
7024 bool *pbIsNegative,
7025 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007026{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007027 if(pMe->uLastError != QCBOR_SUCCESS) {
7028 return;
7029 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007030
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007031 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007032 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
7033 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07007034 return;
7035 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07007036
Laurence Lundblade8e36f812024-01-26 10:59:29 -07007037 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007038 {
7039 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07007040 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
7041 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
7042 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07007043 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07007044
Laurence Lundblade4ae4ef92024-02-05 19:21:31 -07007045 QCBORDecode_Private_ProcessExpMantissaBig(pMe,
7046 TagSpec,
7047 &Item,
7048 BufferForMantissa,
7049 pMantissa,
7050 pbIsNegative,
7051 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07007052}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07007053
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07007054#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */