blob: ebcbc97dab4c90a437df2f3f313f90c08788c5d2 [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 Lundblade3f1318a2021-01-04 18:26:44 -08003 Copyright (c) 2018-2021, Laurence Lundblade.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07004 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08005
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07006Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are
8met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15 * Neither the name of The Linux Foundation nor the names of its
16 contributors, nor the name "Laurence Lundblade" may be used to
17 endorse or promote products derived from this software without
18 specific prior written permission.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080019
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070020THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080031 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070032
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080033
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080034#include "qcbor/qcbor_decode.h"
Laurence Lundblade67257dc2020-07-27 03:33:37 -070035#include "qcbor/qcbor_spiffy_decode.h"
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080036#include "ieee754.h" /* Does not use math.h */
Laurence Lundbladec7114722020-08-13 05:11:40 -070037
38#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080039
40#include <math.h> /* For isnan(), llround(), llroudf(), round(), roundf(),
41 * pow(), exp2()
42 */
43#include <fenv.h> /* feclearexcept(), fetestexcept() */
44
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080045#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070046
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070047
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080048
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053049/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080050 * This casts away the const-ness of a pointer, usually so it can be
51 * freed or realloced.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053052 */
53#define UNCONST_POINTER(ptr) ((void *)(ptr))
54
Laurence Lundbladea9489f82020-09-12 13:50:56 -070055#define SIZEOF_C_ARRAY(array,type) (sizeof(array)/sizeof(type))
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070056
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070057
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080058
59
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070060static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070061QCBORItem_IsMapOrArray(const QCBORItem *pMe)
62{
63 const uint8_t uDataType = pMe->uDataType;
64 return uDataType == QCBOR_TYPE_MAP ||
65 uDataType == QCBOR_TYPE_ARRAY ||
66 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
67}
68
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070069static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070070QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem *pMe)
71{
72 if(!QCBORItem_IsMapOrArray(pMe)){
73 return false;
74 }
75
76 if(pMe->val.uCount != 0) {
77 return false;
78 }
79 return true;
80}
81
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070082static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070083QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem *pMe)
84{
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080085#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -070086 if(!QCBORItem_IsMapOrArray(pMe)){
87 return false;
88 }
89
90 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
91 return false;
92 }
93 return true;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080094#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
95 (void)pMe;
96 return false;
97#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade02625d42020-06-25 14:41:41 -070098}
99
100
Laurence Lundbladeee851742020-01-08 08:37:05 -0800101/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700102 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -0800103 ===========================================================================*/
104
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700105/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800106 * See comments about and typedef of QCBORDecodeNesting in qcbor_private.h,
107 * the data structure all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700108 */
109
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700110
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700111static inline uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700112DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700113{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700114 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800115 /* Limit in DecodeNesting_Descend against more than
116 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700117 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700118 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700119}
120
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700121
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700122static inline uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700123DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700124{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700125 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800126 /* Limit in DecodeNesting_Descend against more than
127 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700128 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700129 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700130}
131
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700132
Laurence Lundblade5f4e8712020-07-25 11:44:43 -0700133static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700134DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700135{
136 return pNesting->pCurrentBounded->u.ma.uStartOffset;
137}
138
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700139
Laurence Lundblade085d7952020-07-24 10:26:30 -0700140static inline bool
141DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
142{
143 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
144 return true;
145 } else {
146 return false;
147 }
148}
149
150
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700151static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700152DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700153{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700154 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700155 return true;
156 } else {
157 return false;
158 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700159}
160
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700161
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700162static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700163DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700164{
165 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800166 /* Not a map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700167 return false;
168 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800169
170#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700171 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800172 /* Is indefinite */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700173 return false;
174 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800175
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800176#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
177
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800178 /* All checks passed; is a definte length map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700179 return true;
180}
181
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700182static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700183DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700184{
185 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800186 /* is a byte string */
Laurence Lundblade642282a2020-06-23 12:00:33 -0700187 return true;
188 }
189 return false;
190}
191
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700192
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700193static inline bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700194{
195 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
196 return true;
197 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700198 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700199 return true;
200 }
201 return false;
202}
203
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700204
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700205static inline void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700206{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800207 /* Should be only called on maps and arrays */
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700208 /*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800209 * DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
210 * larger than DecodeNesting_EnterBoundedMode which keeps it less than
211 * uin32_t so the cast is safe.
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700212 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700213 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700214
215 if(bIsEmpty) {
216 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
217 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700218}
219
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700220
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700221static inline void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700222{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700223 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700224}
225
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700226
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700227static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700228DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700229{
230 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800231 /* No bounded map or array set up */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700232 return false;
233 }
234 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800235 /* Not a map or array; end of those is by byte count */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700236 return false;
237 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700238 if(!DecodeNesting_IsCurrentBounded(pNesting)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800239 /* In a traveral at a level deeper than the bounded level */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700240 return false;
241 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800242 /* Works for both definite- and indefinitelength maps/arrays */
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800243 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0 &&
244 pNesting->pCurrentBounded->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800245 /* Count is not zero, still unconsumed item */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700246 return false;
247 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800248 /* All checks passed, got to the end of an array or map*/
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700249 return true;
250}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700251
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700252
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700253static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700254DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700255{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800256 /* Must only be called on map / array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700257 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
258 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700259 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700260 return false;
261 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700262}
263
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700264
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700265static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700266DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700267{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700268 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
269 return true;
270 } else {
271 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700272 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700273}
274
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700275
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700276static inline bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700277DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700278{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700279 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700280 return false;
281 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700282
283 if(pNesting->pCurrentBounded->uLevelType != uType) {
284 return false;
285 }
286
287 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700288}
289
Laurence Lundblade02625d42020-06-25 14:41:41 -0700290
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700291static inline void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700292DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700293{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800294 /* Only call on a definite-length array / map */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700295 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700296}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700297
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700298
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700299static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700300DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
301{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800302 /* Only call on a definite-length array / map */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700303 pNesting->pCurrent->u.ma.uCountCursor++;
304}
305
306
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700307static inline void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700308DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
309{
310 pNesting->pCurrent--;
311}
312
Laurence Lundblade02625d42020-06-25 14:41:41 -0700313
314static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700315DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700316{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800317 /* Error out if nesting is too deep */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700318 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700319 return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700320 }
321
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800322 /* The actual descend */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700323 pNesting->pCurrent++;
324
325 pNesting->pCurrent->uLevelType = uType;
326
327 return QCBOR_SUCCESS;
328}
329
330
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700331static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800332DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting,
333 bool bIsEmpty,
334 size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700335{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700336 /*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800337 * Should only be called on map/array.
338 *
339 * Have descended into this before this is called. The job here is
340 * just to mark it in bounded mode.
341 *
342 * Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
343 * uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET.
344 *
345 * Cast of uOffset to uint32_t for cases where SIZE_MAX < UINT32_MAX.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700346 */
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -0800347 if((uint32_t)uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700348 return QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700349 }
350
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700351 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700352
353 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700354
355 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700356}
357
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700358
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700359static inline QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700360DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700361 uint8_t uQCBORType,
362 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700363{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700364 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700365
366 if(uCount == 0) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800367 /* Nothing to do for empty definite-length arrays. They are just are
368 * effectively the same as an item that is not a map or array.
369 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700370 goto Done;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800371 /* Empty indefinite-length maps and arrays are handled elsewhere */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700372 }
373
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800374 /* Error out if arrays is too long to handle */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700375 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
376 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700377 uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700378 goto Done;
379 }
380
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700381 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700382 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700383 goto Done;
384 }
385
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800386 /* Fill in the new map/array level. Check above makes casts OK. */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700387 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
388 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700389
390 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700391
392Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700393 return uError;;
394}
395
396
397static inline void
398DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
399{
400 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
401}
402
403
404static inline void
405DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
406{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700407 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700408 pNesting->pCurrentBounded--;
409 if(DecodeNesting_IsCurrentBounded(pNesting)) {
410 break;
411 }
412 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700413}
414
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800415
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700416static inline void
417DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
418{
419 pNesting->pCurrent = pNesting->pCurrentBounded;
420}
421
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700422
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700423static inline QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700424DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700425 uint32_t uEndOffset,
426 uint32_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700427{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700428 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700429
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700430 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700431 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700432 goto Done;
433 }
434
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800435 /* Fill in the new byte string level */
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700436 pNesting->pCurrent->u.bs.uPreviousEndOffset = uEndOffset;
437 pNesting->pCurrent->u.bs.uEndOfBstr = uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700438
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800439 /* Bstr wrapped levels are always bounded */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700440 pNesting->pCurrentBounded = pNesting->pCurrent;
441
442Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700443 return uError;;
444}
445
Laurence Lundbladed0304932020-06-27 10:59:38 -0700446
447static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700448DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700449{
450 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700451}
452
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700453
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700454static inline void
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800455DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
456{
457 pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
458}
459
460
461static inline void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700462DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700463{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700464 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700465 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
466 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700467}
468
469
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700470static inline void
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800471DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting,
472 QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700473{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700474 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700475 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800476 DecodeNesting_ResetMapOrArrayCount(pNesting);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700477}
478
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700479
Laurence Lundblade02625d42020-06-25 14:41:41 -0700480static inline void
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800481DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting,
482 const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700483{
484 *pNesting = *pSave;
485}
486
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700487
Laurence Lundblade02625d42020-06-25 14:41:41 -0700488static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700489DecodeNesting_GetEndOfBstr(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700490{
491 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
492}
493
494
Laurence Lundblade02625d42020-06-25 14:41:41 -0700495static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700496DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700497{
498 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
499}
500
501
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800502
503
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800504#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladeee851742020-01-08 08:37:05 -0800505/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800506 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
507
508 The following four functions are pretty wrappers for invocation of
509 the string allocator supplied by the caller.
510
Laurence Lundbladeee851742020-01-08 08:37:05 -0800511 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800512
Laurence Lundbladeee851742020-01-08 08:37:05 -0800513static inline void
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800514StringAllocator_Free(const QCBORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800515{
516 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
517}
518
Laurence Lundbladeee851742020-01-08 08:37:05 -0800519// StringAllocator_Reallocate called with pMem NULL is
520// equal to StringAllocator_Allocate()
521static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800522StringAllocator_Reallocate(const QCBORInternalAllocator *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800523 void *pMem,
524 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800525{
526 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
527}
528
Laurence Lundbladeee851742020-01-08 08:37:05 -0800529static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800530StringAllocator_Allocate(const QCBORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800531{
532 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
533}
534
Laurence Lundbladeee851742020-01-08 08:37:05 -0800535static inline void
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800536StringAllocator_Destruct(const QCBORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800537{
538 if(pMe->pfAllocator) {
539 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
540 }
541}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800542#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800543
544
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800545
546
Laurence Lundbladeee851742020-01-08 08:37:05 -0800547/*===========================================================================
548 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700549
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800550 See qcbor/qcbor_decode.h for definition of the object
551 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800552 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700553/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800554 * Public function, see header file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700555 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800556void QCBORDecode_Init(QCBORDecodeContext *pMe,
557 UsefulBufC EncodedCBOR,
558 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700559{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800560 memset(pMe, 0, sizeof(QCBORDecodeContext));
561 UsefulInputBuf_Init(&(pMe->InBuf), EncodedCBOR);
562 /* Don't bother with error check on decode mode. If a bad value is
563 * passed it will just act as if the default normal mode of 0 was set.
564 */
565 pMe->uDecodeMode = (uint8_t)nDecodeMode;
566 DecodeNesting_Init(&(pMe->nesting));
567
568 /* Inialize me->auMappedTags to CBOR_TAG_INVALID16. See
569 * GetNext_TaggedItem() and MapTagNumber(). */
570 memset(pMe->auMappedTags, 0xff, sizeof(pMe->auMappedTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700571}
572
573
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800574#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
575
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700576/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800577 * Public function, see header file
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700578 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800579void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
580 QCBORStringAllocate pfAllocateFunction,
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800581 void *pAllocateContext,
582 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700583{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800584 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
585 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
586 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700587}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800588#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700589
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800590
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800591
592
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800593/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800594 * Deprecated public function, see header file
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800595 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800596void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800597 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700598{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800599 /* This does nothing now. It is retained for backwards compatibility */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700600 (void)pMe;
601 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700602}
603
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700604
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800605
606
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700607/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800608 * Decoding items is done in six layers, one calling the next one
609 * down. If a layer has no work to do for a particular item, it
610 * returns quickly.
611 *
612 * 1. QCBORDecode_GetNextTagContent - The top layer processes tagged
613 * data items, turning them into the local C representation. For the
614 * most simple it is just associating a QCBOR_TYPE with the data. For
615 * the complex ones that an aggregate of data items, there is some
616 * further decoding and some limited recursion.
617 *
618 * 2. QCBORDecode_GetNextMapOrArray - This manages the beginnings and
619 * ends of maps and arrays. It tracks descending into and ascending
620 * out of maps/arrays. It processes breaks that terminate
621 * indefinite-length maps and arrays.
622 *
623 * 3. QCBORDecode_GetNextMapEntry - This handles the combining of two
624 * items, the label and the data, that make up a map entry. It only
625 * does work on maps. It combines the label and data items into one
626 * labeled item.
627 *
628 * 4. QCBORDecode_GetNextTagNumber - This decodes type 6 tag
629 * numbers. It turns the tag numbers into bit flags associated with
630 * the data item. No actual decoding of the contents of the tag is
631 * performed here.
632 *
633 * 5. QCBORDecode_GetNextFullString - This assembles the sub-items
634 * that make up an indefinite-length string into one string item. It
635 * uses the string allocator to create contiguous space for the
636 * item. It processes all breaks that are part of indefinite-length
637 * strings.
638 *
639 * 6. DecodeAtomicDataItem - This decodes the atomic data items in
640 * CBOR. Each atomic data item has a "major type", an integer
641 * "argument" and optionally some content. For text and byte strings,
642 * the content is the bytes that make up the string. These are the
643 * smallest data items that are considered to be well-formed. The
644 * content may also be other data items in the case of aggregate
645 * types. They are not handled in this layer.
646 *
647 * Roughly this takes 300 bytes of stack for vars. TODO: evaluate this
648 * more carefully and correctly.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700649 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800650
651
652/*
653 * Note about use of int and unsigned variables.
654 *
655 * See http://www.unix.org/whitepapers/64bit.html for reasons int is
656 * used carefully here, and in particular why it isn't used in the
657 * public interface. Also see
658 * https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
659 *
660 * Int is used for values that need less than 16-bits and would be
661 * subject to integer promotion and result in complaining from static
662 * analyzers.
663 */
664
665
666/**
667 * @brief Decode the CBOR head, the type and argument.
668 *
669 * @param[in] pUInBuf The input buffer to read from.
670 * @param[out] pnMajorType The decoded major type.
671 * @param[out] puArgument The decoded argument.
672 * @param[out] pnAdditionalInfo The decoded Lower 5 bits of initial byte.
673 *
674 * @retval QCBOR_ERR_UNSUPPORTED
675 * @retval QCBOR_ERR_HIT_END
676 *
677 * This decodes the CBOR "head" that every CBOR data item has. See
678 * longer explaination of the head in documentation for
679 * QCBOREncode_EncodeHead().
680 *
681 * This does the network->host byte order conversion. The conversion
682 * here also results in the conversion for floats in addition to that
683 * for lengths, tags and integer values.
684 *
685 * The int type is preferred to uint8_t for some variables as this
686 * avoids integer promotions, can reduce code size and makes static
687 * analyzers happier.
688 */
689static inline QCBORError
690DecodeHead(UsefulInputBuf *pUInBuf,
691 int *pnMajorType,
692 uint64_t *puArgument,
693 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700694{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800695 QCBORError uReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800696
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800697 /* Get the initial byte that every CBOR data item has and break it
698 * down. */
699 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800700 const int nTmpMajorType = nInitialByte >> 5;
701 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800702
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800703 /* Where the argument accumulates */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800704 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800705
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800706 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800707 /* Need to get 1,2,4 or 8 additional argument bytes. Map
708 * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
709 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800710 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800711
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800712 /* Loop getting all the bytes in the argument */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800713 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800714 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800715 /* This shift and add gives the endian conversion. */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800716 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
717 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800718 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800719 /* The reserved and thus-far unused additional info values */
720 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800721 goto Done;
722 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800723 /* Less than 24, additional info is argument or 31, an
724 * indefinite-length. No more bytes to get.
725 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800726 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700727 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800728
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700729 if(UsefulInputBuf_GetError(pUInBuf)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800730 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700731 goto Done;
732 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800733
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800734 /* All successful if arrived here. */
735 uReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800736 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800737 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800738 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800739
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700740Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800741 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700742}
743
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800744
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800745/**
746 * @brief Decode integer types, major types 0 and 1.
747 *
748 * @param[in] nMajorType The CBOR major type (0 or 1).
749 * @param[in] uArgument The argument from the head.
750 * @param[out] pDecodedItem The filled in decoded item.
751 *
752 * @retval QCBOR_ERR_INT_OVERFLOW
753 *
754 * Must only be called when major type is 0 or 1.
755 *
756 * CBOR doesn't explicitly specify two's compliment for integers but
757 * all CPUs use it these days and the test vectors in the RFC are
758 * so. All integers in the CBOR structure are positive and the major
759 * type indicates positive or negative. CBOR can express positive
760 * integers up to 2^x - 1 where x is the number of bits and negative
761 * integers down to 2^x. Note that negative numbers can be one more
762 * away from zero than positive. Stdint, as far as I can tell, uses
763 * two's compliment to represent negative integers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700764 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700765static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800766DecodeInteger(int nMajorType, uint64_t uArgument, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700767{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800768 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800769
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700770 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800771 if (uArgument <= INT64_MAX) {
772 pDecodedItem->val.int64 = (int64_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700773 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800774
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700775 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800776 pDecodedItem->val.uint64 = uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700777 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700778 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800779
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700780 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800781 if(uArgument <= INT64_MAX) {
782 /* CBOR's representation of negative numbers lines up with
783 * the two-compliment representation. A negative integer has
784 * one more in range than a positive integer. INT64_MIN is
785 * equal to (-INT64_MAX) - 1.
786 */
787 pDecodedItem->val.int64 = (-(int64_t)uArgument) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700788 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800789
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700790 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800791 /* C can't represent a negative integer in this range so it
792 * is an error.
793 */
794 uReturn = QCBOR_ERR_INT_OVERFLOW;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700795 }
796 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800797
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800798 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700799}
800
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800801
802/* Make sure #define value line up as DecodeSimple counts on this. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700803#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
804#error QCBOR_TYPE_FALSE macro value wrong
805#endif
806
807#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
808#error QCBOR_TYPE_TRUE macro value wrong
809#endif
810
811#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
812#error QCBOR_TYPE_NULL macro value wrong
813#endif
814
815#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
816#error QCBOR_TYPE_UNDEF macro value wrong
817#endif
818
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700819#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
820#error QCBOR_TYPE_BREAK macro value wrong
821#endif
822
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700823#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
824#error QCBOR_TYPE_DOUBLE macro value wrong
825#endif
826
827#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
828#error QCBOR_TYPE_FLOAT macro value wrong
829#endif
830
Laurence Lundblade9b334962020-08-27 10:55:53 -0700831
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800832/**
833 * @brief Decode major type 7 -- true, false, floating-point, break...
834 *
835 * @param[in] nAdditionalInfo The lower five bits from the initial byte.
836 * @param[in] uArgument The argument from the head.
837 * @param[out] pDecodedItem The filled in decoded item.
838 *
839 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
840 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700841 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800842
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800843static inline QCBORError
844DecodeType7(int nAdditionalInfo, uint64_t uArgument, QCBORItem *pDecodedItem)
845{
846 QCBORError uReturn = QCBOR_SUCCESS;
847
848 /* uAdditionalInfo is 5 bits from the initial byte. Compile time
849 * checks above make sure uAdditionalInfo values line up with
850 * uDataType values. DecodeHead() never returns an AdditionalInfo
851 * > 0x1f so cast is safe.
852 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800853 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800854
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800855 switch(nAdditionalInfo) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800856 /* No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they
857 * are caught before this is called.
858 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800859
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800860 case HALF_PREC_FLOAT: /* 25 */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700861#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800862 /* Half-precision is returned as a double. The cast to
863 * uint16_t is safe because the encoded value was 16 bits. It
864 * was widened to 64 bits to be passed in here.
865 */
866 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700867 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800868#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800869 uReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800870#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700871 break;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800872 case SINGLE_PREC_FLOAT: /* 26 */
873 /* Single precision is normally returned as a double since
874 * double is widely supported, there is no loss of precision,
875 * it makes it easy for the caller in most cases and it can
876 * be converted back to single with no loss of precision
877 *
878 * The cast to uint32_t is safe because the encoded value was
879 * 32 bits. It was widened to 64 bits to be passed in here.
880 */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700881 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800882 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uArgument);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700883#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800884 /* In the normal case, use HW to convert float to
885 * double. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700886 pDecodedItem->val.dfnum = (double)f;
887 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800888#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800889 /* Use of float HW is disabled, return as a float. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700890 pDecodedItem->val.fnum = f;
891 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
892
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800893 /* IEEE754_FloatToDouble() could be used here to return as
894 * a double, but it adds object code and most likely
895 * anyone disabling FLOAT HW use doesn't care about floats
896 * and wants to save object code.
897 */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800898#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700899 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700900 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700901
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800902 case DOUBLE_PREC_FLOAT: /* 27 */
903 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700904 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700905 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800906
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800907 case CBOR_SIMPLEV_FALSE: /* 20 */
908 case CBOR_SIMPLEV_TRUE: /* 21 */
909 case CBOR_SIMPLEV_NULL: /* 22 */
910 case CBOR_SIMPLEV_UNDEF: /* 23 */
911 case CBOR_SIMPLE_BREAK: /* 31 */
912 break; /* nothing to do */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800913
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800914 case CBOR_SIMPLEV_ONEBYTE: /* 24 */
915 if(uArgument <= CBOR_SIMPLE_BREAK) {
916 /* This takes out f8 00 ... f8 1f which should be encoded
917 * as e0 … f7
918 */
919 uReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700920 goto Done;
921 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800922 /* FALLTHROUGH */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800923
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800924 default: /* 0-19 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700925 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800926 /* DecodeHead() will make uArgument equal to
927 * nAdditionalInfo when nAdditionalInfo is < 24. This cast is
928 * safe because the 2, 4 and 8 byte lengths of uNumber are in
929 * the double/float cases above
Laurence Lundbladeee851742020-01-08 08:37:05 -0800930 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800931 pDecodedItem->val.uSimple = (uint8_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700932 break;
933 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800934
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700935Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800936 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700937}
938
939
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800940/**
941 * @brief Decode text and byte strings
942 *
943 * @param[in] pAllocator The string allocator or NULL.
944 * @param[in] uStrLen The length of the string.
945 * @param[in] pUInBuf The surce from which to read the string's bytes.
946 * @param[out] pDecodedItem The filled in decoded item.
947 *
948 * @retval QCBOR_ERR_HIT_END
949 * @retval QCBOR_ERR_STRING_ALLOCATE
950 * @retval QCBOR_ERR_STRING_TOO_LONG
951 *
952 * The reads @c uStrlen bytes from @c pUInBuf and fills in @c
953 * pDecodedItem. If @c pAllocator is not NULL then memory for the
954 * string is allocated.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700955 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800956static inline QCBORError
957DecodeBytes(const QCBORInternalAllocator *pAllocator,
958 uint64_t uStrLen,
959 UsefulInputBuf *pUInBuf,
960 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700961{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800962 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800963
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800964 /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
965 * CPUs. This check makes the casts to size_t below safe.
966 *
967 * The max is 4 bytes less than the largest sizeof() so this can be
968 * tested by putting a SIZE_MAX length in the CBOR test input (no
969 * one will care the limit on strings is 4 bytes shorter).
970 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800971 if(uStrLen > SIZE_MAX-4) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800972 uReturn = QCBOR_ERR_STRING_TOO_LONG;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800973 goto Done;
974 }
975
976 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530977 if(UsefulBuf_IsNULLC(Bytes)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800978 /* Failed to get the bytes for this string item */
979 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530980 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700981 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530982
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800983#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800984 /* Note that this is not where allocation to coalesce
985 * indefinite-length strings is done. This is for when the caller
986 * has requested all strings be allocated. Disabling indefinite
987 * length strings also disables this allocate-all option.
988 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800989 if(pAllocator) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800990 /* request to use the string allocator to make a copy */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800991 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530992 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800993 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530994 goto Done;
995 }
996 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800997 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800998 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530999 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001000#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1001 (void)pAllocator;
1002#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1003
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001004 /* Normal case with no string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001005 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001006
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301007Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001008 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001009}
1010
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001011
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001012/**
1013 * @brief Map the CBOR major types for strings to the QCBOR types.
1014 *
1015 * @param[in] nCBORMajorType The CBOR major type to convert.
1016 * @retturns QCBOR type number.
1017 *
1018 * This only works for the two string types.
1019 */
1020static inline uint8_t ConvertStringMajorTypes(int nCBORMajorType)
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001021{
1022 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
1023 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
1024 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001025
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001026 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
1027 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
1028 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001029
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001030 return (uint8_t)(nCBORMajorType + 4);
1031}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001032
1033
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001034/**
1035 * @brief Map the CBOR major types for arrays/maps to the QCBOR types.
1036 *
1037 * @param[in] nCBORMajorType The CBOR major type to convert.
1038 * @retturns QCBOR type number.
1039 *
1040 * This only works for the two aggregate types.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001041 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001042static inline uint8_t ConvertArrayOrMapType(int nCBORMajorType)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001043{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001044 #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
1045 #error QCBOR_TYPE_ARRAY value not lined up with major type
1046 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001047
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001048 #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
1049 #error QCBOR_TYPE_MAP value not lined up with major type
1050 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001051
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001052 return (uint8_t)(nCBORMajorType);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001053}
1054
1055
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001056/**
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001057 * @brief Decode a single primitive data item (decode layer 6).
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001058 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001059 * @param[in] pUInBuf Input buffer to read data item from.
1060 * @param[out] pDecodedItem The filled-in decoded item.
1061 * @param[in] pAllocator The allocator to use for strings or NULL.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001062 *
1063 * @retval QCBOR_ERR_UNSUPPORTED
1064 * @retval QCBOR_ERR_HIT_END
1065 * @retval QCBOR_ERR_INT_OVERFLOW
1066 * @retval QCBOR_ERR_STRING_ALLOCATE
1067 * @retval QCBOR_ERR_STRING_TOO_LONG
1068 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1069 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001070 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1071 *
1072 * This decodes the most primitive / atomic data item. It does
1073 * no combing of data items.
1074 */
1075static QCBORError
1076DecodeAtomicDataItem(UsefulInputBuf *pUInBuf,
1077 QCBORItem *pDecodedItem,
1078 const QCBORInternalAllocator *pAllocator)
1079{
1080 QCBORError uReturn;
1081
1082 /* Get the major type and the argument. The argument could be
1083 * length of more bytes or the value depending on the major
1084 * type. nAdditionalInfo is an encoding of the length of the
1085 * uNumber and is needed to decode floats and doubles.
1086 */
1087 int nMajorType = 0;
1088 uint64_t uArgument = 0;
1089 int nAdditionalInfo = 0;
1090
1091 memset(pDecodedItem, 0, sizeof(QCBORItem));
1092
1093 uReturn = DecodeHead(pUInBuf, &nMajorType, &uArgument, &nAdditionalInfo);
1094 if(uReturn) {
1095 goto Done;
1096 }
1097
1098 /* At this point the major type and the argument are valid. We've
1099 * got the type and the argument that starts every CBOR data item.
1100 */
1101 switch (nMajorType) {
1102 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1103 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
1104 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1105 uReturn = QCBOR_ERR_BAD_INT;
1106 } else {
1107 uReturn = DecodeInteger(nMajorType, uArgument, pDecodedItem);
1108 }
1109 break;
1110
1111 case CBOR_MAJOR_TYPE_BYTE_STRING: /* Major type 2 */
1112 case CBOR_MAJOR_TYPE_TEXT_STRING: /* Major type 3 */
1113 pDecodedItem->uDataType = ConvertStringMajorTypes(nMajorType);
1114 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1115 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
1116 } else {
1117 uReturn = DecodeBytes(pAllocator, uArgument, pUInBuf, pDecodedItem);
1118 }
1119 break;
1120
1121 case CBOR_MAJOR_TYPE_ARRAY: /* Major type 4 */
1122 case CBOR_MAJOR_TYPE_MAP: /* Major type 5 */
1123 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1124 /* Indefinite-length string. */
1125#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
1126 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
1127#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1128 uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
1129 break;
1130#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1131 } else {
1132 /* Definite-length string. */
1133 if(uArgument > QCBOR_MAX_ITEMS_IN_ARRAY) {
1134 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
1135 goto Done;
1136 }
1137 /* cast OK because of check above */
1138 pDecodedItem->val.uCount = (uint16_t)uArgument;
1139 }
1140 pDecodedItem->uDataType = ConvertArrayOrMapType(nMajorType);
1141 break;
1142
1143 case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */
1144 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1145 uReturn = QCBOR_ERR_BAD_INT;
1146 } else {
1147 pDecodedItem->val.uTagV = uArgument;
1148 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
1149 }
1150 break;
1151
1152 case CBOR_MAJOR_TYPE_SIMPLE:
1153 /* Major type 7: float, double, true, false, null... */
1154 uReturn = DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
1155 break;
1156
1157 default:
1158 /* Never happens because DecodeHead() should never return > 7 */
1159 uReturn = QCBOR_ERR_UNSUPPORTED;
1160 break;
1161 }
1162
1163Done:
1164 return uReturn;
1165}
1166
1167
1168/**
1169 * @brief Process indefinite-length strings (decode layer 5).
1170 *
1171 * @param[in] pMe Decoder context
1172 * @param[out] pDecodedItem The decoded item that work is done on.
1173 *
1174 * @retval QCBOR_ERR_UNSUPPORTED
1175 * @retval QCBOR_ERR_HIT_END
1176 * @retval QCBOR_ERR_INT_OVERFLOW
1177 * @retval QCBOR_ERR_STRING_ALLOCATE
1178 * @retval QCBOR_ERR_STRING_TOO_LONG
1179 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1180 * @retval QCBOR_ERR_BAD_TYPE_7
1181 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001182 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1183 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001184 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001185 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001186 * If @c pDecodedItem is not an indefinite-length string, this does nothing.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001187 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001188 * If it is, this loops getting the subsequent chunk data items that
1189 * make up the string. The string allocator is used to make a
1190 * contiguous buffer for the chunks. When this completes @c
1191 * pDecodedItem contains the put-together string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001192 *
1193 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001194 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001195static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001196QCBORDecode_GetNextFullString(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001197{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001198 /* Aproximate stack usage
1199 * 64-bit 32-bit
1200 * local vars 32 16
1201 * 2 UsefulBufs 32 16
1202 * QCBORItem 56 52
1203 * TOTAL 120 74
1204 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001205
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001206 /* The string allocator is used here for two purposes: 1)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001207 * coalescing the chunks of an indefinite-length string, 2)
1208 * allocating storage for every string returned when requested.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001209 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001210 * The first use is below in this function. Indefinite-length
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001211 * strings cannot be processed at all without a string allocator.
1212 *
1213 * The second used is in DecodeBytes() which is called by
1214 * GetNext_Item() below. This second use unneccessary for most use
1215 * and only happens when requested in the call to
1216 * QCBORDecode_SetMemPool(). If the second use not requested then
1217 * NULL is passed for the string allocator to GetNext_Item().
1218 *
1219 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1220 * allocator altogether and thus both of these uses. It reduced the
1221 * decoder object code by about 400 bytes.
1222 */
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001223 const QCBORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001224
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001225#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001226 const QCBORInternalAllocator *pAllocator = NULL;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001227
1228 if(pMe->StringAllocator.pfAllocator) {
1229 pAllocator = &(pMe->StringAllocator);
1230 if(pMe->bStringAllocateAll) {
1231 pAllocatorForGetNext = pAllocator;
1232 }
1233 }
1234#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1235
1236 QCBORError uReturn;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001237 uReturn = DecodeAtomicDataItem(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001238 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001239 goto Done;
1240 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001241
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001242 /* Only do indefinite-length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001243 const uint8_t uStringType = pDecodedItem->uDataType;
1244 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001245 goto Done;
1246 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001247
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001248 /* Is this a string with an indefinite length? */
1249 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1250 goto Done;
1251 }
1252
1253#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001254 /* Can't decode indefinite-length strings without a string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001255 if(pAllocator == NULL) {
1256 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1257 goto Done;
1258 }
1259
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001260 /* Loop getting chunks of the indefinite-length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001261 UsefulBufC FullString = NULLUsefulBufC;
1262
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001263 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001264 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001265 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001266 /* Pass a NULL string allocator to GetNext_Item() because the
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001267 * individual string chunks in an indefinite-length should not
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001268 * be allocated. They are always copied in the the contiguous
1269 * buffer allocated here.
1270 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001271 uReturn = DecodeAtomicDataItem(&(pMe->InBuf), &StringChunkItem, NULL);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001272 if(uReturn) {
1273 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001274 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001275
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001276 /* Is item is the marker for end of the indefinite-length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001277 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001278 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001279 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301280 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001281 break;
1282 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001283
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001284 /* All chunks must be of the same type, the type of the item
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001285 * that introduces the indefinite-length string. This also
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001286 * catches errors where the chunk is not a string at all and an
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001287 * indefinite-length string inside an indefinite-length string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001288 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001289 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001290 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1291 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001292 break;
1293 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001294
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001295 /* The first time throurgh FullString.ptr is NULL and this is
1296 * equivalent to StringAllocator_Allocate(). Subsequently it is
1297 * not NULL and a reallocation happens.
1298 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001299 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1300 UNCONST_POINTER(FullString.ptr),
1301 FullString.len + StringChunkItem.val.string.len);
1302
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001303 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001304 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001305 break;
1306 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001307
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001308 /* Copy new string chunk to the end of accumulated string */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001309 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001310 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001311
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001312 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1313 /* Getting the item failed, clean up the allocated memory */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001314 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001315 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001316#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1317 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1318#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001319
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001320Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001321 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001322}
1323
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001324
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001325/**
1326 * @brief This converts a tag number to a shorter mapped value for storage.
1327 *
1328 * @param[in] pMe The decode context.
1329 * @param[in] uUnMappedTag The tag number to map
1330 * @param[out] puMappedTagNumer The stored tag number.
1331 *
1332 * @return error code.
1333 *
1334 * The main point of mapping tag numbers is make QCBORItem
1335 * smaller. With this mapping storage of 4 tags takes up 8
1336 * bytes. Without, it would take up 32 bytes.
1337 *
1338 * This maps tag numbers greater than QCBOR_LAST_UNMAPPED_TAG.
1339 * QCBOR_LAST_UNMAPPED_TAG is a little smaller than MAX_UINT16.
1340 *
1341 * See also UnMapTagNumber() and @ref QCBORItem.
1342 */
1343static inline QCBORError
1344MapTagNumber(QCBORDecodeContext *pMe, uint64_t uUnMappedTag, uint16_t *puMappedTagNumer)
1345{
1346 if(uUnMappedTag > QCBOR_LAST_UNMAPPED_TAG) {
1347 unsigned uTagMapIndex;
1348 /* Is there room in the tag map, or is it in it already? */
1349 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
1350 if(pMe->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID64) {
1351 break;
1352 }
1353 if(pMe->auMappedTags[uTagMapIndex] == uUnMappedTag) {
1354 break;
1355 }
1356 }
1357 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1358 return QCBOR_ERR_TOO_MANY_TAGS;
1359 }
1360
1361 /* Covers the cases where tag is new and were it is already in the map */
1362 pMe->auMappedTags[uTagMapIndex] = uUnMappedTag;
1363 *puMappedTagNumer = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
1364
1365 } else {
1366 *puMappedTagNumer = (uint16_t)uUnMappedTag;
1367 }
1368
1369 return QCBOR_SUCCESS;
1370}
1371
1372
1373/**
1374 * @brief This converts a mapped tag number to the actual tag number.
1375 *
1376 * @param[in] pMe The decode context.
1377 * @param[in] uMappedTagNumber The stored tag number.
1378 *
1379 * @return The actual tag number is returned or
1380 * @ref CBOR_TAG_INVALID64 on error.
1381 *
1382 * This is the reverse of MapTagNumber()
1383 */
1384static uint64_t
1385UnMapTagNumber(const QCBORDecodeContext *pMe, uint16_t uMappedTagNumber)
1386{
1387 if(uMappedTagNumber <= QCBOR_LAST_UNMAPPED_TAG) {
1388 return uMappedTagNumber;
1389 } else if(uMappedTagNumber == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001390 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001391 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001392 /* This won't be negative because of code below in
1393 * MapTagNumber()
1394 */
1395 const unsigned uIndex = uMappedTagNumber - (QCBOR_LAST_UNMAPPED_TAG + 1);
1396 return pMe->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001397 }
1398}
1399
Laurence Lundblade9b334962020-08-27 10:55:53 -07001400
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001401/**
1402 * @brief Aggregate all tags wrapping a data item (decode layer 4).
1403 *
1404 * @param[in] pMe Decoder context
1405 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001406
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001407 * @retval QCBOR_ERR_UNSUPPORTED
1408 * @retval QCBOR_ERR_HIT_END
1409 * @retval QCBOR_ERR_INT_OVERFLOW
1410 * @retval QCBOR_ERR_STRING_ALLOCATE
1411 * @retval QCBOR_ERR_STRING_TOO_LONG
1412 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1413 * @retval QCBOR_ERR_BAD_TYPE_7
1414 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1415 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1416 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1417 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1418 * @retval QCBOR_ERR_TOO_MANY_TAGS
1419 *
1420 * This loops getting atomic data items until one is not a tag
1421 * number. Usually this is largely pass-through because most
1422 * item are not tag numbers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001423 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001424static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001425QCBORDecode_GetNextTagNumber(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001426{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001427 uint16_t auItemsTags[QCBOR_MAX_TAGS_PER_ITEM];
1428
1429 /* Initialize to CBOR_TAG_INVALID16 */
1430 #if CBOR_TAG_INVALID16 != 0xffff
1431 /* Be sure the memset does the right thing. */
1432 #err CBOR_TAG_INVALID16 tag not defined as expected
1433 #endif
1434 memset(auItemsTags, 0xff, sizeof(auItemsTags));
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001435
Laurence Lundblade9b334962020-08-27 10:55:53 -07001436 QCBORError uReturn = QCBOR_SUCCESS;
1437
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001438 /* Loop fetching data items until the item fetched is not a tag */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001439 for(;;) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001440 QCBORError uErr = QCBORDecode_GetNextFullString(pMe, pDecodedItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07001441 if(uErr != QCBOR_SUCCESS) {
1442 uReturn = uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001443 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001444 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001445
Laurence Lundblade9b334962020-08-27 10:55:53 -07001446 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001447 /* Successful exit from loop; maybe got some tags, maybe not */
1448 memcpy(pDecodedItem->uTags, auItemsTags, sizeof(auItemsTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001449 break;
1450 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001451
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001452 if(auItemsTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1453 /* No room in the tag list */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001454 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001455 /* Continue on to get all tags wrapping this item even though
1456 * it is erroring out in the end. This allows decoding to
1457 * continue. This is a resource limit error, not a problem
1458 * with being well-formed CBOR.
1459 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001460 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001461 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001462 /* Slide tags over one in the array to make room at index 0.
1463 * Must use memmove because the move source and destination
1464 * overlap.
1465 */
1466 memmove(&auItemsTags[1], auItemsTags, sizeof(auItemsTags) - sizeof(auItemsTags[0]));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001467
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001468 /* Map the tag */
1469 uint16_t uMappedTagNumer;
1470 uReturn = MapTagNumber(pMe, pDecodedItem->val.uTagV, &uMappedTagNumer);
1471 /* Continue even on error so as to consume all tags wrapping
1472 * this data item so decoding can go on. If MapTagNumber()
1473 * errors once it will continue to error.
1474 */
1475 auItemsTags[0] = uMappedTagNumer;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001476 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001477
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001478Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001479 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001480}
1481
1482
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001483/**
1484 * @brief Combine a map entry label and value into one item (decode layer 3).
1485 *
1486 * @param[in] pMe Decoder context
1487 * @param[out] pDecodedItem The decoded item that work is done on.
1488 *
1489 * @retval QCBOR_ERR_UNSUPPORTED
1490 * @retval QCBOR_ERR_HIT_END
1491 * @retval QCBOR_ERR_INT_OVERFLOW
1492 * @retval QCBOR_ERR_STRING_ALLOCATE
1493 * @retval QCBOR_ERR_STRING_TOO_LONG
1494 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1495 * @retval QCBOR_ERR_BAD_TYPE_7
1496 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1497 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1498 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1499 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1500 * @retval QCBOR_ERR_TOO_MANY_TAGS
1501 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1502 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1503 *
1504 * If a the current nesting level is a map, then this
1505 * combines pairs of items into one data item with a label
1506 * and value.
1507 *
1508 * This is pass-through if the current nesting leve is
1509 * not a map.
1510 *
1511 * This also implements maps-as-array mode where a map
1512 * is treated like an array to allow caller to do their
1513 * own label processing.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001514 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001515static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001516QCBORDecode_GetNextMapEntry(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001517{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001518 QCBORError uReturn = QCBORDecode_GetNextTagNumber(pMe, pDecodedItem);
1519 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001520 goto Done;
1521 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001522
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001523 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
1524 /* Break can't be a map entry */
1525 goto Done;
1526 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001527
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001528 if(pMe->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1529 /* Normal decoding of maps -- combine label and value into one item. */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001530
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001531 if(DecodeNesting_IsCurrentTypeMap(&(pMe->nesting))) {
1532 /* Save label in pDecodedItem and get the next which will
1533 * be the real data item.
1534 */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001535 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001536 uReturn = QCBORDecode_GetNextTagNumber(pMe, pDecodedItem);
1537 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001538 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001539 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001540
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301541 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001542
1543 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001544 /* strings are always good labels */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001545 pDecodedItem->label.string = LabelItem.val.string;
1546 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001547 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == pMe->uDecodeMode) {
1548 /* It's not a string and we only want strings */
1549 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001550 goto Done;
1551 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1552 pDecodedItem->label.int64 = LabelItem.val.int64;
1553 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1554 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1555 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1556 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1557 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1558 pDecodedItem->label.string = LabelItem.val.string;
1559 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1560 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1561 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001562 /* label is not an int or a string. It is an arrray
1563 * or a float or such and this implementation doesn't handle that.
1564 * Also, tags on labels are ignored.
1565 */
1566 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001567 goto Done;
1568 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001569 }
1570 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001571 /* Decoding of maps as arrays to let the caller decide what to do
1572 * about labels, particularly lables that are not integers or
1573 * strings.
1574 */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001575 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001576 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001577 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001578 goto Done;
1579 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001580 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001581 /* Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2.
1582 * Cast is needed because of integer promotion.
1583 */
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001584 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001585 }
1586 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001587
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001588Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001589 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001590}
1591
1592
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001593#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001594/**
1595 * @brief Peek and see if next data item is a break;
1596 *
1597 * @param[in] pUIB UsefulInputBuf to read from.
1598 * @param[out] pbNextIsBreak Indicate if next was a break or not.
1599 *
1600 * @return Any decoding error.
1601 *
1602 * See if next item is a CBOR break. If it is, it is consumed,
1603 * if not it is not consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001604*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001605static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001606NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1607{
1608 *pbNextIsBreak = false;
1609 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001610 QCBORItem Peek;
1611 size_t uPeek = UsefulInputBuf_Tell(pUIB);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001612 QCBORError uReturn = DecodeAtomicDataItem(pUIB, &Peek, NULL);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001613 if(uReturn != QCBOR_SUCCESS) {
1614 return uReturn;
1615 }
1616 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001617 /* It is not a break, rewind so it can be processed normally. */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001618 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001619 } else {
1620 *pbNextIsBreak = true;
1621 }
1622 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001623
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001624 return QCBOR_SUCCESS;
1625}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001626#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001627
1628
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001629/**
1630 * @brief Ascend up nesting levels if all items in them have been consumed.
1631 *
1632 * @param[in] pMe The decode context.
1633 * @param[in] bMarkEnd If true mark end of maps/arrays with count of zero.
1634 *
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001635 * An item was just consumed, now figure out if it was the
1636 * end of an array/map map that can be closed out. That
1637 * may in turn close out the above array/map...
Laurence Lundblade642282a2020-06-23 12:00:33 -07001638*/
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001639static QCBORError
1640QCBORDecode_NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001641{
1642 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001643
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001644 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001645 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1646
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001647 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1648 /* Nesting level is bstr-wrapped CBOR */
1649
1650 /* Ascent for bstr-wrapped CBOR is always by explicit call
1651 * so no further ascending can happen.
1652 */
1653 break;
1654
1655 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1656 /* Level is a definite-length array/map */
1657
1658 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001659 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1660 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001661 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001662 break;
1663 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001664 /* All items in a definite-length array were consumed so it
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001665 * is time to ascend one level. This happens below.
1666 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001667
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001668#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001669 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001670 /* Level is an indefinite-length array/map. */
1671
1672 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001673 bool bIsBreak = false;
1674 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1675 if(uReturn != QCBOR_SUCCESS) {
1676 goto Done;
1677 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001678
1679 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001680 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001681 break;
1682 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001683
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001684 /* It was a break in an indefinitelength map / array so
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001685 * it is time to ascend one level.
1686 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001687
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001688#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001689 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001690
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001691
1692 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001693
Laurence Lundblade93d89472020-10-03 22:30:50 -07001694 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001695 * QCBORDecode_ExitBoundedMode().
1696 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001697 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001698 /* Set the count to zero for definite-length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001699 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001700 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001701 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001702 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001703
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001704 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001705 break;
1706 }
1707
1708 /* Finally, actually ascend one level. */
1709 DecodeNesting_Ascend(&(pMe->nesting));
1710 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001711
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001712 uReturn = QCBOR_SUCCESS;
1713
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001714#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001715Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001716#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1717
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001718 return uReturn;
1719}
1720
1721
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001722/**
1723 * @brief Ascending & Descending out of nesting levels (decode layer 2).
1724 *
1725 * @param[in] pMe Decoder context
1726 * @param[out] pDecodedItem The decoded item that work is done on.
1727 *
1728 * @retval QCBOR_ERR_UNSUPPORTED
1729 * @retval QCBOR_ERR_HIT_END
1730 * @retval QCBOR_ERR_INT_OVERFLOW
1731 * @retval QCBOR_ERR_STRING_ALLOCATE
1732 * @retval QCBOR_ERR_STRING_TOO_LONG
1733 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1734 * @retval QCBOR_ERR_BAD_TYPE_7
1735 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1736 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1737 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1738 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1739 * @retval QCBOR_ERR_TOO_MANY_TAGS
1740 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1741 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1742 * @retval QCBOR_ERR_NO_MORE_ITEMS
1743 * @retval QCBOR_ERR_BAD_BREAK
1744 * @retval QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
1745 *
1746 * This handles the traversal descending into and asecnding out of
1747 * maps, arrays and bstr-wrapped CBOR. It figures out the ends of
1748 * definite- and indefinte-length maps and arrays by looking at the
1749 * item count or finding CBOR breaks. It detects the ends of the
1750 * top-level sequence and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001751 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001752static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001753QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001754{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001755 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001756 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001757
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001758 /* If out of bytes to consume, it is either the end of the
1759 * top-level sequence of some bstr-wrapped CBOR that was entered.
1760 *
1761 * In the case of bstr-wrapped CBOR, the length of the
1762 * UsefulInputBuf was set to that of the bstr-wrapped CBOR. When
1763 * the bstr-wrapped CBOR is exited, the length is set back to the
1764 * top-level's length or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001765 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001766 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001767 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001768 goto Done;
1769 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001770
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001771 /* Check to see if at the end of a bounded definite-length map or
1772 * array. The check for a break ending indefinite-length array is
1773 * later in QCBORDecode_NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001774 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001775 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001776 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001777 goto Done;
1778 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001779
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001780 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001781 uReturn = QCBORDecode_GetNextMapEntry(pMe, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001782 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1783 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001784 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001785 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301786
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001787 /* Breaks ending arrays/maps are processed later in the call to
1788 * QCBORDecode_NestLevelAscender(). They should never show up here.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001789 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301790 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001791 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301792 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301793 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001794
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001795 /* Record the nesting level for this data item before processing
1796 * any of decrementing and descending.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001797 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001798 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001799
Laurence Lundblade642282a2020-06-23 12:00:33 -07001800
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001801 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001802 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001803 /* If the new item is a map or array, descend.
1804 *
1805 * Empty indefinite-length maps and arrays are descended into,
1806 * but then ascended out of in the next chunk of code.
1807 *
1808 * Maps and arrays do count as items in the map/array that
1809 * encloses them so a decrement needs to be done for them too,
1810 * but that is done only when all the items in them have been
1811 * processed, not when they are opened with the exception of an
1812 * empty map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001813 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001814 QCBORError uDescendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001815 uDescendErr = DecodeNesting_DescendMapOrArray(&(pMe->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001816 pDecodedItem->uDataType,
1817 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001818 if(uDescendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001819 /* This error is probably a traversal error and it overrides
1820 * the non-traversal error.
1821 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001822 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001823 goto Done;
1824 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001825 }
1826
Laurence Lundblade02625d42020-06-25 14:41:41 -07001827 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1828 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1829 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001830 /* The following cases are handled here:
1831 * - A non-aggregate item like an integer or string
1832 * - An empty definite-length map or array
1833 * - An indefinite-length map or array that might be empty or might not.
1834 *
1835 * QCBORDecode_NestLevelAscender() does the work of decrementing the count
1836 * for an definite-length map/array and break detection for an
1837 * indefinite-0length map/array. If the end of the map/array was
1838 * reached, then it ascends nesting levels, possibly all the way
1839 * to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001840 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001841 QCBORError uAscendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001842 uAscendErr = QCBORDecode_NestLevelAscender(pMe, true);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001843 if(uAscendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001844 /* This error is probably a traversal error and it overrides
1845 * the non-traversal error.
1846 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001847 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001848 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001849 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301850 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001851
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001852 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001853 /* Tell the caller what level is next. This tells them what
1854 * maps/arrays were closed out and makes it possible for them to
1855 * reconstruct the tree with just the information returned in a
1856 * QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001857 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001858 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001859 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001860 pDecodedItem->uNextNestLevel = 0;
1861 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001862 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001863 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001864
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001865Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001866 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001867}
1868
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001869
1870/**
1871 * @brief Shift 0th tag out of the tag list.
1872 *
1873 * pDecodedItem[in,out] The data item to convert.
1874 *
1875 * The 0th tag is discarded. \ref CBOR_TAG_INVALID16 is
1876 * shifted into empty slot at the end of the tag list.
1877 */
1878static inline void ShiftTags(QCBORItem *pDecodedItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07001879{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001880 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM-1; i++) {
1881 pDecodedItem->uTags[i] = pDecodedItem->uTags[i+1];
1882 }
1883 pDecodedItem->uTags[QCBOR_MAX_TAGS_PER_ITEM-1] = CBOR_TAG_INVALID16;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001884}
1885
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001886
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001887/**
1888 * @brief Convert different epoch date formats in to the QCBOR epoch date format
1889 *
1890 * pDecodedItem[in,out] The data item to convert.
1891 *
1892 * @retval QCBOR_ERR_DATE_OVERFLOW
1893 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
1894 * @retval QCBOR_ERR_BAD_TAG_CONTENT
1895 *
1896 * The epoch date tag defined in QCBOR allows for floating-point
1897 * dates. It even allows a protocol to flop between date formats when
1898 * ever it wants. Floating-point dates aren't that useful as they are
1899 * only needed for dates beyond the age of the earth.
1900 *
1901 * This converts all the date formats into one format of an unsigned
1902 * integer plus a floating-point fraction.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001903 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001904static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001905{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001906 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001907
1908 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1909
1910 switch (pDecodedItem->uDataType) {
1911
1912 case QCBOR_TYPE_INT64:
1913 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1914 break;
1915
1916 case QCBOR_TYPE_UINT64:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001917 /* This only happens for CBOR type 0 > INT64_MAX so it is
1918 * always an overflow.
1919 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07001920 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1921 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001922 break;
1923
1924 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001925 case QCBOR_TYPE_FLOAT:
1926#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001927 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001928 /* Convert working value to double if input was a float */
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001929 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001930 pDecodedItem->val.dfnum :
1931 (double)pDecodedItem->val.fnum;
1932
1933 /* The conversion from float to integer requires overflow
1934 * detection since floats can be much larger than integers.
1935 * This implementation errors out on these large float values
1936 * since they are beyond the age of the earth.
1937 *
1938 * These constants for the overflow check are computed by the
1939 * compiler. They are not computed at run time.
1940 *
1941 * The factor of 0x7ff is added/subtracted to avoid a
1942 * rounding error in the wrong direction when the compiler
1943 * computes these constants. There is rounding because an
1944 * 64-bit integer has 63 bits of precision where a double
1945 * only has 53 bits. Without the 0x7ff factor, the compiler
1946 * may round up and produce a double for the bounds check
1947 * that is larger than can be stored in a 64-bit integer. The
1948 * amount of 0x7ff is picked because it has 11 bits set.
1949 *
1950 * Without the 0x7ff there is a ~30 minute range of time
1951 * values 10 billion years in the past and in the future
1952 * where this code could go wrong. Some compilers correctly
1953 * generate a warning or error without the 0x7ff.
1954 */
1955 const double dDateMax = (double)(INT64_MAX - 0x7ff);
1956 const double dDateMin = (double)(INT64_MIN + 0x7ff);
1957
1958 if(isnan(d) || d > dDateMax || d < dDateMin) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07001959 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001960 goto Done;
1961 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001962
1963 /* The actual conversion */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001964 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001965 pDecodedItem->val.epochDate.fSecondsFraction =
1966 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001967 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001968#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade4b270642020-08-14 12:53:07 -07001969
Laurence Lundbladec7114722020-08-13 05:11:40 -07001970 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001971 goto Done;
1972
Laurence Lundblade9682a532020-06-06 18:33:04 -07001973#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001974 break;
1975
1976 default:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001977 uReturn = QCBOR_ERR_BAD_TAG_CONTENT;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001978 goto Done;
1979 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001980
Laurence Lundblade59289e52019-12-30 13:44:37 -08001981 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1982
1983Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001984 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001985}
1986
1987
1988#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001989/**
1990 * @brief Decode decimal fractions and big floats.
1991 *
1992 * @param[in] pMe The decode context.
1993 * @param[in,out] pDecodedItem On input the array data item that
1994 * holds the mantissa and exponent. On
1995 * output the decoded mantissa and
1996 * exponent.
1997 *
1998 * @returns Decoding errors from getting primitive data items or
1999 * \ref QCBOR_ERR_BAD_EXP_AND_MANTISSA.
2000 *
2001 * When called pDecodedItem must be the array that is tagged as a big
2002 * float or decimal fraction, the array that has the two members, the
2003 * exponent and mantissa.
2004 *
2005 * This will fetch and decode the exponent and mantissa and put the
2006 * result back into pDecodedItem.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002007 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002008static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002009QCBORDecode_MantissaAndExponent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002010{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002011 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002012
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002013 /* --- Make sure it is an array; track nesting level of members --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002014 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002015 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002016 goto Done;
2017 }
2018
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002019 /* A check for pDecodedItem->val.uCount == 2 would work for
2020 * definite-length arrays, but not for indefnite. Instead remember
2021 * the nesting level the two integers must be at, which is one
2022 * deeper than that of the array.
2023 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002024 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
2025
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002026 /* --- Which is it, decimal fraction or a bigfloat? --- */
2027 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(pMe, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002028 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
2029
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002030 /* --- Get the exponent --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002031 QCBORItem exponentItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002032 uReturn = QCBORDecode_GetNextMapOrArray(pMe, &exponentItem);
2033 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002034 goto Done;
2035 }
2036 if(exponentItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002037 /* Array is empty or a map/array encountered when expecting an int */
2038 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002039 goto Done;
2040 }
2041 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002042 /* Data arriving as an unsigned int < INT64_MAX has been
2043 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2044 * also means that the only data arriving here of type
2045 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2046 * and thus an error that will get handled in the next else.
2047 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002048 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
2049 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002050 /* Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX */
2051 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002052 goto Done;
2053 }
2054
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002055 /* --- Get the mantissa --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002056 QCBORItem mantissaItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002057 uReturn = QCBORDecode_GetNextWithTags(pMe, &mantissaItem, NULL);
2058 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002059 goto Done;
2060 }
2061 if(mantissaItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002062 /* Mantissa missing or map/array encountered when expecting number */
2063 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002064 goto Done;
2065 }
2066 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002067 /* Data arriving as an unsigned int < INT64_MAX has been
2068 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2069 * also means that the only data arriving here of type
2070 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2071 * and thus an error that will get handled in an else below.
2072 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002073 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade93d89472020-10-03 22:30:50 -07002074 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
2075 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002076 /* Got a good big num mantissa */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002077 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002078 /* Depends on numbering of QCBOR_TYPE_XXX */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002079 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
2080 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
2081 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002082 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002083 /* Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX */
2084 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002085 goto Done;
2086 }
2087
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002088 /* --- Check that array only has the two numbers --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002089 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002090 /* Extra items in the decimal fraction / big float */
2091 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002092 goto Done;
2093 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002094 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002095
2096Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002097 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002098}
2099#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
2100
2101
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002102#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002103/**
2104 * @brief Decode the MIME type tag
2105 *
2106 * @param[in,out] pDecodedItem The item to decode.
2107 *
2108 * Handle the text and binary MIME type tags. Slightly too complicated
2109 * f or ProcessTaggedString() because the RFC 7049 MIME type was
2110 * incorreclty text-only.
2111 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002112static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002113{
2114 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
2115 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07002116 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002117 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
2118 } else {
2119 return QCBOR_ERR_BAD_OPT_TAG;
2120 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002121
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002122 return QCBOR_SUCCESS;
2123}
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002124#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002125
2126
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002127/**
Laurence Lundblade99615302020-11-29 11:19:47 -08002128 * Table of CBOR tags whose content is either a text string or a byte
2129 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
2130 * of uQCBORtype indicates the content should be a byte string rather
2131 * than a text string
2132 */
2133struct StringTagMapEntry {
2134 uint16_t uTagNumber;
2135 uint8_t uQCBORtype;
2136};
2137
2138#define IS_BYTE_STRING_BIT 0x80
2139#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
2140
2141static const struct StringTagMapEntry StringTagMap[] = {
2142 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
2143 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
2144 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
2145 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
2146 {CBOR_TAG_URI, QCBOR_TYPE_URI},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002147#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002148 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
2149 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
2150 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
2151 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002152#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade99615302020-11-29 11:19:47 -08002153 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
2154 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
2155};
2156
2157
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002158/**
2159 * @brief Process standard CBOR tags whose content is a string
2160 *
2161 * @param[in] uTag The tag.
2162 * @param[in,out] pDecodedItem The data item.
2163 *
2164 * @returns This returns QCBOR_SUCCESS if the tag was procssed,
2165 * \ref QCBOR_ERR_UNSUPPORTED if the tag was not processed and
2166 * \ref QCBOR_ERR_BAD_OPT_TAG if the content type was wrong for the tag.
2167 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002168 * Process the CBOR tags that whose content is a byte string or a text
2169 * string and for which the string is just passed on to the caller.
2170 *
2171 * This maps the CBOR tag to the QCBOR type and checks the content
2172 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08002173 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08002174 * possible.
Laurence Lundblade99615302020-11-29 11:19:47 -08002175 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002176static inline QCBORError
2177ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002178{
Laurence Lundblade99615302020-11-29 11:19:47 -08002179 /* This only works on tags that were not mapped; no need for other yet */
2180 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
2181 return QCBOR_ERR_UNSUPPORTED;
2182 }
2183
2184 unsigned uIndex;
2185 for(uIndex = 0; StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
2186 if(StringTagMap[uIndex].uTagNumber == uTag) {
2187 break;
2188 }
2189 }
2190
2191 const uint8_t uQCBORType = StringTagMap[uIndex].uQCBORtype;
2192 if(uQCBORType == QCBOR_TYPE_NONE) {
2193 /* repurpose this error to mean, not handled here */
2194 return QCBOR_ERR_UNSUPPORTED;
2195 }
2196
2197 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
2198 if(uQCBORType & IS_BYTE_STRING_BIT) {
2199 uExpectedType = QCBOR_TYPE_BYTE_STRING;
2200 }
2201
2202 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002203 return QCBOR_ERR_BAD_OPT_TAG;
2204 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002205
Laurence Lundblade99615302020-11-29 11:19:47 -08002206 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002207 return QCBOR_SUCCESS;
2208}
2209
2210
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002211/**
2212 * @brief Decode tag content for select tags (decoding layer 1).
2213 *
2214 * @param[in] pMe The decode context.
2215 * @param[out] pDecodedItem The decoded item.
2216 *
2217 * @return Decoding error code.
2218 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002219 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
2220 * but the whole tag was not decoded. Here, the whole tags (tag number
2221 * and tag content) that are supported by QCBOR are decoded. This is a
2222 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002223 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002224static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002225QCBORDecode_GetNextTagContent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002226{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002227 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002228
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002229 uReturn = QCBORDecode_GetNextMapOrArray(pMe, pDecodedItem);
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002230 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002231 goto Done;
2232 }
2233
Laurence Lundblade99615302020-11-29 11:19:47 -08002234 /* When there are no tag numbers for the item, this exits first
2235 * thing and effectively does nothing.
2236 *
2237 * This loops over all the tag numbers accumulated for this item
2238 * trying to decode and interpret them. This stops at the end of
2239 * the list or at the first tag number that can't be interpreted by
2240 * this code. This is effectively a recursive processing of the
2241 * tags number list that handles nested tags.
2242 */
2243 while(1) {
2244 /* Don't bother to unmap tags via QCBORITem.uTags since this
2245 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2246 */
2247 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002248
Laurence Lundblade99615302020-11-29 11:19:47 -08002249 if(uTagToProcess == CBOR_TAG_INVALID16) {
2250 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002251 break;
2252
Laurence Lundblade99615302020-11-29 11:19:47 -08002253 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002254 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002255
Laurence Lundblade93d89472020-10-03 22:30:50 -07002256#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002257 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2258 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002259 uReturn = QCBORDecode_MantissaAndExponent(pMe, pDecodedItem);
Laurence Lundblade93d89472020-10-03 22:30:50 -07002260#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002261#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002262 } else if(uTagToProcess == CBOR_TAG_MIME ||
2263 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002264 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002265#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002266
Laurence Lundblade99615302020-11-29 11:19:47 -08002267 } else {
2268 /* See if it is a pass-through byte/text string tag; process if so */
2269 uReturn = ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002270
Laurence Lundblade99615302020-11-29 11:19:47 -08002271 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
2272 /* It wasn't a pass-through byte/text string tag so it is
2273 * an unknown tag. This is the exit from the loop on the
2274 * first unknown tag. It is a successful exit.
2275 */
2276 uReturn = QCBOR_SUCCESS;
2277 break;
2278 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002279 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002280
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002281 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002282 /* Error exit from the loop */
2283 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002284 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002285
2286 /* A tag was successfully processed, shift it out of the list of
2287 * tags returned. This is the loop increment.
2288 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002289 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002290 }
2291
2292Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002293 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002294}
2295
2296
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002297/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002298 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002299 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002300QCBORError
2301QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2302{
2303 QCBORError uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002304 uErr = QCBORDecode_GetNextTagContent(pMe, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002305 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002306 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2307 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2308 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002309 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002310}
2311
2312
2313/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002314 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002315 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002316QCBORError
2317QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2318{
2319 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2320 const UsefulInputBuf Save = pMe->InBuf;
2321
2322 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2323
2324 pMe->nesting = SaveNesting;
2325 pMe->InBuf = Save;
2326
2327 return uErr;
2328}
2329
2330
2331/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002332 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002333 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002334void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2335{
2336 if(pMe->uLastError != QCBOR_SUCCESS) {
2337 return;
2338 }
2339
2340 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2341}
2342
2343
2344/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002345 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002346 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002347QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002348QCBORDecode_GetNextWithTags(QCBORDecodeContext *pMe,
2349 QCBORItem *pDecodedItem,
2350 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002351{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002352 QCBORError uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002353
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002354 uReturn = QCBORDecode_GetNext(pMe, pDecodedItem);
2355 if(uReturn != QCBOR_SUCCESS) {
2356 return uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002357 }
2358
2359 if(pTags != NULL) {
2360 pTags->uNumUsed = 0;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002361 /* Reverse the order because pTags is reverse of QCBORItem.uTags. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002362 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2363 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002364 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002365 }
2366 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2367 return QCBOR_ERR_TOO_MANY_TAGS;
2368 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002369 pTags->puTags[pTags->uNumUsed] = UnMapTagNumber(pMe,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002370 pTags->uNumUsed++;
2371 }
2372 }
2373
2374 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002375}
2376
2377
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002378/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002379 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302380 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002381bool QCBORDecode_IsTagged(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002382 const QCBORItem *pItem,
2383 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002384{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002385 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2386 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002387 break;
2388 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002389 if(UnMapTagNumber(pMe, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002390 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002391 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002392 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002393
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002394 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002395}
2396
2397
2398/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002399 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002400 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002401QCBORError QCBORDecode_Finish(QCBORDecodeContext *pMe)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002402{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002403 QCBORError uReturn = pMe->uLastError;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002404
2405 if(uReturn != QCBOR_SUCCESS) {
2406 goto Done;
2407 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002408
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002409 /* Error out if all the maps/arrays are not closed out */
2410 if(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002411 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002412 goto Done;
2413 }
2414
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002415 /* Error out if not all the bytes are consumed */
2416 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002417 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002418 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002419
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002420Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002421#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002422 /* Call the destructor for the string allocator if there is one.
2423 * Always called, even if there are errors; always have to clean up.
2424 */
2425 StringAllocator_Destruct(&(pMe->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002426#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002427
Laurence Lundblade085d7952020-07-24 10:26:30 -07002428 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002429}
2430
2431
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002432/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002433 * Public function, see header qcbor/qcbor_decode.h file
2434 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002435// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002436uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2437 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002438 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002439{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002440 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2441 return CBOR_TAG_INVALID64;
2442 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002443 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2444 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002445 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002446 return UnMapTagNumber(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002447 }
2448}
2449
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002450
Laurence Lundblade9b334962020-08-27 10:55:53 -07002451/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002452 * Public function, see header qcbor/qcbor_decode.h file
2453 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002454uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2455 uint32_t uIndex)
2456{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002457 if(pMe->uLastError != QCBOR_SUCCESS) {
2458 return CBOR_TAG_INVALID64;
2459 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002460 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2461 return CBOR_TAG_INVALID64;
2462 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002463 return UnMapTagNumber(pMe, pMe->uLastTags[uIndex]);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002464 }
2465}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002466
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002467
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002468
2469
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002470#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002471
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002472/* ===========================================================================
2473 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002474
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002475 This implements a simple sting allocator for indefinite-length
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002476 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2477 implements the function type QCBORStringAllocate and allows easy
2478 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002479
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002480 This particular allocator is built-in for convenience. The caller
2481 can implement their own. All of this following code will get
2482 dead-stripped if QCBORDecode_SetMemPool() is not called.
2483
2484 This is a very primitive memory allocator. It does not track
2485 individual allocations, only a high-water mark. A free or
2486 reallocation must be of the last chunk allocated.
2487
2488 The size of the pool and offset to free memory are packed into the
2489 first 8 bytes of the memory pool so we don't have to keep them in
2490 the decode context. Since the address of the pool may not be
2491 aligned, they have to be packed and unpacked as if they were
2492 serialized data of the wire or such.
2493
2494 The sizes packed in are uint32_t to be the same on all CPU types
2495 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002496 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002497
2498
Laurence Lundbladeee851742020-01-08 08:37:05 -08002499static inline int
2500MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002501{
2502 // Use of UsefulInputBuf is overkill, but it is convenient.
2503 UsefulInputBuf UIB;
2504
Laurence Lundbladeee851742020-01-08 08:37:05 -08002505 // Just assume the size here. It was checked during SetUp so
2506 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002507 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002508 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2509 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2510 return UsefulInputBuf_GetError(&UIB);
2511}
2512
2513
Laurence Lundbladeee851742020-01-08 08:37:05 -08002514static inline int
2515MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002516{
2517 // Use of UsefulOutBuf is overkill, but convenient. The
2518 // length check performed here is useful.
2519 UsefulOutBuf UOB;
2520
2521 UsefulOutBuf_Init(&UOB, Pool);
2522 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2523 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2524 return UsefulOutBuf_GetError(&UOB);
2525}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002526
2527
2528/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002529 Internal function for an allocation, reallocation free and destuct.
2530
2531 Having only one function rather than one each per mode saves space in
2532 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002533
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002534 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2535 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002536static UsefulBuf
2537MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002538{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002539 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002540
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002541 uint32_t uPoolSize;
2542 uint32_t uFreeOffset;
2543
2544 if(uNewSize > UINT32_MAX) {
2545 // This allocator is only good up to 4GB. This check should
2546 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2547 goto Done;
2548 }
2549 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2550
2551 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2552 goto Done;
2553 }
2554
2555 if(uNewSize) {
2556 if(pMem) {
2557 // REALLOCATION MODE
2558 // Calculate pointer to the end of the memory pool. It is
2559 // assumed that pPool + uPoolSize won't wrap around by
2560 // assuming the caller won't pass a pool buffer in that is
2561 // not in legitimate memory space.
2562 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2563
2564 // Check that the pointer for reallocation is in the range of the
2565 // pool. This also makes sure that pointer math further down
2566 // doesn't wrap under or over.
2567 if(pMem >= pPool && pMem < pPoolEnd) {
2568 // Offset to start of chunk for reallocation. This won't
2569 // wrap under because of check that pMem >= pPool. Cast
2570 // is safe because the pool is always less than UINT32_MAX
2571 // because of check in QCBORDecode_SetMemPool().
2572 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2573
2574 // Check to see if the allocation will fit. uPoolSize -
2575 // uMemOffset will not wrap under because of check that
2576 // pMem is in the range of the uPoolSize by check above.
2577 if(uNewSize <= uPoolSize - uMemOffset) {
2578 ReturnValue.ptr = pMem;
2579 ReturnValue.len = uNewSize;
2580
2581 // Addition won't wrap around over because uNewSize was
2582 // checked to be sure it is less than the pool size.
2583 uFreeOffset = uMemOffset + uNewSize32;
2584 }
2585 }
2586 } else {
2587 // ALLOCATION MODE
2588 // uPoolSize - uFreeOffset will not underflow because this
2589 // pool implementation makes sure uFreeOffset is always
2590 // smaller than uPoolSize through this check here and
2591 // reallocation case.
2592 if(uNewSize <= uPoolSize - uFreeOffset) {
2593 ReturnValue.len = uNewSize;
2594 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002595 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002596 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002597 }
2598 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002599 if(pMem) {
2600 // FREE MODE
2601 // Cast is safe because of limit on pool size in
2602 // QCBORDecode_SetMemPool()
2603 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2604 } else {
2605 // DESTRUCT MODE
2606 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002607 }
2608 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002609
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002610 UsefulBuf Pool = {pPool, uPoolSize};
2611 MemPool_Pack(Pool, uFreeOffset);
2612
2613Done:
2614 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002615}
2616
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002617
Laurence Lundbladef6531662018-12-04 10:42:22 +09002618/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002619 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002620 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002621QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2622 UsefulBuf Pool,
2623 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002624{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002625 // The pool size and free mem offset are packed into the beginning
2626 // of the pool memory. This compile time check make sure the
2627 // constant in the header is correct. This check should optimize
2628 // down to nothing.
2629 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002630 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002631 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002632
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002633 // The pool size and free offset packed in to the beginning of pool
2634 // memory are only 32-bits. This check will optimize out on 32-bit
2635 // machines.
2636 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002637 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002638 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002639
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002640 // This checks that the pool buffer given is big enough.
2641 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002642 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002643 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002644
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002645 pMe->StringAllocator.pfAllocator = MemPool_Function;
2646 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2647 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002648
Laurence Lundblade30816f22018-11-10 13:40:22 +07002649 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002650}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002651#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002652
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002653
2654
Laurence Lundblade9b334962020-08-27 10:55:53 -07002655static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2656{
2657 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2658}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002659
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002660
2661/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002662 Consume an entire map or array (and do next to
2663 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002664 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002665static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002666ConsumeItem(QCBORDecodeContext *pMe,
2667 const QCBORItem *pItemToConsume,
2668 uint_fast8_t *puNextNestLevel)
2669{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002670 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002671 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002672
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002673 // If it is a map or array, this will tell if it is empty.
2674 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2675
2676 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2677 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002678
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002679 /* This works for definite- and indefinite- length
Laurence Lundblade1341c592020-04-11 14:19:05 -07002680 * maps and arrays by using the nesting level
2681 */
2682 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002683 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002684 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002685 goto Done;
2686 }
2687 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002688
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002689 *puNextNestLevel = Item.uNextNestLevel;
2690
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002691 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002692
Laurence Lundblade1341c592020-04-11 14:19:05 -07002693 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002694 /* item_to_consume is not a map or array */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002695 /* Just pass the nesting level through */
2696 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2697
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002698 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002699 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002700
2701Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002702 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002703}
2704
2705
Laurence Lundblade1341c592020-04-11 14:19:05 -07002706/* Return true if the labels in Item1 and Item2 are the same.
2707 Works only for integer and string labels. Returns false
2708 for any other type. */
2709static inline bool
2710MatchLabel(QCBORItem Item1, QCBORItem Item2)
2711{
2712 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2713 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2714 return true;
2715 }
2716 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002717 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002718 return true;
2719 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002720 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002721 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2722 return true;
2723 }
2724 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2725 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2726 return true;
2727 }
2728 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002729
Laurence Lundblade1341c592020-04-11 14:19:05 -07002730 /* Other label types are never matched */
2731 return false;
2732}
2733
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002734
2735/*
2736 Returns true if Item1 and Item2 are the same type
2737 or if either are of QCBOR_TYPE_ANY.
2738 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002739static inline bool
2740MatchType(QCBORItem Item1, QCBORItem Item2)
2741{
2742 if(Item1.uDataType == Item2.uDataType) {
2743 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002744 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002745 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002746 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002747 return true;
2748 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002749 return false;
2750}
2751
2752
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002753/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002754 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002755
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002756 @param[in] pMe The decode context to search.
2757 @param[in,out] pItemArray The items to search for and the items found.
2758 @param[out] puOffset Byte offset of last item matched.
2759 @param[in] pCBContext Context for the not-found item call back.
2760 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002761
2762 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2763
Laurence Lundblade93d89472020-10-03 22:30:50 -07002764 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2765 were found for one of the labels being
2766 search for. This duplicate detection is
2767 only performed for items in pItemArray,
2768 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002769
Laurence Lundblade93d89472020-10-03 22:30:50 -07002770 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2771 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002772
2773 @retval Also errors returned by QCBORDecode_GetNext().
2774
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002775 On input pItemArray contains a list of labels and data types
2776 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002777
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002778 On output the fully retrieved items are filled in with
2779 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002780
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002781 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002782
2783 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002784 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002785static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002786MapSearch(QCBORDecodeContext *pMe,
2787 QCBORItem *pItemArray,
2788 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002789 void *pCBContext,
2790 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002791{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002792 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002793 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002794
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002795 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002796 uReturn = pMe->uLastError;
2797 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002798 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002799
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002800 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002801 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2802 /* QCBOR_TYPE_NONE as first item indicates just looking
2803 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002804 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2805 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002806 }
2807
Laurence Lundblade085d7952020-07-24 10:26:30 -07002808 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2809 // It is an empty bounded array or map
2810 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2811 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002812 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002813 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002814 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002815 // Nothing is ever found in an empty array or map. All items
2816 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002817 uReturn = QCBOR_SUCCESS;
2818 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002819 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002820 }
2821
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002822 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002823 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2824
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002825 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002826 UsefulInputBuf_Seek(&(pMe->InBuf),
2827 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002828
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002829 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002830 Loop over all the items in the map or array. Each item
2831 could be a map or array, but label matching is only at
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002832 the main level. This handles definite- and indefinite-
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002833 length maps and arrays. The only reason this is ever
2834 called on arrays is to find their end position.
2835
2836 This will always run over all items in order to do
2837 duplicate detection.
2838
2839 This will exit with failure if it encounters an
2840 unrecoverable error, but continue on for recoverable
2841 errors.
2842
2843 If a recoverable error occurs on a matched item, then
2844 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002845 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002846 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002847 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002848 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002849 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002850 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002851
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002852 /* Get the item */
2853 QCBORItem Item;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002854 QCBORError uResult = QCBORDecode_GetNextTagContent(pMe, &Item);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002855 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002856 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002857 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002858 goto Done;
2859 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002860 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002861 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002862 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002863 goto Done;
2864 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002865
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002866 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002867 bool bMatched = false;
2868 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2869 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002870 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002871 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2872 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002873 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002874 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002875 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002876 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002877 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002878 goto Done;
2879 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002880
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002881 if(uResult != QCBOR_SUCCESS) {
2882 uReturn = uResult;
2883 goto Done;
2884 }
2885
Laurence Lundblade1341c592020-04-11 14:19:05 -07002886 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002887 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002888 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002889 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002890 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002891 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002892 bMatched = true;
2893 }
2894 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002895
2896
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002897 if(!bMatched && pfCallback != NULL) {
2898 /*
2899 Call the callback on unmatched labels.
2900 (It is tempting to do duplicate detection here, but that would
2901 require dynamic memory allocation because the number of labels
2902 that might be encountered is unbounded.)
2903 */
2904 uReturn = (*pfCallback)(pCBContext, &Item);
2905 if(uReturn != QCBOR_SUCCESS) {
2906 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002907 }
2908 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002909
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002910 /*
2911 Consume the item whether matched or not. This
2912 does the work of traversing maps and array and
2913 everything in them. In this loop only the
2914 items at the current nesting level are examined
2915 to match the labels.
2916 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002917 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002918 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002919 goto Done;
2920 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002921
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002922 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002923
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002924 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002925
2926 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002927
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002928 // Check here makes sure that this won't accidentally be
2929 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002930 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08002931 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
2932 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002933 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
2934 goto Done;
2935 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002936 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2937 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002938
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002939 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002940 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2941
2942 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002943 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002944 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002945 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002946 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
2947 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002948 }
2949 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002950
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002951 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002952}
2953
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002954
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002955/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002956 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002957*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002958void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2959 int64_t nLabel,
2960 uint8_t uQcborType,
2961 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002962{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002963 if(pMe->uLastError != QCBOR_SUCCESS) {
2964 return;
2965 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002966
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002967 QCBORItem OneItemSeach[2];
2968 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2969 OneItemSeach[0].label.int64 = nLabel;
2970 OneItemSeach[0].uDataType = uQcborType;
2971 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002972
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002973 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002974
2975 *pItem = OneItemSeach[0];
2976
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002977 if(uReturn != QCBOR_SUCCESS) {
2978 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002979 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002980 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002981 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002982 }
2983
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002984 Done:
2985 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002986}
2987
2988
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002989/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002990 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002991*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002992void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2993 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002994 uint8_t uQcborType,
2995 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002996{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002997 if(pMe->uLastError != QCBOR_SUCCESS) {
2998 return;
2999 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003000
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003001 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003002 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3003 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3004 OneItemSeach[0].uDataType = uQcborType;
3005 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003006
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003007 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
3008 if(uReturn != QCBOR_SUCCESS) {
3009 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003010 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003011 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003012 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003013 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003014 }
3015
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003016 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003017
3018Done:
3019 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003020}
3021
3022
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003023
Laurence Lundblade93d89472020-10-03 22:30:50 -07003024static QCBORError
3025CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003026{
3027 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
3028 if(uDataType == puTypeList[i]) {
3029 return QCBOR_SUCCESS;
3030 }
3031 }
3032 return QCBOR_ERR_UNEXPECTED_TYPE;
3033}
3034
Laurence Lundblade67257dc2020-07-27 03:33:37 -07003035
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003036/**
3037 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003038 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07003039
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003040 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
3041 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07003042
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003043 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered
3044 tag value.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003045 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07003046static QCBORError
3047CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07003048{
3049 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
3050 pItem->uTags[0] != CBOR_TAG_INVALID16) {
3051 /* There are tags that QCBOR couldn't process on this item and
3052 the caller has told us there should not be. */
3053 return QCBOR_ERR_UNEXPECTED_TYPE;
3054 }
3055
3056 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
3057 const int nItemType = pItem->uDataType;
3058
3059 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
3060 // Must match the tag and only the tag
3061 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3062 }
3063
3064 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
3065 if(uReturn == QCBOR_SUCCESS) {
3066 return QCBOR_SUCCESS;
3067 }
3068
3069 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
3070 /* Must match the content type and only the content type.
3071 There was no match just above so it is a fail. */
3072 return QCBOR_ERR_UNEXPECTED_TYPE;
3073 }
3074
3075 /* If here it can match either the tag or the content
3076 and it hasn't matched the content, so the end
3077 result is whether it matches the tag. This is
3078 also the case that the CBOR standard discourages. */
3079
3080 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3081}
3082
Laurence Lundblade9b334962020-08-27 10:55:53 -07003083
Laurence Lundblade9b334962020-08-27 10:55:53 -07003084
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003085// This could be semi-private if need be
3086static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003087void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
3088 int64_t nLabel,
3089 TagSpecification TagSpec,
3090 QCBORItem *pItem)
3091{
3092 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
3093 if(pMe->uLastError != QCBOR_SUCCESS) {
3094 return;
3095 }
3096
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003097 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003098}
3099
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003100
3101// This could be semi-private if need be
3102static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003103void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
3104 const char *szLabel,
3105 TagSpecification TagSpec,
3106 QCBORItem *pItem)
3107{
3108 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
3109 if(pMe->uLastError != QCBOR_SUCCESS) {
3110 return;
3111 }
3112
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003113 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003114}
3115
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003116// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003117void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
3118 int64_t nLabel,
3119 TagSpecification TagSpec,
3120 UsefulBufC *pString)
3121{
3122 QCBORItem Item;
3123 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
3124 if(pMe->uLastError == QCBOR_SUCCESS) {
3125 *pString = Item.val.string;
3126 }
3127}
3128
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003129// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003130void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
3131 const char * szLabel,
3132 TagSpecification TagSpec,
3133 UsefulBufC *pString)
3134{
3135 QCBORItem Item;
3136 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
3137 if(pMe->uLastError == QCBOR_SUCCESS) {
3138 *pString = Item.val.string;
3139 }
3140}
Laurence Lundblade1341c592020-04-11 14:19:05 -07003141
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003142/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003143 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003144*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003145void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003146{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003147 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
3148 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003149}
3150
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003151/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003152 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003153*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003154void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3155 QCBORItem *pItemList,
3156 void *pCallbackCtx,
3157 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003158{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003159 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
3160 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003161}
3162
3163
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003164/**
3165 * @brief Search for a map/array by label and enter it
3166 *
3167 * @param[in] pMe The decode context.
3168 * @param[in] pSearch The map/array to search for.
3169 *
3170 * @c pSearch is expected to contain one item of type map or array
3171 * with the label specified. The current bounded map will be searched for
3172 * this and if found will be entered.
3173 *
3174 * If the label is not found, or the item found is not a map or array,
3175 * the error state is set.
3176 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003177static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003178{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003179 // The first item in pSearch is the one that is to be
3180 // entered. It should be the only one filled in. Any other
3181 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003182 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003183 return;
3184 }
3185
3186 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003187 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003188 if(pMe->uLastError != QCBOR_SUCCESS) {
3189 return;
3190 }
3191
Laurence Lundblade9b334962020-08-27 10:55:53 -07003192 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003193 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003194 return;
3195 }
3196
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003197 /*
3198 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3199 * next item for the pre-order traversal cursor to be the map/array
3200 * found by MapSearch(). The next few lines of code force the
3201 * cursor to that.
3202 *
3203 * There is no need to retain the old cursor because
3204 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3205 * beginning of the map/array being entered.
3206 *
3207 * The cursor is forced by: 1) setting the input buffer position to
3208 * the item offset found by MapSearch(), 2) setting the map/array
3209 * counter to the total in the map/array, 3) setting the nesting
3210 * level. Setting the map/array counter to the total is not
3211 * strictly correct, but this is OK because this cursor only needs
3212 * to be used to get one item and MapSearch() has already found it
3213 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003214 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003215 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003216
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003217 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3218
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003219 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003220
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003221 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003222}
3223
3224
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003225/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003226 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003227*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003228void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003229{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003230 QCBORItem OneItemSeach[2];
3231 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3232 OneItemSeach[0].label.int64 = nLabel;
3233 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3234 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003235
Laurence Lundblade9b334962020-08-27 10:55:53 -07003236 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003237 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003238}
3239
3240
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003241/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003242 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003243*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003244void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003245{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003246 QCBORItem OneItemSeach[2];
3247 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3248 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3249 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3250 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003251
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003252 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003253}
3254
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003255/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003256 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003257*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003258void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003259{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003260 QCBORItem OneItemSeach[2];
3261 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3262 OneItemSeach[0].label.int64 = nLabel;
3263 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3264 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003265
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003266 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003267}
3268
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003269/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003270 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003271*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003272void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3273{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003274 QCBORItem OneItemSeach[2];
3275 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3276 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3277 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3278 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003279
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003280 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003281}
3282
3283
Laurence Lundblade02625d42020-06-25 14:41:41 -07003284// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003285void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003286{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003287 QCBORError uErr;
3288
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003289 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003290 if(pMe->uLastError != QCBOR_SUCCESS) {
3291 // Already in error state; do nothing.
3292 return;
3293 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003294
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003295 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003296 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003297 uErr = QCBORDecode_GetNext(pMe, &Item);
3298 if(uErr != QCBOR_SUCCESS) {
3299 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003300 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003301 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003302 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3303 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003304 }
3305
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003306 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003307
3308
Laurence Lundbladef0499502020-08-01 11:55:57 -07003309 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003310 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003311 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3312 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003313 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003314 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3315 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003316 // Special case to increment nesting level for zero-length maps
3317 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003318 DecodeNesting_Descend(&(pMe->nesting), uType);
3319 }
3320
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003321 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003322
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003323 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3324 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003325
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003326 if(pItem != NULL) {
3327 *pItem = Item;
3328 }
3329
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003330Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003331 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003332}
3333
Laurence Lundblade02625d42020-06-25 14:41:41 -07003334
3335/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003336 This is the common work for exiting a level that is a bounded map,
3337 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003338
3339 One chunk of work is to set up the pre-order traversal so it is at
3340 the item just after the bounded map, array or bstr that is being
3341 exited. This is somewhat complex.
3342
3343 The other work is to level-up the bounded mode to next higest bounded
3344 mode or the top level if there isn't one.
3345 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003346static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003347ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003348{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003349 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003350
Laurence Lundblade02625d42020-06-25 14:41:41 -07003351 /*
3352 First the pre-order-traversal byte offset is positioned to the
3353 item just after the bounded mode item that was just consumed.
3354 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003355 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3356
Laurence Lundblade02625d42020-06-25 14:41:41 -07003357 /*
3358 Next, set the current nesting level to one above the bounded level
3359 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003360
Laurence Lundblade02625d42020-06-25 14:41:41 -07003361 DecodeNesting_CheckBoundedType() is always called before this and
3362 makes sure pCurrentBounded is valid.
3363 */
3364 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3365
3366 /*
3367 This does the complex work of leveling up the pre-order traversal
3368 when the end of a map or array or another bounded level is
3369 reached. It may do nothing, or ascend all the way to the top
3370 level.
3371 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003372 uErr = QCBORDecode_NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003373 if(uErr != QCBOR_SUCCESS) {
3374 goto Done;
3375 }
3376
Laurence Lundblade02625d42020-06-25 14:41:41 -07003377 /*
3378 This makes the next highest bounded level the current bounded
3379 level. If there is no next highest level, then no bounded mode is
3380 in effect.
3381 */
3382 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003383
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003384 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003385
3386Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003387 return uErr;
3388}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003389
Laurence Lundblade02625d42020-06-25 14:41:41 -07003390
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003391// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003392void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003393{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003394 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003395 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003396 return;
3397 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003398
Laurence Lundblade02625d42020-06-25 14:41:41 -07003399 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003400
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003401 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003402 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003403 goto Done;
3404 }
3405
Laurence Lundblade02625d42020-06-25 14:41:41 -07003406 /*
3407 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003408 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003409 from previous map search, then do a dummy search.
3410 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003411 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003412 QCBORItem Dummy;
3413 Dummy.uLabelType = QCBOR_TYPE_NONE;
3414 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3415 if(uErr != QCBOR_SUCCESS) {
3416 goto Done;
3417 }
3418 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003419
Laurence Lundblade02625d42020-06-25 14:41:41 -07003420 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003421
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003422Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003423 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003424}
3425
3426
Laurence Lundblade1341c592020-04-11 14:19:05 -07003427
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003428static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003429 const QCBORItem *pItem,
3430 uint8_t uTagRequirement,
3431 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003432{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003433 if(pBstr) {
3434 *pBstr = NULLUsefulBufC;
3435 }
3436
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003437 if(pMe->uLastError != QCBOR_SUCCESS) {
3438 // Already in error state; do nothing.
3439 return pMe->uLastError;
3440 }
3441
3442 QCBORError uError = QCBOR_SUCCESS;
3443
3444 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3445 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3446 goto Done;;
3447 }
3448
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003449 const TagSpecification TagSpec =
3450 {
3451 uTagRequirement,
3452 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3453 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3454 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003455
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003456 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003457 if(uError != QCBOR_SUCCESS) {
3458 goto Done;
3459 }
3460
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003461 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003462 // Reverse the decrement done by GetNext() for the bstr so the
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003463 // increment in QCBORDecode_NestLevelAscender() called by ExitBoundedLevel()
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003464 // will work right.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003465 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003466 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003467
3468 if(pBstr) {
3469 *pBstr = pItem->val.string;
3470 }
3471
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003472 // This saves the current length of the UsefulInputBuf and then
3473 // narrows the UsefulInputBuf to start and length of the wrapped
3474 // CBOR that is being entered.
3475 //
3476 // This makes sure the length is less than
3477 // QCBOR_MAX_DECODE_INPUT_SIZE which is slighly less than
3478 // UINT32_MAX. The value UINT32_MAX is used as a special indicator
3479 // value. The checks against QCBOR_MAX_DECODE_INPUT_SIZE also make
3480 // the casts safe. uEndOfBstr will always be less than
3481 // uPreviousLength because of the way UsefulInputBuf works so there
3482 // is no need to check it. There is also a range check in the
3483 // seek.
3484 //
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003485 // Most of these calls are simple inline accessors so this doesn't
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003486 // amount to much code.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003487 // Cast of uPreviousLength to uint32_t for cases where SIZE_MAX < UINT32_MAX.
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003488 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003489 if((uint32_t)uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003490 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003491 goto Done;
3492 }
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003493 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003494 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003495 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003496
Laurence Lundblade02625d42020-06-25 14:41:41 -07003497 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003498 (uint32_t)uPreviousLength,
3499 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003500Done:
3501 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003502}
3503
3504
Laurence Lundblade02625d42020-06-25 14:41:41 -07003505/*
3506 Public function, see header qcbor/qcbor_decode.h file
3507 */
3508void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003509 uint8_t uTagRequirement,
3510 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003511{
3512 if(pMe->uLastError != QCBOR_SUCCESS) {
3513 // Already in error state; do nothing.
3514 return;
3515 }
3516
3517 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003518 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003519 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3520 if(pMe->uLastError != QCBOR_SUCCESS) {
3521 return;
3522 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003523
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003524 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003525 &Item,
3526 uTagRequirement,
3527 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003528}
3529
3530
Laurence Lundblade02625d42020-06-25 14:41:41 -07003531/*
3532 Public function, see header qcbor/qcbor_decode.h file
3533 */
3534void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003535 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003536 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003537 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003538{
3539 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003540 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003541
Laurence Lundblade93d89472020-10-03 22:30:50 -07003542 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3543 &Item,
3544 uTagRequirement,
3545 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003546}
3547
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003548
Laurence Lundblade02625d42020-06-25 14:41:41 -07003549/*
3550 Public function, see header qcbor/qcbor_decode.h file
3551 */
3552void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003553 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003554 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003555 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003556{
3557 QCBORItem Item;
3558 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3559
Laurence Lundblade93d89472020-10-03 22:30:50 -07003560 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3561 &Item,
3562 uTagRequirement,
3563 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003564}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003565
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003566
Laurence Lundblade02625d42020-06-25 14:41:41 -07003567/*
3568 Public function, see header qcbor/qcbor_decode.h file
3569 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003570void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003571{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003572 if(pMe->uLastError != QCBOR_SUCCESS) {
3573 // Already in error state; do nothing.
3574 return;
3575 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003576
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003577 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003578 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003579 return;
3580 }
3581
3582 /*
3583 Reset the length of the UsefulInputBuf to what it was before
3584 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003585 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003586 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003587 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003588
3589
Laurence Lundblade02625d42020-06-25 14:41:41 -07003590 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003591 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003592}
3593
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003594
Laurence Lundbladee6430642020-03-14 21:15:44 -07003595
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003596
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003597
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003598
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003599
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003600
Laurence Lundblade93d89472020-10-03 22:30:50 -07003601static QCBORError
3602InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003603{
3604 switch(pItem->uDataType) {
3605 case QCBOR_TYPE_TRUE:
3606 *pBool = true;
3607 return QCBOR_SUCCESS;
3608 break;
3609
3610 case QCBOR_TYPE_FALSE:
3611 *pBool = false;
3612 return QCBOR_SUCCESS;
3613 break;
3614
3615 default:
3616 return QCBOR_ERR_UNEXPECTED_TYPE;
3617 break;
3618 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003619 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003620}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003621
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003622
Laurence Lundblade9b334962020-08-27 10:55:53 -07003623
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003624/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003625 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003626*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003627void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003628{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003629 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003630 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003631 return;
3632 }
3633
Laurence Lundbladec4537442020-04-14 18:53:22 -07003634 QCBORError nError;
3635 QCBORItem Item;
3636
3637 nError = QCBORDecode_GetNext(pMe, &Item);
3638 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003639 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003640 return;
3641 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003642 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003643}
3644
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003645
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003646/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003647 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003648*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003649void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003650{
3651 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003652 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003653
Laurence Lundblade9b334962020-08-27 10:55:53 -07003654 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003655}
3656
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003657
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003658/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003659 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003660*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003661void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3662{
3663 QCBORItem Item;
3664 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3665
Laurence Lundblade9b334962020-08-27 10:55:53 -07003666 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003667}
3668
3669
3670
Laurence Lundbladec7114722020-08-13 05:11:40 -07003671
3672static void ProcessEpochDate(QCBORDecodeContext *pMe,
3673 QCBORItem *pItem,
3674 uint8_t uTagRequirement,
3675 int64_t *pnTime)
3676{
3677 if(pMe->uLastError != QCBOR_SUCCESS) {
3678 // Already in error state, do nothing
3679 return;
3680 }
3681
3682 QCBORError uErr;
3683
3684 const TagSpecification TagSpec =
3685 {
3686 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003687 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3688 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003689 };
3690
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003691 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003692 if(uErr != QCBOR_SUCCESS) {
3693 goto Done;
3694 }
3695
3696 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3697 uErr = DecodeDateEpoch(pItem);
3698 if(uErr != QCBOR_SUCCESS) {
3699 goto Done;
3700 }
3701 }
3702
Laurence Lundblade9b334962020-08-27 10:55:53 -07003703 // Save the tags in the last item's tags in the decode context
3704 // for QCBORDecode_GetNthTagOfLast()
3705 CopyTags(pMe, pItem);
3706
Laurence Lundbladec7114722020-08-13 05:11:40 -07003707 *pnTime = pItem->val.epochDate.nSeconds;
3708
3709Done:
3710 pMe->uLastError = (uint8_t)uErr;
3711}
3712
3713
3714void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003715 uint8_t uTagRequirement,
3716 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07003717{
3718 if(pMe->uLastError != QCBOR_SUCCESS) {
3719 // Already in error state, do nothing
3720 return;
3721 }
3722
3723 QCBORItem Item;
3724 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3725
3726 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3727}
3728
3729
3730void
3731QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3732 int64_t nLabel,
3733 uint8_t uTagRequirement,
3734 int64_t *pnTime)
3735{
3736 QCBORItem Item;
3737 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3738 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3739}
3740
3741
3742void
3743QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3744 const char *szLabel,
3745 uint8_t uTagRequirement,
3746 int64_t *pnTime)
3747{
3748 QCBORItem Item;
3749 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3750 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3751}
3752
3753
3754
3755
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003756void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3757 TagSpecification TagSpec,
3758 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003759{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003760 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003761 // Already in error state, do nothing
3762 return;
3763 }
3764
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003765 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003766 QCBORItem Item;
3767
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003768 uError = QCBORDecode_GetNext(pMe, &Item);
3769 if(uError != QCBOR_SUCCESS) {
3770 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003771 return;
3772 }
3773
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003774 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003775
3776 if(pMe->uLastError == QCBOR_SUCCESS) {
3777 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003778 } else {
3779 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003780 }
3781}
3782
Laurence Lundbladec4537442020-04-14 18:53:22 -07003783
3784
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003785
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003786static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003787 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003788 UsefulBufC *pValue,
3789 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003790{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003791 const TagSpecification TagSpec =
3792 {
3793 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003794 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3795 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003796 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003797
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003798 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003799 if(uErr != QCBOR_SUCCESS) {
3800 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003801 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003802
3803 *pValue = pItem->val.string;
3804
3805 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3806 *pbIsNegative = false;
3807 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3808 *pbIsNegative = true;
3809 }
3810
3811 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003812}
3813
3814
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003815/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003816 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003817 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003818void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3819 uint8_t uTagRequirement,
3820 UsefulBufC *pValue,
3821 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003822{
3823 if(pMe->uLastError != QCBOR_SUCCESS) {
3824 // Already in error state, do nothing
3825 return;
3826 }
3827
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003828 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003829 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3830 if(uError != QCBOR_SUCCESS) {
3831 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003832 return;
3833 }
3834
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003835 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003836}
3837
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003838
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003839/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003840 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003841*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003842void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3843 int64_t nLabel,
3844 uint8_t uTagRequirement,
3845 UsefulBufC *pValue,
3846 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003847{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003848 QCBORItem Item;
3849 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003850 if(pMe->uLastError != QCBOR_SUCCESS) {
3851 return;
3852 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003853
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003854 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003855}
3856
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003857
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003858/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003859 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003860*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003861void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3862 const char *szLabel,
3863 uint8_t uTagRequirement,
3864 UsefulBufC *pValue,
3865 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003866{
3867 QCBORItem Item;
3868 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003869 if(pMe->uLastError != QCBOR_SUCCESS) {
3870 return;
3871 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003872
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003873 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003874}
3875
3876
3877
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003878
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003879// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003880QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3881 const QCBORItem *pItem,
3882 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07003883 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003884{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003885 const TagSpecification TagSpecText =
3886 {
3887 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003888 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3889 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003890 };
3891 const TagSpecification TagSpecBinary =
3892 {
3893 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003894 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3895 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003896 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003897
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003898 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003899
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003900 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003901 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003902 if(pbIsTag257 != NULL) {
3903 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003904 }
3905 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003906 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003907 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003908 if(pbIsTag257 != NULL) {
3909 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003910 }
3911 uReturn = QCBOR_SUCCESS;
3912
3913 } else {
3914 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3915 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003916
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003917 return uReturn;
3918}
3919
Laurence Lundblade93d89472020-10-03 22:30:50 -07003920// Improvement: add methods for wrapped CBOR, a simple alternate
3921// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003922
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003923
3924
3925
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003926#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003927
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003928typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003929
3930
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003931// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003932static QCBORError
3933Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003934{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003935 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003936
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003937 if(uResult != 0) {
3938 /* This loop will run a maximum of 19 times because
3939 * UINT64_MAX < 10 ^^ 19. More than that will cause
3940 * exit with the overflow error
3941 */
3942 for(; nExponent > 0; nExponent--) {
3943 if(uResult > UINT64_MAX / 10) {
3944 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3945 }
3946 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003947 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003948
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003949 for(; nExponent < 0; nExponent++) {
3950 uResult = uResult / 10;
3951 if(uResult == 0) {
3952 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3953 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003954 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003955 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003956 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003957
3958 *puResult = uResult;
3959
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003960 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003961}
3962
3963
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003964// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003965static QCBORError
3966Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003967{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003968 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003969
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003970 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003971
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003972 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003973 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003974 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003975 */
3976 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003977 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003978 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003979 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003980 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003981 nExponent--;
3982 }
3983
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003984 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003985 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003986 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3987 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003988 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003989 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003990 }
3991
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003992 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003993
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003994 return QCBOR_SUCCESS;
3995}
3996
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003997
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003998/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003999 Compute value with signed mantissa and signed result. Works with
4000 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004001 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004002static inline QCBORError ExponentiateNN(int64_t nMantissa,
4003 int64_t nExponent,
4004 int64_t *pnResult,
4005 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004006{
4007 uint64_t uResult;
4008
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004009 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004010 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004011 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
4012
4013 // Do the exponentiation of the positive mantissa
4014 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
4015 if(uReturn) {
4016 return uReturn;
4017 }
4018
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004019
Laurence Lundblade983500d2020-05-14 11:49:34 -07004020 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
4021 of INT64_MIN. This assumes two's compliment representation where
4022 INT64_MIN is one increment farther from 0 than INT64_MAX.
4023 Trying to write -INT64_MIN doesn't work to get this because the
4024 compiler tries to work with an int64_t which can't represent
4025 -INT64_MIN.
4026 */
4027 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
4028
4029 // Error out if too large
4030 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004031 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4032 }
4033
4034 // Casts are safe because of checks above
4035 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
4036
4037 return QCBOR_SUCCESS;
4038}
4039
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004040
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004041/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004042 Compute value with signed mantissa and unsigned result. Works with
4043 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004044 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004045static inline QCBORError ExponentitateNU(int64_t nMantissa,
4046 int64_t nExponent,
4047 uint64_t *puResult,
4048 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004049{
4050 if(nMantissa < 0) {
4051 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4052 }
4053
4054 // Cast to unsigned is OK because of check for negative
4055 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
4056 // Exponentiation is straight forward
4057 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
4058}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004059
4060
4061/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004062 Compute value with signed mantissa and unsigned result. Works with
4063 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004064 */
4065static inline QCBORError ExponentitateUU(uint64_t uMantissa,
4066 int64_t nExponent,
4067 uint64_t *puResult,
4068 fExponentiator pfExp)
4069{
4070 return (*pfExp)(uMantissa, nExponent, puResult);
4071}
4072
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004073#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4074
4075
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004076
4077
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004078
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004079static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004080{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004081 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004082
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004083 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004084 const uint8_t *pByte = BigNum.ptr;
4085 size_t uLen = BigNum.len;
4086 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07004087 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004088 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004089 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07004090 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004091 }
4092
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004093 *pResult = uResult;
4094 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004095}
4096
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004097
Laurence Lundblade887add82020-05-17 05:50:34 -07004098static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004099{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004100 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004101}
4102
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004103
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004104static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004105{
4106 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004107 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
4108 if(uError) {
4109 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004110 }
4111 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
4112 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004113 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004114}
4115
4116
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004117static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004118{
4119 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004120 /* The negative integer furthest from zero for a C int64_t is
4121 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
4122 negative number in CBOR is computed as -n - 1 where n is the
4123 encoded integer, where n is what is in the variable BigNum. When
4124 converting BigNum to a uint64_t, the maximum value is thus
4125 INT64_MAX, so that when it -n - 1 is applied to it the result will
4126 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07004127
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004128 -n - 1 <= INT64_MIN.
4129 -n - 1 <= -INT64_MAX - 1
4130 n <= INT64_MAX.
4131 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07004132 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004133 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004134 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004135 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004136
4137 /// Now apply -n - 1. The cast is safe because
4138 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
4139 // is the largest positive integer that an int64_t can
4140 // represent. */
4141 *pnResult = -(int64_t)uResult - 1;
4142
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004143 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004144}
4145
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004146
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004147
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004148
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004149
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004150/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004151Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004152
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004153\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004154
Laurence Lundblade93d89472020-10-03 22:30:50 -07004155\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4156 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004157
4158\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4159
Laurence Lundblade93d89472020-10-03 22:30:50 -07004160\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4161 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004162*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07004163static QCBORError
4164ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004165{
4166 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004167 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004168 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004169#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004170 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004171 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
4172 http://www.cplusplus.com/reference/cmath/llround/
4173 */
4174 // Not interested in FE_INEXACT
4175 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004176 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4177 *pnValue = llround(pItem->val.dfnum);
4178 } else {
4179 *pnValue = lroundf(pItem->val.fnum);
4180 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004181 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4182 // llround() shouldn't result in divide by zero, but catch
4183 // it here in case it unexpectedly does. Don't try to
4184 // distinguish between the various exceptions because it seems
4185 // they vary by CPU, compiler and OS.
4186 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004187 }
4188 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004189 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004190 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004191#else
4192 return QCBOR_ERR_HW_FLOAT_DISABLED;
4193#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004194 break;
4195
4196 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004197 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004198 *pnValue = pItem->val.int64;
4199 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004200 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004201 }
4202 break;
4203
4204 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004205 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004206 if(pItem->val.uint64 < INT64_MAX) {
4207 *pnValue = pItem->val.int64;
4208 } else {
4209 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4210 }
4211 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004212 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004213 }
4214 break;
4215
4216 default:
4217 return QCBOR_ERR_UNEXPECTED_TYPE;
4218 }
4219 return QCBOR_SUCCESS;
4220}
4221
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004222
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004223void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004224 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004225 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004226 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004227{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004228 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004229 return;
4230 }
4231
Laurence Lundbladee6430642020-03-14 21:15:44 -07004232 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004233 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4234 if(uError) {
4235 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004236 return;
4237 }
4238
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004239 if(pItem) {
4240 *pItem = Item;
4241 }
4242
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004243 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004244}
4245
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004246
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004247void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4248 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004249 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004250 int64_t *pnValue,
4251 QCBORItem *pItem)
4252{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004253 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004254 if(pMe->uLastError != QCBOR_SUCCESS) {
4255 return;
4256 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004257
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004258 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004259}
4260
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004261
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004262void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4263 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004264 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004265 int64_t *pnValue,
4266 QCBORItem *pItem)
4267{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004268 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004269 if(pMe->uLastError != QCBOR_SUCCESS) {
4270 return;
4271 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004272
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004273 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004274}
4275
4276
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004277/*
4278 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004279
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004280 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004281
Laurence Lundblade93d89472020-10-03 22:30:50 -07004282 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4283 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004284
4285 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4286
Laurence Lundblade93d89472020-10-03 22:30:50 -07004287 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4288 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004289 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004290static QCBORError
4291Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004292{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004293 switch(pItem->uDataType) {
4294
4295 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004296 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004297 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004298 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004299 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004300 }
4301 break;
4302
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004303 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004304 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004305 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004306 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004307 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004308 }
4309 break;
4310
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004311#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4312 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004313 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004314 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004315 pItem->val.expAndMantissa.nExponent,
4316 pnValue,
4317 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004318 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004319 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004320 }
4321 break;
4322
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004323 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004324 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004325 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004326 pItem->val.expAndMantissa.nExponent,
4327 pnValue,
4328 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004329 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004330 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004331 }
4332 break;
4333
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004334 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004335 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004336 int64_t nMantissa;
4337 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004338 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4339 if(uErr) {
4340 return uErr;
4341 }
4342 return ExponentiateNN(nMantissa,
4343 pItem->val.expAndMantissa.nExponent,
4344 pnValue,
4345 Exponentitate10);
4346 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004347 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004348 }
4349 break;
4350
4351 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004352 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004353 int64_t nMantissa;
4354 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004355 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4356 if(uErr) {
4357 return uErr;
4358 }
4359 return ExponentiateNN(nMantissa,
4360 pItem->val.expAndMantissa.nExponent,
4361 pnValue,
4362 Exponentitate10);
4363 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004364 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004365 }
4366 break;
4367
4368 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004369 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004370 int64_t nMantissa;
4371 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004372 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4373 if(uErr) {
4374 return uErr;
4375 }
4376 return ExponentiateNN(nMantissa,
4377 pItem->val.expAndMantissa.nExponent,
4378 pnValue,
4379 Exponentitate2);
4380 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004381 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004382 }
4383 break;
4384
4385 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004386 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004387 int64_t nMantissa;
4388 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004389 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4390 if(uErr) {
4391 return uErr;
4392 }
4393 return ExponentiateNN(nMantissa,
4394 pItem->val.expAndMantissa.nExponent,
4395 pnValue,
4396 Exponentitate2);
4397 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004398 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004399 }
4400 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004401#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4402
Laurence Lundbladee6430642020-03-14 21:15:44 -07004403
Laurence Lundbladec4537442020-04-14 18:53:22 -07004404 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004405 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004406}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004407
4408
Laurence Lundbladec4537442020-04-14 18:53:22 -07004409/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004410 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004411 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004412void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004413{
4414 QCBORItem Item;
4415
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004416 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004417
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004418 if(pMe->uLastError == QCBOR_SUCCESS) {
4419 // The above conversion succeeded
4420 return;
4421 }
4422
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004423 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004424 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004425 return;
4426 }
4427
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004428 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004429}
4430
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004431
4432/*
4433Public function, see header qcbor/qcbor_decode.h file
4434*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004435void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4436 int64_t nLabel,
4437 uint32_t uConvertTypes,
4438 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004439{
4440 QCBORItem Item;
4441
Laurence Lundblade93d89472020-10-03 22:30:50 -07004442 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4443 nLabel,
4444 uConvertTypes,
4445 pnValue,
4446 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004447
4448 if(pMe->uLastError == QCBOR_SUCCESS) {
4449 // The above conversion succeeded
4450 return;
4451 }
4452
4453 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4454 // The above conversion failed in a way that code below can't correct
4455 return;
4456 }
4457
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004458 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004459}
4460
4461
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004462/*
4463Public function, see header qcbor/qcbor_decode.h file
4464*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004465void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4466 const char *szLabel,
4467 uint32_t uConvertTypes,
4468 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004469{
4470 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004471 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4472 szLabel,
4473 uConvertTypes,
4474 pnValue,
4475 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004476
4477 if(pMe->uLastError == QCBOR_SUCCESS) {
4478 // The above conversion succeeded
4479 return;
4480 }
4481
4482 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4483 // The above conversion failed in a way that code below can't correct
4484 return;
4485 }
4486
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004487 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004488}
4489
4490
Laurence Lundblade93d89472020-10-03 22:30:50 -07004491static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004492{
4493 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004494 case QCBOR_TYPE_DOUBLE:
4495 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004496#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004497 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004498 // Can't use llround here because it will not convert values
4499 // greater than INT64_MAX and less than UINT64_MAX that
4500 // need to be converted so it is more complicated.
4501 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4502 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4503 if(isnan(pItem->val.dfnum)) {
4504 return QCBOR_ERR_FLOAT_EXCEPTION;
4505 } else if(pItem->val.dfnum < 0) {
4506 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4507 } else {
4508 double dRounded = round(pItem->val.dfnum);
4509 // See discussion in DecodeDateEpoch() for
4510 // explanation of - 0x7ff
4511 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4512 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4513 }
4514 *puValue = (uint64_t)dRounded;
4515 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004516 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004517 if(isnan(pItem->val.fnum)) {
4518 return QCBOR_ERR_FLOAT_EXCEPTION;
4519 } else if(pItem->val.fnum < 0) {
4520 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4521 } else {
4522 float fRounded = roundf(pItem->val.fnum);
4523 // See discussion in DecodeDateEpoch() for
4524 // explanation of - 0x7ff
4525 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4526 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4527 }
4528 *puValue = (uint64_t)fRounded;
4529 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004530 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004531 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4532 // round() and roundf() shouldn't result in exceptions here, but
4533 // catch them to be robust and thorough. Don't try to
4534 // distinguish between the various exceptions because it seems
4535 // they vary by CPU, compiler and OS.
4536 return QCBOR_ERR_FLOAT_EXCEPTION;
4537 }
4538
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004539 } else {
4540 return QCBOR_ERR_UNEXPECTED_TYPE;
4541 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004542#else
4543 return QCBOR_ERR_HW_FLOAT_DISABLED;
4544#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004545 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004546
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004547 case QCBOR_TYPE_INT64:
4548 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4549 if(pItem->val.int64 >= 0) {
4550 *puValue = (uint64_t)pItem->val.int64;
4551 } else {
4552 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4553 }
4554 } else {
4555 return QCBOR_ERR_UNEXPECTED_TYPE;
4556 }
4557 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004558
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004559 case QCBOR_TYPE_UINT64:
4560 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4561 *puValue = pItem->val.uint64;
4562 } else {
4563 return QCBOR_ERR_UNEXPECTED_TYPE;
4564 }
4565 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004566
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004567 default:
4568 return QCBOR_ERR_UNEXPECTED_TYPE;
4569 }
4570
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004571 return QCBOR_SUCCESS;
4572}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004573
4574
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004575void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004576 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004577 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004578 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004579{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004580 if(pMe->uLastError != QCBOR_SUCCESS) {
4581 return;
4582 }
4583
Laurence Lundbladec4537442020-04-14 18:53:22 -07004584 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004585
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004586 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4587 if(uError) {
4588 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004589 return;
4590 }
4591
Laurence Lundbladea826c502020-05-10 21:07:00 -07004592 if(pItem) {
4593 *pItem = Item;
4594 }
4595
Laurence Lundblade93d89472020-10-03 22:30:50 -07004596 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004597}
4598
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004599
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004600void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004601 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004602 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004603 uint64_t *puValue,
4604 QCBORItem *pItem)
4605{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004606 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004607 if(pMe->uLastError != QCBOR_SUCCESS) {
4608 return;
4609 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004610
Laurence Lundblade93d89472020-10-03 22:30:50 -07004611 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004612}
4613
4614
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004615void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004616 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004617 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004618 uint64_t *puValue,
4619 QCBORItem *pItem)
4620{
4621 if(pMe->uLastError != QCBOR_SUCCESS) {
4622 return;
4623 }
4624
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004625 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004626 if(pMe->uLastError != QCBOR_SUCCESS) {
4627 return;
4628 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004629
Laurence Lundblade93d89472020-10-03 22:30:50 -07004630 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004631}
4632
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004633
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004634
Laurence Lundblade93d89472020-10-03 22:30:50 -07004635static QCBORError
4636UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004637{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004638 switch(pItem->uDataType) {
4639
4640 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004641 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004642 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4643 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004644 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004645 }
4646 break;
4647
4648 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004649 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004650 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4651 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004652 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004653 }
4654 break;
4655
4656#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4657
4658 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004659 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004660 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004661 pItem->val.expAndMantissa.nExponent,
4662 puValue,
4663 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004664 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004665 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004666 }
4667 break;
4668
4669 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004670 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004671 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4672 pItem->val.expAndMantissa.nExponent,
4673 puValue,
4674 Exponentitate2);
4675 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004676 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004677 }
4678 break;
4679
4680 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004681 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004682 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004683 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004684 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004685 if(uErr != QCBOR_SUCCESS) {
4686 return uErr;
4687 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004688 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004689 pItem->val.expAndMantissa.nExponent,
4690 puValue,
4691 Exponentitate10);
4692 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004693 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004694 }
4695 break;
4696
4697 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004698 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004699 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4700 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004701 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004702 }
4703 break;
4704
4705 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004706 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004707 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004708 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004709 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004710 if(uErr != QCBOR_SUCCESS) {
4711 return uErr;
4712 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004713 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004714 pItem->val.expAndMantissa.nExponent,
4715 puValue,
4716 Exponentitate2);
4717 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004718 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004719 }
4720 break;
4721
4722 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004723 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004724 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4725 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004726 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004727 }
4728 break;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004729#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004730 default:
4731 return QCBOR_ERR_UNEXPECTED_TYPE;
4732 }
4733}
4734
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004735
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004736/*
4737 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004738 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004739void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004740{
4741 QCBORItem Item;
4742
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004743 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004744
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004745 if(pMe->uLastError == QCBOR_SUCCESS) {
4746 // The above conversion succeeded
4747 return;
4748 }
4749
4750 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4751 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004752 return;
4753 }
4754
Laurence Lundblade93d89472020-10-03 22:30:50 -07004755 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004756}
4757
Laurence Lundbladec4537442020-04-14 18:53:22 -07004758
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004759/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004760 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004761*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004762void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004763 int64_t nLabel,
4764 uint32_t uConvertTypes,
4765 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004766{
4767 QCBORItem Item;
4768
Laurence Lundblade93d89472020-10-03 22:30:50 -07004769 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
4770 nLabel,
4771 uConvertTypes,
4772 puValue,
4773 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004774
4775 if(pMe->uLastError == QCBOR_SUCCESS) {
4776 // The above conversion succeeded
4777 return;
4778 }
4779
4780 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4781 // The above conversion failed in a way that code below can't correct
4782 return;
4783 }
4784
Laurence Lundblade93d89472020-10-03 22:30:50 -07004785 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004786}
4787
4788
4789/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004790 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004791*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004792void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004793 const char *szLabel,
4794 uint32_t uConvertTypes,
4795 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004796{
4797 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004798 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
4799 szLabel,
4800 uConvertTypes,
4801 puValue,
4802 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004803
4804 if(pMe->uLastError == QCBOR_SUCCESS) {
4805 // The above conversion succeeded
4806 return;
4807 }
4808
4809 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4810 // The above conversion failed in a way that code below can't correct
4811 return;
4812 }
4813
Laurence Lundblade93d89472020-10-03 22:30:50 -07004814 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004815}
4816
4817
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004818
4819
Laurence Lundblade9b334962020-08-27 10:55:53 -07004820static QCBORError ConvertDouble(const QCBORItem *pItem,
4821 uint32_t uConvertTypes,
4822 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004823{
4824 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004825 case QCBOR_TYPE_FLOAT:
4826#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4827 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4828 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004829 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004830 *pdValue = (double)pItem->val.fnum;
4831 } else {
4832 return QCBOR_ERR_UNEXPECTED_TYPE;
4833 }
4834 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004835#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004836 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004837#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004838 break;
4839
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004840 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004841 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4842 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004843 *pdValue = pItem->val.dfnum;
4844 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004845 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004846 }
4847 }
4848 break;
4849
4850 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004851#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004852 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004853 // A simple cast seems to do the job with no worry of exceptions.
4854 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004855 *pdValue = (double)pItem->val.int64;
4856
4857 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004858 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004859 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004860#else
4861 return QCBOR_ERR_HW_FLOAT_DISABLED;
4862#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004863 break;
4864
4865 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004866#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004867 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004868 // A simple cast seems to do the job with no worry of exceptions.
4869 // There will be precision loss for some values.
4870 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004871 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004872 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004873 }
4874 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004875#else
4876 return QCBOR_ERR_HW_FLOAT_DISABLED;
4877#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004878
4879 default:
4880 return QCBOR_ERR_UNEXPECTED_TYPE;
4881 }
4882
4883 return QCBOR_SUCCESS;
4884}
4885
4886
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004887void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004888 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004889 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004890 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004891{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004892 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004893 return;
4894 }
4895
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004896 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004897
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004898 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004899 if(uError) {
4900 pMe->uLastError = (uint8_t)uError;
4901 return;
4902 }
4903
4904 if(pItem) {
4905 *pItem = Item;
4906 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004907
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004908 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004909}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004910
Laurence Lundbladec4537442020-04-14 18:53:22 -07004911
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004912void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4913 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004914 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004915 double *pdValue,
4916 QCBORItem *pItem)
4917{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004918 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004919 if(pMe->uLastError != QCBOR_SUCCESS) {
4920 return;
4921 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004922
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004923 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004924}
4925
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004926
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004927void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4928 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004929 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004930 double *pdValue,
4931 QCBORItem *pItem)
4932{
4933 if(pMe->uLastError != QCBOR_SUCCESS) {
4934 return;
4935 }
4936
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004937 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004938 if(pMe->uLastError != QCBOR_SUCCESS) {
4939 return;
4940 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004941
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004942 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004943}
4944
4945
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004946#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004947static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4948{
4949 double dResult;
4950
4951 dResult = 0.0;
4952 const uint8_t *pByte = BigNum.ptr;
4953 size_t uLen = BigNum.len;
4954 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004955 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004956 while(uLen--) {
4957 dResult = (dResult * 256.0) + (double)*pByte++;
4958 }
4959
4960 return dResult;
4961}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004962#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4963
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004964
Laurence Lundblade93d89472020-10-03 22:30:50 -07004965static QCBORError
4966DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004967{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004968#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004969 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004970 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4971
4972 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004973 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004974
4975#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004976 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004977 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004978 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004979 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4980 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4981 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004982 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004983 }
4984 break;
4985
4986 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004987 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004988 // Underflow gives 0, overflow gives infinity
4989 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4990 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004991 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004992 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004993 }
4994 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004995#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004996
4997 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004998 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004999 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
5000 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005001 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005002 }
5003 break;
5004
5005 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005006 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07005007 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005008 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005009 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005010 }
5011 break;
5012
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005013#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005014 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005015 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005016 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5017 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5018 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005019 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005020 }
5021 break;
5022
5023 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005024 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005025 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5026 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5027 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005028 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005029 }
5030 break;
5031
5032 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005033 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005034 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5035 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5036 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005037 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005038 }
5039 break;
5040
5041 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005042 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07005043 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005044 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5045 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005046 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005047 }
5048 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005049#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
5050
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005051 default:
5052 return QCBOR_ERR_UNEXPECTED_TYPE;
5053 }
5054
5055 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005056
5057#else
5058 (void)pItem;
5059 (void)uConvertTypes;
5060 (void)pdValue;
5061 return QCBOR_ERR_HW_FLOAT_DISABLED;
5062#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5063
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005064}
5065
5066
5067/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005068 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005069*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005070void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
5071 uint32_t uConvertTypes,
5072 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005073{
5074
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005075 QCBORItem Item;
5076
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005077 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -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)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005090}
5091
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005092
5093/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005094 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005095*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005096void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
5097 int64_t nLabel,
5098 uint32_t uConvertTypes,
5099 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005100{
5101 QCBORItem Item;
5102
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005103 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005104
5105 if(pMe->uLastError == QCBOR_SUCCESS) {
5106 // The above conversion succeeded
5107 return;
5108 }
5109
5110 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5111 // The above conversion failed in a way that code below can't correct
5112 return;
5113 }
5114
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005115 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005116}
5117
5118
5119/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005120 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005121*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005122void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
5123 const char *szLabel,
5124 uint32_t uConvertTypes,
5125 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005126{
5127 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005128 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005129
5130 if(pMe->uLastError == QCBOR_SUCCESS) {
5131 // The above conversion succeeded
5132 return;
5133 }
5134
5135 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5136 // The above conversion failed in a way that code below can't correct
5137 return;
5138 }
5139
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005140 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005141}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005142
5143
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005144
5145
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005146#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005147static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
5148{
5149 while((uInt & 0xff00000000000000UL) == 0) {
5150 uInt = uInt << 8;
5151 };
5152
5153 UsefulOutBuf UOB;
5154
5155 UsefulOutBuf_Init(&UOB, Buffer);
5156
5157 while(uInt) {
5158 const uint64_t xx = uInt & 0xff00000000000000UL;
5159 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
5160 uInt = uInt << 8;
5161 (void)xx;
5162 }
5163
5164 return UsefulOutBuf_OutUBuf(&UOB);
5165}
5166
5167
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005168static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
5169 TagSpecification TagSpec,
5170 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005171{
5172 QCBORError uErr;
5173 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005174 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07005175 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005176 if(uErr != QCBOR_SUCCESS) {
5177 goto Done;
5178 }
5179
5180 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
5181 break; // Successful exit. Moving on to finish decoding.
5182 }
5183
5184 // The item is an array, which means an undecoded
5185 // mantissa and exponent, so decode it. It will then
5186 // have a different type and exit the loop if.
5187 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
5188 if(uErr != QCBOR_SUCCESS) {
5189 goto Done;
5190 }
5191
5192 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07005193 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005194 }
5195Done:
5196 return uErr;
5197}
5198
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005199
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005200static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005201 TagSpecification TagSpec,
5202 QCBORItem *pItem,
5203 int64_t *pnMantissa,
5204 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005205{
5206 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005207
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005208 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005209 if(uErr != QCBOR_SUCCESS) {
5210 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005211 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005212
Laurence Lundblade9b334962020-08-27 10:55:53 -07005213 switch (pItem->uDataType) {
5214
5215 case QCBOR_TYPE_DECIMAL_FRACTION:
5216 case QCBOR_TYPE_BIGFLOAT:
5217 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5218 *pnExponent = pItem->val.expAndMantissa.nExponent;
5219 break;
5220
5221 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5222 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5223 *pnExponent = pItem->val.expAndMantissa.nExponent;
5224 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5225 break;
5226
5227 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5228 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5229 *pnExponent = pItem->val.expAndMantissa.nExponent;
5230 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5231 break;
5232
5233 default:
5234 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5235 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005236
5237 Done:
5238 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005239}
5240
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005241
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005242static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005243 TagSpecification TagSpec,
5244 QCBORItem *pItem,
5245 UsefulBuf BufferForMantissa,
5246 UsefulBufC *pMantissa,
5247 bool *pbIsNegative,
5248 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005249{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005250 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005251
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005252 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005253 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005254 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005255 }
5256
5257 uint64_t uMantissa;
5258
5259 switch (pItem->uDataType) {
5260
5261 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005262 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005263 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5264 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5265 *pbIsNegative = false;
5266 } else {
5267 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5268 *pbIsNegative = true;
5269 }
5270 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5271 *pnExponent = pItem->val.expAndMantissa.nExponent;
5272 break;
5273
5274 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005275 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005276 *pnExponent = pItem->val.expAndMantissa.nExponent;
5277 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5278 *pbIsNegative = false;
5279 break;
5280
5281 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005282 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005283 *pnExponent = pItem->val.expAndMantissa.nExponent;
5284 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5285 *pbIsNegative = true;
5286 break;
5287
5288 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005289 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005290 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005291
5292Done:
5293 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005294}
5295
5296
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005297/*
5298 Public function, see header qcbor/qcbor_decode.h file
5299*/
5300void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5301 uint8_t uTagRequirement,
5302 int64_t *pnMantissa,
5303 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005304{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005305 if(pMe->uLastError != QCBOR_SUCCESS) {
5306 return;
5307 }
5308
5309 QCBORItem Item;
5310 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5311 if(uError) {
5312 pMe->uLastError = (uint8_t)uError;
5313 return;
5314 }
5315
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005316 const TagSpecification TagSpec =
5317 {
5318 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005319 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5320 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5321 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005322 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005323
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005324 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005325}
5326
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005327
5328/*
5329 Public function, see header qcbor/qcbor_decode.h file
5330*/
5331void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005332 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005333 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005334 int64_t *pnMantissa,
5335 int64_t *pnExponent)
5336{
5337 if(pMe->uLastError != QCBOR_SUCCESS) {
5338 return;
5339 }
5340
5341 QCBORItem Item;
5342 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5343
5344 const TagSpecification TagSpec =
5345 {
5346 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005347 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5348 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5349 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005350 };
5351
5352 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5353}
5354
5355
5356/*
5357 Public function, see header qcbor/qcbor_decode.h file
5358*/
5359void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005360 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005361 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005362 int64_t *pnMantissa,
5363 int64_t *pnExponent)
5364{
5365 if(pMe->uLastError != QCBOR_SUCCESS) {
5366 return;
5367 }
5368
5369 QCBORItem Item;
5370 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5371
5372 const TagSpecification TagSpec =
5373 {
5374 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005375 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5376 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5377 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005378 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005379
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005380 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5381}
5382
5383
5384/*
5385 Public function, see header qcbor/qcbor_decode.h file
5386*/
5387void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5388 uint8_t uTagRequirement,
5389 UsefulBuf MantissaBuffer,
5390 UsefulBufC *pMantissa,
5391 bool *pbMantissaIsNegative,
5392 int64_t *pnExponent)
5393{
5394 if(pMe->uLastError != QCBOR_SUCCESS) {
5395 return;
5396 }
5397
5398 QCBORItem Item;
5399 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5400 if(uError) {
5401 pMe->uLastError = (uint8_t)uError;
5402 return;
5403 }
5404
5405 const TagSpecification TagSpec =
5406 {
5407 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005408 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5409 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5410 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005411 };
5412
Laurence Lundblade93d89472020-10-03 22:30:50 -07005413 ProcessMantissaAndExponentBig(pMe,
5414 TagSpec,
5415 &Item,
5416 MantissaBuffer,
5417 pMantissa,
5418 pbMantissaIsNegative,
5419 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005420}
5421
5422
5423/*
5424 Public function, see header qcbor/qcbor_decode.h file
5425*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005426void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005427 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005428 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005429 UsefulBuf BufferForMantissa,
5430 UsefulBufC *pMantissa,
5431 bool *pbIsNegative,
5432 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005433{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005434 if(pMe->uLastError != QCBOR_SUCCESS) {
5435 return;
5436 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005437
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005438 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005439 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005440 if(pMe->uLastError != QCBOR_SUCCESS) {
5441 return;
5442 }
5443
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005444 const TagSpecification TagSpec =
5445 {
5446 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005447 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5448 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5449 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005450 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005451
Laurence Lundblade93d89472020-10-03 22:30:50 -07005452 ProcessMantissaAndExponentBig(pMe,
5453 TagSpec,
5454 &Item,
5455 BufferForMantissa,
5456 pMantissa,
5457 pbIsNegative,
5458 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005459}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005460
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005461
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005462/*
5463 Public function, see header qcbor/qcbor_decode.h file
5464*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005465void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005466 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005467 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005468 UsefulBuf BufferForMantissa,
5469 UsefulBufC *pMantissa,
5470 bool *pbIsNegative,
5471 int64_t *pnExponent)
5472{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005473 if(pMe->uLastError != QCBOR_SUCCESS) {
5474 return;
5475 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005476
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005477 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005478 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5479 if(pMe->uLastError != QCBOR_SUCCESS) {
5480 return;
5481 }
5482
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005483 const TagSpecification TagSpec =
5484 {
5485 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005486 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5487 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5488 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005489 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005490
5491 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5492}
5493
5494
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005495/*
5496 Public function, see header qcbor/qcbor_decode.h file
5497*/
5498void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5499 uint8_t uTagRequirement,
5500 int64_t *pnMantissa,
5501 int64_t *pnExponent)
5502{
5503 if(pMe->uLastError != QCBOR_SUCCESS) {
5504 return;
5505 }
5506
5507 QCBORItem Item;
5508 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5509 if(uError) {
5510 pMe->uLastError = (uint8_t)uError;
5511 return;
5512 }
5513 const TagSpecification TagSpec =
5514 {
5515 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005516 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5517 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5518 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005519 };
5520
5521 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5522}
5523
5524
5525/*
5526 Public function, see header qcbor/qcbor_decode.h file
5527*/
5528void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005529 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005530 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005531 int64_t *pnMantissa,
5532 int64_t *pnExponent)
5533{
5534 if(pMe->uLastError != QCBOR_SUCCESS) {
5535 return;
5536 }
5537
5538 QCBORItem Item;
5539 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5540 if(pMe->uLastError != QCBOR_SUCCESS) {
5541 return;
5542 }
5543
5544 const TagSpecification TagSpec =
5545 {
5546 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005547 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5548 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5549 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005550 };
5551
5552 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5553}
5554
5555
5556/*
5557 Public function, see header qcbor/qcbor_decode.h file
5558*/
5559void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005560 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005561 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005562 int64_t *pnMantissa,
5563 int64_t *pnExponent)
5564{
5565 if(pMe->uLastError != QCBOR_SUCCESS) {
5566 return;
5567 }
5568
5569 QCBORItem Item;
5570 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5571 if(pMe->uLastError != QCBOR_SUCCESS) {
5572 return;
5573 }
5574
5575 const TagSpecification TagSpec =
5576 {
5577 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005578 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5579 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5580 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005581 };
5582
5583 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5584}
5585
5586
5587/*
5588 Public function, see header qcbor/qcbor_decode.h file
5589*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005590void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5591 uint8_t uTagRequirement,
5592 UsefulBuf MantissaBuffer,
5593 UsefulBufC *pMantissa,
5594 bool *pbMantissaIsNegative,
5595 int64_t *pnExponent)
5596{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005597 if(pMe->uLastError != QCBOR_SUCCESS) {
5598 return;
5599 }
5600
5601 QCBORItem Item;
5602 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5603 if(uError) {
5604 pMe->uLastError = (uint8_t)uError;
5605 return;
5606 }
5607
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005608 const TagSpecification TagSpec =
5609 {
5610 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005611 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5612 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5613 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005614 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005615
5616 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005617}
5618
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005619
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005620/*
5621 Public function, see header qcbor/qcbor_decode.h file
5622*/
5623void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005624 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005625 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005626 UsefulBuf BufferForMantissa,
5627 UsefulBufC *pMantissa,
5628 bool *pbIsNegative,
5629 int64_t *pnExponent)
5630{
5631 if(pMe->uLastError != QCBOR_SUCCESS) {
5632 return;
5633 }
5634
5635 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005636 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5637 if(pMe->uLastError != QCBOR_SUCCESS) {
5638 return;
5639 }
5640
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005641 const TagSpecification TagSpec =
5642 {
5643 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005644 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5645 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5646 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005647 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005648
Laurence Lundblade93d89472020-10-03 22:30:50 -07005649 ProcessMantissaAndExponentBig(pMe,
5650 TagSpec,
5651 &Item,
5652 BufferForMantissa,
5653 pMantissa,
5654 pbIsNegative,
5655 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005656}
5657
5658
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005659/*
5660 Public function, see header qcbor/qcbor_decode.h file
5661*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005662void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005663 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005664 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005665 UsefulBuf BufferForMantissa,
5666 UsefulBufC *pMantissa,
5667 bool *pbIsNegative,
5668 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005669{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005670 if(pMe->uLastError != QCBOR_SUCCESS) {
5671 return;
5672 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005673
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005674 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005675 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5676 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005677 return;
5678 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005679
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005680 const TagSpecification TagSpec =
5681 {
5682 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005683 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5684 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5685 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005686 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005687
Laurence Lundblade93d89472020-10-03 22:30:50 -07005688 ProcessMantissaAndExponentBig(pMe,
5689 TagSpec,
5690 &Item,
5691 BufferForMantissa,
5692 pMantissa,
5693 pbIsNegative,
5694 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005695}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005696
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005697#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */