blob: 332314b6f35a2fe02c46083ae484a258c201cb97 [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 Lundblade2d493002024-02-01 11:09:17 -0700887 pDecodedItem->val.uint64 = uArgument;
888 pDecodedItem->uDataType = QCBOR_TYPE_65BIT_NEG_INT;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700889 }
890 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800891
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800892 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700893}
894
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800895
896/* Make sure #define value line up as DecodeSimple counts on this. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700897#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
898#error QCBOR_TYPE_FALSE macro value wrong
899#endif
900
901#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
902#error QCBOR_TYPE_TRUE macro value wrong
903#endif
904
905#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
906#error QCBOR_TYPE_NULL macro value wrong
907#endif
908
909#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
910#error QCBOR_TYPE_UNDEF macro value wrong
911#endif
912
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700913#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
914#error QCBOR_TYPE_BREAK macro value wrong
915#endif
916
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700917#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
918#error QCBOR_TYPE_DOUBLE macro value wrong
919#endif
920
921#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
922#error QCBOR_TYPE_FLOAT macro value wrong
923#endif
924
Laurence Lundblade9b334962020-08-27 10:55:53 -0700925
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800926/**
927 * @brief Decode major type 7 -- true, false, floating-point, break...
928 *
929 * @param[in] nAdditionalInfo The lower five bits from the initial byte.
930 * @param[in] uArgument The argument from the head.
931 * @param[out] pDecodedItem The filled in decoded item.
932 *
933 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200934 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800935 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700936 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800937
Laurence Lundblade8e36f812024-01-26 10:59:29 -0700938static QCBORError
939QCBOR_Private_DecodeType7(const int nAdditionalInfo,
940 const uint64_t uArgument,
941 QCBORItem *pDecodedItem)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800942{
943 QCBORError uReturn = QCBOR_SUCCESS;
944
945 /* uAdditionalInfo is 5 bits from the initial byte. Compile time
946 * checks above make sure uAdditionalInfo values line up with
947 * uDataType values. DecodeHead() never returns an AdditionalInfo
948 * > 0x1f so cast is safe.
949 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800950 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800951
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800952 switch(nAdditionalInfo) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800953 /* No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they
954 * are caught before this is called.
955 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800956
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800957 case HALF_PREC_FLOAT: /* 25 */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700958#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800959 /* Half-precision is returned as a double. The cast to
960 * uint16_t is safe because the encoded value was 16 bits. It
961 * was widened to 64 bits to be passed in here.
962 */
963 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700964 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800965#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200966 uReturn = FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700967 break;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800968 case SINGLE_PREC_FLOAT: /* 26 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200969#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800970 /* Single precision is normally returned as a double since
971 * double is widely supported, there is no loss of precision,
972 * it makes it easy for the caller in most cases and it can
973 * be converted back to single with no loss of precision
974 *
975 * The cast to uint32_t is safe because the encoded value was
976 * 32 bits. It was widened to 64 bits to be passed in here.
977 */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700978 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800979 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uArgument);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700980#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800981 /* In the normal case, use HW to convert float to
982 * double. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700983 pDecodedItem->val.dfnum = (double)f;
984 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800985#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800986 /* Use of float HW is disabled, return as a float. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700987 pDecodedItem->val.fnum = f;
988 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
989
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800990 /* IEEE754_FloatToDouble() could be used here to return as
991 * a double, but it adds object code and most likely
992 * anyone disabling FLOAT HW use doesn't care about floats
993 * and wants to save object code.
994 */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800995#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700996 }
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200997#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
998 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700999 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07001000
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001001 case DOUBLE_PREC_FLOAT: /* 27 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001002#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001003 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +07001004 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001005#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
1006 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -07001007 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001008
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001009 case CBOR_SIMPLEV_FALSE: /* 20 */
1010 case CBOR_SIMPLEV_TRUE: /* 21 */
1011 case CBOR_SIMPLEV_NULL: /* 22 */
1012 case CBOR_SIMPLEV_UNDEF: /* 23 */
1013 case CBOR_SIMPLE_BREAK: /* 31 */
1014 break; /* nothing to do */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001015
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001016 case CBOR_SIMPLEV_ONEBYTE: /* 24 */
1017 if(uArgument <= CBOR_SIMPLE_BREAK) {
1018 /* This takes out f8 00 ... f8 1f which should be encoded
1019 * as e0 … f7
1020 */
1021 uReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001022 goto Done;
1023 }
Laurence Lundblade5e390822019-01-06 12:35:01 -08001024 /* FALLTHROUGH */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001025
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001026 default: /* 0-19 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001027 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001028 /* DecodeHead() will make uArgument equal to
1029 * nAdditionalInfo when nAdditionalInfo is < 24. This cast is
1030 * safe because the 2, 4 and 8 byte lengths of uNumber are in
1031 * the double/float cases above
Laurence Lundbladeee851742020-01-08 08:37:05 -08001032 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001033 pDecodedItem->val.uSimple = (uint8_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001034 break;
1035 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001036
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001037Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001038 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001039}
1040
1041
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001042/**
1043 * @brief Decode text and byte strings
1044 *
1045 * @param[in] pAllocator The string allocator or NULL.
1046 * @param[in] uStrLen The length of the string.
1047 * @param[in] pUInBuf The surce from which to read the string's bytes.
1048 * @param[out] pDecodedItem The filled in decoded item.
1049 *
1050 * @retval QCBOR_ERR_HIT_END
1051 * @retval QCBOR_ERR_STRING_ALLOCATE
1052 * @retval QCBOR_ERR_STRING_TOO_LONG
1053 *
1054 * The reads @c uStrlen bytes from @c pUInBuf and fills in @c
1055 * pDecodedItem. If @c pAllocator is not NULL then memory for the
1056 * string is allocated.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001057 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001058static QCBORError
1059QCBOR_Private_DecodeBytes(const QCBORInternalAllocator *pAllocator,
1060 const uint64_t uStrLen,
1061 UsefulInputBuf *pUInBuf,
1062 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001063{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001064 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001065
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001066 /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
1067 * CPUs. This check makes the casts to size_t below safe.
1068 *
1069 * The max is 4 bytes less than the largest sizeof() so this can be
1070 * tested by putting a SIZE_MAX length in the CBOR test input (no
1071 * one will care the limit on strings is 4 bytes shorter).
1072 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001073 if(uStrLen > SIZE_MAX-4) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001074 uReturn = QCBOR_ERR_STRING_TOO_LONG;
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001075 goto Done;
1076 }
1077
1078 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301079 if(UsefulBuf_IsNULLC(Bytes)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001080 /* Failed to get the bytes for this string item */
1081 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301082 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001083 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301084
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001085#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001086 /* Note that this is not where allocation to coalesce
1087 * indefinite-length strings is done. This is for when the caller
1088 * has requested all strings be allocated. Disabling indefinite
1089 * length strings also disables this allocate-all option.
1090 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001091 if(pAllocator) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001092 /* request to use the string allocator to make a copy */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001093 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301094 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001095 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301096 goto Done;
1097 }
1098 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001099 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001100 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301101 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001102#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1103 (void)pAllocator;
1104#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1105
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001106 /* Normal case with no string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001107 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001108
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301109Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001110 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001111}
1112
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001113
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001114/**
1115 * @brief Map the CBOR major types for strings to the QCBOR types.
1116 *
1117 * @param[in] nCBORMajorType The CBOR major type to convert.
1118 * @retturns QCBOR type number.
1119 *
1120 * This only works for the two string types.
1121 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001122static uint8_t
1123QCBOR_Private_ConvertStringMajorTypes(int nCBORMajorType)
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001124{
1125 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
1126 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
1127 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001128
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001129 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
1130 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
1131 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001132
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001133 return (uint8_t)(nCBORMajorType + 4);
1134}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001135
1136
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001137/**
1138 * @brief Map the CBOR major types for arrays/maps to the QCBOR types.
1139 *
1140 * @param[in] nCBORMajorType The CBOR major type to convert.
1141 * @retturns QCBOR type number.
1142 *
1143 * This only works for the two aggregate types.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001144 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001145static uint8_t
1146QCBORDecode_Private_ConvertArrayOrMapType(int nCBORMajorType)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001147{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001148 #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
1149 #error QCBOR_TYPE_ARRAY value not lined up with major type
1150 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001151
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001152 #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
1153 #error QCBOR_TYPE_MAP value not lined up with major type
1154 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001155
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001156 return (uint8_t)(nCBORMajorType);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001157}
1158
1159
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001160/**
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001161 * @brief Decode a single primitive data item (decode layer 6).
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001162 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001163 * @param[in] pUInBuf Input buffer to read data item from.
1164 * @param[out] pDecodedItem The filled-in decoded item.
1165 * @param[in] pAllocator The allocator to use for strings or NULL.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001166 *
1167 * @retval QCBOR_ERR_UNSUPPORTED
1168 * @retval QCBOR_ERR_HIT_END
1169 * @retval QCBOR_ERR_INT_OVERFLOW
1170 * @retval QCBOR_ERR_STRING_ALLOCATE
1171 * @retval QCBOR_ERR_STRING_TOO_LONG
1172 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001173 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001174 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001175 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1176 *
1177 * This decodes the most primitive / atomic data item. It does
1178 * no combing of data items.
1179 */
1180static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001181QCBOR_Private_DecodeAtomicDataItem(UsefulInputBuf *pUInBuf,
1182 QCBORItem *pDecodedItem,
1183 const QCBORInternalAllocator *pAllocator)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001184{
1185 QCBORError uReturn;
1186
1187 /* Get the major type and the argument. The argument could be
1188 * length of more bytes or the value depending on the major
1189 * type. nAdditionalInfo is an encoding of the length of the
1190 * uNumber and is needed to decode floats and doubles.
1191 */
1192 int nMajorType = 0;
1193 uint64_t uArgument = 0;
1194 int nAdditionalInfo = 0;
1195
1196 memset(pDecodedItem, 0, sizeof(QCBORItem));
1197
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001198 uReturn = QCBOR_Private_DecodeHead(pUInBuf, &nMajorType, &uArgument, &nAdditionalInfo);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001199 if(uReturn) {
1200 goto Done;
1201 }
1202
1203 /* At this point the major type and the argument are valid. We've
1204 * got the type and the argument that starts every CBOR data item.
1205 */
1206 switch (nMajorType) {
1207 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1208 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
1209 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1210 uReturn = QCBOR_ERR_BAD_INT;
1211 } else {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001212 uReturn = QCBOR_Private_DecodeInteger(nMajorType, uArgument, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001213 }
1214 break;
1215
1216 case CBOR_MAJOR_TYPE_BYTE_STRING: /* Major type 2 */
1217 case CBOR_MAJOR_TYPE_TEXT_STRING: /* Major type 3 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001218 pDecodedItem->uDataType = QCBOR_Private_ConvertStringMajorTypes(nMajorType);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001219 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1220 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
1221 } else {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001222 uReturn = QCBOR_Private_DecodeBytes(pAllocator, uArgument, pUInBuf, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001223 }
1224 break;
1225
1226 case CBOR_MAJOR_TYPE_ARRAY: /* Major type 4 */
1227 case CBOR_MAJOR_TYPE_MAP: /* Major type 5 */
1228 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1229 /* Indefinite-length string. */
1230#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
1231 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
1232#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1233 uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
1234 break;
1235#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1236 } else {
1237 /* Definite-length string. */
1238 if(uArgument > QCBOR_MAX_ITEMS_IN_ARRAY) {
1239 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
1240 goto Done;
1241 }
1242 /* cast OK because of check above */
1243 pDecodedItem->val.uCount = (uint16_t)uArgument;
1244 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001245 pDecodedItem->uDataType = QCBORDecode_Private_ConvertArrayOrMapType(nMajorType);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001246 break;
1247
1248 case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */
Laurence Lundblade37286c02022-09-03 10:05:02 -07001249#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001250 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1251 uReturn = QCBOR_ERR_BAD_INT;
1252 } else {
1253 pDecodedItem->val.uTagV = uArgument;
1254 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
1255 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07001256#else /* QCBOR_DISABLE_TAGS */
1257 uReturn = QCBOR_ERR_TAGS_DISABLED;
1258#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001259 break;
1260
1261 case CBOR_MAJOR_TYPE_SIMPLE:
1262 /* Major type 7: float, double, true, false, null... */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001263 uReturn = QCBOR_Private_DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001264 break;
1265
1266 default:
1267 /* Never happens because DecodeHead() should never return > 7 */
1268 uReturn = QCBOR_ERR_UNSUPPORTED;
1269 break;
1270 }
1271
1272Done:
1273 return uReturn;
1274}
1275
1276
1277/**
1278 * @brief Process indefinite-length strings (decode layer 5).
1279 *
1280 * @param[in] pMe Decoder context
1281 * @param[out] pDecodedItem The decoded item that work is done on.
1282 *
1283 * @retval QCBOR_ERR_UNSUPPORTED
1284 * @retval QCBOR_ERR_HIT_END
1285 * @retval QCBOR_ERR_INT_OVERFLOW
1286 * @retval QCBOR_ERR_STRING_ALLOCATE
1287 * @retval QCBOR_ERR_STRING_TOO_LONG
1288 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001289 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001290 * @retval QCBOR_ERR_BAD_TYPE_7
1291 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001292 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1293 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001294 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001295 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001296 * If @c pDecodedItem is not an indefinite-length string, this does nothing.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001297 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001298 * If it is, this loops getting the subsequent chunk data items that
1299 * make up the string. The string allocator is used to make a
1300 * contiguous buffer for the chunks. When this completes @c
1301 * pDecodedItem contains the put-together string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001302 *
1303 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001304 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001305static QCBORError
1306QCBORDecode_Private_GetNextFullString(QCBORDecodeContext *pMe,
1307 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001308{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001309 /* Aproximate stack usage
1310 * 64-bit 32-bit
1311 * local vars 32 16
1312 * 2 UsefulBufs 32 16
1313 * QCBORItem 56 52
1314 * TOTAL 120 74
1315 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001316
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001317 /* The string allocator is used here for two purposes: 1)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001318 * coalescing the chunks of an indefinite-length string, 2)
1319 * allocating storage for every string returned when requested.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001320 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001321 * The first use is below in this function. Indefinite-length
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001322 * strings cannot be processed at all without a string allocator.
1323 *
1324 * The second used is in DecodeBytes() which is called by
1325 * GetNext_Item() below. This second use unneccessary for most use
1326 * and only happens when requested in the call to
1327 * QCBORDecode_SetMemPool(). If the second use not requested then
1328 * NULL is passed for the string allocator to GetNext_Item().
1329 *
1330 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1331 * allocator altogether and thus both of these uses. It reduced the
1332 * decoder object code by about 400 bytes.
1333 */
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001334 const QCBORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001335
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001336#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001337 const QCBORInternalAllocator *pAllocator = NULL;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001338
1339 if(pMe->StringAllocator.pfAllocator) {
1340 pAllocator = &(pMe->StringAllocator);
1341 if(pMe->bStringAllocateAll) {
1342 pAllocatorForGetNext = pAllocator;
1343 }
1344 }
1345#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1346
1347 QCBORError uReturn;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001348 uReturn = QCBOR_Private_DecodeAtomicDataItem(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001349 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001350 goto Done;
1351 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001352
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001353 /* Only do indefinite-length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001354 const uint8_t uStringType = pDecodedItem->uDataType;
1355 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001356 goto Done;
1357 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001358
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001359 /* Is this a string with an indefinite length? */
1360 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1361 goto Done;
1362 }
1363
1364#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001365 /* Can't decode indefinite-length strings without a string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001366 if(pAllocator == NULL) {
1367 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1368 goto Done;
1369 }
1370
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001371 /* Loop getting chunks of the indefinite-length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001372 UsefulBufC FullString = NULLUsefulBufC;
1373
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001374 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001375 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001376 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001377 /* Pass a NULL string allocator to GetNext_Item() because the
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001378 * individual string chunks in an indefinite-length should not
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001379 * be allocated. They are always copied in the the contiguous
1380 * buffer allocated here.
1381 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001382 uReturn = QCBOR_Private_DecodeAtomicDataItem(&(pMe->InBuf), &StringChunkItem, NULL);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001383 if(uReturn) {
1384 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001385 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001386
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001387 /* Is item is the marker for end of the indefinite-length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001388 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001389 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001390 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301391 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001392 break;
1393 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001394
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001395 /* All chunks must be of the same type, the type of the item
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001396 * that introduces the indefinite-length string. This also
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001397 * catches errors where the chunk is not a string at all and an
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001398 * indefinite-length string inside an indefinite-length string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001399 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001400 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001401 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1402 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001403 break;
1404 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001405
David Navarro9123e5b2022-03-28 16:04:03 +02001406 if (StringChunkItem.val.string.len > 0) {
1407 /* The first time throurgh FullString.ptr is NULL and this is
1408 * equivalent to StringAllocator_Allocate(). Subsequently it is
1409 * not NULL and a reallocation happens.
1410 */
1411 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1412 FullString.ptr,
1413 FullString.len + StringChunkItem.val.string.len);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001414
David Navarro9123e5b2022-03-28 16:04:03 +02001415 if(UsefulBuf_IsNULL(NewMem)) {
1416 uReturn = QCBOR_ERR_STRING_ALLOCATE;
1417 break;
1418 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001419
David Navarro9123e5b2022-03-28 16:04:03 +02001420 /* Copy new string chunk to the end of accumulated string */
1421 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001422 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001423 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001424
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001425 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1426 /* Getting the item failed, clean up the allocated memory */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001427 StringAllocator_Free(pAllocator, FullString.ptr);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001428 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001429#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1430 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1431#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001432
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001433Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001434 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001435}
1436
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001437
Laurence Lundblade37286c02022-09-03 10:05:02 -07001438#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001439/**
1440 * @brief This converts a tag number to a shorter mapped value for storage.
1441 *
1442 * @param[in] pMe The decode context.
1443 * @param[in] uUnMappedTag The tag number to map
1444 * @param[out] puMappedTagNumer The stored tag number.
1445 *
1446 * @return error code.
1447 *
1448 * The main point of mapping tag numbers is make QCBORItem
1449 * smaller. With this mapping storage of 4 tags takes up 8
1450 * bytes. Without, it would take up 32 bytes.
1451 *
1452 * This maps tag numbers greater than QCBOR_LAST_UNMAPPED_TAG.
1453 * QCBOR_LAST_UNMAPPED_TAG is a little smaller than MAX_UINT16.
1454 *
1455 * See also UnMapTagNumber() and @ref QCBORItem.
1456 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001457static QCBORError
1458QCBORDecode_Private_MapTagNumber(QCBORDecodeContext *pMe,
1459 const uint64_t uUnMappedTag,
1460 uint16_t *puMappedTagNumer)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001461{
1462 if(uUnMappedTag > QCBOR_LAST_UNMAPPED_TAG) {
1463 unsigned uTagMapIndex;
1464 /* Is there room in the tag map, or is it in it already? */
1465 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
1466 if(pMe->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID64) {
1467 break;
1468 }
1469 if(pMe->auMappedTags[uTagMapIndex] == uUnMappedTag) {
1470 break;
1471 }
1472 }
1473 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1474 return QCBOR_ERR_TOO_MANY_TAGS;
1475 }
1476
1477 /* Covers the cases where tag is new and were it is already in the map */
1478 pMe->auMappedTags[uTagMapIndex] = uUnMappedTag;
1479 *puMappedTagNumer = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
1480
1481 } else {
1482 *puMappedTagNumer = (uint16_t)uUnMappedTag;
1483 }
1484
1485 return QCBOR_SUCCESS;
1486}
1487
1488
1489/**
1490 * @brief This converts a mapped tag number to the actual tag number.
1491 *
1492 * @param[in] pMe The decode context.
1493 * @param[in] uMappedTagNumber The stored tag number.
1494 *
1495 * @return The actual tag number is returned or
1496 * @ref CBOR_TAG_INVALID64 on error.
1497 *
1498 * This is the reverse of MapTagNumber()
1499 */
1500static uint64_t
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001501QCBORDecode_Private_UnMapTagNumber(const QCBORDecodeContext *pMe,
1502 const uint16_t uMappedTagNumber)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001503{
1504 if(uMappedTagNumber <= QCBOR_LAST_UNMAPPED_TAG) {
1505 return uMappedTagNumber;
1506 } else if(uMappedTagNumber == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001507 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001508 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001509 /* This won't be negative because of code below in
1510 * MapTagNumber()
1511 */
1512 const unsigned uIndex = uMappedTagNumber - (QCBOR_LAST_UNMAPPED_TAG + 1);
1513 return pMe->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001514 }
1515}
Laurence Lundblade37286c02022-09-03 10:05:02 -07001516#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001517
Laurence Lundblade9b334962020-08-27 10:55:53 -07001518
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001519/**
1520 * @brief Aggregate all tags wrapping a data item (decode layer 4).
1521 *
1522 * @param[in] pMe Decoder context
1523 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001524
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001525 * @retval QCBOR_ERR_UNSUPPORTED
1526 * @retval QCBOR_ERR_HIT_END
1527 * @retval QCBOR_ERR_INT_OVERFLOW
1528 * @retval QCBOR_ERR_STRING_ALLOCATE
1529 * @retval QCBOR_ERR_STRING_TOO_LONG
1530 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001531 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001532 * @retval QCBOR_ERR_BAD_TYPE_7
1533 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1534 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1535 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1536 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1537 * @retval QCBOR_ERR_TOO_MANY_TAGS
1538 *
1539 * This loops getting atomic data items until one is not a tag
1540 * number. Usually this is largely pass-through because most
1541 * item are not tag numbers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001542 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001543static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001544QCBORDecode_Private_GetNextTagNumber(QCBORDecodeContext *pMe,
1545 QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001546{
Laurence Lundblade37286c02022-09-03 10:05:02 -07001547#ifndef QCBOR_DISABLE_TAGS
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001548 /* Accummulate the tags from multiple items here and then copy them
1549 * into the last item, the non-tag item.
1550 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001551 uint16_t auItemsTags[QCBOR_MAX_TAGS_PER_ITEM];
1552
1553 /* Initialize to CBOR_TAG_INVALID16 */
1554 #if CBOR_TAG_INVALID16 != 0xffff
1555 /* Be sure the memset does the right thing. */
1556 #err CBOR_TAG_INVALID16 tag not defined as expected
1557 #endif
1558 memset(auItemsTags, 0xff, sizeof(auItemsTags));
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001559
Laurence Lundblade9b334962020-08-27 10:55:53 -07001560 QCBORError uReturn = QCBOR_SUCCESS;
1561
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001562 /* Loop fetching data items until the item fetched is not a tag */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001563 for(;;) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001564 QCBORError uErr = QCBORDecode_Private_GetNextFullString(pMe, pDecodedItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07001565 if(uErr != QCBOR_SUCCESS) {
1566 uReturn = uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001567 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001568 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001569
Laurence Lundblade9b334962020-08-27 10:55:53 -07001570 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001571 /* Successful exit from loop; maybe got some tags, maybe not */
1572 memcpy(pDecodedItem->uTags, auItemsTags, sizeof(auItemsTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001573 break;
1574 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001575
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001576 if(auItemsTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1577 /* No room in the tag list */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001578 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001579 /* Continue on to get all tags wrapping this item even though
1580 * it is erroring out in the end. This allows decoding to
1581 * continue. This is a resource limit error, not a problem
1582 * with being well-formed CBOR.
1583 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001584 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001585 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001586 /* Slide tags over one in the array to make room at index 0.
1587 * Must use memmove because the move source and destination
1588 * overlap.
1589 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001590 memmove(&auItemsTags[1],
1591 auItemsTags,
1592 sizeof(auItemsTags) - sizeof(auItemsTags[0]));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001593
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001594 /* Map the tag */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001595 uint16_t uMappedTagNumber = 0;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001596 uReturn = QCBORDecode_Private_MapTagNumber(pMe, pDecodedItem->val.uTagV, &uMappedTagNumber);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001597 /* Continue even on error so as to consume all tags wrapping
1598 * this data item so decoding can go on. If MapTagNumber()
1599 * errors once it will continue to error.
1600 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001601 auItemsTags[0] = uMappedTagNumber;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001602 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001603
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001604Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001605 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001606
Laurence Lundblade37286c02022-09-03 10:05:02 -07001607#else /* QCBOR_DISABLE_TAGS */
1608
1609 return QCBORDecode_GetNextFullString(pMe, pDecodedItem);
1610
1611#endif /* QCBOR_DISABLE_TAGS */
1612}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001613
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001614/**
1615 * @brief Combine a map entry label and value into one item (decode layer 3).
1616 *
1617 * @param[in] pMe Decoder context
1618 * @param[out] pDecodedItem The decoded item that work is done on.
1619 *
1620 * @retval QCBOR_ERR_UNSUPPORTED
1621 * @retval QCBOR_ERR_HIT_END
1622 * @retval QCBOR_ERR_INT_OVERFLOW
1623 * @retval QCBOR_ERR_STRING_ALLOCATE
1624 * @retval QCBOR_ERR_STRING_TOO_LONG
1625 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001626 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001627 * @retval QCBOR_ERR_BAD_TYPE_7
1628 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1629 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1630 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1631 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1632 * @retval QCBOR_ERR_TOO_MANY_TAGS
1633 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1634 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1635 *
1636 * If a the current nesting level is a map, then this
1637 * combines pairs of items into one data item with a label
1638 * and value.
1639 *
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07001640 * This is passthrough if the current nesting level is
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001641 * not a map.
1642 *
1643 * This also implements maps-as-array mode where a map
1644 * is treated like an array to allow caller to do their
1645 * own label processing.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001646 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001647static QCBORError
1648QCBORDecode_Private_GetNextMapEntry(QCBORDecodeContext *pMe,
1649 QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001650{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001651 QCBORError uReturn = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001652 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001653 goto Done;
1654 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001655
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001656 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
1657 /* Break can't be a map entry */
1658 goto Done;
1659 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001660
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001661 if(pMe->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1662 /* Normal decoding of maps -- combine label and value into one item. */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001663
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001664 if(DecodeNesting_IsCurrentTypeMap(&(pMe->nesting))) {
1665 /* Save label in pDecodedItem and get the next which will
1666 * be the real data item.
1667 */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001668 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001669 uReturn = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001670 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001671 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001672 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001673
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301674 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001675
1676 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001677 /* strings are always good labels */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001678 pDecodedItem->label.string = LabelItem.val.string;
1679 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001680 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == pMe->uDecodeMode) {
1681 /* It's not a string and we only want strings */
1682 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001683 goto Done;
1684 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1685 pDecodedItem->label.int64 = LabelItem.val.int64;
1686 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1687 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1688 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1689 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1690 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1691 pDecodedItem->label.string = LabelItem.val.string;
1692 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1693 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1694 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001695 /* label is not an int or a string. It is an arrray
1696 * or a float or such and this implementation doesn't handle that.
1697 * Also, tags on labels are ignored.
1698 */
1699 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001700 goto Done;
1701 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001702 }
1703 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001704 /* Decoding of maps as arrays to let the caller decide what to do
1705 * about labels, particularly lables that are not integers or
1706 * strings.
1707 */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001708 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001709 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001710 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001711 goto Done;
1712 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001713 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001714 /* Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2.
1715 * Cast is needed because of integer promotion.
1716 */
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001717 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001718 }
1719 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001720
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001721Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001722 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001723}
1724
1725
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001726#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001727/**
1728 * @brief Peek and see if next data item is a break;
1729 *
1730 * @param[in] pUIB UsefulInputBuf to read from.
1731 * @param[out] pbNextIsBreak Indicate if next was a break or not.
1732 *
1733 * @return Any decoding error.
1734 *
1735 * See if next item is a CBOR break. If it is, it is consumed,
1736 * if not it is not consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001737*/
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001738static QCBORError
1739QCBOR_Private_NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001740{
1741 *pbNextIsBreak = false;
1742 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001743 QCBORItem Peek;
1744 size_t uPeek = UsefulInputBuf_Tell(pUIB);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001745 QCBORError uReturn = QCBOR_Private_DecodeAtomicDataItem(pUIB, &Peek, NULL);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001746 if(uReturn != QCBOR_SUCCESS) {
1747 return uReturn;
1748 }
1749 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001750 /* It is not a break, rewind so it can be processed normally. */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001751 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001752 } else {
1753 *pbNextIsBreak = true;
1754 }
1755 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001756
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001757 return QCBOR_SUCCESS;
1758}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001759#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001760
1761
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001762/**
1763 * @brief Ascend up nesting levels if all items in them have been consumed.
1764 *
1765 * @param[in] pMe The decode context.
1766 * @param[in] bMarkEnd If true mark end of maps/arrays with count of zero.
1767 *
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001768 * An item was just consumed, now figure out if it was the
1769 * end of an array/map map that can be closed out. That
1770 * may in turn close out the above array/map...
Laurence Lundblade642282a2020-06-23 12:00:33 -07001771*/
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001772static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001773QCBORDecode_Private_NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001774{
1775 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001776
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001777 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001778 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1779
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001780 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1781 /* Nesting level is bstr-wrapped CBOR */
1782
1783 /* Ascent for bstr-wrapped CBOR is always by explicit call
1784 * so no further ascending can happen.
1785 */
1786 break;
1787
1788 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1789 /* Level is a definite-length array/map */
1790
1791 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001792 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1793 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001794 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001795 break;
1796 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001797 /* All items in a definite-length array were consumed so it
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001798 * is time to ascend one level. This happens below.
1799 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001800
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001801#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001802 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001803 /* Level is an indefinite-length array/map. */
1804
1805 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001806 bool bIsBreak = false;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001807 uReturn = QCBOR_Private_NextIsBreak(&(pMe->InBuf), &bIsBreak);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001808 if(uReturn != QCBOR_SUCCESS) {
1809 goto Done;
1810 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001811
1812 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001813 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001814 break;
1815 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001816
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001817 /* It was a break in an indefinitelength map / array so
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001818 * it is time to ascend one level.
1819 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001820
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001821#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001822 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001823
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001824
1825 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001826
Laurence Lundblade93d89472020-10-03 22:30:50 -07001827 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001828 * QCBORDecode_ExitBoundedMode().
1829 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001830 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001831 /* Set the count to zero for definite-length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001832 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001833 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001834 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001835 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001836
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001837 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001838 break;
1839 }
1840
1841 /* Finally, actually ascend one level. */
1842 DecodeNesting_Ascend(&(pMe->nesting));
1843 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001844
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001845 uReturn = QCBOR_SUCCESS;
1846
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001847#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001848Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001849#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1850
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001851 return uReturn;
1852}
1853
1854
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001855/**
1856 * @brief Ascending & Descending out of nesting levels (decode layer 2).
1857 *
1858 * @param[in] pMe Decoder context
1859 * @param[out] pDecodedItem The decoded item that work is done on.
1860 *
1861 * @retval QCBOR_ERR_UNSUPPORTED
1862 * @retval QCBOR_ERR_HIT_END
1863 * @retval QCBOR_ERR_INT_OVERFLOW
1864 * @retval QCBOR_ERR_STRING_ALLOCATE
1865 * @retval QCBOR_ERR_STRING_TOO_LONG
1866 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001867 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001868 * @retval QCBOR_ERR_BAD_TYPE_7
1869 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1870 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1871 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1872 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1873 * @retval QCBOR_ERR_TOO_MANY_TAGS
1874 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1875 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1876 * @retval QCBOR_ERR_NO_MORE_ITEMS
1877 * @retval QCBOR_ERR_BAD_BREAK
1878 * @retval QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
1879 *
1880 * This handles the traversal descending into and asecnding out of
1881 * maps, arrays and bstr-wrapped CBOR. It figures out the ends of
1882 * definite- and indefinte-length maps and arrays by looking at the
1883 * item count or finding CBOR breaks. It detects the ends of the
1884 * top-level sequence and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001885 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001886static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001887QCBORDecode_Private_GetNextMapOrArray(QCBORDecodeContext *pMe,
1888 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001889{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001890 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001891 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001892
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001893 /* If out of bytes to consume, it is either the end of the
1894 * top-level sequence of some bstr-wrapped CBOR that was entered.
1895 *
1896 * In the case of bstr-wrapped CBOR, the length of the
1897 * UsefulInputBuf was set to that of the bstr-wrapped CBOR. When
1898 * the bstr-wrapped CBOR is exited, the length is set back to the
1899 * top-level's length or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001900 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001901 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001902 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001903 goto Done;
1904 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001905
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001906 /* Check to see if at the end of a bounded definite-length map or
1907 * array. The check for a break ending indefinite-length array is
1908 * later in QCBORDecode_NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001909 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001910 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001911 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001912 goto Done;
1913 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001914
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001915 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001916 uReturn = QCBORDecode_Private_GetNextMapEntry(pMe, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001917 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1918 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001919 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001920 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301921
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001922 /* Breaks ending arrays/maps are processed later in the call to
1923 * QCBORDecode_NestLevelAscender(). They should never show up here.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001924 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301925 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001926 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301927 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301928 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001929
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001930 /* Record the nesting level for this data item before processing
1931 * any of decrementing and descending.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001932 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001933 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001934
Laurence Lundblade642282a2020-06-23 12:00:33 -07001935
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001936 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001937 if(QCBORItem_IsMapOrArray(*pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001938 /* If the new item is a map or array, descend.
1939 *
1940 * Empty indefinite-length maps and arrays are descended into,
1941 * but then ascended out of in the next chunk of code.
1942 *
1943 * Maps and arrays do count as items in the map/array that
1944 * encloses them so a decrement needs to be done for them too,
1945 * but that is done only when all the items in them have been
1946 * processed, not when they are opened with the exception of an
1947 * empty map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001948 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001949 QCBORError uDescendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001950 uDescendErr = DecodeNesting_DescendMapOrArray(&(pMe->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001951 pDecodedItem->uDataType,
1952 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001953 if(uDescendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001954 /* This error is probably a traversal error and it overrides
1955 * the non-traversal error.
1956 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001957 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001958 goto Done;
1959 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001960 }
1961
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001962 if(!QCBORItem_IsMapOrArray(*pDecodedItem) ||
1963 QCBORItem_IsEmptyDefiniteLengthMapOrArray(*pDecodedItem) ||
1964 QCBORItem_IsIndefiniteLengthMapOrArray(*pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001965 /* The following cases are handled here:
1966 * - A non-aggregate item like an integer or string
1967 * - An empty definite-length map or array
1968 * - An indefinite-length map or array that might be empty or might not.
1969 *
1970 * QCBORDecode_NestLevelAscender() does the work of decrementing the count
1971 * for an definite-length map/array and break detection for an
1972 * indefinite-0length map/array. If the end of the map/array was
1973 * reached, then it ascends nesting levels, possibly all the way
1974 * to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001975 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001976 QCBORError uAscendErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07001977 uAscendErr = QCBORDecode_Private_NestLevelAscender(pMe, true);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001978 if(uAscendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001979 /* This error is probably a traversal error and it overrides
1980 * the non-traversal error.
1981 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001982 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001983 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001984 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301985 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001986
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001987 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001988 /* Tell the caller what level is next. This tells them what
1989 * maps/arrays were closed out and makes it possible for them to
1990 * reconstruct the tree with just the information returned in a
1991 * QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001992 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001993 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001994 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001995 pDecodedItem->uNextNestLevel = 0;
1996 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001997 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001998 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001999
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002000Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002001 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002002}
2003
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002004
Laurence Lundblade37286c02022-09-03 10:05:02 -07002005#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002006/**
2007 * @brief Shift 0th tag out of the tag list.
2008 *
2009 * pDecodedItem[in,out] The data item to convert.
2010 *
2011 * The 0th tag is discarded. \ref CBOR_TAG_INVALID16 is
2012 * shifted into empty slot at the end of the tag list.
2013 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002014static void
2015QCBOR_Private_ShiftTags(QCBORItem *pDecodedItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002016{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002017 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM-1; i++) {
2018 pDecodedItem->uTags[i] = pDecodedItem->uTags[i+1];
2019 }
2020 pDecodedItem->uTags[QCBOR_MAX_TAGS_PER_ITEM-1] = CBOR_TAG_INVALID16;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002021}
2022
Laurence Lundblade37286c02022-09-03 10:05:02 -07002023#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002024
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002025/**
2026 * @brief Convert different epoch date formats in to the QCBOR epoch date format
2027 *
2028 * pDecodedItem[in,out] The data item to convert.
2029 *
2030 * @retval QCBOR_ERR_DATE_OVERFLOW
2031 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002032 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002033 * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002034 *
2035 * The epoch date tag defined in QCBOR allows for floating-point
2036 * dates. It even allows a protocol to flop between date formats when
2037 * ever it wants. Floating-point dates aren't that useful as they are
2038 * only needed for dates beyond the age of the earth.
2039 *
2040 * This converts all the date formats into one format of an unsigned
2041 * integer plus a floating-point fraction.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002042 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002043static QCBORError
2044QCBOR_Private_DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002045{
Laurence Lundbladec7114722020-08-13 05:11:40 -07002046 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002047
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002048#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade59289e52019-12-30 13:44:37 -08002049 pDecodedItem->val.epochDate.fSecondsFraction = 0;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002050#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002051
2052 switch (pDecodedItem->uDataType) {
2053
2054 case QCBOR_TYPE_INT64:
2055 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
2056 break;
2057
2058 case QCBOR_TYPE_UINT64:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002059 /* This only happens for CBOR type 0 > INT64_MAX so it is
2060 * always an overflow.
2061 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002062 uReturn = QCBOR_ERR_DATE_OVERFLOW;
2063 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002064 break;
2065
2066 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07002067 case QCBOR_TYPE_FLOAT:
2068#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08002069 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002070 /* Convert working value to double if input was a float */
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07002071 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002072 pDecodedItem->val.dfnum :
2073 (double)pDecodedItem->val.fnum;
2074
2075 /* The conversion from float to integer requires overflow
2076 * detection since floats can be much larger than integers.
2077 * This implementation errors out on these large float values
2078 * since they are beyond the age of the earth.
2079 *
2080 * These constants for the overflow check are computed by the
2081 * compiler. They are not computed at run time.
2082 *
2083 * The factor of 0x7ff is added/subtracted to avoid a
2084 * rounding error in the wrong direction when the compiler
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002085 * computes these constants. There is rounding because a
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002086 * 64-bit integer has 63 bits of precision where a double
2087 * only has 53 bits. Without the 0x7ff factor, the compiler
2088 * may round up and produce a double for the bounds check
2089 * that is larger than can be stored in a 64-bit integer. The
2090 * amount of 0x7ff is picked because it has 11 bits set.
2091 *
2092 * Without the 0x7ff there is a ~30 minute range of time
2093 * values 10 billion years in the past and in the future
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002094 * where this code could go wrong. Some compilers
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002095 * generate a warning or error without the 0x7ff.
2096 */
2097 const double dDateMax = (double)(INT64_MAX - 0x7ff);
2098 const double dDateMin = (double)(INT64_MIN + 0x7ff);
2099
2100 if(isnan(d) || d > dDateMax || d < dDateMin) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07002101 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002102 goto Done;
2103 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002104
2105 /* The actual conversion */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002106 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07002107 pDecodedItem->val.epochDate.fSecondsFraction =
2108 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002109 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002110#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade4b270642020-08-14 12:53:07 -07002111
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002112 uReturn = QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07002113 goto Done;
2114
Laurence Lundblade9682a532020-06-06 18:33:04 -07002115#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002116 break;
2117
2118 default:
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002119 /* It's the arrays and maps that are unrecoverable because
2120 * they are not consumed here. Since this is just an error
2121 * condition, no extra code is added here to make the error
2122 * recoverable for non-arrays and maps like strings. */
2123 uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002124 goto Done;
2125 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002126
Laurence Lundblade59289e52019-12-30 13:44:37 -08002127 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
2128
2129Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07002130 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002131}
2132
2133
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002134/**
2135 * @brief Convert the days epoch date.
2136 *
2137 * pDecodedItem[in,out] The data item to convert.
2138 *
2139 * @retval QCBOR_ERR_DATE_OVERFLOW
2140 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002141 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002142 * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002143 *
2144 * This is much simpler than the other epoch date format because
2145 * floating-porint is not allowed. This is mostly a simple type check.
2146 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002147static QCBORError
2148QCBOR_Private_DecodeDaysEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002149{
2150 QCBORError uReturn = QCBOR_SUCCESS;
2151
2152 switch (pDecodedItem->uDataType) {
2153
2154 case QCBOR_TYPE_INT64:
2155 pDecodedItem->val.epochDays = pDecodedItem->val.int64;
2156 break;
2157
2158 case QCBOR_TYPE_UINT64:
2159 /* This only happens for CBOR type 0 > INT64_MAX so it is
2160 * always an overflow.
2161 */
2162 uReturn = QCBOR_ERR_DATE_OVERFLOW;
2163 goto Done;
2164 break;
2165
2166 default:
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002167 /* It's the arrays and maps that are unrecoverable because
2168 * they are not consumed here. Since this is just an error
2169 * condition, no extra code is added here to make the error
2170 * recoverable for non-arrays and maps like strings. */
2171 uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002172 goto Done;
2173 break;
2174 }
2175
2176 pDecodedItem->uDataType = QCBOR_TYPE_DAYS_EPOCH;
2177
2178Done:
2179 return uReturn;
2180}
2181
2182
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002183#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade37286c02022-09-03 10:05:02 -07002184
2185/* Forward declaration is necessary for
2186 * QCBORDecode_MantissaAndExponent(). to be able to decode bignum
2187 * tags in the mantissa. If the mantissa is a decimal fraction or big
2188 * float in error, this will result in a recurive call to
2189 * QCBORDecode_MantissaAndExponent(), but the recursion will unwined
2190 * correctly and the correct error is returned.
2191 */
2192static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002193QCBORDecode_Private_GetNextTagContent(QCBORDecodeContext *pMe,
2194 QCBORItem *pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07002195
2196
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002197/**
2198 * @brief Decode decimal fractions and big floats.
2199 *
2200 * @param[in] pMe The decode context.
2201 * @param[in,out] pDecodedItem On input the array data item that
2202 * holds the mantissa and exponent. On
2203 * output the decoded mantissa and
2204 * exponent.
2205 *
2206 * @returns Decoding errors from getting primitive data items or
2207 * \ref QCBOR_ERR_BAD_EXP_AND_MANTISSA.
2208 *
Laurence Lundblade37286c02022-09-03 10:05:02 -07002209 * When called pDecodedItem must be the array with two members, the
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002210 * exponent and mantissa.
2211 *
2212 * This will fetch and decode the exponent and mantissa and put the
2213 * result back into pDecodedItem.
Laurence Lundblade37286c02022-09-03 10:05:02 -07002214 *
2215 * This does no checking or processing of tag numbers. That is to be
2216 * done by the code that calls this.
2217 *
2218 * This stuffs the type of the mantissa into pDecodedItem with the expectation
2219 * the caller will process it.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002220 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07002221static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002222QCBORDecode_Private_ExpMantissa(QCBORDecodeContext *pMe,
2223 QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002224{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002225 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002226
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002227 /* --- Make sure it is an array; track nesting level of members --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002228 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002229 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002230 goto Done;
2231 }
2232
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002233 /* A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundblade37286c02022-09-03 10:05:02 -07002234 * definite-length arrays, but not for indefinite. Instead remember
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002235 * the nesting level the two integers must be at, which is one
2236 * deeper than that of the array.
2237 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002238 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
2239
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002240 /* --- Get the exponent --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002241 QCBORItem exponentItem;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002242 uReturn = QCBORDecode_Private_GetNextMapOrArray(pMe, &exponentItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002243 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002244 goto Done;
2245 }
2246 if(exponentItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002247 /* Array is empty or a map/array encountered when expecting an int */
2248 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002249 goto Done;
2250 }
2251 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002252 /* Data arriving as an unsigned int < INT64_MAX has been
2253 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2254 * also means that the only data arriving here of type
2255 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2256 * and thus an error that will get handled in the next else.
2257 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002258 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
2259 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002260 /* Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX */
2261 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002262 goto Done;
2263 }
2264
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002265 /* --- Get the mantissa --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002266 QCBORItem mantissaItem;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002267 uReturn = QCBORDecode_Private_GetNextTagContent(pMe, &mantissaItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002268 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002269 goto Done;
2270 }
2271 if(mantissaItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002272 /* Mantissa missing or map/array encountered when expecting number */
2273 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002274 goto Done;
2275 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002276 /* Stuff the mantissa data type into the item to send it up to the
2277 * the next level. */
2278 pDecodedItem->uDataType = mantissaItem.uDataType;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002279 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002280 /* Data arriving as an unsigned int < INT64_MAX has been
2281 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2282 * also means that the only data arriving here of type
2283 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2284 * and thus an error that will get handled in an else below.
2285 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002286 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002287#ifndef QCBOR_DISABLE_TAGS
2288 /* With tags fully disabled a big number mantissa will error out
2289 * in the call to QCBORDecode_GetNextWithTags() because it has
2290 * a tag number.
2291 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002292 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
2293 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002294 /* Got a good big num mantissa */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002295 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002296#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002297 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002298 /* Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX */
2299 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002300 goto Done;
2301 }
2302
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002303 /* --- Check that array only has the two numbers --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002304 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002305 /* Extra items in the decimal fraction / big float */
Laurence Lundblade37286c02022-09-03 10:05:02 -07002306 /* Improvement: this should probably be an unrecoverable error. */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002307 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002308 goto Done;
2309 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002310 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002311
2312Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002313 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002314}
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002315#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002316
2317
Laurence Lundblade37286c02022-09-03 10:05:02 -07002318#ifndef QCBOR_DISABLE_TAGS
2319
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002320#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002321/**
2322 * @brief Decode the MIME type tag
2323 *
2324 * @param[in,out] pDecodedItem The item to decode.
2325 *
2326 * Handle the text and binary MIME type tags. Slightly too complicated
2327 * f or ProcessTaggedString() because the RFC 7049 MIME type was
2328 * incorreclty text-only.
2329 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002330static QCBORError
2331QCBOR_Private_DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002332{
2333 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
2334 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07002335 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002336 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
2337 } else {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002338 /* It's the arrays and maps that are unrecoverable because
2339 * they are not consumed here. Since this is just an error
2340 * condition, no extra code is added here to make the error
2341 * recoverable for non-arrays and maps like strings. */
2342 return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002343 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002344
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002345 return QCBOR_SUCCESS;
2346}
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002347#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002348
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002349/**
Laurence Lundblade99615302020-11-29 11:19:47 -08002350 * Table of CBOR tags whose content is either a text string or a byte
2351 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
2352 * of uQCBORtype indicates the content should be a byte string rather
2353 * than a text string
2354 */
2355struct StringTagMapEntry {
2356 uint16_t uTagNumber;
2357 uint8_t uQCBORtype;
2358};
2359
2360#define IS_BYTE_STRING_BIT 0x80
2361#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
2362
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002363static const struct StringTagMapEntry QCBOR_Private_StringTagMap[] = {
Laurence Lundblade99615302020-11-29 11:19:47 -08002364 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002365 {CBOR_TAG_DAYS_STRING, QCBOR_TYPE_DAYS_STRING},
Laurence Lundblade99615302020-11-29 11:19:47 -08002366 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
2367 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
2368 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
2369 {CBOR_TAG_URI, QCBOR_TYPE_URI},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002370#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002371 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
2372 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
2373 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
2374 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002375#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade99615302020-11-29 11:19:47 -08002376 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
2377 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
2378};
2379
2380
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002381/**
2382 * @brief Process standard CBOR tags whose content is a string
2383 *
2384 * @param[in] uTag The tag.
2385 * @param[in,out] pDecodedItem The data item.
2386 *
2387 * @returns This returns QCBOR_SUCCESS if the tag was procssed,
2388 * \ref QCBOR_ERR_UNSUPPORTED if the tag was not processed and
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002389 * \ref QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT if the content type was wrong for the tag.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002390 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002391 * Process the CBOR tags that whose content is a byte string or a text
2392 * string and for which the string is just passed on to the caller.
2393 *
2394 * This maps the CBOR tag to the QCBOR type and checks the content
2395 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08002396 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08002397 * possible.
Laurence Lundblade99615302020-11-29 11:19:47 -08002398 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002399static QCBORError
2400QCBOR_Private_ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002401{
Laurence Lundblade99615302020-11-29 11:19:47 -08002402 /* This only works on tags that were not mapped; no need for other yet */
2403 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
2404 return QCBOR_ERR_UNSUPPORTED;
2405 }
2406
2407 unsigned uIndex;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002408 for(uIndex = 0; QCBOR_Private_StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
2409 if(QCBOR_Private_StringTagMap[uIndex].uTagNumber == uTag) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002410 break;
2411 }
2412 }
2413
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002414 const uint8_t uQCBORType = QCBOR_Private_StringTagMap[uIndex].uQCBORtype;
Laurence Lundblade99615302020-11-29 11:19:47 -08002415 if(uQCBORType == QCBOR_TYPE_NONE) {
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002416 /* repurpose this error to mean not handled here */
Laurence Lundblade99615302020-11-29 11:19:47 -08002417 return QCBOR_ERR_UNSUPPORTED;
2418 }
2419
2420 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
2421 if(uQCBORType & IS_BYTE_STRING_BIT) {
2422 uExpectedType = QCBOR_TYPE_BYTE_STRING;
2423 }
2424
2425 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002426 /* It's the arrays and maps that are unrecoverable because
2427 * they are not consumed here. Since this is just an error
2428 * condition, no extra code is added here to make the error
2429 * recoverable for non-arrays and maps like strings. */
2430 return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002431 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002432
Laurence Lundblade99615302020-11-29 11:19:47 -08002433 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002434 return QCBOR_SUCCESS;
2435}
Laurence Lundblade37286c02022-09-03 10:05:02 -07002436#endif /* QCBOR_DISABLE_TAGS */
2437
2438
2439#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
2440/*
2441 * This returns the QCBOR_TYPE for a mantissa and exponent.
2442
2443Called in one context where there is always a tag
2444
2445 Called in another context where there might be a tag or the caller might say what they are expecting.
2446
2447 6 possible outputs
2448 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002449static uint8_t
2450QCBOR_Private_ExpMantissaDataType(const uint16_t uTagToProcess,
2451 const QCBORItem *pDecodedItem)
Laurence Lundblade37286c02022-09-03 10:05:02 -07002452{
2453 uint8_t uBase = uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ?
2454 QCBOR_TYPE_DECIMAL_FRACTION :
2455 QCBOR_TYPE_BIGFLOAT;
2456 if(pDecodedItem->uDataType != QCBOR_TYPE_INT64) {
2457 uBase = (uint8_t)(uBase + pDecodedItem->uDataType - QCBOR_TYPE_POSBIGNUM + 1);
2458 }
2459 return uBase;
2460}
2461#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002462
2463
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002464/**
2465 * @brief Decode tag content for select tags (decoding layer 1).
2466 *
2467 * @param[in] pMe The decode context.
2468 * @param[out] pDecodedItem The decoded item.
2469 *
2470 * @return Decoding error code.
2471 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002472 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
2473 * but the whole tag was not decoded. Here, the whole tags (tag number
2474 * and tag content) that are supported by QCBOR are decoded. This is a
2475 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002476 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002477static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002478QCBORDecode_Private_GetNextTagContent(QCBORDecodeContext *pMe,
2479 QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002480{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002481 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002482
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002483 uReturn = QCBORDecode_Private_GetNextMapOrArray(pMe, pDecodedItem);
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002484 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002485 goto Done;
2486 }
2487
Laurence Lundblade37286c02022-09-03 10:05:02 -07002488#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002489 /* When there are no tag numbers for the item, this exits first
2490 * thing and effectively does nothing.
2491 *
2492 * This loops over all the tag numbers accumulated for this item
2493 * trying to decode and interpret them. This stops at the end of
2494 * the list or at the first tag number that can't be interpreted by
2495 * this code. This is effectively a recursive processing of the
2496 * tags number list that handles nested tags.
2497 */
2498 while(1) {
2499 /* Don't bother to unmap tags via QCBORITem.uTags since this
2500 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2501 */
2502 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002503
Laurence Lundblade99615302020-11-29 11:19:47 -08002504 if(uTagToProcess == CBOR_TAG_INVALID16) {
2505 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002506 break;
2507
Laurence Lundblade99615302020-11-29 11:19:47 -08002508 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002509 uReturn = QCBOR_Private_DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002510
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002511 } else if(uTagToProcess == CBOR_TAG_DAYS_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002512 uReturn = QCBOR_Private_DecodeDaysEpoch(pDecodedItem);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002513
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002514#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002515 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2516 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002517 uReturn = QCBORDecode_Private_ExpMantissa(pMe, pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07002518 /* --- Which is it, decimal fraction or a bigfloat? --- */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002519 pDecodedItem->uDataType = QCBOR_Private_ExpMantissaDataType(uTagToProcess, pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07002520
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002521#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002522#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002523 } else if(uTagToProcess == CBOR_TAG_MIME ||
2524 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002525 uReturn = QCBOR_Private_DecodeMIME(pDecodedItem);
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002526#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002527
Laurence Lundblade99615302020-11-29 11:19:47 -08002528 } else {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002529 /* See if it is a passthrough byte/text string tag; process if so */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002530 uReturn = QCBOR_Private_ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002531
Laurence Lundblade99615302020-11-29 11:19:47 -08002532 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002533 /* It wasn't a passthrough byte/text string tag so it is
Laurence Lundblade99615302020-11-29 11:19:47 -08002534 * an unknown tag. This is the exit from the loop on the
2535 * first unknown tag. It is a successful exit.
2536 */
2537 uReturn = QCBOR_SUCCESS;
2538 break;
2539 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002540 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002541
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002542 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002543 /* Error exit from the loop */
2544 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002545 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002546
2547 /* A tag was successfully processed, shift it out of the list of
2548 * tags returned. This is the loop increment.
2549 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002550 QCBOR_Private_ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002551 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002552#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002553
2554Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002555 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002556}
2557
2558
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002559/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002560 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002561 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002562QCBORError
2563QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2564{
2565 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002566 uErr = QCBORDecode_Private_GetNextTagContent(pMe, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002567 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002568 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2569 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2570 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002571 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002572}
2573
2574
2575/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002576 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002577 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002578QCBORError
2579QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2580{
2581 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2582 const UsefulInputBuf Save = pMe->InBuf;
2583
2584 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2585
2586 pMe->nesting = SaveNesting;
2587 pMe->InBuf = Save;
2588
2589 return uErr;
2590}
2591
2592
2593/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002594 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002595 */
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002596void
2597QCBORDecode_VPeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2598{
2599 if(pMe->uLastError != QCBOR_SUCCESS) {
2600 return;
2601 }
2602
2603 pMe->uLastError = (uint8_t)QCBORDecode_PeekNext(pMe, pDecodedItem);
2604}
2605
2606
2607/*
2608 * Public function, see header qcbor/qcbor_decode.h file
2609 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002610void
2611QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002612{
2613 if(pMe->uLastError != QCBOR_SUCCESS) {
2614 return;
2615 }
2616
2617 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2618}
2619
2620
2621/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002622 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002623 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002624QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002625QCBORDecode_GetNextWithTags(QCBORDecodeContext *pMe,
2626 QCBORItem *pDecodedItem,
2627 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002628{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002629#ifndef QCBOR_DISABLE_TAGS
2630
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002631 QCBORError uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002632
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002633 uReturn = QCBORDecode_GetNext(pMe, pDecodedItem);
2634 if(uReturn != QCBOR_SUCCESS) {
2635 return uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002636 }
2637
2638 if(pTags != NULL) {
2639 pTags->uNumUsed = 0;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002640 /* Reverse the order because pTags is reverse of QCBORItem.uTags. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002641 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2642 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002643 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002644 }
2645 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2646 return QCBOR_ERR_TOO_MANY_TAGS;
2647 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002648 pTags->puTags[pTags->uNumUsed] = QCBORDecode_Private_UnMapTagNumber(pMe,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002649 pTags->uNumUsed++;
2650 }
2651 }
2652
2653 return QCBOR_SUCCESS;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002654
2655#else /* QCBOR_DISABLE_TAGS */
2656 (void)pMe;
2657 (void)pDecodedItem;
2658 (void)pTags;
2659 return QCBOR_ERR_TAGS_DISABLED;
2660#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002661}
2662
2663
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002664/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002665 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302666 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002667bool
2668QCBORDecode_IsTagged(QCBORDecodeContext *pMe,
2669 const QCBORItem *pItem,
2670 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002671{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002672#ifndef QCBOR_DISABLE_TAGS
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002673 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2674 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002675 break;
2676 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002677 if(QCBORDecode_Private_UnMapTagNumber(pMe, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002678 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002679 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002680 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002681#else /* QCBOR_TAGS_DISABLED */
2682 (void)pMe;
2683 (void)pItem;
2684 (void)uTag;
2685#endif /* QCBOR_TAGS_DISABLED */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002686
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002687 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002688}
2689
2690
2691/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002692 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002693 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002694QCBORError
2695QCBORDecode_PartialFinish(QCBORDecodeContext *pMe, size_t *puConsumed)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002696{
Laurence Lundblade87495732021-02-26 10:05:55 -07002697 if(puConsumed != NULL) {
2698 *puConsumed = pMe->InBuf.cursor;
2699 }
2700
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002701 QCBORError uReturn = pMe->uLastError;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002702
2703 if(uReturn != QCBOR_SUCCESS) {
2704 goto Done;
2705 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002706
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002707 /* Error out if all the maps/arrays are not closed out */
2708 if(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002709 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002710 goto Done;
2711 }
2712
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002713 /* Error out if not all the bytes are consumed */
2714 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002715 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002716 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002717
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002718Done:
Laurence Lundblade87495732021-02-26 10:05:55 -07002719 return uReturn;
2720}
2721
2722
2723/*
2724 * Public function, see header qcbor/qcbor_decode.h file
2725 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002726QCBORError
2727QCBORDecode_Finish(QCBORDecodeContext *pMe)
Laurence Lundblade87495732021-02-26 10:05:55 -07002728{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002729#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002730 /* Call the destructor for the string allocator if there is one.
2731 * Always called, even if there are errors; always have to clean up.
2732 */
2733 StringAllocator_Destruct(&(pMe->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002734#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002735
Laurence Lundblade87495732021-02-26 10:05:55 -07002736 return QCBORDecode_PartialFinish(pMe, NULL);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002737}
2738
2739
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002740/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002741 * Public function, see header qcbor/qcbor_decode.h file
2742 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002743// Improvement: make these inline? TODO:
2744uint64_t
2745QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2746 const QCBORItem *pItem,
2747 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002748{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002749#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002750 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2751 return CBOR_TAG_INVALID64;
2752 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002753 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2754 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002755 } else {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002756 return QCBORDecode_Private_UnMapTagNumber(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002757 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002758#else /* QCBOR_DISABLE_TAGS */
2759 (void)pMe;
2760 (void)pItem;
2761 (void)uIndex;
2762
2763 return CBOR_TAG_INVALID64;
2764#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002765}
2766
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002767
Laurence Lundblade9b334962020-08-27 10:55:53 -07002768/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002769 * Public function, see header qcbor/qcbor_decode.h file
2770 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002771uint64_t
2772QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2773 uint32_t uIndex)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002774{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002775#ifndef QCBOR_DISABLE_TAGS
2776
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002777 if(pMe->uLastError != QCBOR_SUCCESS) {
2778 return CBOR_TAG_INVALID64;
2779 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002780 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2781 return CBOR_TAG_INVALID64;
2782 } else {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002783 return QCBORDecode_Private_UnMapTagNumber(pMe, pMe->uLastTags[uIndex]);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002784 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002785#else /* QCBOR_DISABLE_TAGS */
2786 (void)pMe;
2787 (void)uIndex;
2788
2789 return CBOR_TAG_INVALID64;
2790#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002791}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002792
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002793
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002794
2795
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002796#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002797
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002798/* ===========================================================================
2799 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002800
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002801 This implements a simple sting allocator for indefinite-length
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002802 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2803 implements the function type QCBORStringAllocate and allows easy
2804 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002805
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002806 This particular allocator is built-in for convenience. The caller
2807 can implement their own. All of this following code will get
2808 dead-stripped if QCBORDecode_SetMemPool() is not called.
2809
2810 This is a very primitive memory allocator. It does not track
2811 individual allocations, only a high-water mark. A free or
2812 reallocation must be of the last chunk allocated.
2813
2814 The size of the pool and offset to free memory are packed into the
2815 first 8 bytes of the memory pool so we don't have to keep them in
2816 the decode context. Since the address of the pool may not be
2817 aligned, they have to be packed and unpacked as if they were
2818 serialized data of the wire or such.
2819
2820 The sizes packed in are uint32_t to be the same on all CPU types
2821 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002822 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002823
2824
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002825static int
Laurence Lundbladeee851742020-01-08 08:37:05 -08002826MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002827{
2828 // Use of UsefulInputBuf is overkill, but it is convenient.
2829 UsefulInputBuf UIB;
2830
Laurence Lundbladeee851742020-01-08 08:37:05 -08002831 // Just assume the size here. It was checked during SetUp so
2832 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002833 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002834 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2835 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2836 return UsefulInputBuf_GetError(&UIB);
2837}
2838
2839
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002840static int
Laurence Lundbladeee851742020-01-08 08:37:05 -08002841MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002842{
2843 // Use of UsefulOutBuf is overkill, but convenient. The
2844 // length check performed here is useful.
2845 UsefulOutBuf UOB;
2846
2847 UsefulOutBuf_Init(&UOB, Pool);
2848 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2849 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2850 return UsefulOutBuf_GetError(&UOB);
2851}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002852
2853
2854/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002855 Internal function for an allocation, reallocation free and destuct.
2856
2857 Having only one function rather than one each per mode saves space in
2858 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002859
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002860 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2861 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002862static UsefulBuf
2863MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002864{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002865 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002866
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002867 uint32_t uPoolSize;
2868 uint32_t uFreeOffset;
2869
2870 if(uNewSize > UINT32_MAX) {
2871 // This allocator is only good up to 4GB. This check should
2872 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2873 goto Done;
2874 }
2875 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2876
2877 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2878 goto Done;
2879 }
2880
2881 if(uNewSize) {
2882 if(pMem) {
2883 // REALLOCATION MODE
2884 // Calculate pointer to the end of the memory pool. It is
2885 // assumed that pPool + uPoolSize won't wrap around by
2886 // assuming the caller won't pass a pool buffer in that is
2887 // not in legitimate memory space.
2888 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2889
2890 // Check that the pointer for reallocation is in the range of the
2891 // pool. This also makes sure that pointer math further down
2892 // doesn't wrap under or over.
2893 if(pMem >= pPool && pMem < pPoolEnd) {
2894 // Offset to start of chunk for reallocation. This won't
2895 // wrap under because of check that pMem >= pPool. Cast
2896 // is safe because the pool is always less than UINT32_MAX
2897 // because of check in QCBORDecode_SetMemPool().
2898 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2899
2900 // Check to see if the allocation will fit. uPoolSize -
2901 // uMemOffset will not wrap under because of check that
2902 // pMem is in the range of the uPoolSize by check above.
2903 if(uNewSize <= uPoolSize - uMemOffset) {
2904 ReturnValue.ptr = pMem;
2905 ReturnValue.len = uNewSize;
2906
2907 // Addition won't wrap around over because uNewSize was
2908 // checked to be sure it is less than the pool size.
2909 uFreeOffset = uMemOffset + uNewSize32;
2910 }
2911 }
2912 } else {
2913 // ALLOCATION MODE
2914 // uPoolSize - uFreeOffset will not underflow because this
2915 // pool implementation makes sure uFreeOffset is always
2916 // smaller than uPoolSize through this check here and
2917 // reallocation case.
2918 if(uNewSize <= uPoolSize - uFreeOffset) {
2919 ReturnValue.len = uNewSize;
2920 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002921 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002922 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002923 }
2924 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002925 if(pMem) {
2926 // FREE MODE
2927 // Cast is safe because of limit on pool size in
2928 // QCBORDecode_SetMemPool()
2929 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2930 } else {
2931 // DESTRUCT MODE
2932 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002933 }
2934 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002935
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002936 UsefulBuf Pool = {pPool, uPoolSize};
2937 MemPool_Pack(Pool, uFreeOffset);
2938
2939Done:
2940 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002941}
2942
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002943
Laurence Lundbladef6531662018-12-04 10:42:22 +09002944/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002945 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002946 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002947QCBORError
2948QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2949 UsefulBuf Pool,
2950 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002951{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002952 // The pool size and free mem offset are packed into the beginning
Dave Thaler93c01182022-08-06 15:08:35 -04002953 // of the pool memory. This compile time check makes sure the
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002954 // constant in the header is correct. This check should optimize
2955 // down to nothing.
Dave Thaler93c01182022-08-06 15:08:35 -04002956#ifdef _MSC_VER
2957#pragma warning(push)
2958#pragma warning(disable:4127) // conditional expression is constant
2959#endif
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002960 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002961 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002962 }
Dave Thaler93c01182022-08-06 15:08:35 -04002963#ifdef _MSC_VER
2964#pragma warning(pop)
2965#endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002966
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002967 // The pool size and free offset packed in to the beginning of pool
2968 // memory are only 32-bits. This check will optimize out on 32-bit
2969 // machines.
2970 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002971 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002972 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002973
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002974 // This checks that the pool buffer given is big enough.
2975 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002976 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002977 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002978
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002979 QCBORDecode_SetUpAllocator(pMe, MemPool_Function, Pool.ptr, bAllStrings);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002980
Laurence Lundblade30816f22018-11-10 13:40:22 +07002981 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002982}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002983#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002984
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002985
2986
Laurence Lundblade8e36f812024-01-26 10:59:29 -07002987static void
2988QCBORDecode_Private_CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002989{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002990#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade9b334962020-08-27 10:55:53 -07002991 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
Laurence Lundblade37286c02022-09-03 10:05:02 -07002992#else
2993 (void)pMe;
2994 (void)pItem;
2995#endif
Laurence Lundblade9b334962020-08-27 10:55:53 -07002996}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002997
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002998
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002999/**
3000 * @brief Consume an entire map or array including its contents.
3001 *
3002 * @param[in] pMe The decoder context.
3003 * @param[in] pItemToConsume The array/map whose contents are to be
3004 * consumed.
3005 * @param[out] puNextNestLevel The next nesting level after the item was
3006 * fully consumed.
3007 *
3008 * This may be called when @c pItemToConsume is not an array or
3009 * map. In that case, this is just a pass through for @c puNextNestLevel
3010 * since there is nothing to do.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003011 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003012static QCBORError
3013QCBORDecode_Private_ConsumeItem(QCBORDecodeContext *pMe,
3014 const QCBORItem *pItemToConsume,
3015 uint8_t *puNextNestLevel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003016{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003017 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003018 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003019
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003020 /* If it is a map or array, this will tell if it is empty. */
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003021 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
3022
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003023 if(QCBORItem_IsMapOrArray(*pItemToConsume) && !bIsEmpty) {
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003024 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003025
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003026 /* This works for definite- and indefinite-length maps and
3027 * arrays by using the nesting level
Laurence Lundblade1341c592020-04-11 14:19:05 -07003028 */
3029 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003030 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003031 if(QCBORDecode_IsUnrecoverableError(uReturn) ||
3032 uReturn == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003033 goto Done;
3034 }
3035 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003036
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003037 *puNextNestLevel = Item.uNextNestLevel;
3038
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003039 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003040
Laurence Lundblade1341c592020-04-11 14:19:05 -07003041 } else {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07003042 /* pItemToConsume is not a map or array. Just pass the nesting
3043 * level through. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003044 *puNextNestLevel = pItemToConsume->uNextNestLevel;
3045
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003046 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003047 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003048
3049Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003050 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003051}
3052
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003053
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003054/*
3055 * Public function, see header qcbor/qcbor_decode.h file
3056 */
3057void
3058QCBORDecode_VGetNextConsume(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003059{
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003060 QCBORDecode_VGetNext(pMe, pDecodedItem);
3061
3062 if(pMe->uLastError == QCBOR_SUCCESS) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003063 pMe->uLastError = (uint8_t)QCBORDecode_Private_ConsumeItem(pMe, pDecodedItem,
Máté Tóth-Pálc6d59682021-05-26 18:55:30 +02003064 &pDecodedItem->uNextNestLevel);
Laurence Lundblade732e52d2021-02-22 20:11:01 -07003065 }
3066}
3067
3068
3069
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003070/* Call only on maps and arrays. Rewinds the cursor
3071 * to the start as if it was just entered.
3072 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003073static void
3074QCBORDecode_Private_RewindMapOrArray(QCBORDecodeContext *pMe)
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003075{
3076 /* Reset nesting tracking to the deepest bounded level */
3077 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
3078
3079 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3080
3081 /* Reposition traversal cursor to the start of the map/array */
3082 UsefulInputBuf_Seek(&(pMe->InBuf),
3083 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
3084}
3085
3086
3087/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003088 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003089 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003090void
3091QCBORDecode_Rewind(QCBORDecodeContext *pMe)
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003092{
3093 if(pMe->nesting.pCurrentBounded != NULL) {
3094 /* In a bounded map, array or bstr-wrapped CBOR */
3095
3096 if(DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
3097 /* In bstr-wrapped CBOR. */
3098
3099 /* Reposition traversal cursor to start of wrapping byte string */
3100 UsefulInputBuf_Seek(&(pMe->InBuf),
3101 pMe->nesting.pCurrentBounded->u.bs.uBstrStartOffset);
3102 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
3103
3104 } else {
3105 /* In a map or array */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003106 QCBORDecode_Private_RewindMapOrArray(pMe);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003107 }
3108
3109 } else {
3110 /* Not in anything bounded */
3111
3112 /* Reposition traversal cursor to the start of input CBOR */
3113 UsefulInputBuf_Seek(&(pMe->InBuf), 0ULL);
3114
3115 /* Reset nesting tracking to beginning of input. */
3116 DecodeNesting_Init(&(pMe->nesting));
3117 }
3118
3119 pMe->uLastError = QCBOR_SUCCESS;
3120}
3121
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003122
Laurence Lundblade9b334962020-08-27 10:55:53 -07003123
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003124
3125
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003126/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003127 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003128
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003129 @param[in] pMe The decode context to search.
3130 @param[in,out] pItemArray The items to search for and the items found.
3131 @param[out] puOffset Byte offset of last item matched.
3132 @param[in] pCBContext Context for the not-found item call back.
3133 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003134
3135 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
3136
Laurence Lundblade93d89472020-10-03 22:30:50 -07003137 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
3138 were found for one of the labels being
3139 search for. This duplicate detection is
3140 only performed for items in pItemArray,
3141 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003142
Laurence Lundblade93d89472020-10-03 22:30:50 -07003143 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
3144 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003145
3146 @retval Also errors returned by QCBORDecode_GetNext().
3147
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003148 On input pItemArray contains a list of labels and data types
3149 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07003150
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003151 On output the fully retrieved items are filled in with
3152 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07003153
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003154 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003155
3156 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003157 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003158static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003159QCBORDecode_Private_MapSearch(QCBORDecodeContext *pMe,
3160 QCBORItem *pItemArray,
3161 size_t *puOffset,
3162 void *pCBContext,
3163 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003164{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003165 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003166 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07003167
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003168 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003169 uReturn = pMe->uLastError;
3170 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003171 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003172
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003173 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003174 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
3175 /* QCBOR_TYPE_NONE as first item indicates just looking
3176 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003177 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
3178 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003179 }
3180
Laurence Lundblade085d7952020-07-24 10:26:30 -07003181 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
3182 // It is an empty bounded array or map
3183 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
3184 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003185 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07003186 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003187 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003188 // Nothing is ever found in an empty array or map. All items
3189 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07003190 uReturn = QCBOR_SUCCESS;
3191 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003192 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003193 }
3194
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003195 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003196 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
3197
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003198 /* Reposition to search from the start of the map / array */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003199 QCBORDecode_Private_RewindMapOrArray(pMe);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003200
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003201 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003202 Loop over all the items in the map or array. Each item
3203 could be a map or array, but label matching is only at
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003204 the main level. This handles definite- and indefinite-
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003205 length maps and arrays. The only reason this is ever
3206 called on arrays is to find their end position.
3207
3208 This will always run over all items in order to do
3209 duplicate detection.
3210
3211 This will exit with failure if it encounters an
3212 unrecoverable error, but continue on for recoverable
3213 errors.
3214
3215 If a recoverable error occurs on a matched item, then
3216 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003217 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07003218 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Máté Tóth-Pál2f2aa5f2021-05-17 21:35:09 +02003219 uint8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003220 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003221 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07003222 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003223
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003224 /* Get the item */
3225 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003226 QCBORError uResult = QCBORDecode_Private_GetNextTagContent(pMe, &Item);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003227 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003228 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003229 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003230 goto Done;
3231 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003232 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003233 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003234 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003235 goto Done;
3236 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003237
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003238 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003239 bool bMatched = false;
3240 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003241 if(QCBORItem_MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003242 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003243 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
3244 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003245 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003246 }
Laurence Lundblade63926052021-03-29 16:05:51 -07003247 if(uResult != QCBOR_SUCCESS) {
3248 /* The label matches, but the data item is in error */
3249 uReturn = uResult;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003250 goto Done;
3251 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003252 if(!QCBORItem_MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade63926052021-03-29 16:05:51 -07003253 /* The data item is not of the type(s) requested */
3254 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003255 goto Done;
3256 }
3257
Laurence Lundblade1341c592020-04-11 14:19:05 -07003258 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003259 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003260 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003261 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003262 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003263 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003264 bMatched = true;
3265 }
3266 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003267
3268
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003269 if(!bMatched && pfCallback != NULL) {
3270 /*
3271 Call the callback on unmatched labels.
3272 (It is tempting to do duplicate detection here, but that would
3273 require dynamic memory allocation because the number of labels
3274 that might be encountered is unbounded.)
3275 */
3276 uReturn = (*pfCallback)(pCBContext, &Item);
3277 if(uReturn != QCBOR_SUCCESS) {
3278 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003279 }
3280 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003281
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003282 /*
3283 Consume the item whether matched or not. This
3284 does the work of traversing maps and array and
3285 everything in them. In this loop only the
3286 items at the current nesting level are examined
3287 to match the labels.
3288 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003289 uReturn = QCBORDecode_Private_ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003290 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003291 goto Done;
3292 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003293 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003294
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003295 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003296
3297 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003298
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003299 // Check here makes sure that this won't accidentally be
3300 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003301 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003302 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
3303 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003304 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
3305 goto Done;
3306 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003307 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
3308 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003309
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003310 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003311 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
3312
3313 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003314 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07003315 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003316 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003317 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
3318 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003319 }
3320 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003321
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003322 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003323}
3324
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003325
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003326/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003327 * Public function, see header qcbor/qcbor_decode.h file
3328 */
3329void
3330QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
3331 int64_t nLabel,
3332 uint8_t uQcborType,
3333 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003334{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003335 if(pMe->uLastError != QCBOR_SUCCESS) {
3336 return;
3337 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003338
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003339 QCBORItem OneItemSeach[2];
3340 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3341 OneItemSeach[0].label.int64 = nLabel;
3342 OneItemSeach[0].uDataType = uQcborType;
3343 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003344
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003345 QCBORError uReturn = QCBORDecode_Private_MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003346
3347 *pItem = OneItemSeach[0];
3348
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003349 if(uReturn != QCBOR_SUCCESS) {
3350 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003351 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003352 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003353 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003354 }
3355
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003356 Done:
3357 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003358}
3359
3360
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003361/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003362 * Public function, see header qcbor/qcbor_decode.h file
3363 */
3364void
3365QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
3366 const char *szLabel,
3367 uint8_t uQcborType,
3368 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003369{
Laurence Lundbladeda095972020-06-06 18:35:33 -07003370 if(pMe->uLastError != QCBOR_SUCCESS) {
3371 return;
3372 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003373
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003374 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003375 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3376 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3377 OneItemSeach[0].uDataType = uQcborType;
3378 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003379
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003380 QCBORError uReturn = QCBORDecode_Private_MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003381 if(uReturn != QCBOR_SUCCESS) {
3382 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003383 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003384 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003385 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003386 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003387 }
3388
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003389 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003390
3391Done:
3392 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003393}
3394
3395
Laurence Lundblade93d89472020-10-03 22:30:50 -07003396static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003397QCBOR_Private_CheckTypeList(const int uDataType,
3398 const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003399{
3400 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08003401 if(uDataType == puTypeList[i]) { /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003402 return QCBOR_SUCCESS;
3403 }
3404 }
3405 return QCBOR_ERR_UNEXPECTED_TYPE;
3406}
3407
Laurence Lundblade67257dc2020-07-27 03:33:37 -07003408
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003409/**
Laurence Lundblade37286c02022-09-03 10:05:02 -07003410 * Match a tag/type specification against the type of the item.
3411 *
3412 * @param[in] TagSpec Specification for matching tags.
3413 * @param[in] pItem The item to check.
3414 *
3415 * @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
3416 * @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
3417 *
3418 * This checks the item data type of untagged items as well as of
3419 * tagged items against a specification to see if decoding should
3420 * proceed.
3421 *
3422 * This relies on the automatic tag decoding done by QCBOR that turns
3423 * tag numbers into particular QCBOR_TYPEs so there is no actual
3424 * comparsion of tag numbers, just of QCBOR_TYPEs.
3425 *
3426 * This checks the data item type as possibly representing the tag
3427 * number or as the tag content type.
3428 *
3429 * If QCBOR_DISABLE_TAGS is #defined, this primarily checks the item
3430 * data type against the allowed tag content types. It will also error out
3431 * if the caller tries to require a tag because there is no way that can
3432 * ever be fulfilled.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003433 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07003434static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003435QCBOR_Private_CheckTagRequirement(const QCBOR_Private_TagSpec TagSpec,
3436 const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07003437{
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08003438 const int nItemType = pItem->uDataType; /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade37286c02022-09-03 10:05:02 -07003439 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
3440
3441#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08003442 /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003443 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
3444 pItem->uTags[0] != CBOR_TAG_INVALID16) {
3445 /* There are tags that QCBOR couldn't process on this item and
Laurence Lundblade37286c02022-09-03 10:05:02 -07003446 * the caller has told us there should not be.
3447 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003448 return QCBOR_ERR_UNEXPECTED_TYPE;
3449 }
3450
Laurence Lundblade9b334962020-08-27 10:55:53 -07003451 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
Laurence Lundblade37286c02022-09-03 10:05:02 -07003452 /* Must match the tag number and only the tag */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003453 return QCBOR_Private_CheckTypeList(nItemType, TagSpec.uTaggedTypes);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003454 }
3455
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003456 QCBORError uReturn = QCBOR_Private_CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003457 if(uReturn == QCBOR_SUCCESS) {
3458 return QCBOR_SUCCESS;
3459 }
3460
3461 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
3462 /* Must match the content type and only the content type.
Laurence Lundblade37286c02022-09-03 10:05:02 -07003463 * There was no match just above so it is a fail. */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003464 return QCBOR_ERR_UNEXPECTED_TYPE;
3465 }
3466
Laurence Lundblade37286c02022-09-03 10:05:02 -07003467 /* QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG: If here it can match either the tag or the content
3468 * and it hasn't matched the content, so the end
3469 * result is whether it matches the tag. This is
3470 * the tag optional case that the CBOR standard discourages.
3471 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003472
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003473 return QCBOR_Private_CheckTypeList(nItemType, TagSpec.uTaggedTypes);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003474
Laurence Lundblade37286c02022-09-03 10:05:02 -07003475#else /* QCBOR_DISABLE_TAGS */
3476 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
3477 return QCBOR_ERR_UNEXPECTED_TYPE;
3478 }
3479
3480 return CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
3481
3482#endif /* QCBOR_DISABLE_TAGS */
3483}
Laurence Lundblade9b334962020-08-27 10:55:53 -07003484
Laurence Lundblade9b334962020-08-27 10:55:53 -07003485
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003486// This could be semi-private if need be
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003487// TODO: decide what to do
3488static void
3489QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
3490 const int64_t nLabel,
3491 const QCBOR_Private_TagSpec TagSpec,
3492 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003493{
3494 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
3495 if(pMe->uLastError != QCBOR_SUCCESS) {
3496 return;
3497 }
3498
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003499 pMe->uLastError = (uint8_t)QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003500}
3501
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003502
3503// This could be semi-private if need be
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003504static void
3505QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
3506 const char *szLabel,
3507 const QCBOR_Private_TagSpec TagSpec,
3508 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003509{
3510 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
3511 if(pMe->uLastError != QCBOR_SUCCESS) {
3512 return;
3513 }
3514
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003515 pMe->uLastError = (uint8_t)QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003516}
3517
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003518// Semi-private
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003519void
3520QCBORDecode_Private_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
3521 const int64_t nLabel,
3522 const QCBOR_Private_TagSpec TagSpec,
3523 UsefulBufC *pString)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003524{
3525 QCBORItem Item;
3526 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
3527 if(pMe->uLastError == QCBOR_SUCCESS) {
3528 *pString = Item.val.string;
3529 }
3530}
3531
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003532// Semi-private
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003533void
3534QCBORDecode_Private_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
3535 const char * szLabel,
3536 const QCBOR_Private_TagSpec TagSpec,
3537 UsefulBufC *pString)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003538{
3539 QCBORItem Item;
3540 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
3541 if(pMe->uLastError == QCBOR_SUCCESS) {
3542 *pString = Item.val.string;
3543 }
3544}
Laurence Lundblade1341c592020-04-11 14:19:05 -07003545
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003546/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003547 * Public function, see header qcbor/qcbor_decode.h file
3548 */
3549void
3550QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003551{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003552 QCBORError uErr = QCBORDecode_Private_MapSearch(pMe, pItemList, NULL, NULL, NULL);
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003553 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003554}
3555
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003556/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003557 * Public function, see header qcbor/qcbor_decode.h file
3558 */
3559void
3560QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3561 QCBORItem *pItemList,
3562 void *pCallbackCtx,
3563 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003564{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003565 QCBORError uErr = QCBORDecode_Private_MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003566 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003567}
3568
3569
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003570/**
3571 * @brief Search for a map/array by label and enter it
3572 *
3573 * @param[in] pMe The decode context.
3574 * @param[in] pSearch The map/array to search for.
3575 *
3576 * @c pSearch is expected to contain one item of type map or array
3577 * with the label specified. The current bounded map will be searched for
3578 * this and if found will be entered.
3579 *
3580 * If the label is not found, or the item found is not a map or array,
3581 * the error state is set.
3582 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003583static void
3584QCBORDecode_Private_SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003585{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003586 // The first item in pSearch is the one that is to be
3587 // entered. It should be the only one filled in. Any other
3588 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003589 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003590 return;
3591 }
3592
3593 size_t uOffset;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003594 pMe->uLastError = (uint8_t)QCBORDecode_Private_MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003595 if(pMe->uLastError != QCBOR_SUCCESS) {
3596 return;
3597 }
3598
Laurence Lundblade9b334962020-08-27 10:55:53 -07003599 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003600 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003601 return;
3602 }
3603
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003604
3605 /* The map or array was found. Now enter it.
3606 *
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003607 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3608 * next item for the pre-order traversal cursor to be the map/array
3609 * found by MapSearch(). The next few lines of code force the
3610 * cursor to that.
3611 *
3612 * There is no need to retain the old cursor because
3613 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3614 * beginning of the map/array being entered.
3615 *
3616 * The cursor is forced by: 1) setting the input buffer position to
3617 * the item offset found by MapSearch(), 2) setting the map/array
3618 * counter to the total in the map/array, 3) setting the nesting
3619 * level. Setting the map/array counter to the total is not
3620 * strictly correct, but this is OK because this cursor only needs
3621 * to be used to get one item and MapSearch() has already found it
3622 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003623 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003624 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003625
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003626 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3627
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003628 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003629
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003630 QCBORDecode_Private_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003631}
3632
3633
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003634/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003635 * Public function, see header qcbor/qcbor_decode.h file
3636 */
3637void
3638QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003639{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003640 QCBORItem OneItemSeach[2];
3641 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3642 OneItemSeach[0].label.int64 = nLabel;
3643 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3644 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003645
Laurence Lundblade9b334962020-08-27 10:55:53 -07003646 /* The map to enter was found, now finish off entering it. */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003647 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003648}
3649
3650
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003651/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003652 * Public function, see header qcbor/qcbor_decode.h file
3653 */
3654void
3655QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003656{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003657 QCBORItem OneItemSeach[2];
3658 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3659 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3660 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3661 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003662
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003663 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003664}
3665
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003666/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003667 * Public function, see header qcbor/qcbor_decode.h file
3668 */
3669void
3670QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003671{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003672 QCBORItem OneItemSeach[2];
3673 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3674 OneItemSeach[0].label.int64 = nLabel;
3675 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3676 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003677
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003678 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003679}
3680
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003681/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003682 * Public function, see header qcbor/qcbor_decode.h file
3683 */
3684void
3685QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundblade34691b92020-05-18 22:25:25 -07003686{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003687 QCBORItem OneItemSeach[2];
3688 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3689 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3690 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3691 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003692
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003693 QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003694}
3695
3696
Laurence Lundblade02625d42020-06-25 14:41:41 -07003697// Semi-private function
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003698void
3699QCBORDecode_Private_EnterBoundedMapOrArray(QCBORDecodeContext *pMe,
3700 const uint8_t uType,
3701 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003702{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003703 QCBORError uErr;
3704
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003705 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003706 if(pMe->uLastError != QCBOR_SUCCESS) {
3707 // Already in error state; do nothing.
3708 return;
3709 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003710
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003711 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003712 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003713 uErr = QCBORDecode_GetNext(pMe, &Item);
3714 if(uErr != QCBOR_SUCCESS) {
3715 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003716 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003717 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003718 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3719 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003720 }
3721
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003722 QCBORDecode_Private_CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003723
3724
Laurence Lundbladef0499502020-08-01 11:55:57 -07003725 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003726 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003727 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3728 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003729 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003730 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3731 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003732 // Special case to increment nesting level for zero-length maps
3733 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003734 DecodeNesting_Descend(&(pMe->nesting), uType);
3735 }
3736
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003737 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003738
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003739 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3740 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003741
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003742 if(pItem != NULL) {
3743 *pItem = Item;
3744 }
3745
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003746Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003747 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003748}
3749
Laurence Lundblade02625d42020-06-25 14:41:41 -07003750
3751/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003752 This is the common work for exiting a level that is a bounded map,
3753 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003754
3755 One chunk of work is to set up the pre-order traversal so it is at
3756 the item just after the bounded map, array or bstr that is being
3757 exited. This is somewhat complex.
3758
3759 The other work is to level-up the bounded mode to next higest bounded
3760 mode or the top level if there isn't one.
3761 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003762static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003763QCBORDecode_Private_ExitBoundedLevel(QCBORDecodeContext *pMe,
3764 const uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003765{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003766 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003767
Laurence Lundblade02625d42020-06-25 14:41:41 -07003768 /*
3769 First the pre-order-traversal byte offset is positioned to the
3770 item just after the bounded mode item that was just consumed.
3771 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003772 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3773
Laurence Lundblade02625d42020-06-25 14:41:41 -07003774 /*
3775 Next, set the current nesting level to one above the bounded level
3776 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003777
Laurence Lundblade02625d42020-06-25 14:41:41 -07003778 DecodeNesting_CheckBoundedType() is always called before this and
3779 makes sure pCurrentBounded is valid.
3780 */
3781 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3782
3783 /*
3784 This does the complex work of leveling up the pre-order traversal
3785 when the end of a map or array or another bounded level is
3786 reached. It may do nothing, or ascend all the way to the top
3787 level.
3788 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003789 uErr = QCBORDecode_Private_NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003790 if(uErr != QCBOR_SUCCESS) {
3791 goto Done;
3792 }
3793
Laurence Lundblade02625d42020-06-25 14:41:41 -07003794 /*
3795 This makes the next highest bounded level the current bounded
3796 level. If there is no next highest level, then no bounded mode is
3797 in effect.
3798 */
3799 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003800
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003801 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003802
3803Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003804 return uErr;
3805}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003806
Laurence Lundblade02625d42020-06-25 14:41:41 -07003807
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003808// Semi-private function
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003809void
3810QCBORDecode_Private_ExitBoundedMapOrArray(QCBORDecodeContext *pMe,
3811 const uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003812{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003813 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003814 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003815 return;
3816 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003817
Laurence Lundblade02625d42020-06-25 14:41:41 -07003818 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003819
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003820 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003821 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003822 goto Done;
3823 }
3824
Laurence Lundblade02625d42020-06-25 14:41:41 -07003825 /*
3826 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003827 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003828 from previous map search, then do a dummy search.
3829 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003830 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003831 QCBORItem Dummy;
3832 Dummy.uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003833 uErr = QCBORDecode_Private_MapSearch(pMe, &Dummy, NULL, NULL, NULL);
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003834 if(uErr != QCBOR_SUCCESS) {
3835 goto Done;
3836 }
3837 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003838
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003839 uErr = QCBORDecode_Private_ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003840
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003841Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003842 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003843}
3844
3845
Laurence Lundblade1341c592020-04-11 14:19:05 -07003846
Laurence Lundblade37286c02022-09-03 10:05:02 -07003847static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003848QCBORDecode_Private_EnterBstrWrapped(QCBORDecodeContext *pMe,
3849 const QCBORItem *pItem,
3850 const uint8_t uTagRequirement,
3851 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003852{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003853 if(pBstr) {
3854 *pBstr = NULLUsefulBufC;
3855 }
3856
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003857 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003858 /* Already in error state; do nothing. */
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003859 return pMe->uLastError;
3860 }
3861
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003862 QCBORError uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003863
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003864 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003865 {
3866 uTagRequirement,
3867 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3868 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3869 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003870
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003871 uError = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003872 if(uError != QCBOR_SUCCESS) {
3873 goto Done;
3874 }
3875
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003876 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003877 /* Reverse the decrement done by GetNext() for the bstr so the
3878 * increment in QCBORDecode_NestLevelAscender() called by
3879 * ExitBoundedLevel() will work right.
3880 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003881 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003882 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003883
3884 if(pBstr) {
3885 *pBstr = pItem->val.string;
3886 }
3887
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003888 /* This saves the current length of the UsefulInputBuf and then
3889 * narrows the UsefulInputBuf to start and length of the wrapped
3890 * CBOR that is being entered.
3891 *
3892 * Most of these calls are simple inline accessors so this doesn't
3893 * amount to much code.
3894 */
3895
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003896 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003897 /* This check makes the cast of uPreviousLength to uint32_t below safe. */
3898 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003899 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003900 goto Done;
3901 }
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003902
3903 const size_t uStartOfBstr = UsefulInputBuf_PointerToOffset(&(pMe->InBuf),
3904 pItem->val.string.ptr);
3905 /* This check makes the cast of uStartOfBstr to uint32_t below safe. */
3906 if(uStartOfBstr == SIZE_MAX || uStartOfBstr > QCBOR_MAX_DECODE_INPUT_SIZE) {
3907 /* This should never happen because pItem->val.string.ptr should
3908 * always be valid since it was just returned.
3909 */
3910 uError = QCBOR_ERR_INPUT_TOO_LARGE;
3911 goto Done;
3912 }
3913
3914 const size_t uEndOfBstr = uStartOfBstr + pItem->val.string.len;
3915
3916 UsefulInputBuf_Seek(&(pMe->InBuf), uStartOfBstr);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003917 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003918
Laurence Lundblade02625d42020-06-25 14:41:41 -07003919 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003920 (uint32_t)uPreviousLength,
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003921 (uint32_t)uStartOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003922Done:
3923 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003924}
3925
3926
Laurence Lundblade02625d42020-06-25 14:41:41 -07003927/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003928 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07003929 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003930void
3931QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
3932 const uint8_t uTagRequirement,
3933 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003934{
3935 if(pMe->uLastError != QCBOR_SUCCESS) {
3936 // Already in error state; do nothing.
3937 return;
3938 }
3939
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003940 /* Get the data item that is the byte string being entered */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003941 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003942 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3943 if(pMe->uLastError != QCBOR_SUCCESS) {
3944 return;
3945 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003946
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003947 pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
3948 &Item,
3949 uTagRequirement,
3950 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003951}
3952
3953
Laurence Lundblade02625d42020-06-25 14:41:41 -07003954/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003955 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07003956 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003957void
3958QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
3959 const int64_t nLabel,
3960 const uint8_t uTagRequirement,
3961 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003962{
3963 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003964 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003965
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003966 pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
3967 &Item,
3968 uTagRequirement,
3969 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003970}
3971
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003972
Laurence Lundblade02625d42020-06-25 14:41:41 -07003973/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003974 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07003975 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003976void
3977QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
3978 const char *szLabel,
3979 const uint8_t uTagRequirement,
3980 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003981{
3982 QCBORItem Item;
3983 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3984
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003985 pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
3986 &Item,
3987 uTagRequirement,
3988 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003989}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003990
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003991
Laurence Lundblade02625d42020-06-25 14:41:41 -07003992/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003993 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade02625d42020-06-25 14:41:41 -07003994 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07003995void
3996QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003997{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003998 if(pMe->uLastError != QCBOR_SUCCESS) {
3999 // Already in error state; do nothing.
4000 return;
4001 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004002
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07004003 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07004004 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07004005 return;
4006 }
4007
Laurence Lundbladecf41c522021-02-20 10:19:07 -07004008 const uint32_t uEndOfBstr = (uint32_t)UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
4009
Laurence Lundblade02625d42020-06-25 14:41:41 -07004010 /*
4011 Reset the length of the UsefulInputBuf to what it was before
4012 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004013 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07004014 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004015 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07004016
4017
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004018 QCBORError uErr = QCBORDecode_Private_ExitBoundedLevel(pMe, uEndOfBstr);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07004019 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07004020}
4021
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004022
Laurence Lundbladee6430642020-03-14 21:15:44 -07004023
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07004024
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004025static void
4026QCBORDecode_Private_ProcessBool(QCBORDecodeContext *pMe,
4027 const QCBORItem *pItem,
4028 bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004029{
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004030 if(pMe->uLastError != QCBOR_SUCCESS) {
4031 /* Already in error state, do nothing */
4032 return;
4033 }
4034
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004035 switch(pItem->uDataType) {
4036 case QCBOR_TYPE_TRUE:
4037 *pBool = true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004038 break;
4039
4040 case QCBOR_TYPE_FALSE:
4041 *pBool = false;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004042 break;
4043
4044 default:
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004045 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004046 break;
4047 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004048 QCBORDecode_Private_CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004049}
Laurence Lundbladee6430642020-03-14 21:15:44 -07004050
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004051
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004052/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004053 * Public function, see header qcbor/qcbor_decode.h file
4054 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004055void
4056QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004057{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004058 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004059 /* Already in error state, do nothing */
Laurence Lundbladee6430642020-03-14 21:15:44 -07004060 return;
4061 }
4062
Laurence Lundbladec4537442020-04-14 18:53:22 -07004063 QCBORItem Item;
4064
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004065 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4066
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004067 QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004068}
4069
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004070
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004071/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004072 * Public function, see header qcbor/qcbor_decode.h file
4073 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004074void
4075QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe,
4076 const int64_t nLabel,
4077 bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004078{
4079 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004080 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004081
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004082 QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004083}
4084
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004085
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004086/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004087 * Public function, see header qcbor/qcbor_decode.h file
4088 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004089void
4090QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe,
4091 const char *szLabel,
4092 bool *pValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004093{
4094 QCBORItem Item;
4095 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4096
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004097 QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004098}
4099
4100
4101
Laurence Lundbladec7114722020-08-13 05:11:40 -07004102
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004103static void
4104QCBORDecode_Private_ProcessEpochDate(QCBORDecodeContext *pMe,
4105 QCBORItem *pItem,
4106 const uint8_t uTagRequirement,
4107 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07004108{
4109 if(pMe->uLastError != QCBOR_SUCCESS) {
4110 // Already in error state, do nothing
4111 return;
4112 }
4113
4114 QCBORError uErr;
4115
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004116 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladec7114722020-08-13 05:11:40 -07004117 {
4118 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004119 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4120 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07004121 };
4122
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004123 uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004124 if(uErr != QCBOR_SUCCESS) {
4125 goto Done;
4126 }
4127
4128 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004129 uErr = QCBOR_Private_DecodeDateEpoch(pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004130 if(uErr != QCBOR_SUCCESS) {
4131 goto Done;
4132 }
4133 }
4134
Laurence Lundblade9b334962020-08-27 10:55:53 -07004135 // Save the tags in the last item's tags in the decode context
4136 // for QCBORDecode_GetNthTagOfLast()
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004137 QCBORDecode_Private_CopyTags(pMe, pItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07004138
Laurence Lundbladec7114722020-08-13 05:11:40 -07004139 *pnTime = pItem->val.epochDate.nSeconds;
4140
4141Done:
4142 pMe->uLastError = (uint8_t)uErr;
4143}
4144
4145
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004146void
4147QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
4148 uint8_t uTagRequirement,
4149 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07004150{
4151 if(pMe->uLastError != QCBOR_SUCCESS) {
4152 // Already in error state, do nothing
4153 return;
4154 }
4155
4156 QCBORItem Item;
4157 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4158
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004159 QCBORDecode_Private_ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004160}
4161
4162
4163void
4164QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
4165 int64_t nLabel,
4166 uint8_t uTagRequirement,
4167 int64_t *pnTime)
4168{
4169 QCBORItem Item;
4170 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004171 QCBORDecode_Private_ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004172}
4173
4174
4175void
4176QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
4177 const char *szLabel,
4178 uint8_t uTagRequirement,
4179 int64_t *pnTime)
4180{
4181 QCBORItem Item;
4182 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004183 QCBORDecode_Private_ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004184}
4185
4186
4187
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004188/*
4189 * Common processing for the RFC 8943 day-count tag. Mostly
4190 * make sure the tag content is correct and copy forward any
4191 * further other tag numbers.
4192 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004193static void
4194QCBORDecode_Private_ProcessEpochDays(QCBORDecodeContext *pMe,
4195 QCBORItem *pItem,
4196 uint8_t uTagRequirement,
4197 int64_t *pnDays)
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004198{
4199 if(pMe->uLastError != QCBOR_SUCCESS) {
4200 /* Already in error state, do nothing */
4201 return;
4202 }
4203
4204 QCBORError uErr;
4205
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004206 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004207 {
4208 uTagRequirement,
4209 {QCBOR_TYPE_DAYS_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4210 {QCBOR_TYPE_INT64, QCBOR_TYPE_UINT64, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4211 };
4212
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004213 uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004214 if(uErr != QCBOR_SUCCESS) {
4215 goto Done;
4216 }
4217
4218 if(pItem->uDataType != QCBOR_TYPE_DAYS_EPOCH) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004219 uErr = QCBOR_Private_DecodeDaysEpoch(pItem);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004220 if(uErr != QCBOR_SUCCESS) {
4221 goto Done;
4222 }
4223 }
4224
4225 /* Save the tags in the last item's tags in the decode context
4226 * for QCBORDecode_GetNthTagOfLast()
4227 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004228 QCBORDecode_Private_CopyTags(pMe, pItem);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004229
4230 *pnDays = pItem->val.epochDays;
4231
4232Done:
4233 pMe->uLastError = (uint8_t)uErr;
4234}
4235
4236
4237/*
4238 * Public function, see header qcbor/qcbor_decode.h
4239 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004240void
4241QCBORDecode_GetEpochDays(QCBORDecodeContext *pMe,
4242 uint8_t uTagRequirement,
4243 int64_t *pnDays)
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004244{
4245 if(pMe->uLastError != QCBOR_SUCCESS) {
4246 /* Already in error state, do nothing */
4247 return;
4248 }
4249
4250 QCBORItem Item;
4251 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4252
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004253 QCBORDecode_Private_ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004254}
4255
4256
4257/*
4258 * Public function, see header qcbor/qcbor_decode.h
4259 */
4260void
4261QCBORDecode_GetEpochDaysInMapN(QCBORDecodeContext *pMe,
4262 int64_t nLabel,
4263 uint8_t uTagRequirement,
4264 int64_t *pnDays)
4265{
4266 QCBORItem Item;
4267 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004268 QCBORDecode_Private_ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004269}
4270
4271
4272/*
4273 * Public function, see header qcbor/qcbor_decode.h
4274 */
4275void
4276QCBORDecode_GetEpochDaysInMapSZ(QCBORDecodeContext *pMe,
4277 const char *szLabel,
4278 uint8_t uTagRequirement,
4279 int64_t *pnDays)
4280{
4281 QCBORItem Item;
4282 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004283 QCBORDecode_Private_ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004284}
4285
4286
4287
Laurence Lundblade37286c02022-09-03 10:05:02 -07004288/*
4289 * @brief Get a string that matches the type/tag specification.
4290 */
4291void
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004292QCBORDecode_Private_GetTaggedString(QCBORDecodeContext *pMe,
4293 const QCBOR_Private_TagSpec TagSpec,
4294 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004295{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004296 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade37286c02022-09-03 10:05:02 -07004297 /* Already in error state, do nothing */
Laurence Lundbladec4537442020-04-14 18:53:22 -07004298 return;
4299 }
4300
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004301 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004302 QCBORItem Item;
4303
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004304 uError = QCBORDecode_GetNext(pMe, &Item);
4305 if(uError != QCBOR_SUCCESS) {
4306 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004307 return;
4308 }
4309
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004310 pMe->uLastError = (uint8_t)QCBOR_Private_CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004311
4312 if(pMe->uLastError == QCBOR_SUCCESS) {
4313 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07004314 } else {
4315 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004316 }
4317}
4318
Laurence Lundbladec4537442020-04-14 18:53:22 -07004319
4320
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004321
Laurence Lundblade37286c02022-09-03 10:05:02 -07004322static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004323QCBOR_Private_ProcessBigNum(const uint8_t uTagRequirement,
4324 const QCBORItem *pItem,
4325 UsefulBufC *pValue,
4326 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004327{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004328 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004329 {
4330 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004331 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4332 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004333 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004334
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004335 QCBORError uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004336 if(uErr != QCBOR_SUCCESS) {
4337 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004338 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004339
4340 *pValue = pItem->val.string;
4341
4342 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
4343 *pbIsNegative = false;
4344 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
4345 *pbIsNegative = true;
4346 }
4347
4348 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004349}
4350
4351
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004352/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004353 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004354 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004355void
4356QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
4357 const uint8_t uTagRequirement,
4358 UsefulBufC *pValue,
4359 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004360{
4361 if(pMe->uLastError != QCBOR_SUCCESS) {
4362 // Already in error state, do nothing
4363 return;
4364 }
4365
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004366 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004367 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4368 if(uError != QCBOR_SUCCESS) {
4369 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004370 return;
4371 }
4372
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004373 pMe->uLastError = (uint8_t)QCBOR_Private_ProcessBigNum(uTagRequirement,
4374 &Item,
4375 pValue,
4376 pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004377}
4378
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004379
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004380/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004381 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004382*/
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004383void
4384QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
4385 const int64_t nLabel,
4386 const uint8_t uTagRequirement,
4387 UsefulBufC *pValue,
4388 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004389{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004390 QCBORItem Item;
4391 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004392 if(pMe->uLastError != QCBOR_SUCCESS) {
4393 return;
4394 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004395
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004396 pMe->uLastError = (uint8_t)QCBOR_Private_ProcessBigNum(uTagRequirement,
4397 &Item,
4398 pValue,
4399 pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004400}
4401
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004402
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004403/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004404 * Public function, see header qcbor/qcbor_decode.h
4405 */
4406void
4407QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
4408 const char *szLabel,
4409 const uint8_t uTagRequirement,
4410 UsefulBufC *pValue,
4411 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004412{
4413 QCBORItem Item;
4414 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004415 if(pMe->uLastError != QCBOR_SUCCESS) {
4416 return;
4417 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004418
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004419 pMe->uLastError = (uint8_t)QCBOR_Private_ProcessBigNum(uTagRequirement,
4420 &Item,
4421 pValue,
4422 pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004423}
4424
4425
4426
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004427
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004428// Semi private
Laurence Lundblade37286c02022-09-03 10:05:02 -07004429QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004430QCBORDecode_Private_GetMIME(const uint8_t uTagRequirement,
Laurence Lundblade37286c02022-09-03 10:05:02 -07004431 const QCBORItem *pItem,
4432 UsefulBufC *pMessage,
4433 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004434{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004435 const QCBOR_Private_TagSpec TagSpecText =
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004436 {
4437 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004438 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4439 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004440 };
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004441 const QCBOR_Private_TagSpec TagSpecBinary =
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004442 {
4443 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004444 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4445 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004446 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004447
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004448 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07004449
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004450 if(QCBOR_Private_CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004451 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004452 if(pbIsTag257 != NULL) {
4453 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004454 }
4455 uReturn = QCBOR_SUCCESS;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004456 } else if(QCBOR_Private_CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004457 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004458 if(pbIsTag257 != NULL) {
4459 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004460 }
4461 uReturn = QCBOR_SUCCESS;
4462
4463 } else {
4464 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
4465 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07004466
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004467 return uReturn;
4468}
4469
Laurence Lundblade93d89472020-10-03 22:30:50 -07004470// Improvement: add methods for wrapped CBOR, a simple alternate
4471// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004472
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004473
4474
4475
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004476#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07004477
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004478typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004479
4480
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004481/**
4482 * @brief Base 10 exponentiate a mantissa and exponent into an unsigned 64-bit integer.
4483 *
4484 * @param[in] uMantissa The unsigned integer mantissa.
4485 * @param[in] nExponent The signed integer exponent.
4486 * @param[out] puResult Place to return the unsigned integer result.
4487 *
4488 * This computes: mantissa * 10 ^^ exponent as for a decimal fraction. The output is a 64-bit
4489 * unsigned integer.
4490 *
4491 * There are many inputs for which the result will not fit in the
4492 * 64-bit integer and \ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will
4493 * be returned.
4494 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004495static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004496QCBOR_Private_Exponentitate10(const uint64_t uMantissa,
4497 int64_t nExponent,
4498 uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004499{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004500 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004501
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004502 if(uResult != 0) {
4503 /* This loop will run a maximum of 19 times because
4504 * UINT64_MAX < 10 ^^ 19. More than that will cause
4505 * exit with the overflow error
4506 */
4507 for(; nExponent > 0; nExponent--) {
4508 if(uResult > UINT64_MAX / 10) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004509 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004510 }
4511 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004512 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004513
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004514 for(; nExponent < 0; nExponent++) {
4515 uResult = uResult / 10;
4516 if(uResult == 0) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004517 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004518 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004519 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004520 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004521 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07004522
4523 *puResult = uResult;
4524
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004525 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004526}
4527
4528
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004529/**
4530 * @brief Base 2 exponentiate a mantissa and exponent into an unsigned 64-bit integer.
4531 *
4532 * @param[in] uMantissa The unsigned integer mantissa.
4533 * @param[in] nExponent The signed integer exponent.
4534 * @param[out] puResult Place to return the unsigned integer result.
4535 *
4536 * This computes: mantissa * 2 ^^ exponent as for a big float. The
4537 * output is a 64-bit unsigned integer.
4538 *
4539 * There are many inputs for which the result will not fit in the
4540 * 64-bit integer and \ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will
4541 * be returned.
4542 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004543static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004544QCBOR_Private_Exponentitate2(const uint64_t uMantissa,
4545 int64_t nExponent,
4546 uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004547{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004548 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004549
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004550 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004551
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004552 /* This loop will run a maximum of 64 times because INT64_MAX <
4553 * 2^31. More than that will cause exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07004554 */
4555 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004556 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004557 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004558 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004559 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004560 nExponent--;
4561 }
4562
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004563 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004564 if(uResult == 0) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004565 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004566 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004567 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004568 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004569 }
4570
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004571 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004572
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004573 return QCBOR_SUCCESS;
4574}
4575
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004576
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004577/**
4578 * @brief Exponentiate a signed mantissa and signed exponent to produce a signed result.
4579 *
4580 * @param[in] nMantissa Signed integer mantissa.
4581 * @param[in] nExponent Signed integer exponent.
4582 * @param[out] pnResult Place to put the signed integer result.
4583 * @param[in] pfExp Exponentiation function.
4584 *
4585 * @returns Error code
4586 *
4587 * \c pfExp performs exponentiation on and unsigned mantissa and
4588 * produces an unsigned result. This converts the mantissa from signed
4589 * and converts the result to signed. The exponentiation function is
4590 * either for base 2 or base 10 (and could be other if needed).
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004591 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004592static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004593QCBOR_Private_ExponentiateNN(const int64_t nMantissa,
4594 const int64_t nExponent,
4595 int64_t *pnResult,
4596 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004597{
4598 uint64_t uResult;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004599 uint64_t uMantissa;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004600
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004601 /* Take the absolute value and put it into an unsigned. */
4602 if(nMantissa >= 0) {
4603 /* Positive case is straightforward */
4604 uMantissa = (uint64_t)nMantissa;
4605 } else if(nMantissa != INT64_MIN) {
4606 /* The common negative case. See next. */
4607 uMantissa = (uint64_t)-nMantissa;
4608 } else {
4609 /* int64_t and uint64_t are always two's complement per the
4610 * C standard (and since QCBOR uses these it only works with
4611 * two's complement, which is pretty much universal these
4612 * days). The range of a negative two's complement integer is
4613 * one more that than a positive, so the simple code above might
4614 * not work all the time because you can't simply negate the
4615 * value INT64_MIN because it can't be represented in an
4616 * int64_t. -INT64_MIN can however be represented in a
4617 * uint64_t. Some compilers seem to recognize this case for the
4618 * above code and put the correct value in uMantissa, however
4619 * they are not required to do this by the C standard. This next
4620 * line does however work for all compilers.
4621 *
4622 * This does assume two's complement where -INT64_MIN ==
4623 * INT64_MAX + 1 (which wouldn't be true for one's complement or
4624 * sign and magnitude (but we know we're using two's complement
4625 * because int64_t requires it)).
4626 *
4627 * See these, particularly the detailed commentary:
4628 * https://stackoverflow.com/questions/54915742/does-c99-mandate-a-int64-t-type-be-available-always
4629 * https://stackoverflow.com/questions/37301078/is-negating-int-min-undefined-behaviour
4630 */
4631 uMantissa = (uint64_t)INT64_MAX+1;
4632 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004633
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004634 /* Call the exponentiator passed for either base 2 or base 10.
4635 * Here is where most of the overflow errors are caught. */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004636 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
4637 if(uReturn) {
4638 return uReturn;
4639 }
4640
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004641 /* Convert back to the sign of the original mantissa */
4642 if(nMantissa >= 0) {
4643 if(uResult > INT64_MAX) {
4644 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4645 }
4646 *pnResult = (int64_t)uResult;
4647 } else {
4648 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
4649 * of INT64_MIN. This assumes two's compliment representation
4650 * where INT64_MIN is one increment farther from 0 than
4651 * INT64_MAX. Trying to write -INT64_MIN doesn't work to get
4652 * this because the compiler makes it an int64_t which can't
4653 * represent -INT64_MIN. Also see above.
4654 */
4655 if(uResult > (uint64_t)INT64_MAX+1) {
4656 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4657 }
4658 *pnResult = -(int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004659 }
4660
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004661 return QCBOR_SUCCESS;
4662}
4663
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004664
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004665/**
4666 * @brief Exponentiate an unsigned mantissa and signed exponent to produce an unsigned result.
4667 *
4668 * @param[in] nMantissa Signed integer mantissa.
4669 * @param[in] nExponent Signed integer exponent.
4670 * @param[out] puResult Place to put the signed integer result.
4671 * @param[in] pfExp Exponentiation function.
4672 *
4673 * @returns Error code
4674 *
4675 * \c pfExp performs exponentiation on and unsigned mantissa and
4676 * produces an unsigned result. This errors out if the mantissa
4677 * is negative because the output is unsigned.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004678 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004679static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004680QCBOR_Private_ExponentitateNU(const int64_t nMantissa,
4681 const int64_t nExponent,
4682 uint64_t *puResult,
4683 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004684{
4685 if(nMantissa < 0) {
4686 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4687 }
4688
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004689 /* Cast to unsigned is OK because of check for negative.
4690 * Cast to unsigned is OK because UINT64_MAX > INT64_MAX.
4691 * Exponentiation is straight forward
4692 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004693 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
4694}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004695
4696
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004697/**
4698 * @brief Exponentiate an usnigned mantissa and unsigned exponent to produce an unsigned result.
4699 *
4700 * @param[in] uMantissa Unsigned integer mantissa.
4701 * @param[in] nExponent Unsigned integer exponent.
4702 * @param[out] puResult Place to put the unsigned integer result.
4703 * @param[in] pfExp Exponentiation function.
4704 *
4705 * @returns Error code
4706 *
4707 * \c pfExp performs exponentiation on and unsigned mantissa and
4708 * produces an unsigned result so this is just a wrapper that does
4709 * nothing (and is likely inlined).
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004710 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004711static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004712QCBOR_Private_ExponentitateUU(const uint64_t uMantissa,
4713 const int64_t nExponent,
4714 uint64_t *puResult,
4715 fExponentiator pfExp)
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004716{
4717 return (*pfExp)(uMantissa, nExponent, puResult);
4718}
4719
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004720#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004721
4722
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004723
4724
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004725/**
4726 * @brief Convert a CBOR big number to a uint64_t.
4727 *
4728 * @param[in] BigNum Bytes of the big number to convert.
4729 * @param[in] uMax Maximum value allowed for the result.
4730 * @param[out] pResult Place to put the unsigned integer result.
4731 *
4732 * @returns Error code
4733 *
4734 * Many values will overflow because a big num can represent a much
4735 * larger range than uint64_t.
4736 */
4737static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004738QCBOR_Private_ConvertBigNumToUnsigned(const UsefulBufC BigNum,
4739 const uint64_t uMax,
4740 uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004741{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004742 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004743
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004744 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004745 const uint8_t *pByte = BigNum.ptr;
4746 size_t uLen = BigNum.len;
4747 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07004748 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004749 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004750 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07004751 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004752 }
4753
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004754 *pResult = uResult;
4755 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004756}
4757
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004758
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004759/**
4760 * @brief Convert a CBOR postive big number to a uint64_t.
4761 *
4762 * @param[in] BigNum Bytes of the big number to convert.
4763 * @param[out] pResult Place to put the unsigned integer result.
4764 *
4765 * @returns Error code
4766 *
4767 * Many values will overflow because a big num can represent a much
4768 * larger range than uint64_t.
4769 */
4770static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004771QCBOR_Private_ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum,
4772 uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004773{
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004774 return QCBOR_Private_ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004775}
4776
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004777
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004778/**
4779 * @brief Convert a CBOR positive big number to an int64_t.
4780 *
4781 * @param[in] BigNum Bytes of the big number to convert.
4782 * @param[out] pResult Place to put the signed integer result.
4783 *
4784 * @returns Error code
4785 *
4786 * Many values will overflow because a big num can represent a much
4787 * larger range than int64_t.
4788 */
4789static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004790QCBOR_Private_ConvertPositiveBigNumToSigned(const UsefulBufC BigNum,
4791 int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004792{
4793 uint64_t uResult;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004794 QCBORError uError = QCBOR_Private_ConvertBigNumToUnsigned(BigNum,
4795 INT64_MAX,
4796 &uResult);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004797 if(uError) {
4798 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004799 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004800 /* Cast is safe because ConvertBigNumToUnsigned limits to INT64_MAX */
Laurence Lundbladee6430642020-03-14 21:15:44 -07004801 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004802 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004803}
4804
4805
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004806/**
4807 * @brief Convert a CBOR negative big number to an int64_t.
4808 *
4809 * @param[in] BigNum Bytes of the big number to convert.
4810 * @param[out] pnResult Place to put the signed integer result.
4811 *
4812 * @returns Error code
4813 *
4814 * Many values will overflow because a big num can represent a much
4815 * larger range than int64_t.
4816 */
4817static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004818QCBOR_Private_ConvertNegativeBigNumToSigned(const UsefulBufC BigNum,
4819 int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004820{
4821 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004822 /* The negative integer furthest from zero for a C int64_t is
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004823 * INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
4824 * negative number in CBOR is computed as -n - 1 where n is the
4825 * encoded integer, where n is what is in the variable BigNum. When
4826 * converting BigNum to a uint64_t, the maximum value is thus
4827 * INT64_MAX, so that when it -n - 1 is applied to it the result
4828 * will never be further from 0 than INT64_MIN.
4829 *
4830 * -n - 1 <= INT64_MIN.
4831 * -n - 1 <= -INT64_MAX - 1
4832 * n <= INT64_MAX.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004833 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004834 QCBORError uError = QCBOR_Private_ConvertBigNumToUnsigned(BigNum,
4835 INT64_MAX,
4836 &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004837 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004838 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004839 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004840
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004841 /* Now apply -n - 1. The cast is safe because
4842 * ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
4843 * is the largest positive integer that an int64_t can
4844 * represent. */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004845 *pnResult = -(int64_t)uResult - 1;
4846
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004847 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004848}
4849
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004850
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004851
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004852
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004853
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004854/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004855Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004856
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004857\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004858
Laurence Lundblade93d89472020-10-03 22:30:50 -07004859\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4860 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004861
4862\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4863
Laurence Lundblade93d89472020-10-03 22:30:50 -07004864\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4865 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004866*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07004867static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004868QCBOR_Private_ConvertInt64(const QCBORItem *pItem,
4869 const uint32_t uConvertTypes,
4870 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004871{
4872 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004873 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004874 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004875#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004876 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004877 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
4878 http://www.cplusplus.com/reference/cmath/llround/
4879 */
4880 // Not interested in FE_INEXACT
4881 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004882 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4883 *pnValue = llround(pItem->val.dfnum);
4884 } else {
4885 *pnValue = lroundf(pItem->val.fnum);
4886 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004887 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4888 // llround() shouldn't result in divide by zero, but catch
4889 // it here in case it unexpectedly does. Don't try to
4890 // distinguish between the various exceptions because it seems
4891 // they vary by CPU, compiler and OS.
4892 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004893 }
4894 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004895 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004896 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004897#else
4898 return QCBOR_ERR_HW_FLOAT_DISABLED;
4899#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004900 break;
4901
4902 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004903 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004904 *pnValue = pItem->val.int64;
4905 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004906 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004907 }
4908 break;
4909
4910 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004911 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004912 if(pItem->val.uint64 < INT64_MAX) {
4913 *pnValue = pItem->val.int64;
4914 } else {
4915 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4916 }
4917 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004918 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004919 }
4920 break;
4921
Laurence Lundblade2d493002024-02-01 11:09:17 -07004922 case QCBOR_TYPE_65BIT_NEG_INT:
4923 /* This type occurs if the value won't fit into int64_t
4924 * so this is always an error. */
4925 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4926 break;
4927
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004928 default:
4929 return QCBOR_ERR_UNEXPECTED_TYPE;
4930 }
4931 return QCBOR_SUCCESS;
4932}
4933
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004934
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004935void
4936QCBORDecode_Private_GetInt64Convert(QCBORDecodeContext *pMe,
4937 uint32_t uConvertTypes,
4938 int64_t *pnValue,
4939 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004940{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004941 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004942 return;
4943 }
4944
Laurence Lundbladee6430642020-03-14 21:15:44 -07004945 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004946 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4947 if(uError) {
4948 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004949 return;
4950 }
4951
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004952 if(pItem) {
4953 *pItem = Item;
4954 }
4955
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004956 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(&Item,
4957 uConvertTypes,
4958 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004959}
4960
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004961
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004962void
4963QCBORDecode_Private_GetInt64ConvertInMapN(QCBORDecodeContext *pMe,
4964 int64_t nLabel,
4965 uint32_t uConvertTypes,
4966 int64_t *pnValue,
4967 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004968{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004969 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004970 if(pMe->uLastError != QCBOR_SUCCESS) {
4971 return;
4972 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004973
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004974 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
4975 uConvertTypes,
4976 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004977}
4978
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004979
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004980void
4981QCBORDecode_Private_GetInt64ConvertInMapSZ(QCBORDecodeContext *pMe,
4982 const char * szLabel,
4983 uint32_t uConvertTypes,
4984 int64_t *pnValue,
4985 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004986{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004987 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004988 if(pMe->uLastError != QCBOR_SUCCESS) {
4989 return;
4990 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004991
Laurence Lundblade8e36f812024-01-26 10:59:29 -07004992 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
4993 uConvertTypes,
4994 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004995}
4996
4997
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004998/*
4999 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005000
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005001 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005002
Laurence Lundblade93d89472020-10-03 22:30:50 -07005003 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
5004 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005005
5006 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
5007
Laurence Lundblade93d89472020-10-03 22:30:50 -07005008 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
5009 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005010 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07005011static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005012QCBOR_Private_Int64ConvertAll(const QCBORItem *pItem,
5013 const uint32_t uConvertTypes,
5014 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005015{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005016 switch(pItem->uDataType) {
5017
5018 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005019 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005020 return QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005021 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005022 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005023 }
5024 break;
5025
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005026 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005027 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005028 return QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005029 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005030 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005031 }
5032 break;
5033
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005034#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005035 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005036 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005037 return QCBOR_Private_ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005038 pItem->val.expAndMantissa.nExponent,
5039 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005040 &QCBOR_Private_Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005041 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005042 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005043 }
5044 break;
5045
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005046 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005047 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005048 return QCBOR_Private_ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005049 pItem->val.expAndMantissa.nExponent,
5050 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005051 QCBOR_Private_Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005052 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005053 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005054 }
5055 break;
5056
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005057 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005058 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005059 int64_t nMantissa;
5060 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005061 uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005062 if(uErr) {
5063 return uErr;
5064 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005065 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005066 pItem->val.expAndMantissa.nExponent,
5067 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005068 QCBOR_Private_Exponentitate10);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005069 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005070 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005071 }
5072 break;
5073
5074 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005075 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005076 int64_t nMantissa;
5077 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005078 uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005079 if(uErr) {
5080 return uErr;
5081 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005082 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005083 pItem->val.expAndMantissa.nExponent,
5084 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005085 QCBOR_Private_Exponentitate10);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005086 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005087 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005088 }
5089 break;
5090
5091 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005092 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005093 int64_t nMantissa;
5094 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005095 uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005096 if(uErr) {
5097 return uErr;
5098 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005099 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005100 pItem->val.expAndMantissa.nExponent,
5101 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005102 QCBOR_Private_Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005103 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005104 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005105 }
5106 break;
5107
5108 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005109 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005110 int64_t nMantissa;
5111 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005112 uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005113 if(uErr) {
5114 return uErr;
5115 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005116 return QCBOR_Private_ExponentiateNN(nMantissa,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005117 pItem->val.expAndMantissa.nExponent,
5118 pnValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005119 QCBOR_Private_Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005120 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005121 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005122 }
5123 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005124#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005125
Laurence Lundbladee6430642020-03-14 21:15:44 -07005126
Laurence Lundbladec4537442020-04-14 18:53:22 -07005127 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005128 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005129}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005130
5131
Laurence Lundbladec4537442020-04-14 18:53:22 -07005132/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005133 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005134 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005135void
5136QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe,
5137 const uint32_t uConvertTypes,
5138 int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07005139{
5140 QCBORItem Item;
5141
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005142 QCBORDecode_Private_GetInt64Convert(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07005143
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005144 if(pMe->uLastError == QCBOR_SUCCESS) {
5145 // The above conversion succeeded
5146 return;
5147 }
5148
Laurence Lundbladef6c86662020-05-12 02:08:00 -07005149 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005150 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07005151 return;
5152 }
5153
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005154 pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
5155 uConvertTypes,
5156 pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005157}
5158
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005159
5160/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005161 * Public function, see header qcbor/qcbor_decode.h file
5162 */
5163void
5164QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
5165 const int64_t nLabel,
5166 const uint32_t uConvertTypes,
5167 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005168{
5169 QCBORItem Item;
5170
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005171 QCBORDecode_Private_GetInt64ConvertInMapN(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07005172 nLabel,
5173 uConvertTypes,
5174 pnValue,
5175 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005176
5177 if(pMe->uLastError == QCBOR_SUCCESS) {
5178 // The above conversion succeeded
5179 return;
5180 }
5181
5182 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5183 // The above conversion failed in a way that code below can't correct
5184 return;
5185 }
5186
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005187 pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
5188 uConvertTypes,
5189 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005190}
5191
5192
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005193/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005194 * Public function, see header qcbor/qcbor_decode.h file
5195 */
5196void
5197QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
5198 const char *szLabel,
5199 const uint32_t uConvertTypes,
5200 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005201{
5202 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005203 QCBORDecode_Private_GetInt64ConvertInMapSZ(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07005204 szLabel,
5205 uConvertTypes,
5206 pnValue,
5207 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005208
5209 if(pMe->uLastError == QCBOR_SUCCESS) {
5210 // The above conversion succeeded
5211 return;
5212 }
5213
5214 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5215 // The above conversion failed in a way that code below can't correct
5216 return;
5217 }
5218
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005219 pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
5220 uConvertTypes,
5221 pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005222}
5223
5224
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005225static QCBORError
5226QCBOR_Private_ConvertUInt64(const QCBORItem *pItem,
5227 const uint32_t uConvertTypes,
5228 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005229{
5230 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005231 case QCBOR_TYPE_DOUBLE:
5232 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005233#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005234 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005235 // Can't use llround here because it will not convert values
5236 // greater than INT64_MAX and less than UINT64_MAX that
5237 // need to be converted so it is more complicated.
5238 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
5239 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
5240 if(isnan(pItem->val.dfnum)) {
5241 return QCBOR_ERR_FLOAT_EXCEPTION;
5242 } else if(pItem->val.dfnum < 0) {
5243 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5244 } else {
5245 double dRounded = round(pItem->val.dfnum);
5246 // See discussion in DecodeDateEpoch() for
5247 // explanation of - 0x7ff
5248 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
5249 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5250 }
5251 *puValue = (uint64_t)dRounded;
5252 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005253 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005254 if(isnan(pItem->val.fnum)) {
5255 return QCBOR_ERR_FLOAT_EXCEPTION;
5256 } else if(pItem->val.fnum < 0) {
5257 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5258 } else {
5259 float fRounded = roundf(pItem->val.fnum);
5260 // See discussion in DecodeDateEpoch() for
5261 // explanation of - 0x7ff
5262 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
5263 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5264 }
5265 *puValue = (uint64_t)fRounded;
5266 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005267 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005268 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
5269 // round() and roundf() shouldn't result in exceptions here, but
5270 // catch them to be robust and thorough. Don't try to
5271 // distinguish between the various exceptions because it seems
5272 // they vary by CPU, compiler and OS.
5273 return QCBOR_ERR_FLOAT_EXCEPTION;
5274 }
5275
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005276 } else {
5277 return QCBOR_ERR_UNEXPECTED_TYPE;
5278 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005279#else
5280 return QCBOR_ERR_HW_FLOAT_DISABLED;
5281#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005282 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005283
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005284 case QCBOR_TYPE_INT64:
5285 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
5286 if(pItem->val.int64 >= 0) {
5287 *puValue = (uint64_t)pItem->val.int64;
5288 } else {
5289 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5290 }
5291 } else {
5292 return QCBOR_ERR_UNEXPECTED_TYPE;
5293 }
5294 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005295
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005296 case QCBOR_TYPE_UINT64:
5297 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade2d493002024-02-01 11:09:17 -07005298 *puValue = pItem->val.uint64;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005299 } else {
5300 return QCBOR_ERR_UNEXPECTED_TYPE;
5301 }
5302 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005303
Laurence Lundblade2d493002024-02-01 11:09:17 -07005304 case QCBOR_TYPE_65BIT_NEG_INT:
5305 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5306
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005307 default:
5308 return QCBOR_ERR_UNEXPECTED_TYPE;
5309 }
5310
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005311 return QCBOR_SUCCESS;
5312}
Laurence Lundbladec4537442020-04-14 18:53:22 -07005313
5314
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005315void
5316QCBORDecode_Private_GetUInt64Convert(QCBORDecodeContext *pMe,
5317 const uint32_t uConvertTypes,
5318 uint64_t *puValue,
5319 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07005320{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005321 if(pMe->uLastError != QCBOR_SUCCESS) {
5322 return;
5323 }
5324
Laurence Lundbladec4537442020-04-14 18:53:22 -07005325 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005326
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005327 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5328 if(uError) {
5329 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005330 return;
5331 }
5332
Laurence Lundbladea826c502020-05-10 21:07:00 -07005333 if(pItem) {
5334 *pItem = Item;
5335 }
5336
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005337 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(&Item,
5338 uConvertTypes,
5339 puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07005340}
5341
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005342
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005343void
5344QCBORDecode_Private_GetUInt64ConvertInMapN(QCBORDecodeContext *pMe,
5345 const int64_t nLabel,
5346 const uint32_t uConvertTypes,
5347 uint64_t *puValue,
5348 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005349{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005350 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005351 if(pMe->uLastError != QCBOR_SUCCESS) {
5352 return;
5353 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005354
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005355 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
5356 uConvertTypes,
5357 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005358}
5359
5360
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005361void
5362QCBORDecode_Private_GetUInt64ConvertInMapSZ(QCBORDecodeContext *pMe,
5363 const char *szLabel,
5364 const uint32_t uConvertTypes,
5365 uint64_t *puValue,
5366 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005367{
5368 if(pMe->uLastError != QCBOR_SUCCESS) {
5369 return;
5370 }
5371
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005372 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005373 if(pMe->uLastError != QCBOR_SUCCESS) {
5374 return;
5375 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005376
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005377 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
5378 uConvertTypes,
5379 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005380}
5381
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005382
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005383
Laurence Lundblade93d89472020-10-03 22:30:50 -07005384static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005385QCBOR_Private_UInt64ConvertAll(const QCBORItem *pItem,
5386 const uint32_t uConvertTypes,
5387 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005388{
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08005389 switch(pItem->uDataType) { /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005390
5391 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005392 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005393 return QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005394 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005395 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005396 }
5397 break;
5398
5399 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005400 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005401 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5402 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005403 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005404 }
5405 break;
5406
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005407#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005408
5409 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005410 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005411 return QCBOR_Private_ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005412 pItem->val.expAndMantissa.nExponent,
5413 puValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005414 QCBOR_Private_Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005415 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005416 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005417 }
5418 break;
5419
5420 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005421 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005422 return QCBOR_Private_ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005423 pItem->val.expAndMantissa.nExponent,
5424 puValue,
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005425 QCBOR_Private_Exponentitate2);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005426 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005427 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005428 }
5429 break;
5430
5431 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005432 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005433 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005434 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005435 uErr = QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005436 if(uErr != QCBOR_SUCCESS) {
5437 return uErr;
5438 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005439 return QCBOR_Private_ExponentitateUU(uMantissa,
5440 pItem->val.expAndMantissa.nExponent,
5441 puValue,
5442 QCBOR_Private_Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005443 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005444 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005445 }
5446 break;
5447
5448 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005449 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005450 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5451 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005452 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005453 }
5454 break;
5455
5456 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005457 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005458 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005459 QCBORError uErr;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005460 uErr = QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum,
5461 &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005462 if(uErr != QCBOR_SUCCESS) {
5463 return uErr;
5464 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005465 return QCBOR_Private_ExponentitateUU(uMantissa,
5466 pItem->val.expAndMantissa.nExponent,
5467 puValue,
5468 QCBOR_Private_Exponentitate2);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005469 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005470 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005471 }
5472 break;
5473
5474 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005475 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005476 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5477 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005478 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005479 }
5480 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005481#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005482 default:
5483 return QCBOR_ERR_UNEXPECTED_TYPE;
5484 }
5485}
5486
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005487
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005488/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005489 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005490 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005491void
5492QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe,
5493 const uint32_t uConvertTypes,
5494 uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005495{
5496 QCBORItem Item;
5497
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005498 QCBORDecode_Private_GetUInt64Convert(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005499
Laurence Lundbladef6c86662020-05-12 02:08:00 -07005500 if(pMe->uLastError == QCBOR_SUCCESS) {
5501 // The above conversion succeeded
5502 return;
5503 }
5504
5505 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5506 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07005507 return;
5508 }
5509
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005510 pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
5511 uConvertTypes,
5512 puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005513}
5514
Laurence Lundbladec4537442020-04-14 18:53:22 -07005515
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005516/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005517 * Public function, see header qcbor/qcbor_decode.h file
5518 */
5519void
5520QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
5521 const int64_t nLabel,
5522 const uint32_t uConvertTypes,
5523 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005524{
5525 QCBORItem Item;
5526
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005527 QCBORDecode_Private_GetUInt64ConvertInMapN(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07005528 nLabel,
5529 uConvertTypes,
5530 puValue,
5531 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005532
5533 if(pMe->uLastError == QCBOR_SUCCESS) {
5534 // The above conversion succeeded
5535 return;
5536 }
5537
5538 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5539 // The above conversion failed in a way that code below can't correct
5540 return;
5541 }
5542
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005543 pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
5544 uConvertTypes,
5545 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005546}
5547
5548
5549/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005550 * Public function, see header qcbor/qcbor_decode.h file
5551 */
5552void
5553QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
5554 const char *szLabel,
5555 const uint32_t uConvertTypes,
5556 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005557{
5558 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005559 QCBORDecode_Private_GetUInt64ConvertInMapSZ(pMe,
Laurence Lundblade93d89472020-10-03 22:30:50 -07005560 szLabel,
5561 uConvertTypes,
5562 puValue,
5563 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005564
5565 if(pMe->uLastError == QCBOR_SUCCESS) {
5566 // The above conversion succeeded
5567 return;
5568 }
5569
5570 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5571 // The above conversion failed in a way that code below can't correct
5572 return;
5573 }
5574
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005575 pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
5576 uConvertTypes,
5577 puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005578}
5579
5580
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005581
5582
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02005583#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005584static QCBORError
5585QCBOR_Private_ConvertDouble(const QCBORItem *pItem,
5586 const uint32_t uConvertTypes,
5587 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005588{
5589 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005590 case QCBOR_TYPE_FLOAT:
5591#ifndef QCBOR_DISABLE_FLOAT_HW_USE
5592 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5593 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005594 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005595 *pdValue = (double)pItem->val.fnum;
5596 } else {
5597 return QCBOR_ERR_UNEXPECTED_TYPE;
5598 }
5599 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005600#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005601 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005602#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005603 break;
5604
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005605 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005606 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5607 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005608 *pdValue = pItem->val.dfnum;
5609 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005610 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005611 }
5612 }
5613 break;
5614
5615 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005616#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005617 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005618 // A simple cast seems to do the job with no worry of exceptions.
5619 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005620 *pdValue = (double)pItem->val.int64;
5621
5622 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005623 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005624 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005625#else
5626 return QCBOR_ERR_HW_FLOAT_DISABLED;
5627#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005628 break;
5629
5630 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005631#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005632 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005633 // A simple cast seems to do the job with no worry of exceptions.
5634 // There will be precision loss for some values.
5635 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005636 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005637 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005638 }
5639 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005640#else
5641 return QCBOR_ERR_HW_FLOAT_DISABLED;
5642#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005643
Laurence Lundblade2d493002024-02-01 11:09:17 -07005644 case QCBOR_TYPE_65BIT_NEG_INT:
5645 *pdValue = -(double)pItem->val.uint64 - 1;
5646 break;
5647
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005648 default:
5649 return QCBOR_ERR_UNEXPECTED_TYPE;
5650 }
5651
5652 return QCBOR_SUCCESS;
5653}
5654
5655
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005656void
5657QCBORDecode_Private_GetDoubleConvert(QCBORDecodeContext *pMe,
5658 const uint32_t uConvertTypes,
5659 double *pdValue,
5660 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005661{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005662 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07005663 return;
5664 }
5665
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005666 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005667
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005668 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005669 if(uError) {
5670 pMe->uLastError = (uint8_t)uError;
5671 return;
5672 }
5673
5674 if(pItem) {
5675 *pItem = Item;
5676 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005677
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005678 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(&Item,
5679 uConvertTypes,
5680 pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005681}
Laurence Lundbladec4537442020-04-14 18:53:22 -07005682
Laurence Lundbladec4537442020-04-14 18:53:22 -07005683
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005684void
5685QCBORDecode_Private_GetDoubleConvertInMapN(QCBORDecodeContext *pMe,
5686 const int64_t nLabel,
5687 const uint32_t uConvertTypes,
5688 double *pdValue,
5689 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005690{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005691 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005692 if(pMe->uLastError != QCBOR_SUCCESS) {
5693 return;
5694 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005695
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005696 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
5697 uConvertTypes,
5698 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005699}
5700
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005701
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005702void
5703QCBORDecode_Private_GetDoubleConvertInMapSZ(QCBORDecodeContext *pMe,
5704 const char *szLabel,
5705 const uint32_t uConvertTypes,
5706 double *pdValue,
5707 QCBORItem *pItem)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005708{
5709 if(pMe->uLastError != QCBOR_SUCCESS) {
5710 return;
5711 }
5712
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005713 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005714 if(pMe->uLastError != QCBOR_SUCCESS) {
5715 return;
5716 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005717
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005718 pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
5719 uConvertTypes,
5720 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005721}
5722
5723
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005724#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005725static double
5726QCBOR_Private_ConvertBigNumToDouble(const UsefulBufC BigNum)
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005727{
5728 double dResult;
5729
5730 dResult = 0.0;
5731 const uint8_t *pByte = BigNum.ptr;
5732 size_t uLen = BigNum.len;
5733 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07005734 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005735 while(uLen--) {
5736 dResult = (dResult * 256.0) + (double)*pByte++;
5737 }
5738
5739 return dResult;
5740}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005741#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5742
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005743
Laurence Lundblade93d89472020-10-03 22:30:50 -07005744static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005745QCBOR_Private_DoubleConvertAll(const QCBORItem *pItem,
5746 const uint32_t uConvertTypes,
5747 double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005748{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005749#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005750 /*
Laurence Lundblade16a207a2021-09-18 17:22:46 -07005751 * What Every Computer Scientist Should Know About Floating-Point Arithmetic
5752 * https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
5753 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005754 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005755
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005756#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005757 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005758 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07005759 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005760 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
5761 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
5762 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005763 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005764 }
5765 break;
5766
5767 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005768 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07005769 // Underflow gives 0, overflow gives infinity
5770 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
5771 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005772 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005773 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005774 }
5775 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005776#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005777
5778 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005779 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005780 *pdValue = QCBOR_Private_ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005781 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005782 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005783 }
5784 break;
5785
5786 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005787 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005788 *pdValue = -1-QCBOR_Private_ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005789 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005790 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005791 }
5792 break;
5793
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005794#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005795 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005796 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005797 double dMantissa = QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005798 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5799 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005800 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005801 }
5802 break;
5803
5804 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005805 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005806 double dMantissa = -QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005807 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5808 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005809 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005810 }
5811 break;
5812
5813 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005814 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005815 double dMantissa = QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005816 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5817 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005818 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005819 }
5820 break;
5821
5822 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005823 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005824 double dMantissa = -1-QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005825 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5826 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005827 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005828 }
5829 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005830#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005831
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005832 default:
5833 return QCBOR_ERR_UNEXPECTED_TYPE;
5834 }
5835
5836 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005837
5838#else
5839 (void)pItem;
5840 (void)uConvertTypes;
5841 (void)pdValue;
5842 return QCBOR_ERR_HW_FLOAT_DISABLED;
5843#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5844
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005845}
5846
5847
5848/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005849 *Public function, see header qcbor/qcbor_decode.h file
5850 */
5851void
5852QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
5853 const uint32_t uConvertTypes,
5854 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005855{
5856
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005857 QCBORItem Item;
5858
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005859 QCBORDecode_Private_GetDoubleConvert(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005860
5861 if(pMe->uLastError == QCBOR_SUCCESS) {
5862 // The above conversion succeeded
5863 return;
5864 }
5865
5866 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5867 // The above conversion failed in a way that code below can't correct
5868 return;
5869 }
5870
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005871 pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
5872 uConvertTypes,
5873 pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005874}
5875
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005876
5877/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005878 * Public function, see header qcbor/qcbor_decode.h file
5879 */
5880void
5881QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
5882 const int64_t nLabel,
5883 const uint32_t uConvertTypes,
5884 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005885{
5886 QCBORItem Item;
5887
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005888 QCBORDecode_Private_GetDoubleConvertInMapN(pMe,
5889 nLabel,
5890 uConvertTypes,
5891 pdValue,
5892 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005893
5894 if(pMe->uLastError == QCBOR_SUCCESS) {
5895 // The above conversion succeeded
5896 return;
5897 }
5898
5899 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5900 // The above conversion failed in a way that code below can't correct
5901 return;
5902 }
5903
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005904 pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
5905 uConvertTypes,
5906 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005907}
5908
5909
5910/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005911 * Public function, see header qcbor/qcbor_decode.h file
5912 */
5913void
5914QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
5915 const char *szLabel,
5916 const uint32_t uConvertTypes,
5917 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005918{
5919 QCBORItem Item;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005920 QCBORDecode_Private_GetDoubleConvertInMapSZ(pMe,
5921 szLabel,
5922 uConvertTypes,
5923 pdValue,
5924 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005925
5926 if(pMe->uLastError == QCBOR_SUCCESS) {
5927 // The above conversion succeeded
5928 return;
5929 }
5930
5931 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5932 // The above conversion failed in a way that code below can't correct
5933 return;
5934 }
5935
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005936 pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
5937 uConvertTypes,
5938 pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005939}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02005940#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005941
5942
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005943
5944
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005945#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005946static UsefulBufC
5947QCBOR_Private_ConvertIntToBigNum(uint64_t uInt, const UsefulBuf Buffer)
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005948{
5949 while((uInt & 0xff00000000000000UL) == 0) {
5950 uInt = uInt << 8;
5951 };
5952
5953 UsefulOutBuf UOB;
5954
5955 UsefulOutBuf_Init(&UOB, Buffer);
5956
5957 while(uInt) {
5958 const uint64_t xx = uInt & 0xff00000000000000UL;
5959 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
5960 uInt = uInt << 8;
5961 (void)xx;
5962 }
5963
5964 return UsefulOutBuf_OutUBuf(&UOB);
5965}
5966
5967
Laurence Lundblade37286c02022-09-03 10:05:02 -07005968/**
5969 * @brief Check and/or complete mantissa and exponent item.
5970 *
5971 * @param[in] pMe The decoder context
5972 * @param[in] TagSpec Expected type(s)
5973 * @param[in,out] pItem See below
5974 *
5975 * This is for decimal fractions and big floats, both of which are a
5976 * mantissa and exponent.
5977 *
5978 * The input item is either a fully decoded decimal faction or big
5979 * float, or a just the decoded first item of a decimal fraction or
5980 * big float.
5981 *
5982 * On output, the item is always a fully decoded decimal fraction or
5983 * big float.
5984 *
5985 * This errors out if the input type does not meet the TagSpec.
5986 */
5987// TODO: document and see tests for the bug that was fixed by this rewrite
5988static QCBORError
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005989QCBOR_Private_ExpMantissaTypeHandler(QCBORDecodeContext *pMe,
5990 const QCBOR_Private_TagSpec TagSpec,
5991 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005992{
5993 QCBORError uErr;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005994
Laurence Lundblade37286c02022-09-03 10:05:02 -07005995 /* pItem could either be an auto-decoded mantissa and exponent or
5996 * the opening array of an undecoded mantissa and exponent. This
5997 * check will succeed on either, but doesn't say which it was.
5998 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07005999 uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07006000 if(uErr != QCBOR_SUCCESS) {
6001 goto Done;
6002 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006003
Laurence Lundblade37286c02022-09-03 10:05:02 -07006004 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
6005 /* The item is an array, which means is is an undecoded mantissa
6006 * and exponent. This call consumes the items in the array and
6007 * results in a decoded mantissa and exponent in pItem. This is
6008 * the case where there was no tag.
6009 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006010 uErr = QCBORDecode_Private_ExpMantissa(pMe, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006011 if(uErr != QCBOR_SUCCESS) {
6012 goto Done;
6013 }
6014
Laurence Lundblade37286c02022-09-03 10:05:02 -07006015 /* The above decode didn't determine whether it is a decimal
6016 * fraction or big num. Which of these two depends on what the
6017 * caller wants it decoded as since there is no tag, so fish the
6018 * type out of the TagSpec. */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006019 pItem->uDataType = QCBOR_Private_ExpMantissaDataType(TagSpec.uTaggedTypes[0], pItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07006020
6021 /* No need to check the type again. All that we need to know was
6022 * that it decoded correctly as a mantissa and exponent. The
6023 * QCBOR type is set out by what was requested.
6024 */
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006025 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07006026
6027 /* If the item was not an array and the check passed, then
6028 * it is a fully decoded big float or decimal fraction and
6029 * matches what is requested.
6030 */
6031
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006032Done:
6033 return uErr;
6034}
6035
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006036
Laurence Lundblade37286c02022-09-03 10:05:02 -07006037/* Some notes from the work to disable tags.
6038 *
6039 * The API for big floats and decimal fractions seems good.
6040 * If there's any issue with it it's that the code size to
6041 * implement is a bit large because of the conversion
6042 * to/from int and bignum that is required. There is no API
6043 * that doesn't do the conversion so dead stripping will never
6044 * leave that code out.
6045 *
6046 * The implementation itself seems correct, but not as clean
6047 * and neat as it could be. It could probably be smaller too.
6048 *
6049 * The implementation has three main parts / functions
6050 * - The decoding of the array of two
6051 * - All the tag and type checking for the various API functions
6052 * - Conversion to/from bignum and int
6053 *
6054 * The type checking seems like it wastes the most code for
6055 * what it needs to do.
6056 *
6057 * The inlining for the conversion is probably making the
6058 * overall code base larger.
6059 *
6060 * The tests cases could be organized a lot better and be
6061 * more thorough.
6062 *
6063 * Seems also like there could be more common code in the
6064 * first tier part of the public API. Some functions only
6065 * vary by a TagSpec.
6066 */
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006067static void
6068QCBOR_Private_ProcessExpMantissa(QCBORDecodeContext *pMe,
6069 const QCBOR_Private_TagSpec TagSpec,
6070 QCBORItem *pItem,
6071 int64_t *pnMantissa,
6072 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006073{
6074 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006075
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006076 uErr = QCBOR_Private_ExpMantissaTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006077 if(uErr != QCBOR_SUCCESS) {
6078 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006079 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006080
Laurence Lundblade9b334962020-08-27 10:55:53 -07006081 switch (pItem->uDataType) {
6082
6083 case QCBOR_TYPE_DECIMAL_FRACTION:
6084 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade9b334962020-08-27 10:55:53 -07006085 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade37286c02022-09-03 10:05:02 -07006086 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
Laurence Lundblade9b334962020-08-27 10:55:53 -07006087 break;
6088
Laurence Lundblade37286c02022-09-03 10:05:02 -07006089#ifndef QCBOR_DISABLE_TAGS
6090 /* If tags are disabled, mantissas can never be big nums */
Laurence Lundblade9b334962020-08-27 10:55:53 -07006091 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
6092 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
6093 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006094 uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
Laurence Lundblade9b334962020-08-27 10:55:53 -07006095 break;
6096
6097 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
6098 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
6099 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006100 uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
Laurence Lundblade9b334962020-08-27 10:55:53 -07006101 break;
Laurence Lundblade37286c02022-09-03 10:05:02 -07006102#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade9b334962020-08-27 10:55:53 -07006103
6104 default:
6105 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
6106 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006107
6108 Done:
6109 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006110}
6111
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006112
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006113static void
6114QCBOR_Private_ProcessExpMantissaBig(QCBORDecodeContext *pMe,
6115 const QCBOR_Private_TagSpec TagSpec,
6116 QCBORItem *pItem,
6117 const UsefulBuf BufferForMantissa,
6118 UsefulBufC *pMantissa,
6119 bool *pbIsNegative,
6120 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006121{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006122 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006123
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006124 uErr = QCBOR_Private_ExpMantissaTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006125 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006126 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006127 }
6128
6129 uint64_t uMantissa;
6130
6131 switch (pItem->uDataType) {
6132
6133 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006134 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07006135 /* See comments in ExponentiateNN() on handling INT64_MIN */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006136 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
6137 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
6138 *pbIsNegative = false;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07006139 } else if(pItem->val.expAndMantissa.Mantissa.nInt != INT64_MIN) {
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006140 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
6141 *pbIsNegative = true;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07006142 } else {
6143 uMantissa = (uint64_t)INT64_MAX+1;
6144 *pbIsNegative = true;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006145 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006146 *pMantissa = QCBOR_Private_ConvertIntToBigNum(uMantissa,
6147 BufferForMantissa);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006148 *pnExponent = pItem->val.expAndMantissa.nExponent;
6149 break;
6150
Laurence Lundblade37286c02022-09-03 10:05:02 -07006151#ifndef QCBOR_DISABLE_TAGS
6152 /* If tags are disabled, mantissas can never be big nums */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006153 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006154 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006155 *pnExponent = pItem->val.expAndMantissa.nExponent;
6156 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
6157 *pbIsNegative = false;
6158 break;
6159
6160 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006161 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006162 *pnExponent = pItem->val.expAndMantissa.nExponent;
6163 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
6164 *pbIsNegative = true;
6165 break;
Laurence Lundblade37286c02022-09-03 10:05:02 -07006166#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006167
6168 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006169 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006170 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006171
6172Done:
6173 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006174}
6175
6176
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006177/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006178 * Public function, see header qcbor/qcbor_decode.h file
6179 */
6180void
6181QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
6182 const uint8_t uTagRequirement,
6183 int64_t *pnMantissa,
6184 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006185{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006186 if(pMe->uLastError != QCBOR_SUCCESS) {
6187 return;
6188 }
6189
6190 QCBORItem Item;
6191 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6192 if(uError) {
6193 pMe->uLastError = (uint8_t)uError;
6194 return;
6195 }
6196
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006197 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006198 {
6199 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006200 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6201 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6202 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006203 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006204
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006205 QCBOR_Private_ProcessExpMantissa(pMe,
6206 TagSpec,
6207 &Item,
6208 pnMantissa,
6209 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006210}
6211
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006212
6213/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006214 * Public function, see header qcbor/qcbor_decode.h file
6215 */
6216void
6217QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
6218 const int64_t nLabel,
6219 const uint8_t uTagRequirement,
6220 int64_t *pnMantissa,
6221 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006222{
6223 if(pMe->uLastError != QCBOR_SUCCESS) {
6224 return;
6225 }
6226
6227 QCBORItem Item;
6228 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
6229
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006230 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006231 {
6232 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006233 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6234 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6235 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006236 };
6237
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006238 QCBOR_Private_ProcessExpMantissa(pMe,
6239 TagSpec,
6240 &Item,
6241 pnMantissa,
6242 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006243}
6244
6245
6246/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006247 * Public function, see header qcbor/qcbor_decode.h file
6248 */
6249void
6250QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
6251 const char *szLabel,
6252 const uint8_t uTagRequirement,
6253 int64_t *pnMantissa,
6254 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006255{
6256 if(pMe->uLastError != QCBOR_SUCCESS) {
6257 return;
6258 }
6259
6260 QCBORItem Item;
6261 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6262
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006263 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006264 {
6265 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006266 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6267 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6268 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006269 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07006270
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006271 QCBOR_Private_ProcessExpMantissa(pMe,
6272 TagSpec,
6273 &Item,
6274 pnMantissa,
6275 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006276}
6277
6278
6279/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006280 * Public function, see header qcbor/qcbor_decode.h file
6281 */
6282void
6283QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
6284 const uint8_t uTagRequirement,
6285 const UsefulBuf MantissaBuffer,
6286 UsefulBufC *pMantissa,
6287 bool *pbMantissaIsNegative,
6288 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006289{
6290 if(pMe->uLastError != QCBOR_SUCCESS) {
6291 return;
6292 }
6293
6294 QCBORItem Item;
6295 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6296 if(uError) {
6297 pMe->uLastError = (uint8_t)uError;
6298 return;
6299 }
6300
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006301 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006302 {
6303 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006304 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6305 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6306 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006307 };
6308
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006309 QCBOR_Private_ProcessExpMantissaBig(pMe,
6310 TagSpec,
6311 &Item,
6312 MantissaBuffer,
6313 pMantissa,
6314 pbMantissaIsNegative,
6315 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006316}
6317
6318
6319/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006320 * Public function, see header qcbor/qcbor_decode.h file
6321 */
6322void
6323QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
6324 const int64_t nLabel,
6325 const uint8_t uTagRequirement,
6326 const UsefulBuf BufferForMantissa,
6327 UsefulBufC *pMantissa,
6328 bool *pbIsNegative,
6329 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006330{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006331 if(pMe->uLastError != QCBOR_SUCCESS) {
6332 return;
6333 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006334
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006335 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006336 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006337 if(pMe->uLastError != QCBOR_SUCCESS) {
6338 return;
6339 }
6340
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006341 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006342 {
6343 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006344 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6345 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6346 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006347 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006348
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006349 QCBOR_Private_ProcessExpMantissaBig(pMe,
6350 TagSpec,
6351 &Item,
6352 BufferForMantissa,
6353 pMantissa,
6354 pbIsNegative,
6355 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006356}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006357
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006358
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006359/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006360 * Public function, see header qcbor/qcbor_decode.h file
6361 */
6362void
6363QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
6364 const char *szLabel,
6365 const uint8_t uTagRequirement,
6366 const UsefulBuf BufferForMantissa,
6367 UsefulBufC *pMantissa,
6368 bool *pbIsNegative,
6369 int64_t *pnExponent)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006370{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006371 if(pMe->uLastError != QCBOR_SUCCESS) {
6372 return;
6373 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006374
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006375 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006376 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6377 if(pMe->uLastError != QCBOR_SUCCESS) {
6378 return;
6379 }
6380
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006381 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006382 {
6383 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006384 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6385 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6386 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006387 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006388
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006389 QCBOR_Private_ProcessExpMantissaBig(pMe,
6390 TagSpec,
6391 &Item,
6392 BufferForMantissa,
6393 pMantissa,
6394 pbIsNegative,
6395 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006396}
6397
6398
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006399/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006400 * Public function, see header qcbor/qcbor_decode.h file
6401 */
6402void
6403QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
6404 const uint8_t uTagRequirement,
6405 int64_t *pnMantissa,
6406 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006407{
6408 if(pMe->uLastError != QCBOR_SUCCESS) {
6409 return;
6410 }
6411
6412 QCBORItem Item;
6413 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6414 if(uError) {
6415 pMe->uLastError = (uint8_t)uError;
6416 return;
6417 }
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006418 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006419 {
6420 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006421 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6422 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6423 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006424 };
6425
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006426 QCBOR_Private_ProcessExpMantissa(pMe,
6427 TagSpec,
6428 &Item,
6429 pnMantissa,
6430 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006431}
6432
6433
6434/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006435 * Public function, see header qcbor/qcbor_decode.h file
6436 */
6437void
6438QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
6439 const int64_t nLabel,
6440 const uint8_t uTagRequirement,
6441 int64_t *pnMantissa,
6442 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006443{
6444 if(pMe->uLastError != QCBOR_SUCCESS) {
6445 return;
6446 }
6447
6448 QCBORItem Item;
6449 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
6450 if(pMe->uLastError != QCBOR_SUCCESS) {
6451 return;
6452 }
6453
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006454 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006455 {
6456 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006457 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6458 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6459 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006460 };
6461
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006462 QCBOR_Private_ProcessExpMantissa(pMe,
6463 TagSpec,
6464 &Item,
6465 pnMantissa,
6466 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006467}
6468
6469
6470/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006471 * Public function, see header qcbor/qcbor_decode.h file
6472 */
6473void
6474QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
6475 const char *szLabel,
6476 const uint8_t uTagRequirement,
6477 int64_t *pnMantissa,
6478 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006479{
6480 if(pMe->uLastError != QCBOR_SUCCESS) {
6481 return;
6482 }
6483
6484 QCBORItem Item;
6485 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6486 if(pMe->uLastError != QCBOR_SUCCESS) {
6487 return;
6488 }
6489
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006490 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006491 {
6492 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006493 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6494 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6495 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006496 };
6497
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006498 QCBOR_Private_ProcessExpMantissa(pMe,
6499 TagSpec,
6500 &Item,
6501 pnMantissa,
6502 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006503}
6504
6505
6506/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006507 * Public function, see header qcbor/qcbor_decode.h file
6508 */
6509void
6510QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
6511 const uint8_t uTagRequirement,
6512 const UsefulBuf MantissaBuffer,
6513 UsefulBufC *pMantissa,
6514 bool *pbMantissaIsNegative,
6515 int64_t *pnExponent)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006516{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006517 if(pMe->uLastError != QCBOR_SUCCESS) {
6518 return;
6519 }
6520
6521 QCBORItem Item;
6522 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6523 if(uError) {
6524 pMe->uLastError = (uint8_t)uError;
6525 return;
6526 }
6527
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006528 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006529 {
6530 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006531 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6532 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6533 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006534 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006535
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006536 QCBOR_Private_ProcessExpMantissaBig(pMe,
6537 TagSpec,
6538 &Item,
6539 MantissaBuffer,
6540 pMantissa,
6541 pbMantissaIsNegative,
6542 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006543}
6544
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006545
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006546/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006547 * Public function, see header qcbor/qcbor_decode.h file
6548 */
6549void
6550QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
6551 const int64_t nLabel,
6552 const uint8_t uTagRequirement,
6553 const UsefulBuf BufferForMantissa,
6554 UsefulBufC *pMantissa,
6555 bool *pbIsNegative,
6556 int64_t *pnExponent)
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006557{
6558 if(pMe->uLastError != QCBOR_SUCCESS) {
6559 return;
6560 }
6561
6562 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006563 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
6564 if(pMe->uLastError != QCBOR_SUCCESS) {
6565 return;
6566 }
6567
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006568 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006569 {
6570 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006571 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6572 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6573 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006574 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006575
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006576 QCBOR_Private_ProcessExpMantissaBig(pMe,
6577 TagSpec,
6578 &Item,
6579 BufferForMantissa,
6580 pMantissa,
6581 pbIsNegative,
6582 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006583}
6584
6585
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006586/*
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006587 * Public function, see header qcbor/qcbor_decode.h file
6588 */
6589void
6590QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
6591 const char *szLabel,
6592 const uint8_t uTagRequirement,
6593 const UsefulBuf BufferForMantissa,
6594 UsefulBufC *pMantissa,
6595 bool *pbIsNegative,
6596 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006597{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006598 if(pMe->uLastError != QCBOR_SUCCESS) {
6599 return;
6600 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006601
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006602 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006603 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6604 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006605 return;
6606 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006607
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006608 const QCBOR_Private_TagSpec TagSpec =
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006609 {
6610 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006611 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6612 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6613 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006614 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006615
Laurence Lundblade8e36f812024-01-26 10:59:29 -07006616 QCBOR_Private_ProcessExpMantissaBig(pMe,
6617 TagSpec,
6618 &Item,
6619 BufferForMantissa,
6620 pMantissa,
6621 pbIsNegative,
6622 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006623}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006624
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006625#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */