blob: 44473525aa51022700ea18291f3f173b91f4c8fa [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 Lundbladeaf5921e2022-07-15 09:06:30 -07003 Copyright (c) 2018-2022, 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 Lundbladed3adb7c2023-02-08 12:43:11 -070049#if (defined(__GNUC__) && !defined(__clang__))
50/* -Wmaybe-uninitialized will generate false warnings because it
51 * doesn't do a thorough static analysis. It is known that The
52 * warnings generated for this code are false positives because 1)
53 * each case was examined and 2) this code has been run through proper
54 * static analyzers.
55 *
56 * What is reported by -Wmaybe-uninitialized varies by GCC version,
57 * target OS and optimizer settings. Sometimes it's on with -Wall and
58 * some times it's not. Compilers that aren't GCC (e.g., clang)
59 * pretend to be GCC and don't know about this warn option. It's kind
60 * of a mess... :-(
61 *
62 * There are no warnings for qcbode_decode.c with
63 * -Wuninitialized. Presumably the difference is that -Wuninitialized
64 * only reports issues that are clearly issues that have no
65 * possibility of a false positive.
66 *
67 * This pragma disables the warning for -Wmaybe-uninitialized for the whole file so the source
68 * code is kept a bit cleaner and nicer, in particularly because what
69 * this warns about is so variable.
70 *
71 * Another way to solve this is to provide initializations. The
72 * problem with this is that they make the code bigger,
73 * but even worse, just initializing without understanding what
74 * the code does and what it should be initialized to understand if it really
75 * isn't initialized is just as bad for the end correctness as
76 * suppressing the warning without checking the code.
77 *
78 * Most of the warnings are about Item.Item->uDataType being
79 * unitialized. QCBORDecode_GetNext() *always* sets this value. -Wmaybe-uninitialized
80 * just can't tell.
81 *
82 * https://stackoverflow.com/questions/5080848/disable-gcc-may-be-used-uninitialized-on-a-particular-variable
83 */
84#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
85#endif
86
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080087
Laurence Lundbladea9489f82020-09-12 13:50:56 -070088#define SIZEOF_C_ARRAY(array,type) (sizeof(array)/sizeof(type))
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070089
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070090
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080091
92
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070093static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070094QCBORItem_IsMapOrArray(const QCBORItem *pMe)
95{
96 const uint8_t uDataType = pMe->uDataType;
97 return uDataType == QCBOR_TYPE_MAP ||
98 uDataType == QCBOR_TYPE_ARRAY ||
99 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
100}
101
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700102static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -0700103QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem *pMe)
104{
105 if(!QCBORItem_IsMapOrArray(pMe)){
106 return false;
107 }
108
109 if(pMe->val.uCount != 0) {
110 return false;
111 }
112 return true;
113}
114
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700115static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -0700116QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem *pMe)
117{
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800118#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -0700119 if(!QCBORItem_IsMapOrArray(pMe)){
120 return false;
121 }
122
123 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
124 return false;
125 }
126 return true;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800127#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
128 (void)pMe;
129 return false;
130#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700131}
132
133
Laurence Lundbladeee851742020-01-08 08:37:05 -0800134/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700135 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -0800136 ===========================================================================*/
137
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700138/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800139 * See comments about and typedef of QCBORDecodeNesting in qcbor_private.h,
140 * the data structure all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700141 */
142
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700143
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700144static inline uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700145DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700146{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700147 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800148 /* Limit in DecodeNesting_Descend against more than
149 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700150 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700151 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700152}
153
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700154
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700155static inline uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700156DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700157{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700158 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800159 /* Limit in DecodeNesting_Descend against more than
160 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700161 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700162 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700163}
164
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700165
Laurence Lundblade5f4e8712020-07-25 11:44:43 -0700166static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700167DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700168{
169 return pNesting->pCurrentBounded->u.ma.uStartOffset;
170}
171
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700172
Laurence Lundblade085d7952020-07-24 10:26:30 -0700173static inline bool
174DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
175{
176 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
177 return true;
178 } else {
179 return false;
180 }
181}
182
183
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700184static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700185DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700186{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700187 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700188 return true;
189 } else {
190 return false;
191 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700192}
193
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700194
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700195static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700196DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700197{
198 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800199 /* Not a map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700200 return false;
201 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800202
203#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700204 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800205 /* Is indefinite */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700206 return false;
207 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800208
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800209#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
210
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800211 /* All checks passed; is a definte length map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700212 return true;
213}
214
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700215static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700216DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700217{
218 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800219 /* is a byte string */
Laurence Lundblade642282a2020-06-23 12:00:33 -0700220 return true;
221 }
222 return false;
223}
224
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700225
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700226static inline bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700227{
228 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
229 return true;
230 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700231 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700232 return true;
233 }
234 return false;
235}
236
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700237
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700238static inline void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700239{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800240 /* Should be only called on maps and arrays */
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700241 /*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800242 * DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
243 * larger than DecodeNesting_EnterBoundedMode which keeps it less than
244 * uin32_t so the cast is safe.
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700245 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700246 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700247
248 if(bIsEmpty) {
249 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
250 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700251}
252
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700253
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700254static inline void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700255{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700256 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700257}
258
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700259
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700260static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700261DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700262{
263 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800264 /* No bounded map or array set up */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700265 return false;
266 }
267 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800268 /* Not a map or array; end of those is by byte count */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700269 return false;
270 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700271 if(!DecodeNesting_IsCurrentBounded(pNesting)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800272 /* In a traveral at a level deeper than the bounded level */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700273 return false;
274 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800275 /* Works for both definite- and indefinitelength maps/arrays */
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800276 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0 &&
277 pNesting->pCurrentBounded->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800278 /* Count is not zero, still unconsumed item */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700279 return false;
280 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800281 /* All checks passed, got to the end of an array or map*/
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700282 return true;
283}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700284
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700285
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700286static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700287DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700288{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800289 /* Must only be called on map / array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700290 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
291 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700292 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700293 return false;
294 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700295}
296
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700297
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700298static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700299DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700300{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700301 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
302 return true;
303 } else {
304 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700305 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700306}
307
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700308
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700309static inline bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700310DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700311{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700312 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700313 return false;
314 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700315
316 if(pNesting->pCurrentBounded->uLevelType != uType) {
317 return false;
318 }
319
320 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700321}
322
Laurence Lundblade02625d42020-06-25 14:41:41 -0700323
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700324static inline void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700325DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700326{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800327 /* Only call on a definite-length array / map */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700328 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700329}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700330
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700331
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700332static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700333DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
334{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800335 /* Only call on a definite-length array / map */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700336 pNesting->pCurrent->u.ma.uCountCursor++;
337}
338
339
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700340static inline void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700341DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
342{
343 pNesting->pCurrent--;
344}
345
Laurence Lundblade02625d42020-06-25 14:41:41 -0700346
347static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700348DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700349{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800350 /* Error out if nesting is too deep */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700351 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700352 return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700353 }
354
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800355 /* The actual descend */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700356 pNesting->pCurrent++;
357
358 pNesting->pCurrent->uLevelType = uType;
359
360 return QCBOR_SUCCESS;
361}
362
363
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700364static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800365DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting,
366 bool bIsEmpty,
367 size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700368{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700369 /*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800370 * Should only be called on map/array.
371 *
372 * Have descended into this before this is called. The job here is
373 * just to mark it in bounded mode.
374 *
375 * Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
376 * uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET.
377 *
378 * Cast of uOffset to uint32_t for cases where SIZE_MAX < UINT32_MAX.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700379 */
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -0800380 if((uint32_t)uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700381 return QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700382 }
383
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700384 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700385
386 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700387
388 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700389}
390
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700391
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700392static inline QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700393DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700394 uint8_t uQCBORType,
395 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700396{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700397 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700398
399 if(uCount == 0) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800400 /* Nothing to do for empty definite-length arrays. They are just are
401 * effectively the same as an item that is not a map or array.
402 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700403 goto Done;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800404 /* Empty indefinite-length maps and arrays are handled elsewhere */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700405 }
406
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800407 /* Error out if arrays is too long to handle */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700408 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
409 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700410 uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700411 goto Done;
412 }
413
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700414 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700415 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700416 goto Done;
417 }
418
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800419 /* Fill in the new map/array level. Check above makes casts OK. */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700420 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
421 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700422
423 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700424
425Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700426 return uError;;
427}
428
429
430static inline void
431DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
432{
433 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
434}
435
436
437static inline void
438DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
439{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700440 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700441 pNesting->pCurrentBounded--;
442 if(DecodeNesting_IsCurrentBounded(pNesting)) {
443 break;
444 }
445 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700446}
447
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800448
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700449static inline void
450DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
451{
452 pNesting->pCurrent = pNesting->pCurrentBounded;
453}
454
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700455
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700456static inline QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700457DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700458 uint32_t uEndOffset,
459 uint32_t uStartOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700460{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700461 QCBORError uError;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700462
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700463 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700464 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700465 goto Done;
466 }
467
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800468 /* Fill in the new byte string level */
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700469 pNesting->pCurrent->u.bs.uSavedEndOffset = uEndOffset;
470 pNesting->pCurrent->u.bs.uBstrStartOffset = uStartOffset;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700471
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800472 /* Bstr wrapped levels are always bounded */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700473 pNesting->pCurrentBounded = pNesting->pCurrent;
474
475Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700476 return uError;;
477}
478
Laurence Lundbladed0304932020-06-27 10:59:38 -0700479
480static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700481DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700482{
483 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700484}
485
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700486
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700487static inline void
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800488DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
489{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700490 if(pNesting->pCurrent->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
491 pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
492 }
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800493}
494
495
496static inline void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700497DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700498{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700499 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700500 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
501 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700502}
503
504
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700505static inline void
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800506DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting,
507 QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700508{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700509 *pSave = *pNesting;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700510}
511
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700512
Laurence Lundblade02625d42020-06-25 14:41:41 -0700513static inline void
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800514DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting,
515 const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700516{
517 *pNesting = *pSave;
518}
519
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700520
Laurence Lundblade02625d42020-06-25 14:41:41 -0700521static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700522DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700523{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700524 return pMe->pCurrentBounded->u.bs.uSavedEndOffset;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700525}
526
527
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800528
529
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800530#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladeee851742020-01-08 08:37:05 -0800531/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800532 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
533
534 The following four functions are pretty wrappers for invocation of
535 the string allocator supplied by the caller.
536
Laurence Lundbladeee851742020-01-08 08:37:05 -0800537 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800538
Laurence Lundbladeee851742020-01-08 08:37:05 -0800539static inline void
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800540StringAllocator_Free(const QCBORInternalAllocator *pMe, const void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800541{
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300542 /* This cast to uintptr_t suppresses the "-Wcast-qual" warnings.
543 * This is the one place where the const needs to be cast away so const can
544 * be use in the rest of the code.
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800545 */
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300546 (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)(uintptr_t)pMem, 0);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800547}
548
Laurence Lundbladeee851742020-01-08 08:37:05 -0800549// StringAllocator_Reallocate called with pMem NULL is
550// equal to StringAllocator_Allocate()
551static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800552StringAllocator_Reallocate(const QCBORInternalAllocator *pMe,
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800553 const void *pMem,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800554 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800555{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800556 /* See comment in StringAllocator_Free() */
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300557 return (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)(uintptr_t)pMem, uSize);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800558}
559
Laurence Lundbladeee851742020-01-08 08:37:05 -0800560static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800561StringAllocator_Allocate(const QCBORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800562{
563 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
564}
565
Laurence Lundbladeee851742020-01-08 08:37:05 -0800566static inline void
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800567StringAllocator_Destruct(const QCBORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800568{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800569 /* See comment in StringAllocator_Free() */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800570 if(pMe->pfAllocator) {
571 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
572 }
573}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800574#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800575
576
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800577
578
Laurence Lundbladeee851742020-01-08 08:37:05 -0800579/*===========================================================================
580 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700581
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800582 See qcbor/qcbor_decode.h for definition of the object
583 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800584 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700585/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800586 * Public function, see header file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700587 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800588void QCBORDecode_Init(QCBORDecodeContext *pMe,
589 UsefulBufC EncodedCBOR,
590 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700591{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800592 memset(pMe, 0, sizeof(QCBORDecodeContext));
593 UsefulInputBuf_Init(&(pMe->InBuf), EncodedCBOR);
594 /* Don't bother with error check on decode mode. If a bad value is
595 * passed it will just act as if the default normal mode of 0 was set.
596 */
597 pMe->uDecodeMode = (uint8_t)nDecodeMode;
598 DecodeNesting_Init(&(pMe->nesting));
599
600 /* Inialize me->auMappedTags to CBOR_TAG_INVALID16. See
601 * GetNext_TaggedItem() and MapTagNumber(). */
602 memset(pMe->auMappedTags, 0xff, sizeof(pMe->auMappedTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700603}
604
605
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800606#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
607
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700608/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800609 * Public function, see header file
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700610 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800611void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
612 QCBORStringAllocate pfAllocateFunction,
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800613 void *pAllocateContext,
614 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700615{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800616 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
617 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
618 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700619}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800620#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700621
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800622
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800623
624
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800625/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800626 * Deprecated public function, see header file
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800627 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800628void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800629 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700630{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800631 /* This does nothing now. It is retained for backwards compatibility */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700632 (void)pMe;
633 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700634}
635
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700636
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800637
638
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700639/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800640 * Decoding items is done in six layers, one calling the next one
641 * down. If a layer has no work to do for a particular item, it
642 * returns quickly.
643 *
644 * 1. QCBORDecode_GetNextTagContent - The top layer processes tagged
645 * data items, turning them into the local C representation. For the
646 * most simple it is just associating a QCBOR_TYPE with the data. For
647 * the complex ones that an aggregate of data items, there is some
648 * further decoding and some limited recursion.
649 *
650 * 2. QCBORDecode_GetNextMapOrArray - This manages the beginnings and
651 * ends of maps and arrays. It tracks descending into and ascending
652 * out of maps/arrays. It processes breaks that terminate
653 * indefinite-length maps and arrays.
654 *
655 * 3. QCBORDecode_GetNextMapEntry - This handles the combining of two
656 * items, the label and the data, that make up a map entry. It only
657 * does work on maps. It combines the label and data items into one
658 * labeled item.
659 *
660 * 4. QCBORDecode_GetNextTagNumber - This decodes type 6 tag
661 * numbers. It turns the tag numbers into bit flags associated with
662 * the data item. No actual decoding of the contents of the tag is
663 * performed here.
664 *
665 * 5. QCBORDecode_GetNextFullString - This assembles the sub-items
666 * that make up an indefinite-length string into one string item. It
667 * uses the string allocator to create contiguous space for the
668 * item. It processes all breaks that are part of indefinite-length
669 * strings.
670 *
671 * 6. DecodeAtomicDataItem - This decodes the atomic data items in
672 * CBOR. Each atomic data item has a "major type", an integer
673 * "argument" and optionally some content. For text and byte strings,
674 * the content is the bytes that make up the string. These are the
675 * smallest data items that are considered to be well-formed. The
676 * content may also be other data items in the case of aggregate
677 * types. They are not handled in this layer.
678 *
679 * Roughly this takes 300 bytes of stack for vars. TODO: evaluate this
680 * more carefully and correctly.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700681 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800682
683
684/*
685 * Note about use of int and unsigned variables.
686 *
687 * See http://www.unix.org/whitepapers/64bit.html for reasons int is
688 * used carefully here, and in particular why it isn't used in the
689 * public interface. Also see
690 * https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
691 *
692 * Int is used for values that need less than 16-bits and would be
693 * subject to integer promotion and result in complaining from static
694 * analyzers.
695 */
696
697
698/**
699 * @brief Decode the CBOR head, the type and argument.
700 *
701 * @param[in] pUInBuf The input buffer to read from.
702 * @param[out] pnMajorType The decoded major type.
703 * @param[out] puArgument The decoded argument.
704 * @param[out] pnAdditionalInfo The decoded Lower 5 bits of initial byte.
705 *
706 * @retval QCBOR_ERR_UNSUPPORTED
707 * @retval QCBOR_ERR_HIT_END
708 *
709 * This decodes the CBOR "head" that every CBOR data item has. See
710 * longer explaination of the head in documentation for
711 * QCBOREncode_EncodeHead().
712 *
713 * This does the network->host byte order conversion. The conversion
714 * here also results in the conversion for floats in addition to that
715 * for lengths, tags and integer values.
716 *
717 * The int type is preferred to uint8_t for some variables as this
718 * avoids integer promotions, can reduce code size and makes static
719 * analyzers happier.
720 */
721static inline QCBORError
722DecodeHead(UsefulInputBuf *pUInBuf,
723 int *pnMajorType,
724 uint64_t *puArgument,
725 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700726{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800727 QCBORError uReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800728
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800729 /* Get the initial byte that every CBOR data item has and break it
730 * down. */
731 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800732 const int nTmpMajorType = nInitialByte >> 5;
733 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800734
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800735 /* Where the argument accumulates */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800736 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800737
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800738 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800739 /* Need to get 1,2,4 or 8 additional argument bytes. Map
740 * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
741 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800742 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800743
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800744 /* Loop getting all the bytes in the argument */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800745 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800746 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800747 /* This shift and add gives the endian conversion. */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800748 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
749 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800750 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800751 /* The reserved and thus-far unused additional info values */
752 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800753 goto Done;
754 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800755 /* Less than 24, additional info is argument or 31, an
756 * indefinite-length. No more bytes to get.
757 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800758 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700759 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800760
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700761 if(UsefulInputBuf_GetError(pUInBuf)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800762 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700763 goto Done;
764 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800765
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800766 /* All successful if arrived here. */
767 uReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800768 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800769 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800770 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800771
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700772Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800773 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700774}
775
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800776
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800777/**
778 * @brief Decode integer types, major types 0 and 1.
779 *
780 * @param[in] nMajorType The CBOR major type (0 or 1).
781 * @param[in] uArgument The argument from the head.
782 * @param[out] pDecodedItem The filled in decoded item.
783 *
784 * @retval QCBOR_ERR_INT_OVERFLOW
785 *
786 * Must only be called when major type is 0 or 1.
787 *
788 * CBOR doesn't explicitly specify two's compliment for integers but
789 * all CPUs use it these days and the test vectors in the RFC are
790 * so. All integers in the CBOR structure are positive and the major
791 * type indicates positive or negative. CBOR can express positive
792 * integers up to 2^x - 1 where x is the number of bits and negative
793 * integers down to 2^x. Note that negative numbers can be one more
794 * away from zero than positive. Stdint, as far as I can tell, uses
795 * two's compliment to represent negative integers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700796 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700797static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800798DecodeInteger(int nMajorType, uint64_t uArgument, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700799{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800800 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800801
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700802 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800803 if (uArgument <= INT64_MAX) {
804 pDecodedItem->val.int64 = (int64_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700805 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800806
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700807 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800808 pDecodedItem->val.uint64 = uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700809 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700810 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800811
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700812 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800813 if(uArgument <= INT64_MAX) {
814 /* CBOR's representation of negative numbers lines up with
815 * the two-compliment representation. A negative integer has
816 * one more in range than a positive integer. INT64_MIN is
817 * equal to (-INT64_MAX) - 1.
818 */
819 pDecodedItem->val.int64 = (-(int64_t)uArgument) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700820 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800821
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700822 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800823 /* C can't represent a negative integer in this range so it
824 * is an error.
825 */
826 uReturn = QCBOR_ERR_INT_OVERFLOW;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700827 }
828 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800829
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800830 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700831}
832
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800833
834/* Make sure #define value line up as DecodeSimple counts on this. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700835#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
836#error QCBOR_TYPE_FALSE macro value wrong
837#endif
838
839#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
840#error QCBOR_TYPE_TRUE macro value wrong
841#endif
842
843#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
844#error QCBOR_TYPE_NULL macro value wrong
845#endif
846
847#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
848#error QCBOR_TYPE_UNDEF macro value wrong
849#endif
850
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700851#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
852#error QCBOR_TYPE_BREAK macro value wrong
853#endif
854
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700855#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
856#error QCBOR_TYPE_DOUBLE macro value wrong
857#endif
858
859#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
860#error QCBOR_TYPE_FLOAT macro value wrong
861#endif
862
Laurence Lundblade9b334962020-08-27 10:55:53 -0700863
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800864/**
865 * @brief Decode major type 7 -- true, false, floating-point, break...
866 *
867 * @param[in] nAdditionalInfo The lower five bits from the initial byte.
868 * @param[in] uArgument The argument from the head.
869 * @param[out] pDecodedItem The filled in decoded item.
870 *
871 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200872 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800873 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700874 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800875
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800876static inline QCBORError
877DecodeType7(int nAdditionalInfo, uint64_t uArgument, QCBORItem *pDecodedItem)
878{
879 QCBORError uReturn = QCBOR_SUCCESS;
880
881 /* uAdditionalInfo is 5 bits from the initial byte. Compile time
882 * checks above make sure uAdditionalInfo values line up with
883 * uDataType values. DecodeHead() never returns an AdditionalInfo
884 * > 0x1f so cast is safe.
885 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800886 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800887
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800888 switch(nAdditionalInfo) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800889 /* No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they
890 * are caught before this is called.
891 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800892
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800893 case HALF_PREC_FLOAT: /* 25 */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700894#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800895 /* Half-precision is returned as a double. The cast to
896 * uint16_t is safe because the encoded value was 16 bits. It
897 * was widened to 64 bits to be passed in here.
898 */
899 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700900 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800901#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200902 uReturn = FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700903 break;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800904 case SINGLE_PREC_FLOAT: /* 26 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200905#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800906 /* Single precision is normally returned as a double since
907 * double is widely supported, there is no loss of precision,
908 * it makes it easy for the caller in most cases and it can
909 * be converted back to single with no loss of precision
910 *
911 * The cast to uint32_t is safe because the encoded value was
912 * 32 bits. It was widened to 64 bits to be passed in here.
913 */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700914 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800915 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uArgument);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700916#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800917 /* In the normal case, use HW to convert float to
918 * double. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700919 pDecodedItem->val.dfnum = (double)f;
920 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800921#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800922 /* Use of float HW is disabled, return as a float. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700923 pDecodedItem->val.fnum = f;
924 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
925
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800926 /* IEEE754_FloatToDouble() could be used here to return as
927 * a double, but it adds object code and most likely
928 * anyone disabling FLOAT HW use doesn't care about floats
929 * and wants to save object code.
930 */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800931#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700932 }
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200933#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
934 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700935 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700936
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800937 case DOUBLE_PREC_FLOAT: /* 27 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200938#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800939 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700940 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200941#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
942 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700943 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800944
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800945 case CBOR_SIMPLEV_FALSE: /* 20 */
946 case CBOR_SIMPLEV_TRUE: /* 21 */
947 case CBOR_SIMPLEV_NULL: /* 22 */
948 case CBOR_SIMPLEV_UNDEF: /* 23 */
949 case CBOR_SIMPLE_BREAK: /* 31 */
950 break; /* nothing to do */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800951
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800952 case CBOR_SIMPLEV_ONEBYTE: /* 24 */
953 if(uArgument <= CBOR_SIMPLE_BREAK) {
954 /* This takes out f8 00 ... f8 1f which should be encoded
955 * as e0 … f7
956 */
957 uReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700958 goto Done;
959 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800960 /* FALLTHROUGH */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800961
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800962 default: /* 0-19 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700963 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800964 /* DecodeHead() will make uArgument equal to
965 * nAdditionalInfo when nAdditionalInfo is < 24. This cast is
966 * safe because the 2, 4 and 8 byte lengths of uNumber are in
967 * the double/float cases above
Laurence Lundbladeee851742020-01-08 08:37:05 -0800968 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800969 pDecodedItem->val.uSimple = (uint8_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700970 break;
971 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800972
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700973Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800974 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700975}
976
977
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800978/**
979 * @brief Decode text and byte strings
980 *
981 * @param[in] pAllocator The string allocator or NULL.
982 * @param[in] uStrLen The length of the string.
983 * @param[in] pUInBuf The surce from which to read the string's bytes.
984 * @param[out] pDecodedItem The filled in decoded item.
985 *
986 * @retval QCBOR_ERR_HIT_END
987 * @retval QCBOR_ERR_STRING_ALLOCATE
988 * @retval QCBOR_ERR_STRING_TOO_LONG
989 *
990 * The reads @c uStrlen bytes from @c pUInBuf and fills in @c
991 * pDecodedItem. If @c pAllocator is not NULL then memory for the
992 * string is allocated.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700993 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800994static inline QCBORError
995DecodeBytes(const QCBORInternalAllocator *pAllocator,
996 uint64_t uStrLen,
997 UsefulInputBuf *pUInBuf,
998 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700999{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001000 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001001
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001002 /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
1003 * CPUs. This check makes the casts to size_t below safe.
1004 *
1005 * The max is 4 bytes less than the largest sizeof() so this can be
1006 * tested by putting a SIZE_MAX length in the CBOR test input (no
1007 * one will care the limit on strings is 4 bytes shorter).
1008 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001009 if(uStrLen > SIZE_MAX-4) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001010 uReturn = QCBOR_ERR_STRING_TOO_LONG;
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001011 goto Done;
1012 }
1013
1014 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301015 if(UsefulBuf_IsNULLC(Bytes)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001016 /* Failed to get the bytes for this string item */
1017 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301018 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001019 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301020
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001021#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001022 /* Note that this is not where allocation to coalesce
1023 * indefinite-length strings is done. This is for when the caller
1024 * has requested all strings be allocated. Disabling indefinite
1025 * length strings also disables this allocate-all option.
1026 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001027 if(pAllocator) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001028 /* request to use the string allocator to make a copy */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001029 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301030 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001031 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301032 goto Done;
1033 }
1034 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001035 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001036 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301037 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001038#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1039 (void)pAllocator;
1040#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1041
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001042 /* Normal case with no string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001043 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001044
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301045Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001046 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001047}
1048
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001049
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001050/**
1051 * @brief Map the CBOR major types for strings to the QCBOR types.
1052 *
1053 * @param[in] nCBORMajorType The CBOR major type to convert.
1054 * @retturns QCBOR type number.
1055 *
1056 * This only works for the two string types.
1057 */
1058static inline uint8_t ConvertStringMajorTypes(int nCBORMajorType)
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001059{
1060 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
1061 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
1062 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001063
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001064 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
1065 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
1066 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001067
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001068 return (uint8_t)(nCBORMajorType + 4);
1069}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001070
1071
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001072/**
1073 * @brief Map the CBOR major types for arrays/maps to the QCBOR types.
1074 *
1075 * @param[in] nCBORMajorType The CBOR major type to convert.
1076 * @retturns QCBOR type number.
1077 *
1078 * This only works for the two aggregate types.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001079 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001080static inline uint8_t ConvertArrayOrMapType(int nCBORMajorType)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001081{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001082 #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
1083 #error QCBOR_TYPE_ARRAY value not lined up with major type
1084 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001085
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001086 #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
1087 #error QCBOR_TYPE_MAP value not lined up with major type
1088 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001089
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001090 return (uint8_t)(nCBORMajorType);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001091}
1092
1093
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001094/**
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001095 * @brief Decode a single primitive data item (decode layer 6).
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001096 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001097 * @param[in] pUInBuf Input buffer to read data item from.
1098 * @param[out] pDecodedItem The filled-in decoded item.
1099 * @param[in] pAllocator The allocator to use for strings or NULL.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001100 *
1101 * @retval QCBOR_ERR_UNSUPPORTED
1102 * @retval QCBOR_ERR_HIT_END
1103 * @retval QCBOR_ERR_INT_OVERFLOW
1104 * @retval QCBOR_ERR_STRING_ALLOCATE
1105 * @retval QCBOR_ERR_STRING_TOO_LONG
1106 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001107 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001108 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001109 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1110 *
1111 * This decodes the most primitive / atomic data item. It does
1112 * no combing of data items.
1113 */
1114static QCBORError
1115DecodeAtomicDataItem(UsefulInputBuf *pUInBuf,
1116 QCBORItem *pDecodedItem,
1117 const QCBORInternalAllocator *pAllocator)
1118{
1119 QCBORError uReturn;
1120
1121 /* Get the major type and the argument. The argument could be
1122 * length of more bytes or the value depending on the major
1123 * type. nAdditionalInfo is an encoding of the length of the
1124 * uNumber and is needed to decode floats and doubles.
1125 */
1126 int nMajorType = 0;
1127 uint64_t uArgument = 0;
1128 int nAdditionalInfo = 0;
1129
1130 memset(pDecodedItem, 0, sizeof(QCBORItem));
1131
1132 uReturn = DecodeHead(pUInBuf, &nMajorType, &uArgument, &nAdditionalInfo);
1133 if(uReturn) {
1134 goto Done;
1135 }
1136
1137 /* At this point the major type and the argument are valid. We've
1138 * got the type and the argument that starts every CBOR data item.
1139 */
1140 switch (nMajorType) {
1141 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1142 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
1143 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1144 uReturn = QCBOR_ERR_BAD_INT;
1145 } else {
1146 uReturn = DecodeInteger(nMajorType, uArgument, pDecodedItem);
1147 }
1148 break;
1149
1150 case CBOR_MAJOR_TYPE_BYTE_STRING: /* Major type 2 */
1151 case CBOR_MAJOR_TYPE_TEXT_STRING: /* Major type 3 */
1152 pDecodedItem->uDataType = ConvertStringMajorTypes(nMajorType);
1153 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1154 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
1155 } else {
1156 uReturn = DecodeBytes(pAllocator, uArgument, pUInBuf, pDecodedItem);
1157 }
1158 break;
1159
1160 case CBOR_MAJOR_TYPE_ARRAY: /* Major type 4 */
1161 case CBOR_MAJOR_TYPE_MAP: /* Major type 5 */
1162 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1163 /* Indefinite-length string. */
1164#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
1165 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
1166#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1167 uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
1168 break;
1169#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1170 } else {
1171 /* Definite-length string. */
1172 if(uArgument > QCBOR_MAX_ITEMS_IN_ARRAY) {
1173 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
1174 goto Done;
1175 }
1176 /* cast OK because of check above */
1177 pDecodedItem->val.uCount = (uint16_t)uArgument;
1178 }
1179 pDecodedItem->uDataType = ConvertArrayOrMapType(nMajorType);
1180 break;
1181
1182 case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */
Laurence Lundblade37286c02022-09-03 10:05:02 -07001183#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001184 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1185 uReturn = QCBOR_ERR_BAD_INT;
1186 } else {
1187 pDecodedItem->val.uTagV = uArgument;
1188 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
1189 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07001190#else /* QCBOR_DISABLE_TAGS */
1191 uReturn = QCBOR_ERR_TAGS_DISABLED;
1192#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001193 break;
1194
1195 case CBOR_MAJOR_TYPE_SIMPLE:
1196 /* Major type 7: float, double, true, false, null... */
1197 uReturn = DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
1198 break;
1199
1200 default:
1201 /* Never happens because DecodeHead() should never return > 7 */
1202 uReturn = QCBOR_ERR_UNSUPPORTED;
1203 break;
1204 }
1205
1206Done:
1207 return uReturn;
1208}
1209
1210
1211/**
1212 * @brief Process indefinite-length strings (decode layer 5).
1213 *
1214 * @param[in] pMe Decoder context
1215 * @param[out] pDecodedItem The decoded item that work is done on.
1216 *
1217 * @retval QCBOR_ERR_UNSUPPORTED
1218 * @retval QCBOR_ERR_HIT_END
1219 * @retval QCBOR_ERR_INT_OVERFLOW
1220 * @retval QCBOR_ERR_STRING_ALLOCATE
1221 * @retval QCBOR_ERR_STRING_TOO_LONG
1222 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001223 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001224 * @retval QCBOR_ERR_BAD_TYPE_7
1225 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001226 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1227 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001228 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001229 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001230 * If @c pDecodedItem is not an indefinite-length string, this does nothing.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001231 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001232 * If it is, this loops getting the subsequent chunk data items that
1233 * make up the string. The string allocator is used to make a
1234 * contiguous buffer for the chunks. When this completes @c
1235 * pDecodedItem contains the put-together string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001236 *
1237 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001238 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001239static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001240QCBORDecode_GetNextFullString(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001241{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001242 /* Aproximate stack usage
1243 * 64-bit 32-bit
1244 * local vars 32 16
1245 * 2 UsefulBufs 32 16
1246 * QCBORItem 56 52
1247 * TOTAL 120 74
1248 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001249
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001250 /* The string allocator is used here for two purposes: 1)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001251 * coalescing the chunks of an indefinite-length string, 2)
1252 * allocating storage for every string returned when requested.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001253 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001254 * The first use is below in this function. Indefinite-length
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001255 * strings cannot be processed at all without a string allocator.
1256 *
1257 * The second used is in DecodeBytes() which is called by
1258 * GetNext_Item() below. This second use unneccessary for most use
1259 * and only happens when requested in the call to
1260 * QCBORDecode_SetMemPool(). If the second use not requested then
1261 * NULL is passed for the string allocator to GetNext_Item().
1262 *
1263 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1264 * allocator altogether and thus both of these uses. It reduced the
1265 * decoder object code by about 400 bytes.
1266 */
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001267 const QCBORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001268
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001269#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001270 const QCBORInternalAllocator *pAllocator = NULL;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001271
1272 if(pMe->StringAllocator.pfAllocator) {
1273 pAllocator = &(pMe->StringAllocator);
1274 if(pMe->bStringAllocateAll) {
1275 pAllocatorForGetNext = pAllocator;
1276 }
1277 }
1278#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1279
1280 QCBORError uReturn;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001281 uReturn = DecodeAtomicDataItem(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001282 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001283 goto Done;
1284 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001285
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001286 /* Only do indefinite-length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001287 const uint8_t uStringType = pDecodedItem->uDataType;
1288 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001289 goto Done;
1290 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001291
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001292 /* Is this a string with an indefinite length? */
1293 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1294 goto Done;
1295 }
1296
1297#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001298 /* Can't decode indefinite-length strings without a string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001299 if(pAllocator == NULL) {
1300 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1301 goto Done;
1302 }
1303
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001304 /* Loop getting chunks of the indefinite-length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001305 UsefulBufC FullString = NULLUsefulBufC;
1306
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001307 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001308 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001309 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001310 /* Pass a NULL string allocator to GetNext_Item() because the
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001311 * individual string chunks in an indefinite-length should not
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001312 * be allocated. They are always copied in the the contiguous
1313 * buffer allocated here.
1314 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001315 uReturn = DecodeAtomicDataItem(&(pMe->InBuf), &StringChunkItem, NULL);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001316 if(uReturn) {
1317 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001318 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001319
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001320 /* Is item is the marker for end of the indefinite-length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001321 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001322 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001323 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301324 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001325 break;
1326 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001327
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001328 /* All chunks must be of the same type, the type of the item
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001329 * that introduces the indefinite-length string. This also
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001330 * catches errors where the chunk is not a string at all and an
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001331 * indefinite-length string inside an indefinite-length string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001332 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001333 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001334 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1335 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001336 break;
1337 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001338
David Navarro9123e5b2022-03-28 16:04:03 +02001339 if (StringChunkItem.val.string.len > 0) {
1340 /* The first time throurgh FullString.ptr is NULL and this is
1341 * equivalent to StringAllocator_Allocate(). Subsequently it is
1342 * not NULL and a reallocation happens.
1343 */
1344 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1345 FullString.ptr,
1346 FullString.len + StringChunkItem.val.string.len);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001347
David Navarro9123e5b2022-03-28 16:04:03 +02001348 if(UsefulBuf_IsNULL(NewMem)) {
1349 uReturn = QCBOR_ERR_STRING_ALLOCATE;
1350 break;
1351 }
1352
1353 /* Copy new string chunk to the end of accumulated string */
1354 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001355 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001356 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001357
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001358 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1359 /* Getting the item failed, clean up the allocated memory */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001360 StringAllocator_Free(pAllocator, FullString.ptr);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001361 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001362#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1363 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1364#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001365
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001366Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001367 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001368}
1369
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001370
Laurence Lundblade37286c02022-09-03 10:05:02 -07001371#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001372/**
1373 * @brief This converts a tag number to a shorter mapped value for storage.
1374 *
1375 * @param[in] pMe The decode context.
1376 * @param[in] uUnMappedTag The tag number to map
1377 * @param[out] puMappedTagNumer The stored tag number.
1378 *
1379 * @return error code.
1380 *
1381 * The main point of mapping tag numbers is make QCBORItem
1382 * smaller. With this mapping storage of 4 tags takes up 8
1383 * bytes. Without, it would take up 32 bytes.
1384 *
1385 * This maps tag numbers greater than QCBOR_LAST_UNMAPPED_TAG.
1386 * QCBOR_LAST_UNMAPPED_TAG is a little smaller than MAX_UINT16.
1387 *
1388 * See also UnMapTagNumber() and @ref QCBORItem.
1389 */
1390static inline QCBORError
1391MapTagNumber(QCBORDecodeContext *pMe, uint64_t uUnMappedTag, uint16_t *puMappedTagNumer)
1392{
1393 if(uUnMappedTag > QCBOR_LAST_UNMAPPED_TAG) {
1394 unsigned uTagMapIndex;
1395 /* Is there room in the tag map, or is it in it already? */
1396 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
1397 if(pMe->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID64) {
1398 break;
1399 }
1400 if(pMe->auMappedTags[uTagMapIndex] == uUnMappedTag) {
1401 break;
1402 }
1403 }
1404 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1405 return QCBOR_ERR_TOO_MANY_TAGS;
1406 }
1407
1408 /* Covers the cases where tag is new and were it is already in the map */
1409 pMe->auMappedTags[uTagMapIndex] = uUnMappedTag;
1410 *puMappedTagNumer = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
1411
1412 } else {
1413 *puMappedTagNumer = (uint16_t)uUnMappedTag;
1414 }
1415
1416 return QCBOR_SUCCESS;
1417}
1418
1419
1420/**
1421 * @brief This converts a mapped tag number to the actual tag number.
1422 *
1423 * @param[in] pMe The decode context.
1424 * @param[in] uMappedTagNumber The stored tag number.
1425 *
1426 * @return The actual tag number is returned or
1427 * @ref CBOR_TAG_INVALID64 on error.
1428 *
1429 * This is the reverse of MapTagNumber()
1430 */
1431static uint64_t
1432UnMapTagNumber(const QCBORDecodeContext *pMe, uint16_t uMappedTagNumber)
1433{
1434 if(uMappedTagNumber <= QCBOR_LAST_UNMAPPED_TAG) {
1435 return uMappedTagNumber;
1436 } else if(uMappedTagNumber == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001437 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001438 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001439 /* This won't be negative because of code below in
1440 * MapTagNumber()
1441 */
1442 const unsigned uIndex = uMappedTagNumber - (QCBOR_LAST_UNMAPPED_TAG + 1);
1443 return pMe->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001444 }
1445}
Laurence Lundblade37286c02022-09-03 10:05:02 -07001446#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001447
Laurence Lundblade9b334962020-08-27 10:55:53 -07001448
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001449/**
1450 * @brief Aggregate all tags wrapping a data item (decode layer 4).
1451 *
1452 * @param[in] pMe Decoder context
1453 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001454
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001455 * @retval QCBOR_ERR_UNSUPPORTED
1456 * @retval QCBOR_ERR_HIT_END
1457 * @retval QCBOR_ERR_INT_OVERFLOW
1458 * @retval QCBOR_ERR_STRING_ALLOCATE
1459 * @retval QCBOR_ERR_STRING_TOO_LONG
1460 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001461 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001462 * @retval QCBOR_ERR_BAD_TYPE_7
1463 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1464 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1465 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1466 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1467 * @retval QCBOR_ERR_TOO_MANY_TAGS
1468 *
1469 * This loops getting atomic data items until one is not a tag
1470 * number. Usually this is largely pass-through because most
1471 * item are not tag numbers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001472 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001473static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001474QCBORDecode_GetNextTagNumber(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001475{
Laurence Lundblade37286c02022-09-03 10:05:02 -07001476#ifndef QCBOR_DISABLE_TAGS
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001477 /* Accummulate the tags from multiple items here and then copy them
1478 * into the last item, the non-tag item.
1479 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001480 uint16_t auItemsTags[QCBOR_MAX_TAGS_PER_ITEM];
1481
1482 /* Initialize to CBOR_TAG_INVALID16 */
1483 #if CBOR_TAG_INVALID16 != 0xffff
1484 /* Be sure the memset does the right thing. */
1485 #err CBOR_TAG_INVALID16 tag not defined as expected
1486 #endif
1487 memset(auItemsTags, 0xff, sizeof(auItemsTags));
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001488
Laurence Lundblade9b334962020-08-27 10:55:53 -07001489 QCBORError uReturn = QCBOR_SUCCESS;
1490
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001491 /* Loop fetching data items until the item fetched is not a tag */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001492 for(;;) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001493 QCBORError uErr = QCBORDecode_GetNextFullString(pMe, pDecodedItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07001494 if(uErr != QCBOR_SUCCESS) {
1495 uReturn = uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001496 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001497 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001498
Laurence Lundblade9b334962020-08-27 10:55:53 -07001499 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001500 /* Successful exit from loop; maybe got some tags, maybe not */
1501 memcpy(pDecodedItem->uTags, auItemsTags, sizeof(auItemsTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001502 break;
1503 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001504
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001505 if(auItemsTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1506 /* No room in the tag list */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001507 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001508 /* Continue on to get all tags wrapping this item even though
1509 * it is erroring out in the end. This allows decoding to
1510 * continue. This is a resource limit error, not a problem
1511 * with being well-formed CBOR.
1512 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001513 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001514 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001515 /* Slide tags over one in the array to make room at index 0.
1516 * Must use memmove because the move source and destination
1517 * overlap.
1518 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001519 memmove(&auItemsTags[1],
1520 auItemsTags,
1521 sizeof(auItemsTags) - sizeof(auItemsTags[0]));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001522
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001523 /* Map the tag */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001524 uint16_t uMappedTagNumber = 0;
1525 uReturn = MapTagNumber(pMe, pDecodedItem->val.uTagV, &uMappedTagNumber);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001526 /* Continue even on error so as to consume all tags wrapping
1527 * this data item so decoding can go on. If MapTagNumber()
1528 * errors once it will continue to error.
1529 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001530 auItemsTags[0] = uMappedTagNumber;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001531 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001532
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001533Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001534 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001535
Laurence Lundblade37286c02022-09-03 10:05:02 -07001536#else /* QCBOR_DISABLE_TAGS */
1537
1538 return QCBORDecode_GetNextFullString(pMe, pDecodedItem);
1539
1540#endif /* QCBOR_DISABLE_TAGS */
1541}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001542
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001543/**
1544 * @brief Combine a map entry label and value into one item (decode layer 3).
1545 *
1546 * @param[in] pMe Decoder context
1547 * @param[out] pDecodedItem The decoded item that work is done on.
1548 *
1549 * @retval QCBOR_ERR_UNSUPPORTED
1550 * @retval QCBOR_ERR_HIT_END
1551 * @retval QCBOR_ERR_INT_OVERFLOW
1552 * @retval QCBOR_ERR_STRING_ALLOCATE
1553 * @retval QCBOR_ERR_STRING_TOO_LONG
1554 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001555 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001556 * @retval QCBOR_ERR_BAD_TYPE_7
1557 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1558 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1559 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1560 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1561 * @retval QCBOR_ERR_TOO_MANY_TAGS
1562 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1563 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1564 *
1565 * If a the current nesting level is a map, then this
1566 * combines pairs of items into one data item with a label
1567 * and value.
1568 *
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07001569 * This is passthrough if the current nesting level is
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001570 * not a map.
1571 *
1572 * This also implements maps-as-array mode where a map
1573 * is treated like an array to allow caller to do their
1574 * own label processing.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001575 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001576static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001577QCBORDecode_GetNextMapEntry(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001578{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001579 QCBORError uReturn = QCBORDecode_GetNextTagNumber(pMe, pDecodedItem);
1580 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001581 goto Done;
1582 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001583
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001584 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
1585 /* Break can't be a map entry */
1586 goto Done;
1587 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001588
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001589 if(pMe->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1590 /* Normal decoding of maps -- combine label and value into one item. */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001591
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001592 if(DecodeNesting_IsCurrentTypeMap(&(pMe->nesting))) {
1593 /* Save label in pDecodedItem and get the next which will
1594 * be the real data item.
1595 */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001596 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001597 uReturn = QCBORDecode_GetNextTagNumber(pMe, pDecodedItem);
1598 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001599 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001600 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001601
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301602 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001603
1604 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001605 /* strings are always good labels */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001606 pDecodedItem->label.string = LabelItem.val.string;
1607 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001608 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == pMe->uDecodeMode) {
1609 /* It's not a string and we only want strings */
1610 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001611 goto Done;
1612 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1613 pDecodedItem->label.int64 = LabelItem.val.int64;
1614 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1615 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1616 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1617 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1618 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1619 pDecodedItem->label.string = LabelItem.val.string;
1620 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1621 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1622 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001623 /* label is not an int or a string. It is an arrray
1624 * or a float or such and this implementation doesn't handle that.
1625 * Also, tags on labels are ignored.
1626 */
1627 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001628 goto Done;
1629 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001630 }
1631 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001632 /* Decoding of maps as arrays to let the caller decide what to do
1633 * about labels, particularly lables that are not integers or
1634 * strings.
1635 */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001636 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001637 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001638 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001639 goto Done;
1640 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001641 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001642 /* Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2.
1643 * Cast is needed because of integer promotion.
1644 */
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001645 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001646 }
1647 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001648
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001649Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001650 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001651}
1652
1653
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001654#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001655/**
1656 * @brief Peek and see if next data item is a break;
1657 *
1658 * @param[in] pUIB UsefulInputBuf to read from.
1659 * @param[out] pbNextIsBreak Indicate if next was a break or not.
1660 *
1661 * @return Any decoding error.
1662 *
1663 * See if next item is a CBOR break. If it is, it is consumed,
1664 * if not it is not consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001665*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001666static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001667NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1668{
1669 *pbNextIsBreak = false;
1670 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001671 QCBORItem Peek;
1672 size_t uPeek = UsefulInputBuf_Tell(pUIB);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001673 QCBORError uReturn = DecodeAtomicDataItem(pUIB, &Peek, NULL);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001674 if(uReturn != QCBOR_SUCCESS) {
1675 return uReturn;
1676 }
1677 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001678 /* It is not a break, rewind so it can be processed normally. */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001679 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001680 } else {
1681 *pbNextIsBreak = true;
1682 }
1683 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001684
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001685 return QCBOR_SUCCESS;
1686}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001687#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001688
1689
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001690/**
1691 * @brief Ascend up nesting levels if all items in them have been consumed.
1692 *
1693 * @param[in] pMe The decode context.
1694 * @param[in] bMarkEnd If true mark end of maps/arrays with count of zero.
1695 *
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001696 * An item was just consumed, now figure out if it was the
1697 * end of an array/map map that can be closed out. That
1698 * may in turn close out the above array/map...
Laurence Lundblade642282a2020-06-23 12:00:33 -07001699*/
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001700static QCBORError
1701QCBORDecode_NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001702{
1703 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001704
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001705 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001706 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1707
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001708 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1709 /* Nesting level is bstr-wrapped CBOR */
1710
1711 /* Ascent for bstr-wrapped CBOR is always by explicit call
1712 * so no further ascending can happen.
1713 */
1714 break;
1715
1716 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1717 /* Level is a definite-length array/map */
1718
1719 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001720 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1721 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001722 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001723 break;
1724 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001725 /* All items in a definite-length array were consumed so it
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001726 * is time to ascend one level. This happens below.
1727 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001728
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001729#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001730 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001731 /* Level is an indefinite-length array/map. */
1732
1733 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001734 bool bIsBreak = false;
1735 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1736 if(uReturn != QCBOR_SUCCESS) {
1737 goto Done;
1738 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001739
1740 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001741 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001742 break;
1743 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001744
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001745 /* It was a break in an indefinitelength map / array so
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001746 * it is time to ascend one level.
1747 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001748
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001749#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001750 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001751
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001752
1753 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001754
Laurence Lundblade93d89472020-10-03 22:30:50 -07001755 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001756 * QCBORDecode_ExitBoundedMode().
1757 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001758 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001759 /* Set the count to zero for definite-length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001760 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001761 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001762 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001763 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001764
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001765 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001766 break;
1767 }
1768
1769 /* Finally, actually ascend one level. */
1770 DecodeNesting_Ascend(&(pMe->nesting));
1771 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001772
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001773 uReturn = QCBOR_SUCCESS;
1774
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001775#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001776Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001777#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1778
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001779 return uReturn;
1780}
1781
1782
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001783/**
1784 * @brief Ascending & Descending out of nesting levels (decode layer 2).
1785 *
1786 * @param[in] pMe Decoder context
1787 * @param[out] pDecodedItem The decoded item that work is done on.
1788 *
1789 * @retval QCBOR_ERR_UNSUPPORTED
1790 * @retval QCBOR_ERR_HIT_END
1791 * @retval QCBOR_ERR_INT_OVERFLOW
1792 * @retval QCBOR_ERR_STRING_ALLOCATE
1793 * @retval QCBOR_ERR_STRING_TOO_LONG
1794 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001795 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001796 * @retval QCBOR_ERR_BAD_TYPE_7
1797 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1798 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1799 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1800 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1801 * @retval QCBOR_ERR_TOO_MANY_TAGS
1802 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1803 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1804 * @retval QCBOR_ERR_NO_MORE_ITEMS
1805 * @retval QCBOR_ERR_BAD_BREAK
1806 * @retval QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
1807 *
1808 * This handles the traversal descending into and asecnding out of
1809 * maps, arrays and bstr-wrapped CBOR. It figures out the ends of
1810 * definite- and indefinte-length maps and arrays by looking at the
1811 * item count or finding CBOR breaks. It detects the ends of the
1812 * top-level sequence and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001813 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001814static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001815QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001816{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001817 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001818 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001819
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001820 /* If out of bytes to consume, it is either the end of the
1821 * top-level sequence of some bstr-wrapped CBOR that was entered.
1822 *
1823 * In the case of bstr-wrapped CBOR, the length of the
1824 * UsefulInputBuf was set to that of the bstr-wrapped CBOR. When
1825 * the bstr-wrapped CBOR is exited, the length is set back to the
1826 * top-level's length or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001827 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001828 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001829 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001830 goto Done;
1831 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001832
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001833 /* Check to see if at the end of a bounded definite-length map or
1834 * array. The check for a break ending indefinite-length array is
1835 * later in QCBORDecode_NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001836 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001837 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001838 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001839 goto Done;
1840 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001841
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001842 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001843 uReturn = QCBORDecode_GetNextMapEntry(pMe, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001844 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1845 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001846 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001847 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301848
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001849 /* Breaks ending arrays/maps are processed later in the call to
1850 * QCBORDecode_NestLevelAscender(). They should never show up here.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001851 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301852 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001853 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301854 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301855 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001856
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001857 /* Record the nesting level for this data item before processing
1858 * any of decrementing and descending.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001859 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001860 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001861
Laurence Lundblade642282a2020-06-23 12:00:33 -07001862
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001863 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001864 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001865 /* If the new item is a map or array, descend.
1866 *
1867 * Empty indefinite-length maps and arrays are descended into,
1868 * but then ascended out of in the next chunk of code.
1869 *
1870 * Maps and arrays do count as items in the map/array that
1871 * encloses them so a decrement needs to be done for them too,
1872 * but that is done only when all the items in them have been
1873 * processed, not when they are opened with the exception of an
1874 * empty map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001875 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001876 QCBORError uDescendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001877 uDescendErr = DecodeNesting_DescendMapOrArray(&(pMe->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001878 pDecodedItem->uDataType,
1879 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001880 if(uDescendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001881 /* This error is probably a traversal error and it overrides
1882 * the non-traversal error.
1883 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001884 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001885 goto Done;
1886 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001887 }
1888
Laurence Lundblade02625d42020-06-25 14:41:41 -07001889 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1890 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1891 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001892 /* The following cases are handled here:
1893 * - A non-aggregate item like an integer or string
1894 * - An empty definite-length map or array
1895 * - An indefinite-length map or array that might be empty or might not.
1896 *
1897 * QCBORDecode_NestLevelAscender() does the work of decrementing the count
1898 * for an definite-length map/array and break detection for an
1899 * indefinite-0length map/array. If the end of the map/array was
1900 * reached, then it ascends nesting levels, possibly all the way
1901 * to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001902 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001903 QCBORError uAscendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001904 uAscendErr = QCBORDecode_NestLevelAscender(pMe, true);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001905 if(uAscendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001906 /* This error is probably a traversal error and it overrides
1907 * the non-traversal error.
1908 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001909 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001910 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001911 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301912 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001913
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001914 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001915 /* Tell the caller what level is next. This tells them what
1916 * maps/arrays were closed out and makes it possible for them to
1917 * reconstruct the tree with just the information returned in a
1918 * QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001919 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001920 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001921 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001922 pDecodedItem->uNextNestLevel = 0;
1923 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001924 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001925 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001926
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001927Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001928 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001929}
1930
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001931
Laurence Lundblade37286c02022-09-03 10:05:02 -07001932#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001933/**
1934 * @brief Shift 0th tag out of the tag list.
1935 *
1936 * pDecodedItem[in,out] The data item to convert.
1937 *
1938 * The 0th tag is discarded. \ref CBOR_TAG_INVALID16 is
1939 * shifted into empty slot at the end of the tag list.
1940 */
1941static inline void ShiftTags(QCBORItem *pDecodedItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07001942{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001943 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM-1; i++) {
1944 pDecodedItem->uTags[i] = pDecodedItem->uTags[i+1];
1945 }
1946 pDecodedItem->uTags[QCBOR_MAX_TAGS_PER_ITEM-1] = CBOR_TAG_INVALID16;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001947}
1948
Laurence Lundblade37286c02022-09-03 10:05:02 -07001949#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001950
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001951/**
1952 * @brief Convert different epoch date formats in to the QCBOR epoch date format
1953 *
1954 * pDecodedItem[in,out] The data item to convert.
1955 *
1956 * @retval QCBOR_ERR_DATE_OVERFLOW
1957 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001958 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07001959 * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001960 *
1961 * The epoch date tag defined in QCBOR allows for floating-point
1962 * dates. It even allows a protocol to flop between date formats when
1963 * ever it wants. Floating-point dates aren't that useful as they are
1964 * only needed for dates beyond the age of the earth.
1965 *
1966 * This converts all the date formats into one format of an unsigned
1967 * integer plus a floating-point fraction.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001968 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001969static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001970{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001971 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001972
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001973#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade59289e52019-12-30 13:44:37 -08001974 pDecodedItem->val.epochDate.fSecondsFraction = 0;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001975#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001976
1977 switch (pDecodedItem->uDataType) {
1978
1979 case QCBOR_TYPE_INT64:
1980 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1981 break;
1982
1983 case QCBOR_TYPE_UINT64:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001984 /* This only happens for CBOR type 0 > INT64_MAX so it is
1985 * always an overflow.
1986 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07001987 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1988 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001989 break;
1990
1991 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001992 case QCBOR_TYPE_FLOAT:
1993#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001994 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001995 /* Convert working value to double if input was a float */
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001996 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001997 pDecodedItem->val.dfnum :
1998 (double)pDecodedItem->val.fnum;
1999
2000 /* The conversion from float to integer requires overflow
2001 * detection since floats can be much larger than integers.
2002 * This implementation errors out on these large float values
2003 * since they are beyond the age of the earth.
2004 *
2005 * These constants for the overflow check are computed by the
2006 * compiler. They are not computed at run time.
2007 *
2008 * The factor of 0x7ff is added/subtracted to avoid a
2009 * rounding error in the wrong direction when the compiler
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002010 * computes these constants. There is rounding because a
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002011 * 64-bit integer has 63 bits of precision where a double
2012 * only has 53 bits. Without the 0x7ff factor, the compiler
2013 * may round up and produce a double for the bounds check
2014 * that is larger than can be stored in a 64-bit integer. The
2015 * amount of 0x7ff is picked because it has 11 bits set.
2016 *
2017 * Without the 0x7ff there is a ~30 minute range of time
2018 * values 10 billion years in the past and in the future
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002019 * where this code could go wrong. Some compilers
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002020 * generate a warning or error without the 0x7ff.
2021 */
2022 const double dDateMax = (double)(INT64_MAX - 0x7ff);
2023 const double dDateMin = (double)(INT64_MIN + 0x7ff);
2024
2025 if(isnan(d) || d > dDateMax || d < dDateMin) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07002026 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002027 goto Done;
2028 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002029
2030 /* The actual conversion */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002031 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07002032 pDecodedItem->val.epochDate.fSecondsFraction =
2033 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002034 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002035#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade4b270642020-08-14 12:53:07 -07002036
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002037 uReturn = QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07002038 goto Done;
2039
Laurence Lundblade9682a532020-06-06 18:33:04 -07002040#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002041 break;
2042
2043 default:
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002044 /* It's the arrays and maps that are unrecoverable because
2045 * they are not consumed here. Since this is just an error
2046 * condition, no extra code is added here to make the error
2047 * recoverable for non-arrays and maps like strings. */
2048 uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002049 goto Done;
2050 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002051
Laurence Lundblade59289e52019-12-30 13:44:37 -08002052 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
2053
2054Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07002055 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002056}
2057
2058
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002059/**
2060 * @brief Convert the days epoch date.
2061 *
2062 * pDecodedItem[in,out] The data item to convert.
2063 *
2064 * @retval QCBOR_ERR_DATE_OVERFLOW
2065 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002066 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002067 * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002068 *
2069 * This is much simpler than the other epoch date format because
2070 * floating-porint is not allowed. This is mostly a simple type check.
2071 */
2072static QCBORError DecodeDaysEpoch(QCBORItem *pDecodedItem)
2073{
2074 QCBORError uReturn = QCBOR_SUCCESS;
2075
2076 switch (pDecodedItem->uDataType) {
2077
2078 case QCBOR_TYPE_INT64:
2079 pDecodedItem->val.epochDays = pDecodedItem->val.int64;
2080 break;
2081
2082 case QCBOR_TYPE_UINT64:
2083 /* This only happens for CBOR type 0 > INT64_MAX so it is
2084 * always an overflow.
2085 */
2086 uReturn = QCBOR_ERR_DATE_OVERFLOW;
2087 goto Done;
2088 break;
2089
2090 default:
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002091 /* It's the arrays and maps that are unrecoverable because
2092 * they are not consumed here. Since this is just an error
2093 * condition, no extra code is added here to make the error
2094 * recoverable for non-arrays and maps like strings. */
2095 uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002096 goto Done;
2097 break;
2098 }
2099
2100 pDecodedItem->uDataType = QCBOR_TYPE_DAYS_EPOCH;
2101
2102Done:
2103 return uReturn;
2104}
2105
2106
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002107#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade37286c02022-09-03 10:05:02 -07002108
2109/* Forward declaration is necessary for
2110 * QCBORDecode_MantissaAndExponent(). to be able to decode bignum
2111 * tags in the mantissa. If the mantissa is a decimal fraction or big
2112 * float in error, this will result in a recurive call to
2113 * QCBORDecode_MantissaAndExponent(), but the recursion will unwined
2114 * correctly and the correct error is returned.
2115 */
2116static QCBORError
2117QCBORDecode_GetNextTagContent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem);
2118
2119
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002120/**
2121 * @brief Decode decimal fractions and big floats.
2122 *
2123 * @param[in] pMe The decode context.
2124 * @param[in,out] pDecodedItem On input the array data item that
2125 * holds the mantissa and exponent. On
2126 * output the decoded mantissa and
2127 * exponent.
2128 *
2129 * @returns Decoding errors from getting primitive data items or
2130 * \ref QCBOR_ERR_BAD_EXP_AND_MANTISSA.
2131 *
Laurence Lundblade37286c02022-09-03 10:05:02 -07002132 * When called pDecodedItem must be the array with two members, the
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002133 * exponent and mantissa.
2134 *
2135 * This will fetch and decode the exponent and mantissa and put the
2136 * result back into pDecodedItem.
Laurence Lundblade37286c02022-09-03 10:05:02 -07002137 *
2138 * This does no checking or processing of tag numbers. That is to be
2139 * done by the code that calls this.
2140 *
2141 * This stuffs the type of the mantissa into pDecodedItem with the expectation
2142 * the caller will process it.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002143 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07002144static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002145QCBORDecode_MantissaAndExponent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002146{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002147 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002148
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002149 /* --- Make sure it is an array; track nesting level of members --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002150 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002151 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002152 goto Done;
2153 }
2154
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002155 /* A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundblade37286c02022-09-03 10:05:02 -07002156 * definite-length arrays, but not for indefinite. Instead remember
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002157 * the nesting level the two integers must be at, which is one
2158 * deeper than that of the array.
2159 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002160 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
2161
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002162 /* --- Get the exponent --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002163 QCBORItem exponentItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002164 uReturn = QCBORDecode_GetNextMapOrArray(pMe, &exponentItem);
2165 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002166 goto Done;
2167 }
2168 if(exponentItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002169 /* Array is empty or a map/array encountered when expecting an int */
2170 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002171 goto Done;
2172 }
2173 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002174 /* Data arriving as an unsigned int < INT64_MAX has been
2175 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2176 * also means that the only data arriving here of type
2177 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2178 * and thus an error that will get handled in the next else.
2179 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002180 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
2181 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002182 /* Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX */
2183 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002184 goto Done;
2185 }
2186
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002187 /* --- Get the mantissa --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002188 QCBORItem mantissaItem;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002189 uReturn = QCBORDecode_GetNextTagContent(pMe, &mantissaItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002190 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002191 goto Done;
2192 }
2193 if(mantissaItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002194 /* Mantissa missing or map/array encountered when expecting number */
2195 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002196 goto Done;
2197 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002198 /* Stuff the mantissa data type into the item to send it up to the
2199 * the next level. */
2200 pDecodedItem->uDataType = mantissaItem.uDataType;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002201 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002202 /* Data arriving as an unsigned int < INT64_MAX has been
2203 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2204 * also means that the only data arriving here of type
2205 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2206 * and thus an error that will get handled in an else below.
2207 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002208 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002209#ifndef QCBOR_DISABLE_TAGS
2210 /* With tags fully disabled a big number mantissa will error out
2211 * in the call to QCBORDecode_GetNextWithTags() because it has
2212 * a tag number.
2213 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002214 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
2215 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002216 /* Got a good big num mantissa */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002217 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002218#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002219 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002220 /* Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX */
2221 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002222 goto Done;
2223 }
2224
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002225 /* --- Check that array only has the two numbers --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002226 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002227 /* Extra items in the decimal fraction / big float */
Laurence Lundblade37286c02022-09-03 10:05:02 -07002228 /* Improvement: this should probably be an unrecoverable error. */
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 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002232 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002233
2234Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002235 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002236}
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002237#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002238
2239
Laurence Lundblade37286c02022-09-03 10:05:02 -07002240#ifndef QCBOR_DISABLE_TAGS
2241
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002242#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002243/**
2244 * @brief Decode the MIME type tag
2245 *
2246 * @param[in,out] pDecodedItem The item to decode.
2247 *
2248 * Handle the text and binary MIME type tags. Slightly too complicated
2249 * f or ProcessTaggedString() because the RFC 7049 MIME type was
2250 * incorreclty text-only.
2251 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002252static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002253{
2254 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
2255 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07002256 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002257 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
2258 } else {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002259 /* It's the arrays and maps that are unrecoverable because
2260 * they are not consumed here. Since this is just an error
2261 * condition, no extra code is added here to make the error
2262 * recoverable for non-arrays and maps like strings. */
2263 return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002264 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002265
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002266 return QCBOR_SUCCESS;
2267}
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002268#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002269
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002270/**
Laurence Lundblade99615302020-11-29 11:19:47 -08002271 * Table of CBOR tags whose content is either a text string or a byte
2272 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
2273 * of uQCBORtype indicates the content should be a byte string rather
2274 * than a text string
2275 */
2276struct StringTagMapEntry {
2277 uint16_t uTagNumber;
2278 uint8_t uQCBORtype;
2279};
2280
2281#define IS_BYTE_STRING_BIT 0x80
2282#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
2283
2284static const struct StringTagMapEntry StringTagMap[] = {
2285 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002286 {CBOR_TAG_DAYS_STRING, QCBOR_TYPE_DAYS_STRING},
Laurence Lundblade99615302020-11-29 11:19:47 -08002287 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
2288 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
2289 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
2290 {CBOR_TAG_URI, QCBOR_TYPE_URI},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002291#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002292 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
2293 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
2294 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
2295 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002296#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade99615302020-11-29 11:19:47 -08002297 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
2298 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
2299};
2300
2301
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002302/**
2303 * @brief Process standard CBOR tags whose content is a string
2304 *
2305 * @param[in] uTag The tag.
2306 * @param[in,out] pDecodedItem The data item.
2307 *
2308 * @returns This returns QCBOR_SUCCESS if the tag was procssed,
2309 * \ref QCBOR_ERR_UNSUPPORTED if the tag was not processed and
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002310 * \ref QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT if the content type was wrong for the tag.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002311 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002312 * Process the CBOR tags that whose content is a byte string or a text
2313 * string and for which the string is just passed on to the caller.
2314 *
2315 * This maps the CBOR tag to the QCBOR type and checks the content
2316 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08002317 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08002318 * possible.
Laurence Lundblade99615302020-11-29 11:19:47 -08002319 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002320static inline QCBORError
2321ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002322{
Laurence Lundblade99615302020-11-29 11:19:47 -08002323 /* This only works on tags that were not mapped; no need for other yet */
2324 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
2325 return QCBOR_ERR_UNSUPPORTED;
2326 }
2327
2328 unsigned uIndex;
2329 for(uIndex = 0; StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
2330 if(StringTagMap[uIndex].uTagNumber == uTag) {
2331 break;
2332 }
2333 }
2334
2335 const uint8_t uQCBORType = StringTagMap[uIndex].uQCBORtype;
2336 if(uQCBORType == QCBOR_TYPE_NONE) {
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002337 /* repurpose this error to mean not handled here */
Laurence Lundblade99615302020-11-29 11:19:47 -08002338 return QCBOR_ERR_UNSUPPORTED;
2339 }
2340
2341 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
2342 if(uQCBORType & IS_BYTE_STRING_BIT) {
2343 uExpectedType = QCBOR_TYPE_BYTE_STRING;
2344 }
2345
2346 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002347 /* It's the arrays and maps that are unrecoverable because
2348 * they are not consumed here. Since this is just an error
2349 * condition, no extra code is added here to make the error
2350 * recoverable for non-arrays and maps like strings. */
2351 return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002352 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002353
Laurence Lundblade99615302020-11-29 11:19:47 -08002354 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002355 return QCBOR_SUCCESS;
2356}
Laurence Lundblade37286c02022-09-03 10:05:02 -07002357#endif /* QCBOR_DISABLE_TAGS */
2358
2359
2360#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
2361/*
2362 * This returns the QCBOR_TYPE for a mantissa and exponent.
2363
2364Called in one context where there is always a tag
2365
2366 Called in another context where there might be a tag or the caller might say what they are expecting.
2367
2368 6 possible outputs
2369 */
2370static inline uint8_t
2371MantissaExponentDataType(const uint16_t uTagToProcess, const QCBORItem *pDecodedItem)
2372{
2373 uint8_t uBase = uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ?
2374 QCBOR_TYPE_DECIMAL_FRACTION :
2375 QCBOR_TYPE_BIGFLOAT;
2376 if(pDecodedItem->uDataType != QCBOR_TYPE_INT64) {
2377 uBase = (uint8_t)(uBase + pDecodedItem->uDataType - QCBOR_TYPE_POSBIGNUM + 1);
2378 }
2379 return uBase;
2380}
2381#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002382
2383
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002384/**
2385 * @brief Decode tag content for select tags (decoding layer 1).
2386 *
2387 * @param[in] pMe The decode context.
2388 * @param[out] pDecodedItem The decoded item.
2389 *
2390 * @return Decoding error code.
2391 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002392 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
2393 * but the whole tag was not decoded. Here, the whole tags (tag number
2394 * and tag content) that are supported by QCBOR are decoded. This is a
2395 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002396 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002397static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002398QCBORDecode_GetNextTagContent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002399{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002400 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002401
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002402 uReturn = QCBORDecode_GetNextMapOrArray(pMe, pDecodedItem);
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002403 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002404 goto Done;
2405 }
2406
Laurence Lundblade37286c02022-09-03 10:05:02 -07002407#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002408 /* When there are no tag numbers for the item, this exits first
2409 * thing and effectively does nothing.
2410 *
2411 * This loops over all the tag numbers accumulated for this item
2412 * trying to decode and interpret them. This stops at the end of
2413 * the list or at the first tag number that can't be interpreted by
2414 * this code. This is effectively a recursive processing of the
2415 * tags number list that handles nested tags.
2416 */
2417 while(1) {
2418 /* Don't bother to unmap tags via QCBORITem.uTags since this
2419 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2420 */
2421 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002422
Laurence Lundblade99615302020-11-29 11:19:47 -08002423 if(uTagToProcess == CBOR_TAG_INVALID16) {
2424 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002425 break;
2426
Laurence Lundblade99615302020-11-29 11:19:47 -08002427 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002428 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002429
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002430 } else if(uTagToProcess == CBOR_TAG_DAYS_EPOCH) {
2431 uReturn = DecodeDaysEpoch(pDecodedItem);
2432
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002433#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002434 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2435 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002436 uReturn = QCBORDecode_MantissaAndExponent(pMe, pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07002437 /* --- Which is it, decimal fraction or a bigfloat? --- */
2438 pDecodedItem->uDataType = MantissaExponentDataType(uTagToProcess, pDecodedItem);
2439
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002440#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002441#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002442 } else if(uTagToProcess == CBOR_TAG_MIME ||
2443 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002444 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002445#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002446
Laurence Lundblade99615302020-11-29 11:19:47 -08002447 } else {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002448 /* See if it is a passthrough byte/text string tag; process if so */
Laurence Lundblade99615302020-11-29 11:19:47 -08002449 uReturn = ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002450
Laurence Lundblade99615302020-11-29 11:19:47 -08002451 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002452 /* It wasn't a passthrough byte/text string tag so it is
Laurence Lundblade99615302020-11-29 11:19:47 -08002453 * an unknown tag. This is the exit from the loop on the
2454 * first unknown tag. It is a successful exit.
2455 */
2456 uReturn = QCBOR_SUCCESS;
2457 break;
2458 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002459 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002460
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002461 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002462 /* Error exit from the loop */
2463 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002464 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002465
2466 /* A tag was successfully processed, shift it out of the list of
2467 * tags returned. This is the loop increment.
2468 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002469 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002470 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002471#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002472
2473Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002474 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002475}
2476
2477
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002478/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002479 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002480 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002481QCBORError
2482QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2483{
2484 QCBORError uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002485 uErr = QCBORDecode_GetNextTagContent(pMe, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002486 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002487 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2488 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2489 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002490 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002491}
2492
2493
2494/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002495 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002496 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002497QCBORError
2498QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2499{
2500 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2501 const UsefulInputBuf Save = pMe->InBuf;
2502
2503 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2504
2505 pMe->nesting = SaveNesting;
2506 pMe->InBuf = Save;
2507
2508 return uErr;
2509}
2510
2511
2512/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002513 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002514 */
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002515void
2516QCBORDecode_VPeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2517{
2518 if(pMe->uLastError != QCBOR_SUCCESS) {
2519 return;
2520 }
2521
2522 pMe->uLastError = (uint8_t)QCBORDecode_PeekNext(pMe, pDecodedItem);
2523}
2524
2525
2526/*
2527 * Public function, see header qcbor/qcbor_decode.h file
2528 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002529void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2530{
2531 if(pMe->uLastError != QCBOR_SUCCESS) {
2532 return;
2533 }
2534
2535 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2536}
2537
2538
2539/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002540 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002541 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002542QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002543QCBORDecode_GetNextWithTags(QCBORDecodeContext *pMe,
2544 QCBORItem *pDecodedItem,
2545 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002546{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002547#ifndef QCBOR_DISABLE_TAGS
2548
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002549 QCBORError uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002550
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002551 uReturn = QCBORDecode_GetNext(pMe, pDecodedItem);
2552 if(uReturn != QCBOR_SUCCESS) {
2553 return uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002554 }
2555
2556 if(pTags != NULL) {
2557 pTags->uNumUsed = 0;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002558 /* Reverse the order because pTags is reverse of QCBORItem.uTags. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002559 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2560 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002561 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002562 }
2563 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2564 return QCBOR_ERR_TOO_MANY_TAGS;
2565 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002566 pTags->puTags[pTags->uNumUsed] = UnMapTagNumber(pMe,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002567 pTags->uNumUsed++;
2568 }
2569 }
2570
2571 return QCBOR_SUCCESS;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002572
2573#else /* QCBOR_DISABLE_TAGS */
2574 (void)pMe;
2575 (void)pDecodedItem;
2576 (void)pTags;
2577 return QCBOR_ERR_TAGS_DISABLED;
2578#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002579}
2580
2581
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002582/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002583 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302584 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002585bool QCBORDecode_IsTagged(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002586 const QCBORItem *pItem,
2587 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002588{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002589#ifndef QCBOR_DISABLE_TAGS
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002590 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2591 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002592 break;
2593 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002594 if(UnMapTagNumber(pMe, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002595 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002596 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002597 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002598#else /* QCBOR_TAGS_DISABLED */
2599 (void)pMe;
2600 (void)pItem;
2601 (void)uTag;
2602#endif /* QCBOR_TAGS_DISABLED */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002603
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002604 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002605}
2606
2607
2608/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002609 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002610 */
Laurence Lundblade87495732021-02-26 10:05:55 -07002611QCBORError QCBORDecode_PartialFinish(QCBORDecodeContext *pMe, size_t *puConsumed)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002612{
Laurence Lundblade87495732021-02-26 10:05:55 -07002613 if(puConsumed != NULL) {
2614 *puConsumed = pMe->InBuf.cursor;
2615 }
2616
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002617 QCBORError uReturn = pMe->uLastError;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002618
2619 if(uReturn != QCBOR_SUCCESS) {
2620 goto Done;
2621 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002622
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002623 /* Error out if all the maps/arrays are not closed out */
2624 if(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002625 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002626 goto Done;
2627 }
2628
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002629 /* Error out if not all the bytes are consumed */
2630 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002631 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002632 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002633
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002634Done:
Laurence Lundblade87495732021-02-26 10:05:55 -07002635 return uReturn;
2636}
2637
2638
2639/*
2640 * Public function, see header qcbor/qcbor_decode.h file
2641 */
2642QCBORError QCBORDecode_Finish(QCBORDecodeContext *pMe)
2643{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002644#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002645 /* Call the destructor for the string allocator if there is one.
2646 * Always called, even if there are errors; always have to clean up.
2647 */
2648 StringAllocator_Destruct(&(pMe->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002649#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002650
Laurence Lundblade87495732021-02-26 10:05:55 -07002651 return QCBORDecode_PartialFinish(pMe, NULL);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002652}
2653
2654
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002655/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002656 * Public function, see header qcbor/qcbor_decode.h file
2657 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002658// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002659uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2660 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002661 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002662{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002663#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002664 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2665 return CBOR_TAG_INVALID64;
2666 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002667 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2668 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002669 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002670 return UnMapTagNumber(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002671 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002672#else /* QCBOR_DISABLE_TAGS */
2673 (void)pMe;
2674 (void)pItem;
2675 (void)uIndex;
2676
2677 return CBOR_TAG_INVALID64;
2678#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002679}
2680
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002681
Laurence Lundblade9b334962020-08-27 10:55:53 -07002682/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002683 * Public function, see header qcbor/qcbor_decode.h file
2684 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002685uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2686 uint32_t uIndex)
2687{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002688#ifndef QCBOR_DISABLE_TAGS
2689
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002690 if(pMe->uLastError != QCBOR_SUCCESS) {
2691 return CBOR_TAG_INVALID64;
2692 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002693 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2694 return CBOR_TAG_INVALID64;
2695 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002696 return UnMapTagNumber(pMe, pMe->uLastTags[uIndex]);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002697 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002698#else /* QCBOR_DISABLE_TAGS */
2699 (void)pMe;
2700 (void)uIndex;
2701
2702 return CBOR_TAG_INVALID64;
2703#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002704}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002705
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002706
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002707
2708
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002709#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002710
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002711/* ===========================================================================
2712 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002713
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002714 This implements a simple sting allocator for indefinite-length
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002715 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2716 implements the function type QCBORStringAllocate and allows easy
2717 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002718
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002719 This particular allocator is built-in for convenience. The caller
2720 can implement their own. All of this following code will get
2721 dead-stripped if QCBORDecode_SetMemPool() is not called.
2722
2723 This is a very primitive memory allocator. It does not track
2724 individual allocations, only a high-water mark. A free or
2725 reallocation must be of the last chunk allocated.
2726
2727 The size of the pool and offset to free memory are packed into the
2728 first 8 bytes of the memory pool so we don't have to keep them in
2729 the decode context. Since the address of the pool may not be
2730 aligned, they have to be packed and unpacked as if they were
2731 serialized data of the wire or such.
2732
2733 The sizes packed in are uint32_t to be the same on all CPU types
2734 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002735 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002736
2737
Laurence Lundbladeee851742020-01-08 08:37:05 -08002738static inline int
2739MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002740{
2741 // Use of UsefulInputBuf is overkill, but it is convenient.
2742 UsefulInputBuf UIB;
2743
Laurence Lundbladeee851742020-01-08 08:37:05 -08002744 // Just assume the size here. It was checked during SetUp so
2745 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002746 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002747 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2748 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2749 return UsefulInputBuf_GetError(&UIB);
2750}
2751
2752
Laurence Lundbladeee851742020-01-08 08:37:05 -08002753static inline int
2754MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002755{
2756 // Use of UsefulOutBuf is overkill, but convenient. The
2757 // length check performed here is useful.
2758 UsefulOutBuf UOB;
2759
2760 UsefulOutBuf_Init(&UOB, Pool);
2761 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2762 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2763 return UsefulOutBuf_GetError(&UOB);
2764}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002765
2766
2767/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002768 Internal function for an allocation, reallocation free and destuct.
2769
2770 Having only one function rather than one each per mode saves space in
2771 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002772
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002773 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2774 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002775static UsefulBuf
2776MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002777{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002778 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002779
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002780 uint32_t uPoolSize;
2781 uint32_t uFreeOffset;
2782
2783 if(uNewSize > UINT32_MAX) {
2784 // This allocator is only good up to 4GB. This check should
2785 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2786 goto Done;
2787 }
2788 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2789
2790 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2791 goto Done;
2792 }
2793
2794 if(uNewSize) {
2795 if(pMem) {
2796 // REALLOCATION MODE
2797 // Calculate pointer to the end of the memory pool. It is
2798 // assumed that pPool + uPoolSize won't wrap around by
2799 // assuming the caller won't pass a pool buffer in that is
2800 // not in legitimate memory space.
2801 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2802
2803 // Check that the pointer for reallocation is in the range of the
2804 // pool. This also makes sure that pointer math further down
2805 // doesn't wrap under or over.
2806 if(pMem >= pPool && pMem < pPoolEnd) {
2807 // Offset to start of chunk for reallocation. This won't
2808 // wrap under because of check that pMem >= pPool. Cast
2809 // is safe because the pool is always less than UINT32_MAX
2810 // because of check in QCBORDecode_SetMemPool().
2811 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2812
2813 // Check to see if the allocation will fit. uPoolSize -
2814 // uMemOffset will not wrap under because of check that
2815 // pMem is in the range of the uPoolSize by check above.
2816 if(uNewSize <= uPoolSize - uMemOffset) {
2817 ReturnValue.ptr = pMem;
2818 ReturnValue.len = uNewSize;
2819
2820 // Addition won't wrap around over because uNewSize was
2821 // checked to be sure it is less than the pool size.
2822 uFreeOffset = uMemOffset + uNewSize32;
2823 }
2824 }
2825 } else {
2826 // ALLOCATION MODE
2827 // uPoolSize - uFreeOffset will not underflow because this
2828 // pool implementation makes sure uFreeOffset is always
2829 // smaller than uPoolSize through this check here and
2830 // reallocation case.
2831 if(uNewSize <= uPoolSize - uFreeOffset) {
2832 ReturnValue.len = uNewSize;
2833 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002834 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002835 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002836 }
2837 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002838 if(pMem) {
2839 // FREE MODE
2840 // Cast is safe because of limit on pool size in
2841 // QCBORDecode_SetMemPool()
2842 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2843 } else {
2844 // DESTRUCT MODE
2845 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002846 }
2847 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002848
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002849 UsefulBuf Pool = {pPool, uPoolSize};
2850 MemPool_Pack(Pool, uFreeOffset);
2851
2852Done:
2853 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002854}
2855
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002856
Laurence Lundbladef6531662018-12-04 10:42:22 +09002857/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002858 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002859 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002860QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2861 UsefulBuf Pool,
2862 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002863{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002864 // The pool size and free mem offset are packed into the beginning
Dave Thaler93c01182022-08-06 15:08:35 -04002865 // of the pool memory. This compile time check makes sure the
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002866 // constant in the header is correct. This check should optimize
2867 // down to nothing.
Dave Thaler93c01182022-08-06 15:08:35 -04002868#ifdef _MSC_VER
2869#pragma warning(push)
2870#pragma warning(disable:4127) // conditional expression is constant
2871#endif
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002872 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002873 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002874 }
Dave Thaler93c01182022-08-06 15:08:35 -04002875#ifdef _MSC_VER
2876#pragma warning(pop)
2877#endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002878
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002879 // The pool size and free offset packed in to the beginning of pool
2880 // memory are only 32-bits. This check will optimize out on 32-bit
2881 // machines.
2882 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002883 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002884 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002885
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002886 // This checks that the pool buffer given is big enough.
2887 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002888 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002889 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002890
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002891 QCBORDecode_SetUpAllocator(pMe, MemPool_Function, Pool.ptr, bAllStrings);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002892
Laurence Lundblade30816f22018-11-10 13:40:22 +07002893 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002894}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002895#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002896
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002897
2898
Laurence Lundblade37286c02022-09-03 10:05:02 -07002899static inline void
2900CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002901{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002902#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade9b334962020-08-27 10:55:53 -07002903 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
Laurence Lundblade37286c02022-09-03 10:05:02 -07002904#else
2905 (void)pMe;
2906 (void)pItem;
2907#endif
Laurence Lundblade9b334962020-08-27 10:55:53 -07002908}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002909
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002910
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002911/**
2912 * @brief Consume an entire map or array including its contents.
2913 *
2914 * @param[in] pMe The decoder context.
2915 * @param[in] pItemToConsume The array/map whose contents are to be
2916 * consumed.
2917 * @param[out] puNextNestLevel The next nesting level after the item was
2918 * fully consumed.
2919 *
2920 * This may be called when @c pItemToConsume is not an array or
2921 * map. In that case, this is just a pass through for @c puNextNestLevel
2922 * since there is nothing to do.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002923 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002924static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002925ConsumeItem(QCBORDecodeContext *pMe,
2926 const QCBORItem *pItemToConsume,
Máté Tóth-Pál2f2aa5f2021-05-17 21:35:09 +02002927 uint8_t *puNextNestLevel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002928{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002929 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002930 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002931
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002932 /* If it is a map or array, this will tell if it is empty. */
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002933 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2934
2935 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2936 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002937
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002938 /* This works for definite- and indefinite-length maps and
2939 * arrays by using the nesting level
Laurence Lundblade1341c592020-04-11 14:19:05 -07002940 */
2941 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002942 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002943 if(QCBORDecode_IsUnrecoverableError(uReturn) ||
2944 uReturn == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002945 goto Done;
2946 }
2947 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002948
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002949 *puNextNestLevel = Item.uNextNestLevel;
2950
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002951 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002952
Laurence Lundblade1341c592020-04-11 14:19:05 -07002953 } else {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002954 /* pItemToConsume is not a map or array. Just pass the nesting
2955 * level through. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002956 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2957
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002958 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002959 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002960
2961Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002962 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002963}
2964
Laurence Lundblade732e52d2021-02-22 20:11:01 -07002965
2966void QCBORDecode_VGetNextConsume(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2967{
Laurence Lundblade732e52d2021-02-22 20:11:01 -07002968 QCBORDecode_VGetNext(pMe, pDecodedItem);
2969
2970 if(pMe->uLastError == QCBOR_SUCCESS) {
Máté Tóth-Pálc6d59682021-05-26 18:55:30 +02002971 pMe->uLastError = (uint8_t)ConsumeItem(pMe, pDecodedItem,
2972 &pDecodedItem->uNextNestLevel);
Laurence Lundblade732e52d2021-02-22 20:11:01 -07002973 }
2974}
2975
2976
2977
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002978/* Call only on maps and arrays. Rewinds the cursor
2979 * to the start as if it was just entered.
2980 */
2981static void RewindMapOrArray(QCBORDecodeContext *pMe)
2982{
2983 /* Reset nesting tracking to the deepest bounded level */
2984 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
2985
2986 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
2987
2988 /* Reposition traversal cursor to the start of the map/array */
2989 UsefulInputBuf_Seek(&(pMe->InBuf),
2990 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
2991}
2992
2993
2994/*
2995 Public function, see header qcbor/qcbor_decode.h file
2996 */
2997void QCBORDecode_Rewind(QCBORDecodeContext *pMe)
2998{
2999 if(pMe->nesting.pCurrentBounded != NULL) {
3000 /* In a bounded map, array or bstr-wrapped CBOR */
3001
3002 if(DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
3003 /* In bstr-wrapped CBOR. */
3004
3005 /* Reposition traversal cursor to start of wrapping byte string */
3006 UsefulInputBuf_Seek(&(pMe->InBuf),
3007 pMe->nesting.pCurrentBounded->u.bs.uBstrStartOffset);
3008 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
3009
3010 } else {
3011 /* In a map or array */
3012 RewindMapOrArray(pMe);
3013 }
3014
3015 } else {
3016 /* Not in anything bounded */
3017
3018 /* Reposition traversal cursor to the start of input CBOR */
3019 UsefulInputBuf_Seek(&(pMe->InBuf), 0ULL);
3020
3021 /* Reset nesting tracking to beginning of input. */
3022 DecodeNesting_Init(&(pMe->nesting));
3023 }
3024
3025 pMe->uLastError = QCBOR_SUCCESS;
3026}
3027
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003028
Laurence Lundblade1341c592020-04-11 14:19:05 -07003029/* Return true if the labels in Item1 and Item2 are the same.
3030 Works only for integer and string labels. Returns false
3031 for any other type. */
3032static inline bool
3033MatchLabel(QCBORItem Item1, QCBORItem Item2)
3034{
3035 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
3036 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
3037 return true;
3038 }
3039 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003040 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003041 return true;
3042 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003043 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07003044 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
3045 return true;
3046 }
3047 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
3048 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
3049 return true;
3050 }
3051 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003052
Laurence Lundblade1341c592020-04-11 14:19:05 -07003053 /* Other label types are never matched */
3054 return false;
3055}
3056
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003057
3058/*
3059 Returns true if Item1 and Item2 are the same type
3060 or if either are of QCBOR_TYPE_ANY.
3061 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003062static inline bool
3063MatchType(QCBORItem Item1, QCBORItem Item2)
3064{
3065 if(Item1.uDataType == Item2.uDataType) {
3066 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003067 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003068 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003069 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003070 return true;
3071 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003072 return false;
3073}
3074
3075
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003076/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003077 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003078
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003079 @param[in] pMe The decode context to search.
3080 @param[in,out] pItemArray The items to search for and the items found.
3081 @param[out] puOffset Byte offset of last item matched.
3082 @param[in] pCBContext Context for the not-found item call back.
3083 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003084
3085 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
3086
Laurence Lundblade93d89472020-10-03 22:30:50 -07003087 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
3088 were found for one of the labels being
3089 search for. This duplicate detection is
3090 only performed for items in pItemArray,
3091 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003092
Laurence Lundblade93d89472020-10-03 22:30:50 -07003093 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
3094 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003095
3096 @retval Also errors returned by QCBORDecode_GetNext().
3097
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003098 On input pItemArray contains a list of labels and data types
3099 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07003100
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003101 On output the fully retrieved items are filled in with
3102 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07003103
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003104 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003105
3106 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003107 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003108static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003109MapSearch(QCBORDecodeContext *pMe,
3110 QCBORItem *pItemArray,
3111 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003112 void *pCBContext,
3113 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003114{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003115 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003116 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07003117
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003118 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003119 uReturn = pMe->uLastError;
3120 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003121 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003122
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003123 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003124 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
3125 /* QCBOR_TYPE_NONE as first item indicates just looking
3126 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003127 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
3128 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003129 }
3130
Laurence Lundblade085d7952020-07-24 10:26:30 -07003131 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
3132 // It is an empty bounded array or map
3133 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
3134 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003135 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07003136 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003137 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003138 // Nothing is ever found in an empty array or map. All items
3139 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07003140 uReturn = QCBOR_SUCCESS;
3141 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003142 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003143 }
3144
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003145 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003146 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
3147
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003148 /* Reposition to search from the start of the map / array */
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003149 RewindMapOrArray(pMe);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003150
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003151 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003152 Loop over all the items in the map or array. Each item
3153 could be a map or array, but label matching is only at
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003154 the main level. This handles definite- and indefinite-
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003155 length maps and arrays. The only reason this is ever
3156 called on arrays is to find their end position.
3157
3158 This will always run over all items in order to do
3159 duplicate detection.
3160
3161 This will exit with failure if it encounters an
3162 unrecoverable error, but continue on for recoverable
3163 errors.
3164
3165 If a recoverable error occurs on a matched item, then
3166 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003167 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07003168 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Máté Tóth-Pál2f2aa5f2021-05-17 21:35:09 +02003169 uint8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003170 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003171 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07003172 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003173
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003174 /* Get the item */
3175 QCBORItem Item;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003176 QCBORError uResult = QCBORDecode_GetNextTagContent(pMe, &Item);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003177 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003178 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003179 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003180 goto Done;
3181 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003182 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003183 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003184 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003185 goto Done;
3186 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003187
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003188 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003189 bool bMatched = false;
3190 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
3191 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003192 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003193 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
3194 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003195 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003196 }
Laurence Lundblade63926052021-03-29 16:05:51 -07003197 if(uResult != QCBOR_SUCCESS) {
3198 /* The label matches, but the data item is in error */
3199 uReturn = uResult;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003200 goto Done;
3201 }
Laurence Lundblade63926052021-03-29 16:05:51 -07003202 if(!MatchType(Item, pItemArray[nIndex])) {
3203 /* The data item is not of the type(s) requested */
3204 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003205 goto Done;
3206 }
3207
Laurence Lundblade1341c592020-04-11 14:19:05 -07003208 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003209 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003210 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003211 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003212 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003213 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003214 bMatched = true;
3215 }
3216 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003217
3218
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003219 if(!bMatched && pfCallback != NULL) {
3220 /*
3221 Call the callback on unmatched labels.
3222 (It is tempting to do duplicate detection here, but that would
3223 require dynamic memory allocation because the number of labels
3224 that might be encountered is unbounded.)
3225 */
3226 uReturn = (*pfCallback)(pCBContext, &Item);
3227 if(uReturn != QCBOR_SUCCESS) {
3228 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003229 }
3230 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003231
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003232 /*
3233 Consume the item whether matched or not. This
3234 does the work of traversing maps and array and
3235 everything in them. In this loop only the
3236 items at the current nesting level are examined
3237 to match the labels.
3238 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003239 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003240 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003241 goto Done;
3242 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003243 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003244
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003245 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003246
3247 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003248
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003249 // Check here makes sure that this won't accidentally be
3250 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003251 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003252 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
3253 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003254 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
3255 goto Done;
3256 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003257 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
3258 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003259
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003260 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003261 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
3262
3263 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003264 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07003265 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003266 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003267 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
3268 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003269 }
3270 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003271
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003272 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003273}
3274
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003275
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003276/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003277 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003278*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003279void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
3280 int64_t nLabel,
3281 uint8_t uQcborType,
3282 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003283{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003284 if(pMe->uLastError != QCBOR_SUCCESS) {
3285 return;
3286 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003287
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003288 QCBORItem OneItemSeach[2];
3289 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3290 OneItemSeach[0].label.int64 = nLabel;
3291 OneItemSeach[0].uDataType = uQcborType;
3292 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003293
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003294 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003295
3296 *pItem = OneItemSeach[0];
3297
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003298 if(uReturn != QCBOR_SUCCESS) {
3299 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003300 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003301 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003302 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003303 }
3304
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003305 Done:
3306 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003307}
3308
3309
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003310/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003311 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003312*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07003313void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
3314 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003315 uint8_t uQcborType,
3316 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003317{
Laurence Lundbladeda095972020-06-06 18:35:33 -07003318 if(pMe->uLastError != QCBOR_SUCCESS) {
3319 return;
3320 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003321
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003322 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003323 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3324 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3325 OneItemSeach[0].uDataType = uQcborType;
3326 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003327
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003328 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
3329 if(uReturn != QCBOR_SUCCESS) {
3330 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003331 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003332 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003333 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003334 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003335 }
3336
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003337 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003338
3339Done:
3340 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003341}
3342
3343
Laurence Lundblade93d89472020-10-03 22:30:50 -07003344static QCBORError
3345CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003346{
3347 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
Laurence Lundbladed3adb7c2023-02-08 12:43:11 -07003348 if(uDataType == puTypeList[i]) { /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003349 return QCBOR_SUCCESS;
3350 }
3351 }
3352 return QCBOR_ERR_UNEXPECTED_TYPE;
3353}
3354
Laurence Lundblade67257dc2020-07-27 03:33:37 -07003355
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003356/**
Laurence Lundblade37286c02022-09-03 10:05:02 -07003357 * Match a tag/type specification against the type of the item.
3358 *
3359 * @param[in] TagSpec Specification for matching tags.
3360 * @param[in] pItem The item to check.
3361 *
3362 * @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
3363 * @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
3364 *
3365 * This checks the item data type of untagged items as well as of
3366 * tagged items against a specification to see if decoding should
3367 * proceed.
3368 *
3369 * This relies on the automatic tag decoding done by QCBOR that turns
3370 * tag numbers into particular QCBOR_TYPEs so there is no actual
3371 * comparsion of tag numbers, just of QCBOR_TYPEs.
3372 *
3373 * This checks the data item type as possibly representing the tag
3374 * number or as the tag content type.
3375 *
3376 * If QCBOR_DISABLE_TAGS is #defined, this primarily checks the item
3377 * data type against the allowed tag content types. It will also error out
3378 * if the caller tries to require a tag because there is no way that can
3379 * ever be fulfilled.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003380 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07003381static QCBORError
3382CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07003383{
Laurence Lundbladed3adb7c2023-02-08 12:43:11 -07003384 const int nItemType = pItem->uDataType; /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade37286c02022-09-03 10:05:02 -07003385 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
3386
3387#ifndef QCBOR_DISABLE_TAGS
Laurence Lundbladed3adb7c2023-02-08 12:43:11 -07003388 /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003389 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
3390 pItem->uTags[0] != CBOR_TAG_INVALID16) {
3391 /* There are tags that QCBOR couldn't process on this item and
Laurence Lundblade37286c02022-09-03 10:05:02 -07003392 * the caller has told us there should not be.
3393 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003394 return QCBOR_ERR_UNEXPECTED_TYPE;
3395 }
3396
Laurence Lundblade9b334962020-08-27 10:55:53 -07003397 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
Laurence Lundblade37286c02022-09-03 10:05:02 -07003398 /* Must match the tag number and only the tag */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003399 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3400 }
3401
3402 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
3403 if(uReturn == QCBOR_SUCCESS) {
3404 return QCBOR_SUCCESS;
3405 }
3406
3407 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
3408 /* Must match the content type and only the content type.
Laurence Lundblade37286c02022-09-03 10:05:02 -07003409 * There was no match just above so it is a fail. */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003410 return QCBOR_ERR_UNEXPECTED_TYPE;
3411 }
3412
Laurence Lundblade37286c02022-09-03 10:05:02 -07003413 /* QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG: If here it can match either the tag or the content
3414 * and it hasn't matched the content, so the end
3415 * result is whether it matches the tag. This is
3416 * the tag optional case that the CBOR standard discourages.
3417 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003418
3419 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003420
Laurence Lundblade37286c02022-09-03 10:05:02 -07003421#else /* QCBOR_DISABLE_TAGS */
3422 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
3423 return QCBOR_ERR_UNEXPECTED_TYPE;
3424 }
3425
3426 return CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
3427
3428#endif /* QCBOR_DISABLE_TAGS */
3429}
Laurence Lundblade9b334962020-08-27 10:55:53 -07003430
Laurence Lundblade9b334962020-08-27 10:55:53 -07003431
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003432// This could be semi-private if need be
3433static inline
Laurence Lundblade37286c02022-09-03 10:05:02 -07003434void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
3435 const int64_t nLabel,
3436 const TagSpecification TagSpec,
3437 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003438{
3439 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
3440 if(pMe->uLastError != QCBOR_SUCCESS) {
3441 return;
3442 }
3443
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003444 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003445}
3446
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003447
3448// This could be semi-private if need be
3449static inline
Laurence Lundblade37286c02022-09-03 10:05:02 -07003450void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
3451 const char *szLabel,
3452 const TagSpecification TagSpec,
3453 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003454{
3455 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
3456 if(pMe->uLastError != QCBOR_SUCCESS) {
3457 return;
3458 }
3459
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003460 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003461}
3462
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003463// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003464void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
3465 int64_t nLabel,
3466 TagSpecification TagSpec,
Laurence Lundblade37286c02022-09-03 10:05:02 -07003467 UsefulBufC *pString)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003468{
3469 QCBORItem Item;
3470 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
3471 if(pMe->uLastError == QCBOR_SUCCESS) {
3472 *pString = Item.val.string;
3473 }
3474}
3475
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003476// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003477void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
3478 const char * szLabel,
3479 TagSpecification TagSpec,
3480 UsefulBufC *pString)
3481{
3482 QCBORItem Item;
3483 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
3484 if(pMe->uLastError == QCBOR_SUCCESS) {
3485 *pString = Item.val.string;
3486 }
3487}
Laurence Lundblade1341c592020-04-11 14:19:05 -07003488
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003489/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003490 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003491*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003492void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003493{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003494 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
3495 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003496}
3497
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003498/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003499 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003500*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003501void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3502 QCBORItem *pItemList,
3503 void *pCallbackCtx,
3504 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003505{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003506 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
3507 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003508}
3509
3510
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003511/**
3512 * @brief Search for a map/array by label and enter it
3513 *
3514 * @param[in] pMe The decode context.
3515 * @param[in] pSearch The map/array to search for.
3516 *
3517 * @c pSearch is expected to contain one item of type map or array
3518 * with the label specified. The current bounded map will be searched for
3519 * this and if found will be entered.
3520 *
3521 * If the label is not found, or the item found is not a map or array,
3522 * the error state is set.
3523 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003524static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003525{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003526 // The first item in pSearch is the one that is to be
3527 // entered. It should be the only one filled in. Any other
3528 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003529 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003530 return;
3531 }
3532
3533 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003534 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003535 if(pMe->uLastError != QCBOR_SUCCESS) {
3536 return;
3537 }
3538
Laurence Lundblade9b334962020-08-27 10:55:53 -07003539 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003540 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003541 return;
3542 }
3543
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003544
3545 /* The map or array was found. Now enter it.
3546 *
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003547 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3548 * next item for the pre-order traversal cursor to be the map/array
3549 * found by MapSearch(). The next few lines of code force the
3550 * cursor to that.
3551 *
3552 * There is no need to retain the old cursor because
3553 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3554 * beginning of the map/array being entered.
3555 *
3556 * The cursor is forced by: 1) setting the input buffer position to
3557 * the item offset found by MapSearch(), 2) setting the map/array
3558 * counter to the total in the map/array, 3) setting the nesting
3559 * level. Setting the map/array counter to the total is not
3560 * strictly correct, but this is OK because this cursor only needs
3561 * to be used to get one item and MapSearch() has already found it
3562 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003563 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003564 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003565
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003566 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3567
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003568 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003569
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003570 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003571}
3572
3573
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003574/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003575 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003576*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003577void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003578{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003579 QCBORItem OneItemSeach[2];
3580 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3581 OneItemSeach[0].label.int64 = nLabel;
3582 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3583 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003584
Laurence Lundblade9b334962020-08-27 10:55:53 -07003585 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003586 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003587}
3588
3589
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003590/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003591 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003592*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003593void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003594{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003595 QCBORItem OneItemSeach[2];
3596 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3597 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3598 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3599 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003600
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003601 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003602}
3603
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003604/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003605 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003606*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003607void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003608{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003609 QCBORItem OneItemSeach[2];
3610 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3611 OneItemSeach[0].label.int64 = nLabel;
3612 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3613 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003614
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003615 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003616}
3617
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003618/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003619 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003620*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003621void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3622{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003623 QCBORItem OneItemSeach[2];
3624 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3625 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3626 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3627 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003628
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003629 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003630}
3631
3632
Laurence Lundblade02625d42020-06-25 14:41:41 -07003633// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003634void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003635{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003636 QCBORError uErr;
3637
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003638 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003639 if(pMe->uLastError != QCBOR_SUCCESS) {
3640 // Already in error state; do nothing.
3641 return;
3642 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003643
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003644 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003645 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003646 uErr = QCBORDecode_GetNext(pMe, &Item);
3647 if(uErr != QCBOR_SUCCESS) {
3648 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003649 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003650 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003651 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3652 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003653 }
3654
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003655 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003656
3657
Laurence Lundbladef0499502020-08-01 11:55:57 -07003658 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003659 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003660 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3661 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003662 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003663 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3664 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003665 // Special case to increment nesting level for zero-length maps
3666 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003667 DecodeNesting_Descend(&(pMe->nesting), uType);
3668 }
3669
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003670 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003671
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003672 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3673 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003674
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003675 if(pItem != NULL) {
3676 *pItem = Item;
3677 }
3678
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003679Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003680 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003681}
3682
Laurence Lundblade02625d42020-06-25 14:41:41 -07003683
3684/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003685 This is the common work for exiting a level that is a bounded map,
3686 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003687
3688 One chunk of work is to set up the pre-order traversal so it is at
3689 the item just after the bounded map, array or bstr that is being
3690 exited. This is somewhat complex.
3691
3692 The other work is to level-up the bounded mode to next higest bounded
3693 mode or the top level if there isn't one.
3694 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003695static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003696ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003697{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003698 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003699
Laurence Lundblade02625d42020-06-25 14:41:41 -07003700 /*
3701 First the pre-order-traversal byte offset is positioned to the
3702 item just after the bounded mode item that was just consumed.
3703 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003704 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3705
Laurence Lundblade02625d42020-06-25 14:41:41 -07003706 /*
3707 Next, set the current nesting level to one above the bounded level
3708 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003709
Laurence Lundblade02625d42020-06-25 14:41:41 -07003710 DecodeNesting_CheckBoundedType() is always called before this and
3711 makes sure pCurrentBounded is valid.
3712 */
3713 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3714
3715 /*
3716 This does the complex work of leveling up the pre-order traversal
3717 when the end of a map or array or another bounded level is
3718 reached. It may do nothing, or ascend all the way to the top
3719 level.
3720 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003721 uErr = QCBORDecode_NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003722 if(uErr != QCBOR_SUCCESS) {
3723 goto Done;
3724 }
3725
Laurence Lundblade02625d42020-06-25 14:41:41 -07003726 /*
3727 This makes the next highest bounded level the current bounded
3728 level. If there is no next highest level, then no bounded mode is
3729 in effect.
3730 */
3731 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003732
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003733 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003734
3735Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003736 return uErr;
3737}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003738
Laurence Lundblade02625d42020-06-25 14:41:41 -07003739
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003740// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003741void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003742{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003743 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003744 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003745 return;
3746 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003747
Laurence Lundblade02625d42020-06-25 14:41:41 -07003748 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003749
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003750 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003751 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003752 goto Done;
3753 }
3754
Laurence Lundblade02625d42020-06-25 14:41:41 -07003755 /*
3756 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003757 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003758 from previous map search, then do a dummy search.
3759 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003760 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003761 QCBORItem Dummy;
3762 Dummy.uLabelType = QCBOR_TYPE_NONE;
3763 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3764 if(uErr != QCBOR_SUCCESS) {
3765 goto Done;
3766 }
3767 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003768
Laurence Lundblade02625d42020-06-25 14:41:41 -07003769 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003770
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003771Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003772 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003773}
3774
3775
Laurence Lundblade1341c592020-04-11 14:19:05 -07003776
Laurence Lundblade37286c02022-09-03 10:05:02 -07003777static QCBORError
3778InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
3779 const QCBORItem *pItem,
3780 const uint8_t uTagRequirement,
3781 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003782{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003783 if(pBstr) {
3784 *pBstr = NULLUsefulBufC;
3785 }
3786
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003787 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003788 /* Already in error state; do nothing. */
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003789 return pMe->uLastError;
3790 }
3791
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003792 QCBORError uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003793
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003794 const TagSpecification TagSpec =
3795 {
3796 uTagRequirement,
3797 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3798 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3799 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003800
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003801 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003802 if(uError != QCBOR_SUCCESS) {
3803 goto Done;
3804 }
3805
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003806 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003807 /* Reverse the decrement done by GetNext() for the bstr so the
3808 * increment in QCBORDecode_NestLevelAscender() called by
3809 * ExitBoundedLevel() will work right.
3810 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003811 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003812 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003813
3814 if(pBstr) {
3815 *pBstr = pItem->val.string;
3816 }
3817
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003818 /* This saves the current length of the UsefulInputBuf and then
3819 * narrows the UsefulInputBuf to start and length of the wrapped
3820 * CBOR that is being entered.
3821 *
3822 * Most of these calls are simple inline accessors so this doesn't
3823 * amount to much code.
3824 */
3825
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003826 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003827 /* This check makes the cast of uPreviousLength to uint32_t below safe. */
3828 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003829 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003830 goto Done;
3831 }
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003832
3833 const size_t uStartOfBstr = UsefulInputBuf_PointerToOffset(&(pMe->InBuf),
3834 pItem->val.string.ptr);
3835 /* This check makes the cast of uStartOfBstr to uint32_t below safe. */
3836 if(uStartOfBstr == SIZE_MAX || uStartOfBstr > QCBOR_MAX_DECODE_INPUT_SIZE) {
3837 /* This should never happen because pItem->val.string.ptr should
3838 * always be valid since it was just returned.
3839 */
3840 uError = QCBOR_ERR_INPUT_TOO_LARGE;
3841 goto Done;
3842 }
3843
3844 const size_t uEndOfBstr = uStartOfBstr + pItem->val.string.len;
3845
3846 UsefulInputBuf_Seek(&(pMe->InBuf), uStartOfBstr);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003847 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003848
Laurence Lundblade02625d42020-06-25 14:41:41 -07003849 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003850 (uint32_t)uPreviousLength,
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003851 (uint32_t)uStartOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003852Done:
3853 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003854}
3855
3856
Laurence Lundblade02625d42020-06-25 14:41:41 -07003857/*
3858 Public function, see header qcbor/qcbor_decode.h file
3859 */
3860void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003861 uint8_t uTagRequirement,
3862 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003863{
3864 if(pMe->uLastError != QCBOR_SUCCESS) {
3865 // Already in error state; do nothing.
3866 return;
3867 }
3868
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003869 /* Get the data item that is the byte string being entered */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003870 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003871 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3872 if(pMe->uLastError != QCBOR_SUCCESS) {
3873 return;
3874 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003875
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003876 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003877 &Item,
3878 uTagRequirement,
3879 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003880}
3881
3882
Laurence Lundblade02625d42020-06-25 14:41:41 -07003883/*
3884 Public function, see header qcbor/qcbor_decode.h file
3885 */
3886void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003887 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003888 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003889 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003890{
3891 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003892 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003893
Laurence Lundblade93d89472020-10-03 22:30:50 -07003894 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3895 &Item,
3896 uTagRequirement,
3897 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003898}
3899
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003900
Laurence Lundblade02625d42020-06-25 14:41:41 -07003901/*
3902 Public function, see header qcbor/qcbor_decode.h file
3903 */
3904void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003905 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003906 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003907 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003908{
3909 QCBORItem Item;
3910 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3911
Laurence Lundblade93d89472020-10-03 22:30:50 -07003912 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3913 &Item,
3914 uTagRequirement,
3915 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003916}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003917
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003918
Laurence Lundblade02625d42020-06-25 14:41:41 -07003919/*
3920 Public function, see header qcbor/qcbor_decode.h file
3921 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003922void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003923{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003924 if(pMe->uLastError != QCBOR_SUCCESS) {
3925 // Already in error state; do nothing.
3926 return;
3927 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003928
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003929 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003930 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003931 return;
3932 }
3933
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003934 const uint32_t uEndOfBstr = (uint32_t)UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
3935
Laurence Lundblade02625d42020-06-25 14:41:41 -07003936 /*
3937 Reset the length of the UsefulInputBuf to what it was before
3938 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003939 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003940 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003941 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003942
3943
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003944 QCBORError uErr = ExitBoundedLevel(pMe, uEndOfBstr);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003945 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003946}
3947
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003948
Laurence Lundbladee6430642020-03-14 21:15:44 -07003949
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003950
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003951static inline void
3952ProcessBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003953{
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003954 if(pMe->uLastError != QCBOR_SUCCESS) {
3955 /* Already in error state, do nothing */
3956 return;
3957 }
3958
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003959 switch(pItem->uDataType) {
3960 case QCBOR_TYPE_TRUE:
3961 *pBool = true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003962 break;
3963
3964 case QCBOR_TYPE_FALSE:
3965 *pBool = false;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003966 break;
3967
3968 default:
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003969 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003970 break;
3971 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003972 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003973}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003974
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003975
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003976/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003977 * Public function, see header qcbor/qcbor_decode.h file
3978 */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003979void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003980{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003981 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003982 /* Already in error state, do nothing */
Laurence Lundbladee6430642020-03-14 21:15:44 -07003983 return;
3984 }
3985
Laurence Lundbladec4537442020-04-14 18:53:22 -07003986 QCBORItem Item;
3987
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003988 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3989
3990 ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003991}
3992
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003993
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003994/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003995 * Public function, see header qcbor/qcbor_decode.h file
3996 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003997void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003998{
3999 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004000 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004001
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004002 ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004003}
4004
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004005
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004006/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004007 * Public function, see header qcbor/qcbor_decode.h file
4008 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004009void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
4010{
4011 QCBORItem Item;
4012 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4013
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004014 ProcessBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004015}
4016
4017
4018
Laurence Lundbladec7114722020-08-13 05:11:40 -07004019
4020static void ProcessEpochDate(QCBORDecodeContext *pMe,
4021 QCBORItem *pItem,
Laurence Lundblade37286c02022-09-03 10:05:02 -07004022 const uint8_t uTagRequirement,
Laurence Lundbladec7114722020-08-13 05:11:40 -07004023 int64_t *pnTime)
4024{
4025 if(pMe->uLastError != QCBOR_SUCCESS) {
4026 // Already in error state, do nothing
4027 return;
4028 }
4029
4030 QCBORError uErr;
4031
4032 const TagSpecification TagSpec =
4033 {
4034 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004035 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4036 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07004037 };
4038
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004039 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004040 if(uErr != QCBOR_SUCCESS) {
4041 goto Done;
4042 }
4043
4044 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
4045 uErr = DecodeDateEpoch(pItem);
4046 if(uErr != QCBOR_SUCCESS) {
4047 goto Done;
4048 }
4049 }
4050
Laurence Lundblade9b334962020-08-27 10:55:53 -07004051 // Save the tags in the last item's tags in the decode context
4052 // for QCBORDecode_GetNthTagOfLast()
4053 CopyTags(pMe, pItem);
4054
Laurence Lundbladec7114722020-08-13 05:11:40 -07004055 *pnTime = pItem->val.epochDate.nSeconds;
4056
4057Done:
4058 pMe->uLastError = (uint8_t)uErr;
4059}
4060
4061
4062void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004063 uint8_t uTagRequirement,
4064 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07004065{
4066 if(pMe->uLastError != QCBOR_SUCCESS) {
4067 // Already in error state, do nothing
4068 return;
4069 }
4070
4071 QCBORItem Item;
4072 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4073
4074 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
4075}
4076
4077
4078void
4079QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
4080 int64_t nLabel,
4081 uint8_t uTagRequirement,
4082 int64_t *pnTime)
4083{
4084 QCBORItem Item;
4085 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4086 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
4087}
4088
4089
4090void
4091QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
4092 const char *szLabel,
4093 uint8_t uTagRequirement,
4094 int64_t *pnTime)
4095{
4096 QCBORItem Item;
4097 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4098 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
4099}
4100
4101
4102
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004103/*
4104 * Common processing for the RFC 8943 day-count tag. Mostly
4105 * make sure the tag content is correct and copy forward any
4106 * further other tag numbers.
4107 */
4108static void ProcessEpochDays(QCBORDecodeContext *pMe,
4109 QCBORItem *pItem,
4110 uint8_t uTagRequirement,
4111 int64_t *pnDays)
4112{
4113 if(pMe->uLastError != QCBOR_SUCCESS) {
4114 /* Already in error state, do nothing */
4115 return;
4116 }
4117
4118 QCBORError uErr;
4119
4120 const TagSpecification TagSpec =
4121 {
4122 uTagRequirement,
4123 {QCBOR_TYPE_DAYS_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4124 {QCBOR_TYPE_INT64, QCBOR_TYPE_UINT64, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4125 };
4126
4127 uErr = CheckTagRequirement(TagSpec, pItem);
4128 if(uErr != QCBOR_SUCCESS) {
4129 goto Done;
4130 }
4131
4132 if(pItem->uDataType != QCBOR_TYPE_DAYS_EPOCH) {
4133 uErr = DecodeDaysEpoch(pItem);
4134 if(uErr != QCBOR_SUCCESS) {
4135 goto Done;
4136 }
4137 }
4138
4139 /* Save the tags in the last item's tags in the decode context
4140 * for QCBORDecode_GetNthTagOfLast()
4141 */
4142 CopyTags(pMe, pItem);
4143
4144 *pnDays = pItem->val.epochDays;
4145
4146Done:
4147 pMe->uLastError = (uint8_t)uErr;
4148}
4149
4150
4151/*
4152 * Public function, see header qcbor/qcbor_decode.h
4153 */
4154void QCBORDecode_GetEpochDays(QCBORDecodeContext *pMe,
4155 uint8_t uTagRequirement,
4156 int64_t *pnDays)
4157{
4158 if(pMe->uLastError != QCBOR_SUCCESS) {
4159 /* Already in error state, do nothing */
4160 return;
4161 }
4162
4163 QCBORItem Item;
4164 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4165
4166 ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
4167}
4168
4169
4170/*
4171 * Public function, see header qcbor/qcbor_decode.h
4172 */
4173void
4174QCBORDecode_GetEpochDaysInMapN(QCBORDecodeContext *pMe,
4175 int64_t nLabel,
4176 uint8_t uTagRequirement,
4177 int64_t *pnDays)
4178{
4179 QCBORItem Item;
4180 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4181 ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
4182}
4183
4184
4185/*
4186 * Public function, see header qcbor/qcbor_decode.h
4187 */
4188void
4189QCBORDecode_GetEpochDaysInMapSZ(QCBORDecodeContext *pMe,
4190 const char *szLabel,
4191 uint8_t uTagRequirement,
4192 int64_t *pnDays)
4193{
4194 QCBORItem Item;
4195 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4196 ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
4197}
4198
4199
4200
Laurence Lundblade37286c02022-09-03 10:05:02 -07004201/*
4202 * @brief Get a string that matches the type/tag specification.
4203 */
4204void
4205QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
4206 const TagSpecification TagSpec,
4207 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004208{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004209 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade37286c02022-09-03 10:05:02 -07004210 /* Already in error state, do nothing */
Laurence Lundbladec4537442020-04-14 18:53:22 -07004211 return;
4212 }
4213
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004214 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004215 QCBORItem Item;
4216
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004217 uError = QCBORDecode_GetNext(pMe, &Item);
4218 if(uError != QCBOR_SUCCESS) {
4219 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004220 return;
4221 }
4222
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004223 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004224
4225 if(pMe->uLastError == QCBOR_SUCCESS) {
4226 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07004227 } else {
4228 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004229 }
4230}
4231
Laurence Lundbladec4537442020-04-14 18:53:22 -07004232
4233
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004234
Laurence Lundblade37286c02022-09-03 10:05:02 -07004235static QCBORError
4236ProcessBigNum(const uint8_t uTagRequirement,
4237 const QCBORItem *pItem,
4238 UsefulBufC *pValue,
4239 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004240{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004241 const TagSpecification TagSpec =
4242 {
4243 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004244 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4245 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004246 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004247
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004248 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004249 if(uErr != QCBOR_SUCCESS) {
4250 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004251 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004252
4253 *pValue = pItem->val.string;
4254
4255 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
4256 *pbIsNegative = false;
4257 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
4258 *pbIsNegative = true;
4259 }
4260
4261 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004262}
4263
4264
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004265/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004266 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004267 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004268void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
4269 uint8_t uTagRequirement,
4270 UsefulBufC *pValue,
4271 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004272{
4273 if(pMe->uLastError != QCBOR_SUCCESS) {
4274 // Already in error state, do nothing
4275 return;
4276 }
4277
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004278 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004279 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4280 if(uError != QCBOR_SUCCESS) {
4281 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004282 return;
4283 }
4284
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004285 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004286}
4287
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004288
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004289/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004290 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004291*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004292void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
4293 int64_t nLabel,
4294 uint8_t uTagRequirement,
4295 UsefulBufC *pValue,
4296 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004297{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004298 QCBORItem Item;
4299 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004300 if(pMe->uLastError != QCBOR_SUCCESS) {
4301 return;
4302 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004303
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004304 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004305}
4306
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004307
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004308/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004309 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004310*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004311void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
4312 const char *szLabel,
4313 uint8_t uTagRequirement,
4314 UsefulBufC *pValue,
4315 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004316{
4317 QCBORItem Item;
4318 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004319 if(pMe->uLastError != QCBOR_SUCCESS) {
4320 return;
4321 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004322
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004323 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004324}
4325
4326
4327
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004328
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004329// Semi private
Laurence Lundblade37286c02022-09-03 10:05:02 -07004330QCBORError
4331QCBORDecode_GetMIMEInternal(const uint8_t uTagRequirement,
4332 const QCBORItem *pItem,
4333 UsefulBufC *pMessage,
4334 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004335{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004336 const TagSpecification TagSpecText =
4337 {
4338 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004339 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4340 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004341 };
4342 const TagSpecification TagSpecBinary =
4343 {
4344 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004345 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4346 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004347 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004348
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004349 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07004350
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004351 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004352 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004353 if(pbIsTag257 != NULL) {
4354 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004355 }
4356 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004357 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004358 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004359 if(pbIsTag257 != NULL) {
4360 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004361 }
4362 uReturn = QCBOR_SUCCESS;
4363
4364 } else {
4365 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
4366 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07004367
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004368 return uReturn;
4369}
4370
Laurence Lundblade93d89472020-10-03 22:30:50 -07004371// Improvement: add methods for wrapped CBOR, a simple alternate
4372// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004373
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004374
4375
4376
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004377#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07004378
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004379typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004380
4381
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004382/**
4383 * @brief Base 10 exponentiate a mantissa and exponent into an unsigned 64-bit integer.
4384 *
4385 * @param[in] uMantissa The unsigned integer mantissa.
4386 * @param[in] nExponent The signed integer exponent.
4387 * @param[out] puResult Place to return the unsigned integer result.
4388 *
4389 * This computes: mantissa * 10 ^^ exponent as for a decimal fraction. The output is a 64-bit
4390 * unsigned integer.
4391 *
4392 * There are many inputs for which the result will not fit in the
4393 * 64-bit integer and \ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will
4394 * be returned.
4395 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004396static QCBORError
4397Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004398{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004399 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004400
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004401 if(uResult != 0) {
4402 /* This loop will run a maximum of 19 times because
4403 * UINT64_MAX < 10 ^^ 19. More than that will cause
4404 * exit with the overflow error
4405 */
4406 for(; nExponent > 0; nExponent--) {
4407 if(uResult > UINT64_MAX / 10) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004408 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004409 }
4410 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004411 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004412
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004413 for(; nExponent < 0; nExponent++) {
4414 uResult = uResult / 10;
4415 if(uResult == 0) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004416 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004417 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004418 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004419 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004420 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07004421
4422 *puResult = uResult;
4423
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004424 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004425}
4426
4427
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004428/**
4429 * @brief Base 2 exponentiate a mantissa and exponent into an unsigned 64-bit integer.
4430 *
4431 * @param[in] uMantissa The unsigned integer mantissa.
4432 * @param[in] nExponent The signed integer exponent.
4433 * @param[out] puResult Place to return the unsigned integer result.
4434 *
4435 * This computes: mantissa * 2 ^^ exponent as for a big float. The
4436 * output is a 64-bit unsigned integer.
4437 *
4438 * There are many inputs for which the result will not fit in the
4439 * 64-bit integer and \ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will
4440 * be returned.
4441 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004442static QCBORError
4443Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004444{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004445 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004446
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004447 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004448
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004449 /* This loop will run a maximum of 64 times because INT64_MAX <
4450 * 2^31. More than that will cause exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07004451 */
4452 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004453 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004454 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004455 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004456 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004457 nExponent--;
4458 }
4459
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004460 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004461 if(uResult == 0) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004462 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004463 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004464 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004465 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004466 }
4467
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004468 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004469
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004470 return QCBOR_SUCCESS;
4471}
4472
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004473
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004474/**
4475 * @brief Exponentiate a signed mantissa and signed exponent to produce a signed result.
4476 *
4477 * @param[in] nMantissa Signed integer mantissa.
4478 * @param[in] nExponent Signed integer exponent.
4479 * @param[out] pnResult Place to put the signed integer result.
4480 * @param[in] pfExp Exponentiation function.
4481 *
4482 * @returns Error code
4483 *
4484 * \c pfExp performs exponentiation on and unsigned mantissa and
4485 * produces an unsigned result. This converts the mantissa from signed
4486 * and converts the result to signed. The exponentiation function is
4487 * either for base 2 or base 10 (and could be other if needed).
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004488 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004489static QCBORError
4490ExponentiateNN(int64_t nMantissa,
4491 int64_t nExponent,
4492 int64_t *pnResult,
4493 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004494{
4495 uint64_t uResult;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004496 uint64_t uMantissa;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004497
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004498 /* Take the absolute value and put it into an unsigned. */
4499 if(nMantissa >= 0) {
4500 /* Positive case is straightforward */
4501 uMantissa = (uint64_t)nMantissa;
4502 } else if(nMantissa != INT64_MIN) {
4503 /* The common negative case. See next. */
4504 uMantissa = (uint64_t)-nMantissa;
4505 } else {
4506 /* int64_t and uint64_t are always two's complement per the
4507 * C standard (and since QCBOR uses these it only works with
4508 * two's complement, which is pretty much universal these
4509 * days). The range of a negative two's complement integer is
4510 * one more that than a positive, so the simple code above might
4511 * not work all the time because you can't simply negate the
4512 * value INT64_MIN because it can't be represented in an
4513 * int64_t. -INT64_MIN can however be represented in a
4514 * uint64_t. Some compilers seem to recognize this case for the
4515 * above code and put the correct value in uMantissa, however
4516 * they are not required to do this by the C standard. This next
4517 * line does however work for all compilers.
4518 *
4519 * This does assume two's complement where -INT64_MIN ==
4520 * INT64_MAX + 1 (which wouldn't be true for one's complement or
4521 * sign and magnitude (but we know we're using two's complement
4522 * because int64_t requires it)).
4523 *
4524 * See these, particularly the detailed commentary:
4525 * https://stackoverflow.com/questions/54915742/does-c99-mandate-a-int64-t-type-be-available-always
4526 * https://stackoverflow.com/questions/37301078/is-negating-int-min-undefined-behaviour
4527 */
4528 uMantissa = (uint64_t)INT64_MAX+1;
4529 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004530
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004531 /* Call the exponentiator passed for either base 2 or base 10.
4532 * Here is where most of the overflow errors are caught. */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004533 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
4534 if(uReturn) {
4535 return uReturn;
4536 }
4537
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004538 /* Convert back to the sign of the original mantissa */
4539 if(nMantissa >= 0) {
4540 if(uResult > INT64_MAX) {
4541 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4542 }
4543 *pnResult = (int64_t)uResult;
4544 } else {
4545 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
4546 * of INT64_MIN. This assumes two's compliment representation
4547 * where INT64_MIN is one increment farther from 0 than
4548 * INT64_MAX. Trying to write -INT64_MIN doesn't work to get
4549 * this because the compiler makes it an int64_t which can't
4550 * represent -INT64_MIN. Also see above.
4551 */
4552 if(uResult > (uint64_t)INT64_MAX+1) {
4553 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4554 }
4555 *pnResult = -(int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004556 }
4557
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004558 return QCBOR_SUCCESS;
4559}
4560
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004561
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004562/**
4563 * @brief Exponentiate an unsigned mantissa and signed exponent to produce an unsigned result.
4564 *
4565 * @param[in] nMantissa Signed integer mantissa.
4566 * @param[in] nExponent Signed integer exponent.
4567 * @param[out] puResult Place to put the signed integer result.
4568 * @param[in] pfExp Exponentiation function.
4569 *
4570 * @returns Error code
4571 *
4572 * \c pfExp performs exponentiation on and unsigned mantissa and
4573 * produces an unsigned result. This errors out if the mantissa
4574 * is negative because the output is unsigned.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004575 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004576static QCBORError
4577ExponentitateNU(int64_t nMantissa,
4578 int64_t nExponent,
4579 uint64_t *puResult,
4580 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004581{
4582 if(nMantissa < 0) {
4583 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4584 }
4585
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004586 /* Cast to unsigned is OK because of check for negative.
4587 * Cast to unsigned is OK because UINT64_MAX > INT64_MAX.
4588 * Exponentiation is straight forward
4589 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004590 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
4591}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004592
4593
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004594/**
4595 * @brief Exponentiate an usnigned mantissa and unsigned exponent to produce an unsigned result.
4596 *
4597 * @param[in] uMantissa Unsigned integer mantissa.
4598 * @param[in] nExponent Unsigned integer exponent.
4599 * @param[out] puResult Place to put the unsigned integer result.
4600 * @param[in] pfExp Exponentiation function.
4601 *
4602 * @returns Error code
4603 *
4604 * \c pfExp performs exponentiation on and unsigned mantissa and
4605 * produces an unsigned result so this is just a wrapper that does
4606 * nothing (and is likely inlined).
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004607 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004608static QCBORError
4609ExponentitateUU(uint64_t uMantissa,
4610 int64_t nExponent,
4611 uint64_t *puResult,
4612 fExponentiator pfExp)
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004613{
4614 return (*pfExp)(uMantissa, nExponent, puResult);
4615}
4616
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004617#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004618
4619
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004620
4621
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004622/**
4623 * @brief Convert a CBOR big number to a uint64_t.
4624 *
4625 * @param[in] BigNum Bytes of the big number to convert.
4626 * @param[in] uMax Maximum value allowed for the result.
4627 * @param[out] pResult Place to put the unsigned integer result.
4628 *
4629 * @returns Error code
4630 *
4631 * Many values will overflow because a big num can represent a much
4632 * larger range than uint64_t.
4633 */
4634static QCBORError
4635ConvertBigNumToUnsigned(const UsefulBufC BigNum, const uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004636{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004637 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004638
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004639 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004640 const uint8_t *pByte = BigNum.ptr;
4641 size_t uLen = BigNum.len;
4642 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07004643 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004644 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004645 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07004646 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004647 }
4648
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004649 *pResult = uResult;
4650 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004651}
4652
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004653
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004654/**
4655 * @brief Convert a CBOR postive big number to a uint64_t.
4656 *
4657 * @param[in] BigNum Bytes of the big number to convert.
4658 * @param[out] pResult Place to put the unsigned integer result.
4659 *
4660 * @returns Error code
4661 *
4662 * Many values will overflow because a big num can represent a much
4663 * larger range than uint64_t.
4664 */
4665static QCBORError
4666ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004667{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004668 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004669}
4670
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004671
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004672/**
4673 * @brief Convert a CBOR positive big number to an int64_t.
4674 *
4675 * @param[in] BigNum Bytes of the big number to convert.
4676 * @param[out] pResult Place to put the signed integer result.
4677 *
4678 * @returns Error code
4679 *
4680 * Many values will overflow because a big num can represent a much
4681 * larger range than int64_t.
4682 */
4683static QCBORError
4684ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004685{
4686 uint64_t uResult;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004687 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004688 if(uError) {
4689 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004690 }
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004691 /* Cast is safe because ConvertBigNumToUnsigned is told to limit to INT64_MAX */
Laurence Lundbladee6430642020-03-14 21:15:44 -07004692 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004693 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004694}
4695
4696
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004697/**
4698 * @brief Convert a CBOR negative big number to an int64_t.
4699 *
4700 * @param[in] BigNum Bytes of the big number to convert.
4701 * @param[out] pnResult Place to put the signed integer result.
4702 *
4703 * @returns Error code
4704 *
4705 * Many values will overflow because a big num can represent a much
4706 * larger range than int64_t.
4707 */
4708static QCBORError
4709ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004710{
4711 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004712 /* The negative integer furthest from zero for a C int64_t is
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004713 * INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
4714 * negative number in CBOR is computed as -n - 1 where n is the
4715 * encoded integer, where n is what is in the variable BigNum. When
4716 * converting BigNum to a uint64_t, the maximum value is thus
4717 * INT64_MAX, so that when it -n - 1 is applied to it the result
4718 * will never be further from 0 than INT64_MIN.
4719 *
4720 * -n - 1 <= INT64_MIN.
4721 * -n - 1 <= -INT64_MAX - 1
4722 * n <= INT64_MAX.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004723 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07004724 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004725 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004726 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004727 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004728
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004729 /* Now apply -n - 1. The cast is safe because
4730 * ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
4731 * is the largest positive integer that an int64_t can
4732 * represent. */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004733 *pnResult = -(int64_t)uResult - 1;
4734
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004735 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004736}
4737
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004738
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004739
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004740
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004741
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004742/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004743Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004744
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004745\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004746
Laurence Lundblade93d89472020-10-03 22:30:50 -07004747\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4748 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004749
4750\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4751
Laurence Lundblade93d89472020-10-03 22:30:50 -07004752\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4753 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004754*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07004755static QCBORError
4756ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004757{
4758 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004759 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004760 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004761#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004762 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004763 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
4764 http://www.cplusplus.com/reference/cmath/llround/
4765 */
4766 // Not interested in FE_INEXACT
4767 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004768 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4769 *pnValue = llround(pItem->val.dfnum);
4770 } else {
4771 *pnValue = lroundf(pItem->val.fnum);
4772 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004773 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4774 // llround() shouldn't result in divide by zero, but catch
4775 // it here in case it unexpectedly does. Don't try to
4776 // distinguish between the various exceptions because it seems
4777 // they vary by CPU, compiler and OS.
4778 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004779 }
4780 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004781 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004782 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004783#else
4784 return QCBOR_ERR_HW_FLOAT_DISABLED;
4785#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004786 break;
4787
4788 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004789 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004790 *pnValue = pItem->val.int64;
4791 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004792 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004793 }
4794 break;
4795
4796 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004797 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004798 if(pItem->val.uint64 < INT64_MAX) {
4799 *pnValue = pItem->val.int64;
4800 } else {
4801 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4802 }
4803 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004804 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004805 }
4806 break;
4807
4808 default:
4809 return QCBOR_ERR_UNEXPECTED_TYPE;
4810 }
4811 return QCBOR_SUCCESS;
4812}
4813
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004814
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004815void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004816 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004817 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004818 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004819{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004820 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004821 return;
4822 }
4823
Laurence Lundbladee6430642020-03-14 21:15:44 -07004824 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004825 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4826 if(uError) {
4827 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004828 return;
4829 }
4830
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004831 if(pItem) {
4832 *pItem = Item;
4833 }
4834
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004835 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004836}
4837
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004838
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004839void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4840 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004841 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004842 int64_t *pnValue,
4843 QCBORItem *pItem)
4844{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004845 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004846 if(pMe->uLastError != QCBOR_SUCCESS) {
4847 return;
4848 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004849
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004850 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004851}
4852
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004853
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004854void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4855 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004856 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004857 int64_t *pnValue,
4858 QCBORItem *pItem)
4859{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004860 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004861 if(pMe->uLastError != QCBOR_SUCCESS) {
4862 return;
4863 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004864
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004865 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004866}
4867
4868
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004869/*
4870 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004871
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004872 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004873
Laurence Lundblade93d89472020-10-03 22:30:50 -07004874 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4875 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004876
4877 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4878
Laurence Lundblade93d89472020-10-03 22:30:50 -07004879 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4880 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004881 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004882static QCBORError
4883Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004884{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004885 switch(pItem->uDataType) {
4886
4887 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004888 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004889 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004890 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004891 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004892 }
4893 break;
4894
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004895 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004896 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004897 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004898 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004899 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004900 }
4901 break;
4902
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004903#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004904 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004905 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004906 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004907 pItem->val.expAndMantissa.nExponent,
4908 pnValue,
4909 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004910 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004911 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004912 }
4913 break;
4914
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004915 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004916 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004917 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004918 pItem->val.expAndMantissa.nExponent,
4919 pnValue,
4920 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004921 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004922 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004923 }
4924 break;
4925
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004926 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004927 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004928 int64_t nMantissa;
4929 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004930 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4931 if(uErr) {
4932 return uErr;
4933 }
4934 return ExponentiateNN(nMantissa,
4935 pItem->val.expAndMantissa.nExponent,
4936 pnValue,
4937 Exponentitate10);
4938 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004939 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004940 }
4941 break;
4942
4943 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004944 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004945 int64_t nMantissa;
4946 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004947 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4948 if(uErr) {
4949 return uErr;
4950 }
4951 return ExponentiateNN(nMantissa,
4952 pItem->val.expAndMantissa.nExponent,
4953 pnValue,
4954 Exponentitate10);
4955 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004956 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004957 }
4958 break;
4959
4960 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004961 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004962 int64_t nMantissa;
4963 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004964 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4965 if(uErr) {
4966 return uErr;
4967 }
4968 return ExponentiateNN(nMantissa,
4969 pItem->val.expAndMantissa.nExponent,
4970 pnValue,
4971 Exponentitate2);
4972 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004973 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004974 }
4975 break;
4976
4977 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004978 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004979 int64_t nMantissa;
4980 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004981 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4982 if(uErr) {
4983 return uErr;
4984 }
4985 return ExponentiateNN(nMantissa,
4986 pItem->val.expAndMantissa.nExponent,
4987 pnValue,
4988 Exponentitate2);
4989 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004990 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004991 }
4992 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004993#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004994
Laurence Lundbladee6430642020-03-14 21:15:44 -07004995
Laurence Lundbladec4537442020-04-14 18:53:22 -07004996 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004997 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004998}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004999
5000
Laurence Lundbladec4537442020-04-14 18:53:22 -07005001/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005002 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005003 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005004void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07005005{
5006 QCBORItem Item;
5007
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005008 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07005009
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005010 if(pMe->uLastError == QCBOR_SUCCESS) {
5011 // The above conversion succeeded
5012 return;
5013 }
5014
Laurence Lundbladef6c86662020-05-12 02:08:00 -07005015 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005016 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07005017 return;
5018 }
5019
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005020 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005021}
5022
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005023
5024/*
5025Public function, see header qcbor/qcbor_decode.h file
5026*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005027void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
5028 int64_t nLabel,
5029 uint32_t uConvertTypes,
5030 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005031{
5032 QCBORItem Item;
5033
Laurence Lundblade93d89472020-10-03 22:30:50 -07005034 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
5035 nLabel,
5036 uConvertTypes,
5037 pnValue,
5038 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005039
5040 if(pMe->uLastError == QCBOR_SUCCESS) {
5041 // The above conversion succeeded
5042 return;
5043 }
5044
5045 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5046 // The above conversion failed in a way that code below can't correct
5047 return;
5048 }
5049
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005050 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005051}
5052
5053
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005054/*
5055Public function, see header qcbor/qcbor_decode.h file
5056*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005057void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
5058 const char *szLabel,
5059 uint32_t uConvertTypes,
5060 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005061{
5062 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07005063 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
5064 szLabel,
5065 uConvertTypes,
5066 pnValue,
5067 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005068
5069 if(pMe->uLastError == QCBOR_SUCCESS) {
5070 // The above conversion succeeded
5071 return;
5072 }
5073
5074 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5075 // The above conversion failed in a way that code below can't correct
5076 return;
5077 }
5078
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005079 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005080}
5081
5082
Laurence Lundblade93d89472020-10-03 22:30:50 -07005083static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005084{
5085 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005086 case QCBOR_TYPE_DOUBLE:
5087 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005088#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005089 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005090 // Can't use llround here because it will not convert values
5091 // greater than INT64_MAX and less than UINT64_MAX that
5092 // need to be converted so it is more complicated.
5093 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
5094 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
5095 if(isnan(pItem->val.dfnum)) {
5096 return QCBOR_ERR_FLOAT_EXCEPTION;
5097 } else if(pItem->val.dfnum < 0) {
5098 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5099 } else {
5100 double dRounded = round(pItem->val.dfnum);
5101 // See discussion in DecodeDateEpoch() for
5102 // explanation of - 0x7ff
5103 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
5104 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5105 }
5106 *puValue = (uint64_t)dRounded;
5107 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005108 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005109 if(isnan(pItem->val.fnum)) {
5110 return QCBOR_ERR_FLOAT_EXCEPTION;
5111 } else if(pItem->val.fnum < 0) {
5112 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5113 } else {
5114 float fRounded = roundf(pItem->val.fnum);
5115 // See discussion in DecodeDateEpoch() for
5116 // explanation of - 0x7ff
5117 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
5118 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5119 }
5120 *puValue = (uint64_t)fRounded;
5121 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005122 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005123 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
5124 // round() and roundf() shouldn't result in exceptions here, but
5125 // catch them to be robust and thorough. Don't try to
5126 // distinguish between the various exceptions because it seems
5127 // they vary by CPU, compiler and OS.
5128 return QCBOR_ERR_FLOAT_EXCEPTION;
5129 }
5130
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005131 } else {
5132 return QCBOR_ERR_UNEXPECTED_TYPE;
5133 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005134#else
5135 return QCBOR_ERR_HW_FLOAT_DISABLED;
5136#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005137 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005138
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005139 case QCBOR_TYPE_INT64:
5140 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
5141 if(pItem->val.int64 >= 0) {
5142 *puValue = (uint64_t)pItem->val.int64;
5143 } else {
5144 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5145 }
5146 } else {
5147 return QCBOR_ERR_UNEXPECTED_TYPE;
5148 }
5149 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005150
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005151 case QCBOR_TYPE_UINT64:
5152 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
5153 *puValue = pItem->val.uint64;
5154 } else {
5155 return QCBOR_ERR_UNEXPECTED_TYPE;
5156 }
5157 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005158
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005159 default:
5160 return QCBOR_ERR_UNEXPECTED_TYPE;
5161 }
5162
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005163 return QCBOR_SUCCESS;
5164}
Laurence Lundbladec4537442020-04-14 18:53:22 -07005165
5166
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005167void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005168 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005169 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005170 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07005171{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005172 if(pMe->uLastError != QCBOR_SUCCESS) {
5173 return;
5174 }
5175
Laurence Lundbladec4537442020-04-14 18:53:22 -07005176 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005177
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005178 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5179 if(uError) {
5180 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005181 return;
5182 }
5183
Laurence Lundbladea826c502020-05-10 21:07:00 -07005184 if(pItem) {
5185 *pItem = Item;
5186 }
5187
Laurence Lundblade93d89472020-10-03 22:30:50 -07005188 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07005189}
5190
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005191
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07005192void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005193 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005194 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005195 uint64_t *puValue,
5196 QCBORItem *pItem)
5197{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005198 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005199 if(pMe->uLastError != QCBOR_SUCCESS) {
5200 return;
5201 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005202
Laurence Lundblade93d89472020-10-03 22:30:50 -07005203 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005204}
5205
5206
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005207void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005208 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005209 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005210 uint64_t *puValue,
5211 QCBORItem *pItem)
5212{
5213 if(pMe->uLastError != QCBOR_SUCCESS) {
5214 return;
5215 }
5216
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005217 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005218 if(pMe->uLastError != QCBOR_SUCCESS) {
5219 return;
5220 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005221
Laurence Lundblade93d89472020-10-03 22:30:50 -07005222 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005223}
5224
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005225
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005226
Laurence Lundblade93d89472020-10-03 22:30:50 -07005227static QCBORError
5228UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005229{
Laurence Lundbladed3adb7c2023-02-08 12:43:11 -07005230 switch(pItem->uDataType) { /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005231
5232 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005233 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005234 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
5235 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005236 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005237 }
5238 break;
5239
5240 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005241 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005242 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5243 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005244 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005245 }
5246 break;
5247
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005248#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005249
5250 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005251 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005252 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005253 pItem->val.expAndMantissa.nExponent,
5254 puValue,
5255 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005256 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005257 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005258 }
5259 break;
5260
5261 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005262 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005263 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
5264 pItem->val.expAndMantissa.nExponent,
5265 puValue,
5266 Exponentitate2);
5267 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005268 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005269 }
5270 break;
5271
5272 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005273 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005274 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005275 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005276 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005277 if(uErr != QCBOR_SUCCESS) {
5278 return uErr;
5279 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005280 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005281 pItem->val.expAndMantissa.nExponent,
5282 puValue,
5283 Exponentitate10);
5284 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005285 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005286 }
5287 break;
5288
5289 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005290 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005291 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5292 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005293 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005294 }
5295 break;
5296
5297 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005298 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005299 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005300 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005301 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005302 if(uErr != QCBOR_SUCCESS) {
5303 return uErr;
5304 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005305 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005306 pItem->val.expAndMantissa.nExponent,
5307 puValue,
5308 Exponentitate2);
5309 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005310 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005311 }
5312 break;
5313
5314 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005315 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005316 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5317 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005318 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005319 }
5320 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005321#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005322 default:
5323 return QCBOR_ERR_UNEXPECTED_TYPE;
5324 }
5325}
5326
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005327
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005328/*
5329 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005330 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005331void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005332{
5333 QCBORItem Item;
5334
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005335 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005336
Laurence Lundbladef6c86662020-05-12 02:08:00 -07005337 if(pMe->uLastError == QCBOR_SUCCESS) {
5338 // The above conversion succeeded
5339 return;
5340 }
5341
5342 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5343 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07005344 return;
5345 }
5346
Laurence Lundblade93d89472020-10-03 22:30:50 -07005347 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005348}
5349
Laurence Lundbladec4537442020-04-14 18:53:22 -07005350
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005351/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005352 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005353*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07005354void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07005355 int64_t nLabel,
5356 uint32_t uConvertTypes,
5357 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005358{
5359 QCBORItem Item;
5360
Laurence Lundblade93d89472020-10-03 22:30:50 -07005361 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
5362 nLabel,
5363 uConvertTypes,
5364 puValue,
5365 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005366
5367 if(pMe->uLastError == QCBOR_SUCCESS) {
5368 // The above conversion succeeded
5369 return;
5370 }
5371
5372 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5373 // The above conversion failed in a way that code below can't correct
5374 return;
5375 }
5376
Laurence Lundblade93d89472020-10-03 22:30:50 -07005377 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005378}
5379
5380
5381/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005382 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005383*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07005384void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07005385 const char *szLabel,
5386 uint32_t uConvertTypes,
5387 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005388{
5389 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07005390 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
5391 szLabel,
5392 uConvertTypes,
5393 puValue,
5394 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005395
5396 if(pMe->uLastError == QCBOR_SUCCESS) {
5397 // The above conversion succeeded
5398 return;
5399 }
5400
5401 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5402 // The above conversion failed in a way that code below can't correct
5403 return;
5404 }
5405
Laurence Lundblade93d89472020-10-03 22:30:50 -07005406 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005407}
5408
5409
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005410
5411
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02005412#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade9b334962020-08-27 10:55:53 -07005413static QCBORError ConvertDouble(const QCBORItem *pItem,
5414 uint32_t uConvertTypes,
5415 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005416{
5417 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005418 case QCBOR_TYPE_FLOAT:
5419#ifndef QCBOR_DISABLE_FLOAT_HW_USE
5420 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5421 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005422 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005423 *pdValue = (double)pItem->val.fnum;
5424 } else {
5425 return QCBOR_ERR_UNEXPECTED_TYPE;
5426 }
5427 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005428#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005429 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005430#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005431 break;
5432
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005433 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005434 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5435 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005436 *pdValue = pItem->val.dfnum;
5437 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005438 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005439 }
5440 }
5441 break;
5442
5443 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005444#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005445 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005446 // A simple cast seems to do the job with no worry of exceptions.
5447 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005448 *pdValue = (double)pItem->val.int64;
5449
5450 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005451 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005452 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005453#else
5454 return QCBOR_ERR_HW_FLOAT_DISABLED;
5455#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005456 break;
5457
5458 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005459#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005460 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005461 // A simple cast seems to do the job with no worry of exceptions.
5462 // There will be precision loss for some values.
5463 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005464 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005465 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005466 }
5467 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005468#else
5469 return QCBOR_ERR_HW_FLOAT_DISABLED;
5470#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005471
5472 default:
5473 return QCBOR_ERR_UNEXPECTED_TYPE;
5474 }
5475
5476 return QCBOR_SUCCESS;
5477}
5478
5479
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005480void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005481 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005482 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005483 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005484{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005485 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07005486 return;
5487 }
5488
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005489 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005490
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005491 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005492 if(uError) {
5493 pMe->uLastError = (uint8_t)uError;
5494 return;
5495 }
5496
5497 if(pItem) {
5498 *pItem = Item;
5499 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005500
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005501 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005502}
Laurence Lundbladec4537442020-04-14 18:53:22 -07005503
Laurence Lundbladec4537442020-04-14 18:53:22 -07005504
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005505void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
5506 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005507 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005508 double *pdValue,
5509 QCBORItem *pItem)
5510{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005511 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005512 if(pMe->uLastError != QCBOR_SUCCESS) {
5513 return;
5514 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005515
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005516 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005517}
5518
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005519
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005520void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
5521 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005522 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005523 double *pdValue,
5524 QCBORItem *pItem)
5525{
5526 if(pMe->uLastError != QCBOR_SUCCESS) {
5527 return;
5528 }
5529
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005530 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005531 if(pMe->uLastError != QCBOR_SUCCESS) {
5532 return;
5533 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005534
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005535 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005536}
5537
5538
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005539#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005540static double ConvertBigNumToDouble(const UsefulBufC BigNum)
5541{
5542 double dResult;
5543
5544 dResult = 0.0;
5545 const uint8_t *pByte = BigNum.ptr;
5546 size_t uLen = BigNum.len;
5547 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07005548 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005549 while(uLen--) {
5550 dResult = (dResult * 256.0) + (double)*pByte++;
5551 }
5552
5553 return dResult;
5554}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005555#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5556
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005557
Laurence Lundblade93d89472020-10-03 22:30:50 -07005558static QCBORError
5559DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005560{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005561#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005562 /*
Laurence Lundblade16a207a2021-09-18 17:22:46 -07005563 * What Every Computer Scientist Should Know About Floating-Point Arithmetic
5564 * https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
5565 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005566 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005567
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005568#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005569 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005570 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07005571 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005572 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
5573 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
5574 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005575 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005576 }
5577 break;
5578
5579 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005580 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07005581 // Underflow gives 0, overflow gives infinity
5582 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
5583 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005584 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005585 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005586 }
5587 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005588#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005589
5590 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005591 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005592 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
5593 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005594 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005595 }
5596 break;
5597
5598 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005599 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07005600 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005601 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005602 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005603 }
5604 break;
5605
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005606#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005607 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005608 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005609 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5610 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5611 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005612 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005613 }
5614 break;
5615
5616 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005617 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005618 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5619 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5620 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005621 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005622 }
5623 break;
5624
5625 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005626 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005627 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5628 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5629 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005630 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005631 }
5632 break;
5633
5634 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005635 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07005636 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005637 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5638 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005639 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005640 }
5641 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005642#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005643
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005644 default:
5645 return QCBOR_ERR_UNEXPECTED_TYPE;
5646 }
5647
5648 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005649
5650#else
5651 (void)pItem;
5652 (void)uConvertTypes;
5653 (void)pdValue;
5654 return QCBOR_ERR_HW_FLOAT_DISABLED;
5655#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5656
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005657}
5658
5659
5660/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005661 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005662*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005663void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
5664 uint32_t uConvertTypes,
5665 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005666{
5667
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005668 QCBORItem Item;
5669
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005670 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005671
5672 if(pMe->uLastError == QCBOR_SUCCESS) {
5673 // The above conversion succeeded
5674 return;
5675 }
5676
5677 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5678 // The above conversion failed in a way that code below can't correct
5679 return;
5680 }
5681
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005682 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005683}
5684
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005685
5686/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005687 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005688*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005689void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
5690 int64_t nLabel,
5691 uint32_t uConvertTypes,
5692 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005693{
5694 QCBORItem Item;
5695
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005696 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005697
5698 if(pMe->uLastError == QCBOR_SUCCESS) {
5699 // The above conversion succeeded
5700 return;
5701 }
5702
5703 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5704 // The above conversion failed in a way that code below can't correct
5705 return;
5706 }
5707
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005708 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005709}
5710
5711
5712/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005713 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005714*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005715void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
5716 const char *szLabel,
5717 uint32_t uConvertTypes,
5718 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005719{
5720 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005721 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005722
5723 if(pMe->uLastError == QCBOR_SUCCESS) {
5724 // The above conversion succeeded
5725 return;
5726 }
5727
5728 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5729 // The above conversion failed in a way that code below can't correct
5730 return;
5731 }
5732
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005733 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005734}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02005735#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005736
5737
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005738
5739
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005740#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005741static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
5742{
5743 while((uInt & 0xff00000000000000UL) == 0) {
5744 uInt = uInt << 8;
5745 };
5746
5747 UsefulOutBuf UOB;
5748
5749 UsefulOutBuf_Init(&UOB, Buffer);
5750
5751 while(uInt) {
5752 const uint64_t xx = uInt & 0xff00000000000000UL;
5753 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
5754 uInt = uInt << 8;
5755 (void)xx;
5756 }
5757
5758 return UsefulOutBuf_OutUBuf(&UOB);
5759}
5760
5761
Laurence Lundblade37286c02022-09-03 10:05:02 -07005762/**
5763 * @brief Check and/or complete mantissa and exponent item.
5764 *
5765 * @param[in] pMe The decoder context
5766 * @param[in] TagSpec Expected type(s)
5767 * @param[in,out] pItem See below
5768 *
5769 * This is for decimal fractions and big floats, both of which are a
5770 * mantissa and exponent.
5771 *
5772 * The input item is either a fully decoded decimal faction or big
5773 * float, or a just the decoded first item of a decimal fraction or
5774 * big float.
5775 *
5776 * On output, the item is always a fully decoded decimal fraction or
5777 * big float.
5778 *
5779 * This errors out if the input type does not meet the TagSpec.
5780 */
5781// TODO: document and see tests for the bug that was fixed by this rewrite
5782static QCBORError
5783MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
5784 const TagSpecification TagSpec,
5785 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005786{
5787 QCBORError uErr;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005788
Laurence Lundblade37286c02022-09-03 10:05:02 -07005789 /* pItem could either be an auto-decoded mantissa and exponent or
5790 * the opening array of an undecoded mantissa and exponent. This
5791 * check will succeed on either, but doesn't say which it was.
5792 */
5793 uErr = CheckTagRequirement(TagSpec, pItem);
5794 if(uErr != QCBOR_SUCCESS) {
5795 goto Done;
5796 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005797
Laurence Lundblade37286c02022-09-03 10:05:02 -07005798 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
5799 /* The item is an array, which means is is an undecoded mantissa
5800 * and exponent. This call consumes the items in the array and
5801 * results in a decoded mantissa and exponent in pItem. This is
5802 * the case where there was no tag.
5803 */
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005804 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
5805 if(uErr != QCBOR_SUCCESS) {
5806 goto Done;
5807 }
5808
Laurence Lundblade37286c02022-09-03 10:05:02 -07005809 /* The above decode didn't determine whether it is a decimal
5810 * fraction or big num. Which of these two depends on what the
5811 * caller wants it decoded as since there is no tag, so fish the
5812 * type out of the TagSpec. */
5813 pItem->uDataType = MantissaExponentDataType(TagSpec.uTaggedTypes[0], pItem);
5814
5815 /* No need to check the type again. All that we need to know was
5816 * that it decoded correctly as a mantissa and exponent. The
5817 * QCBOR type is set out by what was requested.
5818 */
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005819 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07005820
5821 /* If the item was not an array and the check passed, then
5822 * it is a fully decoded big float or decimal fraction and
5823 * matches what is requested.
5824 */
5825
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005826Done:
5827 return uErr;
5828}
5829
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005830
Laurence Lundblade37286c02022-09-03 10:05:02 -07005831/* Some notes from the work to disable tags.
5832 *
5833 * The API for big floats and decimal fractions seems good.
5834 * If there's any issue with it it's that the code size to
5835 * implement is a bit large because of the conversion
5836 * to/from int and bignum that is required. There is no API
5837 * that doesn't do the conversion so dead stripping will never
5838 * leave that code out.
5839 *
5840 * The implementation itself seems correct, but not as clean
5841 * and neat as it could be. It could probably be smaller too.
5842 *
5843 * The implementation has three main parts / functions
5844 * - The decoding of the array of two
5845 * - All the tag and type checking for the various API functions
5846 * - Conversion to/from bignum and int
5847 *
5848 * The type checking seems like it wastes the most code for
5849 * what it needs to do.
5850 *
5851 * The inlining for the conversion is probably making the
5852 * overall code base larger.
5853 *
5854 * The tests cases could be organized a lot better and be
5855 * more thorough.
5856 *
5857 * Seems also like there could be more common code in the
5858 * first tier part of the public API. Some functions only
5859 * vary by a TagSpec.
5860 */
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005861static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005862 TagSpecification TagSpec,
5863 QCBORItem *pItem,
5864 int64_t *pnMantissa,
5865 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005866{
5867 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005868
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005869 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005870 if(uErr != QCBOR_SUCCESS) {
5871 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005872 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005873
Laurence Lundblade9b334962020-08-27 10:55:53 -07005874 switch (pItem->uDataType) {
5875
5876 case QCBOR_TYPE_DECIMAL_FRACTION:
5877 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade9b334962020-08-27 10:55:53 -07005878 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade37286c02022-09-03 10:05:02 -07005879 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
Laurence Lundblade9b334962020-08-27 10:55:53 -07005880 break;
5881
Laurence Lundblade37286c02022-09-03 10:05:02 -07005882#ifndef QCBOR_DISABLE_TAGS
5883 /* If tags are disabled, mantissas can never be big nums */
Laurence Lundblade9b334962020-08-27 10:55:53 -07005884 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5885 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5886 *pnExponent = pItem->val.expAndMantissa.nExponent;
5887 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5888 break;
5889
5890 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5891 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5892 *pnExponent = pItem->val.expAndMantissa.nExponent;
5893 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5894 break;
Laurence Lundblade37286c02022-09-03 10:05:02 -07005895#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade9b334962020-08-27 10:55:53 -07005896
5897 default:
5898 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5899 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005900
5901 Done:
5902 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005903}
5904
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005905
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005906static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005907 TagSpecification TagSpec,
5908 QCBORItem *pItem,
5909 UsefulBuf BufferForMantissa,
5910 UsefulBufC *pMantissa,
5911 bool *pbIsNegative,
5912 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005913{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005914 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005915
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005916 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005917 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005918 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005919 }
5920
5921 uint64_t uMantissa;
5922
5923 switch (pItem->uDataType) {
5924
5925 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005926 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005927 /* See comments in ExponentiateNN() on handling INT64_MIN */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005928 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5929 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5930 *pbIsNegative = false;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005931 } else if(pItem->val.expAndMantissa.Mantissa.nInt != INT64_MIN) {
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005932 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5933 *pbIsNegative = true;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005934 } else {
5935 uMantissa = (uint64_t)INT64_MAX+1;
5936 *pbIsNegative = true;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005937 }
5938 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5939 *pnExponent = pItem->val.expAndMantissa.nExponent;
5940 break;
5941
Laurence Lundblade37286c02022-09-03 10:05:02 -07005942#ifndef QCBOR_DISABLE_TAGS
5943 /* If tags are disabled, mantissas can never be big nums */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005944 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005945 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005946 *pnExponent = pItem->val.expAndMantissa.nExponent;
5947 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5948 *pbIsNegative = false;
5949 break;
5950
5951 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005952 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005953 *pnExponent = pItem->val.expAndMantissa.nExponent;
5954 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5955 *pbIsNegative = true;
5956 break;
Laurence Lundblade37286c02022-09-03 10:05:02 -07005957#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005958
5959 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005960 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005961 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005962
5963Done:
5964 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005965}
5966
5967
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005968/*
5969 Public function, see header qcbor/qcbor_decode.h file
5970*/
5971void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5972 uint8_t uTagRequirement,
5973 int64_t *pnMantissa,
5974 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005975{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005976 if(pMe->uLastError != QCBOR_SUCCESS) {
5977 return;
5978 }
5979
5980 QCBORItem Item;
5981 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5982 if(uError) {
5983 pMe->uLastError = (uint8_t)uError;
5984 return;
5985 }
5986
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005987 const TagSpecification TagSpec =
5988 {
5989 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005990 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5991 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5992 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005993 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005994
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005995 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005996}
5997
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005998
5999/*
6000 Public function, see header qcbor/qcbor_decode.h file
6001*/
6002void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006003 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07006004 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006005 int64_t *pnMantissa,
6006 int64_t *pnExponent)
6007{
6008 if(pMe->uLastError != QCBOR_SUCCESS) {
6009 return;
6010 }
6011
6012 QCBORItem Item;
6013 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
6014
6015 const TagSpecification TagSpec =
6016 {
6017 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006018 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6019 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6020 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006021 };
6022
6023 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
6024}
6025
6026
6027/*
6028 Public function, see header qcbor/qcbor_decode.h file
6029*/
6030void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006031 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07006032 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006033 int64_t *pnMantissa,
6034 int64_t *pnExponent)
6035{
6036 if(pMe->uLastError != QCBOR_SUCCESS) {
6037 return;
6038 }
6039
6040 QCBORItem Item;
6041 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6042
6043 const TagSpecification TagSpec =
6044 {
6045 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006046 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6047 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6048 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006049 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07006050
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006051 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
6052}
6053
6054
6055/*
6056 Public function, see header qcbor/qcbor_decode.h file
6057*/
6058void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
6059 uint8_t uTagRequirement,
Laurence Lundblade37286c02022-09-03 10:05:02 -07006060 UsefulBuf MantissaBuffer,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006061 UsefulBufC *pMantissa,
6062 bool *pbMantissaIsNegative,
6063 int64_t *pnExponent)
6064{
6065 if(pMe->uLastError != QCBOR_SUCCESS) {
6066 return;
6067 }
6068
6069 QCBORItem Item;
6070 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6071 if(uError) {
6072 pMe->uLastError = (uint8_t)uError;
6073 return;
6074 }
6075
6076 const TagSpecification TagSpec =
6077 {
6078 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006079 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6080 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6081 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006082 };
6083
Laurence Lundblade93d89472020-10-03 22:30:50 -07006084 ProcessMantissaAndExponentBig(pMe,
6085 TagSpec,
6086 &Item,
6087 MantissaBuffer,
6088 pMantissa,
6089 pbMantissaIsNegative,
6090 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006091}
6092
6093
6094/*
6095 Public function, see header qcbor/qcbor_decode.h file
6096*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006097void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006098 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07006099 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006100 UsefulBuf BufferForMantissa,
6101 UsefulBufC *pMantissa,
6102 bool *pbIsNegative,
6103 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006104{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006105 if(pMe->uLastError != QCBOR_SUCCESS) {
6106 return;
6107 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006108
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006109 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006110 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006111 if(pMe->uLastError != QCBOR_SUCCESS) {
6112 return;
6113 }
6114
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006115 const TagSpecification TagSpec =
6116 {
6117 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006118 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6119 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6120 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006121 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006122
Laurence Lundblade93d89472020-10-03 22:30:50 -07006123 ProcessMantissaAndExponentBig(pMe,
6124 TagSpec,
6125 &Item,
6126 BufferForMantissa,
6127 pMantissa,
6128 pbIsNegative,
6129 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006130}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006131
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006132
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006133/*
6134 Public function, see header qcbor/qcbor_decode.h file
6135*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006136void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006137 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07006138 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006139 UsefulBuf BufferForMantissa,
6140 UsefulBufC *pMantissa,
6141 bool *pbIsNegative,
6142 int64_t *pnExponent)
6143{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006144 if(pMe->uLastError != QCBOR_SUCCESS) {
6145 return;
6146 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006147
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006148 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006149 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6150 if(pMe->uLastError != QCBOR_SUCCESS) {
6151 return;
6152 }
6153
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006154 const TagSpecification TagSpec =
6155 {
6156 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006157 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6158 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6159 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006160 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006161
6162 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
6163}
6164
6165
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006166/*
6167 Public function, see header qcbor/qcbor_decode.h file
6168*/
6169void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
6170 uint8_t uTagRequirement,
6171 int64_t *pnMantissa,
6172 int64_t *pnExponent)
6173{
6174 if(pMe->uLastError != QCBOR_SUCCESS) {
6175 return;
6176 }
6177
6178 QCBORItem Item;
6179 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6180 if(uError) {
6181 pMe->uLastError = (uint8_t)uError;
6182 return;
6183 }
6184 const TagSpecification TagSpec =
6185 {
6186 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006187 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6188 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6189 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006190 };
6191
6192 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
6193}
6194
6195
6196/*
6197 Public function, see header qcbor/qcbor_decode.h file
6198*/
6199void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006200 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07006201 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006202 int64_t *pnMantissa,
6203 int64_t *pnExponent)
6204{
6205 if(pMe->uLastError != QCBOR_SUCCESS) {
6206 return;
6207 }
6208
6209 QCBORItem Item;
6210 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
6211 if(pMe->uLastError != QCBOR_SUCCESS) {
6212 return;
6213 }
6214
6215 const TagSpecification TagSpec =
6216 {
6217 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006218 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6219 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6220 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006221 };
6222
6223 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
6224}
6225
6226
6227/*
6228 Public function, see header qcbor/qcbor_decode.h file
6229*/
6230void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006231 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07006232 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006233 int64_t *pnMantissa,
6234 int64_t *pnExponent)
6235{
6236 if(pMe->uLastError != QCBOR_SUCCESS) {
6237 return;
6238 }
6239
6240 QCBORItem Item;
6241 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6242 if(pMe->uLastError != QCBOR_SUCCESS) {
6243 return;
6244 }
6245
6246 const TagSpecification TagSpec =
6247 {
6248 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006249 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6250 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6251 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006252 };
6253
6254 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
6255}
6256
6257
6258/*
6259 Public function, see header qcbor/qcbor_decode.h file
6260*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006261void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
6262 uint8_t uTagRequirement,
6263 UsefulBuf MantissaBuffer,
6264 UsefulBufC *pMantissa,
6265 bool *pbMantissaIsNegative,
6266 int64_t *pnExponent)
6267{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006268 if(pMe->uLastError != QCBOR_SUCCESS) {
6269 return;
6270 }
6271
6272 QCBORItem Item;
6273 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6274 if(uError) {
6275 pMe->uLastError = (uint8_t)uError;
6276 return;
6277 }
6278
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006279 const TagSpecification TagSpec =
6280 {
6281 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006282 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6283 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6284 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006285 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006286
6287 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006288}
6289
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006290
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006291/*
6292 Public function, see header qcbor/qcbor_decode.h file
6293*/
6294void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006295 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07006296 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006297 UsefulBuf BufferForMantissa,
6298 UsefulBufC *pMantissa,
6299 bool *pbIsNegative,
6300 int64_t *pnExponent)
6301{
6302 if(pMe->uLastError != QCBOR_SUCCESS) {
6303 return;
6304 }
6305
6306 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006307 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
6308 if(pMe->uLastError != QCBOR_SUCCESS) {
6309 return;
6310 }
6311
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006312 const TagSpecification TagSpec =
6313 {
6314 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006315 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6316 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6317 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006318 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006319
Laurence Lundblade93d89472020-10-03 22:30:50 -07006320 ProcessMantissaAndExponentBig(pMe,
6321 TagSpec,
6322 &Item,
6323 BufferForMantissa,
6324 pMantissa,
6325 pbIsNegative,
6326 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006327}
6328
6329
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006330/*
6331 Public function, see header qcbor/qcbor_decode.h file
6332*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006333void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006334 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07006335 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006336 UsefulBuf BufferForMantissa,
6337 UsefulBufC *pMantissa,
6338 bool *pbIsNegative,
6339 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006340{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006341 if(pMe->uLastError != QCBOR_SUCCESS) {
6342 return;
6343 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006344
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006345 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006346 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6347 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006348 return;
6349 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006350
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006351 const TagSpecification TagSpec =
6352 {
6353 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006354 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6355 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6356 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006357 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006358
Laurence Lundblade93d89472020-10-03 22:30:50 -07006359 ProcessMantissaAndExponentBig(pMe,
6360 TagSpec,
6361 &Item,
6362 BufferForMantissa,
6363 pMantissa,
6364 pbIsNegative,
6365 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006366}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006367
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006368#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */