blob: 693152fd4f9c18ba4635bc244b7fdb8cdfc309c7 [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
Laurence Lundbladed92a6162018-11-01 11:38:35 +07002 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003 Copyright (c) 2018-2024, Laurence Lundblade.
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02004 Copyright (c) 2021, Arm Limited.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07005 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08006
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07007Redistribution and use in source and binary forms, with or without
8modification, are permitted provided that the following conditions are
9met:
10 * Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above
13 copyright notice, this list of conditions and the following
14 disclaimer in the documentation and/or other materials provided
15 with the distribution.
16 * Neither the name of The Linux Foundation nor the names of its
17 contributors, nor the name "Laurence Lundblade" may be used to
18 endorse or promote products derived from this software without
19 specific prior written permission.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080020
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070021THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
22WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
24ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
25BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
30OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080032 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070033
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080034
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080035#include "qcbor/qcbor_decode.h"
Laurence Lundblade67257dc2020-07-27 03:33:37 -070036#include "qcbor/qcbor_spiffy_decode.h"
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080037#include "ieee754.h" /* Does not use math.h */
Laurence Lundbladec7114722020-08-13 05:11:40 -070038
39#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080040
41#include <math.h> /* For isnan(), llround(), llroudf(), round(), roundf(),
42 * pow(), exp2()
43 */
44#include <fenv.h> /* feclearexcept(), fetestexcept() */
45
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080046#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070047
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070048
Laurence Lundblade68cb61c2023-02-12 13:21:44 -080049#if (defined(__GNUC__) && !defined(__clang__))
Laurence Lundblade8e36f812024-01-26 10:59:29 -070050/*
Laurence Lundblade68cb61c2023-02-12 13:21:44 -080051 * This is how the -Wmaybe-uninitialized compiler warning is
52 * handled. It can’t be ignored because some version of gcc enable it
53 * with -Wall which is a common and useful gcc warning option. It also
54 * can’t be ignored because it is the goal of QCBOR to compile clean
55 * out of the box in all environments.
56 *
57 * The big problem with -Wmaybe-uninitialized is that it generates
58 * false positives. It complains things are uninitialized when they
59 * are not. This is because it is not a thorough static analyzer. This
60 * is why “maybe” is in its name. The problem is it is just not
61 * thorough enough to understand all the code (and someone saw fit to
62 * put it in gcc and worse to enable it with -Wall).
63 *
64 * One solution would be to change the code so -Wmaybe-uninitialized
65 * doesn’t get confused, for example adding an unnecessary extra
66 * initialization to zero. (If variables were truly uninitialized, the
67 * correct path is to understand the code thoroughly and set them to
68 * the correct value at the correct time; in essence this is already
69 * done; -Wmaybe-uninitialized just can’t tell). This path is not
70 * taken because it makes the code bigger and is kind of the tail
71 * wagging the dog.
72 *
73 * The solution here is to just use a pragma to disable it for the
74 * whole file. Disabling it for each line makes the code fairly ugly
75 * requiring #pragma to push, pop and ignore. Another reason is the
76 * warnings issues vary by version of gcc and which optimization
77 * optimizations are selected. Another reason is that compilers other
78 * than gcc don’t have -Wmaybe-uninitialized.
79 *
80 * One may ask how to be sure these warnings are false positives and
81 * not real issues. 1) The code has been read carefully to check. 2)
82 * Testing is pretty thorough. 3) This code has been run through
83 * thorough high-quality static analyzers.
84 *
85 * In particularly, most of the warnings are about
86 * Item.Item->uDataType being uninitialized. QCBORDecode_GetNext()
87 * *always* sets this value and test case confirm
88 * this. -Wmaybe-uninitialized just can't tell.
89 *
90 * https://stackoverflow.com/questions/5080848/disable-gcc-may-be-used-uninitialized-on-a-particular-variable
91 */
92#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
Laurence Lundblade8e36f812024-01-26 10:59:29 -070093#endif
Laurence Lundblade68cb61c2023-02-12 13:21:44 -080094
95
96
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080097
Laurence Lundbladea9489f82020-09-12 13:50:56 -070098#define SIZEOF_C_ARRAY(array,type) (sizeof(array)/sizeof(type))
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070099
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700100
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800101
102
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700103static bool
104QCBORItem_IsMapOrArray(const QCBORItem Item)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700105{
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700106 const uint8_t uDataType = Item.uDataType;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700107 return uDataType == QCBOR_TYPE_MAP ||
108 uDataType == QCBOR_TYPE_ARRAY ||
109 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
110}
111
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700112static bool
113QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem Item)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700114{
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700115 if(!QCBORItem_IsMapOrArray(Item)){
Laurence Lundblade02625d42020-06-25 14:41:41 -0700116 return false;
117 }
118
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700119 if(Item.val.uCount != 0) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700120 return false;
121 }
122 return true;
123}
124
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700125static bool
126QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem Item)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700127{
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800128#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700129 if(!QCBORItem_IsMapOrArray(Item)){
Laurence Lundblade02625d42020-06-25 14:41:41 -0700130 return false;
131 }
132
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700133 if(Item.val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700134 return false;
135 }
136 return true;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800137#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700138 (void)Item;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800139 return false;
140#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700141}
142
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700143/* Return true if the labels in Item1 and Item2 are the same.
144 Works only for integer and string labels. Returns false
145 for any other type. */
146static bool
147QCBORItem_MatchLabel(const QCBORItem Item1, const QCBORItem Item2)
148{
149 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
150 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
151 return true;
152 }
153 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
154 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
155 return true;
156 }
157 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
158 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
159 return true;
160 }
161 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
162 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
163 return true;
164 }
165 }
166
167 /* Other label types are never matched */
168 return false;
169}
170
171
172/*
173 Returns true if Item1 and Item2 are the same type
174 or if either are of QCBOR_TYPE_ANY.
175 */
176static bool
177QCBORItem_MatchType(const QCBORItem Item1, const QCBORItem Item2)
178{
179 if(Item1.uDataType == Item2.uDataType) {
180 return true;
181 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
182 return true;
183 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
184 return true;
185 }
186 return false;
187}
188
Laurence Lundblade02625d42020-06-25 14:41:41 -0700189
Laurence Lundbladeee851742020-01-08 08:37:05 -0800190/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700191 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -0800192 ===========================================================================*/
193
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700194/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800195 * See comments about and typedef of QCBORDecodeNesting in qcbor_private.h,
196 * the data structure all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700197 */
198
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700199
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700200static uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700201DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700202{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700203 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800204 /* Limit in DecodeNesting_Descend against more than
205 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700206 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700207 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700208}
209
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700210
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700211static uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700212DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700213{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700214 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800215 /* Limit in DecodeNesting_Descend against more than
216 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700217 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700218 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700219}
220
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700221
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700222static uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700223DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700224{
225 return pNesting->pCurrentBounded->u.ma.uStartOffset;
226}
227
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700228
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700229static bool
Laurence Lundblade085d7952020-07-24 10:26:30 -0700230DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
231{
232 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
233 return true;
234 } else {
235 return false;
236 }
237}
238
239
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700240static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700241DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700242{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700243 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700244 return true;
245 } else {
246 return false;
247 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700248}
249
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700250
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700251static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700252DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700253{
254 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800255 /* Not a map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700256 return false;
257 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800258
259#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700260 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800261 /* Is indefinite */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700262 return false;
263 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800264
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800265#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
266
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800267 /* All checks passed; is a definte length map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700268 return true;
269}
270
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700271static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700272DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700273{
274 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800275 /* is a byte string */
Laurence Lundblade642282a2020-06-23 12:00:33 -0700276 return true;
277 }
278 return false;
279}
280
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700281
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700282static bool
283DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700284{
285 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
286 return true;
287 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700288 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700289 return true;
290 }
291 return false;
292}
293
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700294
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700295static void
296DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700297{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800298 /* Should be only called on maps and arrays */
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700299 /*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800300 * DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
301 * larger than DecodeNesting_EnterBoundedMode which keeps it less than
302 * uin32_t so the cast is safe.
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700303 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700304 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700305
306 if(bIsEmpty) {
307 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
308 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700309}
310
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700311
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700312static void
313DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700314{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700315 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700316}
317
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700318
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700319static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700320DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700321{
322 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800323 /* No bounded map or array set up */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700324 return false;
325 }
326 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800327 /* Not a map or array; end of those is by byte count */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700328 return false;
329 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700330 if(!DecodeNesting_IsCurrentBounded(pNesting)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800331 /* In a traveral at a level deeper than the bounded level */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700332 return false;
333 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800334 /* Works for both definite- and indefinitelength maps/arrays */
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800335 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0 &&
336 pNesting->pCurrentBounded->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800337 /* Count is not zero, still unconsumed item */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700338 return false;
339 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800340 /* All checks passed, got to the end of an array or map*/
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700341 return true;
342}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700343
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700344
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700345static bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700346DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700347{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800348 /* Must only be called on map / array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700349 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
350 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700351 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700352 return false;
353 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700354}
355
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700356
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700357static bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700358DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700359{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700360 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
361 return true;
362 } else {
363 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700364 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700365}
366
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700367
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700368static bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700369DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700370{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700371 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700372 return false;
373 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700374
375 if(pNesting->pCurrentBounded->uLevelType != uType) {
376 return false;
377 }
378
379 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700380}
381
Laurence Lundblade02625d42020-06-25 14:41:41 -0700382
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700383static void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700384DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700385{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800386 /* Only call on a definite-length array / map */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700387 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700388}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700389
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700390
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700391static void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700392DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
393{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800394 /* Only call on a definite-length array / map */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700395 pNesting->pCurrent->u.ma.uCountCursor++;
396}
397
398
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700399static void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700400DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
401{
402 pNesting->pCurrent--;
403}
404
Laurence Lundblade02625d42020-06-25 14:41:41 -0700405
406static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700407DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700408{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800409 /* Error out if nesting is too deep */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700410 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700411 return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700412 }
413
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800414 /* The actual descend */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700415 pNesting->pCurrent++;
416
417 pNesting->pCurrent->uLevelType = uType;
418
419 return QCBOR_SUCCESS;
420}
421
422
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700423static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800424DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting,
425 bool bIsEmpty,
426 size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700427{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700428 /*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800429 * Should only be called on map/array.
430 *
431 * Have descended into this before this is called. The job here is
432 * just to mark it in bounded mode.
433 *
434 * Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
435 * uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET.
436 *
437 * Cast of uOffset to uint32_t for cases where SIZE_MAX < UINT32_MAX.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700438 */
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -0800439 if((uint32_t)uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700440 return QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700441 }
442
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700443 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700444
445 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700446
447 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700448}
449
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700450
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700451static QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700452DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700453 uint8_t uQCBORType,
454 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700455{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700456 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700457
458 if(uCount == 0) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800459 /* Nothing to do for empty definite-length arrays. They are just are
460 * effectively the same as an item that is not a map or array.
461 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700462 goto Done;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800463 /* Empty indefinite-length maps and arrays are handled elsewhere */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700464 }
465
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800466 /* Error out if arrays is too long to handle */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700467 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
468 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700469 uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700470 goto Done;
471 }
472
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700473 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700474 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700475 goto Done;
476 }
477
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800478 /* Fill in the new map/array level. Check above makes casts OK. */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700479 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
480 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700481
482 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700483
484Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700485 return uError;;
486}
487
488
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700489static void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700490DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
491{
492 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
493}
494
495
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700496static void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700497DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
498{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700499 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700500 pNesting->pCurrentBounded--;
501 if(DecodeNesting_IsCurrentBounded(pNesting)) {
502 break;
503 }
504 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700505}
506
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800507
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700508static void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700509DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
510{
511 pNesting->pCurrent = pNesting->pCurrentBounded;
512}
513
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700514
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700515static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700516DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700517 uint32_t uEndOffset,
518 uint32_t uStartOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700519{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700520 QCBORError uError;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700521
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700522 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700523 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700524 goto Done;
525 }
526
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800527 /* Fill in the new byte string level */
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700528 pNesting->pCurrent->u.bs.uSavedEndOffset = uEndOffset;
529 pNesting->pCurrent->u.bs.uBstrStartOffset = uStartOffset;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700530
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800531 /* Bstr wrapped levels are always bounded */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700532 pNesting->pCurrentBounded = pNesting->pCurrent;
533
534Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700535 return uError;;
536}
537
Laurence Lundbladed0304932020-06-27 10:59:38 -0700538
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700539static void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700540DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700541{
542 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700543}
544
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700545
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700546static void
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800547DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
548{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700549 if(pNesting->pCurrent->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
550 pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
551 }
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800552}
553
554
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700555static void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700556DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700557{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700558 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700559 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
560 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700561}
562
563
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700564static void
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800565DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting,
566 QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700567{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700568 *pSave = *pNesting;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700569}
570
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700571
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700572static void
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800573DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting,
574 const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700575{
576 *pNesting = *pSave;
577}
578
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700579
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700580static uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700581DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700582{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700583 return pMe->pCurrentBounded->u.bs.uSavedEndOffset;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700584}
585
586
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800587
588
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800589#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladeee851742020-01-08 08:37:05 -0800590/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800591 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
592
593 The following four functions are pretty wrappers for invocation of
594 the string allocator supplied by the caller.
595
Laurence Lundbladeee851742020-01-08 08:37:05 -0800596 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800597
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700598static void
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800599StringAllocator_Free(const QCBORInternalAllocator *pMe, const void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800600{
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300601 /* This cast to uintptr_t suppresses the "-Wcast-qual" warnings.
602 * This is the one place where the const needs to be cast away so const can
603 * be use in the rest of the code.
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800604 */
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300605 (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)(uintptr_t)pMem, 0);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800606}
607
Laurence Lundbladeee851742020-01-08 08:37:05 -0800608// StringAllocator_Reallocate called with pMem NULL is
609// equal to StringAllocator_Allocate()
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700610static UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800611StringAllocator_Reallocate(const QCBORInternalAllocator *pMe,
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800612 const void *pMem,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800613 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800614{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800615 /* See comment in StringAllocator_Free() */
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300616 return (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)(uintptr_t)pMem, uSize);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800617}
618
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700619static UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800620StringAllocator_Allocate(const QCBORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800621{
622 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
623}
624
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700625static void
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800626StringAllocator_Destruct(const QCBORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800627{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800628 /* See comment in StringAllocator_Free() */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800629 if(pMe->pfAllocator) {
630 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
631 }
632}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800633#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800634
635
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800636
637
Laurence Lundbladeee851742020-01-08 08:37:05 -0800638/*===========================================================================
639 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700640
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800641 See qcbor/qcbor_decode.h for definition of the object
642 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800643 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700644/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800645 * Public function, see header file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700646 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700647void
648QCBORDecode_Init(QCBORDecodeContext *pMe,
649 UsefulBufC EncodedCBOR,
650 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700651{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800652 memset(pMe, 0, sizeof(QCBORDecodeContext));
653 UsefulInputBuf_Init(&(pMe->InBuf), EncodedCBOR);
654 /* Don't bother with error check on decode mode. If a bad value is
655 * passed it will just act as if the default normal mode of 0 was set.
656 */
657 pMe->uDecodeMode = (uint8_t)nDecodeMode;
658 DecodeNesting_Init(&(pMe->nesting));
659
660 /* Inialize me->auMappedTags to CBOR_TAG_INVALID16. See
661 * GetNext_TaggedItem() and MapTagNumber(). */
662 memset(pMe->auMappedTags, 0xff, sizeof(pMe->auMappedTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700663}
664
665
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800666#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
667
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700668/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800669 * Public function, see header file
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700670 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700671void
672QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
673 QCBORStringAllocate pfAllocateFunction,
674 void *pAllocateContext,
675 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700676{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800677 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
678 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
679 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700680}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800681#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700682
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800683
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800684
685
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800686/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800687 * Deprecated public function, see header file
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800688 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700689void
690QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
691 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700692{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800693 /* This does nothing now. It is retained for backwards compatibility */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700694 (void)pMe;
695 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700696}
697
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700698
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800699
700
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700701/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800702 * Decoding items is done in six layers, one calling the next one
703 * down. If a layer has no work to do for a particular item, it
704 * returns quickly.
705 *
706 * 1. QCBORDecode_GetNextTagContent - The top layer processes tagged
707 * data items, turning them into the local C representation. For the
708 * most simple it is just associating a QCBOR_TYPE with the data. For
709 * the complex ones that an aggregate of data items, there is some
710 * further decoding and some limited recursion.
711 *
712 * 2. QCBORDecode_GetNextMapOrArray - This manages the beginnings and
713 * ends of maps and arrays. It tracks descending into and ascending
714 * out of maps/arrays. It processes breaks that terminate
715 * indefinite-length maps and arrays.
716 *
717 * 3. QCBORDecode_GetNextMapEntry - This handles the combining of two
718 * items, the label and the data, that make up a map entry. It only
719 * does work on maps. It combines the label and data items into one
720 * labeled item.
721 *
722 * 4. QCBORDecode_GetNextTagNumber - This decodes type 6 tag
723 * numbers. It turns the tag numbers into bit flags associated with
724 * the data item. No actual decoding of the contents of the tag is
725 * performed here.
726 *
727 * 5. QCBORDecode_GetNextFullString - This assembles the sub-items
728 * that make up an indefinite-length string into one string item. It
729 * uses the string allocator to create contiguous space for the
730 * item. It processes all breaks that are part of indefinite-length
731 * strings.
732 *
733 * 6. DecodeAtomicDataItem - This decodes the atomic data items in
734 * CBOR. Each atomic data item has a "major type", an integer
735 * "argument" and optionally some content. For text and byte strings,
736 * the content is the bytes that make up the string. These are the
737 * smallest data items that are considered to be well-formed. The
738 * content may also be other data items in the case of aggregate
739 * types. They are not handled in this layer.
740 *
741 * Roughly this takes 300 bytes of stack for vars. TODO: evaluate this
742 * more carefully and correctly.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700743 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800744
745
746/*
747 * Note about use of int and unsigned variables.
748 *
749 * See http://www.unix.org/whitepapers/64bit.html for reasons int is
750 * used carefully here, and in particular why it isn't used in the
751 * public interface. Also see
752 * https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
753 *
754 * Int is used for values that need less than 16-bits and would be
755 * subject to integer promotion and result in complaining from static
756 * analyzers.
757 */
758
759
760/**
761 * @brief Decode the CBOR head, the type and argument.
762 *
763 * @param[in] pUInBuf The input buffer to read from.
764 * @param[out] pnMajorType The decoded major type.
765 * @param[out] puArgument The decoded argument.
766 * @param[out] pnAdditionalInfo The decoded Lower 5 bits of initial byte.
767 *
768 * @retval QCBOR_ERR_UNSUPPORTED
769 * @retval QCBOR_ERR_HIT_END
770 *
771 * This decodes the CBOR "head" that every CBOR data item has. See
772 * longer explaination of the head in documentation for
773 * QCBOREncode_EncodeHead().
774 *
775 * This does the network->host byte order conversion. The conversion
776 * here also results in the conversion for floats in addition to that
777 * for lengths, tags and integer values.
778 *
779 * The int type is preferred to uint8_t for some variables as this
780 * avoids integer promotions, can reduce code size and makes static
781 * analyzers happier.
782 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700783static QCBORError
784QCBOR_Private_DecodeHead(UsefulInputBuf *pUInBuf,
785 int *pnMajorType,
786 uint64_t *puArgument,
787 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700788{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800789 QCBORError uReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800790
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800791 /* Get the initial byte that every CBOR data item has and break it
792 * down. */
793 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800794 const int nTmpMajorType = nInitialByte >> 5;
795 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800796
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800797 /* Where the argument accumulates */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800798 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800799
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800800 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800801 /* Need to get 1,2,4 or 8 additional argument bytes. Map
802 * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
803 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800804 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800805
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800806 /* Loop getting all the bytes in the argument */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800807 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800808 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800809 /* This shift and add gives the endian conversion. */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800810 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
811 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800812 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800813 /* The reserved and thus-far unused additional info values */
814 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800815 goto Done;
816 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800817 /* Less than 24, additional info is argument or 31, an
818 * indefinite-length. No more bytes to get.
819 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800820 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700821 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800822
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700823 if(UsefulInputBuf_GetError(pUInBuf)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800824 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700825 goto Done;
826 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800827
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800828 /* All successful if arrived here. */
829 uReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800830 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800831 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800832 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800833
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700834Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800835 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700836}
837
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800838
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800839/**
840 * @brief Decode integer types, major types 0 and 1.
841 *
842 * @param[in] nMajorType The CBOR major type (0 or 1).
843 * @param[in] uArgument The argument from the head.
844 * @param[out] pDecodedItem The filled in decoded item.
845 *
846 * @retval QCBOR_ERR_INT_OVERFLOW
847 *
848 * Must only be called when major type is 0 or 1.
849 *
850 * CBOR doesn't explicitly specify two's compliment for integers but
851 * all CPUs use it these days and the test vectors in the RFC are
852 * so. All integers in the CBOR structure are positive and the major
853 * type indicates positive or negative. CBOR can express positive
854 * integers up to 2^x - 1 where x is the number of bits and negative
855 * integers down to 2^x. Note that negative numbers can be one more
856 * away from zero than positive. Stdint, as far as I can tell, uses
857 * two's compliment to represent negative integers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700858 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700859static QCBORError
860QCBOR_Private_DecodeInteger(const int nMajorType,
861 const uint64_t uArgument,
862 QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700863{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800864 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800865
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700866 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800867 if (uArgument <= INT64_MAX) {
868 pDecodedItem->val.int64 = (int64_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700869 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800870
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700871 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800872 pDecodedItem->val.uint64 = uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700873 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700874 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800875
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700876 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800877 if(uArgument <= INT64_MAX) {
878 /* CBOR's representation of negative numbers lines up with
879 * the two-compliment representation. A negative integer has
880 * one more in range than a positive integer. INT64_MIN is
881 * equal to (-INT64_MAX) - 1.
882 */
883 pDecodedItem->val.int64 = (-(int64_t)uArgument) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700884 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800885
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700886 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800887 /* C can't represent a negative integer in this range so it
888 * is an error.
889 */
890 uReturn = QCBOR_ERR_INT_OVERFLOW;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700891 }
892 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800893
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800894 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700895}
896
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800897
898/* Make sure #define value line up as DecodeSimple counts on this. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700899#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
900#error QCBOR_TYPE_FALSE macro value wrong
901#endif
902
903#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
904#error QCBOR_TYPE_TRUE macro value wrong
905#endif
906
907#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
908#error QCBOR_TYPE_NULL macro value wrong
909#endif
910
911#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
912#error QCBOR_TYPE_UNDEF macro value wrong
913#endif
914
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700915#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
916#error QCBOR_TYPE_BREAK macro value wrong
917#endif
918
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700919#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
920#error QCBOR_TYPE_DOUBLE macro value wrong
921#endif
922
923#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
924#error QCBOR_TYPE_FLOAT macro value wrong
925#endif
926
Laurence Lundblade9b334962020-08-27 10:55:53 -0700927
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800928/**
929 * @brief Decode major type 7 -- true, false, floating-point, break...
930 *
931 * @param[in] nAdditionalInfo The lower five bits from the initial byte.
932 * @param[in] uArgument The argument from the head.
933 * @param[out] pDecodedItem The filled in decoded item.
934 *
935 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200936 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800937 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700938 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800939
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700940static QCBORError
941QCBOR_Private_DecodeType7(const int nAdditionalInfo,
942 const uint64_t uArgument,
943 QCBORItem *pDecodedItem)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800944{
945 QCBORError uReturn = QCBOR_SUCCESS;
946
947 /* uAdditionalInfo is 5 bits from the initial byte. Compile time
948 * checks above make sure uAdditionalInfo values line up with
949 * uDataType values. DecodeHead() never returns an AdditionalInfo
950 * > 0x1f so cast is safe.
951 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800952 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800953
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800954 switch(nAdditionalInfo) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800955 /* No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they
956 * are caught before this is called.
957 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800958
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800959 case HALF_PREC_FLOAT: /* 25 */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700960#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800961 /* Half-precision is returned as a double. The cast to
962 * uint16_t is safe because the encoded value was 16 bits. It
963 * was widened to 64 bits to be passed in here.
964 */
965 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700966 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800967#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200968 uReturn = FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700969 break;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800970 case SINGLE_PREC_FLOAT: /* 26 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200971#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800972 /* Single precision is normally returned as a double since
973 * double is widely supported, there is no loss of precision,
974 * it makes it easy for the caller in most cases and it can
975 * be converted back to single with no loss of precision
976 *
977 * The cast to uint32_t is safe because the encoded value was
978 * 32 bits. It was widened to 64 bits to be passed in here.
979 */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700980 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800981 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uArgument);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700982#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800983 /* In the normal case, use HW to convert float to
984 * double. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700985 pDecodedItem->val.dfnum = (double)f;
986 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800987#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800988 /* Use of float HW is disabled, return as a float. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700989 pDecodedItem->val.fnum = f;
990 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
991
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800992 /* IEEE754_FloatToDouble() could be used here to return as
993 * a double, but it adds object code and most likely
994 * anyone disabling FLOAT HW use doesn't care about floats
995 * and wants to save object code.
996 */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800997#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700998 }
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200999#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1000 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -07001001 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001002
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001003 case DOUBLE_PREC_FLOAT: /* 27 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001004#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001005 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +07001006 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001007#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1008 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -07001009 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001010
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001011 case CBOR_SIMPLEV_FALSE: /* 20 */
1012 case CBOR_SIMPLEV_TRUE: /* 21 */
1013 case CBOR_SIMPLEV_NULL: /* 22 */
1014 case CBOR_SIMPLEV_UNDEF: /* 23 */
1015 case CBOR_SIMPLE_BREAK: /* 31 */
1016 break; /* nothing to do */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001017
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001018 case CBOR_SIMPLEV_ONEBYTE: /* 24 */
1019 if(uArgument <= CBOR_SIMPLE_BREAK) {
1020 /* This takes out f8 00 ... f8 1f which should be encoded
1021 * as e0 … f7
1022 */
1023 uReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001024 goto Done;
1025 }
Laurence Lundblade5e390822019-01-06 12:35:01 -08001026 /* FALLTHROUGH */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001027
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001028 default: /* 0-19 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001029 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001030 /* DecodeHead() will make uArgument equal to
1031 * nAdditionalInfo when nAdditionalInfo is < 24. This cast is
1032 * safe because the 2, 4 and 8 byte lengths of uNumber are in
1033 * the double/float cases above
Laurence Lundbladeee851742020-01-08 08:37:05 -08001034 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001035 pDecodedItem->val.uSimple = (uint8_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001036 break;
1037 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001038
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001039Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001040 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001041}
1042
1043
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001044/**
1045 * @brief Decode text and byte strings
1046 *
1047 * @param[in] pAllocator The string allocator or NULL.
1048 * @param[in] uStrLen The length of the string.
1049 * @param[in] pUInBuf The surce from which to read the string's bytes.
1050 * @param[out] pDecodedItem The filled in decoded item.
1051 *
1052 * @retval QCBOR_ERR_HIT_END
1053 * @retval QCBOR_ERR_STRING_ALLOCATE
1054 * @retval QCBOR_ERR_STRING_TOO_LONG
1055 *
1056 * The reads @c uStrlen bytes from @c pUInBuf and fills in @c
1057 * pDecodedItem. If @c pAllocator is not NULL then memory for the
1058 * string is allocated.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001059 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001060static QCBORError
1061QCBOR_Private_DecodeBytes(const QCBORInternalAllocator *pAllocator,
1062 const uint64_t uStrLen,
1063 UsefulInputBuf *pUInBuf,
1064 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001065{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001066 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001067
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001068 /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
1069 * CPUs. This check makes the casts to size_t below safe.
1070 *
1071 * The max is 4 bytes less than the largest sizeof() so this can be
1072 * tested by putting a SIZE_MAX length in the CBOR test input (no
1073 * one will care the limit on strings is 4 bytes shorter).
1074 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001075 if(uStrLen > SIZE_MAX-4) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001076 uReturn = QCBOR_ERR_STRING_TOO_LONG;
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001077 goto Done;
1078 }
1079
1080 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301081 if(UsefulBuf_IsNULLC(Bytes)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001082 /* Failed to get the bytes for this string item */
1083 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301084 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001085 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301086
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001087#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001088 /* Note that this is not where allocation to coalesce
1089 * indefinite-length strings is done. This is for when the caller
1090 * has requested all strings be allocated. Disabling indefinite
1091 * length strings also disables this allocate-all option.
1092 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001093 if(pAllocator) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001094 /* request to use the string allocator to make a copy */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001095 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301096 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001097 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301098 goto Done;
1099 }
1100 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001101 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001102 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301103 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001104#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1105 (void)pAllocator;
1106#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1107
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001108 /* Normal case with no string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001109 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001110
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301111Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001112 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001113}
1114
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001115
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001116/**
1117 * @brief Map the CBOR major types for strings to the QCBOR types.
1118 *
1119 * @param[in] nCBORMajorType The CBOR major type to convert.
1120 * @retturns QCBOR type number.
1121 *
1122 * This only works for the two string types.
1123 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001124static uint8_t
1125QCBOR_Private_ConvertStringMajorTypes(int nCBORMajorType)
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001126{
1127 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
1128 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
1129 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001130
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001131 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
1132 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
1133 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001134
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001135 return (uint8_t)(nCBORMajorType + 4);
1136}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001137
1138
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001139/**
1140 * @brief Map the CBOR major types for arrays/maps to the QCBOR types.
1141 *
1142 * @param[in] nCBORMajorType The CBOR major type to convert.
1143 * @retturns QCBOR type number.
1144 *
1145 * This only works for the two aggregate types.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001146 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001147static uint8_t
1148QCBORDecode_Private_ConvertArrayOrMapType(int nCBORMajorType)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001149{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001150 #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
1151 #error QCBOR_TYPE_ARRAY value not lined up with major type
1152 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001153
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001154 #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
1155 #error QCBOR_TYPE_MAP value not lined up with major type
1156 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001157
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001158 return (uint8_t)(nCBORMajorType);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001159}
1160
1161
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001162/**
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001163 * @brief Decode a single primitive data item (decode layer 6).
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001164 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001165 * @param[in] pUInBuf Input buffer to read data item from.
1166 * @param[out] pDecodedItem The filled-in decoded item.
1167 * @param[in] pAllocator The allocator to use for strings or NULL.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001168 *
1169 * @retval QCBOR_ERR_UNSUPPORTED
1170 * @retval QCBOR_ERR_HIT_END
1171 * @retval QCBOR_ERR_INT_OVERFLOW
1172 * @retval QCBOR_ERR_STRING_ALLOCATE
1173 * @retval QCBOR_ERR_STRING_TOO_LONG
1174 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001175 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001176 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001177 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1178 *
1179 * This decodes the most primitive / atomic data item. It does
1180 * no combing of data items.
1181 */
1182static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001183QCBOR_Private_DecodeAtomicDataItem(UsefulInputBuf *pUInBuf,
1184 QCBORItem *pDecodedItem,
1185 const QCBORInternalAllocator *pAllocator)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001186{
1187 QCBORError uReturn;
1188
1189 /* Get the major type and the argument. The argument could be
1190 * length of more bytes or the value depending on the major
1191 * type. nAdditionalInfo is an encoding of the length of the
1192 * uNumber and is needed to decode floats and doubles.
1193 */
1194 int nMajorType = 0;
1195 uint64_t uArgument = 0;
1196 int nAdditionalInfo = 0;
1197
1198 memset(pDecodedItem, 0, sizeof(QCBORItem));
1199
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001200 uReturn = QCBOR_Private_DecodeHead(pUInBuf, &nMajorType, &uArgument, &nAdditionalInfo);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001201 if(uReturn) {
1202 goto Done;
1203 }
1204
1205 /* At this point the major type and the argument are valid. We've
1206 * got the type and the argument that starts every CBOR data item.
1207 */
1208 switch (nMajorType) {
1209 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1210 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
1211 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1212 uReturn = QCBOR_ERR_BAD_INT;
1213 } else {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001214 uReturn = QCBOR_Private_DecodeInteger(nMajorType, uArgument, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001215 }
1216 break;
1217
1218 case CBOR_MAJOR_TYPE_BYTE_STRING: /* Major type 2 */
1219 case CBOR_MAJOR_TYPE_TEXT_STRING: /* Major type 3 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001220 pDecodedItem->uDataType = QCBOR_Private_ConvertStringMajorTypes(nMajorType);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001221 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1222 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
1223 } else {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001224 uReturn = QCBOR_Private_DecodeBytes(pAllocator, uArgument, pUInBuf, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001225 }
1226 break;
1227
1228 case CBOR_MAJOR_TYPE_ARRAY: /* Major type 4 */
1229 case CBOR_MAJOR_TYPE_MAP: /* Major type 5 */
1230 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1231 /* Indefinite-length string. */
1232#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
1233 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
1234#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1235 uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
1236 break;
1237#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1238 } else {
1239 /* Definite-length string. */
1240 if(uArgument > QCBOR_MAX_ITEMS_IN_ARRAY) {
1241 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
1242 goto Done;
1243 }
1244 /* cast OK because of check above */
1245 pDecodedItem->val.uCount = (uint16_t)uArgument;
1246 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001247 pDecodedItem->uDataType = QCBORDecode_Private_ConvertArrayOrMapType(nMajorType);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001248 break;
1249
1250 case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */
Laurence Lundblade37286c02022-09-03 10:05:02 -07001251#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001252 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1253 uReturn = QCBOR_ERR_BAD_INT;
1254 } else {
1255 pDecodedItem->val.uTagV = uArgument;
1256 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
1257 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07001258#else /* QCBOR_DISABLE_TAGS */
1259 uReturn = QCBOR_ERR_TAGS_DISABLED;
1260#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001261 break;
1262
1263 case CBOR_MAJOR_TYPE_SIMPLE:
1264 /* Major type 7: float, double, true, false, null... */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001265 uReturn = QCBOR_Private_DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001266 break;
1267
1268 default:
1269 /* Never happens because DecodeHead() should never return > 7 */
1270 uReturn = QCBOR_ERR_UNSUPPORTED;
1271 break;
1272 }
1273
1274Done:
1275 return uReturn;
1276}
1277
1278
1279/**
1280 * @brief Process indefinite-length strings (decode layer 5).
1281 *
1282 * @param[in] pMe Decoder context
1283 * @param[out] pDecodedItem The decoded item that work is done on.
1284 *
1285 * @retval QCBOR_ERR_UNSUPPORTED
1286 * @retval QCBOR_ERR_HIT_END
1287 * @retval QCBOR_ERR_INT_OVERFLOW
1288 * @retval QCBOR_ERR_STRING_ALLOCATE
1289 * @retval QCBOR_ERR_STRING_TOO_LONG
1290 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001291 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001292 * @retval QCBOR_ERR_BAD_TYPE_7
1293 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001294 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1295 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001296 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001297 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001298 * If @c pDecodedItem is not an indefinite-length string, this does nothing.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001299 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001300 * If it is, this loops getting the subsequent chunk data items that
1301 * make up the string. The string allocator is used to make a
1302 * contiguous buffer for the chunks. When this completes @c
1303 * pDecodedItem contains the put-together string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001304 *
1305 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001306 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001307static QCBORError
1308QCBORDecode_Private_GetNextFullString(QCBORDecodeContext *pMe,
1309 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001310{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001311 /* Aproximate stack usage
1312 * 64-bit 32-bit
1313 * local vars 32 16
1314 * 2 UsefulBufs 32 16
1315 * QCBORItem 56 52
1316 * TOTAL 120 74
1317 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001318
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001319 /* The string allocator is used here for two purposes: 1)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001320 * coalescing the chunks of an indefinite-length string, 2)
1321 * allocating storage for every string returned when requested.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001322 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001323 * The first use is below in this function. Indefinite-length
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001324 * strings cannot be processed at all without a string allocator.
1325 *
1326 * The second used is in DecodeBytes() which is called by
1327 * GetNext_Item() below. This second use unneccessary for most use
1328 * and only happens when requested in the call to
1329 * QCBORDecode_SetMemPool(). If the second use not requested then
1330 * NULL is passed for the string allocator to GetNext_Item().
1331 *
1332 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1333 * allocator altogether and thus both of these uses. It reduced the
1334 * decoder object code by about 400 bytes.
1335 */
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001336 const QCBORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001337
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001338#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001339 const QCBORInternalAllocator *pAllocator = NULL;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001340
1341 if(pMe->StringAllocator.pfAllocator) {
1342 pAllocator = &(pMe->StringAllocator);
1343 if(pMe->bStringAllocateAll) {
1344 pAllocatorForGetNext = pAllocator;
1345 }
1346 }
1347#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1348
1349 QCBORError uReturn;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001350 uReturn = QCBOR_Private_DecodeAtomicDataItem(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001351 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001352 goto Done;
1353 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001354
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001355 /* Only do indefinite-length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001356 const uint8_t uStringType = pDecodedItem->uDataType;
1357 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001358 goto Done;
1359 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001360
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001361 /* Is this a string with an indefinite length? */
1362 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1363 goto Done;
1364 }
1365
1366#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001367 /* Can't decode indefinite-length strings without a string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001368 if(pAllocator == NULL) {
1369 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1370 goto Done;
1371 }
1372
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001373 /* Loop getting chunks of the indefinite-length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001374 UsefulBufC FullString = NULLUsefulBufC;
1375
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001376 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001377 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001378 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001379 /* Pass a NULL string allocator to GetNext_Item() because the
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001380 * individual string chunks in an indefinite-length should not
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001381 * be allocated. They are always copied in the the contiguous
1382 * buffer allocated here.
1383 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001384 uReturn = QCBOR_Private_DecodeAtomicDataItem(&(pMe->InBuf), &StringChunkItem, NULL);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001385 if(uReturn) {
1386 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001387 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001388
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001389 /* Is item is the marker for end of the indefinite-length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001390 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001391 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001392 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301393 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001394 break;
1395 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001396
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001397 /* All chunks must be of the same type, the type of the item
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001398 * that introduces the indefinite-length string. This also
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001399 * catches errors where the chunk is not a string at all and an
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001400 * indefinite-length string inside an indefinite-length string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001401 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001402 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001403 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1404 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001405 break;
1406 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001407
David Navarro9123e5b2022-03-28 16:04:03 +02001408 if (StringChunkItem.val.string.len > 0) {
1409 /* The first time throurgh FullString.ptr is NULL and this is
1410 * equivalent to StringAllocator_Allocate(). Subsequently it is
1411 * not NULL and a reallocation happens.
1412 */
1413 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1414 FullString.ptr,
1415 FullString.len + StringChunkItem.val.string.len);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001416
David Navarro9123e5b2022-03-28 16:04:03 +02001417 if(UsefulBuf_IsNULL(NewMem)) {
1418 uReturn = QCBOR_ERR_STRING_ALLOCATE;
1419 break;
1420 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001421
David Navarro9123e5b2022-03-28 16:04:03 +02001422 /* Copy new string chunk to the end of accumulated string */
1423 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001424 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001425 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001426
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001427 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1428 /* Getting the item failed, clean up the allocated memory */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001429 StringAllocator_Free(pAllocator, FullString.ptr);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001430 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001431#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1432 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1433#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001434
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001435Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001436 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001437}
1438
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001439
Laurence Lundblade37286c02022-09-03 10:05:02 -07001440#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001441/**
1442 * @brief This converts a tag number to a shorter mapped value for storage.
1443 *
1444 * @param[in] pMe The decode context.
1445 * @param[in] uUnMappedTag The tag number to map
1446 * @param[out] puMappedTagNumer The stored tag number.
1447 *
1448 * @return error code.
1449 *
1450 * The main point of mapping tag numbers is make QCBORItem
1451 * smaller. With this mapping storage of 4 tags takes up 8
1452 * bytes. Without, it would take up 32 bytes.
1453 *
1454 * This maps tag numbers greater than QCBOR_LAST_UNMAPPED_TAG.
1455 * QCBOR_LAST_UNMAPPED_TAG is a little smaller than MAX_UINT16.
1456 *
1457 * See also UnMapTagNumber() and @ref QCBORItem.
1458 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001459static QCBORError
1460QCBORDecode_Private_MapTagNumber(QCBORDecodeContext *pMe,
1461 const uint64_t uUnMappedTag,
1462 uint16_t *puMappedTagNumer)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001463{
1464 if(uUnMappedTag > QCBOR_LAST_UNMAPPED_TAG) {
1465 unsigned uTagMapIndex;
1466 /* Is there room in the tag map, or is it in it already? */
1467 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
1468 if(pMe->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID64) {
1469 break;
1470 }
1471 if(pMe->auMappedTags[uTagMapIndex] == uUnMappedTag) {
1472 break;
1473 }
1474 }
1475 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1476 return QCBOR_ERR_TOO_MANY_TAGS;
1477 }
1478
1479 /* Covers the cases where tag is new and were it is already in the map */
1480 pMe->auMappedTags[uTagMapIndex] = uUnMappedTag;
1481 *puMappedTagNumer = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
1482
1483 } else {
1484 *puMappedTagNumer = (uint16_t)uUnMappedTag;
1485 }
1486
1487 return QCBOR_SUCCESS;
1488}
1489
1490
1491/**
1492 * @brief This converts a mapped tag number to the actual tag number.
1493 *
1494 * @param[in] pMe The decode context.
1495 * @param[in] uMappedTagNumber The stored tag number.
1496 *
1497 * @return The actual tag number is returned or
1498 * @ref CBOR_TAG_INVALID64 on error.
1499 *
1500 * This is the reverse of MapTagNumber()
1501 */
1502static uint64_t
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001503QCBORDecode_Private_UnMapTagNumber(const QCBORDecodeContext *pMe,
1504 const uint16_t uMappedTagNumber)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001505{
1506 if(uMappedTagNumber <= QCBOR_LAST_UNMAPPED_TAG) {
1507 return uMappedTagNumber;
1508 } else if(uMappedTagNumber == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001509 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001510 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001511 /* This won't be negative because of code below in
1512 * MapTagNumber()
1513 */
1514 const unsigned uIndex = uMappedTagNumber - (QCBOR_LAST_UNMAPPED_TAG + 1);
1515 return pMe->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001516 }
1517}
Laurence Lundblade37286c02022-09-03 10:05:02 -07001518#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001519
Laurence Lundblade9b334962020-08-27 10:55:53 -07001520
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001521/**
1522 * @brief Aggregate all tags wrapping a data item (decode layer 4).
1523 *
1524 * @param[in] pMe Decoder context
1525 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001526
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001527 * @retval QCBOR_ERR_UNSUPPORTED
1528 * @retval QCBOR_ERR_HIT_END
1529 * @retval QCBOR_ERR_INT_OVERFLOW
1530 * @retval QCBOR_ERR_STRING_ALLOCATE
1531 * @retval QCBOR_ERR_STRING_TOO_LONG
1532 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001533 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001534 * @retval QCBOR_ERR_BAD_TYPE_7
1535 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1536 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1537 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1538 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1539 * @retval QCBOR_ERR_TOO_MANY_TAGS
1540 *
1541 * This loops getting atomic data items until one is not a tag
1542 * number. Usually this is largely pass-through because most
1543 * item are not tag numbers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001544 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001545static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001546QCBORDecode_Private_GetNextTagNumber(QCBORDecodeContext *pMe,
1547 QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001548{
Laurence Lundblade37286c02022-09-03 10:05:02 -07001549#ifndef QCBOR_DISABLE_TAGS
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001550 /* Accummulate the tags from multiple items here and then copy them
1551 * into the last item, the non-tag item.
1552 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001553 uint16_t auItemsTags[QCBOR_MAX_TAGS_PER_ITEM];
1554
1555 /* Initialize to CBOR_TAG_INVALID16 */
1556 #if CBOR_TAG_INVALID16 != 0xffff
1557 /* Be sure the memset does the right thing. */
1558 #err CBOR_TAG_INVALID16 tag not defined as expected
1559 #endif
1560 memset(auItemsTags, 0xff, sizeof(auItemsTags));
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001561
Laurence Lundblade9b334962020-08-27 10:55:53 -07001562 QCBORError uReturn = QCBOR_SUCCESS;
1563
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001564 /* Loop fetching data items until the item fetched is not a tag */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001565 for(;;) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001566 QCBORError uErr = QCBORDecode_Private_GetNextFullString(pMe, pDecodedItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07001567 if(uErr != QCBOR_SUCCESS) {
1568 uReturn = uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001569 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001570 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001571
Laurence Lundblade9b334962020-08-27 10:55:53 -07001572 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001573 /* Successful exit from loop; maybe got some tags, maybe not */
1574 memcpy(pDecodedItem->uTags, auItemsTags, sizeof(auItemsTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001575 break;
1576 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001577
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001578 if(auItemsTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1579 /* No room in the tag list */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001580 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001581 /* Continue on to get all tags wrapping this item even though
1582 * it is erroring out in the end. This allows decoding to
1583 * continue. This is a resource limit error, not a problem
1584 * with being well-formed CBOR.
1585 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001586 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001587 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001588 /* Slide tags over one in the array to make room at index 0.
1589 * Must use memmove because the move source and destination
1590 * overlap.
1591 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001592 memmove(&auItemsTags[1],
1593 auItemsTags,
1594 sizeof(auItemsTags) - sizeof(auItemsTags[0]));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001595
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001596 /* Map the tag */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001597 uint16_t uMappedTagNumber = 0;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001598 uReturn = QCBORDecode_Private_MapTagNumber(pMe, pDecodedItem->val.uTagV, &uMappedTagNumber);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001599 /* Continue even on error so as to consume all tags wrapping
1600 * this data item so decoding can go on. If MapTagNumber()
1601 * errors once it will continue to error.
1602 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001603 auItemsTags[0] = uMappedTagNumber;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001604 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001605
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001606Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001607 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001608
Laurence Lundblade37286c02022-09-03 10:05:02 -07001609#else /* QCBOR_DISABLE_TAGS */
1610
1611 return QCBORDecode_GetNextFullString(pMe, pDecodedItem);
1612
1613#endif /* QCBOR_DISABLE_TAGS */
1614}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001615
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001616/**
1617 * @brief Combine a map entry label and value into one item (decode layer 3).
1618 *
1619 * @param[in] pMe Decoder context
1620 * @param[out] pDecodedItem The decoded item that work is done on.
1621 *
1622 * @retval QCBOR_ERR_UNSUPPORTED
1623 * @retval QCBOR_ERR_HIT_END
1624 * @retval QCBOR_ERR_INT_OVERFLOW
1625 * @retval QCBOR_ERR_STRING_ALLOCATE
1626 * @retval QCBOR_ERR_STRING_TOO_LONG
1627 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001628 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001629 * @retval QCBOR_ERR_BAD_TYPE_7
1630 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1631 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1632 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1633 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1634 * @retval QCBOR_ERR_TOO_MANY_TAGS
1635 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1636 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1637 *
1638 * If a the current nesting level is a map, then this
1639 * combines pairs of items into one data item with a label
1640 * and value.
1641 *
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07001642 * This is passthrough if the current nesting level is
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001643 * not a map.
1644 *
1645 * This also implements maps-as-array mode where a map
1646 * is treated like an array to allow caller to do their
1647 * own label processing.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001648 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001649static QCBORError
1650QCBORDecode_Private_GetNextMapEntry(QCBORDecodeContext *pMe,
1651 QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001652{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001653 QCBORError uReturn = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001654 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001655 goto Done;
1656 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001657
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001658 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
1659 /* Break can't be a map entry */
1660 goto Done;
1661 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001662
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001663 if(pMe->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1664 /* Normal decoding of maps -- combine label and value into one item. */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001665
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001666 if(DecodeNesting_IsCurrentTypeMap(&(pMe->nesting))) {
1667 /* Save label in pDecodedItem and get the next which will
1668 * be the real data item.
1669 */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001670 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001671 uReturn = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001672 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001673 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001674 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001675
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301676 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001677
1678 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001679 /* strings are always good labels */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001680 pDecodedItem->label.string = LabelItem.val.string;
1681 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001682 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == pMe->uDecodeMode) {
1683 /* It's not a string and we only want strings */
1684 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001685 goto Done;
1686 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1687 pDecodedItem->label.int64 = LabelItem.val.int64;
1688 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1689 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1690 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1691 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1692 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1693 pDecodedItem->label.string = LabelItem.val.string;
1694 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1695 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1696 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001697 /* label is not an int or a string. It is an arrray
1698 * or a float or such and this implementation doesn't handle that.
1699 * Also, tags on labels are ignored.
1700 */
1701 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001702 goto Done;
1703 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001704 }
1705 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001706 /* Decoding of maps as arrays to let the caller decide what to do
1707 * about labels, particularly lables that are not integers or
1708 * strings.
1709 */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001710 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001711 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001712 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001713 goto Done;
1714 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001715 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001716 /* Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2.
1717 * Cast is needed because of integer promotion.
1718 */
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001719 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001720 }
1721 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001722
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001723Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001724 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001725}
1726
1727
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001728#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001729/**
1730 * @brief Peek and see if next data item is a break;
1731 *
1732 * @param[in] pUIB UsefulInputBuf to read from.
1733 * @param[out] pbNextIsBreak Indicate if next was a break or not.
1734 *
1735 * @return Any decoding error.
1736 *
1737 * See if next item is a CBOR break. If it is, it is consumed,
1738 * if not it is not consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001739*/
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001740static QCBORError
1741QCBOR_Private_NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001742{
1743 *pbNextIsBreak = false;
1744 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001745 QCBORItem Peek;
1746 size_t uPeek = UsefulInputBuf_Tell(pUIB);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001747 QCBORError uReturn = QCBOR_Private_DecodeAtomicDataItem(pUIB, &Peek, NULL);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001748 if(uReturn != QCBOR_SUCCESS) {
1749 return uReturn;
1750 }
1751 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001752 /* It is not a break, rewind so it can be processed normally. */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001753 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001754 } else {
1755 *pbNextIsBreak = true;
1756 }
1757 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001758
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001759 return QCBOR_SUCCESS;
1760}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001761#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001762
1763
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001764/**
1765 * @brief Ascend up nesting levels if all items in them have been consumed.
1766 *
1767 * @param[in] pMe The decode context.
1768 * @param[in] bMarkEnd If true mark end of maps/arrays with count of zero.
1769 *
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001770 * An item was just consumed, now figure out if it was the
1771 * end of an array/map map that can be closed out. That
1772 * may in turn close out the above array/map...
Laurence Lundblade642282a2020-06-23 12:00:33 -07001773*/
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001774static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001775QCBORDecode_Private_NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001776{
1777 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001778
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001779 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001780 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1781
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001782 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1783 /* Nesting level is bstr-wrapped CBOR */
1784
1785 /* Ascent for bstr-wrapped CBOR is always by explicit call
1786 * so no further ascending can happen.
1787 */
1788 break;
1789
1790 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1791 /* Level is a definite-length array/map */
1792
1793 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001794 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1795 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001796 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001797 break;
1798 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001799 /* All items in a definite-length array were consumed so it
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001800 * is time to ascend one level. This happens below.
1801 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001802
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001803#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001804 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001805 /* Level is an indefinite-length array/map. */
1806
1807 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001808 bool bIsBreak = false;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001809 uReturn = QCBOR_Private_NextIsBreak(&(pMe->InBuf), &bIsBreak);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001810 if(uReturn != QCBOR_SUCCESS) {
1811 goto Done;
1812 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001813
1814 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001815 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001816 break;
1817 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001818
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001819 /* It was a break in an indefinitelength map / array so
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001820 * it is time to ascend one level.
1821 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001822
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001823#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001824 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001825
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001826
1827 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001828
Laurence Lundblade93d89472020-10-03 22:30:50 -07001829 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001830 * QCBORDecode_ExitBoundedMode().
1831 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001832 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001833 /* Set the count to zero for definite-length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001834 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001835 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001836 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001837 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001838
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001839 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001840 break;
1841 }
1842
1843 /* Finally, actually ascend one level. */
1844 DecodeNesting_Ascend(&(pMe->nesting));
1845 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001846
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001847 uReturn = QCBOR_SUCCESS;
1848
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001849#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001850Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001851#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1852
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001853 return uReturn;
1854}
1855
1856
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001857/**
1858 * @brief Ascending & Descending out of nesting levels (decode layer 2).
1859 *
1860 * @param[in] pMe Decoder context
1861 * @param[out] pDecodedItem The decoded item that work is done on.
1862 *
1863 * @retval QCBOR_ERR_UNSUPPORTED
1864 * @retval QCBOR_ERR_HIT_END
1865 * @retval QCBOR_ERR_INT_OVERFLOW
1866 * @retval QCBOR_ERR_STRING_ALLOCATE
1867 * @retval QCBOR_ERR_STRING_TOO_LONG
1868 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001869 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001870 * @retval QCBOR_ERR_BAD_TYPE_7
1871 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1872 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1873 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1874 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1875 * @retval QCBOR_ERR_TOO_MANY_TAGS
1876 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1877 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1878 * @retval QCBOR_ERR_NO_MORE_ITEMS
1879 * @retval QCBOR_ERR_BAD_BREAK
1880 * @retval QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
1881 *
1882 * This handles the traversal descending into and asecnding out of
1883 * maps, arrays and bstr-wrapped CBOR. It figures out the ends of
1884 * definite- and indefinte-length maps and arrays by looking at the
1885 * item count or finding CBOR breaks. It detects the ends of the
1886 * top-level sequence and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001887 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001888static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001889QCBORDecode_Private_GetNextMapOrArray(QCBORDecodeContext *pMe,
1890 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001891{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001892 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001893 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001894
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001895 /* If out of bytes to consume, it is either the end of the
1896 * top-level sequence of some bstr-wrapped CBOR that was entered.
1897 *
1898 * In the case of bstr-wrapped CBOR, the length of the
1899 * UsefulInputBuf was set to that of the bstr-wrapped CBOR. When
1900 * the bstr-wrapped CBOR is exited, the length is set back to the
1901 * top-level's length or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001902 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001903 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001904 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001905 goto Done;
1906 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001907
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001908 /* Check to see if at the end of a bounded definite-length map or
1909 * array. The check for a break ending indefinite-length array is
1910 * later in QCBORDecode_NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001911 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001912 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001913 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001914 goto Done;
1915 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001916
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001917 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001918 uReturn = QCBORDecode_Private_GetNextMapEntry(pMe, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001919 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1920 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001921 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001922 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301923
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001924 /* Breaks ending arrays/maps are processed later in the call to
1925 * QCBORDecode_NestLevelAscender(). They should never show up here.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001926 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301927 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001928 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301929 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301930 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001931
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001932 /* Record the nesting level for this data item before processing
1933 * any of decrementing and descending.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001934 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001935 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001936
Laurence Lundblade642282a2020-06-23 12:00:33 -07001937
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001938 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001939 if(QCBORItem_IsMapOrArray(*pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001940 /* If the new item is a map or array, descend.
1941 *
1942 * Empty indefinite-length maps and arrays are descended into,
1943 * but then ascended out of in the next chunk of code.
1944 *
1945 * Maps and arrays do count as items in the map/array that
1946 * encloses them so a decrement needs to be done for them too,
1947 * but that is done only when all the items in them have been
1948 * processed, not when they are opened with the exception of an
1949 * empty map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001950 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001951 QCBORError uDescendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001952 uDescendErr = DecodeNesting_DescendMapOrArray(&(pMe->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001953 pDecodedItem->uDataType,
1954 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001955 if(uDescendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001956 /* This error is probably a traversal error and it overrides
1957 * the non-traversal error.
1958 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001959 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001960 goto Done;
1961 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001962 }
1963
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001964 if(!QCBORItem_IsMapOrArray(*pDecodedItem) ||
1965 QCBORItem_IsEmptyDefiniteLengthMapOrArray(*pDecodedItem) ||
1966 QCBORItem_IsIndefiniteLengthMapOrArray(*pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001967 /* The following cases are handled here:
1968 * - A non-aggregate item like an integer or string
1969 * - An empty definite-length map or array
1970 * - An indefinite-length map or array that might be empty or might not.
1971 *
1972 * QCBORDecode_NestLevelAscender() does the work of decrementing the count
1973 * for an definite-length map/array and break detection for an
1974 * indefinite-0length map/array. If the end of the map/array was
1975 * reached, then it ascends nesting levels, possibly all the way
1976 * to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001977 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001978 QCBORError uAscendErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001979 uAscendErr = QCBORDecode_Private_NestLevelAscender(pMe, true);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001980 if(uAscendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001981 /* This error is probably a traversal error and it overrides
1982 * the non-traversal error.
1983 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001984 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001985 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001986 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301987 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001988
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001989 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001990 /* Tell the caller what level is next. This tells them what
1991 * maps/arrays were closed out and makes it possible for them to
1992 * reconstruct the tree with just the information returned in a
1993 * QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001994 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001995 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001996 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001997 pDecodedItem->uNextNestLevel = 0;
1998 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001999 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002000 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002001
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002002Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002003 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002004}
2005
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002006
Laurence Lundblade37286c02022-09-03 10:05:02 -07002007#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002008/**
2009 * @brief Shift 0th tag out of the tag list.
2010 *
2011 * pDecodedItem[in,out] The data item to convert.
2012 *
2013 * The 0th tag is discarded. \ref CBOR_TAG_INVALID16 is
2014 * shifted into empty slot at the end of the tag list.
2015 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002016static void
2017QCBOR_Private_ShiftTags(QCBORItem *pDecodedItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002018{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002019 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM-1; i++) {
2020 pDecodedItem->uTags[i] = pDecodedItem->uTags[i+1];
2021 }
2022 pDecodedItem->uTags[QCBOR_MAX_TAGS_PER_ITEM-1] = CBOR_TAG_INVALID16;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002023}
2024
Laurence Lundblade37286c02022-09-03 10:05:02 -07002025#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002026
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002027/**
2028 * @brief Convert different epoch date formats in to the QCBOR epoch date format
2029 *
2030 * pDecodedItem[in,out] The data item to convert.
2031 *
2032 * @retval QCBOR_ERR_DATE_OVERFLOW
2033 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002034 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002035 * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002036 *
2037 * The epoch date tag defined in QCBOR allows for floating-point
2038 * dates. It even allows a protocol to flop between date formats when
2039 * ever it wants. Floating-point dates aren't that useful as they are
2040 * only needed for dates beyond the age of the earth.
2041 *
2042 * This converts all the date formats into one format of an unsigned
2043 * integer plus a floating-point fraction.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002044 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002045static QCBORError
2046QCBOR_Private_DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002047{
Laurence Lundbladec7114722020-08-13 05:11:40 -07002048 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002049
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002050#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade59289e52019-12-30 13:44:37 -08002051 pDecodedItem->val.epochDate.fSecondsFraction = 0;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002052#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002053
2054 switch (pDecodedItem->uDataType) {
2055
2056 case QCBOR_TYPE_INT64:
2057 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
2058 break;
2059
2060 case QCBOR_TYPE_UINT64:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002061 /* This only happens for CBOR type 0 > INT64_MAX so it is
2062 * always an overflow.
2063 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002064 uReturn = QCBOR_ERR_DATE_OVERFLOW;
2065 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002066 break;
2067
2068 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07002069 case QCBOR_TYPE_FLOAT:
2070#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08002071 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002072 /* Convert working value to double if input was a float */
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07002073 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002074 pDecodedItem->val.dfnum :
2075 (double)pDecodedItem->val.fnum;
2076
2077 /* The conversion from float to integer requires overflow
2078 * detection since floats can be much larger than integers.
2079 * This implementation errors out on these large float values
2080 * since they are beyond the age of the earth.
2081 *
2082 * These constants for the overflow check are computed by the
2083 * compiler. They are not computed at run time.
2084 *
2085 * The factor of 0x7ff is added/subtracted to avoid a
2086 * rounding error in the wrong direction when the compiler
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002087 * computes these constants. There is rounding because a
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002088 * 64-bit integer has 63 bits of precision where a double
2089 * only has 53 bits. Without the 0x7ff factor, the compiler
2090 * may round up and produce a double for the bounds check
2091 * that is larger than can be stored in a 64-bit integer. The
2092 * amount of 0x7ff is picked because it has 11 bits set.
2093 *
2094 * Without the 0x7ff there is a ~30 minute range of time
2095 * values 10 billion years in the past and in the future
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002096 * where this code could go wrong. Some compilers
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002097 * generate a warning or error without the 0x7ff.
2098 */
2099 const double dDateMax = (double)(INT64_MAX - 0x7ff);
2100 const double dDateMin = (double)(INT64_MIN + 0x7ff);
2101
2102 if(isnan(d) || d > dDateMax || d < dDateMin) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07002103 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002104 goto Done;
2105 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002106
2107 /* The actual conversion */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002108 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07002109 pDecodedItem->val.epochDate.fSecondsFraction =
2110 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002111 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002112#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade4b270642020-08-14 12:53:07 -07002113
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002114 uReturn = QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07002115 goto Done;
2116
Laurence Lundblade9682a532020-06-06 18:33:04 -07002117#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002118 break;
2119
2120 default:
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002121 /* It's the arrays and maps that are unrecoverable because
2122 * they are not consumed here. Since this is just an error
2123 * condition, no extra code is added here to make the error
2124 * recoverable for non-arrays and maps like strings. */
2125 uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002126 goto Done;
2127 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002128
Laurence Lundblade59289e52019-12-30 13:44:37 -08002129 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
2130
2131Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07002132 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002133}
2134
2135
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002136/**
2137 * @brief Convert the days epoch date.
2138 *
2139 * pDecodedItem[in,out] The data item to convert.
2140 *
2141 * @retval QCBOR_ERR_DATE_OVERFLOW
2142 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002143 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002144 * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002145 *
2146 * This is much simpler than the other epoch date format because
2147 * floating-porint is not allowed. This is mostly a simple type check.
2148 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002149static QCBORError
2150QCBOR_Private_DecodeDaysEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002151{
2152 QCBORError uReturn = QCBOR_SUCCESS;
2153
2154 switch (pDecodedItem->uDataType) {
2155
2156 case QCBOR_TYPE_INT64:
2157 pDecodedItem->val.epochDays = pDecodedItem->val.int64;
2158 break;
2159
2160 case QCBOR_TYPE_UINT64:
2161 /* This only happens for CBOR type 0 > INT64_MAX so it is
2162 * always an overflow.
2163 */
2164 uReturn = QCBOR_ERR_DATE_OVERFLOW;
2165 goto Done;
2166 break;
2167
2168 default:
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002169 /* It's the arrays and maps that are unrecoverable because
2170 * they are not consumed here. Since this is just an error
2171 * condition, no extra code is added here to make the error
2172 * recoverable for non-arrays and maps like strings. */
2173 uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002174 goto Done;
2175 break;
2176 }
2177
2178 pDecodedItem->uDataType = QCBOR_TYPE_DAYS_EPOCH;
2179
2180Done:
2181 return uReturn;
2182}
2183
2184
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002185#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade37286c02022-09-03 10:05:02 -07002186
2187/* Forward declaration is necessary for
2188 * QCBORDecode_MantissaAndExponent(). to be able to decode bignum
2189 * tags in the mantissa. If the mantissa is a decimal fraction or big
2190 * float in error, this will result in a recurive call to
2191 * QCBORDecode_MantissaAndExponent(), but the recursion will unwined
2192 * correctly and the correct error is returned.
2193 */
2194static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002195QCBORDecode_Private_GetNextTagContent(QCBORDecodeContext *pMe,
2196 QCBORItem *pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07002197
2198
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002199/**
2200 * @brief Decode decimal fractions and big floats.
2201 *
2202 * @param[in] pMe The decode context.
2203 * @param[in,out] pDecodedItem On input the array data item that
2204 * holds the mantissa and exponent. On
2205 * output the decoded mantissa and
2206 * exponent.
2207 *
2208 * @returns Decoding errors from getting primitive data items or
2209 * \ref QCBOR_ERR_BAD_EXP_AND_MANTISSA.
2210 *
Laurence Lundblade37286c02022-09-03 10:05:02 -07002211 * When called pDecodedItem must be the array with two members, the
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002212 * exponent and mantissa.
2213 *
2214 * This will fetch and decode the exponent and mantissa and put the
2215 * result back into pDecodedItem.
Laurence Lundblade37286c02022-09-03 10:05:02 -07002216 *
2217 * This does no checking or processing of tag numbers. That is to be
2218 * done by the code that calls this.
2219 *
2220 * This stuffs the type of the mantissa into pDecodedItem with the expectation
2221 * the caller will process it.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002222 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07002223static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002224QCBORDecode_Private_ExpMantissa(QCBORDecodeContext *pMe,
2225 QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002226{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002227 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002228
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002229 /* --- Make sure it is an array; track nesting level of members --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002230 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002231 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002232 goto Done;
2233 }
2234
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002235 /* A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundblade37286c02022-09-03 10:05:02 -07002236 * definite-length arrays, but not for indefinite. Instead remember
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002237 * the nesting level the two integers must be at, which is one
2238 * deeper than that of the array.
2239 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002240 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
2241
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002242 /* --- Get the exponent --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002243 QCBORItem exponentItem;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002244 uReturn = QCBORDecode_Private_GetNextMapOrArray(pMe, &exponentItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002245 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002246 goto Done;
2247 }
2248 if(exponentItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002249 /* Array is empty or a map/array encountered when expecting an int */
2250 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002251 goto Done;
2252 }
2253 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002254 /* Data arriving as an unsigned int < INT64_MAX has been
2255 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2256 * also means that the only data arriving here of type
2257 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2258 * and thus an error that will get handled in the next else.
2259 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002260 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
2261 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002262 /* Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX */
2263 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002264 goto Done;
2265 }
2266
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002267 /* --- Get the mantissa --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002268 QCBORItem mantissaItem;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002269 uReturn = QCBORDecode_Private_GetNextTagContent(pMe, &mantissaItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002270 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002271 goto Done;
2272 }
2273 if(mantissaItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002274 /* Mantissa missing or map/array encountered when expecting number */
2275 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002276 goto Done;
2277 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002278 /* Stuff the mantissa data type into the item to send it up to the
2279 * the next level. */
2280 pDecodedItem->uDataType = mantissaItem.uDataType;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002281 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002282 /* Data arriving as an unsigned int < INT64_MAX has been
2283 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2284 * also means that the only data arriving here of type
2285 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2286 * and thus an error that will get handled in an else below.
2287 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002288 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002289#ifndef QCBOR_DISABLE_TAGS
2290 /* With tags fully disabled a big number mantissa will error out
2291 * in the call to QCBORDecode_GetNextWithTags() because it has
2292 * a tag number.
2293 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002294 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
2295 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002296 /* Got a good big num mantissa */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002297 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002298#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002299 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002300 /* Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX */
2301 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002302 goto Done;
2303 }
2304
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002305 /* --- Check that array only has the two numbers --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002306 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002307 /* Extra items in the decimal fraction / big float */
Laurence Lundblade37286c02022-09-03 10:05:02 -07002308 /* Improvement: this should probably be an unrecoverable error. */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002309 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002310 goto Done;
2311 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002312 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002313
2314Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002315 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002316}
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002317#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002318
2319
Laurence Lundblade37286c02022-09-03 10:05:02 -07002320#ifndef QCBOR_DISABLE_TAGS
2321
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002322#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002323/**
2324 * @brief Decode the MIME type tag
2325 *
2326 * @param[in,out] pDecodedItem The item to decode.
2327 *
2328 * Handle the text and binary MIME type tags. Slightly too complicated
2329 * f or ProcessTaggedString() because the RFC 7049 MIME type was
2330 * incorreclty text-only.
2331 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002332static QCBORError
2333QCBOR_Private_DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002334{
2335 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
2336 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07002337 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002338 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
2339 } else {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002340 /* It's the arrays and maps that are unrecoverable because
2341 * they are not consumed here. Since this is just an error
2342 * condition, no extra code is added here to make the error
2343 * recoverable for non-arrays and maps like strings. */
2344 return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002345 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002346
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002347 return QCBOR_SUCCESS;
2348}
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002349#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002350
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002351/**
Laurence Lundblade99615302020-11-29 11:19:47 -08002352 * Table of CBOR tags whose content is either a text string or a byte
2353 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
2354 * of uQCBORtype indicates the content should be a byte string rather
2355 * than a text string
2356 */
2357struct StringTagMapEntry {
2358 uint16_t uTagNumber;
2359 uint8_t uQCBORtype;
2360};
2361
2362#define IS_BYTE_STRING_BIT 0x80
2363#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
2364
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002365static const struct StringTagMapEntry QCBOR_Private_StringTagMap[] = {
Laurence Lundblade99615302020-11-29 11:19:47 -08002366 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002367 {CBOR_TAG_DAYS_STRING, QCBOR_TYPE_DAYS_STRING},
Laurence Lundblade99615302020-11-29 11:19:47 -08002368 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
2369 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
2370 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
2371 {CBOR_TAG_URI, QCBOR_TYPE_URI},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002372#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002373 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
2374 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
2375 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
2376 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002377#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade99615302020-11-29 11:19:47 -08002378 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
2379 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
2380};
2381
2382
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002383/**
2384 * @brief Process standard CBOR tags whose content is a string
2385 *
2386 * @param[in] uTag The tag.
2387 * @param[in,out] pDecodedItem The data item.
2388 *
2389 * @returns This returns QCBOR_SUCCESS if the tag was procssed,
2390 * \ref QCBOR_ERR_UNSUPPORTED if the tag was not processed and
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002391 * \ref QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT if the content type was wrong for the tag.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002392 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002393 * Process the CBOR tags that whose content is a byte string or a text
2394 * string and for which the string is just passed on to the caller.
2395 *
2396 * This maps the CBOR tag to the QCBOR type and checks the content
2397 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08002398 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08002399 * possible.
Laurence Lundblade99615302020-11-29 11:19:47 -08002400 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002401static QCBORError
2402QCBOR_Private_ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002403{
Laurence Lundblade99615302020-11-29 11:19:47 -08002404 /* This only works on tags that were not mapped; no need for other yet */
2405 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
2406 return QCBOR_ERR_UNSUPPORTED;
2407 }
2408
2409 unsigned uIndex;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002410 for(uIndex = 0; QCBOR_Private_StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
2411 if(QCBOR_Private_StringTagMap[uIndex].uTagNumber == uTag) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002412 break;
2413 }
2414 }
2415
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002416 const uint8_t uQCBORType = QCBOR_Private_StringTagMap[uIndex].uQCBORtype;
Laurence Lundblade99615302020-11-29 11:19:47 -08002417 if(uQCBORType == QCBOR_TYPE_NONE) {
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002418 /* repurpose this error to mean not handled here */
Laurence Lundblade99615302020-11-29 11:19:47 -08002419 return QCBOR_ERR_UNSUPPORTED;
2420 }
2421
2422 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
2423 if(uQCBORType & IS_BYTE_STRING_BIT) {
2424 uExpectedType = QCBOR_TYPE_BYTE_STRING;
2425 }
2426
2427 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002428 /* It's the arrays and maps that are unrecoverable because
2429 * they are not consumed here. Since this is just an error
2430 * condition, no extra code is added here to make the error
2431 * recoverable for non-arrays and maps like strings. */
2432 return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002433 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002434
Laurence Lundblade99615302020-11-29 11:19:47 -08002435 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002436 return QCBOR_SUCCESS;
2437}
Laurence Lundblade37286c02022-09-03 10:05:02 -07002438#endif /* QCBOR_DISABLE_TAGS */
2439
2440
2441#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
2442/*
2443 * This returns the QCBOR_TYPE for a mantissa and exponent.
2444
2445Called in one context where there is always a tag
2446
2447 Called in another context where there might be a tag or the caller might say what they are expecting.
2448
2449 6 possible outputs
2450 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002451static uint8_t
2452QCBOR_Private_ExpMantissaDataType(const uint16_t uTagToProcess,
2453 const QCBORItem *pDecodedItem)
Laurence Lundblade37286c02022-09-03 10:05:02 -07002454{
2455 uint8_t uBase = uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ?
2456 QCBOR_TYPE_DECIMAL_FRACTION :
2457 QCBOR_TYPE_BIGFLOAT;
2458 if(pDecodedItem->uDataType != QCBOR_TYPE_INT64) {
2459 uBase = (uint8_t)(uBase + pDecodedItem->uDataType - QCBOR_TYPE_POSBIGNUM + 1);
2460 }
2461 return uBase;
2462}
2463#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002464
2465
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002466/**
2467 * @brief Decode tag content for select tags (decoding layer 1).
2468 *
2469 * @param[in] pMe The decode context.
2470 * @param[out] pDecodedItem The decoded item.
2471 *
2472 * @return Decoding error code.
2473 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002474 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
2475 * but the whole tag was not decoded. Here, the whole tags (tag number
2476 * and tag content) that are supported by QCBOR are decoded. This is a
2477 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002478 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002479static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002480QCBORDecode_Private_GetNextTagContent(QCBORDecodeContext *pMe,
2481 QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002482{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002483 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002484
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002485 uReturn = QCBORDecode_Private_GetNextMapOrArray(pMe, pDecodedItem);
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002486 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002487 goto Done;
2488 }
2489
Laurence Lundblade37286c02022-09-03 10:05:02 -07002490#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002491 /* When there are no tag numbers for the item, this exits first
2492 * thing and effectively does nothing.
2493 *
2494 * This loops over all the tag numbers accumulated for this item
2495 * trying to decode and interpret them. This stops at the end of
2496 * the list or at the first tag number that can't be interpreted by
2497 * this code. This is effectively a recursive processing of the
2498 * tags number list that handles nested tags.
2499 */
2500 while(1) {
2501 /* Don't bother to unmap tags via QCBORITem.uTags since this
2502 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2503 */
2504 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002505
Laurence Lundblade99615302020-11-29 11:19:47 -08002506 if(uTagToProcess == CBOR_TAG_INVALID16) {
2507 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002508 break;
2509
Laurence Lundblade99615302020-11-29 11:19:47 -08002510 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002511 uReturn = QCBOR_Private_DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002512
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002513 } else if(uTagToProcess == CBOR_TAG_DAYS_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002514 uReturn = QCBOR_Private_DecodeDaysEpoch(pDecodedItem);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002515
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002516#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002517 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2518 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002519 uReturn = QCBORDecode_Private_ExpMantissa(pMe, pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07002520 /* --- Which is it, decimal fraction or a bigfloat? --- */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002521 pDecodedItem->uDataType = QCBOR_Private_ExpMantissaDataType(uTagToProcess, pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07002522
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002523#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002524#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002525 } else if(uTagToProcess == CBOR_TAG_MIME ||
2526 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002527 uReturn = QCBOR_Private_DecodeMIME(pDecodedItem);
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002528#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002529
Laurence Lundblade99615302020-11-29 11:19:47 -08002530 } else {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002531 /* See if it is a passthrough byte/text string tag; process if so */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002532 uReturn = QCBOR_Private_ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002533
Laurence Lundblade99615302020-11-29 11:19:47 -08002534 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002535 /* It wasn't a passthrough byte/text string tag so it is
Laurence Lundblade99615302020-11-29 11:19:47 -08002536 * an unknown tag. This is the exit from the loop on the
2537 * first unknown tag. It is a successful exit.
2538 */
2539 uReturn = QCBOR_SUCCESS;
2540 break;
2541 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002542 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002543
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002544 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002545 /* Error exit from the loop */
2546 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002547 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002548
2549 /* A tag was successfully processed, shift it out of the list of
2550 * tags returned. This is the loop increment.
2551 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002552 QCBOR_Private_ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002553 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002554#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002555
2556Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002557 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002558}
2559
2560
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002561/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002562 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002563 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002564QCBORError
2565QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2566{
2567 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002568 uErr = QCBORDecode_Private_GetNextTagContent(pMe, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002569 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002570 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2571 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2572 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002573 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002574}
2575
2576
2577/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002578 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002579 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002580QCBORError
2581QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2582{
2583 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2584 const UsefulInputBuf Save = pMe->InBuf;
2585
2586 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2587
2588 pMe->nesting = SaveNesting;
2589 pMe->InBuf = Save;
2590
2591 return uErr;
2592}
2593
2594
2595/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002596 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002597 */
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002598void
2599QCBORDecode_VPeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2600{
2601 if(pMe->uLastError != QCBOR_SUCCESS) {
2602 return;
2603 }
2604
2605 pMe->uLastError = (uint8_t)QCBORDecode_PeekNext(pMe, pDecodedItem);
2606}
2607
2608
2609/*
2610 * Public function, see header qcbor/qcbor_decode.h file
2611 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002612void
2613QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002614{
2615 if(pMe->uLastError != QCBOR_SUCCESS) {
2616 return;
2617 }
2618
2619 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2620}
2621
2622
2623/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002624 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002625 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002626QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002627QCBORDecode_GetNextWithTags(QCBORDecodeContext *pMe,
2628 QCBORItem *pDecodedItem,
2629 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002630{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002631#ifndef QCBOR_DISABLE_TAGS
2632
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002633 QCBORError uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002634
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002635 uReturn = QCBORDecode_GetNext(pMe, pDecodedItem);
2636 if(uReturn != QCBOR_SUCCESS) {
2637 return uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002638 }
2639
2640 if(pTags != NULL) {
2641 pTags->uNumUsed = 0;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002642 /* Reverse the order because pTags is reverse of QCBORItem.uTags. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002643 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2644 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002645 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002646 }
2647 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2648 return QCBOR_ERR_TOO_MANY_TAGS;
2649 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002650 pTags->puTags[pTags->uNumUsed] = QCBORDecode_Private_UnMapTagNumber(pMe,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002651 pTags->uNumUsed++;
2652 }
2653 }
2654
2655 return QCBOR_SUCCESS;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002656
2657#else /* QCBOR_DISABLE_TAGS */
2658 (void)pMe;
2659 (void)pDecodedItem;
2660 (void)pTags;
2661 return QCBOR_ERR_TAGS_DISABLED;
2662#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002663}
2664
2665
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002666/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002667 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302668 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002669bool
2670QCBORDecode_IsTagged(QCBORDecodeContext *pMe,
2671 const QCBORItem *pItem,
2672 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002673{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002674#ifndef QCBOR_DISABLE_TAGS
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002675 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2676 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002677 break;
2678 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002679 if(QCBORDecode_Private_UnMapTagNumber(pMe, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002680 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002681 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002682 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002683#else /* QCBOR_TAGS_DISABLED */
2684 (void)pMe;
2685 (void)pItem;
2686 (void)uTag;
2687#endif /* QCBOR_TAGS_DISABLED */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002688
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002689 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002690}
2691
2692
2693/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002694 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002695 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002696QCBORError
2697QCBORDecode_PartialFinish(QCBORDecodeContext *pMe, size_t *puConsumed)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002698{
Laurence Lundblade87495732021-02-26 10:05:55 -07002699 if(puConsumed != NULL) {
2700 *puConsumed = pMe->InBuf.cursor;
2701 }
2702
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002703 QCBORError uReturn = pMe->uLastError;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002704
2705 if(uReturn != QCBOR_SUCCESS) {
2706 goto Done;
2707 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002708
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002709 /* Error out if all the maps/arrays are not closed out */
2710 if(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002711 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002712 goto Done;
2713 }
2714
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002715 /* Error out if not all the bytes are consumed */
2716 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002717 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002718 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002719
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002720Done:
Laurence Lundblade87495732021-02-26 10:05:55 -07002721 return uReturn;
2722}
2723
2724
2725/*
2726 * Public function, see header qcbor/qcbor_decode.h file
2727 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002728QCBORError
2729QCBORDecode_Finish(QCBORDecodeContext *pMe)
Laurence Lundblade87495732021-02-26 10:05:55 -07002730{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002731#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002732 /* Call the destructor for the string allocator if there is one.
2733 * Always called, even if there are errors; always have to clean up.
2734 */
2735 StringAllocator_Destruct(&(pMe->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002736#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002737
Laurence Lundblade87495732021-02-26 10:05:55 -07002738 return QCBORDecode_PartialFinish(pMe, NULL);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002739}
2740
2741
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002742/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002743 * Public function, see header qcbor/qcbor_decode.h file
2744 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002745// Improvement: make these inline? TODO:
2746uint64_t
2747QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2748 const QCBORItem *pItem,
2749 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002750{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002751#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002752 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2753 return CBOR_TAG_INVALID64;
2754 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002755 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2756 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002757 } else {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002758 return QCBORDecode_Private_UnMapTagNumber(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002759 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002760#else /* QCBOR_DISABLE_TAGS */
2761 (void)pMe;
2762 (void)pItem;
2763 (void)uIndex;
2764
2765 return CBOR_TAG_INVALID64;
2766#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002767}
2768
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002769
Laurence Lundblade9b334962020-08-27 10:55:53 -07002770/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002771 * Public function, see header qcbor/qcbor_decode.h file
2772 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002773uint64_t
2774QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2775 uint32_t uIndex)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002776{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002777#ifndef QCBOR_DISABLE_TAGS
2778
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002779 if(pMe->uLastError != QCBOR_SUCCESS) {
2780 return CBOR_TAG_INVALID64;
2781 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002782 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2783 return CBOR_TAG_INVALID64;
2784 } else {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002785 return QCBORDecode_Private_UnMapTagNumber(pMe, pMe->uLastTags[uIndex]);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002786 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002787#else /* QCBOR_DISABLE_TAGS */
2788 (void)pMe;
2789 (void)uIndex;
2790
2791 return CBOR_TAG_INVALID64;
2792#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002793}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002794
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002795
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002796
2797
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002798#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002799
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002800/* ===========================================================================
2801 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002802
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002803 This implements a simple sting allocator for indefinite-length
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002804 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2805 implements the function type QCBORStringAllocate and allows easy
2806 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002807
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002808 This particular allocator is built-in for convenience. The caller
2809 can implement their own. All of this following code will get
2810 dead-stripped if QCBORDecode_SetMemPool() is not called.
2811
2812 This is a very primitive memory allocator. It does not track
2813 individual allocations, only a high-water mark. A free or
2814 reallocation must be of the last chunk allocated.
2815
2816 The size of the pool and offset to free memory are packed into the
2817 first 8 bytes of the memory pool so we don't have to keep them in
2818 the decode context. Since the address of the pool may not be
2819 aligned, they have to be packed and unpacked as if they were
2820 serialized data of the wire or such.
2821
2822 The sizes packed in are uint32_t to be the same on all CPU types
2823 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002824 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002825
2826
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002827static int
Laurence Lundbladeee851742020-01-08 08:37:05 -08002828MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002829{
2830 // Use of UsefulInputBuf is overkill, but it is convenient.
2831 UsefulInputBuf UIB;
2832
Laurence Lundbladeee851742020-01-08 08:37:05 -08002833 // Just assume the size here. It was checked during SetUp so
2834 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002835 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002836 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2837 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2838 return UsefulInputBuf_GetError(&UIB);
2839}
2840
2841
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002842static int
Laurence Lundbladeee851742020-01-08 08:37:05 -08002843MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002844{
2845 // Use of UsefulOutBuf is overkill, but convenient. The
2846 // length check performed here is useful.
2847 UsefulOutBuf UOB;
2848
2849 UsefulOutBuf_Init(&UOB, Pool);
2850 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2851 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2852 return UsefulOutBuf_GetError(&UOB);
2853}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002854
2855
2856/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002857 Internal function for an allocation, reallocation free and destuct.
2858
2859 Having only one function rather than one each per mode saves space in
2860 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002861
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002862 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2863 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002864static UsefulBuf
2865MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002866{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002867 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002868
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002869 uint32_t uPoolSize;
2870 uint32_t uFreeOffset;
2871
2872 if(uNewSize > UINT32_MAX) {
2873 // This allocator is only good up to 4GB. This check should
2874 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2875 goto Done;
2876 }
2877 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2878
2879 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2880 goto Done;
2881 }
2882
2883 if(uNewSize) {
2884 if(pMem) {
2885 // REALLOCATION MODE
2886 // Calculate pointer to the end of the memory pool. It is
2887 // assumed that pPool + uPoolSize won't wrap around by
2888 // assuming the caller won't pass a pool buffer in that is
2889 // not in legitimate memory space.
2890 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2891
2892 // Check that the pointer for reallocation is in the range of the
2893 // pool. This also makes sure that pointer math further down
2894 // doesn't wrap under or over.
2895 if(pMem >= pPool && pMem < pPoolEnd) {
2896 // Offset to start of chunk for reallocation. This won't
2897 // wrap under because of check that pMem >= pPool. Cast
2898 // is safe because the pool is always less than UINT32_MAX
2899 // because of check in QCBORDecode_SetMemPool().
2900 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2901
2902 // Check to see if the allocation will fit. uPoolSize -
2903 // uMemOffset will not wrap under because of check that
2904 // pMem is in the range of the uPoolSize by check above.
2905 if(uNewSize <= uPoolSize - uMemOffset) {
2906 ReturnValue.ptr = pMem;
2907 ReturnValue.len = uNewSize;
2908
2909 // Addition won't wrap around over because uNewSize was
2910 // checked to be sure it is less than the pool size.
2911 uFreeOffset = uMemOffset + uNewSize32;
2912 }
2913 }
2914 } else {
2915 // ALLOCATION MODE
2916 // uPoolSize - uFreeOffset will not underflow because this
2917 // pool implementation makes sure uFreeOffset is always
2918 // smaller than uPoolSize through this check here and
2919 // reallocation case.
2920 if(uNewSize <= uPoolSize - uFreeOffset) {
2921 ReturnValue.len = uNewSize;
2922 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002923 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002924 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002925 }
2926 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002927 if(pMem) {
2928 // FREE MODE
2929 // Cast is safe because of limit on pool size in
2930 // QCBORDecode_SetMemPool()
2931 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2932 } else {
2933 // DESTRUCT MODE
2934 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002935 }
2936 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002937
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002938 UsefulBuf Pool = {pPool, uPoolSize};
2939 MemPool_Pack(Pool, uFreeOffset);
2940
2941Done:
2942 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002943}
2944
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002945
Laurence Lundbladef6531662018-12-04 10:42:22 +09002946/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002947 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002948 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002949QCBORError
2950QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2951 UsefulBuf Pool,
2952 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002953{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002954 // The pool size and free mem offset are packed into the beginning
Dave Thaler93c01182022-08-06 15:08:35 -04002955 // of the pool memory. This compile time check makes sure the
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002956 // constant in the header is correct. This check should optimize
2957 // down to nothing.
Dave Thaler93c01182022-08-06 15:08:35 -04002958#ifdef _MSC_VER
2959#pragma warning(push)
2960#pragma warning(disable:4127) // conditional expression is constant
2961#endif
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002962 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002963 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002964 }
Dave Thaler93c01182022-08-06 15:08:35 -04002965#ifdef _MSC_VER
2966#pragma warning(pop)
2967#endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002968
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002969 // The pool size and free offset packed in to the beginning of pool
2970 // memory are only 32-bits. This check will optimize out on 32-bit
2971 // machines.
2972 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002973 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002974 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002975
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002976 // This checks that the pool buffer given is big enough.
2977 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002978 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002979 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002980
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002981 QCBORDecode_SetUpAllocator(pMe, MemPool_Function, Pool.ptr, bAllStrings);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002982
Laurence Lundblade30816f22018-11-10 13:40:22 +07002983 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002984}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002985#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002986
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002987
2988
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002989static void
2990QCBORDecode_Private_CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002991{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002992#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade9b334962020-08-27 10:55:53 -07002993 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
Laurence Lundblade37286c02022-09-03 10:05:02 -07002994#else
2995 (void)pMe;
2996 (void)pItem;
2997#endif
Laurence Lundblade9b334962020-08-27 10:55:53 -07002998}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002999
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003000
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003001/**
3002 * @brief Consume an entire map or array including its contents.
3003 *
3004 * @param[in] pMe The decoder context.
3005 * @param[in] pItemToConsume The array/map whose contents are to be
3006 * consumed.
3007 * @param[out] puNextNestLevel The next nesting level after the item was
3008 * fully consumed.
3009 *
3010 * This may be called when @c pItemToConsume is not an array or
3011 * map. In that case, this is just a pass through for @c puNextNestLevel
3012 * since there is nothing to do.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003013 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003014static QCBORError
3015QCBORDecode_Private_ConsumeItem(QCBORDecodeContext *pMe,
3016 const QCBORItem *pItemToConsume,
3017 uint8_t *puNextNestLevel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003018{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003019 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003020 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003021
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003022 /* If it is a map or array, this will tell if it is empty. */
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003023 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
3024
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003025 if(QCBORItem_IsMapOrArray(*pItemToConsume) && !bIsEmpty) {
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003026 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003027
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003028 /* This works for definite- and indefinite-length maps and
3029 * arrays by using the nesting level
Laurence Lundblade1341c592020-04-11 14:19:05 -07003030 */
3031 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003032 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003033 if(QCBORDecode_IsUnrecoverableError(uReturn) ||
3034 uReturn == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003035 goto Done;
3036 }
3037 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003038
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003039 *puNextNestLevel = Item.uNextNestLevel;
3040
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003041 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003042
Laurence Lundblade1341c592020-04-11 14:19:05 -07003043 } else {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003044 /* pItemToConsume is not a map or array. Just pass the nesting
3045 * level through. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003046 *puNextNestLevel = pItemToConsume->uNextNestLevel;
3047
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003048 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003049 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003050
3051Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003052 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003053}
3054
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003055
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003056/*
3057 * Public function, see header qcbor/qcbor_decode.h file
3058 */
3059void
3060QCBORDecode_VGetNextConsume(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003061{
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003062 QCBORDecode_VGetNext(pMe, pDecodedItem);
3063
3064 if(pMe->uLastError == QCBOR_SUCCESS) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003065 pMe->uLastError = (uint8_t)QCBORDecode_Private_ConsumeItem(pMe, pDecodedItem,
Máté Tóth-Pálc6d59682021-05-26 18:55:30 +02003066 &pDecodedItem->uNextNestLevel);
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003067 }
3068}
3069
3070
3071
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003072/* Call only on maps and arrays. Rewinds the cursor
3073 * to the start as if it was just entered.
3074 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003075static void
3076QCBORDecode_Private_RewindMapOrArray(QCBORDecodeContext *pMe)
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003077{
3078 /* Reset nesting tracking to the deepest bounded level */
3079 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
3080
3081 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3082
3083 /* Reposition traversal cursor to the start of the map/array */
3084 UsefulInputBuf_Seek(&(pMe->InBuf),
3085 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
3086}
3087
3088
3089/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003090 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003091 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003092void
3093QCBORDecode_Rewind(QCBORDecodeContext *pMe)
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003094{
3095 if(pMe->nesting.pCurrentBounded != NULL) {
3096 /* In a bounded map, array or bstr-wrapped CBOR */
3097
3098 if(DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
3099 /* In bstr-wrapped CBOR. */
3100
3101 /* Reposition traversal cursor to start of wrapping byte string */
3102 UsefulInputBuf_Seek(&(pMe->InBuf),
3103 pMe->nesting.pCurrentBounded->u.bs.uBstrStartOffset);
3104 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
3105
3106 } else {
3107 /* In a map or array */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003108 QCBORDecode_Private_RewindMapOrArray(pMe);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003109 }
3110
3111 } else {
3112 /* Not in anything bounded */
3113
3114 /* Reposition traversal cursor to the start of input CBOR */
3115 UsefulInputBuf_Seek(&(pMe->InBuf), 0ULL);
3116
3117 /* Reset nesting tracking to beginning of input. */
3118 DecodeNesting_Init(&(pMe->nesting));
3119 }
3120
3121 pMe->uLastError = QCBOR_SUCCESS;
3122}
3123
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003124
Laurence Lundblade9b334962020-08-27 10:55:53 -07003125
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003126
3127
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003128/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003129 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003130
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003131 @param[in] pMe The decode context to search.
3132 @param[in,out] pItemArray The items to search for and the items found.
3133 @param[out] puOffset Byte offset of last item matched.
3134 @param[in] pCBContext Context for the not-found item call back.
3135 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003136
3137 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
3138
Laurence Lundblade93d89472020-10-03 22:30:50 -07003139 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
3140 were found for one of the labels being
3141 search for. This duplicate detection is
3142 only performed for items in pItemArray,
3143 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003144
Laurence Lundblade93d89472020-10-03 22:30:50 -07003145 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
3146 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003147
3148 @retval Also errors returned by QCBORDecode_GetNext().
3149
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003150 On input pItemArray contains a list of labels and data types
3151 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07003152
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003153 On output the fully retrieved items are filled in with
3154 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07003155
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003156 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003157
3158 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003159 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003160static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003161QCBORDecode_Private_MapSearch(QCBORDecodeContext *pMe,
3162 QCBORItem *pItemArray,
3163 size_t *puOffset,
3164 void *pCBContext,
3165 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003166{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003167 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003168 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07003169
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003170 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003171 uReturn = pMe->uLastError;
3172 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003173 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003174
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003175 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003176 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
3177 /* QCBOR_TYPE_NONE as first item indicates just looking
3178 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003179 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
3180 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003181 }
3182
Laurence Lundblade085d7952020-07-24 10:26:30 -07003183 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
3184 // It is an empty bounded array or map
3185 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
3186 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003187 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07003188 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003189 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003190 // Nothing is ever found in an empty array or map. All items
3191 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07003192 uReturn = QCBOR_SUCCESS;
3193 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003194 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003195 }
3196
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003197 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003198 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
3199
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003200 /* Reposition to search from the start of the map / array */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003201 QCBORDecode_Private_RewindMapOrArray(pMe);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003202
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003203 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003204 Loop over all the items in the map or array. Each item
3205 could be a map or array, but label matching is only at
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003206 the main level. This handles definite- and indefinite-
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003207 length maps and arrays. The only reason this is ever
3208 called on arrays is to find their end position.
3209
3210 This will always run over all items in order to do
3211 duplicate detection.
3212
3213 This will exit with failure if it encounters an
3214 unrecoverable error, but continue on for recoverable
3215 errors.
3216
3217 If a recoverable error occurs on a matched item, then
3218 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003219 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07003220 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Máté Tóth-Pál2f2aa5f2021-05-17 21:35:09 +02003221 uint8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003222 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003223 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07003224 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003225
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003226 /* Get the item */
3227 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003228 QCBORError uResult = QCBORDecode_Private_GetNextTagContent(pMe, &Item);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003229 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003230 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003231 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003232 goto Done;
3233 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003234 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003235 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003236 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003237 goto Done;
3238 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003239
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003240 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003241 bool bMatched = false;
3242 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003243 if(QCBORItem_MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003244 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003245 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
3246 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003247 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003248 }
Laurence Lundblade63926052021-03-29 16:05:51 -07003249 if(uResult != QCBOR_SUCCESS) {
3250 /* The label matches, but the data item is in error */
3251 uReturn = uResult;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003252 goto Done;
3253 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003254 if(!QCBORItem_MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade63926052021-03-29 16:05:51 -07003255 /* The data item is not of the type(s) requested */
3256 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003257 goto Done;
3258 }
3259
Laurence Lundblade1341c592020-04-11 14:19:05 -07003260 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003261 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003262 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003263 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003264 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003265 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003266 bMatched = true;
3267 }
3268 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003269
3270
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003271 if(!bMatched && pfCallback != NULL) {
3272 /*
3273 Call the callback on unmatched labels.
3274 (It is tempting to do duplicate detection here, but that would
3275 require dynamic memory allocation because the number of labels
3276 that might be encountered is unbounded.)
3277 */
3278 uReturn = (*pfCallback)(pCBContext, &Item);
3279 if(uReturn != QCBOR_SUCCESS) {
3280 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003281 }
3282 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003283
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003284 /*
3285 Consume the item whether matched or not. This
3286 does the work of traversing maps and array and
3287 everything in them. In this loop only the
3288 items at the current nesting level are examined
3289 to match the labels.
3290 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003291 uReturn = QCBORDecode_Private_ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003292 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003293 goto Done;
3294 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003295 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003296
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003297 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003298
3299 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003300
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003301 // Check here makes sure that this won't accidentally be
3302 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003303 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003304 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
3305 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003306 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
3307 goto Done;
3308 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003309 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
3310 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003311
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003312 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003313 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
3314
3315 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003316 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07003317 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003318 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003319 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
3320 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003321 }
3322 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003323
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003324 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003325}
3326
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003327
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003328/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003329 * Public function, see header qcbor/qcbor_decode.h file
3330 */
3331void
3332QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
3333 int64_t nLabel,
3334 uint8_t uQcborType,
3335 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003336{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003337 if(pMe->uLastError != QCBOR_SUCCESS) {
3338 return;
3339 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003340
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003341 QCBORItem OneItemSeach[2];
3342 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3343 OneItemSeach[0].label.int64 = nLabel;
3344 OneItemSeach[0].uDataType = uQcborType;
3345 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003346
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003347 QCBORError uReturn = QCBORDecode_Private_MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003348
3349 *pItem = OneItemSeach[0];
3350
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003351 if(uReturn != QCBOR_SUCCESS) {
3352 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003353 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003354 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003355 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003356 }
3357
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003358 Done:
3359 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003360}
3361
3362
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003363/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003364 * Public function, see header qcbor/qcbor_decode.h file
3365 */
3366void
3367QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
3368 const char *szLabel,
3369 uint8_t uQcborType,
3370 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003371{
Laurence Lundbladeda095972020-06-06 18:35:33 -07003372 if(pMe->uLastError != QCBOR_SUCCESS) {
3373 return;
3374 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003375
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003376 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003377 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3378 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3379 OneItemSeach[0].uDataType = uQcborType;
3380 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003381
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003382 QCBORError uReturn = QCBORDecode_Private_MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003383 if(uReturn != QCBOR_SUCCESS) {
3384 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003385 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003386 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003387 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003388 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003389 }
3390
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003391 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003392
3393Done:
3394 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003395}
3396
3397
Laurence Lundblade93d89472020-10-03 22:30:50 -07003398static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003399QCBOR_Private_CheckTypeList(const int uDataType,
3400 const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003401{
3402 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08003403 if(uDataType == puTypeList[i]) { /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003404 return QCBOR_SUCCESS;
3405 }
3406 }
3407 return QCBOR_ERR_UNEXPECTED_TYPE;
3408}
3409
Laurence Lundblade67257dc2020-07-27 03:33:37 -07003410
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003411/**
Laurence Lundblade37286c02022-09-03 10:05:02 -07003412 * Match a tag/type specification against the type of the item.
3413 *
3414 * @param[in] TagSpec Specification for matching tags.
3415 * @param[in] pItem The item to check.
3416 *
3417 * @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
3418 * @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
3419 *
3420 * This checks the item data type of untagged items as well as of
3421 * tagged items against a specification to see if decoding should
3422 * proceed.
3423 *
3424 * This relies on the automatic tag decoding done by QCBOR that turns
3425 * tag numbers into particular QCBOR_TYPEs so there is no actual
3426 * comparsion of tag numbers, just of QCBOR_TYPEs.
3427 *
3428 * This checks the data item type as possibly representing the tag
3429 * number or as the tag content type.
3430 *
3431 * If QCBOR_DISABLE_TAGS is #defined, this primarily checks the item
3432 * data type against the allowed tag content types. It will also error out
3433 * if the caller tries to require a tag because there is no way that can
3434 * ever be fulfilled.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003435 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07003436static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003437QCBOR_Private_CheckTagRequirement(const QCBOR_Private_TagSpec TagSpec,
3438 const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07003439{
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08003440 const int nItemType = pItem->uDataType; /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade37286c02022-09-03 10:05:02 -07003441 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
3442
3443#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08003444 /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003445 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
3446 pItem->uTags[0] != CBOR_TAG_INVALID16) {
3447 /* There are tags that QCBOR couldn't process on this item and
Laurence Lundblade37286c02022-09-03 10:05:02 -07003448 * the caller has told us there should not be.
3449 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003450 return QCBOR_ERR_UNEXPECTED_TYPE;
3451 }
3452
Laurence Lundblade9b334962020-08-27 10:55:53 -07003453 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
Laurence Lundblade37286c02022-09-03 10:05:02 -07003454 /* Must match the tag number and only the tag */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003455 return QCBOR_Private_CheckTypeList(nItemType, TagSpec.uTaggedTypes);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003456 }
3457
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003458 QCBORError uReturn = QCBOR_Private_CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003459 if(uReturn == QCBOR_SUCCESS) {
3460 return QCBOR_SUCCESS;
3461 }
3462
3463 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
3464 /* Must match the content type and only the content type.
Laurence Lundblade37286c02022-09-03 10:05:02 -07003465 * There was no match just above so it is a fail. */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003466 return QCBOR_ERR_UNEXPECTED_TYPE;
3467 }
3468
Laurence Lundblade37286c02022-09-03 10:05:02 -07003469 /* QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG: If here it can match either the tag or the content
3470 * and it hasn't matched the content, so the end
3471 * result is whether it matches the tag. This is
3472 * the tag optional case that the CBOR standard discourages.
3473 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003474
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003475 return QCBOR_Private_CheckTypeList(nItemType, TagSpec.uTaggedTypes);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003476
Laurence Lundblade37286c02022-09-03 10:05:02 -07003477#else /* QCBOR_DISABLE_TAGS */
3478 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
3479 return QCBOR_ERR_UNEXPECTED_TYPE;
3480 }
3481
3482 return CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
3483
3484#endif /* QCBOR_DISABLE_TAGS */
3485}
Laurence Lundblade9b334962020-08-27 10:55:53 -07003486
Laurence Lundblade9b334962020-08-27 10:55:53 -07003487
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003488// This could be semi-private if need be
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003489// TODO: decide what to do
3490static void
3491QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
3492 const int64_t nLabel,
3493 const QCBOR_Private_TagSpec TagSpec,
3494 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003495{
3496 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
3497 if(pMe->uLastError != QCBOR_SUCCESS) {
3498 return;
3499 }
3500
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003501 pMe->uLastError = (uint8_t)QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003502}
3503
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003504
3505// This could be semi-private if need be
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003506static void
3507QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
3508 const char *szLabel,
3509 const QCBOR_Private_TagSpec TagSpec,
3510 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003511{
3512 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
3513 if(pMe->uLastError != QCBOR_SUCCESS) {
3514 return;
3515 }
3516
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003517 pMe->uLastError = (uint8_t)QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003518}
3519
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003520// Semi-private
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003521void
3522QCBORDecode_Private_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
3523 const int64_t nLabel,
3524 const QCBOR_Private_TagSpec TagSpec,
3525 UsefulBufC *pString)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003526{
3527 QCBORItem Item;
3528 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
3529 if(pMe->uLastError == QCBOR_SUCCESS) {
3530 *pString = Item.val.string;
3531 }
3532}
3533
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003534// Semi-private
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003535void
3536QCBORDecode_Private_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
3537 const char * szLabel,
3538 const QCBOR_Private_TagSpec TagSpec,
3539 UsefulBufC *pString)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003540{
3541 QCBORItem Item;
3542 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
3543 if(pMe->uLastError == QCBOR_SUCCESS) {
3544 *pString = Item.val.string;
3545 }
3546}
Laurence Lundblade1341c592020-04-11 14:19:05 -07003547
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003548/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003549 * Public function, see header qcbor/qcbor_decode.h file
3550 */
3551void
3552QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003553{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003554 QCBORError uErr = QCBORDecode_Private_MapSearch(pMe, pItemList, NULL, NULL, NULL);
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003555 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003556}
3557
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003558/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003559 * Public function, see header qcbor/qcbor_decode.h file
3560 */
3561void
3562QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3563 QCBORItem *pItemList,
3564 void *pCallbackCtx,
3565 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003566{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003567 QCBORError uErr = QCBORDecode_Private_MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003568 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003569}
3570
3571
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003572/**
3573 * @brief Search for a map/array by label and enter it
3574 *
3575 * @param[in] pMe The decode context.
3576 * @param[in] pSearch The map/array to search for.
3577 *
3578 * @c pSearch is expected to contain one item of type map or array
3579 * with the label specified. The current bounded map will be searched for
3580 * this and if found will be entered.
3581 *
3582 * If the label is not found, or the item found is not a map or array,
3583 * the error state is set.
3584 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003585static void
3586QCBORDecode_Private_SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003587{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003588 // The first item in pSearch is the one that is to be
3589 // entered. It should be the only one filled in. Any other
3590 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003591 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003592 return;
3593 }
3594
3595 size_t uOffset;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003596 pMe->uLastError = (uint8_t)QCBORDecode_Private_MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003597 if(pMe->uLastError != QCBOR_SUCCESS) {
3598 return;
3599 }
3600
Laurence Lundblade9b334962020-08-27 10:55:53 -07003601 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003602 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003603 return;
3604 }
3605
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003606
3607 /* The map or array was found. Now enter it.
3608 *
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003609 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3610 * next item for the pre-order traversal cursor to be the map/array
3611 * found by MapSearch(). The next few lines of code force the
3612 * cursor to that.
3613 *
3614 * There is no need to retain the old cursor because
3615 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3616 * beginning of the map/array being entered.
3617 *
3618 * The cursor is forced by: 1) setting the input buffer position to
3619 * the item offset found by MapSearch(), 2) setting the map/array
3620 * counter to the total in the map/array, 3) setting the nesting
3621 * level. Setting the map/array counter to the total is not
3622 * strictly correct, but this is OK because this cursor only needs
3623 * to be used to get one item and MapSearch() has already found it
3624 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003625 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003626 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003627
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003628 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3629
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003630 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003631
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003632 QCBORDecode_Private_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003633}
3634
3635
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003636/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003637 * Public function, see header qcbor/qcbor_decode.h file
3638 */
3639void
3640QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003641{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003642 QCBORItem OneItemSeach[2];
3643 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3644 OneItemSeach[0].label.int64 = nLabel;
3645 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3646 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003647
Laurence Lundblade9b334962020-08-27 10:55:53 -07003648 /* The map to enter was found, now finish off entering it. */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003649 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003650}
3651
3652
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003653/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003654 * Public function, see header qcbor/qcbor_decode.h file
3655 */
3656void
3657QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003658{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003659 QCBORItem OneItemSeach[2];
3660 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3661 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3662 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3663 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003664
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003665 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003666}
3667
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003668/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003669 * Public function, see header qcbor/qcbor_decode.h file
3670 */
3671void
3672QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003673{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003674 QCBORItem OneItemSeach[2];
3675 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3676 OneItemSeach[0].label.int64 = nLabel;
3677 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3678 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003679
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003680 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003681}
3682
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003683/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003684 * Public function, see header qcbor/qcbor_decode.h file
3685 */
3686void
3687QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundblade34691b92020-05-18 22:25:25 -07003688{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003689 QCBORItem OneItemSeach[2];
3690 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3691 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3692 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3693 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003694
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003695 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003696}
3697
3698
Laurence Lundblade02625d42020-06-25 14:41:41 -07003699// Semi-private function
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003700void
3701QCBORDecode_Private_EnterBoundedMapOrArray(QCBORDecodeContext *pMe,
3702 const uint8_t uType,
3703 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003704{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003705 QCBORError uErr;
3706
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003707 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003708 if(pMe->uLastError != QCBOR_SUCCESS) {
3709 // Already in error state; do nothing.
3710 return;
3711 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003712
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003713 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003714 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003715 uErr = QCBORDecode_GetNext(pMe, &Item);
3716 if(uErr != QCBOR_SUCCESS) {
3717 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003718 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003719 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003720 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3721 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003722 }
3723
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003724 QCBORDecode_Private_CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003725
3726
Laurence Lundbladef0499502020-08-01 11:55:57 -07003727 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003728 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003729 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3730 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003731 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003732 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3733 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003734 // Special case to increment nesting level for zero-length maps
3735 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003736 DecodeNesting_Descend(&(pMe->nesting), uType);
3737 }
3738
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003739 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003740
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003741 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3742 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003743
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003744 if(pItem != NULL) {
3745 *pItem = Item;
3746 }
3747
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003748Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003749 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003750}
3751
Laurence Lundblade02625d42020-06-25 14:41:41 -07003752
3753/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003754 This is the common work for exiting a level that is a bounded map,
3755 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003756
3757 One chunk of work is to set up the pre-order traversal so it is at
3758 the item just after the bounded map, array or bstr that is being
3759 exited. This is somewhat complex.
3760
3761 The other work is to level-up the bounded mode to next higest bounded
3762 mode or the top level if there isn't one.
3763 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003764static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003765QCBORDecode_Private_ExitBoundedLevel(QCBORDecodeContext *pMe,
3766 const uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003767{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003768 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003769
Laurence Lundblade02625d42020-06-25 14:41:41 -07003770 /*
3771 First the pre-order-traversal byte offset is positioned to the
3772 item just after the bounded mode item that was just consumed.
3773 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003774 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3775
Laurence Lundblade02625d42020-06-25 14:41:41 -07003776 /*
3777 Next, set the current nesting level to one above the bounded level
3778 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003779
Laurence Lundblade02625d42020-06-25 14:41:41 -07003780 DecodeNesting_CheckBoundedType() is always called before this and
3781 makes sure pCurrentBounded is valid.
3782 */
3783 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3784
3785 /*
3786 This does the complex work of leveling up the pre-order traversal
3787 when the end of a map or array or another bounded level is
3788 reached. It may do nothing, or ascend all the way to the top
3789 level.
3790 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003791 uErr = QCBORDecode_Private_NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003792 if(uErr != QCBOR_SUCCESS) {
3793 goto Done;
3794 }
3795
Laurence Lundblade02625d42020-06-25 14:41:41 -07003796 /*
3797 This makes the next highest bounded level the current bounded
3798 level. If there is no next highest level, then no bounded mode is
3799 in effect.
3800 */
3801 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003802
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003803 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003804
3805Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003806 return uErr;
3807}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003808
Laurence Lundblade02625d42020-06-25 14:41:41 -07003809
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003810// Semi-private function
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003811void
3812QCBORDecode_Private_ExitBoundedMapOrArray(QCBORDecodeContext *pMe,
3813 const uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003814{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003815 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003816 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003817 return;
3818 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003819
Laurence Lundblade02625d42020-06-25 14:41:41 -07003820 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003821
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003822 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003823 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003824 goto Done;
3825 }
3826
Laurence Lundblade02625d42020-06-25 14:41:41 -07003827 /*
3828 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003829 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003830 from previous map search, then do a dummy search.
3831 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003832 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003833 QCBORItem Dummy;
3834 Dummy.uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003835 uErr = QCBORDecode_Private_MapSearch(pMe, &Dummy, NULL, NULL, NULL);
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003836 if(uErr != QCBOR_SUCCESS) {
3837 goto Done;
3838 }
3839 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003840
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003841 uErr = QCBORDecode_Private_ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003842
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003843Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003844 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003845}
3846
3847
Laurence Lundblade1341c592020-04-11 14:19:05 -07003848
Laurence Lundblade37286c02022-09-03 10:05:02 -07003849static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003850QCBORDecode_Private_EnterBstrWrapped(QCBORDecodeContext *pMe,
3851 const QCBORItem *pItem,
3852 const uint8_t uTagRequirement,
3853 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003854{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003855 if(pBstr) {
3856 *pBstr = NULLUsefulBufC;
3857 }
3858
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003859 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003860 /* Already in error state; do nothing. */
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003861 return pMe->uLastError;
3862 }
3863
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003864 QCBORError uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003865
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003866 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003867 {
3868 uTagRequirement,
3869 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3870 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3871 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003872
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003873 uError = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003874 if(uError != QCBOR_SUCCESS) {
3875 goto Done;
3876 }
3877
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003878 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003879 /* Reverse the decrement done by GetNext() for the bstr so the
3880 * increment in QCBORDecode_NestLevelAscender() called by
3881 * ExitBoundedLevel() will work right.
3882 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003883 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003884 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003885
3886 if(pBstr) {
3887 *pBstr = pItem->val.string;
3888 }
3889
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003890 /* This saves the current length of the UsefulInputBuf and then
3891 * narrows the UsefulInputBuf to start and length of the wrapped
3892 * CBOR that is being entered.
3893 *
3894 * Most of these calls are simple inline accessors so this doesn't
3895 * amount to much code.
3896 */
3897
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003898 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003899 /* This check makes the cast of uPreviousLength to uint32_t below safe. */
3900 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003901 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003902 goto Done;
3903 }
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003904
3905 const size_t uStartOfBstr = UsefulInputBuf_PointerToOffset(&(pMe->InBuf),
3906 pItem->val.string.ptr);
3907 /* This check makes the cast of uStartOfBstr to uint32_t below safe. */
3908 if(uStartOfBstr == SIZE_MAX || uStartOfBstr > QCBOR_MAX_DECODE_INPUT_SIZE) {
3909 /* This should never happen because pItem->val.string.ptr should
3910 * always be valid since it was just returned.
3911 */
3912 uError = QCBOR_ERR_INPUT_TOO_LARGE;
3913 goto Done;
3914 }
3915
3916 const size_t uEndOfBstr = uStartOfBstr + pItem->val.string.len;
3917
3918 UsefulInputBuf_Seek(&(pMe->InBuf), uStartOfBstr);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003919 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003920
Laurence Lundblade02625d42020-06-25 14:41:41 -07003921 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003922 (uint32_t)uPreviousLength,
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003923 (uint32_t)uStartOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003924Done:
3925 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003926}
3927
3928
Laurence Lundblade02625d42020-06-25 14:41:41 -07003929/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003930 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07003931 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003932void
3933QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
3934 const uint8_t uTagRequirement,
3935 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003936{
3937 if(pMe->uLastError != QCBOR_SUCCESS) {
3938 // Already in error state; do nothing.
3939 return;
3940 }
3941
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003942 /* Get the data item that is the byte string being entered */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003943 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003944 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3945 if(pMe->uLastError != QCBOR_SUCCESS) {
3946 return;
3947 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003948
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003949 pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
3950 &Item,
3951 uTagRequirement,
3952 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003953}
3954
3955
Laurence Lundblade02625d42020-06-25 14:41:41 -07003956/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003957 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07003958 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003959void
3960QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
3961 const int64_t nLabel,
3962 const uint8_t uTagRequirement,
3963 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003964{
3965 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003966 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003967
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003968 pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
3969 &Item,
3970 uTagRequirement,
3971 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003972}
3973
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003974
Laurence Lundblade02625d42020-06-25 14:41:41 -07003975/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003976 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07003977 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003978void
3979QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
3980 const char *szLabel,
3981 const uint8_t uTagRequirement,
3982 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003983{
3984 QCBORItem Item;
3985 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3986
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003987 pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
3988 &Item,
3989 uTagRequirement,
3990 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003991}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003992
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003993
Laurence Lundblade02625d42020-06-25 14:41:41 -07003994/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003995 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07003996 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003997void
3998QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003999{
Laurence Lundblade02625d42020-06-25 14:41:41 -07004000 if(pMe->uLastError != QCBOR_SUCCESS) {
4001 // Already in error state; do nothing.
4002 return;
4003 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004004
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07004005 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07004006 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07004007 return;
4008 }
4009
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004010 const uint32_t uEndOfBstr = (uint32_t)UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
4011
Laurence Lundblade02625d42020-06-25 14:41:41 -07004012 /*
4013 Reset the length of the UsefulInputBuf to what it was before
4014 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004015 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07004016 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004017 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004018
4019
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004020 QCBORError uErr = QCBORDecode_Private_ExitBoundedLevel(pMe, uEndOfBstr);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004021 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004022}
4023
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004024
Laurence Lundbladee6430642020-03-14 21:15:44 -07004025
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07004026
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004027static void
4028QCBORDecode_Private_ProcessBool(QCBORDecodeContext *pMe,
4029 const QCBORItem *pItem,
4030 bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004031{
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004032 if(pMe->uLastError != QCBOR_SUCCESS) {
4033 /* Already in error state, do nothing */
4034 return;
4035 }
4036
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004037 switch(pItem->uDataType) {
4038 case QCBOR_TYPE_TRUE:
4039 *pBool = true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004040 break;
4041
4042 case QCBOR_TYPE_FALSE:
4043 *pBool = false;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004044 break;
4045
4046 default:
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004047 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004048 break;
4049 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004050 QCBORDecode_Private_CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004051}
Laurence Lundbladee6430642020-03-14 21:15:44 -07004052
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004053
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004054/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004055 * Public function, see header qcbor/qcbor_decode.h file
4056 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004057void
4058QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004059{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004060 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004061 /* Already in error state, do nothing */
Laurence Lundbladee6430642020-03-14 21:15:44 -07004062 return;
4063 }
4064
Laurence Lundbladec4537442020-04-14 18:53:22 -07004065 QCBORItem Item;
4066
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004067 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4068
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004069 QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004070}
4071
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004072
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004073/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004074 * Public function, see header qcbor/qcbor_decode.h file
4075 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004076void
4077QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe,
4078 const int64_t nLabel,
4079 bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004080{
4081 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004082 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004083
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004084 QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004085}
4086
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004087
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004088/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004089 * Public function, see header qcbor/qcbor_decode.h file
4090 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004091void
4092QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe,
4093 const char *szLabel,
4094 bool *pValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004095{
4096 QCBORItem Item;
4097 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4098
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004099 QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004100}
4101
4102
4103
Laurence Lundbladec7114722020-08-13 05:11:40 -07004104
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004105static void
4106QCBORDecode_Private_ProcessEpochDate(QCBORDecodeContext *pMe,
4107 QCBORItem *pItem,
4108 const uint8_t uTagRequirement,
4109 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07004110{
4111 if(pMe->uLastError != QCBOR_SUCCESS) {
4112 // Already in error state, do nothing
4113 return;
4114 }
4115
4116 QCBORError uErr;
4117
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004118 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladec7114722020-08-13 05:11:40 -07004119 {
4120 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004121 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4122 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07004123 };
4124
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004125 uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004126 if(uErr != QCBOR_SUCCESS) {
4127 goto Done;
4128 }
4129
4130 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004131 uErr = QCBOR_Private_DecodeDateEpoch(pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004132 if(uErr != QCBOR_SUCCESS) {
4133 goto Done;
4134 }
4135 }
4136
Laurence Lundblade9b334962020-08-27 10:55:53 -07004137 // Save the tags in the last item's tags in the decode context
4138 // for QCBORDecode_GetNthTagOfLast()
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004139 QCBORDecode_Private_CopyTags(pMe, pItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07004140
Laurence Lundbladec7114722020-08-13 05:11:40 -07004141 *pnTime = pItem->val.epochDate.nSeconds;
4142
4143Done:
4144 pMe->uLastError = (uint8_t)uErr;
4145}
4146
4147
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004148void
4149QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
4150 uint8_t uTagRequirement,
4151 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07004152{
4153 if(pMe->uLastError != QCBOR_SUCCESS) {
4154 // Already in error state, do nothing
4155 return;
4156 }
4157
4158 QCBORItem Item;
4159 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4160
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004161 QCBORDecode_Private_ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004162}
4163
4164
4165void
4166QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
4167 int64_t nLabel,
4168 uint8_t uTagRequirement,
4169 int64_t *pnTime)
4170{
4171 QCBORItem Item;
4172 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004173 QCBORDecode_Private_ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004174}
4175
4176
4177void
4178QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
4179 const char *szLabel,
4180 uint8_t uTagRequirement,
4181 int64_t *pnTime)
4182{
4183 QCBORItem Item;
4184 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004185 QCBORDecode_Private_ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004186}
4187
4188
4189
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004190/*
4191 * Common processing for the RFC 8943 day-count tag. Mostly
4192 * make sure the tag content is correct and copy forward any
4193 * further other tag numbers.
4194 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004195static void
4196QCBORDecode_Private_ProcessEpochDays(QCBORDecodeContext *pMe,
4197 QCBORItem *pItem,
4198 uint8_t uTagRequirement,
4199 int64_t *pnDays)
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004200{
4201 if(pMe->uLastError != QCBOR_SUCCESS) {
4202 /* Already in error state, do nothing */
4203 return;
4204 }
4205
4206 QCBORError uErr;
4207
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004208 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004209 {
4210 uTagRequirement,
4211 {QCBOR_TYPE_DAYS_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4212 {QCBOR_TYPE_INT64, QCBOR_TYPE_UINT64, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4213 };
4214
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004215 uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004216 if(uErr != QCBOR_SUCCESS) {
4217 goto Done;
4218 }
4219
4220 if(pItem->uDataType != QCBOR_TYPE_DAYS_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004221 uErr = QCBOR_Private_DecodeDaysEpoch(pItem);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004222 if(uErr != QCBOR_SUCCESS) {
4223 goto Done;
4224 }
4225 }
4226
4227 /* Save the tags in the last item's tags in the decode context
4228 * for QCBORDecode_GetNthTagOfLast()
4229 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004230 QCBORDecode_Private_CopyTags(pMe, pItem);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004231
4232 *pnDays = pItem->val.epochDays;
4233
4234Done:
4235 pMe->uLastError = (uint8_t)uErr;
4236}
4237
4238
4239/*
4240 * Public function, see header qcbor/qcbor_decode.h
4241 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004242void
4243QCBORDecode_GetEpochDays(QCBORDecodeContext *pMe,
4244 uint8_t uTagRequirement,
4245 int64_t *pnDays)
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004246{
4247 if(pMe->uLastError != QCBOR_SUCCESS) {
4248 /* Already in error state, do nothing */
4249 return;
4250 }
4251
4252 QCBORItem Item;
4253 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4254
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004255 QCBORDecode_Private_ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004256}
4257
4258
4259/*
4260 * Public function, see header qcbor/qcbor_decode.h
4261 */
4262void
4263QCBORDecode_GetEpochDaysInMapN(QCBORDecodeContext *pMe,
4264 int64_t nLabel,
4265 uint8_t uTagRequirement,
4266 int64_t *pnDays)
4267{
4268 QCBORItem Item;
4269 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004270 QCBORDecode_Private_ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004271}
4272
4273
4274/*
4275 * Public function, see header qcbor/qcbor_decode.h
4276 */
4277void
4278QCBORDecode_GetEpochDaysInMapSZ(QCBORDecodeContext *pMe,
4279 const char *szLabel,
4280 uint8_t uTagRequirement,
4281 int64_t *pnDays)
4282{
4283 QCBORItem Item;
4284 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004285 QCBORDecode_Private_ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004286}
4287
4288
4289
Laurence Lundblade37286c02022-09-03 10:05:02 -07004290/*
4291 * @brief Get a string that matches the type/tag specification.
4292 */
4293void
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004294QCBORDecode_Private_GetTaggedString(QCBORDecodeContext *pMe,
4295 const QCBOR_Private_TagSpec TagSpec,
4296 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004297{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004298 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade37286c02022-09-03 10:05:02 -07004299 /* Already in error state, do nothing */
Laurence Lundbladec4537442020-04-14 18:53:22 -07004300 return;
4301 }
4302
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004303 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004304 QCBORItem Item;
4305
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004306 uError = QCBORDecode_GetNext(pMe, &Item);
4307 if(uError != QCBOR_SUCCESS) {
4308 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004309 return;
4310 }
4311
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004312 pMe->uLastError = (uint8_t)QCBOR_Private_CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004313
4314 if(pMe->uLastError == QCBOR_SUCCESS) {
4315 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07004316 } else {
4317 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004318 }
4319}
4320
Laurence Lundbladec4537442020-04-14 18:53:22 -07004321
4322
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004323
Laurence Lundblade37286c02022-09-03 10:05:02 -07004324static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004325QCBOR_Private_ProcessBigNum(const uint8_t uTagRequirement,
4326 const QCBORItem *pItem,
4327 UsefulBufC *pValue,
4328 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004329{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004330 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004331 {
4332 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004333 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4334 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004335 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004336
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004337 QCBORError uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004338 if(uErr != QCBOR_SUCCESS) {
4339 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004340 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004341
4342 *pValue = pItem->val.string;
4343
4344 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
4345 *pbIsNegative = false;
4346 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
4347 *pbIsNegative = true;
4348 }
4349
4350 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004351}
4352
4353
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004354/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004355 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004356 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004357void
4358QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
4359 const uint8_t uTagRequirement,
4360 UsefulBufC *pValue,
4361 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004362{
4363 if(pMe->uLastError != QCBOR_SUCCESS) {
4364 // Already in error state, do nothing
4365 return;
4366 }
4367
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004368 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004369 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4370 if(uError != QCBOR_SUCCESS) {
4371 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004372 return;
4373 }
4374
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004375 pMe->uLastError = (uint8_t)QCBOR_Private_ProcessBigNum(uTagRequirement,
4376 &Item,
4377 pValue,
4378 pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004379}
4380
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004381
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004382/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004383 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004384*/
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004385void
4386QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
4387 const int64_t nLabel,
4388 const uint8_t uTagRequirement,
4389 UsefulBufC *pValue,
4390 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004391{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004392 QCBORItem Item;
4393 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004394 if(pMe->uLastError != QCBOR_SUCCESS) {
4395 return;
4396 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004397
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004398 pMe->uLastError = (uint8_t)QCBOR_Private_ProcessBigNum(uTagRequirement,
4399 &Item,
4400 pValue,
4401 pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004402}
4403
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004404
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004405/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004406 * Public function, see header qcbor/qcbor_decode.h
4407 */
4408void
4409QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
4410 const char *szLabel,
4411 const uint8_t uTagRequirement,
4412 UsefulBufC *pValue,
4413 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004414{
4415 QCBORItem Item;
4416 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004417 if(pMe->uLastError != QCBOR_SUCCESS) {
4418 return;
4419 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004420
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004421 pMe->uLastError = (uint8_t)QCBOR_Private_ProcessBigNum(uTagRequirement,
4422 &Item,
4423 pValue,
4424 pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004425}
4426
4427
4428
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004429
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004430// Semi private
Laurence Lundblade37286c02022-09-03 10:05:02 -07004431QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004432QCBORDecode_Private_GetMIME(const uint8_t uTagRequirement,
Laurence Lundblade37286c02022-09-03 10:05:02 -07004433 const QCBORItem *pItem,
4434 UsefulBufC *pMessage,
4435 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004436{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004437 const QCBOR_Private_TagSpec TagSpecText =
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004438 {
4439 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004440 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4441 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004442 };
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004443 const QCBOR_Private_TagSpec TagSpecBinary =
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004444 {
4445 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004446 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4447 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004448 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004449
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004450 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07004451
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004452 if(QCBOR_Private_CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004453 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004454 if(pbIsTag257 != NULL) {
4455 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004456 }
4457 uReturn = QCBOR_SUCCESS;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004458 } else if(QCBOR_Private_CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004459 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004460 if(pbIsTag257 != NULL) {
4461 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004462 }
4463 uReturn = QCBOR_SUCCESS;
4464
4465 } else {
4466 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
4467 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07004468
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004469 return uReturn;
4470}
4471
Laurence Lundblade93d89472020-10-03 22:30:50 -07004472// Improvement: add methods for wrapped CBOR, a simple alternate
4473// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004474
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004475
4476
4477
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004478#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07004479
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004480typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004481
4482
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004483/**
4484 * @brief Base 10 exponentiate a mantissa and exponent into an unsigned 64-bit integer.
4485 *
4486 * @param[in] uMantissa The unsigned integer mantissa.
4487 * @param[in] nExponent The signed integer exponent.
4488 * @param[out] puResult Place to return the unsigned integer result.
4489 *
4490 * This computes: mantissa * 10 ^^ exponent as for a decimal fraction. The output is a 64-bit
4491 * unsigned integer.
4492 *
4493 * There are many inputs for which the result will not fit in the
4494 * 64-bit integer and \ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will
4495 * be returned.
4496 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004497static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004498QCBOR_Private_Exponentitate10(const uint64_t uMantissa,
4499 int64_t nExponent,
4500 uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004501{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004502 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004503
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004504 if(uResult != 0) {
4505 /* This loop will run a maximum of 19 times because
4506 * UINT64_MAX < 10 ^^ 19. More than that will cause
4507 * exit with the overflow error
4508 */
4509 for(; nExponent > 0; nExponent--) {
4510 if(uResult > UINT64_MAX / 10) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004511 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004512 }
4513 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004514 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004515
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004516 for(; nExponent < 0; nExponent++) {
4517 uResult = uResult / 10;
4518 if(uResult == 0) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004519 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004520 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004521 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004522 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004523 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07004524
4525 *puResult = uResult;
4526
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004527 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004528}
4529
4530
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004531/**
4532 * @brief Base 2 exponentiate a mantissa and exponent into an unsigned 64-bit integer.
4533 *
4534 * @param[in] uMantissa The unsigned integer mantissa.
4535 * @param[in] nExponent The signed integer exponent.
4536 * @param[out] puResult Place to return the unsigned integer result.
4537 *
4538 * This computes: mantissa * 2 ^^ exponent as for a big float. The
4539 * output is a 64-bit unsigned integer.
4540 *
4541 * There are many inputs for which the result will not fit in the
4542 * 64-bit integer and \ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will
4543 * be returned.
4544 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004545static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004546QCBOR_Private_Exponentitate2(const uint64_t uMantissa,
4547 int64_t nExponent,
4548 uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004549{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004550 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004551
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004552 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004553
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004554 /* This loop will run a maximum of 64 times because INT64_MAX <
4555 * 2^31. More than that will cause exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07004556 */
4557 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004558 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004559 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004560 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004561 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004562 nExponent--;
4563 }
4564
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004565 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004566 if(uResult == 0) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004567 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004568 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004569 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004570 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004571 }
4572
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004573 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004574
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004575 return QCBOR_SUCCESS;
4576}
4577
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004578
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004579/**
4580 * @brief Exponentiate a signed mantissa and signed exponent to produce a signed result.
4581 *
4582 * @param[in] nMantissa Signed integer mantissa.
4583 * @param[in] nExponent Signed integer exponent.
4584 * @param[out] pnResult Place to put the signed integer result.
4585 * @param[in] pfExp Exponentiation function.
4586 *
4587 * @returns Error code
4588 *
4589 * \c pfExp performs exponentiation on and unsigned mantissa and
4590 * produces an unsigned result. This converts the mantissa from signed
4591 * and converts the result to signed. The exponentiation function is
4592 * either for base 2 or base 10 (and could be other if needed).
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004593 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004594static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004595QCBOR_Private_ExponentiateNN(const int64_t nMantissa,
4596 const int64_t nExponent,
4597 int64_t *pnResult,
4598 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004599{
4600 uint64_t uResult;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004601 uint64_t uMantissa;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004602
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004603 /* Take the absolute value and put it into an unsigned. */
4604 if(nMantissa >= 0) {
4605 /* Positive case is straightforward */
4606 uMantissa = (uint64_t)nMantissa;
4607 } else if(nMantissa != INT64_MIN) {
4608 /* The common negative case. See next. */
4609 uMantissa = (uint64_t)-nMantissa;
4610 } else {
4611 /* int64_t and uint64_t are always two's complement per the
4612 * C standard (and since QCBOR uses these it only works with
4613 * two's complement, which is pretty much universal these
4614 * days). The range of a negative two's complement integer is
4615 * one more that than a positive, so the simple code above might
4616 * not work all the time because you can't simply negate the
4617 * value INT64_MIN because it can't be represented in an
4618 * int64_t. -INT64_MIN can however be represented in a
4619 * uint64_t. Some compilers seem to recognize this case for the
4620 * above code and put the correct value in uMantissa, however
4621 * they are not required to do this by the C standard. This next
4622 * line does however work for all compilers.
4623 *
4624 * This does assume two's complement where -INT64_MIN ==
4625 * INT64_MAX + 1 (which wouldn't be true for one's complement or
4626 * sign and magnitude (but we know we're using two's complement
4627 * because int64_t requires it)).
4628 *
4629 * See these, particularly the detailed commentary:
4630 * https://stackoverflow.com/questions/54915742/does-c99-mandate-a-int64-t-type-be-available-always
4631 * https://stackoverflow.com/questions/37301078/is-negating-int-min-undefined-behaviour
4632 */
4633 uMantissa = (uint64_t)INT64_MAX+1;
4634 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004635
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004636 /* Call the exponentiator passed for either base 2 or base 10.
4637 * Here is where most of the overflow errors are caught. */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004638 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
4639 if(uReturn) {
4640 return uReturn;
4641 }
4642
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004643 /* Convert back to the sign of the original mantissa */
4644 if(nMantissa >= 0) {
4645 if(uResult > INT64_MAX) {
4646 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4647 }
4648 *pnResult = (int64_t)uResult;
4649 } else {
4650 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
4651 * of INT64_MIN. This assumes two's compliment representation
4652 * where INT64_MIN is one increment farther from 0 than
4653 * INT64_MAX. Trying to write -INT64_MIN doesn't work to get
4654 * this because the compiler makes it an int64_t which can't
4655 * represent -INT64_MIN. Also see above.
4656 */
4657 if(uResult > (uint64_t)INT64_MAX+1) {
4658 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4659 }
4660 *pnResult = -(int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004661 }
4662
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004663 return QCBOR_SUCCESS;
4664}
4665
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004666
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004667/**
4668 * @brief Exponentiate an unsigned mantissa and signed exponent to produce an unsigned result.
4669 *
4670 * @param[in] nMantissa Signed integer mantissa.
4671 * @param[in] nExponent Signed integer exponent.
4672 * @param[out] puResult Place to put the signed integer result.
4673 * @param[in] pfExp Exponentiation function.
4674 *
4675 * @returns Error code
4676 *
4677 * \c pfExp performs exponentiation on and unsigned mantissa and
4678 * produces an unsigned result. This errors out if the mantissa
4679 * is negative because the output is unsigned.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004680 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004681static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004682QCBOR_Private_ExponentitateNU(const int64_t nMantissa,
4683 const int64_t nExponent,
4684 uint64_t *puResult,
4685 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004686{
4687 if(nMantissa < 0) {
4688 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4689 }
4690
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004691 /* Cast to unsigned is OK because of check for negative.
4692 * Cast to unsigned is OK because UINT64_MAX > INT64_MAX.
4693 * Exponentiation is straight forward
4694 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004695 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
4696}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004697
4698
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004699/**
4700 * @brief Exponentiate an usnigned mantissa and unsigned exponent to produce an unsigned result.
4701 *
4702 * @param[in] uMantissa Unsigned integer mantissa.
4703 * @param[in] nExponent Unsigned integer exponent.
4704 * @param[out] puResult Place to put the unsigned integer result.
4705 * @param[in] pfExp Exponentiation function.
4706 *
4707 * @returns Error code
4708 *
4709 * \c pfExp performs exponentiation on and unsigned mantissa and
4710 * produces an unsigned result so this is just a wrapper that does
4711 * nothing (and is likely inlined).
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004712 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004713static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004714QCBOR_Private_ExponentitateUU(const uint64_t uMantissa,
4715 const int64_t nExponent,
4716 uint64_t *puResult,
4717 fExponentiator pfExp)
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004718{
4719 return (*pfExp)(uMantissa, nExponent, puResult);
4720}
4721
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004722#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004723
4724
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004725
4726
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004727/**
4728 * @brief Convert a CBOR big number to a uint64_t.
4729 *
4730 * @param[in] BigNum Bytes of the big number to convert.
4731 * @param[in] uMax Maximum value allowed for the result.
4732 * @param[out] pResult Place to put the unsigned integer result.
4733 *
4734 * @returns Error code
4735 *
4736 * Many values will overflow because a big num can represent a much
4737 * larger range than uint64_t.
4738 */
4739static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004740QCBOR_Private_ConvertBigNumToUnsigned(const UsefulBufC BigNum,
4741 const uint64_t uMax,
4742 uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004743{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004744 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004745
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004746 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004747 const uint8_t *pByte = BigNum.ptr;
4748 size_t uLen = BigNum.len;
4749 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07004750 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004751 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004752 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07004753 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004754 }
4755
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004756 *pResult = uResult;
4757 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004758}
4759
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004760
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004761/**
4762 * @brief Convert a CBOR postive big number to a uint64_t.
4763 *
4764 * @param[in] BigNum Bytes of the big number to convert.
4765 * @param[out] pResult Place to put the unsigned integer result.
4766 *
4767 * @returns Error code
4768 *
4769 * Many values will overflow because a big num can represent a much
4770 * larger range than uint64_t.
4771 */
4772static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004773QCBOR_Private_ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum,
4774 uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004775{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004776 return QCBOR_Private_ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004777}
4778
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004779
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004780/**
4781 * @brief Convert a CBOR positive big number to an int64_t.
4782 *
4783 * @param[in] BigNum Bytes of the big number to convert.
4784 * @param[out] pResult Place to put the signed integer result.
4785 *
4786 * @returns Error code
4787 *
4788 * Many values will overflow because a big num can represent a much
4789 * larger range than int64_t.
4790 */
4791static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004792QCBOR_Private_ConvertPositiveBigNumToSigned(const UsefulBufC BigNum,
4793 int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004794{
4795 uint64_t uResult;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004796 QCBORError uError = QCBOR_Private_ConvertBigNumToUnsigned(BigNum,
4797 INT64_MAX,
4798 &uResult);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004799 if(uError) {
4800 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004801 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004802 /* Cast is safe because ConvertBigNumToUnsigned limits to INT64_MAX */
Laurence Lundbladee6430642020-03-14 21:15:44 -07004803 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004804 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004805}
4806
4807
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004808/**
4809 * @brief Convert a CBOR negative big number to an int64_t.
4810 *
4811 * @param[in] BigNum Bytes of the big number to convert.
4812 * @param[out] pnResult Place to put the signed integer result.
4813 *
4814 * @returns Error code
4815 *
4816 * Many values will overflow because a big num can represent a much
4817 * larger range than int64_t.
4818 */
4819static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004820QCBOR_Private_ConvertNegativeBigNumToSigned(const UsefulBufC BigNum,
4821 int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004822{
4823 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004824 /* The negative integer furthest from zero for a C int64_t is
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004825 * INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
4826 * negative number in CBOR is computed as -n - 1 where n is the
4827 * encoded integer, where n is what is in the variable BigNum. When
4828 * converting BigNum to a uint64_t, the maximum value is thus
4829 * INT64_MAX, so that when it -n - 1 is applied to it the result
4830 * will never be further from 0 than INT64_MIN.
4831 *
4832 * -n - 1 <= INT64_MIN.
4833 * -n - 1 <= -INT64_MAX - 1
4834 * n <= INT64_MAX.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004835 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004836 QCBORError uError = QCBOR_Private_ConvertBigNumToUnsigned(BigNum,
4837 INT64_MAX,
4838 &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004839 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004840 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004841 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004842
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004843 /* Now apply -n - 1. The cast is safe because
4844 * ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
4845 * is the largest positive integer that an int64_t can
4846 * represent. */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004847 *pnResult = -(int64_t)uResult - 1;
4848
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004849 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004850}
4851
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004852
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004853
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004854
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004855
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004856/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004857Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004858
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004859\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004860
Laurence Lundblade93d89472020-10-03 22:30:50 -07004861\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4862 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004863
4864\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4865
Laurence Lundblade93d89472020-10-03 22:30:50 -07004866\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4867 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004868*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07004869static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004870QCBOR_Private_ConvertInt64(const QCBORItem *pItem,
4871 const uint32_t uConvertTypes,
4872 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004873{
4874 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004875 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004876 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004877#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004878 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004879 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
4880 http://www.cplusplus.com/reference/cmath/llround/
4881 */
4882 // Not interested in FE_INEXACT
4883 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004884 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4885 *pnValue = llround(pItem->val.dfnum);
4886 } else {
4887 *pnValue = lroundf(pItem->val.fnum);
4888 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004889 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4890 // llround() shouldn't result in divide by zero, but catch
4891 // it here in case it unexpectedly does. Don't try to
4892 // distinguish between the various exceptions because it seems
4893 // they vary by CPU, compiler and OS.
4894 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004895 }
4896 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004897 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004898 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004899#else
4900 return QCBOR_ERR_HW_FLOAT_DISABLED;
4901#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004902 break;
4903
4904 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004905 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004906 *pnValue = pItem->val.int64;
4907 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004908 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004909 }
4910 break;
4911
4912 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004913 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004914 if(pItem->val.uint64 < INT64_MAX) {
4915 *pnValue = pItem->val.int64;
4916 } else {
4917 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4918 }
4919 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004920 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004921 }
4922 break;
4923
4924 default:
4925 return QCBOR_ERR_UNEXPECTED_TYPE;
4926 }
4927 return QCBOR_SUCCESS;
4928}
4929
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004930
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004931void
4932QCBORDecode_Private_GetInt64Convert(QCBORDecodeContext *pMe,
4933 uint32_t uConvertTypes,
4934 int64_t *pnValue,
4935 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004936{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004937 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004938 return;
4939 }
4940
Laurence Lundbladee6430642020-03-14 21:15:44 -07004941 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004942 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4943 if(uError) {
4944 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004945 return;
4946 }
4947
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004948 if(pItem) {
4949 *pItem = Item;
4950 }
4951
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004952 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(&Item,
4953 uConvertTypes,
4954 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004955}
4956
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004957
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004958void
4959QCBORDecode_Private_GetInt64ConvertInMapN(QCBORDecodeContext *pMe,
4960 int64_t nLabel,
4961 uint32_t uConvertTypes,
4962 int64_t *pnValue,
4963 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004964{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004965 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004966 if(pMe->uLastError != QCBOR_SUCCESS) {
4967 return;
4968 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004969
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004970 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
4971 uConvertTypes,
4972 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004973}
4974
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004975
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004976void
4977QCBORDecode_Private_GetInt64ConvertInMapSZ(QCBORDecodeContext *pMe,
4978 const char * szLabel,
4979 uint32_t uConvertTypes,
4980 int64_t *pnValue,
4981 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004982{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004983 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004984 if(pMe->uLastError != QCBOR_SUCCESS) {
4985 return;
4986 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004987
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004988 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
4989 uConvertTypes,
4990 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004991}
4992
4993
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004994/*
4995 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004996
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004997 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004998
Laurence Lundblade93d89472020-10-03 22:30:50 -07004999 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
5000 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005001
5002 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
5003
Laurence Lundblade93d89472020-10-03 22:30:50 -07005004 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
5005 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005006 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07005007static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005008QCBOR_Private_Int64ConvertAll(const QCBORItem *pItem,
5009 const uint32_t uConvertTypes,
5010 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005011{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005012 switch(pItem->uDataType) {
5013
5014 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005015 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005016 return QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005017 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005018 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005019 }
5020 break;
5021
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005022 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005023 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005024 return QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005025 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005026 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005027 }
5028 break;
5029
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005030#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005031 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005032 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005033 return QCBOR_Private_ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005034 pItem->val.expAndMantissa.nExponent,
5035 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005036 &QCBOR_Private_Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005037 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005038 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005039 }
5040 break;
5041
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005042 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005043 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005044 return QCBOR_Private_ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005045 pItem->val.expAndMantissa.nExponent,
5046 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005047 QCBOR_Private_Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005048 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005049 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005050 }
5051 break;
5052
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005053 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005054 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005055 int64_t nMantissa;
5056 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005057 uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005058 if(uErr) {
5059 return uErr;
5060 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005061 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005062 pItem->val.expAndMantissa.nExponent,
5063 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005064 QCBOR_Private_Exponentitate10);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005065 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005066 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005067 }
5068 break;
5069
5070 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005071 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005072 int64_t nMantissa;
5073 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005074 uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005075 if(uErr) {
5076 return uErr;
5077 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005078 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005079 pItem->val.expAndMantissa.nExponent,
5080 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005081 QCBOR_Private_Exponentitate10);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005082 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005083 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005084 }
5085 break;
5086
5087 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005088 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005089 int64_t nMantissa;
5090 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005091 uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005092 if(uErr) {
5093 return uErr;
5094 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005095 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005096 pItem->val.expAndMantissa.nExponent,
5097 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005098 QCBOR_Private_Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005099 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005100 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005101 }
5102 break;
5103
5104 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005105 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005106 int64_t nMantissa;
5107 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005108 uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005109 if(uErr) {
5110 return uErr;
5111 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005112 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005113 pItem->val.expAndMantissa.nExponent,
5114 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005115 QCBOR_Private_Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005116 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005117 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005118 }
5119 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005120#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005121
Laurence Lundbladee6430642020-03-14 21:15:44 -07005122
Laurence Lundbladec4537442020-04-14 18:53:22 -07005123 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005124 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005125}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005126
5127
Laurence Lundbladec4537442020-04-14 18:53:22 -07005128/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005129 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005130 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005131void
5132QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe,
5133 const uint32_t uConvertTypes,
5134 int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07005135{
5136 QCBORItem Item;
5137
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005138 QCBORDecode_Private_GetInt64Convert(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07005139
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005140 if(pMe->uLastError == QCBOR_SUCCESS) {
5141 // The above conversion succeeded
5142 return;
5143 }
5144
Laurence Lundbladef6c86662020-05-12 02:08:00 -07005145 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005146 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07005147 return;
5148 }
5149
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005150 pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
5151 uConvertTypes,
5152 pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005153}
5154
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005155
5156/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005157 * Public function, see header qcbor/qcbor_decode.h file
5158 */
5159void
5160QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
5161 const int64_t nLabel,
5162 const uint32_t uConvertTypes,
5163 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005164{
5165 QCBORItem Item;
5166
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005167 QCBORDecode_Private_GetInt64ConvertInMapN(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07005168 nLabel,
5169 uConvertTypes,
5170 pnValue,
5171 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005172
5173 if(pMe->uLastError == QCBOR_SUCCESS) {
5174 // The above conversion succeeded
5175 return;
5176 }
5177
5178 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5179 // The above conversion failed in a way that code below can't correct
5180 return;
5181 }
5182
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005183 pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
5184 uConvertTypes,
5185 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005186}
5187
5188
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005189/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005190 * Public function, see header qcbor/qcbor_decode.h file
5191 */
5192void
5193QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
5194 const char *szLabel,
5195 const uint32_t uConvertTypes,
5196 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005197{
5198 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005199 QCBORDecode_Private_GetInt64ConvertInMapSZ(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07005200 szLabel,
5201 uConvertTypes,
5202 pnValue,
5203 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005204
5205 if(pMe->uLastError == QCBOR_SUCCESS) {
5206 // The above conversion succeeded
5207 return;
5208 }
5209
5210 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5211 // The above conversion failed in a way that code below can't correct
5212 return;
5213 }
5214
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005215 pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
5216 uConvertTypes,
5217 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005218}
5219
5220
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005221static QCBORError
5222QCBOR_Private_ConvertUInt64(const QCBORItem *pItem,
5223 const uint32_t uConvertTypes,
5224 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005225{
5226 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005227 case QCBOR_TYPE_DOUBLE:
5228 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005229#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005230 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005231 // Can't use llround here because it will not convert values
5232 // greater than INT64_MAX and less than UINT64_MAX that
5233 // need to be converted so it is more complicated.
5234 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
5235 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
5236 if(isnan(pItem->val.dfnum)) {
5237 return QCBOR_ERR_FLOAT_EXCEPTION;
5238 } else if(pItem->val.dfnum < 0) {
5239 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5240 } else {
5241 double dRounded = round(pItem->val.dfnum);
5242 // See discussion in DecodeDateEpoch() for
5243 // explanation of - 0x7ff
5244 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
5245 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5246 }
5247 *puValue = (uint64_t)dRounded;
5248 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005249 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005250 if(isnan(pItem->val.fnum)) {
5251 return QCBOR_ERR_FLOAT_EXCEPTION;
5252 } else if(pItem->val.fnum < 0) {
5253 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5254 } else {
5255 float fRounded = roundf(pItem->val.fnum);
5256 // See discussion in DecodeDateEpoch() for
5257 // explanation of - 0x7ff
5258 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
5259 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5260 }
5261 *puValue = (uint64_t)fRounded;
5262 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005263 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005264 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
5265 // round() and roundf() shouldn't result in exceptions here, but
5266 // catch them to be robust and thorough. Don't try to
5267 // distinguish between the various exceptions because it seems
5268 // they vary by CPU, compiler and OS.
5269 return QCBOR_ERR_FLOAT_EXCEPTION;
5270 }
5271
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005272 } else {
5273 return QCBOR_ERR_UNEXPECTED_TYPE;
5274 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005275#else
5276 return QCBOR_ERR_HW_FLOAT_DISABLED;
5277#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005278 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005279
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005280 case QCBOR_TYPE_INT64:
5281 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
5282 if(pItem->val.int64 >= 0) {
5283 *puValue = (uint64_t)pItem->val.int64;
5284 } else {
5285 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5286 }
5287 } else {
5288 return QCBOR_ERR_UNEXPECTED_TYPE;
5289 }
5290 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005291
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005292 case QCBOR_TYPE_UINT64:
5293 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
5294 *puValue = pItem->val.uint64;
5295 } else {
5296 return QCBOR_ERR_UNEXPECTED_TYPE;
5297 }
5298 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005299
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005300 default:
5301 return QCBOR_ERR_UNEXPECTED_TYPE;
5302 }
5303
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005304 return QCBOR_SUCCESS;
5305}
Laurence Lundbladec4537442020-04-14 18:53:22 -07005306
5307
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005308void
5309QCBORDecode_Private_GetUInt64Convert(QCBORDecodeContext *pMe,
5310 const uint32_t uConvertTypes,
5311 uint64_t *puValue,
5312 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07005313{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005314 if(pMe->uLastError != QCBOR_SUCCESS) {
5315 return;
5316 }
5317
Laurence Lundbladec4537442020-04-14 18:53:22 -07005318 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005319
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005320 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5321 if(uError) {
5322 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005323 return;
5324 }
5325
Laurence Lundbladea826c502020-05-10 21:07:00 -07005326 if(pItem) {
5327 *pItem = Item;
5328 }
5329
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005330 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(&Item,
5331 uConvertTypes,
5332 puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07005333}
5334
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005335
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005336void
5337QCBORDecode_Private_GetUInt64ConvertInMapN(QCBORDecodeContext *pMe,
5338 const int64_t nLabel,
5339 const uint32_t uConvertTypes,
5340 uint64_t *puValue,
5341 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005342{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005343 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005344 if(pMe->uLastError != QCBOR_SUCCESS) {
5345 return;
5346 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005347
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005348 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
5349 uConvertTypes,
5350 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005351}
5352
5353
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005354void
5355QCBORDecode_Private_GetUInt64ConvertInMapSZ(QCBORDecodeContext *pMe,
5356 const char *szLabel,
5357 const uint32_t uConvertTypes,
5358 uint64_t *puValue,
5359 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005360{
5361 if(pMe->uLastError != QCBOR_SUCCESS) {
5362 return;
5363 }
5364
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005365 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005366 if(pMe->uLastError != QCBOR_SUCCESS) {
5367 return;
5368 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005369
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005370 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
5371 uConvertTypes,
5372 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005373}
5374
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005375
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005376
Laurence Lundblade93d89472020-10-03 22:30:50 -07005377static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005378QCBOR_Private_UInt64ConvertAll(const QCBORItem *pItem,
5379 const uint32_t uConvertTypes,
5380 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005381{
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08005382 switch(pItem->uDataType) { /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005383
5384 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005385 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005386 return QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005387 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005388 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005389 }
5390 break;
5391
5392 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005393 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005394 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5395 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005396 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005397 }
5398 break;
5399
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005400#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005401
5402 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005403 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005404 return QCBOR_Private_ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005405 pItem->val.expAndMantissa.nExponent,
5406 puValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005407 QCBOR_Private_Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005408 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005409 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005410 }
5411 break;
5412
5413 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005414 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005415 return QCBOR_Private_ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005416 pItem->val.expAndMantissa.nExponent,
5417 puValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005418 QCBOR_Private_Exponentitate2);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005419 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005420 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005421 }
5422 break;
5423
5424 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005425 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005426 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005427 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005428 uErr = QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005429 if(uErr != QCBOR_SUCCESS) {
5430 return uErr;
5431 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005432 return QCBOR_Private_ExponentitateUU(uMantissa,
5433 pItem->val.expAndMantissa.nExponent,
5434 puValue,
5435 QCBOR_Private_Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005436 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005437 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005438 }
5439 break;
5440
5441 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005442 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005443 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5444 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005445 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005446 }
5447 break;
5448
5449 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005450 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005451 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005452 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005453 uErr = QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum,
5454 &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005455 if(uErr != QCBOR_SUCCESS) {
5456 return uErr;
5457 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005458 return QCBOR_Private_ExponentitateUU(uMantissa,
5459 pItem->val.expAndMantissa.nExponent,
5460 puValue,
5461 QCBOR_Private_Exponentitate2);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005462 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005463 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005464 }
5465 break;
5466
5467 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005468 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005469 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5470 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005471 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005472 }
5473 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005474#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005475 default:
5476 return QCBOR_ERR_UNEXPECTED_TYPE;
5477 }
5478}
5479
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005480
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005481/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005482 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005483 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005484void
5485QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe,
5486 const uint32_t uConvertTypes,
5487 uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005488{
5489 QCBORItem Item;
5490
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005491 QCBORDecode_Private_GetUInt64Convert(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005492
Laurence Lundbladef6c86662020-05-12 02:08:00 -07005493 if(pMe->uLastError == QCBOR_SUCCESS) {
5494 // The above conversion succeeded
5495 return;
5496 }
5497
5498 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5499 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07005500 return;
5501 }
5502
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005503 pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
5504 uConvertTypes,
5505 puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005506}
5507
Laurence Lundbladec4537442020-04-14 18:53:22 -07005508
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005509/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005510 * Public function, see header qcbor/qcbor_decode.h file
5511 */
5512void
5513QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
5514 const int64_t nLabel,
5515 const uint32_t uConvertTypes,
5516 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005517{
5518 QCBORItem Item;
5519
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005520 QCBORDecode_Private_GetUInt64ConvertInMapN(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07005521 nLabel,
5522 uConvertTypes,
5523 puValue,
5524 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005525
5526 if(pMe->uLastError == QCBOR_SUCCESS) {
5527 // The above conversion succeeded
5528 return;
5529 }
5530
5531 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5532 // The above conversion failed in a way that code below can't correct
5533 return;
5534 }
5535
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005536 pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
5537 uConvertTypes,
5538 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005539}
5540
5541
5542/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005543 * Public function, see header qcbor/qcbor_decode.h file
5544 */
5545void
5546QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
5547 const char *szLabel,
5548 const uint32_t uConvertTypes,
5549 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005550{
5551 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005552 QCBORDecode_Private_GetUInt64ConvertInMapSZ(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07005553 szLabel,
5554 uConvertTypes,
5555 puValue,
5556 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005557
5558 if(pMe->uLastError == QCBOR_SUCCESS) {
5559 // The above conversion succeeded
5560 return;
5561 }
5562
5563 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5564 // The above conversion failed in a way that code below can't correct
5565 return;
5566 }
5567
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005568 pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
5569 uConvertTypes,
5570 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005571}
5572
5573
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005574
5575
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02005576#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005577static QCBORError
5578QCBOR_Private_ConvertDouble(const QCBORItem *pItem,
5579 const uint32_t uConvertTypes,
5580 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005581{
5582 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005583 case QCBOR_TYPE_FLOAT:
5584#ifndef QCBOR_DISABLE_FLOAT_HW_USE
5585 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5586 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005587 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005588 *pdValue = (double)pItem->val.fnum;
5589 } else {
5590 return QCBOR_ERR_UNEXPECTED_TYPE;
5591 }
5592 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005593#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005594 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005595#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005596 break;
5597
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005598 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005599 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5600 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005601 *pdValue = pItem->val.dfnum;
5602 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005603 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005604 }
5605 }
5606 break;
5607
5608 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005609#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005610 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005611 // A simple cast seems to do the job with no worry of exceptions.
5612 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005613 *pdValue = (double)pItem->val.int64;
5614
5615 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005616 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005617 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005618#else
5619 return QCBOR_ERR_HW_FLOAT_DISABLED;
5620#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005621 break;
5622
5623 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005624#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005625 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005626 // A simple cast seems to do the job with no worry of exceptions.
5627 // There will be precision loss for some values.
5628 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005629 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005630 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005631 }
5632 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005633#else
5634 return QCBOR_ERR_HW_FLOAT_DISABLED;
5635#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005636
5637 default:
5638 return QCBOR_ERR_UNEXPECTED_TYPE;
5639 }
5640
5641 return QCBOR_SUCCESS;
5642}
5643
5644
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005645void
5646QCBORDecode_Private_GetDoubleConvert(QCBORDecodeContext *pMe,
5647 const uint32_t uConvertTypes,
5648 double *pdValue,
5649 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005650{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005651 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07005652 return;
5653 }
5654
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005655 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005656
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005657 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005658 if(uError) {
5659 pMe->uLastError = (uint8_t)uError;
5660 return;
5661 }
5662
5663 if(pItem) {
5664 *pItem = Item;
5665 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005666
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005667 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(&Item,
5668 uConvertTypes,
5669 pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005670}
Laurence Lundbladec4537442020-04-14 18:53:22 -07005671
Laurence Lundbladec4537442020-04-14 18:53:22 -07005672
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005673void
5674QCBORDecode_Private_GetDoubleConvertInMapN(QCBORDecodeContext *pMe,
5675 const int64_t nLabel,
5676 const uint32_t uConvertTypes,
5677 double *pdValue,
5678 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005679{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005680 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005681 if(pMe->uLastError != QCBOR_SUCCESS) {
5682 return;
5683 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005684
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005685 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
5686 uConvertTypes,
5687 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005688}
5689
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005690
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005691void
5692QCBORDecode_Private_GetDoubleConvertInMapSZ(QCBORDecodeContext *pMe,
5693 const char *szLabel,
5694 const uint32_t uConvertTypes,
5695 double *pdValue,
5696 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005697{
5698 if(pMe->uLastError != QCBOR_SUCCESS) {
5699 return;
5700 }
5701
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005702 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005703 if(pMe->uLastError != QCBOR_SUCCESS) {
5704 return;
5705 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005706
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005707 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
5708 uConvertTypes,
5709 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005710}
5711
5712
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005713#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005714static double
5715QCBOR_Private_ConvertBigNumToDouble(const UsefulBufC BigNum)
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005716{
5717 double dResult;
5718
5719 dResult = 0.0;
5720 const uint8_t *pByte = BigNum.ptr;
5721 size_t uLen = BigNum.len;
5722 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07005723 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005724 while(uLen--) {
5725 dResult = (dResult * 256.0) + (double)*pByte++;
5726 }
5727
5728 return dResult;
5729}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005730#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5731
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005732
Laurence Lundblade93d89472020-10-03 22:30:50 -07005733static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005734QCBOR_Private_DoubleConvertAll(const QCBORItem *pItem,
5735 const uint32_t uConvertTypes,
5736 double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005737{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005738#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005739 /*
Laurence Lundblade16a207a2021-09-18 17:22:46 -07005740 * What Every Computer Scientist Should Know About Floating-Point Arithmetic
5741 * https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
5742 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005743 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005744
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005745#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005746 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005747 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07005748 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005749 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
5750 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
5751 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005752 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005753 }
5754 break;
5755
5756 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005757 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07005758 // Underflow gives 0, overflow gives infinity
5759 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
5760 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005761 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005762 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005763 }
5764 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005765#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005766
5767 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005768 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005769 *pdValue = QCBOR_Private_ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005770 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005771 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005772 }
5773 break;
5774
5775 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005776 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005777 *pdValue = -1-QCBOR_Private_ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005778 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005779 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005780 }
5781 break;
5782
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005783#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005784 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005785 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005786 double dMantissa = QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005787 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5788 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005789 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005790 }
5791 break;
5792
5793 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005794 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005795 double dMantissa = -QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005796 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5797 } 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_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005803 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005804 double dMantissa = QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005805 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5806 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005807 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005808 }
5809 break;
5810
5811 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005812 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005813 double dMantissa = -1-QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005814 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5815 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005816 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005817 }
5818 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005819#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005820
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005821 default:
5822 return QCBOR_ERR_UNEXPECTED_TYPE;
5823 }
5824
5825 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005826
5827#else
5828 (void)pItem;
5829 (void)uConvertTypes;
5830 (void)pdValue;
5831 return QCBOR_ERR_HW_FLOAT_DISABLED;
5832#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5833
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005834}
5835
5836
5837/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005838 *Public function, see header qcbor/qcbor_decode.h file
5839 */
5840void
5841QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
5842 const uint32_t uConvertTypes,
5843 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005844{
5845
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005846 QCBORItem Item;
5847
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005848 QCBORDecode_Private_GetDoubleConvert(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005849
5850 if(pMe->uLastError == QCBOR_SUCCESS) {
5851 // The above conversion succeeded
5852 return;
5853 }
5854
5855 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5856 // The above conversion failed in a way that code below can't correct
5857 return;
5858 }
5859
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005860 pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
5861 uConvertTypes,
5862 pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005863}
5864
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005865
5866/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005867 * Public function, see header qcbor/qcbor_decode.h file
5868 */
5869void
5870QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
5871 const int64_t nLabel,
5872 const uint32_t uConvertTypes,
5873 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005874{
5875 QCBORItem Item;
5876
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005877 QCBORDecode_Private_GetDoubleConvertInMapN(pMe,
5878 nLabel,
5879 uConvertTypes,
5880 pdValue,
5881 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005882
5883 if(pMe->uLastError == QCBOR_SUCCESS) {
5884 // The above conversion succeeded
5885 return;
5886 }
5887
5888 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5889 // The above conversion failed in a way that code below can't correct
5890 return;
5891 }
5892
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005893 pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
5894 uConvertTypes,
5895 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005896}
5897
5898
5899/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005900 * Public function, see header qcbor/qcbor_decode.h file
5901 */
5902void
5903QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
5904 const char *szLabel,
5905 const uint32_t uConvertTypes,
5906 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005907{
5908 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005909 QCBORDecode_Private_GetDoubleConvertInMapSZ(pMe,
5910 szLabel,
5911 uConvertTypes,
5912 pdValue,
5913 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005914
5915 if(pMe->uLastError == QCBOR_SUCCESS) {
5916 // The above conversion succeeded
5917 return;
5918 }
5919
5920 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5921 // The above conversion failed in a way that code below can't correct
5922 return;
5923 }
5924
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005925 pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
5926 uConvertTypes,
5927 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005928}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02005929#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005930
5931
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005932
5933
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005934#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005935static UsefulBufC
5936QCBOR_Private_ConvertIntToBigNum(uint64_t uInt, const UsefulBuf Buffer)
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005937{
5938 while((uInt & 0xff00000000000000UL) == 0) {
5939 uInt = uInt << 8;
5940 };
5941
5942 UsefulOutBuf UOB;
5943
5944 UsefulOutBuf_Init(&UOB, Buffer);
5945
5946 while(uInt) {
5947 const uint64_t xx = uInt & 0xff00000000000000UL;
5948 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
5949 uInt = uInt << 8;
5950 (void)xx;
5951 }
5952
5953 return UsefulOutBuf_OutUBuf(&UOB);
5954}
5955
5956
Laurence Lundblade37286c02022-09-03 10:05:02 -07005957/**
5958 * @brief Check and/or complete mantissa and exponent item.
5959 *
5960 * @param[in] pMe The decoder context
5961 * @param[in] TagSpec Expected type(s)
5962 * @param[in,out] pItem See below
5963 *
5964 * This is for decimal fractions and big floats, both of which are a
5965 * mantissa and exponent.
5966 *
5967 * The input item is either a fully decoded decimal faction or big
5968 * float, or a just the decoded first item of a decimal fraction or
5969 * big float.
5970 *
5971 * On output, the item is always a fully decoded decimal fraction or
5972 * big float.
5973 *
5974 * This errors out if the input type does not meet the TagSpec.
5975 */
5976// TODO: document and see tests for the bug that was fixed by this rewrite
5977static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005978QCBOR_Private_ExpMantissaTypeHandler(QCBORDecodeContext *pMe,
5979 const QCBOR_Private_TagSpec TagSpec,
5980 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005981{
5982 QCBORError uErr;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005983
Laurence Lundblade37286c02022-09-03 10:05:02 -07005984 /* pItem could either be an auto-decoded mantissa and exponent or
5985 * the opening array of an undecoded mantissa and exponent. This
5986 * check will succeed on either, but doesn't say which it was.
5987 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005988 uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07005989 if(uErr != QCBOR_SUCCESS) {
5990 goto Done;
5991 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005992
Laurence Lundblade37286c02022-09-03 10:05:02 -07005993 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
5994 /* The item is an array, which means is is an undecoded mantissa
5995 * and exponent. This call consumes the items in the array and
5996 * results in a decoded mantissa and exponent in pItem. This is
5997 * the case where there was no tag.
5998 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005999 uErr = QCBORDecode_Private_ExpMantissa(pMe, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006000 if(uErr != QCBOR_SUCCESS) {
6001 goto Done;
6002 }
6003
Laurence Lundblade37286c02022-09-03 10:05:02 -07006004 /* The above decode didn't determine whether it is a decimal
6005 * fraction or big num. Which of these two depends on what the
6006 * caller wants it decoded as since there is no tag, so fish the
6007 * type out of the TagSpec. */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006008 pItem->uDataType = QCBOR_Private_ExpMantissaDataType(TagSpec.uTaggedTypes[0], pItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07006009
6010 /* No need to check the type again. All that we need to know was
6011 * that it decoded correctly as a mantissa and exponent. The
6012 * QCBOR type is set out by what was requested.
6013 */
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006014 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07006015
6016 /* If the item was not an array and the check passed, then
6017 * it is a fully decoded big float or decimal fraction and
6018 * matches what is requested.
6019 */
6020
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006021Done:
6022 return uErr;
6023}
6024
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006025
Laurence Lundblade37286c02022-09-03 10:05:02 -07006026/* Some notes from the work to disable tags.
6027 *
6028 * The API for big floats and decimal fractions seems good.
6029 * If there's any issue with it it's that the code size to
6030 * implement is a bit large because of the conversion
6031 * to/from int and bignum that is required. There is no API
6032 * that doesn't do the conversion so dead stripping will never
6033 * leave that code out.
6034 *
6035 * The implementation itself seems correct, but not as clean
6036 * and neat as it could be. It could probably be smaller too.
6037 *
6038 * The implementation has three main parts / functions
6039 * - The decoding of the array of two
6040 * - All the tag and type checking for the various API functions
6041 * - Conversion to/from bignum and int
6042 *
6043 * The type checking seems like it wastes the most code for
6044 * what it needs to do.
6045 *
6046 * The inlining for the conversion is probably making the
6047 * overall code base larger.
6048 *
6049 * The tests cases could be organized a lot better and be
6050 * more thorough.
6051 *
6052 * Seems also like there could be more common code in the
6053 * first tier part of the public API. Some functions only
6054 * vary by a TagSpec.
6055 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006056static void
6057QCBOR_Private_ProcessExpMantissa(QCBORDecodeContext *pMe,
6058 const QCBOR_Private_TagSpec TagSpec,
6059 QCBORItem *pItem,
6060 int64_t *pnMantissa,
6061 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006062{
6063 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006064
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006065 uErr = QCBOR_Private_ExpMantissaTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006066 if(uErr != QCBOR_SUCCESS) {
6067 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006068 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006069
Laurence Lundblade9b334962020-08-27 10:55:53 -07006070 switch (pItem->uDataType) {
6071
6072 case QCBOR_TYPE_DECIMAL_FRACTION:
6073 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade9b334962020-08-27 10:55:53 -07006074 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade37286c02022-09-03 10:05:02 -07006075 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
Laurence Lundblade9b334962020-08-27 10:55:53 -07006076 break;
6077
Laurence Lundblade37286c02022-09-03 10:05:02 -07006078#ifndef QCBOR_DISABLE_TAGS
6079 /* If tags are disabled, mantissas can never be big nums */
Laurence Lundblade9b334962020-08-27 10:55:53 -07006080 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
6081 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
6082 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006083 uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
Laurence Lundblade9b334962020-08-27 10:55:53 -07006084 break;
6085
6086 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
6087 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
6088 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006089 uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
Laurence Lundblade9b334962020-08-27 10:55:53 -07006090 break;
Laurence Lundblade37286c02022-09-03 10:05:02 -07006091#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade9b334962020-08-27 10:55:53 -07006092
6093 default:
6094 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
6095 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006096
6097 Done:
6098 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006099}
6100
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006101
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006102static void
6103QCBOR_Private_ProcessExpMantissaBig(QCBORDecodeContext *pMe,
6104 const QCBOR_Private_TagSpec TagSpec,
6105 QCBORItem *pItem,
6106 const UsefulBuf BufferForMantissa,
6107 UsefulBufC *pMantissa,
6108 bool *pbIsNegative,
6109 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006110{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006111 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006112
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006113 uErr = QCBOR_Private_ExpMantissaTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006114 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006115 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006116 }
6117
6118 uint64_t uMantissa;
6119
6120 switch (pItem->uDataType) {
6121
6122 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006123 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07006124 /* See comments in ExponentiateNN() on handling INT64_MIN */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006125 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
6126 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
6127 *pbIsNegative = false;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07006128 } else if(pItem->val.expAndMantissa.Mantissa.nInt != INT64_MIN) {
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006129 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
6130 *pbIsNegative = true;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07006131 } else {
6132 uMantissa = (uint64_t)INT64_MAX+1;
6133 *pbIsNegative = true;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006134 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006135 *pMantissa = QCBOR_Private_ConvertIntToBigNum(uMantissa,
6136 BufferForMantissa);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006137 *pnExponent = pItem->val.expAndMantissa.nExponent;
6138 break;
6139
Laurence Lundblade37286c02022-09-03 10:05:02 -07006140#ifndef QCBOR_DISABLE_TAGS
6141 /* If tags are disabled, mantissas can never be big nums */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006142 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006143 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006144 *pnExponent = pItem->val.expAndMantissa.nExponent;
6145 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
6146 *pbIsNegative = false;
6147 break;
6148
6149 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006150 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006151 *pnExponent = pItem->val.expAndMantissa.nExponent;
6152 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
6153 *pbIsNegative = true;
6154 break;
Laurence Lundblade37286c02022-09-03 10:05:02 -07006155#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006156
6157 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006158 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006159 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006160
6161Done:
6162 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006163}
6164
6165
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006166/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006167 * Public function, see header qcbor/qcbor_decode.h file
6168 */
6169void
6170QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
6171 const uint8_t uTagRequirement,
6172 int64_t *pnMantissa,
6173 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006174{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006175 if(pMe->uLastError != QCBOR_SUCCESS) {
6176 return;
6177 }
6178
6179 QCBORItem Item;
6180 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6181 if(uError) {
6182 pMe->uLastError = (uint8_t)uError;
6183 return;
6184 }
6185
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006186 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006187 {
6188 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006189 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6190 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6191 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006192 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006193
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006194 QCBOR_Private_ProcessExpMantissa(pMe,
6195 TagSpec,
6196 &Item,
6197 pnMantissa,
6198 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006199}
6200
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006201
6202/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006203 * Public function, see header qcbor/qcbor_decode.h file
6204 */
6205void
6206QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
6207 const int64_t nLabel,
6208 const uint8_t uTagRequirement,
6209 int64_t *pnMantissa,
6210 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006211{
6212 if(pMe->uLastError != QCBOR_SUCCESS) {
6213 return;
6214 }
6215
6216 QCBORItem Item;
6217 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
6218
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006219 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006220 {
6221 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006222 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6223 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6224 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006225 };
6226
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006227 QCBOR_Private_ProcessExpMantissa(pMe,
6228 TagSpec,
6229 &Item,
6230 pnMantissa,
6231 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006232}
6233
6234
6235/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006236 * Public function, see header qcbor/qcbor_decode.h file
6237 */
6238void
6239QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
6240 const char *szLabel,
6241 const uint8_t uTagRequirement,
6242 int64_t *pnMantissa,
6243 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006244{
6245 if(pMe->uLastError != QCBOR_SUCCESS) {
6246 return;
6247 }
6248
6249 QCBORItem Item;
6250 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6251
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006252 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006253 {
6254 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006255 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6256 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6257 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006258 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07006259
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006260 QCBOR_Private_ProcessExpMantissa(pMe,
6261 TagSpec,
6262 &Item,
6263 pnMantissa,
6264 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006265}
6266
6267
6268/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006269 * Public function, see header qcbor/qcbor_decode.h file
6270 */
6271void
6272QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
6273 const uint8_t uTagRequirement,
6274 const UsefulBuf MantissaBuffer,
6275 UsefulBufC *pMantissa,
6276 bool *pbMantissaIsNegative,
6277 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006278{
6279 if(pMe->uLastError != QCBOR_SUCCESS) {
6280 return;
6281 }
6282
6283 QCBORItem Item;
6284 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6285 if(uError) {
6286 pMe->uLastError = (uint8_t)uError;
6287 return;
6288 }
6289
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006290 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006291 {
6292 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006293 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6294 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6295 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006296 };
6297
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006298 QCBOR_Private_ProcessExpMantissaBig(pMe,
6299 TagSpec,
6300 &Item,
6301 MantissaBuffer,
6302 pMantissa,
6303 pbMantissaIsNegative,
6304 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006305}
6306
6307
6308/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006309 * Public function, see header qcbor/qcbor_decode.h file
6310 */
6311void
6312QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
6313 const int64_t nLabel,
6314 const uint8_t uTagRequirement,
6315 const UsefulBuf BufferForMantissa,
6316 UsefulBufC *pMantissa,
6317 bool *pbIsNegative,
6318 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006319{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006320 if(pMe->uLastError != QCBOR_SUCCESS) {
6321 return;
6322 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006323
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006324 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006325 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006326 if(pMe->uLastError != QCBOR_SUCCESS) {
6327 return;
6328 }
6329
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006330 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006331 {
6332 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006333 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6334 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6335 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006336 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006337
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006338 QCBOR_Private_ProcessExpMantissaBig(pMe,
6339 TagSpec,
6340 &Item,
6341 BufferForMantissa,
6342 pMantissa,
6343 pbIsNegative,
6344 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006345}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006346
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006347
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006348/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006349 * Public function, see header qcbor/qcbor_decode.h file
6350 */
6351void
6352QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
6353 const char *szLabel,
6354 const uint8_t uTagRequirement,
6355 const UsefulBuf BufferForMantissa,
6356 UsefulBufC *pMantissa,
6357 bool *pbIsNegative,
6358 int64_t *pnExponent)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006359{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006360 if(pMe->uLastError != QCBOR_SUCCESS) {
6361 return;
6362 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006363
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006364 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006365 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6366 if(pMe->uLastError != QCBOR_SUCCESS) {
6367 return;
6368 }
6369
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006370 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006371 {
6372 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006373 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6374 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6375 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006376 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006377
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006378 QCBOR_Private_ProcessExpMantissaBig(pMe,
6379 TagSpec,
6380 &Item,
6381 BufferForMantissa,
6382 pMantissa,
6383 pbIsNegative,
6384 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006385}
6386
6387
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006388/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006389 * Public function, see header qcbor/qcbor_decode.h file
6390 */
6391void
6392QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
6393 const uint8_t uTagRequirement,
6394 int64_t *pnMantissa,
6395 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006396{
6397 if(pMe->uLastError != QCBOR_SUCCESS) {
6398 return;
6399 }
6400
6401 QCBORItem Item;
6402 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6403 if(uError) {
6404 pMe->uLastError = (uint8_t)uError;
6405 return;
6406 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006407 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006408 {
6409 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006410 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6411 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6412 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006413 };
6414
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006415 QCBOR_Private_ProcessExpMantissa(pMe,
6416 TagSpec,
6417 &Item,
6418 pnMantissa,
6419 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006420}
6421
6422
6423/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006424 * Public function, see header qcbor/qcbor_decode.h file
6425 */
6426void
6427QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
6428 const int64_t nLabel,
6429 const uint8_t uTagRequirement,
6430 int64_t *pnMantissa,
6431 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006432{
6433 if(pMe->uLastError != QCBOR_SUCCESS) {
6434 return;
6435 }
6436
6437 QCBORItem Item;
6438 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
6439 if(pMe->uLastError != QCBOR_SUCCESS) {
6440 return;
6441 }
6442
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006443 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006444 {
6445 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006446 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6447 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6448 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006449 };
6450
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006451 QCBOR_Private_ProcessExpMantissa(pMe,
6452 TagSpec,
6453 &Item,
6454 pnMantissa,
6455 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006456}
6457
6458
6459/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006460 * Public function, see header qcbor/qcbor_decode.h file
6461 */
6462void
6463QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
6464 const char *szLabel,
6465 const uint8_t uTagRequirement,
6466 int64_t *pnMantissa,
6467 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006468{
6469 if(pMe->uLastError != QCBOR_SUCCESS) {
6470 return;
6471 }
6472
6473 QCBORItem Item;
6474 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6475 if(pMe->uLastError != QCBOR_SUCCESS) {
6476 return;
6477 }
6478
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006479 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006480 {
6481 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006482 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6483 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6484 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006485 };
6486
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006487 QCBOR_Private_ProcessExpMantissa(pMe,
6488 TagSpec,
6489 &Item,
6490 pnMantissa,
6491 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006492}
6493
6494
6495/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006496 * Public function, see header qcbor/qcbor_decode.h file
6497 */
6498void
6499QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
6500 const uint8_t uTagRequirement,
6501 const UsefulBuf MantissaBuffer,
6502 UsefulBufC *pMantissa,
6503 bool *pbMantissaIsNegative,
6504 int64_t *pnExponent)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006505{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006506 if(pMe->uLastError != QCBOR_SUCCESS) {
6507 return;
6508 }
6509
6510 QCBORItem Item;
6511 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6512 if(uError) {
6513 pMe->uLastError = (uint8_t)uError;
6514 return;
6515 }
6516
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006517 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006518 {
6519 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006520 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6521 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6522 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006523 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006524
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006525 QCBOR_Private_ProcessExpMantissaBig(pMe,
6526 TagSpec,
6527 &Item,
6528 MantissaBuffer,
6529 pMantissa,
6530 pbMantissaIsNegative,
6531 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006532}
6533
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006534
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006535/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006536 * Public function, see header qcbor/qcbor_decode.h file
6537 */
6538void
6539QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
6540 const int64_t nLabel,
6541 const uint8_t uTagRequirement,
6542 const UsefulBuf BufferForMantissa,
6543 UsefulBufC *pMantissa,
6544 bool *pbIsNegative,
6545 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006546{
6547 if(pMe->uLastError != QCBOR_SUCCESS) {
6548 return;
6549 }
6550
6551 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006552 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
6553 if(pMe->uLastError != QCBOR_SUCCESS) {
6554 return;
6555 }
6556
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006557 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006558 {
6559 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006560 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6561 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6562 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006563 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006564
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006565 QCBOR_Private_ProcessExpMantissaBig(pMe,
6566 TagSpec,
6567 &Item,
6568 BufferForMantissa,
6569 pMantissa,
6570 pbIsNegative,
6571 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006572}
6573
6574
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006575/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006576 * Public function, see header qcbor/qcbor_decode.h file
6577 */
6578void
6579QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
6580 const char *szLabel,
6581 const uint8_t uTagRequirement,
6582 const UsefulBuf BufferForMantissa,
6583 UsefulBufC *pMantissa,
6584 bool *pbIsNegative,
6585 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006586{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006587 if(pMe->uLastError != QCBOR_SUCCESS) {
6588 return;
6589 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006590
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006591 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006592 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6593 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006594 return;
6595 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006596
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006597 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006598 {
6599 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006600 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6601 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6602 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006603 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006604
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006605 QCBOR_Private_ProcessExpMantissaBig(pMe,
6606 TagSpec,
6607 &Item,
6608 BufferForMantissa,
6609 pMantissa,
6610 pbIsNegative,
6611 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006612}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006613
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006614#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */