blob: 57aab977030704e7256344038f9c2543202dc51e [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 Lundblade68cb61c2023-02-12 13:21:44 -08003 Copyright (c) 2018-2023, Laurence Lundblade.
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02004 Copyright (c) 2021, Arm Limited.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07005 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08006
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07007Redistribution and use in source and binary forms, with or without
8modification, are permitted provided that the following conditions are
9met:
10 * Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above
13 copyright notice, this list of conditions and the following
14 disclaimer in the documentation and/or other materials provided
15 with the distribution.
16 * Neither the name of The Linux Foundation nor the names of its
17 contributors, nor the name "Laurence Lundblade" may be used to
18 endorse or promote products derived from this software without
19 specific prior written permission.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080020
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070021THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
22WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
24ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
25BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
30OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080032 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070033
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080034
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080035#include "qcbor/qcbor_decode.h"
Laurence Lundblade67257dc2020-07-27 03:33:37 -070036#include "qcbor/qcbor_spiffy_decode.h"
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080037#include "ieee754.h" /* Does not use math.h */
Laurence Lundbladec7114722020-08-13 05:11:40 -070038
39#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080040
41#include <math.h> /* For isnan(), llround(), llroudf(), round(), roundf(),
42 * pow(), exp2()
43 */
44#include <fenv.h> /* feclearexcept(), fetestexcept() */
45
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080046#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070047
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070048
Laurence Lundblade68cb61c2023-02-12 13:21:44 -080049#if (defined(__GNUC__) && !defined(__clang__))
50/*
51 * This is how the -Wmaybe-uninitialized compiler warning is
52 * handled. It can’t be ignored because some version of gcc enable it
53 * with -Wall which is a common and useful gcc warning option. It also
54 * can’t be ignored because it is the goal of QCBOR to compile clean
55 * out of the box in all environments.
56 *
57 * The big problem with -Wmaybe-uninitialized is that it generates
58 * false positives. It complains things are uninitialized when they
59 * are not. This is because it is not a thorough static analyzer. This
60 * is why “maybe” is in its name. The problem is it is just not
61 * thorough enough to understand all the code (and someone saw fit to
62 * put it in gcc and worse to enable it with -Wall).
63 *
64 * One solution would be to change the code so -Wmaybe-uninitialized
65 * doesn’t get confused, for example adding an unnecessary extra
66 * initialization to zero. (If variables were truly uninitialized, the
67 * correct path is to understand the code thoroughly and set them to
68 * the correct value at the correct time; in essence this is already
69 * done; -Wmaybe-uninitialized just can’t tell). This path is not
70 * taken because it makes the code bigger and is kind of the tail
71 * wagging the dog.
72 *
73 * The solution here is to just use a pragma to disable it for the
74 * whole file. Disabling it for each line makes the code fairly ugly
75 * requiring #pragma to push, pop and ignore. Another reason is the
76 * warnings issues vary by version of gcc and which optimization
77 * optimizations are selected. Another reason is that compilers other
78 * than gcc don’t have -Wmaybe-uninitialized.
79 *
80 * One may ask how to be sure these warnings are false positives and
81 * not real issues. 1) The code has been read carefully to check. 2)
82 * Testing is pretty thorough. 3) This code has been run through
83 * thorough high-quality static analyzers.
84 *
85 * In particularly, most of the warnings are about
86 * Item.Item->uDataType being uninitialized. QCBORDecode_GetNext()
87 * *always* sets this value and test case confirm
88 * this. -Wmaybe-uninitialized just can't tell.
89 *
90 * https://stackoverflow.com/questions/5080848/disable-gcc-may-be-used-uninitialized-on-a-particular-variable
91 */
92#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
93#endif
94
95
96
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080097
Laurence Lundbladea9489f82020-09-12 13:50:56 -070098#define SIZEOF_C_ARRAY(array,type) (sizeof(array)/sizeof(type))
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070099
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700100
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800101
102
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700103static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -0700104QCBORItem_IsMapOrArray(const QCBORItem *pMe)
105{
106 const uint8_t uDataType = pMe->uDataType;
107 return uDataType == QCBOR_TYPE_MAP ||
108 uDataType == QCBOR_TYPE_ARRAY ||
109 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
110}
111
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700112static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -0700113QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem *pMe)
114{
115 if(!QCBORItem_IsMapOrArray(pMe)){
116 return false;
117 }
118
119 if(pMe->val.uCount != 0) {
120 return false;
121 }
122 return true;
123}
124
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700125static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -0700126QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem *pMe)
127{
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800128#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -0700129 if(!QCBORItem_IsMapOrArray(pMe)){
130 return false;
131 }
132
133 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
134 return false;
135 }
136 return true;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800137#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
138 (void)pMe;
139 return false;
140#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700141}
142
143
Laurence Lundbladeee851742020-01-08 08:37:05 -0800144/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700145 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -0800146 ===========================================================================*/
147
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700148/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800149 * See comments about and typedef of QCBORDecodeNesting in qcbor_private.h,
150 * the data structure all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700151 */
152
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700153
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700154static inline uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700155DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700156{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700157 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800158 /* Limit in DecodeNesting_Descend against more than
159 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700160 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700161 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700162}
163
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700164
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700165static inline uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700166DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700167{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700168 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800169 /* Limit in DecodeNesting_Descend against more than
170 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700171 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700172 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700173}
174
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700175
Laurence Lundblade5f4e8712020-07-25 11:44:43 -0700176static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700177DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700178{
179 return pNesting->pCurrentBounded->u.ma.uStartOffset;
180}
181
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700182
Laurence Lundblade085d7952020-07-24 10:26:30 -0700183static inline bool
184DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
185{
186 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
187 return true;
188 } else {
189 return false;
190 }
191}
192
193
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700194static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700195DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700196{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700197 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700198 return true;
199 } else {
200 return false;
201 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700202}
203
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700204
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700205static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700206DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700207{
208 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800209 /* Not a map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700210 return false;
211 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800212
213#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700214 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800215 /* Is indefinite */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700216 return false;
217 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800218
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800219#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
220
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800221 /* All checks passed; is a definte length map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700222 return true;
223}
224
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700225static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700226DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700227{
228 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800229 /* is a byte string */
Laurence Lundblade642282a2020-06-23 12:00:33 -0700230 return true;
231 }
232 return false;
233}
234
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700235
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700236static inline bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700237{
238 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
239 return true;
240 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700241 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700242 return true;
243 }
244 return false;
245}
246
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700247
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700248static inline void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700249{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800250 /* Should be only called on maps and arrays */
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700251 /*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800252 * DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
253 * larger than DecodeNesting_EnterBoundedMode which keeps it less than
254 * uin32_t so the cast is safe.
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700255 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700256 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700257
258 if(bIsEmpty) {
259 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
260 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700261}
262
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700263
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700264static inline void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700265{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700266 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700267}
268
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700269
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700270static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700271DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700272{
273 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800274 /* No bounded map or array set up */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700275 return false;
276 }
277 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800278 /* Not a map or array; end of those is by byte count */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700279 return false;
280 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700281 if(!DecodeNesting_IsCurrentBounded(pNesting)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800282 /* In a traveral at a level deeper than the bounded level */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700283 return false;
284 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800285 /* Works for both definite- and indefinitelength maps/arrays */
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800286 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0 &&
287 pNesting->pCurrentBounded->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800288 /* Count is not zero, still unconsumed item */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700289 return false;
290 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800291 /* All checks passed, got to the end of an array or map*/
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700292 return true;
293}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700294
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700295
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700296static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700297DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700298{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800299 /* Must only be called on map / array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700300 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
301 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700302 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700303 return false;
304 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700305}
306
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700307
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700308static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700309DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700310{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700311 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
312 return true;
313 } else {
314 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700315 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700316}
317
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700318
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700319static inline bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700320DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700321{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700322 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700323 return false;
324 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700325
326 if(pNesting->pCurrentBounded->uLevelType != uType) {
327 return false;
328 }
329
330 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700331}
332
Laurence Lundblade02625d42020-06-25 14:41:41 -0700333
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700334static inline void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700335DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700336{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800337 /* Only call on a definite-length array / map */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700338 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700339}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700340
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700341
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700342static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700343DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
344{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800345 /* Only call on a definite-length array / map */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700346 pNesting->pCurrent->u.ma.uCountCursor++;
347}
348
349
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700350static inline void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700351DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
352{
353 pNesting->pCurrent--;
354}
355
Laurence Lundblade02625d42020-06-25 14:41:41 -0700356
357static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700358DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700359{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800360 /* Error out if nesting is too deep */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700361 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700362 return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700363 }
364
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800365 /* The actual descend */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700366 pNesting->pCurrent++;
367
368 pNesting->pCurrent->uLevelType = uType;
369
370 return QCBOR_SUCCESS;
371}
372
373
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700374static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800375DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting,
376 bool bIsEmpty,
377 size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700378{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700379 /*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800380 * Should only be called on map/array.
381 *
382 * Have descended into this before this is called. The job here is
383 * just to mark it in bounded mode.
384 *
385 * Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
386 * uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET.
387 *
388 * Cast of uOffset to uint32_t for cases where SIZE_MAX < UINT32_MAX.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700389 */
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -0800390 if((uint32_t)uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700391 return QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700392 }
393
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700394 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700395
396 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700397
398 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700399}
400
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700401
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700402static inline QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700403DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700404 uint8_t uQCBORType,
405 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700406{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700407 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700408
409 if(uCount == 0) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800410 /* Nothing to do for empty definite-length arrays. They are just are
411 * effectively the same as an item that is not a map or array.
412 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700413 goto Done;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800414 /* Empty indefinite-length maps and arrays are handled elsewhere */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700415 }
416
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800417 /* Error out if arrays is too long to handle */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700418 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
419 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700420 uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700421 goto Done;
422 }
423
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700424 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700425 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700426 goto Done;
427 }
428
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800429 /* Fill in the new map/array level. Check above makes casts OK. */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700430 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
431 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700432
433 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700434
435Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700436 return uError;;
437}
438
439
440static inline void
441DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
442{
443 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
444}
445
446
447static inline void
448DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
449{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700450 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700451 pNesting->pCurrentBounded--;
452 if(DecodeNesting_IsCurrentBounded(pNesting)) {
453 break;
454 }
455 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700456}
457
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800458
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700459static inline void
460DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
461{
462 pNesting->pCurrent = pNesting->pCurrentBounded;
463}
464
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700465
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700466static inline QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700467DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700468 uint32_t uEndOffset,
469 uint32_t uStartOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700470{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700471 QCBORError uError;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700472
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700473 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700474 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700475 goto Done;
476 }
477
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800478 /* Fill in the new byte string level */
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700479 pNesting->pCurrent->u.bs.uSavedEndOffset = uEndOffset;
480 pNesting->pCurrent->u.bs.uBstrStartOffset = uStartOffset;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700481
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800482 /* Bstr wrapped levels are always bounded */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700483 pNesting->pCurrentBounded = pNesting->pCurrent;
484
485Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700486 return uError;;
487}
488
Laurence Lundbladed0304932020-06-27 10:59:38 -0700489
490static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700491DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700492{
493 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700494}
495
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700496
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700497static inline void
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800498DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
499{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700500 if(pNesting->pCurrent->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
501 pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
502 }
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800503}
504
505
506static inline void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700507DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700508{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700509 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700510 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
511 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700512}
513
514
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700515static inline void
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800516DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting,
517 QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700518{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700519 *pSave = *pNesting;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700520}
521
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700522
Laurence Lundblade02625d42020-06-25 14:41:41 -0700523static inline void
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800524DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting,
525 const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700526{
527 *pNesting = *pSave;
528}
529
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700530
Laurence Lundblade02625d42020-06-25 14:41:41 -0700531static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700532DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700533{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700534 return pMe->pCurrentBounded->u.bs.uSavedEndOffset;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700535}
536
537
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800538
539
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800540#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladeee851742020-01-08 08:37:05 -0800541/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800542 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
543
544 The following four functions are pretty wrappers for invocation of
545 the string allocator supplied by the caller.
546
Laurence Lundbladeee851742020-01-08 08:37:05 -0800547 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800548
Laurence Lundbladeee851742020-01-08 08:37:05 -0800549static inline void
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800550StringAllocator_Free(const QCBORInternalAllocator *pMe, const void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800551{
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300552 /* This cast to uintptr_t suppresses the "-Wcast-qual" warnings.
553 * This is the one place where the const needs to be cast away so const can
554 * be use in the rest of the code.
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800555 */
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300556 (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)(uintptr_t)pMem, 0);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800557}
558
Laurence Lundbladeee851742020-01-08 08:37:05 -0800559// StringAllocator_Reallocate called with pMem NULL is
560// equal to StringAllocator_Allocate()
561static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800562StringAllocator_Reallocate(const QCBORInternalAllocator *pMe,
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800563 const void *pMem,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800564 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800565{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800566 /* See comment in StringAllocator_Free() */
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300567 return (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)(uintptr_t)pMem, uSize);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800568}
569
Laurence Lundbladeee851742020-01-08 08:37:05 -0800570static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800571StringAllocator_Allocate(const QCBORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800572{
573 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
574}
575
Laurence Lundbladeee851742020-01-08 08:37:05 -0800576static inline void
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800577StringAllocator_Destruct(const QCBORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800578{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800579 /* See comment in StringAllocator_Free() */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800580 if(pMe->pfAllocator) {
581 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
582 }
583}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800584#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800585
586
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800587
588
Laurence Lundbladeee851742020-01-08 08:37:05 -0800589/*===========================================================================
590 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700591
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800592 See qcbor/qcbor_decode.h for definition of the object
593 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800594 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700595/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800596 * Public function, see header file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700597 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800598void QCBORDecode_Init(QCBORDecodeContext *pMe,
599 UsefulBufC EncodedCBOR,
600 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700601{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800602 memset(pMe, 0, sizeof(QCBORDecodeContext));
603 UsefulInputBuf_Init(&(pMe->InBuf), EncodedCBOR);
604 /* Don't bother with error check on decode mode. If a bad value is
605 * passed it will just act as if the default normal mode of 0 was set.
606 */
607 pMe->uDecodeMode = (uint8_t)nDecodeMode;
608 DecodeNesting_Init(&(pMe->nesting));
609
610 /* Inialize me->auMappedTags to CBOR_TAG_INVALID16. See
611 * GetNext_TaggedItem() and MapTagNumber(). */
612 memset(pMe->auMappedTags, 0xff, sizeof(pMe->auMappedTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700613}
614
615
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800616#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
617
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700618/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800619 * Public function, see header file
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700620 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800621void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
622 QCBORStringAllocate pfAllocateFunction,
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800623 void *pAllocateContext,
624 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700625{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800626 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
627 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
628 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700629}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800630#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700631
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800632
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800633
634
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800635/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800636 * Deprecated public function, see header file
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800637 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800638void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800639 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700640{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800641 /* This does nothing now. It is retained for backwards compatibility */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700642 (void)pMe;
643 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700644}
645
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700646
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800647
648
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700649/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800650 * Decoding items is done in six layers, one calling the next one
651 * down. If a layer has no work to do for a particular item, it
652 * returns quickly.
653 *
654 * 1. QCBORDecode_GetNextTagContent - The top layer processes tagged
655 * data items, turning them into the local C representation. For the
656 * most simple it is just associating a QCBOR_TYPE with the data. For
657 * the complex ones that an aggregate of data items, there is some
658 * further decoding and some limited recursion.
659 *
660 * 2. QCBORDecode_GetNextMapOrArray - This manages the beginnings and
661 * ends of maps and arrays. It tracks descending into and ascending
662 * out of maps/arrays. It processes breaks that terminate
663 * indefinite-length maps and arrays.
664 *
665 * 3. QCBORDecode_GetNextMapEntry - This handles the combining of two
666 * items, the label and the data, that make up a map entry. It only
667 * does work on maps. It combines the label and data items into one
668 * labeled item.
669 *
670 * 4. QCBORDecode_GetNextTagNumber - This decodes type 6 tag
671 * numbers. It turns the tag numbers into bit flags associated with
672 * the data item. No actual decoding of the contents of the tag is
673 * performed here.
674 *
675 * 5. QCBORDecode_GetNextFullString - This assembles the sub-items
676 * that make up an indefinite-length string into one string item. It
677 * uses the string allocator to create contiguous space for the
678 * item. It processes all breaks that are part of indefinite-length
679 * strings.
680 *
681 * 6. DecodeAtomicDataItem - This decodes the atomic data items in
682 * CBOR. Each atomic data item has a "major type", an integer
683 * "argument" and optionally some content. For text and byte strings,
684 * the content is the bytes that make up the string. These are the
685 * smallest data items that are considered to be well-formed. The
686 * content may also be other data items in the case of aggregate
687 * types. They are not handled in this layer.
688 *
689 * Roughly this takes 300 bytes of stack for vars. TODO: evaluate this
690 * more carefully and correctly.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700691 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800692
693
694/*
695 * Note about use of int and unsigned variables.
696 *
697 * See http://www.unix.org/whitepapers/64bit.html for reasons int is
698 * used carefully here, and in particular why it isn't used in the
699 * public interface. Also see
700 * https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
701 *
702 * Int is used for values that need less than 16-bits and would be
703 * subject to integer promotion and result in complaining from static
704 * analyzers.
705 */
706
707
708/**
709 * @brief Decode the CBOR head, the type and argument.
710 *
711 * @param[in] pUInBuf The input buffer to read from.
712 * @param[out] pnMajorType The decoded major type.
713 * @param[out] puArgument The decoded argument.
714 * @param[out] pnAdditionalInfo The decoded Lower 5 bits of initial byte.
715 *
716 * @retval QCBOR_ERR_UNSUPPORTED
717 * @retval QCBOR_ERR_HIT_END
718 *
719 * This decodes the CBOR "head" that every CBOR data item has. See
720 * longer explaination of the head in documentation for
721 * QCBOREncode_EncodeHead().
722 *
723 * This does the network->host byte order conversion. The conversion
724 * here also results in the conversion for floats in addition to that
725 * for lengths, tags and integer values.
726 *
727 * The int type is preferred to uint8_t for some variables as this
728 * avoids integer promotions, can reduce code size and makes static
729 * analyzers happier.
730 */
731static inline QCBORError
732DecodeHead(UsefulInputBuf *pUInBuf,
733 int *pnMajorType,
734 uint64_t *puArgument,
735 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700736{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800737 QCBORError uReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800738
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800739 /* Get the initial byte that every CBOR data item has and break it
740 * down. */
741 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800742 const int nTmpMajorType = nInitialByte >> 5;
743 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800744
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800745 /* Where the argument accumulates */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800746 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800747
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800748 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800749 /* Need to get 1,2,4 or 8 additional argument bytes. Map
750 * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
751 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800752 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800753
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800754 /* Loop getting all the bytes in the argument */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800755 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800756 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800757 /* This shift and add gives the endian conversion. */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800758 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
759 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800760 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800761 /* The reserved and thus-far unused additional info values */
762 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800763 goto Done;
764 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800765 /* Less than 24, additional info is argument or 31, an
766 * indefinite-length. No more bytes to get.
767 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800768 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700769 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800770
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700771 if(UsefulInputBuf_GetError(pUInBuf)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800772 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700773 goto Done;
774 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800775
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800776 /* All successful if arrived here. */
777 uReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800778 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800779 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800780 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800781
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700782Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800783 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700784}
785
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800786
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800787/**
788 * @brief Decode integer types, major types 0 and 1.
789 *
790 * @param[in] nMajorType The CBOR major type (0 or 1).
791 * @param[in] uArgument The argument from the head.
792 * @param[out] pDecodedItem The filled in decoded item.
793 *
794 * @retval QCBOR_ERR_INT_OVERFLOW
795 *
796 * Must only be called when major type is 0 or 1.
797 *
798 * CBOR doesn't explicitly specify two's compliment for integers but
799 * all CPUs use it these days and the test vectors in the RFC are
800 * so. All integers in the CBOR structure are positive and the major
801 * type indicates positive or negative. CBOR can express positive
802 * integers up to 2^x - 1 where x is the number of bits and negative
803 * integers down to 2^x. Note that negative numbers can be one more
804 * away from zero than positive. Stdint, as far as I can tell, uses
805 * two's compliment to represent negative integers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700806 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700807static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800808DecodeInteger(int nMajorType, uint64_t uArgument, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700809{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800810 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800811
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700812 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800813 if (uArgument <= INT64_MAX) {
814 pDecodedItem->val.int64 = (int64_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700815 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800816
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700817 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800818 pDecodedItem->val.uint64 = uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700819 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700820 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800821
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700822 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800823 if(uArgument <= INT64_MAX) {
824 /* CBOR's representation of negative numbers lines up with
825 * the two-compliment representation. A negative integer has
826 * one more in range than a positive integer. INT64_MIN is
827 * equal to (-INT64_MAX) - 1.
828 */
829 pDecodedItem->val.int64 = (-(int64_t)uArgument) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700830 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800831
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700832 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800833 /* C can't represent a negative integer in this range so it
834 * is an error.
835 */
836 uReturn = QCBOR_ERR_INT_OVERFLOW;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700837 }
838 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800839
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800840 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700841}
842
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800843
844/* Make sure #define value line up as DecodeSimple counts on this. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700845#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
846#error QCBOR_TYPE_FALSE macro value wrong
847#endif
848
849#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
850#error QCBOR_TYPE_TRUE macro value wrong
851#endif
852
853#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
854#error QCBOR_TYPE_NULL macro value wrong
855#endif
856
857#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
858#error QCBOR_TYPE_UNDEF macro value wrong
859#endif
860
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700861#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
862#error QCBOR_TYPE_BREAK macro value wrong
863#endif
864
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700865#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
866#error QCBOR_TYPE_DOUBLE macro value wrong
867#endif
868
869#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
870#error QCBOR_TYPE_FLOAT macro value wrong
871#endif
872
Laurence Lundblade9b334962020-08-27 10:55:53 -0700873
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800874/**
875 * @brief Decode major type 7 -- true, false, floating-point, break...
876 *
877 * @param[in] nAdditionalInfo The lower five bits from the initial byte.
878 * @param[in] uArgument The argument from the head.
879 * @param[out] pDecodedItem The filled in decoded item.
880 *
881 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200882 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800883 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700884 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800885
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800886static inline QCBORError
887DecodeType7(int nAdditionalInfo, uint64_t uArgument, QCBORItem *pDecodedItem)
888{
889 QCBORError uReturn = QCBOR_SUCCESS;
890
891 /* uAdditionalInfo is 5 bits from the initial byte. Compile time
892 * checks above make sure uAdditionalInfo values line up with
893 * uDataType values. DecodeHead() never returns an AdditionalInfo
894 * > 0x1f so cast is safe.
895 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800896 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800897
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800898 switch(nAdditionalInfo) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800899 /* No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they
900 * are caught before this is called.
901 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800902
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800903 case HALF_PREC_FLOAT: /* 25 */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700904#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800905 /* Half-precision is returned as a double. The cast to
906 * uint16_t is safe because the encoded value was 16 bits. It
907 * was widened to 64 bits to be passed in here.
908 */
909 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700910 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800911#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200912 uReturn = FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700913 break;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800914 case SINGLE_PREC_FLOAT: /* 26 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200915#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800916 /* Single precision is normally returned as a double since
917 * double is widely supported, there is no loss of precision,
918 * it makes it easy for the caller in most cases and it can
919 * be converted back to single with no loss of precision
920 *
921 * The cast to uint32_t is safe because the encoded value was
922 * 32 bits. It was widened to 64 bits to be passed in here.
923 */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700924 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800925 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uArgument);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700926#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800927 /* In the normal case, use HW to convert float to
928 * double. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700929 pDecodedItem->val.dfnum = (double)f;
930 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800931#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800932 /* Use of float HW is disabled, return as a float. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700933 pDecodedItem->val.fnum = f;
934 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
935
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800936 /* IEEE754_FloatToDouble() could be used here to return as
937 * a double, but it adds object code and most likely
938 * anyone disabling FLOAT HW use doesn't care about floats
939 * and wants to save object code.
940 */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800941#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700942 }
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200943#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
944 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700945 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700946
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800947 case DOUBLE_PREC_FLOAT: /* 27 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200948#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800949 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700950 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200951#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
952 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700953 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800954
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800955 case CBOR_SIMPLEV_FALSE: /* 20 */
956 case CBOR_SIMPLEV_TRUE: /* 21 */
957 case CBOR_SIMPLEV_NULL: /* 22 */
958 case CBOR_SIMPLEV_UNDEF: /* 23 */
959 case CBOR_SIMPLE_BREAK: /* 31 */
960 break; /* nothing to do */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800961
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800962 case CBOR_SIMPLEV_ONEBYTE: /* 24 */
963 if(uArgument <= CBOR_SIMPLE_BREAK) {
964 /* This takes out f8 00 ... f8 1f which should be encoded
965 * as e0 … f7
966 */
967 uReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700968 goto Done;
969 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800970 /* FALLTHROUGH */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800971
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800972 default: /* 0-19 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700973 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800974 /* DecodeHead() will make uArgument equal to
975 * nAdditionalInfo when nAdditionalInfo is < 24. This cast is
976 * safe because the 2, 4 and 8 byte lengths of uNumber are in
977 * the double/float cases above
Laurence Lundbladeee851742020-01-08 08:37:05 -0800978 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800979 pDecodedItem->val.uSimple = (uint8_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700980 break;
981 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800982
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700983Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800984 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700985}
986
987
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800988/**
989 * @brief Decode text and byte strings
990 *
991 * @param[in] pAllocator The string allocator or NULL.
992 * @param[in] uStrLen The length of the string.
993 * @param[in] pUInBuf The surce from which to read the string's bytes.
994 * @param[out] pDecodedItem The filled in decoded item.
995 *
996 * @retval QCBOR_ERR_HIT_END
997 * @retval QCBOR_ERR_STRING_ALLOCATE
998 * @retval QCBOR_ERR_STRING_TOO_LONG
999 *
1000 * The reads @c uStrlen bytes from @c pUInBuf and fills in @c
1001 * pDecodedItem. If @c pAllocator is not NULL then memory for the
1002 * string is allocated.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001003 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001004static inline QCBORError
1005DecodeBytes(const QCBORInternalAllocator *pAllocator,
1006 uint64_t uStrLen,
1007 UsefulInputBuf *pUInBuf,
1008 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001009{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001010 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001011
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001012 /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
1013 * CPUs. This check makes the casts to size_t below safe.
1014 *
1015 * The max is 4 bytes less than the largest sizeof() so this can be
1016 * tested by putting a SIZE_MAX length in the CBOR test input (no
1017 * one will care the limit on strings is 4 bytes shorter).
1018 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001019 if(uStrLen > SIZE_MAX-4) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001020 uReturn = QCBOR_ERR_STRING_TOO_LONG;
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001021 goto Done;
1022 }
1023
1024 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301025 if(UsefulBuf_IsNULLC(Bytes)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001026 /* Failed to get the bytes for this string item */
1027 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301028 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001029 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301030
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001031#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001032 /* Note that this is not where allocation to coalesce
1033 * indefinite-length strings is done. This is for when the caller
1034 * has requested all strings be allocated. Disabling indefinite
1035 * length strings also disables this allocate-all option.
1036 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001037 if(pAllocator) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001038 /* request to use the string allocator to make a copy */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001039 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301040 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001041 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301042 goto Done;
1043 }
1044 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001045 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001046 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301047 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001048#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1049 (void)pAllocator;
1050#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1051
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001052 /* Normal case with no string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001053 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001054
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301055Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001056 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001057}
1058
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001059
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001060/**
1061 * @brief Map the CBOR major types for strings to the QCBOR types.
1062 *
1063 * @param[in] nCBORMajorType The CBOR major type to convert.
1064 * @retturns QCBOR type number.
1065 *
1066 * This only works for the two string types.
1067 */
1068static inline uint8_t ConvertStringMajorTypes(int nCBORMajorType)
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001069{
1070 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
1071 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
1072 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001073
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001074 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
1075 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
1076 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001077
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001078 return (uint8_t)(nCBORMajorType + 4);
1079}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001080
1081
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001082/**
1083 * @brief Map the CBOR major types for arrays/maps to the QCBOR types.
1084 *
1085 * @param[in] nCBORMajorType The CBOR major type to convert.
1086 * @retturns QCBOR type number.
1087 *
1088 * This only works for the two aggregate types.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001089 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001090static inline uint8_t ConvertArrayOrMapType(int nCBORMajorType)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001091{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001092 #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
1093 #error QCBOR_TYPE_ARRAY value not lined up with major type
1094 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001095
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001096 #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
1097 #error QCBOR_TYPE_MAP value not lined up with major type
1098 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001099
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001100 return (uint8_t)(nCBORMajorType);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001101}
1102
1103
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001104/**
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001105 * @brief Decode a single primitive data item (decode layer 6).
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001106 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001107 * @param[in] pUInBuf Input buffer to read data item from.
1108 * @param[out] pDecodedItem The filled-in decoded item.
1109 * @param[in] pAllocator The allocator to use for strings or NULL.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001110 *
1111 * @retval QCBOR_ERR_UNSUPPORTED
1112 * @retval QCBOR_ERR_HIT_END
1113 * @retval QCBOR_ERR_INT_OVERFLOW
1114 * @retval QCBOR_ERR_STRING_ALLOCATE
1115 * @retval QCBOR_ERR_STRING_TOO_LONG
1116 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001117 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001118 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001119 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1120 *
1121 * This decodes the most primitive / atomic data item. It does
1122 * no combing of data items.
1123 */
1124static QCBORError
1125DecodeAtomicDataItem(UsefulInputBuf *pUInBuf,
1126 QCBORItem *pDecodedItem,
1127 const QCBORInternalAllocator *pAllocator)
1128{
1129 QCBORError uReturn;
1130
1131 /* Get the major type and the argument. The argument could be
1132 * length of more bytes or the value depending on the major
1133 * type. nAdditionalInfo is an encoding of the length of the
1134 * uNumber and is needed to decode floats and doubles.
1135 */
1136 int nMajorType = 0;
1137 uint64_t uArgument = 0;
1138 int nAdditionalInfo = 0;
1139
1140 memset(pDecodedItem, 0, sizeof(QCBORItem));
1141
1142 uReturn = DecodeHead(pUInBuf, &nMajorType, &uArgument, &nAdditionalInfo);
1143 if(uReturn) {
1144 goto Done;
1145 }
1146
1147 /* At this point the major type and the argument are valid. We've
1148 * got the type and the argument that starts every CBOR data item.
1149 */
1150 switch (nMajorType) {
1151 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1152 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
1153 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1154 uReturn = QCBOR_ERR_BAD_INT;
1155 } else {
1156 uReturn = DecodeInteger(nMajorType, uArgument, pDecodedItem);
1157 }
1158 break;
1159
1160 case CBOR_MAJOR_TYPE_BYTE_STRING: /* Major type 2 */
1161 case CBOR_MAJOR_TYPE_TEXT_STRING: /* Major type 3 */
1162 pDecodedItem->uDataType = ConvertStringMajorTypes(nMajorType);
1163 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1164 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
1165 } else {
1166 uReturn = DecodeBytes(pAllocator, uArgument, pUInBuf, pDecodedItem);
1167 }
1168 break;
1169
1170 case CBOR_MAJOR_TYPE_ARRAY: /* Major type 4 */
1171 case CBOR_MAJOR_TYPE_MAP: /* Major type 5 */
1172 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1173 /* Indefinite-length string. */
1174#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
1175 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
1176#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1177 uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
1178 break;
1179#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1180 } else {
1181 /* Definite-length string. */
1182 if(uArgument > QCBOR_MAX_ITEMS_IN_ARRAY) {
1183 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
1184 goto Done;
1185 }
1186 /* cast OK because of check above */
1187 pDecodedItem->val.uCount = (uint16_t)uArgument;
1188 }
1189 pDecodedItem->uDataType = ConvertArrayOrMapType(nMajorType);
1190 break;
1191
1192 case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */
Laurence Lundblade37286c02022-09-03 10:05:02 -07001193#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001194 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1195 uReturn = QCBOR_ERR_BAD_INT;
1196 } else {
1197 pDecodedItem->val.uTagV = uArgument;
1198 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
1199 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07001200#else /* QCBOR_DISABLE_TAGS */
1201 uReturn = QCBOR_ERR_TAGS_DISABLED;
1202#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001203 break;
1204
1205 case CBOR_MAJOR_TYPE_SIMPLE:
1206 /* Major type 7: float, double, true, false, null... */
1207 uReturn = DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
1208 break;
1209
1210 default:
1211 /* Never happens because DecodeHead() should never return > 7 */
1212 uReturn = QCBOR_ERR_UNSUPPORTED;
1213 break;
1214 }
1215
1216Done:
1217 return uReturn;
1218}
1219
1220
1221/**
1222 * @brief Process indefinite-length strings (decode layer 5).
1223 *
1224 * @param[in] pMe Decoder context
1225 * @param[out] pDecodedItem The decoded item that work is done on.
1226 *
1227 * @retval QCBOR_ERR_UNSUPPORTED
1228 * @retval QCBOR_ERR_HIT_END
1229 * @retval QCBOR_ERR_INT_OVERFLOW
1230 * @retval QCBOR_ERR_STRING_ALLOCATE
1231 * @retval QCBOR_ERR_STRING_TOO_LONG
1232 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001233 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001234 * @retval QCBOR_ERR_BAD_TYPE_7
1235 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001236 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1237 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001238 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001239 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001240 * If @c pDecodedItem is not an indefinite-length string, this does nothing.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001241 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001242 * If it is, this loops getting the subsequent chunk data items that
1243 * make up the string. The string allocator is used to make a
1244 * contiguous buffer for the chunks. When this completes @c
1245 * pDecodedItem contains the put-together string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001246 *
1247 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001248 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001249static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001250QCBORDecode_GetNextFullString(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001251{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001252 /* Aproximate stack usage
1253 * 64-bit 32-bit
1254 * local vars 32 16
1255 * 2 UsefulBufs 32 16
1256 * QCBORItem 56 52
1257 * TOTAL 120 74
1258 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001259
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001260 /* The string allocator is used here for two purposes: 1)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001261 * coalescing the chunks of an indefinite-length string, 2)
1262 * allocating storage for every string returned when requested.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001263 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001264 * The first use is below in this function. Indefinite-length
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001265 * strings cannot be processed at all without a string allocator.
1266 *
1267 * The second used is in DecodeBytes() which is called by
1268 * GetNext_Item() below. This second use unneccessary for most use
1269 * and only happens when requested in the call to
1270 * QCBORDecode_SetMemPool(). If the second use not requested then
1271 * NULL is passed for the string allocator to GetNext_Item().
1272 *
1273 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1274 * allocator altogether and thus both of these uses. It reduced the
1275 * decoder object code by about 400 bytes.
1276 */
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001277 const QCBORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001278
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001279#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001280 const QCBORInternalAllocator *pAllocator = NULL;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001281
1282 if(pMe->StringAllocator.pfAllocator) {
1283 pAllocator = &(pMe->StringAllocator);
1284 if(pMe->bStringAllocateAll) {
1285 pAllocatorForGetNext = pAllocator;
1286 }
1287 }
1288#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1289
1290 QCBORError uReturn;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001291 uReturn = DecodeAtomicDataItem(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001292 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001293 goto Done;
1294 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001295
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001296 /* Only do indefinite-length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001297 const uint8_t uStringType = pDecodedItem->uDataType;
1298 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001299 goto Done;
1300 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001301
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001302 /* Is this a string with an indefinite length? */
1303 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1304 goto Done;
1305 }
1306
1307#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001308 /* Can't decode indefinite-length strings without a string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001309 if(pAllocator == NULL) {
1310 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1311 goto Done;
1312 }
1313
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001314 /* Loop getting chunks of the indefinite-length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001315 UsefulBufC FullString = NULLUsefulBufC;
1316
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001317 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001318 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001319 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001320 /* Pass a NULL string allocator to GetNext_Item() because the
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001321 * individual string chunks in an indefinite-length should not
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001322 * be allocated. They are always copied in the the contiguous
1323 * buffer allocated here.
1324 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001325 uReturn = DecodeAtomicDataItem(&(pMe->InBuf), &StringChunkItem, NULL);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001326 if(uReturn) {
1327 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001328 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001329
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001330 /* Is item is the marker for end of the indefinite-length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001331 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001332 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001333 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301334 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001335 break;
1336 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001337
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001338 /* All chunks must be of the same type, the type of the item
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001339 * that introduces the indefinite-length string. This also
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001340 * catches errors where the chunk is not a string at all and an
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001341 * indefinite-length string inside an indefinite-length string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001342 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001343 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001344 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1345 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001346 break;
1347 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001348
David Navarro9123e5b2022-03-28 16:04:03 +02001349 if (StringChunkItem.val.string.len > 0) {
1350 /* The first time throurgh FullString.ptr is NULL and this is
1351 * equivalent to StringAllocator_Allocate(). Subsequently it is
1352 * not NULL and a reallocation happens.
1353 */
1354 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1355 FullString.ptr,
1356 FullString.len + StringChunkItem.val.string.len);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001357
David Navarro9123e5b2022-03-28 16:04:03 +02001358 if(UsefulBuf_IsNULL(NewMem)) {
1359 uReturn = QCBOR_ERR_STRING_ALLOCATE;
1360 break;
1361 }
1362
1363 /* Copy new string chunk to the end of accumulated string */
1364 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001365 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001366 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001367
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001368 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1369 /* Getting the item failed, clean up the allocated memory */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001370 StringAllocator_Free(pAllocator, FullString.ptr);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001371 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001372#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1373 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1374#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001375
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001376Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001377 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001378}
1379
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001380
Laurence Lundblade37286c02022-09-03 10:05:02 -07001381#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001382/**
1383 * @brief This converts a tag number to a shorter mapped value for storage.
1384 *
1385 * @param[in] pMe The decode context.
1386 * @param[in] uUnMappedTag The tag number to map
1387 * @param[out] puMappedTagNumer The stored tag number.
1388 *
1389 * @return error code.
1390 *
1391 * The main point of mapping tag numbers is make QCBORItem
1392 * smaller. With this mapping storage of 4 tags takes up 8
1393 * bytes. Without, it would take up 32 bytes.
1394 *
1395 * This maps tag numbers greater than QCBOR_LAST_UNMAPPED_TAG.
1396 * QCBOR_LAST_UNMAPPED_TAG is a little smaller than MAX_UINT16.
1397 *
1398 * See also UnMapTagNumber() and @ref QCBORItem.
1399 */
1400static inline QCBORError
1401MapTagNumber(QCBORDecodeContext *pMe, uint64_t uUnMappedTag, uint16_t *puMappedTagNumer)
1402{
1403 if(uUnMappedTag > QCBOR_LAST_UNMAPPED_TAG) {
1404 unsigned uTagMapIndex;
1405 /* Is there room in the tag map, or is it in it already? */
1406 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
1407 if(pMe->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID64) {
1408 break;
1409 }
1410 if(pMe->auMappedTags[uTagMapIndex] == uUnMappedTag) {
1411 break;
1412 }
1413 }
1414 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1415 return QCBOR_ERR_TOO_MANY_TAGS;
1416 }
1417
1418 /* Covers the cases where tag is new and were it is already in the map */
1419 pMe->auMappedTags[uTagMapIndex] = uUnMappedTag;
1420 *puMappedTagNumer = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
1421
1422 } else {
1423 *puMappedTagNumer = (uint16_t)uUnMappedTag;
1424 }
1425
1426 return QCBOR_SUCCESS;
1427}
1428
1429
1430/**
1431 * @brief This converts a mapped tag number to the actual tag number.
1432 *
1433 * @param[in] pMe The decode context.
1434 * @param[in] uMappedTagNumber The stored tag number.
1435 *
1436 * @return The actual tag number is returned or
1437 * @ref CBOR_TAG_INVALID64 on error.
1438 *
1439 * This is the reverse of MapTagNumber()
1440 */
1441static uint64_t
1442UnMapTagNumber(const QCBORDecodeContext *pMe, uint16_t uMappedTagNumber)
1443{
1444 if(uMappedTagNumber <= QCBOR_LAST_UNMAPPED_TAG) {
1445 return uMappedTagNumber;
1446 } else if(uMappedTagNumber == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001447 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001448 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001449 /* This won't be negative because of code below in
1450 * MapTagNumber()
1451 */
1452 const unsigned uIndex = uMappedTagNumber - (QCBOR_LAST_UNMAPPED_TAG + 1);
1453 return pMe->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001454 }
1455}
Laurence Lundblade37286c02022-09-03 10:05:02 -07001456#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001457
Laurence Lundblade9b334962020-08-27 10:55:53 -07001458
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001459/**
1460 * @brief Aggregate all tags wrapping a data item (decode layer 4).
1461 *
1462 * @param[in] pMe Decoder context
1463 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001464
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001465 * @retval QCBOR_ERR_UNSUPPORTED
1466 * @retval QCBOR_ERR_HIT_END
1467 * @retval QCBOR_ERR_INT_OVERFLOW
1468 * @retval QCBOR_ERR_STRING_ALLOCATE
1469 * @retval QCBOR_ERR_STRING_TOO_LONG
1470 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001471 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001472 * @retval QCBOR_ERR_BAD_TYPE_7
1473 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1474 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1475 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1476 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1477 * @retval QCBOR_ERR_TOO_MANY_TAGS
1478 *
1479 * This loops getting atomic data items until one is not a tag
1480 * number. Usually this is largely pass-through because most
1481 * item are not tag numbers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001482 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001483static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001484QCBORDecode_GetNextTagNumber(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001485{
Laurence Lundblade37286c02022-09-03 10:05:02 -07001486#ifndef QCBOR_DISABLE_TAGS
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001487 /* Accummulate the tags from multiple items here and then copy them
1488 * into the last item, the non-tag item.
1489 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001490 uint16_t auItemsTags[QCBOR_MAX_TAGS_PER_ITEM];
1491
1492 /* Initialize to CBOR_TAG_INVALID16 */
1493 #if CBOR_TAG_INVALID16 != 0xffff
1494 /* Be sure the memset does the right thing. */
1495 #err CBOR_TAG_INVALID16 tag not defined as expected
1496 #endif
1497 memset(auItemsTags, 0xff, sizeof(auItemsTags));
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001498
Laurence Lundblade9b334962020-08-27 10:55:53 -07001499 QCBORError uReturn = QCBOR_SUCCESS;
1500
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001501 /* Loop fetching data items until the item fetched is not a tag */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001502 for(;;) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001503 QCBORError uErr = QCBORDecode_GetNextFullString(pMe, pDecodedItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07001504 if(uErr != QCBOR_SUCCESS) {
1505 uReturn = uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001506 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001507 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001508
Laurence Lundblade9b334962020-08-27 10:55:53 -07001509 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001510 /* Successful exit from loop; maybe got some tags, maybe not */
1511 memcpy(pDecodedItem->uTags, auItemsTags, sizeof(auItemsTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001512 break;
1513 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001514
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001515 if(auItemsTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1516 /* No room in the tag list */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001517 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001518 /* Continue on to get all tags wrapping this item even though
1519 * it is erroring out in the end. This allows decoding to
1520 * continue. This is a resource limit error, not a problem
1521 * with being well-formed CBOR.
1522 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001523 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001524 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001525 /* Slide tags over one in the array to make room at index 0.
1526 * Must use memmove because the move source and destination
1527 * overlap.
1528 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001529 memmove(&auItemsTags[1],
1530 auItemsTags,
1531 sizeof(auItemsTags) - sizeof(auItemsTags[0]));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001532
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001533 /* Map the tag */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001534 uint16_t uMappedTagNumber = 0;
1535 uReturn = MapTagNumber(pMe, pDecodedItem->val.uTagV, &uMappedTagNumber);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001536 /* Continue even on error so as to consume all tags wrapping
1537 * this data item so decoding can go on. If MapTagNumber()
1538 * errors once it will continue to error.
1539 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001540 auItemsTags[0] = uMappedTagNumber;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001541 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001542
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001543Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001544 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001545
Laurence Lundblade37286c02022-09-03 10:05:02 -07001546#else /* QCBOR_DISABLE_TAGS */
1547
1548 return QCBORDecode_GetNextFullString(pMe, pDecodedItem);
1549
1550#endif /* QCBOR_DISABLE_TAGS */
1551}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001552
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001553/**
1554 * @brief Combine a map entry label and value into one item (decode layer 3).
1555 *
1556 * @param[in] pMe Decoder context
1557 * @param[out] pDecodedItem The decoded item that work is done on.
1558 *
1559 * @retval QCBOR_ERR_UNSUPPORTED
1560 * @retval QCBOR_ERR_HIT_END
1561 * @retval QCBOR_ERR_INT_OVERFLOW
1562 * @retval QCBOR_ERR_STRING_ALLOCATE
1563 * @retval QCBOR_ERR_STRING_TOO_LONG
1564 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001565 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001566 * @retval QCBOR_ERR_BAD_TYPE_7
1567 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1568 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1569 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1570 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1571 * @retval QCBOR_ERR_TOO_MANY_TAGS
1572 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1573 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1574 *
1575 * If a the current nesting level is a map, then this
1576 * combines pairs of items into one data item with a label
1577 * and value.
1578 *
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07001579 * This is passthrough if the current nesting level is
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001580 * not a map.
1581 *
1582 * This also implements maps-as-array mode where a map
1583 * is treated like an array to allow caller to do their
1584 * own label processing.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001585 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001586static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001587QCBORDecode_GetNextMapEntry(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001588{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001589 QCBORError uReturn = QCBORDecode_GetNextTagNumber(pMe, pDecodedItem);
1590 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001591 goto Done;
1592 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001593
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001594 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
1595 /* Break can't be a map entry */
1596 goto Done;
1597 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001598
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001599 if(pMe->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1600 /* Normal decoding of maps -- combine label and value into one item. */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001601
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001602 if(DecodeNesting_IsCurrentTypeMap(&(pMe->nesting))) {
1603 /* Save label in pDecodedItem and get the next which will
1604 * be the real data item.
1605 */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001606 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001607 uReturn = QCBORDecode_GetNextTagNumber(pMe, pDecodedItem);
1608 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001609 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001610 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001611
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301612 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001613
1614 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001615 /* strings are always good labels */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001616 pDecodedItem->label.string = LabelItem.val.string;
1617 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001618 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == pMe->uDecodeMode) {
1619 /* It's not a string and we only want strings */
1620 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001621 goto Done;
1622 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1623 pDecodedItem->label.int64 = LabelItem.val.int64;
1624 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1625 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1626 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1627 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1628 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1629 pDecodedItem->label.string = LabelItem.val.string;
1630 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1631 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1632 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001633 /* label is not an int or a string. It is an arrray
1634 * or a float or such and this implementation doesn't handle that.
1635 * Also, tags on labels are ignored.
1636 */
1637 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001638 goto Done;
1639 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001640 }
1641 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001642 /* Decoding of maps as arrays to let the caller decide what to do
1643 * about labels, particularly lables that are not integers or
1644 * strings.
1645 */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001646 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001647 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001648 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001649 goto Done;
1650 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001651 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001652 /* Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2.
1653 * Cast is needed because of integer promotion.
1654 */
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001655 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001656 }
1657 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001658
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001659Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001660 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001661}
1662
1663
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001664#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001665/**
1666 * @brief Peek and see if next data item is a break;
1667 *
1668 * @param[in] pUIB UsefulInputBuf to read from.
1669 * @param[out] pbNextIsBreak Indicate if next was a break or not.
1670 *
1671 * @return Any decoding error.
1672 *
1673 * See if next item is a CBOR break. If it is, it is consumed,
1674 * if not it is not consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001675*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001676static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001677NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1678{
1679 *pbNextIsBreak = false;
1680 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001681 QCBORItem Peek;
1682 size_t uPeek = UsefulInputBuf_Tell(pUIB);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001683 QCBORError uReturn = DecodeAtomicDataItem(pUIB, &Peek, NULL);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001684 if(uReturn != QCBOR_SUCCESS) {
1685 return uReturn;
1686 }
1687 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001688 /* It is not a break, rewind so it can be processed normally. */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001689 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001690 } else {
1691 *pbNextIsBreak = true;
1692 }
1693 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001694
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001695 return QCBOR_SUCCESS;
1696}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001697#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001698
1699
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001700/**
1701 * @brief Ascend up nesting levels if all items in them have been consumed.
1702 *
1703 * @param[in] pMe The decode context.
1704 * @param[in] bMarkEnd If true mark end of maps/arrays with count of zero.
1705 *
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001706 * An item was just consumed, now figure out if it was the
1707 * end of an array/map map that can be closed out. That
1708 * may in turn close out the above array/map...
Laurence Lundblade642282a2020-06-23 12:00:33 -07001709*/
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001710static QCBORError
1711QCBORDecode_NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001712{
1713 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001714
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001715 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001716 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1717
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001718 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1719 /* Nesting level is bstr-wrapped CBOR */
1720
1721 /* Ascent for bstr-wrapped CBOR is always by explicit call
1722 * so no further ascending can happen.
1723 */
1724 break;
1725
1726 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1727 /* Level is a definite-length array/map */
1728
1729 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001730 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1731 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001732 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001733 break;
1734 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001735 /* All items in a definite-length array were consumed so it
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001736 * is time to ascend one level. This happens below.
1737 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001738
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001739#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001740 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001741 /* Level is an indefinite-length array/map. */
1742
1743 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001744 bool bIsBreak = false;
1745 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1746 if(uReturn != QCBOR_SUCCESS) {
1747 goto Done;
1748 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001749
1750 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001751 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001752 break;
1753 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001754
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001755 /* It was a break in an indefinitelength map / array so
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001756 * it is time to ascend one level.
1757 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001758
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001759#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001760 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001761
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001762
1763 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001764
Laurence Lundblade93d89472020-10-03 22:30:50 -07001765 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001766 * QCBORDecode_ExitBoundedMode().
1767 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001768 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001769 /* Set the count to zero for definite-length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001770 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001771 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001772 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001773 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001774
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001775 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001776 break;
1777 }
1778
1779 /* Finally, actually ascend one level. */
1780 DecodeNesting_Ascend(&(pMe->nesting));
1781 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001782
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001783 uReturn = QCBOR_SUCCESS;
1784
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001785#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001786Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001787#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1788
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001789 return uReturn;
1790}
1791
1792
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001793/**
1794 * @brief Ascending & Descending out of nesting levels (decode layer 2).
1795 *
1796 * @param[in] pMe Decoder context
1797 * @param[out] pDecodedItem The decoded item that work is done on.
1798 *
1799 * @retval QCBOR_ERR_UNSUPPORTED
1800 * @retval QCBOR_ERR_HIT_END
1801 * @retval QCBOR_ERR_INT_OVERFLOW
1802 * @retval QCBOR_ERR_STRING_ALLOCATE
1803 * @retval QCBOR_ERR_STRING_TOO_LONG
1804 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001805 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001806 * @retval QCBOR_ERR_BAD_TYPE_7
1807 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1808 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1809 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1810 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1811 * @retval QCBOR_ERR_TOO_MANY_TAGS
1812 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1813 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1814 * @retval QCBOR_ERR_NO_MORE_ITEMS
1815 * @retval QCBOR_ERR_BAD_BREAK
1816 * @retval QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
1817 *
1818 * This handles the traversal descending into and asecnding out of
1819 * maps, arrays and bstr-wrapped CBOR. It figures out the ends of
1820 * definite- and indefinte-length maps and arrays by looking at the
1821 * item count or finding CBOR breaks. It detects the ends of the
1822 * top-level sequence and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001823 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001824static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001825QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001826{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001827 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001828 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001829
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001830 /* If out of bytes to consume, it is either the end of the
1831 * top-level sequence of some bstr-wrapped CBOR that was entered.
1832 *
1833 * In the case of bstr-wrapped CBOR, the length of the
1834 * UsefulInputBuf was set to that of the bstr-wrapped CBOR. When
1835 * the bstr-wrapped CBOR is exited, the length is set back to the
1836 * top-level's length or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001837 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001838 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001839 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001840 goto Done;
1841 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001842
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001843 /* Check to see if at the end of a bounded definite-length map or
1844 * array. The check for a break ending indefinite-length array is
1845 * later in QCBORDecode_NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001846 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001847 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001848 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001849 goto Done;
1850 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001851
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001852 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001853 uReturn = QCBORDecode_GetNextMapEntry(pMe, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001854 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1855 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001856 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001857 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301858
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001859 /* Breaks ending arrays/maps are processed later in the call to
1860 * QCBORDecode_NestLevelAscender(). They should never show up here.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001861 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301862 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001863 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301864 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301865 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001866
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001867 /* Record the nesting level for this data item before processing
1868 * any of decrementing and descending.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001869 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001870 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001871
Laurence Lundblade642282a2020-06-23 12:00:33 -07001872
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001873 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001874 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001875 /* If the new item is a map or array, descend.
1876 *
1877 * Empty indefinite-length maps and arrays are descended into,
1878 * but then ascended out of in the next chunk of code.
1879 *
1880 * Maps and arrays do count as items in the map/array that
1881 * encloses them so a decrement needs to be done for them too,
1882 * but that is done only when all the items in them have been
1883 * processed, not when they are opened with the exception of an
1884 * empty map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001885 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001886 QCBORError uDescendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001887 uDescendErr = DecodeNesting_DescendMapOrArray(&(pMe->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001888 pDecodedItem->uDataType,
1889 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001890 if(uDescendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001891 /* This error is probably a traversal error and it overrides
1892 * the non-traversal error.
1893 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001894 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001895 goto Done;
1896 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001897 }
1898
Laurence Lundblade02625d42020-06-25 14:41:41 -07001899 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1900 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1901 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001902 /* The following cases are handled here:
1903 * - A non-aggregate item like an integer or string
1904 * - An empty definite-length map or array
1905 * - An indefinite-length map or array that might be empty or might not.
1906 *
1907 * QCBORDecode_NestLevelAscender() does the work of decrementing the count
1908 * for an definite-length map/array and break detection for an
1909 * indefinite-0length map/array. If the end of the map/array was
1910 * reached, then it ascends nesting levels, possibly all the way
1911 * to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001912 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001913 QCBORError uAscendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001914 uAscendErr = QCBORDecode_NestLevelAscender(pMe, true);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001915 if(uAscendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001916 /* This error is probably a traversal error and it overrides
1917 * the non-traversal error.
1918 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001919 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001920 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001921 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301922 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001923
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001924 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001925 /* Tell the caller what level is next. This tells them what
1926 * maps/arrays were closed out and makes it possible for them to
1927 * reconstruct the tree with just the information returned in a
1928 * QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001929 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001930 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001931 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001932 pDecodedItem->uNextNestLevel = 0;
1933 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001934 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001935 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001936
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001937Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001938 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001939}
1940
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001941
Laurence Lundblade37286c02022-09-03 10:05:02 -07001942#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001943/**
1944 * @brief Shift 0th tag out of the tag list.
1945 *
1946 * pDecodedItem[in,out] The data item to convert.
1947 *
1948 * The 0th tag is discarded. \ref CBOR_TAG_INVALID16 is
1949 * shifted into empty slot at the end of the tag list.
1950 */
1951static inline void ShiftTags(QCBORItem *pDecodedItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07001952{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001953 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM-1; i++) {
1954 pDecodedItem->uTags[i] = pDecodedItem->uTags[i+1];
1955 }
1956 pDecodedItem->uTags[QCBOR_MAX_TAGS_PER_ITEM-1] = CBOR_TAG_INVALID16;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001957}
1958
Laurence Lundblade37286c02022-09-03 10:05:02 -07001959#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001960
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001961/**
1962 * @brief Convert different epoch date formats in to the QCBOR epoch date format
1963 *
1964 * pDecodedItem[in,out] The data item to convert.
1965 *
1966 * @retval QCBOR_ERR_DATE_OVERFLOW
1967 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001968 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07001969 * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001970 *
1971 * The epoch date tag defined in QCBOR allows for floating-point
1972 * dates. It even allows a protocol to flop between date formats when
1973 * ever it wants. Floating-point dates aren't that useful as they are
1974 * only needed for dates beyond the age of the earth.
1975 *
1976 * This converts all the date formats into one format of an unsigned
1977 * integer plus a floating-point fraction.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001978 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001979static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001980{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001981 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001982
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001983#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade59289e52019-12-30 13:44:37 -08001984 pDecodedItem->val.epochDate.fSecondsFraction = 0;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001985#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001986
1987 switch (pDecodedItem->uDataType) {
1988
1989 case QCBOR_TYPE_INT64:
1990 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1991 break;
1992
1993 case QCBOR_TYPE_UINT64:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001994 /* This only happens for CBOR type 0 > INT64_MAX so it is
1995 * always an overflow.
1996 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07001997 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1998 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001999 break;
2000
2001 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07002002 case QCBOR_TYPE_FLOAT:
2003#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08002004 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002005 /* Convert working value to double if input was a float */
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07002006 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002007 pDecodedItem->val.dfnum :
2008 (double)pDecodedItem->val.fnum;
2009
2010 /* The conversion from float to integer requires overflow
2011 * detection since floats can be much larger than integers.
2012 * This implementation errors out on these large float values
2013 * since they are beyond the age of the earth.
2014 *
2015 * These constants for the overflow check are computed by the
2016 * compiler. They are not computed at run time.
2017 *
2018 * The factor of 0x7ff is added/subtracted to avoid a
2019 * rounding error in the wrong direction when the compiler
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002020 * computes these constants. There is rounding because a
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002021 * 64-bit integer has 63 bits of precision where a double
2022 * only has 53 bits. Without the 0x7ff factor, the compiler
2023 * may round up and produce a double for the bounds check
2024 * that is larger than can be stored in a 64-bit integer. The
2025 * amount of 0x7ff is picked because it has 11 bits set.
2026 *
2027 * Without the 0x7ff there is a ~30 minute range of time
2028 * values 10 billion years in the past and in the future
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002029 * where this code could go wrong. Some compilers
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002030 * generate a warning or error without the 0x7ff.
2031 */
2032 const double dDateMax = (double)(INT64_MAX - 0x7ff);
2033 const double dDateMin = (double)(INT64_MIN + 0x7ff);
2034
2035 if(isnan(d) || d > dDateMax || d < dDateMin) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07002036 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002037 goto Done;
2038 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002039
2040 /* The actual conversion */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002041 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07002042 pDecodedItem->val.epochDate.fSecondsFraction =
2043 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002044 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002045#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade4b270642020-08-14 12:53:07 -07002046
Laurence Lundblade16a207a2021-09-18 17:22:46 -07002047 uReturn = QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07002048 goto Done;
2049
Laurence Lundblade9682a532020-06-06 18:33:04 -07002050#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002051 break;
2052
2053 default:
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002054 /* It's the arrays and maps that are unrecoverable because
2055 * they are not consumed here. Since this is just an error
2056 * condition, no extra code is added here to make the error
2057 * recoverable for non-arrays and maps like strings. */
2058 uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002059 goto Done;
2060 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002061
Laurence Lundblade59289e52019-12-30 13:44:37 -08002062 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
2063
2064Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07002065 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002066}
2067
2068
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002069/**
2070 * @brief Convert the days epoch date.
2071 *
2072 * pDecodedItem[in,out] The data item to convert.
2073 *
2074 * @retval QCBOR_ERR_DATE_OVERFLOW
2075 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002076 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002077 * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002078 *
2079 * This is much simpler than the other epoch date format because
2080 * floating-porint is not allowed. This is mostly a simple type check.
2081 */
2082static QCBORError DecodeDaysEpoch(QCBORItem *pDecodedItem)
2083{
2084 QCBORError uReturn = QCBOR_SUCCESS;
2085
2086 switch (pDecodedItem->uDataType) {
2087
2088 case QCBOR_TYPE_INT64:
2089 pDecodedItem->val.epochDays = pDecodedItem->val.int64;
2090 break;
2091
2092 case QCBOR_TYPE_UINT64:
2093 /* This only happens for CBOR type 0 > INT64_MAX so it is
2094 * always an overflow.
2095 */
2096 uReturn = QCBOR_ERR_DATE_OVERFLOW;
2097 goto Done;
2098 break;
2099
2100 default:
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002101 /* It's the arrays and maps that are unrecoverable because
2102 * they are not consumed here. Since this is just an error
2103 * condition, no extra code is added here to make the error
2104 * recoverable for non-arrays and maps like strings. */
2105 uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002106 goto Done;
2107 break;
2108 }
2109
2110 pDecodedItem->uDataType = QCBOR_TYPE_DAYS_EPOCH;
2111
2112Done:
2113 return uReturn;
2114}
2115
2116
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002117#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade37286c02022-09-03 10:05:02 -07002118
2119/* Forward declaration is necessary for
2120 * QCBORDecode_MantissaAndExponent(). to be able to decode bignum
2121 * tags in the mantissa. If the mantissa is a decimal fraction or big
2122 * float in error, this will result in a recurive call to
2123 * QCBORDecode_MantissaAndExponent(), but the recursion will unwined
2124 * correctly and the correct error is returned.
2125 */
2126static QCBORError
2127QCBORDecode_GetNextTagContent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem);
2128
2129
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002130/**
2131 * @brief Decode decimal fractions and big floats.
2132 *
2133 * @param[in] pMe The decode context.
2134 * @param[in,out] pDecodedItem On input the array data item that
2135 * holds the mantissa and exponent. On
2136 * output the decoded mantissa and
2137 * exponent.
2138 *
2139 * @returns Decoding errors from getting primitive data items or
2140 * \ref QCBOR_ERR_BAD_EXP_AND_MANTISSA.
2141 *
Laurence Lundblade37286c02022-09-03 10:05:02 -07002142 * When called pDecodedItem must be the array with two members, the
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002143 * exponent and mantissa.
2144 *
2145 * This will fetch and decode the exponent and mantissa and put the
2146 * result back into pDecodedItem.
Laurence Lundblade37286c02022-09-03 10:05:02 -07002147 *
2148 * This does no checking or processing of tag numbers. That is to be
2149 * done by the code that calls this.
2150 *
2151 * This stuffs the type of the mantissa into pDecodedItem with the expectation
2152 * the caller will process it.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002153 */
Laurence Lundblade37286c02022-09-03 10:05:02 -07002154static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002155QCBORDecode_MantissaAndExponent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002156{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002157 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002158
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002159 /* --- Make sure it is an array; track nesting level of members --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002160 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002161 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002162 goto Done;
2163 }
2164
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002165 /* A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundblade37286c02022-09-03 10:05:02 -07002166 * definite-length arrays, but not for indefinite. Instead remember
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002167 * the nesting level the two integers must be at, which is one
2168 * deeper than that of the array.
2169 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002170 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
2171
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002172 /* --- Get the exponent --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002173 QCBORItem exponentItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002174 uReturn = QCBORDecode_GetNextMapOrArray(pMe, &exponentItem);
2175 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002176 goto Done;
2177 }
2178 if(exponentItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002179 /* Array is empty or a map/array encountered when expecting an int */
2180 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002181 goto Done;
2182 }
2183 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002184 /* Data arriving as an unsigned int < INT64_MAX has been
2185 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2186 * also means that the only data arriving here of type
2187 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2188 * and thus an error that will get handled in the next else.
2189 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002190 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
2191 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002192 /* Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX */
2193 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002194 goto Done;
2195 }
2196
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002197 /* --- Get the mantissa --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002198 QCBORItem mantissaItem;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002199 uReturn = QCBORDecode_GetNextTagContent(pMe, &mantissaItem);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002200 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002201 goto Done;
2202 }
2203 if(mantissaItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002204 /* Mantissa missing or map/array encountered when expecting number */
2205 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002206 goto Done;
2207 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002208 /* Stuff the mantissa data type into the item to send it up to the
2209 * the next level. */
2210 pDecodedItem->uDataType = mantissaItem.uDataType;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002211 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002212 /* Data arriving as an unsigned int < INT64_MAX has been
2213 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2214 * also means that the only data arriving here of type
2215 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2216 * and thus an error that will get handled in an else below.
2217 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002218 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002219#ifndef QCBOR_DISABLE_TAGS
2220 /* With tags fully disabled a big number mantissa will error out
2221 * in the call to QCBORDecode_GetNextWithTags() because it has
2222 * a tag number.
2223 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002224 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
2225 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002226 /* Got a good big num mantissa */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002227 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002228#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002229 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002230 /* Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX */
2231 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002232 goto Done;
2233 }
2234
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002235 /* --- Check that array only has the two numbers --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002236 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002237 /* Extra items in the decimal fraction / big float */
Laurence Lundblade37286c02022-09-03 10:05:02 -07002238 /* Improvement: this should probably be an unrecoverable error. */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002239 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002240 goto Done;
2241 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002242 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002243
2244Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002245 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002246}
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002247#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002248
2249
Laurence Lundblade37286c02022-09-03 10:05:02 -07002250#ifndef QCBOR_DISABLE_TAGS
2251
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002252#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002253/**
2254 * @brief Decode the MIME type tag
2255 *
2256 * @param[in,out] pDecodedItem The item to decode.
2257 *
2258 * Handle the text and binary MIME type tags. Slightly too complicated
2259 * f or ProcessTaggedString() because the RFC 7049 MIME type was
2260 * incorreclty text-only.
2261 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002262static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002263{
2264 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
2265 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07002266 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002267 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
2268 } else {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002269 /* It's the arrays and maps that are unrecoverable because
2270 * they are not consumed here. Since this is just an error
2271 * condition, no extra code is added here to make the error
2272 * recoverable for non-arrays and maps like strings. */
2273 return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002274 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002275
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002276 return QCBOR_SUCCESS;
2277}
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002278#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002279
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002280/**
Laurence Lundblade99615302020-11-29 11:19:47 -08002281 * Table of CBOR tags whose content is either a text string or a byte
2282 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
2283 * of uQCBORtype indicates the content should be a byte string rather
2284 * than a text string
2285 */
2286struct StringTagMapEntry {
2287 uint16_t uTagNumber;
2288 uint8_t uQCBORtype;
2289};
2290
2291#define IS_BYTE_STRING_BIT 0x80
2292#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
2293
2294static const struct StringTagMapEntry StringTagMap[] = {
2295 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002296 {CBOR_TAG_DAYS_STRING, QCBOR_TYPE_DAYS_STRING},
Laurence Lundblade99615302020-11-29 11:19:47 -08002297 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
2298 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
2299 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
2300 {CBOR_TAG_URI, QCBOR_TYPE_URI},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002301#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002302 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
2303 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
2304 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
2305 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002306#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade99615302020-11-29 11:19:47 -08002307 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
2308 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
2309};
2310
2311
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002312/**
2313 * @brief Process standard CBOR tags whose content is a string
2314 *
2315 * @param[in] uTag The tag.
2316 * @param[in,out] pDecodedItem The data item.
2317 *
2318 * @returns This returns QCBOR_SUCCESS if the tag was procssed,
2319 * \ref QCBOR_ERR_UNSUPPORTED if the tag was not processed and
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002320 * \ref QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT if the content type was wrong for the tag.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002321 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002322 * Process the CBOR tags that whose content is a byte string or a text
2323 * string and for which the string is just passed on to the caller.
2324 *
2325 * This maps the CBOR tag to the QCBOR type and checks the content
2326 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08002327 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08002328 * possible.
Laurence Lundblade99615302020-11-29 11:19:47 -08002329 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002330static inline QCBORError
2331ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002332{
Laurence Lundblade99615302020-11-29 11:19:47 -08002333 /* This only works on tags that were not mapped; no need for other yet */
2334 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
2335 return QCBOR_ERR_UNSUPPORTED;
2336 }
2337
2338 unsigned uIndex;
2339 for(uIndex = 0; StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
2340 if(StringTagMap[uIndex].uTagNumber == uTag) {
2341 break;
2342 }
2343 }
2344
2345 const uint8_t uQCBORType = StringTagMap[uIndex].uQCBORtype;
2346 if(uQCBORType == QCBOR_TYPE_NONE) {
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002347 /* repurpose this error to mean not handled here */
Laurence Lundblade99615302020-11-29 11:19:47 -08002348 return QCBOR_ERR_UNSUPPORTED;
2349 }
2350
2351 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
2352 if(uQCBORType & IS_BYTE_STRING_BIT) {
2353 uExpectedType = QCBOR_TYPE_BYTE_STRING;
2354 }
2355
2356 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002357 /* It's the arrays and maps that are unrecoverable because
2358 * they are not consumed here. Since this is just an error
2359 * condition, no extra code is added here to make the error
2360 * recoverable for non-arrays and maps like strings. */
2361 return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002362 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002363
Laurence Lundblade99615302020-11-29 11:19:47 -08002364 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002365 return QCBOR_SUCCESS;
2366}
Laurence Lundblade37286c02022-09-03 10:05:02 -07002367#endif /* QCBOR_DISABLE_TAGS */
2368
2369
2370#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
2371/*
2372 * This returns the QCBOR_TYPE for a mantissa and exponent.
2373
2374Called in one context where there is always a tag
2375
2376 Called in another context where there might be a tag or the caller might say what they are expecting.
2377
2378 6 possible outputs
2379 */
2380static inline uint8_t
2381MantissaExponentDataType(const uint16_t uTagToProcess, const QCBORItem *pDecodedItem)
2382{
2383 uint8_t uBase = uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ?
2384 QCBOR_TYPE_DECIMAL_FRACTION :
2385 QCBOR_TYPE_BIGFLOAT;
2386 if(pDecodedItem->uDataType != QCBOR_TYPE_INT64) {
2387 uBase = (uint8_t)(uBase + pDecodedItem->uDataType - QCBOR_TYPE_POSBIGNUM + 1);
2388 }
2389 return uBase;
2390}
2391#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002392
2393
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002394/**
2395 * @brief Decode tag content for select tags (decoding layer 1).
2396 *
2397 * @param[in] pMe The decode context.
2398 * @param[out] pDecodedItem The decoded item.
2399 *
2400 * @return Decoding error code.
2401 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002402 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
2403 * but the whole tag was not decoded. Here, the whole tags (tag number
2404 * and tag content) that are supported by QCBOR are decoded. This is a
2405 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002406 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002407static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002408QCBORDecode_GetNextTagContent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002409{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002410 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002411
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002412 uReturn = QCBORDecode_GetNextMapOrArray(pMe, pDecodedItem);
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002413 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002414 goto Done;
2415 }
2416
Laurence Lundblade37286c02022-09-03 10:05:02 -07002417#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002418 /* When there are no tag numbers for the item, this exits first
2419 * thing and effectively does nothing.
2420 *
2421 * This loops over all the tag numbers accumulated for this item
2422 * trying to decode and interpret them. This stops at the end of
2423 * the list or at the first tag number that can't be interpreted by
2424 * this code. This is effectively a recursive processing of the
2425 * tags number list that handles nested tags.
2426 */
2427 while(1) {
2428 /* Don't bother to unmap tags via QCBORITem.uTags since this
2429 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2430 */
2431 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002432
Laurence Lundblade99615302020-11-29 11:19:47 -08002433 if(uTagToProcess == CBOR_TAG_INVALID16) {
2434 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002435 break;
2436
Laurence Lundblade99615302020-11-29 11:19:47 -08002437 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002438 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002439
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002440 } else if(uTagToProcess == CBOR_TAG_DAYS_EPOCH) {
2441 uReturn = DecodeDaysEpoch(pDecodedItem);
2442
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002443#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002444 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2445 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002446 uReturn = QCBORDecode_MantissaAndExponent(pMe, pDecodedItem);
Laurence Lundblade37286c02022-09-03 10:05:02 -07002447 /* --- Which is it, decimal fraction or a bigfloat? --- */
2448 pDecodedItem->uDataType = MantissaExponentDataType(uTagToProcess, pDecodedItem);
2449
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002450#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002451#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002452 } else if(uTagToProcess == CBOR_TAG_MIME ||
2453 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002454 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002455#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002456
Laurence Lundblade99615302020-11-29 11:19:47 -08002457 } else {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002458 /* See if it is a passthrough byte/text string tag; process if so */
Laurence Lundblade99615302020-11-29 11:19:47 -08002459 uReturn = ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002460
Laurence Lundblade99615302020-11-29 11:19:47 -08002461 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002462 /* It wasn't a passthrough byte/text string tag so it is
Laurence Lundblade99615302020-11-29 11:19:47 -08002463 * an unknown tag. This is the exit from the loop on the
2464 * first unknown tag. It is a successful exit.
2465 */
2466 uReturn = QCBOR_SUCCESS;
2467 break;
2468 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002469 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002470
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002471 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002472 /* Error exit from the loop */
2473 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002474 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002475
2476 /* A tag was successfully processed, shift it out of the list of
2477 * tags returned. This is the loop increment.
2478 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002479 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002480 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002481#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002482
2483Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002484 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002485}
2486
2487
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002488/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002489 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002490 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002491QCBORError
2492QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2493{
2494 QCBORError uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002495 uErr = QCBORDecode_GetNextTagContent(pMe, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002496 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002497 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2498 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2499 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002500 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002501}
2502
2503
2504/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002505 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002506 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002507QCBORError
2508QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2509{
2510 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2511 const UsefulInputBuf Save = pMe->InBuf;
2512
2513 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2514
2515 pMe->nesting = SaveNesting;
2516 pMe->InBuf = Save;
2517
2518 return uErr;
2519}
2520
2521
2522/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002523 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002524 */
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002525void
2526QCBORDecode_VPeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2527{
2528 if(pMe->uLastError != QCBOR_SUCCESS) {
2529 return;
2530 }
2531
2532 pMe->uLastError = (uint8_t)QCBORDecode_PeekNext(pMe, pDecodedItem);
2533}
2534
2535
2536/*
2537 * Public function, see header qcbor/qcbor_decode.h file
2538 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002539void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2540{
2541 if(pMe->uLastError != QCBOR_SUCCESS) {
2542 return;
2543 }
2544
2545 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2546}
2547
2548
2549/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002550 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002551 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002552QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002553QCBORDecode_GetNextWithTags(QCBORDecodeContext *pMe,
2554 QCBORItem *pDecodedItem,
2555 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002556{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002557#ifndef QCBOR_DISABLE_TAGS
2558
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002559 QCBORError uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002560
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002561 uReturn = QCBORDecode_GetNext(pMe, pDecodedItem);
2562 if(uReturn != QCBOR_SUCCESS) {
2563 return uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002564 }
2565
2566 if(pTags != NULL) {
2567 pTags->uNumUsed = 0;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002568 /* Reverse the order because pTags is reverse of QCBORItem.uTags. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002569 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2570 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002571 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002572 }
2573 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2574 return QCBOR_ERR_TOO_MANY_TAGS;
2575 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002576 pTags->puTags[pTags->uNumUsed] = UnMapTagNumber(pMe,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002577 pTags->uNumUsed++;
2578 }
2579 }
2580
2581 return QCBOR_SUCCESS;
Laurence Lundblade37286c02022-09-03 10:05:02 -07002582
2583#else /* QCBOR_DISABLE_TAGS */
2584 (void)pMe;
2585 (void)pDecodedItem;
2586 (void)pTags;
2587 return QCBOR_ERR_TAGS_DISABLED;
2588#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002589}
2590
2591
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002592/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002593 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302594 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002595bool QCBORDecode_IsTagged(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002596 const QCBORItem *pItem,
2597 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002598{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002599#ifndef QCBOR_DISABLE_TAGS
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002600 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2601 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002602 break;
2603 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002604 if(UnMapTagNumber(pMe, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002605 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002606 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002607 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002608#else /* QCBOR_TAGS_DISABLED */
2609 (void)pMe;
2610 (void)pItem;
2611 (void)uTag;
2612#endif /* QCBOR_TAGS_DISABLED */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002613
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002614 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002615}
2616
2617
2618/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002619 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002620 */
Laurence Lundblade87495732021-02-26 10:05:55 -07002621QCBORError QCBORDecode_PartialFinish(QCBORDecodeContext *pMe, size_t *puConsumed)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002622{
Laurence Lundblade87495732021-02-26 10:05:55 -07002623 if(puConsumed != NULL) {
2624 *puConsumed = pMe->InBuf.cursor;
2625 }
2626
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002627 QCBORError uReturn = pMe->uLastError;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002628
2629 if(uReturn != QCBOR_SUCCESS) {
2630 goto Done;
2631 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002632
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002633 /* Error out if all the maps/arrays are not closed out */
2634 if(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002635 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002636 goto Done;
2637 }
2638
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002639 /* Error out if not all the bytes are consumed */
2640 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002641 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002642 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002643
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002644Done:
Laurence Lundblade87495732021-02-26 10:05:55 -07002645 return uReturn;
2646}
2647
2648
2649/*
2650 * Public function, see header qcbor/qcbor_decode.h file
2651 */
2652QCBORError QCBORDecode_Finish(QCBORDecodeContext *pMe)
2653{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002654#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002655 /* Call the destructor for the string allocator if there is one.
2656 * Always called, even if there are errors; always have to clean up.
2657 */
2658 StringAllocator_Destruct(&(pMe->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002659#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002660
Laurence Lundblade87495732021-02-26 10:05:55 -07002661 return QCBORDecode_PartialFinish(pMe, NULL);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002662}
2663
2664
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002665/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002666 * Public function, see header qcbor/qcbor_decode.h file
2667 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002668// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002669uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2670 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002671 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002672{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002673#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002674 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2675 return CBOR_TAG_INVALID64;
2676 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002677 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2678 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002679 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002680 return UnMapTagNumber(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002681 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002682#else /* QCBOR_DISABLE_TAGS */
2683 (void)pMe;
2684 (void)pItem;
2685 (void)uIndex;
2686
2687 return CBOR_TAG_INVALID64;
2688#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002689}
2690
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002691
Laurence Lundblade9b334962020-08-27 10:55:53 -07002692/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002693 * Public function, see header qcbor/qcbor_decode.h file
2694 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002695uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2696 uint32_t uIndex)
2697{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002698#ifndef QCBOR_DISABLE_TAGS
2699
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002700 if(pMe->uLastError != QCBOR_SUCCESS) {
2701 return CBOR_TAG_INVALID64;
2702 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002703 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2704 return CBOR_TAG_INVALID64;
2705 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002706 return UnMapTagNumber(pMe, pMe->uLastTags[uIndex]);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002707 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07002708#else /* QCBOR_DISABLE_TAGS */
2709 (void)pMe;
2710 (void)uIndex;
2711
2712 return CBOR_TAG_INVALID64;
2713#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002714}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002715
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002716
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002717
2718
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002719#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002720
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002721/* ===========================================================================
2722 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002723
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002724 This implements a simple sting allocator for indefinite-length
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002725 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2726 implements the function type QCBORStringAllocate and allows easy
2727 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002728
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002729 This particular allocator is built-in for convenience. The caller
2730 can implement their own. All of this following code will get
2731 dead-stripped if QCBORDecode_SetMemPool() is not called.
2732
2733 This is a very primitive memory allocator. It does not track
2734 individual allocations, only a high-water mark. A free or
2735 reallocation must be of the last chunk allocated.
2736
2737 The size of the pool and offset to free memory are packed into the
2738 first 8 bytes of the memory pool so we don't have to keep them in
2739 the decode context. Since the address of the pool may not be
2740 aligned, they have to be packed and unpacked as if they were
2741 serialized data of the wire or such.
2742
2743 The sizes packed in are uint32_t to be the same on all CPU types
2744 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002745 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002746
2747
Laurence Lundbladeee851742020-01-08 08:37:05 -08002748static inline int
2749MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002750{
2751 // Use of UsefulInputBuf is overkill, but it is convenient.
2752 UsefulInputBuf UIB;
2753
Laurence Lundbladeee851742020-01-08 08:37:05 -08002754 // Just assume the size here. It was checked during SetUp so
2755 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002756 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002757 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2758 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2759 return UsefulInputBuf_GetError(&UIB);
2760}
2761
2762
Laurence Lundbladeee851742020-01-08 08:37:05 -08002763static inline int
2764MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002765{
2766 // Use of UsefulOutBuf is overkill, but convenient. The
2767 // length check performed here is useful.
2768 UsefulOutBuf UOB;
2769
2770 UsefulOutBuf_Init(&UOB, Pool);
2771 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2772 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2773 return UsefulOutBuf_GetError(&UOB);
2774}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002775
2776
2777/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002778 Internal function for an allocation, reallocation free and destuct.
2779
2780 Having only one function rather than one each per mode saves space in
2781 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002782
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002783 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2784 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002785static UsefulBuf
2786MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002787{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002788 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002789
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002790 uint32_t uPoolSize;
2791 uint32_t uFreeOffset;
2792
2793 if(uNewSize > UINT32_MAX) {
2794 // This allocator is only good up to 4GB. This check should
2795 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2796 goto Done;
2797 }
2798 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2799
2800 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2801 goto Done;
2802 }
2803
2804 if(uNewSize) {
2805 if(pMem) {
2806 // REALLOCATION MODE
2807 // Calculate pointer to the end of the memory pool. It is
2808 // assumed that pPool + uPoolSize won't wrap around by
2809 // assuming the caller won't pass a pool buffer in that is
2810 // not in legitimate memory space.
2811 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2812
2813 // Check that the pointer for reallocation is in the range of the
2814 // pool. This also makes sure that pointer math further down
2815 // doesn't wrap under or over.
2816 if(pMem >= pPool && pMem < pPoolEnd) {
2817 // Offset to start of chunk for reallocation. This won't
2818 // wrap under because of check that pMem >= pPool. Cast
2819 // is safe because the pool is always less than UINT32_MAX
2820 // because of check in QCBORDecode_SetMemPool().
2821 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2822
2823 // Check to see if the allocation will fit. uPoolSize -
2824 // uMemOffset will not wrap under because of check that
2825 // pMem is in the range of the uPoolSize by check above.
2826 if(uNewSize <= uPoolSize - uMemOffset) {
2827 ReturnValue.ptr = pMem;
2828 ReturnValue.len = uNewSize;
2829
2830 // Addition won't wrap around over because uNewSize was
2831 // checked to be sure it is less than the pool size.
2832 uFreeOffset = uMemOffset + uNewSize32;
2833 }
2834 }
2835 } else {
2836 // ALLOCATION MODE
2837 // uPoolSize - uFreeOffset will not underflow because this
2838 // pool implementation makes sure uFreeOffset is always
2839 // smaller than uPoolSize through this check here and
2840 // reallocation case.
2841 if(uNewSize <= uPoolSize - uFreeOffset) {
2842 ReturnValue.len = uNewSize;
2843 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002844 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002845 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002846 }
2847 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002848 if(pMem) {
2849 // FREE MODE
2850 // Cast is safe because of limit on pool size in
2851 // QCBORDecode_SetMemPool()
2852 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2853 } else {
2854 // DESTRUCT MODE
2855 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002856 }
2857 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002858
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002859 UsefulBuf Pool = {pPool, uPoolSize};
2860 MemPool_Pack(Pool, uFreeOffset);
2861
2862Done:
2863 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002864}
2865
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002866
Laurence Lundbladef6531662018-12-04 10:42:22 +09002867/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002868 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002869 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002870QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2871 UsefulBuf Pool,
2872 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002873{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002874 // The pool size and free mem offset are packed into the beginning
Dave Thaler93c01182022-08-06 15:08:35 -04002875 // of the pool memory. This compile time check makes sure the
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002876 // constant in the header is correct. This check should optimize
2877 // down to nothing.
Dave Thaler93c01182022-08-06 15:08:35 -04002878#ifdef _MSC_VER
2879#pragma warning(push)
2880#pragma warning(disable:4127) // conditional expression is constant
2881#endif
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002882 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002883 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002884 }
Dave Thaler93c01182022-08-06 15:08:35 -04002885#ifdef _MSC_VER
2886#pragma warning(pop)
2887#endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002888
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002889 // The pool size and free offset packed in to the beginning of pool
2890 // memory are only 32-bits. This check will optimize out on 32-bit
2891 // machines.
2892 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002893 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002894 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002895
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002896 // This checks that the pool buffer given is big enough.
2897 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002898 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002899 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002900
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002901 QCBORDecode_SetUpAllocator(pMe, MemPool_Function, Pool.ptr, bAllStrings);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002902
Laurence Lundblade30816f22018-11-10 13:40:22 +07002903 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002904}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002905#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002906
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002907
2908
Laurence Lundblade37286c02022-09-03 10:05:02 -07002909static inline void
2910CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002911{
Laurence Lundblade37286c02022-09-03 10:05:02 -07002912#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade9b334962020-08-27 10:55:53 -07002913 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
Laurence Lundblade37286c02022-09-03 10:05:02 -07002914#else
2915 (void)pMe;
2916 (void)pItem;
2917#endif
Laurence Lundblade9b334962020-08-27 10:55:53 -07002918}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002919
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002920
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002921/**
2922 * @brief Consume an entire map or array including its contents.
2923 *
2924 * @param[in] pMe The decoder context.
2925 * @param[in] pItemToConsume The array/map whose contents are to be
2926 * consumed.
2927 * @param[out] puNextNestLevel The next nesting level after the item was
2928 * fully consumed.
2929 *
2930 * This may be called when @c pItemToConsume is not an array or
2931 * map. In that case, this is just a pass through for @c puNextNestLevel
2932 * since there is nothing to do.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002933 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002934static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002935ConsumeItem(QCBORDecodeContext *pMe,
2936 const QCBORItem *pItemToConsume,
Máté Tóth-Pál2f2aa5f2021-05-17 21:35:09 +02002937 uint8_t *puNextNestLevel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002938{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002939 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002940 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002941
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002942 /* If it is a map or array, this will tell if it is empty. */
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002943 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2944
2945 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2946 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002947
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002948 /* This works for definite- and indefinite-length maps and
2949 * arrays by using the nesting level
Laurence Lundblade1341c592020-04-11 14:19:05 -07002950 */
2951 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002952 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002953 if(QCBORDecode_IsUnrecoverableError(uReturn) ||
2954 uReturn == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002955 goto Done;
2956 }
2957 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002958
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002959 *puNextNestLevel = Item.uNextNestLevel;
2960
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002961 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002962
Laurence Lundblade1341c592020-04-11 14:19:05 -07002963 } else {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002964 /* pItemToConsume is not a map or array. Just pass the nesting
2965 * level through. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002966 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2967
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002968 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002969 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002970
2971Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002972 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002973}
2974
Laurence Lundblade732e52d2021-02-22 20:11:01 -07002975
2976void QCBORDecode_VGetNextConsume(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2977{
Laurence Lundblade732e52d2021-02-22 20:11:01 -07002978 QCBORDecode_VGetNext(pMe, pDecodedItem);
2979
2980 if(pMe->uLastError == QCBOR_SUCCESS) {
Máté Tóth-Pálc6d59682021-05-26 18:55:30 +02002981 pMe->uLastError = (uint8_t)ConsumeItem(pMe, pDecodedItem,
2982 &pDecodedItem->uNextNestLevel);
Laurence Lundblade732e52d2021-02-22 20:11:01 -07002983 }
2984}
2985
2986
2987
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002988/* Call only on maps and arrays. Rewinds the cursor
2989 * to the start as if it was just entered.
2990 */
2991static void RewindMapOrArray(QCBORDecodeContext *pMe)
2992{
2993 /* Reset nesting tracking to the deepest bounded level */
2994 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
2995
2996 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
2997
2998 /* Reposition traversal cursor to the start of the map/array */
2999 UsefulInputBuf_Seek(&(pMe->InBuf),
3000 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
3001}
3002
3003
3004/*
3005 Public function, see header qcbor/qcbor_decode.h file
3006 */
3007void QCBORDecode_Rewind(QCBORDecodeContext *pMe)
3008{
3009 if(pMe->nesting.pCurrentBounded != NULL) {
3010 /* In a bounded map, array or bstr-wrapped CBOR */
3011
3012 if(DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
3013 /* In bstr-wrapped CBOR. */
3014
3015 /* Reposition traversal cursor to start of wrapping byte string */
3016 UsefulInputBuf_Seek(&(pMe->InBuf),
3017 pMe->nesting.pCurrentBounded->u.bs.uBstrStartOffset);
3018 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
3019
3020 } else {
3021 /* In a map or array */
3022 RewindMapOrArray(pMe);
3023 }
3024
3025 } else {
3026 /* Not in anything bounded */
3027
3028 /* Reposition traversal cursor to the start of input CBOR */
3029 UsefulInputBuf_Seek(&(pMe->InBuf), 0ULL);
3030
3031 /* Reset nesting tracking to beginning of input. */
3032 DecodeNesting_Init(&(pMe->nesting));
3033 }
3034
3035 pMe->uLastError = QCBOR_SUCCESS;
3036}
3037
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003038
Laurence Lundblade1341c592020-04-11 14:19:05 -07003039/* Return true if the labels in Item1 and Item2 are the same.
3040 Works only for integer and string labels. Returns false
3041 for any other type. */
3042static inline bool
3043MatchLabel(QCBORItem Item1, QCBORItem Item2)
3044{
3045 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
3046 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
3047 return true;
3048 }
3049 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003050 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003051 return true;
3052 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003053 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07003054 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
3055 return true;
3056 }
3057 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
3058 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
3059 return true;
3060 }
3061 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003062
Laurence Lundblade1341c592020-04-11 14:19:05 -07003063 /* Other label types are never matched */
3064 return false;
3065}
3066
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003067
3068/*
3069 Returns true if Item1 and Item2 are the same type
3070 or if either are of QCBOR_TYPE_ANY.
3071 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003072static inline bool
3073MatchType(QCBORItem Item1, QCBORItem Item2)
3074{
3075 if(Item1.uDataType == Item2.uDataType) {
3076 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003077 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003078 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003079 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003080 return true;
3081 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003082 return false;
3083}
3084
3085
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003086/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003087 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003088
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003089 @param[in] pMe The decode context to search.
3090 @param[in,out] pItemArray The items to search for and the items found.
3091 @param[out] puOffset Byte offset of last item matched.
3092 @param[in] pCBContext Context for the not-found item call back.
3093 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003094
3095 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
3096
Laurence Lundblade93d89472020-10-03 22:30:50 -07003097 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
3098 were found for one of the labels being
3099 search for. This duplicate detection is
3100 only performed for items in pItemArray,
3101 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003102
Laurence Lundblade93d89472020-10-03 22:30:50 -07003103 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
3104 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003105
3106 @retval Also errors returned by QCBORDecode_GetNext().
3107
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003108 On input pItemArray contains a list of labels and data types
3109 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07003110
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003111 On output the fully retrieved items are filled in with
3112 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07003113
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003114 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003115
3116 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003117 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003118static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003119MapSearch(QCBORDecodeContext *pMe,
3120 QCBORItem *pItemArray,
3121 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003122 void *pCBContext,
3123 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003124{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003125 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003126 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07003127
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003128 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003129 uReturn = pMe->uLastError;
3130 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003131 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003132
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003133 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003134 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
3135 /* QCBOR_TYPE_NONE as first item indicates just looking
3136 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003137 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
3138 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003139 }
3140
Laurence Lundblade085d7952020-07-24 10:26:30 -07003141 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
3142 // It is an empty bounded array or map
3143 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
3144 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003145 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07003146 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003147 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003148 // Nothing is ever found in an empty array or map. All items
3149 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07003150 uReturn = QCBOR_SUCCESS;
3151 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003152 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003153 }
3154
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003155 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003156 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
3157
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003158 /* Reposition to search from the start of the map / array */
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003159 RewindMapOrArray(pMe);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003160
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003161 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003162 Loop over all the items in the map or array. Each item
3163 could be a map or array, but label matching is only at
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003164 the main level. This handles definite- and indefinite-
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003165 length maps and arrays. The only reason this is ever
3166 called on arrays is to find their end position.
3167
3168 This will always run over all items in order to do
3169 duplicate detection.
3170
3171 This will exit with failure if it encounters an
3172 unrecoverable error, but continue on for recoverable
3173 errors.
3174
3175 If a recoverable error occurs on a matched item, then
3176 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003177 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07003178 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Máté Tóth-Pál2f2aa5f2021-05-17 21:35:09 +02003179 uint8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003180 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003181 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07003182 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003183
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003184 /* Get the item */
3185 QCBORItem Item;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003186 QCBORError uResult = QCBORDecode_GetNextTagContent(pMe, &Item);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003187 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003188 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003189 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003190 goto Done;
3191 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003192 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003193 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003194 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003195 goto Done;
3196 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003197
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003198 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003199 bool bMatched = false;
3200 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
3201 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003202 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003203 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
3204 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003205 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003206 }
Laurence Lundblade63926052021-03-29 16:05:51 -07003207 if(uResult != QCBOR_SUCCESS) {
3208 /* The label matches, but the data item is in error */
3209 uReturn = uResult;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003210 goto Done;
3211 }
Laurence Lundblade63926052021-03-29 16:05:51 -07003212 if(!MatchType(Item, pItemArray[nIndex])) {
3213 /* The data item is not of the type(s) requested */
3214 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003215 goto Done;
3216 }
3217
Laurence Lundblade1341c592020-04-11 14:19:05 -07003218 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003219 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003220 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003221 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003222 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003223 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003224 bMatched = true;
3225 }
3226 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003227
3228
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003229 if(!bMatched && pfCallback != NULL) {
3230 /*
3231 Call the callback on unmatched labels.
3232 (It is tempting to do duplicate detection here, but that would
3233 require dynamic memory allocation because the number of labels
3234 that might be encountered is unbounded.)
3235 */
3236 uReturn = (*pfCallback)(pCBContext, &Item);
3237 if(uReturn != QCBOR_SUCCESS) {
3238 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003239 }
3240 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003241
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003242 /*
3243 Consume the item whether matched or not. This
3244 does the work of traversing maps and array and
3245 everything in them. In this loop only the
3246 items at the current nesting level are examined
3247 to match the labels.
3248 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003249 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003250 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003251 goto Done;
3252 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003253 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003254
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003255 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003256
3257 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003258
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003259 // Check here makes sure that this won't accidentally be
3260 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003261 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003262 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
3263 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003264 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
3265 goto Done;
3266 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003267 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
3268 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003269
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003270 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003271 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
3272
3273 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003274 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07003275 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003276 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003277 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
3278 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003279 }
3280 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003281
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003282 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003283}
3284
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003285
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003286/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003287 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003288*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003289void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
3290 int64_t nLabel,
3291 uint8_t uQcborType,
3292 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003293{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003294 if(pMe->uLastError != QCBOR_SUCCESS) {
3295 return;
3296 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003297
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003298 QCBORItem OneItemSeach[2];
3299 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3300 OneItemSeach[0].label.int64 = nLabel;
3301 OneItemSeach[0].uDataType = uQcborType;
3302 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003303
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003304 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003305
3306 *pItem = OneItemSeach[0];
3307
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003308 if(uReturn != QCBOR_SUCCESS) {
3309 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003310 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003311 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003312 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003313 }
3314
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003315 Done:
3316 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003317}
3318
3319
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003320/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003321 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003322*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07003323void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
3324 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003325 uint8_t uQcborType,
3326 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003327{
Laurence Lundbladeda095972020-06-06 18:35:33 -07003328 if(pMe->uLastError != QCBOR_SUCCESS) {
3329 return;
3330 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003331
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003332 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003333 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3334 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3335 OneItemSeach[0].uDataType = uQcborType;
3336 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003337
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003338 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
3339 if(uReturn != QCBOR_SUCCESS) {
3340 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003341 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003342 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003343 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003344 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003345 }
3346
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003347 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003348
3349Done:
3350 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003351}
3352
3353
Laurence Lundblade93d89472020-10-03 22:30:50 -07003354static QCBORError
3355CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003356{
3357 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08003358 if(uDataType == puTypeList[i]) { /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003359 return QCBOR_SUCCESS;
3360 }
3361 }
3362 return QCBOR_ERR_UNEXPECTED_TYPE;
3363}
3364
Laurence Lundblade67257dc2020-07-27 03:33:37 -07003365
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003366/**
Laurence Lundblade37286c02022-09-03 10:05:02 -07003367 * Match a tag/type specification against the type of the item.
3368 *
3369 * @param[in] TagSpec Specification for matching tags.
3370 * @param[in] pItem The item to check.
3371 *
3372 * @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
3373 * @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
3374 *
3375 * This checks the item data type of untagged items as well as of
3376 * tagged items against a specification to see if decoding should
3377 * proceed.
3378 *
3379 * This relies on the automatic tag decoding done by QCBOR that turns
3380 * tag numbers into particular QCBOR_TYPEs so there is no actual
3381 * comparsion of tag numbers, just of QCBOR_TYPEs.
3382 *
3383 * This checks the data item type as possibly representing the tag
3384 * number or as the tag content type.
3385 *
3386 * If QCBOR_DISABLE_TAGS is #defined, this primarily checks the item
3387 * data type against the allowed tag content types. It will also error out
3388 * if the caller tries to require a tag because there is no way that can
3389 * ever be fulfilled.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003390 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07003391static QCBORError
3392CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07003393{
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08003394 const int nItemType = pItem->uDataType; /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade37286c02022-09-03 10:05:02 -07003395 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
3396
3397#ifndef QCBOR_DISABLE_TAGS
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08003398 /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003399 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
3400 pItem->uTags[0] != CBOR_TAG_INVALID16) {
3401 /* There are tags that QCBOR couldn't process on this item and
Laurence Lundblade37286c02022-09-03 10:05:02 -07003402 * the caller has told us there should not be.
3403 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003404 return QCBOR_ERR_UNEXPECTED_TYPE;
3405 }
3406
Laurence Lundblade9b334962020-08-27 10:55:53 -07003407 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
Laurence Lundblade37286c02022-09-03 10:05:02 -07003408 /* Must match the tag number and only the tag */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003409 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3410 }
3411
3412 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
3413 if(uReturn == QCBOR_SUCCESS) {
3414 return QCBOR_SUCCESS;
3415 }
3416
3417 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
3418 /* Must match the content type and only the content type.
Laurence Lundblade37286c02022-09-03 10:05:02 -07003419 * There was no match just above so it is a fail. */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003420 return QCBOR_ERR_UNEXPECTED_TYPE;
3421 }
3422
Laurence Lundblade37286c02022-09-03 10:05:02 -07003423 /* QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG: If here it can match either the tag or the content
3424 * and it hasn't matched the content, so the end
3425 * result is whether it matches the tag. This is
3426 * the tag optional case that the CBOR standard discourages.
3427 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07003428
3429 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003430
Laurence Lundblade37286c02022-09-03 10:05:02 -07003431#else /* QCBOR_DISABLE_TAGS */
3432 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
3433 return QCBOR_ERR_UNEXPECTED_TYPE;
3434 }
3435
3436 return CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
3437
3438#endif /* QCBOR_DISABLE_TAGS */
3439}
Laurence Lundblade9b334962020-08-27 10:55:53 -07003440
Laurence Lundblade9b334962020-08-27 10:55:53 -07003441
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003442// This could be semi-private if need be
3443static inline
Laurence Lundblade37286c02022-09-03 10:05:02 -07003444void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
3445 const int64_t nLabel,
3446 const TagSpecification TagSpec,
3447 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003448{
3449 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
3450 if(pMe->uLastError != QCBOR_SUCCESS) {
3451 return;
3452 }
3453
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003454 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003455}
3456
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003457
3458// This could be semi-private if need be
3459static inline
Laurence Lundblade37286c02022-09-03 10:05:02 -07003460void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
3461 const char *szLabel,
3462 const TagSpecification TagSpec,
3463 QCBORItem *pItem)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003464{
3465 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
3466 if(pMe->uLastError != QCBOR_SUCCESS) {
3467 return;
3468 }
3469
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003470 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003471}
3472
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003473// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003474void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
3475 int64_t nLabel,
3476 TagSpecification TagSpec,
Laurence Lundblade37286c02022-09-03 10:05:02 -07003477 UsefulBufC *pString)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003478{
3479 QCBORItem Item;
3480 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
3481 if(pMe->uLastError == QCBOR_SUCCESS) {
3482 *pString = Item.val.string;
3483 }
3484}
3485
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003486// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003487void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
3488 const char * szLabel,
3489 TagSpecification TagSpec,
3490 UsefulBufC *pString)
3491{
3492 QCBORItem Item;
3493 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
3494 if(pMe->uLastError == QCBOR_SUCCESS) {
3495 *pString = Item.val.string;
3496 }
3497}
Laurence Lundblade1341c592020-04-11 14:19:05 -07003498
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003499/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003500 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003501*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003502void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003503{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003504 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
3505 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003506}
3507
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003508/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003509 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003510*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003511void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3512 QCBORItem *pItemList,
3513 void *pCallbackCtx,
3514 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003515{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003516 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
3517 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003518}
3519
3520
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003521/**
3522 * @brief Search for a map/array by label and enter it
3523 *
3524 * @param[in] pMe The decode context.
3525 * @param[in] pSearch The map/array to search for.
3526 *
3527 * @c pSearch is expected to contain one item of type map or array
3528 * with the label specified. The current bounded map will be searched for
3529 * this and if found will be entered.
3530 *
3531 * If the label is not found, or the item found is not a map or array,
3532 * the error state is set.
3533 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003534static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003535{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003536 // The first item in pSearch is the one that is to be
3537 // entered. It should be the only one filled in. Any other
3538 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003539 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003540 return;
3541 }
3542
3543 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003544 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003545 if(pMe->uLastError != QCBOR_SUCCESS) {
3546 return;
3547 }
3548
Laurence Lundblade9b334962020-08-27 10:55:53 -07003549 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003550 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003551 return;
3552 }
3553
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003554
3555 /* The map or array was found. Now enter it.
3556 *
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003557 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3558 * next item for the pre-order traversal cursor to be the map/array
3559 * found by MapSearch(). The next few lines of code force the
3560 * cursor to that.
3561 *
3562 * There is no need to retain the old cursor because
3563 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3564 * beginning of the map/array being entered.
3565 *
3566 * The cursor is forced by: 1) setting the input buffer position to
3567 * the item offset found by MapSearch(), 2) setting the map/array
3568 * counter to the total in the map/array, 3) setting the nesting
3569 * level. Setting the map/array counter to the total is not
3570 * strictly correct, but this is OK because this cursor only needs
3571 * to be used to get one item and MapSearch() has already found it
3572 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003573 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003574 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003575
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003576 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3577
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003578 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003579
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003580 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003581}
3582
3583
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003584/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003585 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003586*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003587void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003588{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003589 QCBORItem OneItemSeach[2];
3590 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3591 OneItemSeach[0].label.int64 = nLabel;
3592 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3593 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003594
Laurence Lundblade9b334962020-08-27 10:55:53 -07003595 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003596 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003597}
3598
3599
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003600/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003601 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003602*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003603void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003604{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003605 QCBORItem OneItemSeach[2];
3606 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3607 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3608 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3609 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003610
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003611 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003612}
3613
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003614/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003615 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003616*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003617void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003618{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003619 QCBORItem OneItemSeach[2];
3620 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3621 OneItemSeach[0].label.int64 = nLabel;
3622 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3623 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003624
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003625 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003626}
3627
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003628/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003629 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003630*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003631void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3632{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003633 QCBORItem OneItemSeach[2];
3634 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3635 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3636 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3637 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003638
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003639 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003640}
3641
3642
Laurence Lundblade02625d42020-06-25 14:41:41 -07003643// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003644void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003645{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003646 QCBORError uErr;
3647
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003648 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003649 if(pMe->uLastError != QCBOR_SUCCESS) {
3650 // Already in error state; do nothing.
3651 return;
3652 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003653
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003654 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003655 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003656 uErr = QCBORDecode_GetNext(pMe, &Item);
3657 if(uErr != QCBOR_SUCCESS) {
3658 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003659 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003660 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003661 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3662 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003663 }
3664
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003665 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003666
3667
Laurence Lundbladef0499502020-08-01 11:55:57 -07003668 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003669 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003670 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3671 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003672 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003673 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3674 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003675 // Special case to increment nesting level for zero-length maps
3676 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003677 DecodeNesting_Descend(&(pMe->nesting), uType);
3678 }
3679
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003680 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003681
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003682 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3683 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003684
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003685 if(pItem != NULL) {
3686 *pItem = Item;
3687 }
3688
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003689Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003690 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003691}
3692
Laurence Lundblade02625d42020-06-25 14:41:41 -07003693
3694/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003695 This is the common work for exiting a level that is a bounded map,
3696 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003697
3698 One chunk of work is to set up the pre-order traversal so it is at
3699 the item just after the bounded map, array or bstr that is being
3700 exited. This is somewhat complex.
3701
3702 The other work is to level-up the bounded mode to next higest bounded
3703 mode or the top level if there isn't one.
3704 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003705static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003706ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003707{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003708 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003709
Laurence Lundblade02625d42020-06-25 14:41:41 -07003710 /*
3711 First the pre-order-traversal byte offset is positioned to the
3712 item just after the bounded mode item that was just consumed.
3713 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003714 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3715
Laurence Lundblade02625d42020-06-25 14:41:41 -07003716 /*
3717 Next, set the current nesting level to one above the bounded level
3718 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003719
Laurence Lundblade02625d42020-06-25 14:41:41 -07003720 DecodeNesting_CheckBoundedType() is always called before this and
3721 makes sure pCurrentBounded is valid.
3722 */
3723 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3724
3725 /*
3726 This does the complex work of leveling up the pre-order traversal
3727 when the end of a map or array or another bounded level is
3728 reached. It may do nothing, or ascend all the way to the top
3729 level.
3730 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003731 uErr = QCBORDecode_NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003732 if(uErr != QCBOR_SUCCESS) {
3733 goto Done;
3734 }
3735
Laurence Lundblade02625d42020-06-25 14:41:41 -07003736 /*
3737 This makes the next highest bounded level the current bounded
3738 level. If there is no next highest level, then no bounded mode is
3739 in effect.
3740 */
3741 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003742
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003743 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003744
3745Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003746 return uErr;
3747}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003748
Laurence Lundblade02625d42020-06-25 14:41:41 -07003749
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003750// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003751void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003752{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003753 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003754 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003755 return;
3756 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003757
Laurence Lundblade02625d42020-06-25 14:41:41 -07003758 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003759
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003760 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003761 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003762 goto Done;
3763 }
3764
Laurence Lundblade02625d42020-06-25 14:41:41 -07003765 /*
3766 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003767 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003768 from previous map search, then do a dummy search.
3769 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003770 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003771 QCBORItem Dummy;
3772 Dummy.uLabelType = QCBOR_TYPE_NONE;
3773 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3774 if(uErr != QCBOR_SUCCESS) {
3775 goto Done;
3776 }
3777 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003778
Laurence Lundblade02625d42020-06-25 14:41:41 -07003779 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003780
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003781Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003782 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003783}
3784
3785
Laurence Lundblade1341c592020-04-11 14:19:05 -07003786
Laurence Lundblade37286c02022-09-03 10:05:02 -07003787static QCBORError
3788InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
3789 const QCBORItem *pItem,
3790 const uint8_t uTagRequirement,
3791 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003792{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003793 if(pBstr) {
3794 *pBstr = NULLUsefulBufC;
3795 }
3796
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003797 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003798 /* Already in error state; do nothing. */
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003799 return pMe->uLastError;
3800 }
3801
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003802 QCBORError uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003803
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003804 const TagSpecification TagSpec =
3805 {
3806 uTagRequirement,
3807 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3808 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3809 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003810
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003811 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003812 if(uError != QCBOR_SUCCESS) {
3813 goto Done;
3814 }
3815
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003816 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003817 /* Reverse the decrement done by GetNext() for the bstr so the
3818 * increment in QCBORDecode_NestLevelAscender() called by
3819 * ExitBoundedLevel() will work right.
3820 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003821 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003822 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003823
3824 if(pBstr) {
3825 *pBstr = pItem->val.string;
3826 }
3827
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003828 /* This saves the current length of the UsefulInputBuf and then
3829 * narrows the UsefulInputBuf to start and length of the wrapped
3830 * CBOR that is being entered.
3831 *
3832 * Most of these calls are simple inline accessors so this doesn't
3833 * amount to much code.
3834 */
3835
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003836 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003837 /* This check makes the cast of uPreviousLength to uint32_t below safe. */
3838 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003839 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003840 goto Done;
3841 }
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003842
3843 const size_t uStartOfBstr = UsefulInputBuf_PointerToOffset(&(pMe->InBuf),
3844 pItem->val.string.ptr);
3845 /* This check makes the cast of uStartOfBstr to uint32_t below safe. */
3846 if(uStartOfBstr == SIZE_MAX || uStartOfBstr > QCBOR_MAX_DECODE_INPUT_SIZE) {
3847 /* This should never happen because pItem->val.string.ptr should
3848 * always be valid since it was just returned.
3849 */
3850 uError = QCBOR_ERR_INPUT_TOO_LARGE;
3851 goto Done;
3852 }
3853
3854 const size_t uEndOfBstr = uStartOfBstr + pItem->val.string.len;
3855
3856 UsefulInputBuf_Seek(&(pMe->InBuf), uStartOfBstr);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003857 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003858
Laurence Lundblade02625d42020-06-25 14:41:41 -07003859 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003860 (uint32_t)uPreviousLength,
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003861 (uint32_t)uStartOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003862Done:
3863 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003864}
3865
3866
Laurence Lundblade02625d42020-06-25 14:41:41 -07003867/*
3868 Public function, see header qcbor/qcbor_decode.h file
3869 */
3870void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003871 uint8_t uTagRequirement,
3872 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003873{
3874 if(pMe->uLastError != QCBOR_SUCCESS) {
3875 // Already in error state; do nothing.
3876 return;
3877 }
3878
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003879 /* Get the data item that is the byte string being entered */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003880 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003881 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3882 if(pMe->uLastError != QCBOR_SUCCESS) {
3883 return;
3884 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003885
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003886 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003887 &Item,
3888 uTagRequirement,
3889 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003890}
3891
3892
Laurence Lundblade02625d42020-06-25 14:41:41 -07003893/*
3894 Public function, see header qcbor/qcbor_decode.h file
3895 */
3896void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003897 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003898 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003899 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003900{
3901 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003902 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003903
Laurence Lundblade93d89472020-10-03 22:30:50 -07003904 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3905 &Item,
3906 uTagRequirement,
3907 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003908}
3909
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003910
Laurence Lundblade02625d42020-06-25 14:41:41 -07003911/*
3912 Public function, see header qcbor/qcbor_decode.h file
3913 */
3914void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003915 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003916 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003917 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003918{
3919 QCBORItem Item;
3920 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3921
Laurence Lundblade93d89472020-10-03 22:30:50 -07003922 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3923 &Item,
3924 uTagRequirement,
3925 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003926}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003927
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003928
Laurence Lundblade02625d42020-06-25 14:41:41 -07003929/*
3930 Public function, see header qcbor/qcbor_decode.h file
3931 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003932void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003933{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003934 if(pMe->uLastError != QCBOR_SUCCESS) {
3935 // Already in error state; do nothing.
3936 return;
3937 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003938
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003939 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003940 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003941 return;
3942 }
3943
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003944 const uint32_t uEndOfBstr = (uint32_t)UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
3945
Laurence Lundblade02625d42020-06-25 14:41:41 -07003946 /*
3947 Reset the length of the UsefulInputBuf to what it was before
3948 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003949 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003950 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003951 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003952
3953
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003954 QCBORError uErr = ExitBoundedLevel(pMe, uEndOfBstr);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003955 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003956}
3957
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003958
Laurence Lundbladee6430642020-03-14 21:15:44 -07003959
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003960
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003961static inline void
3962ProcessBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003963{
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003964 if(pMe->uLastError != QCBOR_SUCCESS) {
3965 /* Already in error state, do nothing */
3966 return;
3967 }
3968
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003969 switch(pItem->uDataType) {
3970 case QCBOR_TYPE_TRUE:
3971 *pBool = true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003972 break;
3973
3974 case QCBOR_TYPE_FALSE:
3975 *pBool = false;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003976 break;
3977
3978 default:
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003979 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003980 break;
3981 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003982 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003983}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003984
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003985
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003986/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003987 * Public function, see header qcbor/qcbor_decode.h file
3988 */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003989void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003990{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003991 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003992 /* Already in error state, do nothing */
Laurence Lundbladee6430642020-03-14 21:15:44 -07003993 return;
3994 }
3995
Laurence Lundbladec4537442020-04-14 18:53:22 -07003996 QCBORItem Item;
3997
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003998 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3999
4000 ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004001}
4002
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004003
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004004/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004005 * Public function, see header qcbor/qcbor_decode.h file
4006 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004007void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004008{
4009 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004010 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004011
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004012 ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004013}
4014
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004015
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004016/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004017 * Public function, see header qcbor/qcbor_decode.h file
4018 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004019void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
4020{
4021 QCBORItem Item;
4022 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4023
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07004024 ProcessBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004025}
4026
4027
4028
Laurence Lundbladec7114722020-08-13 05:11:40 -07004029
4030static void ProcessEpochDate(QCBORDecodeContext *pMe,
4031 QCBORItem *pItem,
Laurence Lundblade37286c02022-09-03 10:05:02 -07004032 const uint8_t uTagRequirement,
Laurence Lundbladec7114722020-08-13 05:11:40 -07004033 int64_t *pnTime)
4034{
4035 if(pMe->uLastError != QCBOR_SUCCESS) {
4036 // Already in error state, do nothing
4037 return;
4038 }
4039
4040 QCBORError uErr;
4041
4042 const TagSpecification TagSpec =
4043 {
4044 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004045 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4046 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07004047 };
4048
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004049 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07004050 if(uErr != QCBOR_SUCCESS) {
4051 goto Done;
4052 }
4053
4054 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
4055 uErr = DecodeDateEpoch(pItem);
4056 if(uErr != QCBOR_SUCCESS) {
4057 goto Done;
4058 }
4059 }
4060
Laurence Lundblade9b334962020-08-27 10:55:53 -07004061 // Save the tags in the last item's tags in the decode context
4062 // for QCBORDecode_GetNthTagOfLast()
4063 CopyTags(pMe, pItem);
4064
Laurence Lundbladec7114722020-08-13 05:11:40 -07004065 *pnTime = pItem->val.epochDate.nSeconds;
4066
4067Done:
4068 pMe->uLastError = (uint8_t)uErr;
4069}
4070
4071
4072void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004073 uint8_t uTagRequirement,
4074 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07004075{
4076 if(pMe->uLastError != QCBOR_SUCCESS) {
4077 // Already in error state, do nothing
4078 return;
4079 }
4080
4081 QCBORItem Item;
4082 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4083
4084 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
4085}
4086
4087
4088void
4089QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
4090 int64_t nLabel,
4091 uint8_t uTagRequirement,
4092 int64_t *pnTime)
4093{
4094 QCBORItem Item;
4095 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4096 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
4097}
4098
4099
4100void
4101QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
4102 const char *szLabel,
4103 uint8_t uTagRequirement,
4104 int64_t *pnTime)
4105{
4106 QCBORItem Item;
4107 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4108 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
4109}
4110
4111
4112
Laurence Lundblade46d63e92021-05-13 11:37:10 -07004113/*
4114 * Common processing for the RFC 8943 day-count tag. Mostly
4115 * make sure the tag content is correct and copy forward any
4116 * further other tag numbers.
4117 */
4118static void ProcessEpochDays(QCBORDecodeContext *pMe,
4119 QCBORItem *pItem,
4120 uint8_t uTagRequirement,
4121 int64_t *pnDays)
4122{
4123 if(pMe->uLastError != QCBOR_SUCCESS) {
4124 /* Already in error state, do nothing */
4125 return;
4126 }
4127
4128 QCBORError uErr;
4129
4130 const TagSpecification TagSpec =
4131 {
4132 uTagRequirement,
4133 {QCBOR_TYPE_DAYS_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4134 {QCBOR_TYPE_INT64, QCBOR_TYPE_UINT64, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
4135 };
4136
4137 uErr = CheckTagRequirement(TagSpec, pItem);
4138 if(uErr != QCBOR_SUCCESS) {
4139 goto Done;
4140 }
4141
4142 if(pItem->uDataType != QCBOR_TYPE_DAYS_EPOCH) {
4143 uErr = DecodeDaysEpoch(pItem);
4144 if(uErr != QCBOR_SUCCESS) {
4145 goto Done;
4146 }
4147 }
4148
4149 /* Save the tags in the last item's tags in the decode context
4150 * for QCBORDecode_GetNthTagOfLast()
4151 */
4152 CopyTags(pMe, pItem);
4153
4154 *pnDays = pItem->val.epochDays;
4155
4156Done:
4157 pMe->uLastError = (uint8_t)uErr;
4158}
4159
4160
4161/*
4162 * Public function, see header qcbor/qcbor_decode.h
4163 */
4164void QCBORDecode_GetEpochDays(QCBORDecodeContext *pMe,
4165 uint8_t uTagRequirement,
4166 int64_t *pnDays)
4167{
4168 if(pMe->uLastError != QCBOR_SUCCESS) {
4169 /* Already in error state, do nothing */
4170 return;
4171 }
4172
4173 QCBORItem Item;
4174 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4175
4176 ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
4177}
4178
4179
4180/*
4181 * Public function, see header qcbor/qcbor_decode.h
4182 */
4183void
4184QCBORDecode_GetEpochDaysInMapN(QCBORDecodeContext *pMe,
4185 int64_t nLabel,
4186 uint8_t uTagRequirement,
4187 int64_t *pnDays)
4188{
4189 QCBORItem Item;
4190 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4191 ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
4192}
4193
4194
4195/*
4196 * Public function, see header qcbor/qcbor_decode.h
4197 */
4198void
4199QCBORDecode_GetEpochDaysInMapSZ(QCBORDecodeContext *pMe,
4200 const char *szLabel,
4201 uint8_t uTagRequirement,
4202 int64_t *pnDays)
4203{
4204 QCBORItem Item;
4205 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4206 ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
4207}
4208
4209
4210
Laurence Lundblade37286c02022-09-03 10:05:02 -07004211/*
4212 * @brief Get a string that matches the type/tag specification.
4213 */
4214void
4215QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
4216 const TagSpecification TagSpec,
4217 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004218{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004219 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade37286c02022-09-03 10:05:02 -07004220 /* Already in error state, do nothing */
Laurence Lundbladec4537442020-04-14 18:53:22 -07004221 return;
4222 }
4223
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004224 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004225 QCBORItem Item;
4226
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004227 uError = QCBORDecode_GetNext(pMe, &Item);
4228 if(uError != QCBOR_SUCCESS) {
4229 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004230 return;
4231 }
4232
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004233 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004234
4235 if(pMe->uLastError == QCBOR_SUCCESS) {
4236 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07004237 } else {
4238 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004239 }
4240}
4241
Laurence Lundbladec4537442020-04-14 18:53:22 -07004242
4243
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004244
Laurence Lundblade37286c02022-09-03 10:05:02 -07004245static QCBORError
4246ProcessBigNum(const uint8_t uTagRequirement,
4247 const QCBORItem *pItem,
4248 UsefulBufC *pValue,
4249 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004250{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004251 const TagSpecification TagSpec =
4252 {
4253 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004254 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4255 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004256 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004257
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004258 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004259 if(uErr != QCBOR_SUCCESS) {
4260 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004261 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004262
4263 *pValue = pItem->val.string;
4264
4265 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
4266 *pbIsNegative = false;
4267 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
4268 *pbIsNegative = true;
4269 }
4270
4271 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004272}
4273
4274
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004275/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004276 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004277 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004278void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
4279 uint8_t uTagRequirement,
4280 UsefulBufC *pValue,
4281 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004282{
4283 if(pMe->uLastError != QCBOR_SUCCESS) {
4284 // Already in error state, do nothing
4285 return;
4286 }
4287
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004288 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004289 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4290 if(uError != QCBOR_SUCCESS) {
4291 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004292 return;
4293 }
4294
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004295 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004296}
4297
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004298
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004299/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004300 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004301*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004302void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
4303 int64_t nLabel,
4304 uint8_t uTagRequirement,
4305 UsefulBufC *pValue,
4306 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004307{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004308 QCBORItem Item;
4309 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004310 if(pMe->uLastError != QCBOR_SUCCESS) {
4311 return;
4312 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004313
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004314 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004315}
4316
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004317
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004318/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004319 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004320*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004321void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
4322 const char *szLabel,
4323 uint8_t uTagRequirement,
4324 UsefulBufC *pValue,
4325 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004326{
4327 QCBORItem Item;
4328 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004329 if(pMe->uLastError != QCBOR_SUCCESS) {
4330 return;
4331 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004332
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004333 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004334}
4335
4336
4337
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004338
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004339// Semi private
Laurence Lundblade37286c02022-09-03 10:05:02 -07004340QCBORError
4341QCBORDecode_GetMIMEInternal(const uint8_t uTagRequirement,
4342 const QCBORItem *pItem,
4343 UsefulBufC *pMessage,
4344 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004345{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004346 const TagSpecification TagSpecText =
4347 {
4348 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004349 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4350 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004351 };
4352 const TagSpecification TagSpecBinary =
4353 {
4354 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004355 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4356 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004357 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004358
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004359 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07004360
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004361 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004362 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004363 if(pbIsTag257 != NULL) {
4364 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004365 }
4366 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004367 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004368 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004369 if(pbIsTag257 != NULL) {
4370 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004371 }
4372 uReturn = QCBOR_SUCCESS;
4373
4374 } else {
4375 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
4376 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07004377
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004378 return uReturn;
4379}
4380
Laurence Lundblade93d89472020-10-03 22:30:50 -07004381// Improvement: add methods for wrapped CBOR, a simple alternate
4382// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004383
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004384
4385
4386
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004387#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07004388
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004389typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004390
4391
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004392/**
4393 * @brief Base 10 exponentiate a mantissa and exponent into an unsigned 64-bit integer.
4394 *
4395 * @param[in] uMantissa The unsigned integer mantissa.
4396 * @param[in] nExponent The signed integer exponent.
4397 * @param[out] puResult Place to return the unsigned integer result.
4398 *
4399 * This computes: mantissa * 10 ^^ exponent as for a decimal fraction. The output is a 64-bit
4400 * unsigned integer.
4401 *
4402 * There are many inputs for which the result will not fit in the
4403 * 64-bit integer and \ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will
4404 * be returned.
4405 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004406static QCBORError
4407Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004408{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004409 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004410
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004411 if(uResult != 0) {
4412 /* This loop will run a maximum of 19 times because
4413 * UINT64_MAX < 10 ^^ 19. More than that will cause
4414 * exit with the overflow error
4415 */
4416 for(; nExponent > 0; nExponent--) {
4417 if(uResult > UINT64_MAX / 10) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004418 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004419 }
4420 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004421 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004422
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004423 for(; nExponent < 0; nExponent++) {
4424 uResult = uResult / 10;
4425 if(uResult == 0) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004426 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004427 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004428 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004429 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004430 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07004431
4432 *puResult = uResult;
4433
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004434 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004435}
4436
4437
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004438/**
4439 * @brief Base 2 exponentiate a mantissa and exponent into an unsigned 64-bit integer.
4440 *
4441 * @param[in] uMantissa The unsigned integer mantissa.
4442 * @param[in] nExponent The signed integer exponent.
4443 * @param[out] puResult Place to return the unsigned integer result.
4444 *
4445 * This computes: mantissa * 2 ^^ exponent as for a big float. The
4446 * output is a 64-bit unsigned integer.
4447 *
4448 * There are many inputs for which the result will not fit in the
4449 * 64-bit integer and \ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will
4450 * be returned.
4451 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004452static QCBORError
4453Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004454{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004455 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004456
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004457 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004458
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004459 /* This loop will run a maximum of 64 times because INT64_MAX <
4460 * 2^31. More than that will cause exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07004461 */
4462 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004463 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004464 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004465 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004466 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004467 nExponent--;
4468 }
4469
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004470 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004471 if(uResult == 0) {
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004472 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004473 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004474 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004475 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004476 }
4477
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004478 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004479
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004480 return QCBOR_SUCCESS;
4481}
4482
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004483
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004484/**
4485 * @brief Exponentiate a signed mantissa and signed exponent to produce a signed result.
4486 *
4487 * @param[in] nMantissa Signed integer mantissa.
4488 * @param[in] nExponent Signed integer exponent.
4489 * @param[out] pnResult Place to put the signed integer result.
4490 * @param[in] pfExp Exponentiation function.
4491 *
4492 * @returns Error code
4493 *
4494 * \c pfExp performs exponentiation on and unsigned mantissa and
4495 * produces an unsigned result. This converts the mantissa from signed
4496 * and converts the result to signed. The exponentiation function is
4497 * either for base 2 or base 10 (and could be other if needed).
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004498 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004499static QCBORError
4500ExponentiateNN(int64_t nMantissa,
4501 int64_t nExponent,
4502 int64_t *pnResult,
4503 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004504{
4505 uint64_t uResult;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004506 uint64_t uMantissa;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004507
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004508 /* Take the absolute value and put it into an unsigned. */
4509 if(nMantissa >= 0) {
4510 /* Positive case is straightforward */
4511 uMantissa = (uint64_t)nMantissa;
4512 } else if(nMantissa != INT64_MIN) {
4513 /* The common negative case. See next. */
4514 uMantissa = (uint64_t)-nMantissa;
4515 } else {
4516 /* int64_t and uint64_t are always two's complement per the
4517 * C standard (and since QCBOR uses these it only works with
4518 * two's complement, which is pretty much universal these
4519 * days). The range of a negative two's complement integer is
4520 * one more that than a positive, so the simple code above might
4521 * not work all the time because you can't simply negate the
4522 * value INT64_MIN because it can't be represented in an
4523 * int64_t. -INT64_MIN can however be represented in a
4524 * uint64_t. Some compilers seem to recognize this case for the
4525 * above code and put the correct value in uMantissa, however
4526 * they are not required to do this by the C standard. This next
4527 * line does however work for all compilers.
4528 *
4529 * This does assume two's complement where -INT64_MIN ==
4530 * INT64_MAX + 1 (which wouldn't be true for one's complement or
4531 * sign and magnitude (but we know we're using two's complement
4532 * because int64_t requires it)).
4533 *
4534 * See these, particularly the detailed commentary:
4535 * https://stackoverflow.com/questions/54915742/does-c99-mandate-a-int64-t-type-be-available-always
4536 * https://stackoverflow.com/questions/37301078/is-negating-int-min-undefined-behaviour
4537 */
4538 uMantissa = (uint64_t)INT64_MAX+1;
4539 }
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004540
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004541 /* Call the exponentiator passed for either base 2 or base 10.
4542 * Here is where most of the overflow errors are caught. */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004543 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
4544 if(uReturn) {
4545 return uReturn;
4546 }
4547
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004548 /* Convert back to the sign of the original mantissa */
4549 if(nMantissa >= 0) {
4550 if(uResult > INT64_MAX) {
4551 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4552 }
4553 *pnResult = (int64_t)uResult;
4554 } else {
4555 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
4556 * of INT64_MIN. This assumes two's compliment representation
4557 * where INT64_MIN is one increment farther from 0 than
4558 * INT64_MAX. Trying to write -INT64_MIN doesn't work to get
4559 * this because the compiler makes it an int64_t which can't
4560 * represent -INT64_MIN. Also see above.
4561 */
4562 if(uResult > (uint64_t)INT64_MAX+1) {
4563 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4564 }
4565 *pnResult = -(int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004566 }
4567
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004568 return QCBOR_SUCCESS;
4569}
4570
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004571
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004572/**
4573 * @brief Exponentiate an unsigned mantissa and signed exponent to produce an unsigned result.
4574 *
4575 * @param[in] nMantissa Signed integer mantissa.
4576 * @param[in] nExponent Signed integer exponent.
4577 * @param[out] puResult Place to put the signed integer result.
4578 * @param[in] pfExp Exponentiation function.
4579 *
4580 * @returns Error code
4581 *
4582 * \c pfExp performs exponentiation on and unsigned mantissa and
4583 * produces an unsigned result. This errors out if the mantissa
4584 * is negative because the output is unsigned.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004585 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004586static QCBORError
4587ExponentitateNU(int64_t nMantissa,
4588 int64_t nExponent,
4589 uint64_t *puResult,
4590 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004591{
4592 if(nMantissa < 0) {
4593 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4594 }
4595
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004596 /* Cast to unsigned is OK because of check for negative.
4597 * Cast to unsigned is OK because UINT64_MAX > INT64_MAX.
4598 * Exponentiation is straight forward
4599 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004600 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
4601}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004602
4603
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004604/**
4605 * @brief Exponentiate an usnigned mantissa and unsigned exponent to produce an unsigned result.
4606 *
4607 * @param[in] uMantissa Unsigned integer mantissa.
4608 * @param[in] nExponent Unsigned integer exponent.
4609 * @param[out] puResult Place to put the unsigned integer result.
4610 * @param[in] pfExp Exponentiation function.
4611 *
4612 * @returns Error code
4613 *
4614 * \c pfExp performs exponentiation on and unsigned mantissa and
4615 * produces an unsigned result so this is just a wrapper that does
4616 * nothing (and is likely inlined).
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004617 */
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004618static QCBORError
4619ExponentitateUU(uint64_t uMantissa,
4620 int64_t nExponent,
4621 uint64_t *puResult,
4622 fExponentiator pfExp)
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004623{
4624 return (*pfExp)(uMantissa, nExponent, puResult);
4625}
4626
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004627#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004628
4629
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004630
4631
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004632/**
4633 * @brief Convert a CBOR big number to a uint64_t.
4634 *
4635 * @param[in] BigNum Bytes of the big number to convert.
4636 * @param[in] uMax Maximum value allowed for the result.
4637 * @param[out] pResult Place to put the unsigned integer result.
4638 *
4639 * @returns Error code
4640 *
4641 * Many values will overflow because a big num can represent a much
4642 * larger range than uint64_t.
4643 */
4644static QCBORError
4645ConvertBigNumToUnsigned(const UsefulBufC BigNum, const uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004646{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004647 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004648
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004649 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004650 const uint8_t *pByte = BigNum.ptr;
4651 size_t uLen = BigNum.len;
4652 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07004653 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004654 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004655 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07004656 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004657 }
4658
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004659 *pResult = uResult;
4660 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004661}
4662
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004663
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004664/**
4665 * @brief Convert a CBOR postive big number to a uint64_t.
4666 *
4667 * @param[in] BigNum Bytes of the big number to convert.
4668 * @param[out] pResult Place to put the unsigned integer result.
4669 *
4670 * @returns Error code
4671 *
4672 * Many values will overflow because a big num can represent a much
4673 * larger range than uint64_t.
4674 */
4675static QCBORError
4676ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004677{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004678 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004679}
4680
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004681
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004682/**
4683 * @brief Convert a CBOR positive big number to an int64_t.
4684 *
4685 * @param[in] BigNum Bytes of the big number to convert.
4686 * @param[out] pResult Place to put the signed integer result.
4687 *
4688 * @returns Error code
4689 *
4690 * Many values will overflow because a big num can represent a much
4691 * larger range than int64_t.
4692 */
4693static QCBORError
4694ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004695{
4696 uint64_t uResult;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004697 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004698 if(uError) {
4699 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004700 }
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004701 /* Cast is safe because ConvertBigNumToUnsigned is told to limit to INT64_MAX */
Laurence Lundbladee6430642020-03-14 21:15:44 -07004702 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004703 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004704}
4705
4706
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004707/**
4708 * @brief Convert a CBOR negative big number to an int64_t.
4709 *
4710 * @param[in] BigNum Bytes of the big number to convert.
4711 * @param[out] pnResult Place to put the signed integer result.
4712 *
4713 * @returns Error code
4714 *
4715 * Many values will overflow because a big num can represent a much
4716 * larger range than int64_t.
4717 */
4718static QCBORError
4719ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004720{
4721 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004722 /* The negative integer furthest from zero for a C int64_t is
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004723 * INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
4724 * negative number in CBOR is computed as -n - 1 where n is the
4725 * encoded integer, where n is what is in the variable BigNum. When
4726 * converting BigNum to a uint64_t, the maximum value is thus
4727 * INT64_MAX, so that when it -n - 1 is applied to it the result
4728 * will never be further from 0 than INT64_MIN.
4729 *
4730 * -n - 1 <= INT64_MIN.
4731 * -n - 1 <= -INT64_MAX - 1
4732 * n <= INT64_MAX.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004733 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07004734 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004735 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004736 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004737 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004738
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07004739 /* Now apply -n - 1. The cast is safe because
4740 * ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
4741 * is the largest positive integer that an int64_t can
4742 * represent. */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004743 *pnResult = -(int64_t)uResult - 1;
4744
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004745 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004746}
4747
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004748
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004749
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004750
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004751
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004752/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004753Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004754
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004755\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004756
Laurence Lundblade93d89472020-10-03 22:30:50 -07004757\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4758 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004759
4760\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4761
Laurence Lundblade93d89472020-10-03 22:30:50 -07004762\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4763 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004764*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07004765static QCBORError
4766ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004767{
4768 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004769 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004770 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004771#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004772 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004773 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
4774 http://www.cplusplus.com/reference/cmath/llround/
4775 */
4776 // Not interested in FE_INEXACT
4777 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004778 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4779 *pnValue = llround(pItem->val.dfnum);
4780 } else {
4781 *pnValue = lroundf(pItem->val.fnum);
4782 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004783 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4784 // llround() shouldn't result in divide by zero, but catch
4785 // it here in case it unexpectedly does. Don't try to
4786 // distinguish between the various exceptions because it seems
4787 // they vary by CPU, compiler and OS.
4788 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004789 }
4790 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004791 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004792 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004793#else
4794 return QCBOR_ERR_HW_FLOAT_DISABLED;
4795#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004796 break;
4797
4798 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004799 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004800 *pnValue = pItem->val.int64;
4801 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004802 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004803 }
4804 break;
4805
4806 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004807 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004808 if(pItem->val.uint64 < INT64_MAX) {
4809 *pnValue = pItem->val.int64;
4810 } else {
4811 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4812 }
4813 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004814 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004815 }
4816 break;
4817
4818 default:
4819 return QCBOR_ERR_UNEXPECTED_TYPE;
4820 }
4821 return QCBOR_SUCCESS;
4822}
4823
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004824
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004825void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004826 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004827 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004828 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004829{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004830 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004831 return;
4832 }
4833
Laurence Lundbladee6430642020-03-14 21:15:44 -07004834 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004835 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4836 if(uError) {
4837 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004838 return;
4839 }
4840
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004841 if(pItem) {
4842 *pItem = Item;
4843 }
4844
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004845 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004846}
4847
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004848
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004849void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4850 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004851 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004852 int64_t *pnValue,
4853 QCBORItem *pItem)
4854{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004855 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004856 if(pMe->uLastError != QCBOR_SUCCESS) {
4857 return;
4858 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004859
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004860 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004861}
4862
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004863
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004864void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4865 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004866 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004867 int64_t *pnValue,
4868 QCBORItem *pItem)
4869{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004870 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004871 if(pMe->uLastError != QCBOR_SUCCESS) {
4872 return;
4873 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004874
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004875 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004876}
4877
4878
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004879/*
4880 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004881
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004882 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004883
Laurence Lundblade93d89472020-10-03 22:30:50 -07004884 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4885 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004886
4887 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4888
Laurence Lundblade93d89472020-10-03 22:30:50 -07004889 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4890 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004891 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004892static QCBORError
4893Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004894{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004895 switch(pItem->uDataType) {
4896
4897 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004898 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004899 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004900 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004901 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004902 }
4903 break;
4904
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004905 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004906 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004907 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004908 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004909 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004910 }
4911 break;
4912
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004913#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004914 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004915 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004916 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004917 pItem->val.expAndMantissa.nExponent,
4918 pnValue,
4919 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004920 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004921 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004922 }
4923 break;
4924
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004925 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004926 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004927 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004928 pItem->val.expAndMantissa.nExponent,
4929 pnValue,
4930 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004931 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004932 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004933 }
4934 break;
4935
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004936 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004937 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004938 int64_t nMantissa;
4939 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004940 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4941 if(uErr) {
4942 return uErr;
4943 }
4944 return ExponentiateNN(nMantissa,
4945 pItem->val.expAndMantissa.nExponent,
4946 pnValue,
4947 Exponentitate10);
4948 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004949 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004950 }
4951 break;
4952
4953 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004954 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004955 int64_t nMantissa;
4956 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004957 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4958 if(uErr) {
4959 return uErr;
4960 }
4961 return ExponentiateNN(nMantissa,
4962 pItem->val.expAndMantissa.nExponent,
4963 pnValue,
4964 Exponentitate10);
4965 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004966 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004967 }
4968 break;
4969
4970 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004971 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004972 int64_t nMantissa;
4973 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004974 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4975 if(uErr) {
4976 return uErr;
4977 }
4978 return ExponentiateNN(nMantissa,
4979 pItem->val.expAndMantissa.nExponent,
4980 pnValue,
4981 Exponentitate2);
4982 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004983 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004984 }
4985 break;
4986
4987 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004988 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004989 int64_t nMantissa;
4990 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004991 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4992 if(uErr) {
4993 return uErr;
4994 }
4995 return ExponentiateNN(nMantissa,
4996 pItem->val.expAndMantissa.nExponent,
4997 pnValue,
4998 Exponentitate2);
4999 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005000 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07005001 }
5002 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005003#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005004
Laurence Lundbladee6430642020-03-14 21:15:44 -07005005
Laurence Lundbladec4537442020-04-14 18:53:22 -07005006 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005007 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005008}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005009
5010
Laurence Lundbladec4537442020-04-14 18:53:22 -07005011/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005012 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005013 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005014void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07005015{
5016 QCBORItem Item;
5017
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005018 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07005019
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005020 if(pMe->uLastError == QCBOR_SUCCESS) {
5021 // The above conversion succeeded
5022 return;
5023 }
5024
Laurence Lundbladef6c86662020-05-12 02:08:00 -07005025 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005026 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07005027 return;
5028 }
5029
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005030 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005031}
5032
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005033
5034/*
5035Public function, see header qcbor/qcbor_decode.h file
5036*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005037void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
5038 int64_t nLabel,
5039 uint32_t uConvertTypes,
5040 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005041{
5042 QCBORItem Item;
5043
Laurence Lundblade93d89472020-10-03 22:30:50 -07005044 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
5045 nLabel,
5046 uConvertTypes,
5047 pnValue,
5048 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005049
5050 if(pMe->uLastError == QCBOR_SUCCESS) {
5051 // The above conversion succeeded
5052 return;
5053 }
5054
5055 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5056 // The above conversion failed in a way that code below can't correct
5057 return;
5058 }
5059
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005060 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005061}
5062
5063
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005064/*
5065Public function, see header qcbor/qcbor_decode.h file
5066*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005067void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
5068 const char *szLabel,
5069 uint32_t uConvertTypes,
5070 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005071{
5072 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07005073 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
5074 szLabel,
5075 uConvertTypes,
5076 pnValue,
5077 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005078
5079 if(pMe->uLastError == QCBOR_SUCCESS) {
5080 // The above conversion succeeded
5081 return;
5082 }
5083
5084 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5085 // The above conversion failed in a way that code below can't correct
5086 return;
5087 }
5088
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005089 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005090}
5091
5092
Laurence Lundblade93d89472020-10-03 22:30:50 -07005093static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005094{
5095 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005096 case QCBOR_TYPE_DOUBLE:
5097 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005098#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005099 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005100 // Can't use llround here because it will not convert values
5101 // greater than INT64_MAX and less than UINT64_MAX that
5102 // need to be converted so it is more complicated.
5103 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
5104 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
5105 if(isnan(pItem->val.dfnum)) {
5106 return QCBOR_ERR_FLOAT_EXCEPTION;
5107 } else if(pItem->val.dfnum < 0) {
5108 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5109 } else {
5110 double dRounded = round(pItem->val.dfnum);
5111 // See discussion in DecodeDateEpoch() for
5112 // explanation of - 0x7ff
5113 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
5114 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5115 }
5116 *puValue = (uint64_t)dRounded;
5117 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005118 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005119 if(isnan(pItem->val.fnum)) {
5120 return QCBOR_ERR_FLOAT_EXCEPTION;
5121 } else if(pItem->val.fnum < 0) {
5122 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5123 } else {
5124 float fRounded = roundf(pItem->val.fnum);
5125 // See discussion in DecodeDateEpoch() for
5126 // explanation of - 0x7ff
5127 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
5128 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
5129 }
5130 *puValue = (uint64_t)fRounded;
5131 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005132 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005133 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
5134 // round() and roundf() shouldn't result in exceptions here, but
5135 // catch them to be robust and thorough. Don't try to
5136 // distinguish between the various exceptions because it seems
5137 // they vary by CPU, compiler and OS.
5138 return QCBOR_ERR_FLOAT_EXCEPTION;
5139 }
5140
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005141 } else {
5142 return QCBOR_ERR_UNEXPECTED_TYPE;
5143 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005144#else
5145 return QCBOR_ERR_HW_FLOAT_DISABLED;
5146#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005147 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07005148
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005149 case QCBOR_TYPE_INT64:
5150 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
5151 if(pItem->val.int64 >= 0) {
5152 *puValue = (uint64_t)pItem->val.int64;
5153 } else {
5154 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5155 }
5156 } else {
5157 return QCBOR_ERR_UNEXPECTED_TYPE;
5158 }
5159 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005160
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005161 case QCBOR_TYPE_UINT64:
5162 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
5163 *puValue = pItem->val.uint64;
5164 } else {
5165 return QCBOR_ERR_UNEXPECTED_TYPE;
5166 }
5167 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005168
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005169 default:
5170 return QCBOR_ERR_UNEXPECTED_TYPE;
5171 }
5172
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005173 return QCBOR_SUCCESS;
5174}
Laurence Lundbladec4537442020-04-14 18:53:22 -07005175
5176
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005177void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005178 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005179 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005180 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07005181{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005182 if(pMe->uLastError != QCBOR_SUCCESS) {
5183 return;
5184 }
5185
Laurence Lundbladec4537442020-04-14 18:53:22 -07005186 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005187
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005188 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5189 if(uError) {
5190 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07005191 return;
5192 }
5193
Laurence Lundbladea826c502020-05-10 21:07:00 -07005194 if(pItem) {
5195 *pItem = Item;
5196 }
5197
Laurence Lundblade93d89472020-10-03 22:30:50 -07005198 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07005199}
5200
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005201
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07005202void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005203 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005204 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005205 uint64_t *puValue,
5206 QCBORItem *pItem)
5207{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005208 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005209 if(pMe->uLastError != QCBOR_SUCCESS) {
5210 return;
5211 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005212
Laurence Lundblade93d89472020-10-03 22:30:50 -07005213 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005214}
5215
5216
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005217void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005218 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005219 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005220 uint64_t *puValue,
5221 QCBORItem *pItem)
5222{
5223 if(pMe->uLastError != QCBOR_SUCCESS) {
5224 return;
5225 }
5226
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005227 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005228 if(pMe->uLastError != QCBOR_SUCCESS) {
5229 return;
5230 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005231
Laurence Lundblade93d89472020-10-03 22:30:50 -07005232 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005233}
5234
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005235
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005236
Laurence Lundblade93d89472020-10-03 22:30:50 -07005237static QCBORError
5238UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005239{
Laurence Lundblade68cb61c2023-02-12 13:21:44 -08005240 switch(pItem->uDataType) { /* -Wmaybe-uninitialized falsly warns here */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005241
5242 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005243 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005244 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
5245 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005246 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005247 }
5248 break;
5249
5250 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005251 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005252 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5253 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005254 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005255 }
5256 break;
5257
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005258#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005259
5260 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005261 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005262 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005263 pItem->val.expAndMantissa.nExponent,
5264 puValue,
5265 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005266 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005267 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005268 }
5269 break;
5270
5271 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005272 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005273 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
5274 pItem->val.expAndMantissa.nExponent,
5275 puValue,
5276 Exponentitate2);
5277 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005278 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005279 }
5280 break;
5281
5282 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005283 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005284 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005285 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005286 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005287 if(uErr != QCBOR_SUCCESS) {
5288 return uErr;
5289 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005290 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005291 pItem->val.expAndMantissa.nExponent,
5292 puValue,
5293 Exponentitate10);
5294 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005295 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005296 }
5297 break;
5298
5299 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005300 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005301 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5302 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005303 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005304 }
5305 break;
5306
5307 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005308 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005309 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005310 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005311 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005312 if(uErr != QCBOR_SUCCESS) {
5313 return uErr;
5314 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005315 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005316 pItem->val.expAndMantissa.nExponent,
5317 puValue,
5318 Exponentitate2);
5319 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005320 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005321 }
5322 break;
5323
5324 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005325 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005326 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5327 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005328 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005329 }
5330 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005331#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005332 default:
5333 return QCBOR_ERR_UNEXPECTED_TYPE;
5334 }
5335}
5336
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005337
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005338/*
5339 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005340 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005341void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005342{
5343 QCBORItem Item;
5344
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005345 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005346
Laurence Lundbladef6c86662020-05-12 02:08:00 -07005347 if(pMe->uLastError == QCBOR_SUCCESS) {
5348 // The above conversion succeeded
5349 return;
5350 }
5351
5352 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5353 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07005354 return;
5355 }
5356
Laurence Lundblade93d89472020-10-03 22:30:50 -07005357 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005358}
5359
Laurence Lundbladec4537442020-04-14 18:53:22 -07005360
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005361/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005362 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005363*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07005364void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07005365 int64_t nLabel,
5366 uint32_t uConvertTypes,
5367 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005368{
5369 QCBORItem Item;
5370
Laurence Lundblade93d89472020-10-03 22:30:50 -07005371 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
5372 nLabel,
5373 uConvertTypes,
5374 puValue,
5375 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005376
5377 if(pMe->uLastError == QCBOR_SUCCESS) {
5378 // The above conversion succeeded
5379 return;
5380 }
5381
5382 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5383 // The above conversion failed in a way that code below can't correct
5384 return;
5385 }
5386
Laurence Lundblade93d89472020-10-03 22:30:50 -07005387 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005388}
5389
5390
5391/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005392 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005393*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07005394void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07005395 const char *szLabel,
5396 uint32_t uConvertTypes,
5397 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005398{
5399 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07005400 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
5401 szLabel,
5402 uConvertTypes,
5403 puValue,
5404 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005405
5406 if(pMe->uLastError == QCBOR_SUCCESS) {
5407 // The above conversion succeeded
5408 return;
5409 }
5410
5411 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5412 // The above conversion failed in a way that code below can't correct
5413 return;
5414 }
5415
Laurence Lundblade93d89472020-10-03 22:30:50 -07005416 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005417}
5418
5419
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005420
5421
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02005422#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade9b334962020-08-27 10:55:53 -07005423static QCBORError ConvertDouble(const QCBORItem *pItem,
5424 uint32_t uConvertTypes,
5425 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005426{
5427 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005428 case QCBOR_TYPE_FLOAT:
5429#ifndef QCBOR_DISABLE_FLOAT_HW_USE
5430 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5431 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005432 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005433 *pdValue = (double)pItem->val.fnum;
5434 } else {
5435 return QCBOR_ERR_UNEXPECTED_TYPE;
5436 }
5437 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005438#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005439 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005440#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005441 break;
5442
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005443 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005444 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5445 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005446 *pdValue = pItem->val.dfnum;
5447 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005448 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005449 }
5450 }
5451 break;
5452
5453 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005454#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005455 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005456 // A simple cast seems to do the job with no worry of exceptions.
5457 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005458 *pdValue = (double)pItem->val.int64;
5459
5460 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005461 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005462 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005463#else
5464 return QCBOR_ERR_HW_FLOAT_DISABLED;
5465#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005466 break;
5467
5468 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005469#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005470 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005471 // A simple cast seems to do the job with no worry of exceptions.
5472 // There will be precision loss for some values.
5473 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005474 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005475 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005476 }
5477 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005478#else
5479 return QCBOR_ERR_HW_FLOAT_DISABLED;
5480#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005481
5482 default:
5483 return QCBOR_ERR_UNEXPECTED_TYPE;
5484 }
5485
5486 return QCBOR_SUCCESS;
5487}
5488
5489
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005490void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005491 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005492 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005493 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005494{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005495 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07005496 return;
5497 }
5498
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005499 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005500
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005501 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005502 if(uError) {
5503 pMe->uLastError = (uint8_t)uError;
5504 return;
5505 }
5506
5507 if(pItem) {
5508 *pItem = Item;
5509 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005510
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005511 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005512}
Laurence Lundbladec4537442020-04-14 18:53:22 -07005513
Laurence Lundbladec4537442020-04-14 18:53:22 -07005514
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005515void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
5516 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005517 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005518 double *pdValue,
5519 QCBORItem *pItem)
5520{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005521 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005522 if(pMe->uLastError != QCBOR_SUCCESS) {
5523 return;
5524 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005525
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005526 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005527}
5528
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005529
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005530void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
5531 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005532 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005533 double *pdValue,
5534 QCBORItem *pItem)
5535{
5536 if(pMe->uLastError != QCBOR_SUCCESS) {
5537 return;
5538 }
5539
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005540 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005541 if(pMe->uLastError != QCBOR_SUCCESS) {
5542 return;
5543 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005544
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005545 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005546}
5547
5548
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005549#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005550static double ConvertBigNumToDouble(const UsefulBufC BigNum)
5551{
5552 double dResult;
5553
5554 dResult = 0.0;
5555 const uint8_t *pByte = BigNum.ptr;
5556 size_t uLen = BigNum.len;
5557 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07005558 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005559 while(uLen--) {
5560 dResult = (dResult * 256.0) + (double)*pByte++;
5561 }
5562
5563 return dResult;
5564}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005565#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5566
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005567
Laurence Lundblade93d89472020-10-03 22:30:50 -07005568static QCBORError
5569DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005570{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005571#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005572 /*
Laurence Lundblade16a207a2021-09-18 17:22:46 -07005573 * What Every Computer Scientist Should Know About Floating-Point Arithmetic
5574 * https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
5575 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005576 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005577
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005578#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005579 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005580 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07005581 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005582 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
5583 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
5584 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005585 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005586 }
5587 break;
5588
5589 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005590 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07005591 // Underflow gives 0, overflow gives infinity
5592 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
5593 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005594 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005595 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005596 }
5597 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005598#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005599
5600 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005601 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005602 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
5603 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005604 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005605 }
5606 break;
5607
5608 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005609 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07005610 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005611 } 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
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005616#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005617 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005618 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005619 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5620 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5621 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005622 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005623 }
5624 break;
5625
5626 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005627 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005628 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5629 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5630 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005631 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005632 }
5633 break;
5634
5635 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005636 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005637 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5638 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5639 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005640 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005641 }
5642 break;
5643
5644 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005645 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07005646 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005647 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5648 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005649 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005650 }
5651 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005652#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005653
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005654 default:
5655 return QCBOR_ERR_UNEXPECTED_TYPE;
5656 }
5657
5658 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005659
5660#else
5661 (void)pItem;
5662 (void)uConvertTypes;
5663 (void)pdValue;
5664 return QCBOR_ERR_HW_FLOAT_DISABLED;
5665#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5666
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005667}
5668
5669
5670/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005671 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005672*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005673void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
5674 uint32_t uConvertTypes,
5675 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005676{
5677
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005678 QCBORItem Item;
5679
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005680 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005681
5682 if(pMe->uLastError == QCBOR_SUCCESS) {
5683 // The above conversion succeeded
5684 return;
5685 }
5686
5687 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5688 // The above conversion failed in a way that code below can't correct
5689 return;
5690 }
5691
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005692 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005693}
5694
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005695
5696/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005697 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005698*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005699void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
5700 int64_t nLabel,
5701 uint32_t uConvertTypes,
5702 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005703{
5704 QCBORItem Item;
5705
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005706 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005707
5708 if(pMe->uLastError == QCBOR_SUCCESS) {
5709 // The above conversion succeeded
5710 return;
5711 }
5712
5713 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5714 // The above conversion failed in a way that code below can't correct
5715 return;
5716 }
5717
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005718 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005719}
5720
5721
5722/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005723 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005724*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005725void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
5726 const char *szLabel,
5727 uint32_t uConvertTypes,
5728 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005729{
5730 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005731 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005732
5733 if(pMe->uLastError == QCBOR_SUCCESS) {
5734 // The above conversion succeeded
5735 return;
5736 }
5737
5738 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5739 // The above conversion failed in a way that code below can't correct
5740 return;
5741 }
5742
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005743 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005744}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02005745#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005746
5747
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005748
5749
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005750#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005751static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
5752{
5753 while((uInt & 0xff00000000000000UL) == 0) {
5754 uInt = uInt << 8;
5755 };
5756
5757 UsefulOutBuf UOB;
5758
5759 UsefulOutBuf_Init(&UOB, Buffer);
5760
5761 while(uInt) {
5762 const uint64_t xx = uInt & 0xff00000000000000UL;
5763 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
5764 uInt = uInt << 8;
5765 (void)xx;
5766 }
5767
5768 return UsefulOutBuf_OutUBuf(&UOB);
5769}
5770
5771
Laurence Lundblade37286c02022-09-03 10:05:02 -07005772/**
5773 * @brief Check and/or complete mantissa and exponent item.
5774 *
5775 * @param[in] pMe The decoder context
5776 * @param[in] TagSpec Expected type(s)
5777 * @param[in,out] pItem See below
5778 *
5779 * This is for decimal fractions and big floats, both of which are a
5780 * mantissa and exponent.
5781 *
5782 * The input item is either a fully decoded decimal faction or big
5783 * float, or a just the decoded first item of a decimal fraction or
5784 * big float.
5785 *
5786 * On output, the item is always a fully decoded decimal fraction or
5787 * big float.
5788 *
5789 * This errors out if the input type does not meet the TagSpec.
5790 */
5791// TODO: document and see tests for the bug that was fixed by this rewrite
5792static QCBORError
5793MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
5794 const TagSpecification TagSpec,
5795 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005796{
5797 QCBORError uErr;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005798
Laurence Lundblade37286c02022-09-03 10:05:02 -07005799 /* pItem could either be an auto-decoded mantissa and exponent or
5800 * the opening array of an undecoded mantissa and exponent. This
5801 * check will succeed on either, but doesn't say which it was.
5802 */
5803 uErr = CheckTagRequirement(TagSpec, pItem);
5804 if(uErr != QCBOR_SUCCESS) {
5805 goto Done;
5806 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005807
Laurence Lundblade37286c02022-09-03 10:05:02 -07005808 if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
5809 /* The item is an array, which means is is an undecoded mantissa
5810 * and exponent. This call consumes the items in the array and
5811 * results in a decoded mantissa and exponent in pItem. This is
5812 * the case where there was no tag.
5813 */
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005814 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
5815 if(uErr != QCBOR_SUCCESS) {
5816 goto Done;
5817 }
5818
Laurence Lundblade37286c02022-09-03 10:05:02 -07005819 /* The above decode didn't determine whether it is a decimal
5820 * fraction or big num. Which of these two depends on what the
5821 * caller wants it decoded as since there is no tag, so fish the
5822 * type out of the TagSpec. */
5823 pItem->uDataType = MantissaExponentDataType(TagSpec.uTaggedTypes[0], pItem);
5824
5825 /* No need to check the type again. All that we need to know was
5826 * that it decoded correctly as a mantissa and exponent. The
5827 * QCBOR type is set out by what was requested.
5828 */
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005829 }
Laurence Lundblade37286c02022-09-03 10:05:02 -07005830
5831 /* If the item was not an array and the check passed, then
5832 * it is a fully decoded big float or decimal fraction and
5833 * matches what is requested.
5834 */
5835
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005836Done:
5837 return uErr;
5838}
5839
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005840
Laurence Lundblade37286c02022-09-03 10:05:02 -07005841/* Some notes from the work to disable tags.
5842 *
5843 * The API for big floats and decimal fractions seems good.
5844 * If there's any issue with it it's that the code size to
5845 * implement is a bit large because of the conversion
5846 * to/from int and bignum that is required. There is no API
5847 * that doesn't do the conversion so dead stripping will never
5848 * leave that code out.
5849 *
5850 * The implementation itself seems correct, but not as clean
5851 * and neat as it could be. It could probably be smaller too.
5852 *
5853 * The implementation has three main parts / functions
5854 * - The decoding of the array of two
5855 * - All the tag and type checking for the various API functions
5856 * - Conversion to/from bignum and int
5857 *
5858 * The type checking seems like it wastes the most code for
5859 * what it needs to do.
5860 *
5861 * The inlining for the conversion is probably making the
5862 * overall code base larger.
5863 *
5864 * The tests cases could be organized a lot better and be
5865 * more thorough.
5866 *
5867 * Seems also like there could be more common code in the
5868 * first tier part of the public API. Some functions only
5869 * vary by a TagSpec.
5870 */
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005871static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005872 TagSpecification TagSpec,
5873 QCBORItem *pItem,
5874 int64_t *pnMantissa,
5875 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005876{
5877 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005878
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005879 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005880 if(uErr != QCBOR_SUCCESS) {
5881 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005882 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005883
Laurence Lundblade9b334962020-08-27 10:55:53 -07005884 switch (pItem->uDataType) {
5885
5886 case QCBOR_TYPE_DECIMAL_FRACTION:
5887 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade9b334962020-08-27 10:55:53 -07005888 *pnExponent = pItem->val.expAndMantissa.nExponent;
Laurence Lundblade37286c02022-09-03 10:05:02 -07005889 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
Laurence Lundblade9b334962020-08-27 10:55:53 -07005890 break;
5891
Laurence Lundblade37286c02022-09-03 10:05:02 -07005892#ifndef QCBOR_DISABLE_TAGS
5893 /* If tags are disabled, mantissas can never be big nums */
Laurence Lundblade9b334962020-08-27 10:55:53 -07005894 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5895 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5896 *pnExponent = pItem->val.expAndMantissa.nExponent;
5897 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5898 break;
5899
5900 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5901 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5902 *pnExponent = pItem->val.expAndMantissa.nExponent;
5903 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5904 break;
Laurence Lundblade37286c02022-09-03 10:05:02 -07005905#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundblade9b334962020-08-27 10:55:53 -07005906
5907 default:
5908 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5909 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005910
5911 Done:
5912 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005913}
5914
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005915
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005916static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005917 TagSpecification TagSpec,
5918 QCBORItem *pItem,
5919 UsefulBuf BufferForMantissa,
5920 UsefulBufC *pMantissa,
5921 bool *pbIsNegative,
5922 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005923{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005924 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005925
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005926 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005927 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005928 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005929 }
5930
5931 uint64_t uMantissa;
5932
5933 switch (pItem->uDataType) {
5934
5935 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005936 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005937 /* See comments in ExponentiateNN() on handling INT64_MIN */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005938 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5939 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5940 *pbIsNegative = false;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005941 } else if(pItem->val.expAndMantissa.Mantissa.nInt != INT64_MIN) {
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005942 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5943 *pbIsNegative = true;
Laurence Lundblade4e808ba2022-12-29 12:45:20 -07005944 } else {
5945 uMantissa = (uint64_t)INT64_MAX+1;
5946 *pbIsNegative = true;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005947 }
5948 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5949 *pnExponent = pItem->val.expAndMantissa.nExponent;
5950 break;
5951
Laurence Lundblade37286c02022-09-03 10:05:02 -07005952#ifndef QCBOR_DISABLE_TAGS
5953 /* If tags are disabled, mantissas can never be big nums */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005954 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005955 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005956 *pnExponent = pItem->val.expAndMantissa.nExponent;
5957 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5958 *pbIsNegative = false;
5959 break;
5960
5961 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005962 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005963 *pnExponent = pItem->val.expAndMantissa.nExponent;
5964 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5965 *pbIsNegative = true;
5966 break;
Laurence Lundblade37286c02022-09-03 10:05:02 -07005967#endif /* QCBOR_DISABLE_TAGS */
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005968
5969 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005970 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005971 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005972
5973Done:
5974 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005975}
5976
5977
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005978/*
5979 Public function, see header qcbor/qcbor_decode.h file
5980*/
5981void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5982 uint8_t uTagRequirement,
5983 int64_t *pnMantissa,
5984 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005985{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005986 if(pMe->uLastError != QCBOR_SUCCESS) {
5987 return;
5988 }
5989
5990 QCBORItem Item;
5991 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5992 if(uError) {
5993 pMe->uLastError = (uint8_t)uError;
5994 return;
5995 }
5996
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005997 const TagSpecification TagSpec =
5998 {
5999 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006000 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6001 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6002 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006003 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006004
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006005 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006006}
6007
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006008
6009/*
6010 Public function, see header qcbor/qcbor_decode.h file
6011*/
6012void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006013 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07006014 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006015 int64_t *pnMantissa,
6016 int64_t *pnExponent)
6017{
6018 if(pMe->uLastError != QCBOR_SUCCESS) {
6019 return;
6020 }
6021
6022 QCBORItem Item;
6023 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
6024
6025 const TagSpecification TagSpec =
6026 {
6027 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006028 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6029 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6030 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006031 };
6032
6033 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
6034}
6035
6036
6037/*
6038 Public function, see header qcbor/qcbor_decode.h file
6039*/
6040void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006041 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07006042 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006043 int64_t *pnMantissa,
6044 int64_t *pnExponent)
6045{
6046 if(pMe->uLastError != QCBOR_SUCCESS) {
6047 return;
6048 }
6049
6050 QCBORItem Item;
6051 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6052
6053 const TagSpecification TagSpec =
6054 {
6055 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006056 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6057 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6058 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006059 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07006060
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006061 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
6062}
6063
6064
6065/*
6066 Public function, see header qcbor/qcbor_decode.h file
6067*/
6068void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
6069 uint8_t uTagRequirement,
Laurence Lundblade37286c02022-09-03 10:05:02 -07006070 UsefulBuf MantissaBuffer,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006071 UsefulBufC *pMantissa,
6072 bool *pbMantissaIsNegative,
6073 int64_t *pnExponent)
6074{
6075 if(pMe->uLastError != QCBOR_SUCCESS) {
6076 return;
6077 }
6078
6079 QCBORItem Item;
6080 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6081 if(uError) {
6082 pMe->uLastError = (uint8_t)uError;
6083 return;
6084 }
6085
6086 const TagSpecification TagSpec =
6087 {
6088 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006089 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6090 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6091 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006092 };
6093
Laurence Lundblade93d89472020-10-03 22:30:50 -07006094 ProcessMantissaAndExponentBig(pMe,
6095 TagSpec,
6096 &Item,
6097 MantissaBuffer,
6098 pMantissa,
6099 pbMantissaIsNegative,
6100 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006101}
6102
6103
6104/*
6105 Public function, see header qcbor/qcbor_decode.h file
6106*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006107void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006108 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07006109 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006110 UsefulBuf BufferForMantissa,
6111 UsefulBufC *pMantissa,
6112 bool *pbIsNegative,
6113 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006114{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006115 if(pMe->uLastError != QCBOR_SUCCESS) {
6116 return;
6117 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006118
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006119 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006120 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006121 if(pMe->uLastError != QCBOR_SUCCESS) {
6122 return;
6123 }
6124
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006125 const TagSpecification TagSpec =
6126 {
6127 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006128 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6129 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6130 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006131 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006132
Laurence Lundblade93d89472020-10-03 22:30:50 -07006133 ProcessMantissaAndExponentBig(pMe,
6134 TagSpec,
6135 &Item,
6136 BufferForMantissa,
6137 pMantissa,
6138 pbIsNegative,
6139 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006140}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006141
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006142
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006143/*
6144 Public function, see header qcbor/qcbor_decode.h file
6145*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006146void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006147 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07006148 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006149 UsefulBuf BufferForMantissa,
6150 UsefulBufC *pMantissa,
6151 bool *pbIsNegative,
6152 int64_t *pnExponent)
6153{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006154 if(pMe->uLastError != QCBOR_SUCCESS) {
6155 return;
6156 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006157
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006158 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006159 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6160 if(pMe->uLastError != QCBOR_SUCCESS) {
6161 return;
6162 }
6163
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006164 const TagSpecification TagSpec =
6165 {
6166 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006167 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
6168 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
6169 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006170 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006171
6172 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
6173}
6174
6175
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006176/*
6177 Public function, see header qcbor/qcbor_decode.h file
6178*/
6179void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
6180 uint8_t uTagRequirement,
6181 int64_t *pnMantissa,
6182 int64_t *pnExponent)
6183{
6184 if(pMe->uLastError != QCBOR_SUCCESS) {
6185 return;
6186 }
6187
6188 QCBORItem Item;
6189 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6190 if(uError) {
6191 pMe->uLastError = (uint8_t)uError;
6192 return;
6193 }
6194 const TagSpecification TagSpec =
6195 {
6196 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006197 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6198 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6199 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006200 };
6201
6202 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
6203}
6204
6205
6206/*
6207 Public function, see header qcbor/qcbor_decode.h file
6208*/
6209void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006210 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07006211 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006212 int64_t *pnMantissa,
6213 int64_t *pnExponent)
6214{
6215 if(pMe->uLastError != QCBOR_SUCCESS) {
6216 return;
6217 }
6218
6219 QCBORItem Item;
6220 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
6221 if(pMe->uLastError != QCBOR_SUCCESS) {
6222 return;
6223 }
6224
6225 const TagSpecification TagSpec =
6226 {
6227 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006228 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6229 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6230 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006231 };
6232
6233 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
6234}
6235
6236
6237/*
6238 Public function, see header qcbor/qcbor_decode.h file
6239*/
6240void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006241 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07006242 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006243 int64_t *pnMantissa,
6244 int64_t *pnExponent)
6245{
6246 if(pMe->uLastError != QCBOR_SUCCESS) {
6247 return;
6248 }
6249
6250 QCBORItem Item;
6251 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6252 if(pMe->uLastError != QCBOR_SUCCESS) {
6253 return;
6254 }
6255
6256 const TagSpecification TagSpec =
6257 {
6258 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006259 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6260 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6261 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006262 };
6263
6264 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
6265}
6266
6267
6268/*
6269 Public function, see header qcbor/qcbor_decode.h file
6270*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006271void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
6272 uint8_t uTagRequirement,
6273 UsefulBuf MantissaBuffer,
6274 UsefulBufC *pMantissa,
6275 bool *pbMantissaIsNegative,
6276 int64_t *pnExponent)
6277{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006278 if(pMe->uLastError != QCBOR_SUCCESS) {
6279 return;
6280 }
6281
6282 QCBORItem Item;
6283 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
6284 if(uError) {
6285 pMe->uLastError = (uint8_t)uError;
6286 return;
6287 }
6288
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006289 const TagSpecification TagSpec =
6290 {
6291 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006292 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6293 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6294 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006295 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006296
6297 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006298}
6299
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006300
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006301/*
6302 Public function, see header qcbor/qcbor_decode.h file
6303*/
6304void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006305 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07006306 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006307 UsefulBuf BufferForMantissa,
6308 UsefulBufC *pMantissa,
6309 bool *pbIsNegative,
6310 int64_t *pnExponent)
6311{
6312 if(pMe->uLastError != QCBOR_SUCCESS) {
6313 return;
6314 }
6315
6316 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006317 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
6318 if(pMe->uLastError != QCBOR_SUCCESS) {
6319 return;
6320 }
6321
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006322 const TagSpecification TagSpec =
6323 {
6324 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006325 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6326 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6327 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006328 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006329
Laurence Lundblade93d89472020-10-03 22:30:50 -07006330 ProcessMantissaAndExponentBig(pMe,
6331 TagSpec,
6332 &Item,
6333 BufferForMantissa,
6334 pMantissa,
6335 pbIsNegative,
6336 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006337}
6338
6339
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006340/*
6341 Public function, see header qcbor/qcbor_decode.h file
6342*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006343void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006344 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07006345 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006346 UsefulBuf BufferForMantissa,
6347 UsefulBufC *pMantissa,
6348 bool *pbIsNegative,
6349 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006350{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006351 if(pMe->uLastError != QCBOR_SUCCESS) {
6352 return;
6353 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006354
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006355 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006356 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
6357 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07006358 return;
6359 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006360
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006361 const TagSpecification TagSpec =
6362 {
6363 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07006364 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
6365 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
6366 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07006367 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07006368
Laurence Lundblade93d89472020-10-03 22:30:50 -07006369 ProcessMantissaAndExponentBig(pMe,
6370 TagSpec,
6371 &Item,
6372 BufferForMantissa,
6373 pMantissa,
6374 pbIsNegative,
6375 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07006376}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07006377
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07006378#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */