blob: 86933030d35b3b549c4c2a2f5100edbdb3c4c01b [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 Lundbladea3336842021-01-03 12:38:36 -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 Lundblade6474c982020-12-26 22:14:34 -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 Lundblade53b945a2020-12-27 02:05:01 -080039
Laurence Lundblade6474c982020-12-26 22:14:34 -080040#include <math.h> /* For isnan(), llround(), llroudf(), round(), roundf(),
41 * pow(), exp2()
42 */
43#include <fenv.h> /* feclearexcept(), fetestexcept() */
Laurence Lundblade53b945a2020-12-27 02:05:01 -080044
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 Lundbladeb69cad72018-09-13 11:09:01 -070048
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053049/*
Laurence Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -0800172 /* Is indefinite */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700173 return false;
174 }
Laurence Lundblade53b945a2020-12-27 02:05:01 -0800175
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800176#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
177
Laurence Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -0800207 /* Should be only called on maps and arrays */
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700208 /*
Laurence Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -0800239 /* In a traveral at a level deeper than the bounded level */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700240 return false;
241 }
Laurence Lundblade6474c982020-12-26 22:14:34 -0800242 /* Works for both definite and indefinite length 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 Lundblade6474c982020-12-26 22:14:34 -0800245 /* Count is not zero, still unconsumed item */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700246 return false;
247 }
Laurence Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -0800294 /* Only call on a defnite 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 Lundblade6474c982020-12-26 22:14:34 -0800302 /* Only call on a defnite 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 Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -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
Laurence Lundblade53b945a2020-12-27 02:05:01 -0800343 * 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 Lundblade6474c982020-12-26 22:14:34 -0800367 /* Nothing to do for empty definite lenth 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 Lundblade6474c982020-12-26 22:14:34 -0800371 /* Empty indefinite length maps and arrays are handled elsewhere */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700372 }
373
Laurence Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -0800554 * Public function, see header file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700555 */
Laurence Lundblade25403ed2021-01-02 16:28:07 -0800556void QCBORDecode_Init(QCBORDecodeContext *pMe,
Laurence Lundblade6474c982020-12-26 22:14:34 -0800557 UsefulBufC EncodedCBOR,
558 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700559{
Laurence Lundblade25403ed2021-01-02 16:28:07 -0800560 memset(pMe, 0, sizeof(QCBORDecodeContext));
561 UsefulInputBuf_Init(&(pMe->InBuf), EncodedCBOR);
Laurence Lundblade6474c982020-12-26 22:14:34 -0800562 /* 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 */
Laurence Lundblade25403ed2021-01-02 16:28:07 -0800565 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 Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -0800591
592
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800593/*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800594 * Deprecated public function, see header file
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800595 */
Laurence Lundblade6474c982020-12-26 22:14:34 -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 Lundblade6474c982020-12-26 22:14:34 -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 Lundblade25403ed2021-01-02 16:28:07 -0800605
606
607/*
608 Decoding items is done in 5 layered functions, one calling the
609 next one down. If a layer has no work to do for a particular item
610 it returns quickly.
611
612 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
613 tagged data items, turning them into the local C representation.
614 For the 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 further
616 decoding and a little bit of recursion.
617
618 - 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 all breaks that terminate
621 indefinite length maps and arrays.
622
623 - GetNext_MapEntry -- This handles the combining of two
624 items, the label and the data, that make up a map entry.
625 It only does work on maps. It combines the label and data
626 items into one labeled item.
627
628 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
629 tags into bit flags associated with the data item. No actual decoding
630 of the contents of the tagged item is performed here.
631
632 - GetNext_FullItem -- This assembles the sub-items that make up
633 an indefinte length string into one string item. It uses the
634 string allocater to create contiguous space for the item. It
635 processes all breaks that are part of indefinite length strings.
636
637 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
638 atomic data item has a "major type", an integer "argument" and optionally
639 some content. For text and byte strings, the content is the bytes
640 that make up the string. These are the smallest data items that are
641 considered to be well-formed. The content may also be other data items in
642 the case of aggregate types. They are not handled in this layer.
643
644 Roughly this takes 300 bytes of stack for vars. Need to
645 evaluate this more carefully and correctly.
646
647 */
648
649
Laurence Lundblade1c929722020-12-27 02:44:57 -0800650/**
651 * @brief Decode the CBOR head, the type and argument.
652 *
653 * @param[in] pUInBuf The input buffer to read from.
654 * @param[out] pnMajorType The decoded major type.
655 * @param[out] puArgument The decoded argument.
656 * @param[out] pnAdditionalInfo The decoded Lower 5 bits of initial byte.
657 *
658 * @retval QCBOR_ERR_UNSUPPORTED
659 * @retval QCBOR_ERR_HIT_END
660 *
661 * This decodes the CBOR "head" that every CBOR data item has. See
662 * longer explaination of the head in documentation for
663 * QCBOREncode_EncodeHead().
664 *
665 * This does the network->host byte order conversion. The conversion
666 * here also results in the conversion for floats in addition to that
667 * for lengths, tags and integer values.
668 *
669 * The int type is preferred to uint8_t for some variables as this
670 * avoids integer promotions, can reduce code size and makes static
671 * analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700672 */
Laurence Lundblade1c929722020-12-27 02:44:57 -0800673static inline QCBORError
674DecodeHead(UsefulInputBuf *pUInBuf,
675 int *pnMajorType,
676 uint64_t *puArgument,
677 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700678{
Laurence Lundblade1c929722020-12-27 02:44:57 -0800679 QCBORError uReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800680
Laurence Lundblade1c929722020-12-27 02:44:57 -0800681 /* Get the initial byte that every CBOR data item has and break it
682 * down. */
683 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800684 const int nTmpMajorType = nInitialByte >> 5;
685 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800686
Laurence Lundblade1c929722020-12-27 02:44:57 -0800687 /* Where the argument accumulates */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800688 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800689
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800690 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800691 /* Need to get 1,2,4 or 8 additional argument bytes. Map
692 * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
693 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800694 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800695
Laurence Lundblade1c929722020-12-27 02:44:57 -0800696 /* Loop getting all the bytes in the argument */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800697 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800698 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800699 /* This shift and add gives the endian conversion. */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800700 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
701 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800702 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800703 /* The reserved and thus-far unused additional info values */
704 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800705 goto Done;
706 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800707 /* Less than 24, additional info is argument or 31, an
708 * indefinite length. No more bytes to get.
709 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800710 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700711 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800712
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700713 if(UsefulInputBuf_GetError(pUInBuf)) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800714 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700715 goto Done;
716 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800717
Laurence Lundblade1c929722020-12-27 02:44:57 -0800718 /* All successful if arrived here. */
719 uReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800720 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800721 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800722 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800723
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700724Done:
Laurence Lundblade1c929722020-12-27 02:44:57 -0800725 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700726}
727
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800728
Laurence Lundblade1c929722020-12-27 02:44:57 -0800729/**
730 * @brief Decode integer types, major types 0 and 1.
731 *
732 * @param[in] nMajorType The CBOR major type (0 or 1).
733 * @param[in] uArgument The argument from the head.
734 * @param[out] pDecodedItem The filled in decoded item.
735 *
736 * @retval QCBOR_ERR_INT_OVERFLOW
737 *
738 * Must only be called when major type is 0 or 1.
739 *
740 * CBOR doesn't explicitly specify two's compliment for integers but
741 * all CPUs use it these days and the test vectors in the RFC are
742 * so. All integers in the CBOR structure are positive and the major
743 * type indicates positive or negative. CBOR can express positive
744 * integers up to 2^x - 1 where x is the number of bits and negative
745 * integers down to 2^x. Note that negative numbers can be one more
746 * away from zero than positive. Stdint, as far as I can tell, uses
747 * two's compliment to represent negative integers.
748 *
749 * See http://www.unix.org/whitepapers/64bit.html for reasons int is
750 * used carefully here, and in particular why it isn't used in the
751 * public interface. Also see
752 * https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
753 *
754 * Int is used for values that need less than 16-bits and would be
755 * subject to integer promotion and result in complaining from static
756 * analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700757 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700758static inline QCBORError
Laurence Lundblade1c929722020-12-27 02:44:57 -0800759DecodeInteger(int nMajorType, uint64_t uArgument, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700760{
Laurence Lundblade1c929722020-12-27 02:44:57 -0800761 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800762
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700763 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800764 if (uArgument <= INT64_MAX) {
765 pDecodedItem->val.int64 = (int64_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700766 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800767
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700768 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800769 pDecodedItem->val.uint64 = uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700770 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700771 }
Laurence Lundblade1c929722020-12-27 02:44:57 -0800772
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700773 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800774 if(uArgument <= INT64_MAX) {
775 /* CBOR's representation of negative numbers lines up with
776 * the two-compliment representation. A negative integer has
777 * one more in range than a positive integer. INT64_MIN is
778 * equal to (-INT64_MAX) - 1.
779 */
780 pDecodedItem->val.int64 = (-(int64_t)uArgument) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700781 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800782
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700783 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800784 /* C can't represent a negative integer in this range so it
785 * is an error.
786 */
787 uReturn = QCBOR_ERR_INT_OVERFLOW;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700788 }
789 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800790
Laurence Lundblade1c929722020-12-27 02:44:57 -0800791 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700792}
793
Laurence Lundblade1c929722020-12-27 02:44:57 -0800794
Laurence Lundblade38299092020-12-28 04:13:50 -0800795/* Make sure #define value line up as DecodeSimple counts on this. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700796#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
797#error QCBOR_TYPE_FALSE macro value wrong
798#endif
799
800#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
801#error QCBOR_TYPE_TRUE macro value wrong
802#endif
803
804#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
805#error QCBOR_TYPE_NULL macro value wrong
806#endif
807
808#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
809#error QCBOR_TYPE_UNDEF macro value wrong
810#endif
811
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700812#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
813#error QCBOR_TYPE_BREAK macro value wrong
814#endif
815
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700816#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
817#error QCBOR_TYPE_DOUBLE macro value wrong
818#endif
819
820#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
821#error QCBOR_TYPE_FLOAT macro value wrong
822#endif
823
Laurence Lundblade38299092020-12-28 04:13:50 -0800824
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800825/**
826 * @brief Decode type 7 -- true, false, floating-point, break...
827 *
828 * @param[in] nAdditionalInfo The lower five bits from the initial byte.
829 * @param[in] uArgument The argument from the head.
830 * @param[out] pDecodedItem The filled in decoded item.
831 *
832 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
833 * @retval QCBOR_ERR_BAD_TYPE_7
834 */
Laurence Lundblade9b334962020-08-27 10:55:53 -0700835
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700836static inline QCBORError
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800837DecodeType7(int nAdditionalInfo, uint64_t uArgument, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700838{
Laurence Lundblade38299092020-12-28 04:13:50 -0800839 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800840
Laurence Lundblade38299092020-12-28 04:13:50 -0800841 /* uAdditionalInfo is 5 bits from the initial byte. Compile time
842 * checks above make sure uAdditionalInfo values line up with
843 * uDataType values. DecodeHead() never returns an AdditionalInfo
844 * > 0x1f so cast is safe.
845 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800846 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800847
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800848 switch(nAdditionalInfo) {
Laurence Lundblade38299092020-12-28 04:13:50 -0800849 /* No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they
850 * are caught before this is called.
851 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800852
Laurence Lundblade38299092020-12-28 04:13:50 -0800853 case HALF_PREC_FLOAT: /* 25 */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700854#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade38299092020-12-28 04:13:50 -0800855 /* Half-precision is returned as a double. The cast to
856 * uint16_t is safe because the encoded value was 16 bits. It
857 * was widened to 64 bits to be passed in here.
858 */
859 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700860 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800861#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade38299092020-12-28 04:13:50 -0800862 uReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800863#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700864 break;
Laurence Lundblade38299092020-12-28 04:13:50 -0800865 case SINGLE_PREC_FLOAT: /* 26 */
866 /* Single precision is normally returned as a double since
867 * double is widely supported, there is no loss of precision,
868 * it makes it easy for the caller in most cases and it can
869 * be converted back to single with no loss of precision
870 *
871 * The cast to uint32_t is safe because the encoded value was
872 * 32 bits. It was widened to 64 bits to be passed in here.
873 */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700874 {
Laurence Lundblade38299092020-12-28 04:13:50 -0800875 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uArgument);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700876#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade38299092020-12-28 04:13:50 -0800877 /* In the normal case, use HW to convert float to
878 * double. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700879 pDecodedItem->val.dfnum = (double)f;
880 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800881#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade38299092020-12-28 04:13:50 -0800882 /* Use of float HW is disabled, return as a float. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700883 pDecodedItem->val.fnum = f;
884 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
885
Laurence Lundblade38299092020-12-28 04:13:50 -0800886 /* IEEE754_FloatToDouble() could be used here to return as
887 * a double, but it adds object code and most likely
888 * anyone disabling FLOAT HW use doesn't care about floats
889 * and wants to save object code.
890 */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800891#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700892 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700893 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700894
Laurence Lundblade38299092020-12-28 04:13:50 -0800895 case DOUBLE_PREC_FLOAT: /* 27 */
896 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700897 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700898 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800899
Laurence Lundblade38299092020-12-28 04:13:50 -0800900 case CBOR_SIMPLEV_FALSE: /* 20 */
901 case CBOR_SIMPLEV_TRUE: /* 21 */
902 case CBOR_SIMPLEV_NULL: /* 22 */
903 case CBOR_SIMPLEV_UNDEF: /* 23 */
904 case CBOR_SIMPLE_BREAK: /* 31 */
905 break; /* nothing to do */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800906
Laurence Lundblade38299092020-12-28 04:13:50 -0800907 case CBOR_SIMPLEV_ONEBYTE: /* 24 */
908 if(uArgument <= CBOR_SIMPLE_BREAK) {
909 /* This takes out f8 00 ... f8 1f which should be encoded
910 * as e0 … f7
911 */
912 uReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700913 goto Done;
914 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800915 /* FALLTHROUGH */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800916
Laurence Lundblade38299092020-12-28 04:13:50 -0800917 default: /* 0-19 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700918 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundblade38299092020-12-28 04:13:50 -0800919 /* DecodeHead() will make uArgument equal to
920 * nAdditionalInfo when nAdditionalInfo is < 24. This cast is
921 * safe because the 2, 4 and 8 byte lengths of uNumber are in
922 * the double/float cases above
Laurence Lundbladeee851742020-01-08 08:37:05 -0800923 */
Laurence Lundblade38299092020-12-28 04:13:50 -0800924 pDecodedItem->val.uSimple = (uint8_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700925 break;
926 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800927
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700928Done:
Laurence Lundblade38299092020-12-28 04:13:50 -0800929 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700930}
931
932
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800933/**
934 * @brief Decode text and byte strings
935 *
936 * @param[in] pAllocator The string allocator or NULL.
937 * @param[in] uStrLen The length of the string.
938 * @param[in] pUInBuf The surce from which to read the string's bytes.
939 * @param[out] pDecodedItem The filled in decoded item.
940 *
941 * @retval QCBOR_ERR_HIT_END
942 * @retval QCBOR_ERR_STRING_ALLOCATE
943 * @retval QCBOR_ERR_STRING_TOO_LONG
944 *
945 * The reads @c uStrlen bytes from @c pUInBuf and fills in @c
946 * pDecodedItem. If @c pAllocator is not NULL then memory for the
947 * string is allocated.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700948 */
Laurence Lundblade38299092020-12-28 04:13:50 -0800949static inline QCBORError
Laurence Lundblade63e68f72020-12-28 04:24:11 -0800950DecodeBytes(const QCBORInternalAllocator *pAllocator,
951 uint64_t uStrLen,
952 UsefulInputBuf *pUInBuf,
953 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700954{
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800955 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800956
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800957 /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
958 * CPUs. This check makes the casts to size_t below safe.
959 *
960 * The max is 4 bytes less than the largest sizeof() so this can be
961 * tested by putting a SIZE_MAX length in the CBOR test input (no
962 * one will care the limit on strings is 4 bytes shorter).
963 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800964 if(uStrLen > SIZE_MAX-4) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800965 uReturn = QCBOR_ERR_STRING_TOO_LONG;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800966 goto Done;
967 }
968
969 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530970 if(UsefulBuf_IsNULLC(Bytes)) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800971 /* Failed to get the bytes for this string item */
972 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530973 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700974 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530975
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800976#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800977 /* Note that this is not where allocation to coallsece
978 * indefinite-length strings is done. This is for when the caller
979 * has requested all strings be allocated. Disabling indefinite
980 * length strings also disables this allocate-all option.
981 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800982 if(pAllocator) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800983 /* request to use the string allocator to make a copy */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800984 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530985 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800986 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530987 goto Done;
988 }
989 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800990 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800991 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530992 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800993#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
994 (void)pAllocator;
995#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
996
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800997 /* Normal case with no string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800998 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800999
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301000Done:
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001001 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001002}
1003
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001004
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001005/**
1006 * @brief Map the CBOR major types for strings to the QCBOR types.
1007 *
1008 * @param[in] nCBORMajorType The CBOR major type to convert.
1009 * @retturns QCBOR type number.
1010 *
1011 * This only works for the two string types.
1012 */
1013static inline uint8_t ConvertStringMajorTypes(int nCBORMajorType)
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001014{
1015 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
1016 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
1017 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001018
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001019 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
1020 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
1021 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001022
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001023 return (uint8_t)(nCBORMajorType + 4);
1024}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001025
1026
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001027/**
1028 * @brief Map the CBOR major types for arrays/maps to the QCBOR types.
1029 *
1030 * @param[in] nCBORMajorType The CBOR major type to convert.
1031 * @retturns QCBOR type number.
1032 *
1033 * This only works for the two aggregate types.
1034 */
1035static inline uint8_t ConvertArrayOrMapType(int nCBORMajorType)
1036{
1037 #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
1038 #error QCBOR_TYPE_ARRAY value not lined up with major type
1039 #endif
1040
1041 #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
1042 #error QCBOR_TYPE_MAP value not lined up with major type
1043 #endif
1044
1045 return (uint8_t)(nCBORMajorType);
1046}
1047
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001048
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001049/**
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001050 * @brief Decode a single primitive data item.
1051 *
1052 * @param[in] pUInBuf Input buffer to read data item from.
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001053 * @param[out] pDecodedItem The filled-in decoded item.
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001054 * @param[in] pAllocator The allocator to use for strings or NULL.
1055 *
1056 * @retval QCBOR_ERR_UNSUPPORTED
1057 * @retval QCBOR_ERR_HIT_END
1058 * @retval QCBOR_ERR_INT_OVERFLOW
1059 * @retval QCBOR_ERR_STRING_ALLOCATE
1060 * @retval QCBOR_ERR_STRING_TOO_LONG
1061 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1062 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001063 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001064 *
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001065 * This decodes the most primitive / atomic data item. It does
1066 * no combing of data items.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001067 */
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001068static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
1069 QCBORItem *pDecodedItem,
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001070 const QCBORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001071{
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001072 QCBORError uReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001073
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001074 /* Get the major type and the argument. The argument could be
1075 * length of more bytes or the value depending on the major
1076 * type. nAdditionalInfo is an encoding of the length of the
1077 * uNumber and is needed to decode floats and doubles.
1078 */
Rob Gilton47cc9562020-08-10 12:03:38 +01001079 int nMajorType = 0;
Laurence Lundblade1c929722020-12-27 02:44:57 -08001080 uint64_t uArgument = 0;
Rob Gilton47cc9562020-08-10 12:03:38 +01001081 int nAdditionalInfo = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001082
Laurence Lundblade4b09f632019-10-09 14:34:59 -07001083 memset(pDecodedItem, 0, sizeof(QCBORItem));
1084
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001085 uReturn = DecodeHead(pUInBuf, &nMajorType, &uArgument, &nAdditionalInfo);
1086 if(uReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001087 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001088 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001089
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001090 /* At this point the major type and the argument are valid. We've
1091 * got the type and the argument that starts every CBOR data item.
1092 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001093 switch (nMajorType) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001094 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1095 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001096 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001097 uReturn = QCBOR_ERR_BAD_INT;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001098 } else {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001099 uReturn = DecodeInteger(nMajorType, uArgument, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001100 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001101 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001102
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001103 case CBOR_MAJOR_TYPE_BYTE_STRING: /* Major type 2 */
1104 case CBOR_MAJOR_TYPE_TEXT_STRING: /* Major type 3 */
1105 pDecodedItem->uDataType = ConvertStringMajorTypes(nMajorType);
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001106 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001107 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001108 } else {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001109 uReturn = DecodeBytes(pAllocator, uArgument, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001110 }
1111 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001112
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001113 case CBOR_MAJOR_TYPE_ARRAY: /* Major type 4 */
1114 case CBOR_MAJOR_TYPE_MAP: /* Major type 5 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001115 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001116 /* Indefinite-length string. */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001117#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -07001118 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001119#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001120 uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001121 break;
1122#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001123 } else {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001124 /* Definite-length string. */
1125 if(uArgument > QCBOR_MAX_ITEMS_IN_ARRAY) {
1126 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
1127 goto Done;
1128 }
1129 /* cast OK because of check above */
Laurence Lundblade1c929722020-12-27 02:44:57 -08001130 pDecodedItem->val.uCount = (uint16_t)uArgument;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001131 }
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001132 pDecodedItem->uDataType = ConvertArrayOrMapType(nMajorType);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001133 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001134
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001135 case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001136 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001137 uReturn = QCBOR_ERR_BAD_INT;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001138 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -08001139 pDecodedItem->val.uTagV = uArgument;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001140 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001141 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001142 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001143
Laurence Lundbladeee851742020-01-08 08:37:05 -08001144 case CBOR_MAJOR_TYPE_SIMPLE:
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001145 /* Major type 7: float, double, true, false, null... */
1146 uReturn = DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001147 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001148
Laurence Lundbladeee851742020-01-08 08:37:05 -08001149 default:
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001150 /* Never happens because DecodeHead() should never return > 7 */
1151 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001152 break;
1153 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001154
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001155Done:
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001156 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001157}
1158
1159
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001160/**
1161 * @brief Process indefinite length strings
1162 *
1163 * @param[in] pMe Decoder context
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001164 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001165 *
1166 * @retval QCBOR_ERR_UNSUPPORTED
1167 * @retval QCBOR_ERR_HIT_END
1168 * @retval QCBOR_ERR_INT_OVERFLOW
1169 * @retval QCBOR_ERR_STRING_ALLOCATE
1170 * @retval QCBOR_ERR_STRING_TOO_LONG
1171 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1172 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001173 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001174 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1175 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001176 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001177 *
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001178 * If @c pDecodedItem is not an indefinite-length string, this does nothing.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001179 *
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001180 * If it is, this loops getting the subsequent chunk data items that
1181 * make up the string. The string allocator is used to make a
1182 * contiguous buffer for the chunks. When this completes @c
1183 * pDecodedItem contains the put-together string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001184 *
1185 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001186 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001187static inline QCBORError
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001188GetNext_FullItem(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001189{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001190 /* Aproximate stack usage
1191 * 64-bit 32-bit
1192 * local vars 32 16
1193 * 2 UsefulBufs 32 16
1194 * QCBORItem 56 52
1195 * TOTAL 120 74
1196 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001197
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001198 /* The string allocator is used here for two purposes: 1)
1199 * coalescing the chunks of an indefinite length string, 2)
1200 * allocating storage for every string returned.
1201 *
1202 * The first use is below in this function. Indefinite length
1203 * strings cannot be processed at all without a string allocator.
1204 *
1205 * The second used is in DecodeBytes() which is called by
1206 * GetNext_Item() below. This second use unneccessary for most use
1207 * and only happens when requested in the call to
1208 * QCBORDecode_SetMemPool(). If the second use not requested then
1209 * NULL is passed for the string allocator to GetNext_Item().
1210 *
1211 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1212 * allocator altogether and thus both of these uses. It reduced the
1213 * decoder object code by about 400 bytes.
1214 */
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001215 const QCBORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001216
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001217#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001218 const QCBORInternalAllocator *pAllocator = NULL;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001219
1220 if(pMe->StringAllocator.pfAllocator) {
1221 pAllocator = &(pMe->StringAllocator);
1222 if(pMe->bStringAllocateAll) {
1223 pAllocatorForGetNext = pAllocator;
1224 }
1225 }
1226#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1227
1228 QCBORError uReturn;
1229 uReturn = GetNext_Item(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
1230 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001231 goto Done;
1232 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001233
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001234 /* Only do indefinite length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001235 const uint8_t uStringType = pDecodedItem->uDataType;
1236 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001237 goto Done;
1238 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001239
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001240 /* Is this a string with an indefinite length? */
1241 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1242 goto Done;
1243 }
1244
1245#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
1246 /* Can't do indefinite length strings without a string allocator */
1247 if(pAllocator == NULL) {
1248 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1249 goto Done;
1250 }
1251
1252 /* Loop getting chunks of the indefinite length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001253 UsefulBufC FullString = NULLUsefulBufC;
1254
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001255 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001256 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001257 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001258 /* Pass a NULL string allocator to GetNext_Item() because the
1259 * individual string chunks in an indefinite length should not
1260 * be allocated. They are always copied in the the contiguous
1261 * buffer allocated here.
1262 */
1263 uReturn = GetNext_Item(&(pMe->InBuf), &StringChunkItem, NULL);
1264 if(uReturn) {
1265 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001266 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001267
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001268 /* Is item is the marker for end of the indefinite length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001269 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001270 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001271 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301272 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001273 break;
1274 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001275
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001276 /* All chunks must be of the same type, the type of the item
1277 * that introduces the indefinite length string. This also
1278 * catches errors where the chunk is not a string at all and an
1279 * indefinite length string inside an indefinite length string.
1280 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001281 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001282 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1283 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001284 break;
1285 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001286
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001287 /* The first time throurgh FullString.ptr is NULL and this is
1288 * equivalent to StringAllocator_Allocate(). Subsequently it is
1289 * not NULL and a reallocation happens.
1290 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001291 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1292 UNCONST_POINTER(FullString.ptr),
1293 FullString.len + StringChunkItem.val.string.len);
1294
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001295 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001296 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001297 break;
1298 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001299
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001300 /* Copy new string chunk to the end of accumulated string */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001301 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001302 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001303
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001304 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1305 /* Getting the item failed, clean up the allocated memory */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001306 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001307 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001308#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1309 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1310#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001311
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001312Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001313 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001314}
1315
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001316
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001317/**
1318 * @brief This converts a tag number to a shorter mapped value for storage.
1319 *
1320 * @param[in] pMe The decode context.
1321 * @param[in] uUnMappedTag The tag number to map
1322 * @param[out] puMappedTagNumer The stored tag number.
1323 *
1324 * @return error code.
1325 *
1326 * The main point of mapping tag numbers is make QCBORItem
1327 * smaller. With this mapping storage of 4 tags takes up 8
1328 * bytes. Without, it would take up 32 bytes.
1329 *
1330 * This maps tag numbers greater than QCBOR_LAST_UNMAPPED_TAG.
1331 * QCBOR_LAST_UNMAPPED_TAG is a little smaller than MAX_UINT16.
1332 *
1333 * See also UnMapTagNumber() and @ref QCBORItem.
1334 */
1335static inline QCBORError
1336MapTagNumber(QCBORDecodeContext *pMe, uint64_t uUnMappedTag, uint16_t *puMappedTagNumer)
1337{
1338 if(uUnMappedTag > QCBOR_LAST_UNMAPPED_TAG) {
1339 int uTagMapIndex;
1340 /* Is there room in the tag map, or is it in it already? */
1341 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
1342 if(pMe->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID64) {
1343 break;
1344 }
1345 if(pMe->auMappedTags[uTagMapIndex] == uUnMappedTag) {
1346 break;
1347 }
1348 }
1349 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1350 return QCBOR_ERR_TOO_MANY_TAGS;
1351 }
1352
1353 /* Covers the cases where tag is new and were it is already in the map */
1354 pMe->auMappedTags[uTagMapIndex] = uUnMappedTag;
1355 *puMappedTagNumer = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
1356
1357 } else {
1358 *puMappedTagNumer = (uint16_t)uUnMappedTag;
1359 }
1360
1361 return QCBOR_SUCCESS;
1362}
1363
1364
1365/**
1366 * @brief This converts a mapped tag number to the actual tag number.
1367 *
1368 * @param[in] pMe The decode context.
1369 * @param[in] uMappedTagNumber The stored tag number.
1370 *
1371 * @return The actual tag number is returned or
1372 * @ref CBOR_TAG_INVALID64 on error.
1373 *
1374 * This is the reverse of MapTagNumber()
1375 */
1376static uint64_t
1377UnMapTagNumber(const QCBORDecodeContext *pMe, uint16_t uMappedTagNumber)
1378{
1379 if(uMappedTagNumber <= QCBOR_LAST_UNMAPPED_TAG) {
1380 return uMappedTagNumber;
1381 } else if(uMappedTagNumber == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001382 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001383 } else {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001384 /* This won't be negative because of code below in
1385 * MapTagNumber()
1386 */
1387 const unsigned uIndex = uMappedTagNumber - (QCBOR_LAST_UNMAPPED_TAG + 1);
1388 return pMe->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001389 }
1390}
1391
Laurence Lundblade9b334962020-08-27 10:55:53 -07001392
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001393/**
1394 * @brief Aggregate all tags wrapping a data item.
1395 *
1396 * @param[in] pMe Decoder context
1397 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001398
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001399 * @retval QCBOR_ERR_UNSUPPORTED
1400 * @retval QCBOR_ERR_HIT_END
1401 * @retval QCBOR_ERR_INT_OVERFLOW
1402 * @retval QCBOR_ERR_STRING_ALLOCATE
1403 * @retval QCBOR_ERR_STRING_TOO_LONG
1404 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1405 * @retval QCBOR_ERR_BAD_TYPE_7
1406 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1407 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1408 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1409 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1410 * @retval QCBOR_ERR_TOO_MANY_TAGS
1411 *
1412 * This loops getting atomic data items until one is not a tag
1413 * number. Usually this is largely pass-through because most
1414 * item are not tag numbers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001415 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001416static QCBORError
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001417GetNext_TaggedItem(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001418{
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001419 uint16_t auItemsTags[QCBOR_MAX_TAGS_PER_ITEM];
1420
1421 /* Initialize to CBOR_TAG_INVALID16 */
1422 #if CBOR_TAG_INVALID16 != 0xffff
1423 /* Be sure the memset does the right thing. */
1424 #err CBOR_TAG_INVALID16 tag not defined as expected
1425 #endif
1426 memset(auItemsTags, 0xff, sizeof(auItemsTags));
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001427
Laurence Lundblade9b334962020-08-27 10:55:53 -07001428 QCBORError uReturn = QCBOR_SUCCESS;
1429
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001430 /* Loop fetching data items until the item fetched is not a tag */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001431 for(;;) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001432 QCBORError uErr = GetNext_FullItem(pMe, pDecodedItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07001433 if(uErr != QCBOR_SUCCESS) {
1434 uReturn = uErr;
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001435 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001436 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001437
Laurence Lundblade9b334962020-08-27 10:55:53 -07001438 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001439 /* Successful exit from loop; maybe got some tags, maybe not */
1440 memcpy(pDecodedItem->uTags, auItemsTags, sizeof(auItemsTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001441 break;
1442 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001443
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001444 if(auItemsTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1445 /* No room in the tag list */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001446 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001447 /* Continue on to get all tags wrapping this item even though
1448 * it is erroring out in the end. This allows decoding to
1449 * continue. This is a resource limit error, not a problem
1450 * with being well-formed CBOR.
1451 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001452 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001453 }
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001454 /* Slide tags over one in the array to make room at index 0.
1455 * Must use memmove because the move source and destination
1456 * overlap.
1457 */
1458 memmove(&auItemsTags[1], auItemsTags, sizeof(auItemsTags) - sizeof(auItemsTags[0]));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001459
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001460 /* Map the tag */
1461 uint16_t uMappedTagNumer;
1462 uReturn = MapTagNumber(pMe, pDecodedItem->val.uTagV, &uMappedTagNumer);
1463 /* Continue even on error so as to consume all tags wrapping
1464 * this data item so decoding can go on. If MapTagNumber()
1465 * errors once it will continue to error.
1466 */
1467 auItemsTags[0] = uMappedTagNumer;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001468 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001469
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001470Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001471 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001472}
1473
1474
1475/*
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001476 * @brief Combine a map entry label and value into one item.
1477 *
1478 * @param[in] pMe Decoder context
1479 * @param[out] pDecodedItem The decoded item that work is done on.
1480 *
1481 * @retval QCBOR_ERR_UNSUPPORTED
1482 * @retval QCBOR_ERR_HIT_END
1483 * @retval QCBOR_ERR_INT_OVERFLOW
1484 * @retval QCBOR_ERR_STRING_ALLOCATE
1485 * @retval QCBOR_ERR_STRING_TOO_LONG
1486 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1487 * @retval QCBOR_ERR_BAD_TYPE_7
1488 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1489 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1490 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1491 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1492 * @retval QCBOR_ERR_TOO_MANY_TAGS
1493 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1494 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1495 *
1496 * If a the current nesting level is a map, then this
1497 * combines pairs of items into one data item with a label
1498 * and value.
1499 *
1500 * This is pass-through if the current nesting leve is
1501 * not a map.
1502 *
1503 * This also implements maps-as-array mode where a map
1504 * is treated like an array to allow caller to do their
1505 * own label processing.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001506 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001507static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001508GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001509{
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001510 QCBORError uReturn = GetNext_TaggedItem(me, pDecodedItem);
1511 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001512 goto Done;
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001513 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001514
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001515 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001516 /* Break can't be a map entry */
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001517 goto Done;
1518 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001519
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001520 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001521 /* Normal decoding of maps -- combine label and value into one item. */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001522
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001523 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001524 /* Save label in pDecodedItem and get the next which will
1525 * be the real data item.
1526 */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001527 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001528 uReturn = GetNext_TaggedItem(me, pDecodedItem);
1529 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001530 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001531 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001532
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301533 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001534
1535 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001536 /* strings are always good labels */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001537 pDecodedItem->label.string = LabelItem.val.string;
1538 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1539 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001540 /* It's not a string and we only want strings */
1541 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001542 goto Done;
1543 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1544 pDecodedItem->label.int64 = LabelItem.val.int64;
1545 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1546 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1547 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1548 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1549 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1550 pDecodedItem->label.string = LabelItem.val.string;
1551 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1552 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1553 } else {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001554 /* label is not an int or a string. It is an arrray
1555 * or a float or such and this implementation doesn't handle that.
1556 * Also, tags on labels are ignored.
1557 */
1558 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001559 goto Done;
1560 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001561 }
1562 } else {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001563 /* Decoding of maps as arrays to let the caller decide what to do
1564 * about labels, particularly lables that are not integers or
1565 * strings.
1566 */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001567 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001568 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001569 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001570 goto Done;
1571 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001572 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001573 /* Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2.
1574 * Cast is needed because of integer promotion.
1575 */
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001576 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001577 }
1578 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001579
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001580Done:
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001581 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001582}
1583
1584
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001585#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001586/**
1587 * @brief Peek and see if next data item is a break;
1588 *
1589 * @param[in] pUIB UsefulInputBuf to read from.
1590 * @param[out] pbNextIsBreak Indicate if next was a break or not.
1591 *
1592 * @return Any decoding error.
1593 *
1594 * See if next item is a CBOR break. If it is, it is consumed,
1595 * if not it is not consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001596*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001597static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001598NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1599{
1600 *pbNextIsBreak = false;
1601 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001602 QCBORItem Peek;
1603 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1604 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1605 if(uReturn != QCBOR_SUCCESS) {
1606 return uReturn;
1607 }
1608 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001609 /* It is not a break, rewind so it can be processed normally. */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001610 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001611 } else {
1612 *pbNextIsBreak = true;
1613 }
1614 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001615
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001616 return QCBOR_SUCCESS;
1617}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001618#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001619
1620
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001621/*
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001622 * @brief Ascend up nesting levels if all items in them have been consumed.
1623 *
1624 * @param[in] pMe The decode context.
1625 * @param[in] bMarkEnd If true mark end of maps/arrays with count of zero.
1626 *
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001627 * An item was just consumed, now figure out if it was the
1628 * end of an array/map map that can be closed out. That
1629 * may in turn close out the above array/map...
Laurence Lundblade642282a2020-06-23 12:00:33 -07001630*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001631static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001632{
1633 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001634
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001635 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001636 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1637
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001638 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1639 /* Nesting level is bstr-wrapped CBOR */
1640
1641 /* Ascent for bstr-wrapped CBOR is always by explicit call
1642 * so no further ascending can happen.
1643 */
1644 break;
1645
1646 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1647 /* Level is a definite-length array/map */
1648
1649 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001650 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1651 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001652 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001653 break;
1654 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001655 /* All items in a definite length array were consumed so it
1656 * is time to ascend one level. This happens below.
1657 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001658
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001659#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001660 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001661 /* Level is an indefinite-length array/map. */
1662
1663 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001664 bool bIsBreak = false;
1665 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1666 if(uReturn != QCBOR_SUCCESS) {
1667 goto Done;
1668 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001669
1670 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001671 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001672 break;
1673 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001674
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001675 /* It was a break in an indefinite length map / array so
1676 * it is time to ascend one level.
1677 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001678
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001679#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001680 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001681
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001682
1683 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001684
Laurence Lundblade93d89472020-10-03 22:30:50 -07001685 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001686 * QCBORDecode_ExitBoundedMode().
1687 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001688 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade93d89472020-10-03 22:30:50 -07001689 /* Set the count to zero for definite length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001690 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001691 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001692 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001693 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001694
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001695 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001696 break;
1697 }
1698
1699 /* Finally, actually ascend one level. */
1700 DecodeNesting_Ascend(&(pMe->nesting));
1701 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001702
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001703 uReturn = QCBOR_SUCCESS;
1704
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001705#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001706Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001707#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1708
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001709 return uReturn;
1710}
1711
1712
1713/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001714 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001715 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1716 indefinte length maps and arrays by looking at the item count or
1717 finding CBOR breaks. It detects the ends of the top-level sequence
1718 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001719
1720 @retval QCBOR_ERR_UNSUPPORTED X
1721
1722 @retval QCBOR_ERR_HIT_END
1723
1724 @retval QCBOR_ERR_INT_OVERFLOW X
1725
1726 @retval QCBOR_ERR_STRING_ALLOCATE
1727
1728 @retval QCBOR_ERR_STRING_TOO_LONG
1729
1730 @retval QCBOR_ERR_HALF_PRECISION_DISABLED X
1731
1732 @retval QCBOR_ERR_BAD_TYPE_7 X
1733
1734 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1735
1736 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1737
1738 @retval QCBOR_ERR_TOO_MANY_TAGS
1739
1740 @retval QCBOR_ERR_MAP_LABEL_TYPE X
1741
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001742 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade9b334962020-08-27 10:55:53 -07001743
1744 @retval QCBOR_ERR_NO_MORE_ITEMS
1745
1746 @retval QCBOR_ERR_BAD_BREAK
1747
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001748 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001749static QCBORError
1750QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001751{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001752 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001753 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001754
Laurence Lundblade642282a2020-06-23 12:00:33 -07001755 /*
1756 If out of bytes to consume, it is either the end of the top-level
1757 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001758
Laurence Lundblade642282a2020-06-23 12:00:33 -07001759 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1760 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1761 CBOR is exited, the length is set back to the top-level's length
1762 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001763 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001764 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001765 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001766 goto Done;
1767 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001768
Laurence Lundblade642282a2020-06-23 12:00:33 -07001769 /*
1770 Check to see if at the end of a bounded definite length map or
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001771 array. The check for a break ending indefinite length array is
1772 later in NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001773 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001774 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001775 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001776 goto Done;
1777 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001778
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001779 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001780 uReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001781 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1782 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001783 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001784 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301785
Laurence Lundblade642282a2020-06-23 12:00:33 -07001786 /*
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001787 Breaks ending arrays/maps are processed later in the call to
1788 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 Lundblade642282a2020-06-23 12:00:33 -07001795 /*
1796 Record the nesting level for this data item before processing any
1797 of decrementing and descending.
1798 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001799 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001800
Laurence Lundblade642282a2020-06-23 12:00:33 -07001801
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001802 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001803 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001804 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001805 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001806
Laurence Lundblade93d89472020-10-03 22:30:50 -07001807 Empty indefinite length maps and arrays are descended into, but
1808 then ascended out of in the next chunk of code.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001809
1810 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001811 encloses them so a decrement needs to be done for them too, but
1812 that is done only when all the items in them have been
1813 processed, not when they are opened with the exception of an
1814 empty map or array.
1815 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001816 QCBORError uDescendErr;
1817 uDescendErr = DecodeNesting_DescendMapOrArray(&(me->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001818 pDecodedItem->uDataType,
1819 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001820 if(uDescendErr != QCBOR_SUCCESS) {
1821 /* This error is probably a traversal error and it
1822 overrides the non-traversal error. */
1823 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001824 goto Done;
1825 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001826 }
1827
Laurence Lundblade02625d42020-06-25 14:41:41 -07001828 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1829 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1830 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001831 /*
1832 The following cases are handled here:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001833 - A non-aggregate item like an integer or string
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001834 - An empty definite length map or array
1835 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001836
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001837 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001838 definite length map/array and break detection for an indefinite
1839 length map/array. If the end of the map/array was reached, then
1840 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001841 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001842 QCBORError uAscendErr;
1843 uAscendErr = NestLevelAscender(me, true);
1844 if(uAscendErr != QCBOR_SUCCESS) {
1845 /* This error is probably a traversal error and it
1846 overrides the non-traversal error. */
1847 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 Lundblade642282a2020-06-23 12:00:33 -07001853 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001854 Tell the caller what level is next. This tells them what
1855 maps/arrays were closed out and makes it possible for them to
1856 reconstruct the tree with just the information returned in
1857 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001858 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001859 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001860 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001861 pDecodedItem->uNextNestLevel = 0;
1862 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001863 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001864 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001865
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001866Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001867 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001868}
1869
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001870
1871static inline void ShiftTags(QCBORItem *pDecodedItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07001872{
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001873 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM-1; i++) {
1874 pDecodedItem->uTags[i] = pDecodedItem->uTags[i+1];
1875 }
1876 pDecodedItem->uTags[QCBOR_MAX_TAGS_PER_ITEM-1] = CBOR_TAG_INVALID16;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001877}
1878
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001879
Laurence Lundblade9b334962020-08-27 10:55:53 -07001880
Laurence Lundbladea3336842021-01-03 12:38:36 -08001881/**
1882 * @brief Convert different epoch date formats in to the QCBOR epoch date format
1883 *
1884 * pDecodedItem[in,out] The data item to convert.
1885 *
1886 * @retval QCBOR_ERR_DATE_OVERFLOW
1887 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
1888 * @retval QCBOR_ERR_BAD_TAG_CONTENT
1889 *
1890 * The epoch date tag defined in QCBOR allows for floating-point
1891 * dates. It even allows a protocol to flop between date formats when
1892 * ever it wants. Floating-point dates aren't that useful as they are
1893 * only needed for dates beyond the age of the earth.
1894 *
1895 * This converts all the date formats into one format of an unsigned
1896 * integer plus a floating-point fraction.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001897 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001898static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001899{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001900 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001901
1902 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1903
1904 switch (pDecodedItem->uDataType) {
1905
1906 case QCBOR_TYPE_INT64:
1907 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1908 break;
1909
1910 case QCBOR_TYPE_UINT64:
Laurence Lundbladea3336842021-01-03 12:38:36 -08001911 /* This only happens for CBOR type 0 > INT64_MAX so it is
1912 * always an overflow.
1913 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07001914 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1915 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001916 break;
1917
1918 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001919 case QCBOR_TYPE_FLOAT:
1920#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001921 {
Laurence Lundbladea3336842021-01-03 12:38:36 -08001922 /* Convert working value to double if input was a float */
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001923 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
Laurence Lundbladea3336842021-01-03 12:38:36 -08001924 pDecodedItem->val.dfnum :
1925 (double)pDecodedItem->val.fnum;
1926
1927 /* The conversion from float to integer requires overflow
1928 * detection since floats can be much larger than integers.
1929 * This implementation errors out on these large float values
1930 * since they are beyond the age of the earth.
1931 *
1932 * These constants for the overflow check are computed by the
1933 * compiler. They are not computed at run time.
1934 *
1935 * The factor of 0x7ff is added/subtracted to avoid a
1936 * rounding error in the wrong direction when the compiler
1937 * computes these constants. There is rounding because an
1938 * 64-bit integer has 63 bits of precision where a double
1939 * only has 53 bits. Without the 0x7ff factor, the compiler
1940 * may round up and produce a double for the bounds check
1941 * that is larger than can be stored in a 64-bit integer. The
1942 * amoutn of 0x7ff is picked because it has 11 bits set.
1943 *
1944 * Without the 0x7ff there is a ~30 minute range of time
1945 * values 10 billion years in the past and in the future
1946 * where this code could go wrong. Some compilers correctly
1947 * generate a warning or error without the 0x7ff.
1948 */
1949 const double dDateMax = (double)(INT64_MAX - 0x7ff);
1950 const double dDateMin = (double)(INT64_MIN + 0x7ff);
1951
1952 if(isnan(d) || d > dDateMax || d < dDateMin) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07001953 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001954 goto Done;
1955 }
Laurence Lundbladea3336842021-01-03 12:38:36 -08001956
1957 /* The actual conversion */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001958 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001959 pDecodedItem->val.epochDate.fSecondsFraction =
1960 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001961 }
Laurence Lundbladea3336842021-01-03 12:38:36 -08001962#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade4b270642020-08-14 12:53:07 -07001963
Laurence Lundbladec7114722020-08-13 05:11:40 -07001964 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001965 goto Done;
1966
Laurence Lundblade9682a532020-06-06 18:33:04 -07001967#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001968 break;
1969
1970 default:
Laurence Lundbladea3336842021-01-03 12:38:36 -08001971 uReturn = QCBOR_ERR_BAD_TAG_CONTENT;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001972 goto Done;
1973 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001974
Laurence Lundblade59289e52019-12-30 13:44:37 -08001975 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1976
1977Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001978 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001979}
1980
1981
1982#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1983/*
1984 Decode decimal fractions and big floats.
1985
1986 When called pDecodedItem must be the array that is tagged as a big
1987 float or decimal fraction, the array that has the two members, the
1988 exponent and mantissa.
1989
1990 This will fetch and decode the exponent and mantissa and put the
1991 result back into pDecodedItem.
1992 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001993static inline QCBORError
Laurence Lundblade59289e52019-12-30 13:44:37 -08001994QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1995{
1996 QCBORError nReturn;
1997
1998 // --- Make sure it is an array; track nesting level of members ---
1999 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
2000 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
2001 goto Done;
2002 }
2003
2004 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08002005 // definite length arrays, but not for indefnite. Instead remember
2006 // the nesting level the two integers must be at, which is one
2007 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002008 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
2009
2010 // --- Is it a decimal fraction or a bigfloat? ---
2011 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
2012 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
2013
2014 // --- Get the exponent ---
2015 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002016 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002017 if(nReturn != QCBOR_SUCCESS) {
2018 goto Done;
2019 }
2020 if(exponentItem.uNestingLevel != nNestLevel) {
2021 // Array is empty or a map/array encountered when expecting an int
2022 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
2023 goto Done;
2024 }
2025 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
2026 // Data arriving as an unsigned int < INT64_MAX has been converted
2027 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
2028 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
2029 // will be too large for this to handle and thus an error that will
2030 // get handled in the next else.
2031 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
2032 } else {
2033 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
2034 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
2035 goto Done;
2036 }
2037
2038 // --- Get the mantissa ---
2039 QCBORItem mantissaItem;
2040 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
2041 if(nReturn != QCBOR_SUCCESS) {
2042 goto Done;
2043 }
2044 if(mantissaItem.uNestingLevel != nNestLevel) {
2045 // Mantissa missing or map/array encountered when expecting number
2046 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
2047 goto Done;
2048 }
2049 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
2050 // Data arriving as an unsigned int < INT64_MAX has been converted
2051 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
2052 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
2053 // will be too large for this to handle and thus an error that
2054 // will get handled in an else below.
2055 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade93d89472020-10-03 22:30:50 -07002056 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
2057 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002058 // Got a good big num mantissa
2059 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
2060 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002061 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
2062 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
2063 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002064 } else {
2065 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
2066 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
2067 goto Done;
2068 }
2069
2070 // --- Check that array only has the two numbers ---
2071 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07002072 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08002073 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
2074 goto Done;
2075 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002076 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002077
2078Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08002079 return nReturn;
2080}
2081#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
2082
2083
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002084static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002085{
2086 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
2087 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07002088 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002089 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
2090 } else {
2091 return QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002092
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002093 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002094
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002095 return QCBOR_SUCCESS;
2096}
2097
2098
Laurence Lundblade99615302020-11-29 11:19:47 -08002099/*
2100 * Table of CBOR tags whose content is either a text string or a byte
2101 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
2102 * of uQCBORtype indicates the content should be a byte string rather
2103 * than a text string
2104 */
2105struct StringTagMapEntry {
2106 uint16_t uTagNumber;
2107 uint8_t uQCBORtype;
2108};
2109
2110#define IS_BYTE_STRING_BIT 0x80
2111#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
2112
2113static const struct StringTagMapEntry StringTagMap[] = {
2114 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
2115 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
2116 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
2117 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
2118 {CBOR_TAG_URI, QCBOR_TYPE_URI},
2119 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
2120 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
2121 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
2122 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
2123 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
2124 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
2125};
2126
2127
2128/*
2129 * Process the CBOR tags that whose content is a byte string or a text
2130 * string and for which the string is just passed on to the caller.
2131 *
2132 * This maps the CBOR tag to the QCBOR type and checks the content
2133 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08002134 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08002135 * possible.
2136 *
2137 * This returns QCBOR_SUCCESS if the tag was procssed,
2138 * QCBOR_ERR_UNSUPPORTED if the tag was not processed and
2139 * QCBOR_ERR_BAD_OPT_TAG if the content type was wrong for the tag.
2140 */
2141static inline
2142QCBORError ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002143{
Laurence Lundblade99615302020-11-29 11:19:47 -08002144 /* This only works on tags that were not mapped; no need for other yet */
2145 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
2146 return QCBOR_ERR_UNSUPPORTED;
2147 }
2148
2149 unsigned uIndex;
2150 for(uIndex = 0; StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
2151 if(StringTagMap[uIndex].uTagNumber == uTag) {
2152 break;
2153 }
2154 }
2155
2156 const uint8_t uQCBORType = StringTagMap[uIndex].uQCBORtype;
2157 if(uQCBORType == QCBOR_TYPE_NONE) {
2158 /* repurpose this error to mean, not handled here */
2159 return QCBOR_ERR_UNSUPPORTED;
2160 }
2161
2162 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
2163 if(uQCBORType & IS_BYTE_STRING_BIT) {
2164 uExpectedType = QCBOR_TYPE_BYTE_STRING;
2165 }
2166
2167 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002168 return QCBOR_ERR_BAD_OPT_TAG;
2169 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002170
Laurence Lundblade99615302020-11-29 11:19:47 -08002171 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002172 return QCBOR_SUCCESS;
2173}
2174
2175
Laurence Lundblade59289e52019-12-30 13:44:37 -08002176/*
Laurence Lundblade99615302020-11-29 11:19:47 -08002177 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
2178 * but the whole tag was not decoded. Here, the whole tags (tag number
2179 * and tag content) that are supported by QCBOR are decoded. This is a
2180 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002181 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002182static QCBORError
2183QCBORDecode_GetNextTag(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002184{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002185 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002186
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002187 uReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
2188 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002189 goto Done;
2190 }
2191
Laurence Lundblade99615302020-11-29 11:19:47 -08002192 /* When there are no tag numbers for the item, this exits first
2193 * thing and effectively does nothing.
2194 *
2195 * This loops over all the tag numbers accumulated for this item
2196 * trying to decode and interpret them. This stops at the end of
2197 * the list or at the first tag number that can't be interpreted by
2198 * this code. This is effectively a recursive processing of the
2199 * tags number list that handles nested tags.
2200 */
2201 while(1) {
2202 /* Don't bother to unmap tags via QCBORITem.uTags since this
2203 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2204 */
2205 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002206
Laurence Lundblade99615302020-11-29 11:19:47 -08002207 if(uTagToProcess == CBOR_TAG_INVALID16) {
2208 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002209 break;
2210
Laurence Lundblade99615302020-11-29 11:19:47 -08002211 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002212 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002213
Laurence Lundblade93d89472020-10-03 22:30:50 -07002214#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002215 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2216 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002217 uReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
Laurence Lundblade93d89472020-10-03 22:30:50 -07002218#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002219
Laurence Lundblade99615302020-11-29 11:19:47 -08002220 } else if(uTagToProcess == CBOR_TAG_MIME ||
2221 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002222 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002223
Laurence Lundblade99615302020-11-29 11:19:47 -08002224 } else {
2225 /* See if it is a pass-through byte/text string tag; process if so */
2226 uReturn = ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002227
Laurence Lundblade99615302020-11-29 11:19:47 -08002228 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
2229 /* It wasn't a pass-through byte/text string tag so it is
2230 * an unknown tag. This is the exit from the loop on the
2231 * first unknown tag. It is a successful exit.
2232 */
2233 uReturn = QCBOR_SUCCESS;
2234 break;
2235 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002236 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002237
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002238 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002239 /* Error exit from the loop */
2240 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002241 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002242
2243 /* A tag was successfully processed, shift it out of the list of
2244 * tags returned. This is the loop increment.
2245 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002246 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002247 }
2248
2249Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002250 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002251}
2252
2253
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002254/*
2255 Public function, see header qcbor/qcbor_decode.h file
2256 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002257QCBORError
2258QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2259{
2260 QCBORError uErr;
2261 uErr = QCBORDecode_GetNextTag(pMe, pDecodedItem);
2262 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002263 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2264 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2265 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002266 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002267}
2268
2269
2270/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002271 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002272 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002273QCBORError
2274QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2275{
2276 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2277 const UsefulInputBuf Save = pMe->InBuf;
2278
2279 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2280
2281 pMe->nesting = SaveNesting;
2282 pMe->InBuf = Save;
2283
2284 return uErr;
2285}
2286
2287
2288/*
2289 Public function, see header qcbor/qcbor_decode.h file
2290 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002291void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2292{
2293 if(pMe->uLastError != QCBOR_SUCCESS) {
2294 return;
2295 }
2296
2297 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2298}
2299
2300
2301/*
2302 Public function, see header qcbor/qcbor_decode.h file
2303 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002304QCBORError
2305QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
2306 QCBORItem *pDecodedItem,
2307 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002308{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002309 QCBORError nReturn;
2310
2311 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
2312 if(nReturn != QCBOR_SUCCESS) {
2313 return nReturn;
2314 }
2315
2316 if(pTags != NULL) {
2317 pTags->uNumUsed = 0;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002318 // Reverse the order because pTags is reverse of
2319 // QCBORItem.uTags.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002320 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2321 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002322 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002323 }
2324 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2325 return QCBOR_ERR_TOO_MANY_TAGS;
2326 }
Laurence Lundblade25403ed2021-01-02 16:28:07 -08002327 pTags->puTags[pTags->uNumUsed] = UnMapTagNumber(me,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002328 pTags->uNumUsed++;
2329 }
2330 }
2331
2332 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002333}
2334
2335
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302336
2337/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002338 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002339 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002340bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002341 const QCBORItem *pItem,
2342 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002343{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002344 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2345 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002346 break;
2347 }
Laurence Lundblade25403ed2021-01-02 16:28:07 -08002348 if(UnMapTagNumber(me, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002349 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002350 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002351 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002352
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002353 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002354}
2355
2356
2357/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002358 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002359 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002360QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002361{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002362 QCBORError uReturn = me->uLastError;
2363
2364 if(uReturn != QCBOR_SUCCESS) {
2365 goto Done;
2366 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002367
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002368 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002369 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002370 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002371 goto Done;
2372 }
2373
2374 // Error out if not all the bytes are consumed
2375 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002376 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002377 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002378
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002379Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002380#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade6de37062018-10-15 12:22:42 +05302381 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002382 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002383 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002384#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002385
Laurence Lundblade085d7952020-07-24 10:26:30 -07002386 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002387}
2388
2389
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002390/*
Laurence Lundblade9b334962020-08-27 10:55:53 -07002391 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002392*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07002393// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002394uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2395 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002396 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002397{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002398 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2399 return CBOR_TAG_INVALID64;
2400 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002401 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2402 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002403 } else {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08002404 return UnMapTagNumber(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002405 }
2406}
2407
Laurence Lundblade9b334962020-08-27 10:55:53 -07002408/*
2409 Public function, see header qcbor/qcbor_decode.h file
2410*/
2411uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2412 uint32_t uIndex)
2413{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002414 if(pMe->uLastError != QCBOR_SUCCESS) {
2415 return CBOR_TAG_INVALID64;
2416 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002417 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2418 return CBOR_TAG_INVALID64;
2419 } else {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08002420 return UnMapTagNumber(pMe, pMe->uLastTags[uIndex]);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002421 }
2422}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002423
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002424/*
2425
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002426Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002427
Laurence Lundbladeee851742020-01-08 08:37:05 -08002428 - Hit end of input before it was expected while decoding type and
2429 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002430
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002431 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002432
Laurence Lundbladeee851742020-01-08 08:37:05 -08002433 - Hit end of input while decoding a text or byte string
2434 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002435
Laurence Lundbladeee851742020-01-08 08:37:05 -08002436 - Encountered conflicting tags -- e.g., an item is tagged both a date
2437 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002438
Laurence Lundbladeee851742020-01-08 08:37:05 -08002439 - Encontered an array or mapp that has too many items
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002440 QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002441
Laurence Lundbladeee851742020-01-08 08:37:05 -08002442 - Encountered array/map nesting that is too deep
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002443 QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002444
Laurence Lundbladeee851742020-01-08 08:37:05 -08002445 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2446 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002447
Laurence Lundbladeee851742020-01-08 08:37:05 -08002448 - The type of a map label is not a string or int
2449 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002450
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002451 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002452
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002453 */
2454
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002455
2456
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002457#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002458
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002459/* ===========================================================================
2460 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002461
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002462 This implements a simple sting allocator for indefinite length
2463 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2464 implements the function type QCBORStringAllocate and allows easy
2465 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002466
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002467 This particular allocator is built-in for convenience. The caller
2468 can implement their own. All of this following code will get
2469 dead-stripped if QCBORDecode_SetMemPool() is not called.
2470
2471 This is a very primitive memory allocator. It does not track
2472 individual allocations, only a high-water mark. A free or
2473 reallocation must be of the last chunk allocated.
2474
2475 The size of the pool and offset to free memory are packed into the
2476 first 8 bytes of the memory pool so we don't have to keep them in
2477 the decode context. Since the address of the pool may not be
2478 aligned, they have to be packed and unpacked as if they were
2479 serialized data of the wire or such.
2480
2481 The sizes packed in are uint32_t to be the same on all CPU types
2482 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002483 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002484
2485
Laurence Lundbladeee851742020-01-08 08:37:05 -08002486static inline int
2487MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002488{
2489 // Use of UsefulInputBuf is overkill, but it is convenient.
2490 UsefulInputBuf UIB;
2491
Laurence Lundbladeee851742020-01-08 08:37:05 -08002492 // Just assume the size here. It was checked during SetUp so
2493 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002494 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002495 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2496 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2497 return UsefulInputBuf_GetError(&UIB);
2498}
2499
2500
Laurence Lundbladeee851742020-01-08 08:37:05 -08002501static inline int
2502MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002503{
2504 // Use of UsefulOutBuf is overkill, but convenient. The
2505 // length check performed here is useful.
2506 UsefulOutBuf UOB;
2507
2508 UsefulOutBuf_Init(&UOB, Pool);
2509 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2510 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2511 return UsefulOutBuf_GetError(&UOB);
2512}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002513
2514
2515/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002516 Internal function for an allocation, reallocation free and destuct.
2517
2518 Having only one function rather than one each per mode saves space in
2519 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002520
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002521 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2522 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002523static UsefulBuf
2524MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002525{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002526 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002527
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002528 uint32_t uPoolSize;
2529 uint32_t uFreeOffset;
2530
2531 if(uNewSize > UINT32_MAX) {
2532 // This allocator is only good up to 4GB. This check should
2533 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2534 goto Done;
2535 }
2536 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2537
2538 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2539 goto Done;
2540 }
2541
2542 if(uNewSize) {
2543 if(pMem) {
2544 // REALLOCATION MODE
2545 // Calculate pointer to the end of the memory pool. It is
2546 // assumed that pPool + uPoolSize won't wrap around by
2547 // assuming the caller won't pass a pool buffer in that is
2548 // not in legitimate memory space.
2549 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2550
2551 // Check that the pointer for reallocation is in the range of the
2552 // pool. This also makes sure that pointer math further down
2553 // doesn't wrap under or over.
2554 if(pMem >= pPool && pMem < pPoolEnd) {
2555 // Offset to start of chunk for reallocation. This won't
2556 // wrap under because of check that pMem >= pPool. Cast
2557 // is safe because the pool is always less than UINT32_MAX
2558 // because of check in QCBORDecode_SetMemPool().
2559 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2560
2561 // Check to see if the allocation will fit. uPoolSize -
2562 // uMemOffset will not wrap under because of check that
2563 // pMem is in the range of the uPoolSize by check above.
2564 if(uNewSize <= uPoolSize - uMemOffset) {
2565 ReturnValue.ptr = pMem;
2566 ReturnValue.len = uNewSize;
2567
2568 // Addition won't wrap around over because uNewSize was
2569 // checked to be sure it is less than the pool size.
2570 uFreeOffset = uMemOffset + uNewSize32;
2571 }
2572 }
2573 } else {
2574 // ALLOCATION MODE
2575 // uPoolSize - uFreeOffset will not underflow because this
2576 // pool implementation makes sure uFreeOffset is always
2577 // smaller than uPoolSize through this check here and
2578 // reallocation case.
2579 if(uNewSize <= uPoolSize - uFreeOffset) {
2580 ReturnValue.len = uNewSize;
2581 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002582 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002583 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002584 }
2585 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002586 if(pMem) {
2587 // FREE MODE
2588 // Cast is safe because of limit on pool size in
2589 // QCBORDecode_SetMemPool()
2590 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2591 } else {
2592 // DESTRUCT MODE
2593 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002594 }
2595 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002596
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002597 UsefulBuf Pool = {pPool, uPoolSize};
2598 MemPool_Pack(Pool, uFreeOffset);
2599
2600Done:
2601 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002602}
2603
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002604
Laurence Lundbladef6531662018-12-04 10:42:22 +09002605/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002606 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002607 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002608QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2609 UsefulBuf Pool,
2610 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002611{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002612 // The pool size and free mem offset are packed into the beginning
2613 // of the pool memory. This compile time check make sure the
2614 // constant in the header is correct. This check should optimize
2615 // down to nothing.
2616 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002617 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002618 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002619
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002620 // The pool size and free offset packed in to the beginning of pool
2621 // memory are only 32-bits. This check will optimize out on 32-bit
2622 // machines.
2623 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002624 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002625 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002626
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002627 // This checks that the pool buffer given is big enough.
2628 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002629 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002630 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002631
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002632 pMe->StringAllocator.pfAllocator = MemPool_Function;
2633 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2634 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002635
Laurence Lundblade30816f22018-11-10 13:40:22 +07002636 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002637}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002638#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002639
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002640
2641
Laurence Lundblade9b334962020-08-27 10:55:53 -07002642static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2643{
2644 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2645}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002646
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002647
2648/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002649 Consume an entire map or array (and do next to
2650 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002651 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002652static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002653ConsumeItem(QCBORDecodeContext *pMe,
2654 const QCBORItem *pItemToConsume,
2655 uint_fast8_t *puNextNestLevel)
2656{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002657 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002658 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002659
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002660 // If it is a map or array, this will tell if it is empty.
2661 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2662
2663 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2664 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002665
Laurence Lundblade1341c592020-04-11 14:19:05 -07002666 /* This works for definite and indefinite length
2667 * maps and arrays by using the nesting level
2668 */
2669 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002670 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002671 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002672 goto Done;
2673 }
2674 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002675
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002676 *puNextNestLevel = Item.uNextNestLevel;
2677
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002678 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002679
Laurence Lundblade1341c592020-04-11 14:19:05 -07002680 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002681 /* item_to_consume is not a map or array */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002682 /* Just pass the nesting level through */
2683 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2684
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002685 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002686 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002687
2688Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002689 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002690}
2691
2692
Laurence Lundblade1341c592020-04-11 14:19:05 -07002693/* Return true if the labels in Item1 and Item2 are the same.
2694 Works only for integer and string labels. Returns false
2695 for any other type. */
2696static inline bool
2697MatchLabel(QCBORItem Item1, QCBORItem Item2)
2698{
2699 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2700 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2701 return true;
2702 }
2703 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002704 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002705 return true;
2706 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002707 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002708 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2709 return true;
2710 }
2711 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2712 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2713 return true;
2714 }
2715 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002716
Laurence Lundblade1341c592020-04-11 14:19:05 -07002717 /* Other label types are never matched */
2718 return false;
2719}
2720
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002721
2722/*
2723 Returns true if Item1 and Item2 are the same type
2724 or if either are of QCBOR_TYPE_ANY.
2725 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002726static inline bool
2727MatchType(QCBORItem Item1, QCBORItem Item2)
2728{
2729 if(Item1.uDataType == Item2.uDataType) {
2730 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002731 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002732 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002733 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002734 return true;
2735 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002736 return false;
2737}
2738
2739
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002740/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002741 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002742
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002743 @param[in] pMe The decode context to search.
2744 @param[in,out] pItemArray The items to search for and the items found.
2745 @param[out] puOffset Byte offset of last item matched.
2746 @param[in] pCBContext Context for the not-found item call back.
2747 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002748
2749 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2750
Laurence Lundblade93d89472020-10-03 22:30:50 -07002751 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2752 were found for one of the labels being
2753 search for. This duplicate detection is
2754 only performed for items in pItemArray,
2755 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002756
Laurence Lundblade93d89472020-10-03 22:30:50 -07002757 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2758 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002759
2760 @retval Also errors returned by QCBORDecode_GetNext().
2761
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002762 On input pItemArray contains a list of labels and data types
2763 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002764
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002765 On output the fully retrieved items are filled in with
2766 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002767
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002768 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002769
2770 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002771 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002772static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002773MapSearch(QCBORDecodeContext *pMe,
2774 QCBORItem *pItemArray,
2775 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002776 void *pCBContext,
2777 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002778{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002779 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002780 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002781
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002782 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002783 uReturn = pMe->uLastError;
2784 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002785 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002786
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002787 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002788 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2789 /* QCBOR_TYPE_NONE as first item indicates just looking
2790 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002791 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2792 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002793 }
2794
Laurence Lundblade085d7952020-07-24 10:26:30 -07002795 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2796 // It is an empty bounded array or map
2797 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2798 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002799 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002800 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002801 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002802 // Nothing is ever found in an empty array or map. All items
2803 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002804 uReturn = QCBOR_SUCCESS;
2805 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002806 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002807 }
2808
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002809 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002810 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2811
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002812 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002813 UsefulInputBuf_Seek(&(pMe->InBuf),
2814 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002815
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002816 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002817 Loop over all the items in the map or array. Each item
2818 could be a map or array, but label matching is only at
2819 the main level. This handles definite and indefinite
2820 length maps and arrays. The only reason this is ever
2821 called on arrays is to find their end position.
2822
2823 This will always run over all items in order to do
2824 duplicate detection.
2825
2826 This will exit with failure if it encounters an
2827 unrecoverable error, but continue on for recoverable
2828 errors.
2829
2830 If a recoverable error occurs on a matched item, then
2831 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002832 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002833 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002834 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002835 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002836 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002837 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002838
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002839 /* Get the item */
2840 QCBORItem Item;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002841 QCBORError uResult = QCBORDecode_GetNextTag(pMe, &Item);
2842 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002843 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002844 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002845 goto Done;
2846 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002847 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002848 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002849 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002850 goto Done;
2851 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002852
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002853 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002854 bool bMatched = false;
2855 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2856 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002857 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002858 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2859 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002860 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002861 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002862 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002863 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002864 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002865 goto Done;
2866 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002867
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002868 if(uResult != QCBOR_SUCCESS) {
2869 uReturn = uResult;
2870 goto Done;
2871 }
2872
Laurence Lundblade1341c592020-04-11 14:19:05 -07002873 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002874 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002875 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002876 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002877 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002878 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002879 bMatched = true;
2880 }
2881 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002882
2883
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002884 if(!bMatched && pfCallback != NULL) {
2885 /*
2886 Call the callback on unmatched labels.
2887 (It is tempting to do duplicate detection here, but that would
2888 require dynamic memory allocation because the number of labels
2889 that might be encountered is unbounded.)
2890 */
2891 uReturn = (*pfCallback)(pCBContext, &Item);
2892 if(uReturn != QCBOR_SUCCESS) {
2893 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002894 }
2895 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002896
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002897 /*
2898 Consume the item whether matched or not. This
2899 does the work of traversing maps and array and
2900 everything in them. In this loop only the
2901 items at the current nesting level are examined
2902 to match the labels.
2903 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002904 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002905 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002906 goto Done;
2907 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002908
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002909 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002910
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002911 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002912
2913 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002914
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002915 // Check here makes sure that this won't accidentally be
2916 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002917 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08002918 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
2919 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002920 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
2921 goto Done;
2922 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002923 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2924 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002925
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002926 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002927 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2928
2929 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002930 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002931 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002932 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002933 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
2934 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002935 }
2936 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002937
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002938 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002939}
2940
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002941
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002942/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002943 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002944*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002945void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2946 int64_t nLabel,
2947 uint8_t uQcborType,
2948 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002949{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002950 if(pMe->uLastError != QCBOR_SUCCESS) {
2951 return;
2952 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002953
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002954 QCBORItem OneItemSeach[2];
2955 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2956 OneItemSeach[0].label.int64 = nLabel;
2957 OneItemSeach[0].uDataType = uQcborType;
2958 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002959
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002960 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002961
2962 *pItem = OneItemSeach[0];
2963
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002964 if(uReturn != QCBOR_SUCCESS) {
2965 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002966 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002967 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002968 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002969 }
2970
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002971 Done:
2972 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002973}
2974
2975
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002976/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002977 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002978*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002979void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2980 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002981 uint8_t uQcborType,
2982 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002983{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002984 if(pMe->uLastError != QCBOR_SUCCESS) {
2985 return;
2986 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002987
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002988 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002989 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2990 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2991 OneItemSeach[0].uDataType = uQcborType;
2992 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002993
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002994 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2995 if(uReturn != QCBOR_SUCCESS) {
2996 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002997 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002998 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002999 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003000 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003001 }
3002
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003003 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003004
3005Done:
3006 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003007}
3008
3009
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003010
Laurence Lundblade93d89472020-10-03 22:30:50 -07003011static QCBORError
3012CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003013{
3014 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
3015 if(uDataType == puTypeList[i]) {
3016 return QCBOR_SUCCESS;
3017 }
3018 }
3019 return QCBOR_ERR_UNEXPECTED_TYPE;
3020}
3021
Laurence Lundblade67257dc2020-07-27 03:33:37 -07003022
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003023/**
3024 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003025 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07003026
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003027 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
3028 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07003029
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003030 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered
3031 tag value.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003032 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07003033static QCBORError
3034CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07003035{
3036 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
3037 pItem->uTags[0] != CBOR_TAG_INVALID16) {
3038 /* There are tags that QCBOR couldn't process on this item and
3039 the caller has told us there should not be. */
3040 return QCBOR_ERR_UNEXPECTED_TYPE;
3041 }
3042
3043 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
3044 const int nItemType = pItem->uDataType;
3045
3046 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
3047 // Must match the tag and only the tag
3048 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3049 }
3050
3051 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
3052 if(uReturn == QCBOR_SUCCESS) {
3053 return QCBOR_SUCCESS;
3054 }
3055
3056 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
3057 /* Must match the content type and only the content type.
3058 There was no match just above so it is a fail. */
3059 return QCBOR_ERR_UNEXPECTED_TYPE;
3060 }
3061
3062 /* If here it can match either the tag or the content
3063 and it hasn't matched the content, so the end
3064 result is whether it matches the tag. This is
3065 also the case that the CBOR standard discourages. */
3066
3067 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3068}
3069
Laurence Lundblade9b334962020-08-27 10:55:53 -07003070
Laurence Lundblade9b334962020-08-27 10:55:53 -07003071
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003072// This could be semi-private if need be
3073static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003074void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
3075 int64_t nLabel,
3076 TagSpecification TagSpec,
3077 QCBORItem *pItem)
3078{
3079 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
3080 if(pMe->uLastError != QCBOR_SUCCESS) {
3081 return;
3082 }
3083
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003084 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003085}
3086
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003087
3088// This could be semi-private if need be
3089static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003090void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
3091 const char *szLabel,
3092 TagSpecification TagSpec,
3093 QCBORItem *pItem)
3094{
3095 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
3096 if(pMe->uLastError != QCBOR_SUCCESS) {
3097 return;
3098 }
3099
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003100 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003101}
3102
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003103// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003104void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
3105 int64_t nLabel,
3106 TagSpecification TagSpec,
3107 UsefulBufC *pString)
3108{
3109 QCBORItem Item;
3110 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
3111 if(pMe->uLastError == QCBOR_SUCCESS) {
3112 *pString = Item.val.string;
3113 }
3114}
3115
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003116// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003117void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
3118 const char * szLabel,
3119 TagSpecification TagSpec,
3120 UsefulBufC *pString)
3121{
3122 QCBORItem Item;
3123 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
3124 if(pMe->uLastError == QCBOR_SUCCESS) {
3125 *pString = Item.val.string;
3126 }
3127}
Laurence Lundblade1341c592020-04-11 14:19:05 -07003128
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003129/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003130 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003131*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003132void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003133{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003134 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
3135 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003136}
3137
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003138/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003139 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003140*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003141void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3142 QCBORItem *pItemList,
3143 void *pCallbackCtx,
3144 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003145{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003146 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
3147 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003148}
3149
3150
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003151/**
3152 * @brief Search for a map/array by label and enter it
3153 *
3154 * @param[in] pMe The decode context.
3155 * @param[in] pSearch The map/array to search for.
3156 *
3157 * @c pSearch is expected to contain one item of type map or array
3158 * with the label specified. The current bounded map will be searched for
3159 * this and if found will be entered.
3160 *
3161 * If the label is not found, or the item found is not a map or array,
3162 * the error state is set.
3163 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003164static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003165{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003166 // The first item in pSearch is the one that is to be
3167 // entered. It should be the only one filled in. Any other
3168 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003169 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003170 return;
3171 }
3172
3173 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003174 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003175 if(pMe->uLastError != QCBOR_SUCCESS) {
3176 return;
3177 }
3178
Laurence Lundblade9b334962020-08-27 10:55:53 -07003179 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003180 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003181 return;
3182 }
3183
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003184 /*
3185 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3186 * next item for the pre-order traversal cursor to be the map/array
3187 * found by MapSearch(). The next few lines of code force the
3188 * cursor to that.
3189 *
3190 * There is no need to retain the old cursor because
3191 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3192 * beginning of the map/array being entered.
3193 *
3194 * The cursor is forced by: 1) setting the input buffer position to
3195 * the item offset found by MapSearch(), 2) setting the map/array
3196 * counter to the total in the map/array, 3) setting the nesting
3197 * level. Setting the map/array counter to the total is not
3198 * strictly correct, but this is OK because this cursor only needs
3199 * to be used to get one item and MapSearch() has already found it
3200 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003201 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003202 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003203
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003204 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3205
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003206 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003207
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003208 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003209}
3210
3211
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003212/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003213 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003214*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003215void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003216{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003217 QCBORItem OneItemSeach[2];
3218 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3219 OneItemSeach[0].label.int64 = nLabel;
3220 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3221 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003222
Laurence Lundblade9b334962020-08-27 10:55:53 -07003223 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003224 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003225}
3226
3227
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003228/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003229 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003230*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003231void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003232{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003233 QCBORItem OneItemSeach[2];
3234 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3235 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3236 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3237 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003238
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003239 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003240}
3241
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003242/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003243 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003244*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003245void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003246{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003247 QCBORItem OneItemSeach[2];
3248 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3249 OneItemSeach[0].label.int64 = nLabel;
3250 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3251 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003252
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003253 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003254}
3255
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003256/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003257 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003258*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003259void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3260{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003261 QCBORItem OneItemSeach[2];
3262 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3263 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3264 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3265 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003266
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003267 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003268}
3269
3270
Laurence Lundblade02625d42020-06-25 14:41:41 -07003271// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003272void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003273{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003274 QCBORError uErr;
3275
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003276 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003277 if(pMe->uLastError != QCBOR_SUCCESS) {
3278 // Already in error state; do nothing.
3279 return;
3280 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003281
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003282 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003283 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003284 uErr = QCBORDecode_GetNext(pMe, &Item);
3285 if(uErr != QCBOR_SUCCESS) {
3286 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003287 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003288 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003289 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3290 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003291 }
3292
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003293 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003294
3295
Laurence Lundbladef0499502020-08-01 11:55:57 -07003296 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003297 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003298 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3299 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003300 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003301 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3302 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003303 // Special case to increment nesting level for zero-length maps
3304 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003305 DecodeNesting_Descend(&(pMe->nesting), uType);
3306 }
3307
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003308 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003309
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003310 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3311 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003312
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003313 if(pItem != NULL) {
3314 *pItem = Item;
3315 }
3316
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003317Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003318 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003319}
3320
Laurence Lundblade02625d42020-06-25 14:41:41 -07003321
3322/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003323 This is the common work for exiting a level that is a bounded map,
3324 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003325
3326 One chunk of work is to set up the pre-order traversal so it is at
3327 the item just after the bounded map, array or bstr that is being
3328 exited. This is somewhat complex.
3329
3330 The other work is to level-up the bounded mode to next higest bounded
3331 mode or the top level if there isn't one.
3332 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003333static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003334ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003335{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003336 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003337
Laurence Lundblade02625d42020-06-25 14:41:41 -07003338 /*
3339 First the pre-order-traversal byte offset is positioned to the
3340 item just after the bounded mode item that was just consumed.
3341 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003342 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3343
Laurence Lundblade02625d42020-06-25 14:41:41 -07003344 /*
3345 Next, set the current nesting level to one above the bounded level
3346 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003347
Laurence Lundblade02625d42020-06-25 14:41:41 -07003348 DecodeNesting_CheckBoundedType() is always called before this and
3349 makes sure pCurrentBounded is valid.
3350 */
3351 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3352
3353 /*
3354 This does the complex work of leveling up the pre-order traversal
3355 when the end of a map or array or another bounded level is
3356 reached. It may do nothing, or ascend all the way to the top
3357 level.
3358 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07003359 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003360 if(uErr != QCBOR_SUCCESS) {
3361 goto Done;
3362 }
3363
Laurence Lundblade02625d42020-06-25 14:41:41 -07003364 /*
3365 This makes the next highest bounded level the current bounded
3366 level. If there is no next highest level, then no bounded mode is
3367 in effect.
3368 */
3369 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003370
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003371 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003372
3373Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003374 return uErr;
3375}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003376
Laurence Lundblade02625d42020-06-25 14:41:41 -07003377
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003378// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003379void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003380{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003381 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003382 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003383 return;
3384 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003385
Laurence Lundblade02625d42020-06-25 14:41:41 -07003386 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003387
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003388 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003389 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003390 goto Done;
3391 }
3392
Laurence Lundblade02625d42020-06-25 14:41:41 -07003393 /*
3394 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003395 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003396 from previous map search, then do a dummy search.
3397 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003398 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003399 QCBORItem Dummy;
3400 Dummy.uLabelType = QCBOR_TYPE_NONE;
3401 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3402 if(uErr != QCBOR_SUCCESS) {
3403 goto Done;
3404 }
3405 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003406
Laurence Lundblade02625d42020-06-25 14:41:41 -07003407 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003408
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003409Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003410 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003411}
3412
3413
Laurence Lundblade1341c592020-04-11 14:19:05 -07003414
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003415static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003416 const QCBORItem *pItem,
3417 uint8_t uTagRequirement,
3418 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003419{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003420 if(pBstr) {
3421 *pBstr = NULLUsefulBufC;
3422 }
3423
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003424 if(pMe->uLastError != QCBOR_SUCCESS) {
3425 // Already in error state; do nothing.
3426 return pMe->uLastError;
3427 }
3428
3429 QCBORError uError = QCBOR_SUCCESS;
3430
3431 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3432 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3433 goto Done;;
3434 }
3435
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003436 const TagSpecification TagSpec =
3437 {
3438 uTagRequirement,
3439 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3440 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3441 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003442
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003443 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003444 if(uError != QCBOR_SUCCESS) {
3445 goto Done;
3446 }
3447
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003448 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003449 // Reverse the decrement done by GetNext() for the bstr so the
3450 // increment in NestLevelAscender() called by ExitBoundedLevel()
3451 // will work right.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003452 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003453 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003454
3455 if(pBstr) {
3456 *pBstr = pItem->val.string;
3457 }
3458
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003459 // This saves the current length of the UsefulInputBuf and then
3460 // narrows the UsefulInputBuf to start and length of the wrapped
3461 // CBOR that is being entered.
3462 //
3463 // This makes sure the length is less than
3464 // QCBOR_MAX_DECODE_INPUT_SIZE which is slighly less than
3465 // UINT32_MAX. The value UINT32_MAX is used as a special indicator
3466 // value. The checks against QCBOR_MAX_DECODE_INPUT_SIZE also make
3467 // the casts safe. uEndOfBstr will always be less than
3468 // uPreviousLength because of the way UsefulInputBuf works so there
3469 // is no need to check it. There is also a range check in the
3470 // seek.
3471 //
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003472 // Most of these calls are simple inline accessors so this doesn't
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003473 // amount to much code.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003474 // Cast of uPreviousLength to uint32_t for cases where SIZE_MAX < UINT32_MAX.
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003475 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003476 if((uint32_t)uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003477 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003478 goto Done;
3479 }
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003480 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003481 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003482 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003483
Laurence Lundblade02625d42020-06-25 14:41:41 -07003484 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003485 (uint32_t)uPreviousLength,
3486 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003487Done:
3488 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003489}
3490
3491
Laurence Lundblade02625d42020-06-25 14:41:41 -07003492/*
3493 Public function, see header qcbor/qcbor_decode.h file
3494 */
3495void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003496 uint8_t uTagRequirement,
3497 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003498{
3499 if(pMe->uLastError != QCBOR_SUCCESS) {
3500 // Already in error state; do nothing.
3501 return;
3502 }
3503
3504 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003505 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003506 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3507 if(pMe->uLastError != QCBOR_SUCCESS) {
3508 return;
3509 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003510
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003511 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003512 &Item,
3513 uTagRequirement,
3514 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003515}
3516
3517
Laurence Lundblade02625d42020-06-25 14:41:41 -07003518/*
3519 Public function, see header qcbor/qcbor_decode.h file
3520 */
3521void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003522 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003523 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003524 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003525{
3526 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003527 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003528
Laurence Lundblade93d89472020-10-03 22:30:50 -07003529 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3530 &Item,
3531 uTagRequirement,
3532 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003533}
3534
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003535
Laurence Lundblade02625d42020-06-25 14:41:41 -07003536/*
3537 Public function, see header qcbor/qcbor_decode.h file
3538 */
3539void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003540 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003541 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003542 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003543{
3544 QCBORItem Item;
3545 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3546
Laurence Lundblade93d89472020-10-03 22:30:50 -07003547 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3548 &Item,
3549 uTagRequirement,
3550 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003551}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003552
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003553
Laurence Lundblade02625d42020-06-25 14:41:41 -07003554/*
3555 Public function, see header qcbor/qcbor_decode.h file
3556 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003557void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003558{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003559 if(pMe->uLastError != QCBOR_SUCCESS) {
3560 // Already in error state; do nothing.
3561 return;
3562 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003563
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003564 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003565 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003566 return;
3567 }
3568
3569 /*
3570 Reset the length of the UsefulInputBuf to what it was before
3571 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003572 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003573 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003574 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003575
3576
Laurence Lundblade02625d42020-06-25 14:41:41 -07003577 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003578 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003579}
3580
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003581
Laurence Lundbladee6430642020-03-14 21:15:44 -07003582
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003583
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003584
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003585
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003586
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003587
Laurence Lundblade93d89472020-10-03 22:30:50 -07003588static QCBORError
3589InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003590{
3591 switch(pItem->uDataType) {
3592 case QCBOR_TYPE_TRUE:
3593 *pBool = true;
3594 return QCBOR_SUCCESS;
3595 break;
3596
3597 case QCBOR_TYPE_FALSE:
3598 *pBool = false;
3599 return QCBOR_SUCCESS;
3600 break;
3601
3602 default:
3603 return QCBOR_ERR_UNEXPECTED_TYPE;
3604 break;
3605 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003606 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003607}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003608
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003609
Laurence Lundblade9b334962020-08-27 10:55:53 -07003610
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003611/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003612 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003613*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003614void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003615{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003616 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003617 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003618 return;
3619 }
3620
Laurence Lundbladec4537442020-04-14 18:53:22 -07003621 QCBORError nError;
3622 QCBORItem Item;
3623
3624 nError = QCBORDecode_GetNext(pMe, &Item);
3625 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003626 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003627 return;
3628 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003629 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003630}
3631
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003632
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003633/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003634 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003635*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003636void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003637{
3638 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003639 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003640
Laurence Lundblade9b334962020-08-27 10:55:53 -07003641 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003642}
3643
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003644
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003645/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003646 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003647*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003648void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3649{
3650 QCBORItem Item;
3651 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3652
Laurence Lundblade9b334962020-08-27 10:55:53 -07003653 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003654}
3655
3656
3657
Laurence Lundbladec7114722020-08-13 05:11:40 -07003658
3659static void ProcessEpochDate(QCBORDecodeContext *pMe,
3660 QCBORItem *pItem,
3661 uint8_t uTagRequirement,
3662 int64_t *pnTime)
3663{
3664 if(pMe->uLastError != QCBOR_SUCCESS) {
3665 // Already in error state, do nothing
3666 return;
3667 }
3668
3669 QCBORError uErr;
3670
3671 const TagSpecification TagSpec =
3672 {
3673 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003674 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3675 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003676 };
3677
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003678 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003679 if(uErr != QCBOR_SUCCESS) {
3680 goto Done;
3681 }
3682
3683 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3684 uErr = DecodeDateEpoch(pItem);
3685 if(uErr != QCBOR_SUCCESS) {
3686 goto Done;
3687 }
3688 }
3689
Laurence Lundblade9b334962020-08-27 10:55:53 -07003690 // Save the tags in the last item's tags in the decode context
3691 // for QCBORDecode_GetNthTagOfLast()
3692 CopyTags(pMe, pItem);
3693
Laurence Lundbladec7114722020-08-13 05:11:40 -07003694 *pnTime = pItem->val.epochDate.nSeconds;
3695
3696Done:
3697 pMe->uLastError = (uint8_t)uErr;
3698}
3699
3700
3701void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003702 uint8_t uTagRequirement,
3703 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07003704{
3705 if(pMe->uLastError != QCBOR_SUCCESS) {
3706 // Already in error state, do nothing
3707 return;
3708 }
3709
3710 QCBORItem Item;
3711 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3712
3713 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3714}
3715
3716
3717void
3718QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3719 int64_t nLabel,
3720 uint8_t uTagRequirement,
3721 int64_t *pnTime)
3722{
3723 QCBORItem Item;
3724 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3725 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3726}
3727
3728
3729void
3730QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3731 const char *szLabel,
3732 uint8_t uTagRequirement,
3733 int64_t *pnTime)
3734{
3735 QCBORItem Item;
3736 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3737 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3738}
3739
3740
3741
3742
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003743void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3744 TagSpecification TagSpec,
3745 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003746{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003747 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003748 // Already in error state, do nothing
3749 return;
3750 }
3751
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003752 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003753 QCBORItem Item;
3754
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003755 uError = QCBORDecode_GetNext(pMe, &Item);
3756 if(uError != QCBOR_SUCCESS) {
3757 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003758 return;
3759 }
3760
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003761 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003762
3763 if(pMe->uLastError == QCBOR_SUCCESS) {
3764 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003765 } else {
3766 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003767 }
3768}
3769
Laurence Lundbladec4537442020-04-14 18:53:22 -07003770
3771
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003772
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003773static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003774 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003775 UsefulBufC *pValue,
3776 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003777{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003778 const TagSpecification TagSpec =
3779 {
3780 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003781 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3782 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003783 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003784
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003785 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003786 if(uErr != QCBOR_SUCCESS) {
3787 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003788 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003789
3790 *pValue = pItem->val.string;
3791
3792 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3793 *pbIsNegative = false;
3794 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3795 *pbIsNegative = true;
3796 }
3797
3798 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003799}
3800
3801
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003802/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003803 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003804 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003805void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3806 uint8_t uTagRequirement,
3807 UsefulBufC *pValue,
3808 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003809{
3810 if(pMe->uLastError != QCBOR_SUCCESS) {
3811 // Already in error state, do nothing
3812 return;
3813 }
3814
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003815 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003816 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3817 if(uError != QCBOR_SUCCESS) {
3818 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003819 return;
3820 }
3821
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003822 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003823}
3824
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003825
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003826/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003827 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003828*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003829void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3830 int64_t nLabel,
3831 uint8_t uTagRequirement,
3832 UsefulBufC *pValue,
3833 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003834{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003835 QCBORItem Item;
3836 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003837 if(pMe->uLastError != QCBOR_SUCCESS) {
3838 return;
3839 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003840
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003841 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003842}
3843
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003844
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003845/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003846 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003847*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003848void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3849 const char *szLabel,
3850 uint8_t uTagRequirement,
3851 UsefulBufC *pValue,
3852 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003853{
3854 QCBORItem Item;
3855 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003856 if(pMe->uLastError != QCBOR_SUCCESS) {
3857 return;
3858 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003859
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003860 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003861}
3862
3863
3864
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003865
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003866// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003867QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3868 const QCBORItem *pItem,
3869 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07003870 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003871{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003872 const TagSpecification TagSpecText =
3873 {
3874 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003875 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3876 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003877 };
3878 const TagSpecification TagSpecBinary =
3879 {
3880 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003881 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3882 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003883 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003884
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003885 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003886
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003887 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003888 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003889 if(pbIsTag257 != NULL) {
3890 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003891 }
3892 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003893 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003894 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003895 if(pbIsTag257 != NULL) {
3896 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003897 }
3898 uReturn = QCBOR_SUCCESS;
3899
3900 } else {
3901 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3902 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003903
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003904 return uReturn;
3905}
3906
Laurence Lundblade93d89472020-10-03 22:30:50 -07003907// Improvement: add methods for wrapped CBOR, a simple alternate
3908// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003909
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003910
3911
3912
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003913#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003914
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003915typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003916
3917
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003918// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003919static QCBORError
3920Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003921{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003922 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003923
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003924 if(uResult != 0) {
3925 /* This loop will run a maximum of 19 times because
3926 * UINT64_MAX < 10 ^^ 19. More than that will cause
3927 * exit with the overflow error
3928 */
3929 for(; nExponent > 0; nExponent--) {
3930 if(uResult > UINT64_MAX / 10) {
3931 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3932 }
3933 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003934 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003935
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003936 for(; nExponent < 0; nExponent++) {
3937 uResult = uResult / 10;
3938 if(uResult == 0) {
3939 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3940 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003941 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003942 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003943 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003944
3945 *puResult = uResult;
3946
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003947 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003948}
3949
3950
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003951// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003952static QCBORError
3953Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003954{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003955 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003956
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003957 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003958
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003959 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003960 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003961 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003962 */
3963 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003964 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003965 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003966 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003967 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003968 nExponent--;
3969 }
3970
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003971 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003972 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003973 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3974 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003975 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003976 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003977 }
3978
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003979 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003980
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003981 return QCBOR_SUCCESS;
3982}
3983
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003984
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003985/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003986 Compute value with signed mantissa and signed result. Works with
3987 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003988 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003989static inline QCBORError ExponentiateNN(int64_t nMantissa,
3990 int64_t nExponent,
3991 int64_t *pnResult,
3992 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003993{
3994 uint64_t uResult;
3995
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003996 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003997 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003998 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3999
4000 // Do the exponentiation of the positive mantissa
4001 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
4002 if(uReturn) {
4003 return uReturn;
4004 }
4005
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004006
Laurence Lundblade983500d2020-05-14 11:49:34 -07004007 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
4008 of INT64_MIN. This assumes two's compliment representation where
4009 INT64_MIN is one increment farther from 0 than INT64_MAX.
4010 Trying to write -INT64_MIN doesn't work to get this because the
4011 compiler tries to work with an int64_t which can't represent
4012 -INT64_MIN.
4013 */
4014 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
4015
4016 // Error out if too large
4017 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004018 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4019 }
4020
4021 // Casts are safe because of checks above
4022 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
4023
4024 return QCBOR_SUCCESS;
4025}
4026
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004027
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004028/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004029 Compute value with signed mantissa and unsigned result. Works with
4030 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004031 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004032static inline QCBORError ExponentitateNU(int64_t nMantissa,
4033 int64_t nExponent,
4034 uint64_t *puResult,
4035 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004036{
4037 if(nMantissa < 0) {
4038 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4039 }
4040
4041 // Cast to unsigned is OK because of check for negative
4042 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
4043 // Exponentiation is straight forward
4044 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
4045}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004046
4047
4048/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004049 Compute value with signed mantissa and unsigned result. Works with
4050 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004051 */
4052static inline QCBORError ExponentitateUU(uint64_t uMantissa,
4053 int64_t nExponent,
4054 uint64_t *puResult,
4055 fExponentiator pfExp)
4056{
4057 return (*pfExp)(uMantissa, nExponent, puResult);
4058}
4059
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004060#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4061
4062
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004063
4064
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004065
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004066static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004067{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004068 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004069
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004070 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004071 const uint8_t *pByte = BigNum.ptr;
4072 size_t uLen = BigNum.len;
4073 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07004074 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004075 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004076 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07004077 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004078 }
4079
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004080 *pResult = uResult;
4081 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004082}
4083
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004084
Laurence Lundblade887add82020-05-17 05:50:34 -07004085static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004086{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004087 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004088}
4089
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004090
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004091static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004092{
4093 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004094 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
4095 if(uError) {
4096 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004097 }
4098 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
4099 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004100 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004101}
4102
4103
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004104static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004105{
4106 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004107 /* The negative integer furthest from zero for a C int64_t is
4108 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
4109 negative number in CBOR is computed as -n - 1 where n is the
4110 encoded integer, where n is what is in the variable BigNum. When
4111 converting BigNum to a uint64_t, the maximum value is thus
4112 INT64_MAX, so that when it -n - 1 is applied to it the result will
4113 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07004114
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004115 -n - 1 <= INT64_MIN.
4116 -n - 1 <= -INT64_MAX - 1
4117 n <= INT64_MAX.
4118 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07004119 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004120 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004121 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004122 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004123
4124 /// Now apply -n - 1. The cast is safe because
4125 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
4126 // is the largest positive integer that an int64_t can
4127 // represent. */
4128 *pnResult = -(int64_t)uResult - 1;
4129
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004130 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004131}
4132
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004133
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004134
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004135
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004136
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004137/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004138Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004139
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004140\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004141
Laurence Lundblade93d89472020-10-03 22:30:50 -07004142\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4143 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004144
4145\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4146
Laurence Lundblade93d89472020-10-03 22:30:50 -07004147\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4148 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004149*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07004150static QCBORError
4151ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004152{
4153 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004154 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004155 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004156#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004157 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004158 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
4159 http://www.cplusplus.com/reference/cmath/llround/
4160 */
4161 // Not interested in FE_INEXACT
4162 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004163 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4164 *pnValue = llround(pItem->val.dfnum);
4165 } else {
4166 *pnValue = lroundf(pItem->val.fnum);
4167 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004168 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4169 // llround() shouldn't result in divide by zero, but catch
4170 // it here in case it unexpectedly does. Don't try to
4171 // distinguish between the various exceptions because it seems
4172 // they vary by CPU, compiler and OS.
4173 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004174 }
4175 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004176 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004177 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004178#else
4179 return QCBOR_ERR_HW_FLOAT_DISABLED;
4180#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004181 break;
4182
4183 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004184 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004185 *pnValue = pItem->val.int64;
4186 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004187 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004188 }
4189 break;
4190
4191 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004192 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004193 if(pItem->val.uint64 < INT64_MAX) {
4194 *pnValue = pItem->val.int64;
4195 } else {
4196 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4197 }
4198 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004199 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004200 }
4201 break;
4202
4203 default:
4204 return QCBOR_ERR_UNEXPECTED_TYPE;
4205 }
4206 return QCBOR_SUCCESS;
4207}
4208
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004209
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004210void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004211 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004212 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004213 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004214{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004215 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004216 return;
4217 }
4218
Laurence Lundbladee6430642020-03-14 21:15:44 -07004219 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004220 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4221 if(uError) {
4222 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004223 return;
4224 }
4225
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004226 if(pItem) {
4227 *pItem = Item;
4228 }
4229
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004230 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004231}
4232
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004233
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004234void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4235 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004236 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004237 int64_t *pnValue,
4238 QCBORItem *pItem)
4239{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004240 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004241 if(pMe->uLastError != QCBOR_SUCCESS) {
4242 return;
4243 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004244
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004245 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004246}
4247
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004248
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004249void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4250 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004251 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004252 int64_t *pnValue,
4253 QCBORItem *pItem)
4254{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004255 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004256 if(pMe->uLastError != QCBOR_SUCCESS) {
4257 return;
4258 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004259
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004260 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004261}
4262
4263
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004264/*
4265 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004266
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004267 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004268
Laurence Lundblade93d89472020-10-03 22:30:50 -07004269 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4270 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004271
4272 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4273
Laurence Lundblade93d89472020-10-03 22:30:50 -07004274 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4275 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004276 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004277static QCBORError
4278Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004279{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004280 switch(pItem->uDataType) {
4281
4282 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004283 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004284 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004285 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004286 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004287 }
4288 break;
4289
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004290 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004291 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004292 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004293 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004294 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004295 }
4296 break;
4297
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004298#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4299 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004300 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004301 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004302 pItem->val.expAndMantissa.nExponent,
4303 pnValue,
4304 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004305 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004306 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004307 }
4308 break;
4309
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004310 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004311 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004312 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004313 pItem->val.expAndMantissa.nExponent,
4314 pnValue,
4315 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004316 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004317 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004318 }
4319 break;
4320
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004321 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004322 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004323 int64_t nMantissa;
4324 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004325 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4326 if(uErr) {
4327 return uErr;
4328 }
4329 return ExponentiateNN(nMantissa,
4330 pItem->val.expAndMantissa.nExponent,
4331 pnValue,
4332 Exponentitate10);
4333 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004334 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004335 }
4336 break;
4337
4338 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004339 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004340 int64_t nMantissa;
4341 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004342 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4343 if(uErr) {
4344 return uErr;
4345 }
4346 return ExponentiateNN(nMantissa,
4347 pItem->val.expAndMantissa.nExponent,
4348 pnValue,
4349 Exponentitate10);
4350 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004351 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004352 }
4353 break;
4354
4355 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004356 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004357 int64_t nMantissa;
4358 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004359 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4360 if(uErr) {
4361 return uErr;
4362 }
4363 return ExponentiateNN(nMantissa,
4364 pItem->val.expAndMantissa.nExponent,
4365 pnValue,
4366 Exponentitate2);
4367 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004368 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004369 }
4370 break;
4371
4372 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004373 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004374 int64_t nMantissa;
4375 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004376 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4377 if(uErr) {
4378 return uErr;
4379 }
4380 return ExponentiateNN(nMantissa,
4381 pItem->val.expAndMantissa.nExponent,
4382 pnValue,
4383 Exponentitate2);
4384 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004385 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004386 }
4387 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004388#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4389
Laurence Lundbladee6430642020-03-14 21:15:44 -07004390
Laurence Lundbladec4537442020-04-14 18:53:22 -07004391 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004392 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004393}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004394
4395
Laurence Lundbladec4537442020-04-14 18:53:22 -07004396/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004397 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004398 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004399void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004400{
4401 QCBORItem Item;
4402
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004403 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004404
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004405 if(pMe->uLastError == QCBOR_SUCCESS) {
4406 // The above conversion succeeded
4407 return;
4408 }
4409
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004410 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004411 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004412 return;
4413 }
4414
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004415 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004416}
4417
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004418
4419/*
4420Public function, see header qcbor/qcbor_decode.h file
4421*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004422void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4423 int64_t nLabel,
4424 uint32_t uConvertTypes,
4425 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004426{
4427 QCBORItem Item;
4428
Laurence Lundblade93d89472020-10-03 22:30:50 -07004429 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4430 nLabel,
4431 uConvertTypes,
4432 pnValue,
4433 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004434
4435 if(pMe->uLastError == QCBOR_SUCCESS) {
4436 // The above conversion succeeded
4437 return;
4438 }
4439
4440 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4441 // The above conversion failed in a way that code below can't correct
4442 return;
4443 }
4444
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004445 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004446}
4447
4448
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004449/*
4450Public function, see header qcbor/qcbor_decode.h file
4451*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004452void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4453 const char *szLabel,
4454 uint32_t uConvertTypes,
4455 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004456{
4457 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004458 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4459 szLabel,
4460 uConvertTypes,
4461 pnValue,
4462 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004463
4464 if(pMe->uLastError == QCBOR_SUCCESS) {
4465 // The above conversion succeeded
4466 return;
4467 }
4468
4469 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4470 // The above conversion failed in a way that code below can't correct
4471 return;
4472 }
4473
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004474 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004475}
4476
4477
Laurence Lundblade93d89472020-10-03 22:30:50 -07004478static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004479{
4480 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004481 case QCBOR_TYPE_DOUBLE:
4482 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004483#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004484 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004485 // Can't use llround here because it will not convert values
4486 // greater than INT64_MAX and less than UINT64_MAX that
4487 // need to be converted so it is more complicated.
4488 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4489 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4490 if(isnan(pItem->val.dfnum)) {
4491 return QCBOR_ERR_FLOAT_EXCEPTION;
4492 } else if(pItem->val.dfnum < 0) {
4493 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4494 } else {
4495 double dRounded = round(pItem->val.dfnum);
4496 // See discussion in DecodeDateEpoch() for
4497 // explanation of - 0x7ff
4498 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4499 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4500 }
4501 *puValue = (uint64_t)dRounded;
4502 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004503 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004504 if(isnan(pItem->val.fnum)) {
4505 return QCBOR_ERR_FLOAT_EXCEPTION;
4506 } else if(pItem->val.fnum < 0) {
4507 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4508 } else {
4509 float fRounded = roundf(pItem->val.fnum);
4510 // See discussion in DecodeDateEpoch() for
4511 // explanation of - 0x7ff
4512 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4513 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4514 }
4515 *puValue = (uint64_t)fRounded;
4516 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004517 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004518 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4519 // round() and roundf() shouldn't result in exceptions here, but
4520 // catch them to be robust and thorough. Don't try to
4521 // distinguish between the various exceptions because it seems
4522 // they vary by CPU, compiler and OS.
4523 return QCBOR_ERR_FLOAT_EXCEPTION;
4524 }
4525
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004526 } else {
4527 return QCBOR_ERR_UNEXPECTED_TYPE;
4528 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004529#else
4530 return QCBOR_ERR_HW_FLOAT_DISABLED;
4531#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004532 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004533
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004534 case QCBOR_TYPE_INT64:
4535 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4536 if(pItem->val.int64 >= 0) {
4537 *puValue = (uint64_t)pItem->val.int64;
4538 } else {
4539 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4540 }
4541 } else {
4542 return QCBOR_ERR_UNEXPECTED_TYPE;
4543 }
4544 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004545
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004546 case QCBOR_TYPE_UINT64:
4547 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4548 *puValue = pItem->val.uint64;
4549 } else {
4550 return QCBOR_ERR_UNEXPECTED_TYPE;
4551 }
4552 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004553
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004554 default:
4555 return QCBOR_ERR_UNEXPECTED_TYPE;
4556 }
4557
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004558 return QCBOR_SUCCESS;
4559}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004560
4561
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004562void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004563 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004564 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004565 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004566{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004567 if(pMe->uLastError != QCBOR_SUCCESS) {
4568 return;
4569 }
4570
Laurence Lundbladec4537442020-04-14 18:53:22 -07004571 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004572
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004573 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4574 if(uError) {
4575 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004576 return;
4577 }
4578
Laurence Lundbladea826c502020-05-10 21:07:00 -07004579 if(pItem) {
4580 *pItem = Item;
4581 }
4582
Laurence Lundblade93d89472020-10-03 22:30:50 -07004583 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004584}
4585
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004586
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004587void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004588 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004589 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004590 uint64_t *puValue,
4591 QCBORItem *pItem)
4592{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004593 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004594 if(pMe->uLastError != QCBOR_SUCCESS) {
4595 return;
4596 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004597
Laurence Lundblade93d89472020-10-03 22:30:50 -07004598 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004599}
4600
4601
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004602void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004603 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004604 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004605 uint64_t *puValue,
4606 QCBORItem *pItem)
4607{
4608 if(pMe->uLastError != QCBOR_SUCCESS) {
4609 return;
4610 }
4611
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004612 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004613 if(pMe->uLastError != QCBOR_SUCCESS) {
4614 return;
4615 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004616
Laurence Lundblade93d89472020-10-03 22:30:50 -07004617 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004618}
4619
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004620
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004621
Laurence Lundblade93d89472020-10-03 22:30:50 -07004622static QCBORError
4623UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004624{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004625 switch(pItem->uDataType) {
4626
4627 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004628 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004629 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4630 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004631 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004632 }
4633 break;
4634
4635 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004636 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004637 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4638 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004639 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004640 }
4641 break;
4642
4643#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4644
4645 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004646 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004647 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004648 pItem->val.expAndMantissa.nExponent,
4649 puValue,
4650 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004651 } 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 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004657 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004658 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4659 pItem->val.expAndMantissa.nExponent,
4660 puValue,
4661 Exponentitate2);
4662 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004663 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004664 }
4665 break;
4666
4667 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004668 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004669 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004670 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004671 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004672 if(uErr != QCBOR_SUCCESS) {
4673 return uErr;
4674 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004675 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004676 pItem->val.expAndMantissa.nExponent,
4677 puValue,
4678 Exponentitate10);
4679 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004680 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004681 }
4682 break;
4683
4684 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004685 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004686 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4687 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004688 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004689 }
4690 break;
4691
4692 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004693 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004694 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004695 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004696 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004697 if(uErr != QCBOR_SUCCESS) {
4698 return uErr;
4699 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004700 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004701 pItem->val.expAndMantissa.nExponent,
4702 puValue,
4703 Exponentitate2);
4704 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004705 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004706 }
4707 break;
4708
4709 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004710 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004711 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4712 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004713 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004714 }
4715 break;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004716#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004717 default:
4718 return QCBOR_ERR_UNEXPECTED_TYPE;
4719 }
4720}
4721
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004722
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004723/*
4724 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004725 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004726void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004727{
4728 QCBORItem Item;
4729
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004730 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004731
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004732 if(pMe->uLastError == QCBOR_SUCCESS) {
4733 // The above conversion succeeded
4734 return;
4735 }
4736
4737 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4738 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004739 return;
4740 }
4741
Laurence Lundblade93d89472020-10-03 22:30:50 -07004742 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004743}
4744
Laurence Lundbladec4537442020-04-14 18:53:22 -07004745
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004746/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004747 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004748*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004749void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004750 int64_t nLabel,
4751 uint32_t uConvertTypes,
4752 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004753{
4754 QCBORItem Item;
4755
Laurence Lundblade93d89472020-10-03 22:30:50 -07004756 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
4757 nLabel,
4758 uConvertTypes,
4759 puValue,
4760 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004761
4762 if(pMe->uLastError == QCBOR_SUCCESS) {
4763 // The above conversion succeeded
4764 return;
4765 }
4766
4767 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4768 // The above conversion failed in a way that code below can't correct
4769 return;
4770 }
4771
Laurence Lundblade93d89472020-10-03 22:30:50 -07004772 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004773}
4774
4775
4776/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004777 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004778*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004779void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004780 const char *szLabel,
4781 uint32_t uConvertTypes,
4782 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004783{
4784 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004785 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
4786 szLabel,
4787 uConvertTypes,
4788 puValue,
4789 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004790
4791 if(pMe->uLastError == QCBOR_SUCCESS) {
4792 // The above conversion succeeded
4793 return;
4794 }
4795
4796 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4797 // The above conversion failed in a way that code below can't correct
4798 return;
4799 }
4800
Laurence Lundblade93d89472020-10-03 22:30:50 -07004801 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004802}
4803
4804
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004805
4806
Laurence Lundblade9b334962020-08-27 10:55:53 -07004807static QCBORError ConvertDouble(const QCBORItem *pItem,
4808 uint32_t uConvertTypes,
4809 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004810{
4811 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004812 case QCBOR_TYPE_FLOAT:
4813#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4814 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4815 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004816 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004817 *pdValue = (double)pItem->val.fnum;
4818 } else {
4819 return QCBOR_ERR_UNEXPECTED_TYPE;
4820 }
4821 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004822#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004823 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004824#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004825 break;
4826
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004827 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004828 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4829 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004830 *pdValue = pItem->val.dfnum;
4831 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004832 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004833 }
4834 }
4835 break;
4836
4837 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004838#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004839 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004840 // A simple cast seems to do the job with no worry of exceptions.
4841 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004842 *pdValue = (double)pItem->val.int64;
4843
4844 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004845 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004846 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004847#else
4848 return QCBOR_ERR_HW_FLOAT_DISABLED;
4849#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004850 break;
4851
4852 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004853#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004854 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004855 // A simple cast seems to do the job with no worry of exceptions.
4856 // There will be precision loss for some values.
4857 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004858 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004859 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004860 }
4861 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004862#else
4863 return QCBOR_ERR_HW_FLOAT_DISABLED;
4864#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004865
4866 default:
4867 return QCBOR_ERR_UNEXPECTED_TYPE;
4868 }
4869
4870 return QCBOR_SUCCESS;
4871}
4872
4873
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004874void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004875 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004876 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004877 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004878{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004879 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004880 return;
4881 }
4882
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004883 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004884
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004885 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004886 if(uError) {
4887 pMe->uLastError = (uint8_t)uError;
4888 return;
4889 }
4890
4891 if(pItem) {
4892 *pItem = Item;
4893 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004894
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004895 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004896}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004897
Laurence Lundbladec4537442020-04-14 18:53:22 -07004898
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004899void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4900 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004901 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004902 double *pdValue,
4903 QCBORItem *pItem)
4904{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004905 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004906 if(pMe->uLastError != QCBOR_SUCCESS) {
4907 return;
4908 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004909
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004910 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004911}
4912
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004913
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004914void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4915 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004916 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004917 double *pdValue,
4918 QCBORItem *pItem)
4919{
4920 if(pMe->uLastError != QCBOR_SUCCESS) {
4921 return;
4922 }
4923
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004924 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004925 if(pMe->uLastError != QCBOR_SUCCESS) {
4926 return;
4927 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004928
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004929 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004930}
4931
4932
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004933#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004934static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4935{
4936 double dResult;
4937
4938 dResult = 0.0;
4939 const uint8_t *pByte = BigNum.ptr;
4940 size_t uLen = BigNum.len;
4941 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004942 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004943 while(uLen--) {
4944 dResult = (dResult * 256.0) + (double)*pByte++;
4945 }
4946
4947 return dResult;
4948}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004949#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4950
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004951
Laurence Lundblade93d89472020-10-03 22:30:50 -07004952static QCBORError
4953DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004954{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004955#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004956 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004957 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4958
4959 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004960 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004961
4962#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004963 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004964 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004965 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004966 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4967 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4968 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004969 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004970 }
4971 break;
4972
4973 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004974 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004975 // Underflow gives 0, overflow gives infinity
4976 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4977 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004978 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004979 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004980 }
4981 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004982#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004983
4984 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004985 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004986 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4987 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004988 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004989 }
4990 break;
4991
4992 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004993 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004994 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004995 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004996 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004997 }
4998 break;
4999
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005000#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005001 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005002 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005003 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5004 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5005 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005006 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005007 }
5008 break;
5009
5010 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005011 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005012 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5013 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5014 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005015 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005016 }
5017 break;
5018
5019 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005020 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005021 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5022 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5023 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005024 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005025 }
5026 break;
5027
5028 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005029 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07005030 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005031 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5032 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005033 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005034 }
5035 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005036#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
5037
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005038 default:
5039 return QCBOR_ERR_UNEXPECTED_TYPE;
5040 }
5041
5042 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005043
5044#else
5045 (void)pItem;
5046 (void)uConvertTypes;
5047 (void)pdValue;
5048 return QCBOR_ERR_HW_FLOAT_DISABLED;
5049#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5050
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005051}
5052
5053
5054/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005055 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005056*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005057void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
5058 uint32_t uConvertTypes,
5059 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005060{
5061
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005062 QCBORItem Item;
5063
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005064 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005065
5066 if(pMe->uLastError == QCBOR_SUCCESS) {
5067 // The above conversion succeeded
5068 return;
5069 }
5070
5071 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5072 // The above conversion failed in a way that code below can't correct
5073 return;
5074 }
5075
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005076 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005077}
5078
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005079
5080/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005081 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005082*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005083void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
5084 int64_t nLabel,
5085 uint32_t uConvertTypes,
5086 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005087{
5088 QCBORItem Item;
5089
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005090 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005091
5092 if(pMe->uLastError == QCBOR_SUCCESS) {
5093 // The above conversion succeeded
5094 return;
5095 }
5096
5097 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5098 // The above conversion failed in a way that code below can't correct
5099 return;
5100 }
5101
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005102 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005103}
5104
5105
5106/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005107 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005108*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005109void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
5110 const char *szLabel,
5111 uint32_t uConvertTypes,
5112 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005113{
5114 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005115 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005116
5117 if(pMe->uLastError == QCBOR_SUCCESS) {
5118 // The above conversion succeeded
5119 return;
5120 }
5121
5122 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5123 // The above conversion failed in a way that code below can't correct
5124 return;
5125 }
5126
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005127 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005128}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005129
5130
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005131
5132
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005133#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005134static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
5135{
5136 while((uInt & 0xff00000000000000UL) == 0) {
5137 uInt = uInt << 8;
5138 };
5139
5140 UsefulOutBuf UOB;
5141
5142 UsefulOutBuf_Init(&UOB, Buffer);
5143
5144 while(uInt) {
5145 const uint64_t xx = uInt & 0xff00000000000000UL;
5146 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
5147 uInt = uInt << 8;
5148 (void)xx;
5149 }
5150
5151 return UsefulOutBuf_OutUBuf(&UOB);
5152}
5153
5154
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005155static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
5156 TagSpecification TagSpec,
5157 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005158{
5159 QCBORError uErr;
5160 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005161 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07005162 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005163 if(uErr != QCBOR_SUCCESS) {
5164 goto Done;
5165 }
5166
5167 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
5168 break; // Successful exit. Moving on to finish decoding.
5169 }
5170
5171 // The item is an array, which means an undecoded
5172 // mantissa and exponent, so decode it. It will then
5173 // have a different type and exit the loop if.
5174 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
5175 if(uErr != QCBOR_SUCCESS) {
5176 goto Done;
5177 }
5178
5179 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07005180 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005181 }
5182Done:
5183 return uErr;
5184}
5185
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005186
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005187static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005188 TagSpecification TagSpec,
5189 QCBORItem *pItem,
5190 int64_t *pnMantissa,
5191 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005192{
5193 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005194
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005195 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005196 if(uErr != QCBOR_SUCCESS) {
5197 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005198 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005199
Laurence Lundblade9b334962020-08-27 10:55:53 -07005200 switch (pItem->uDataType) {
5201
5202 case QCBOR_TYPE_DECIMAL_FRACTION:
5203 case QCBOR_TYPE_BIGFLOAT:
5204 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5205 *pnExponent = pItem->val.expAndMantissa.nExponent;
5206 break;
5207
5208 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5209 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5210 *pnExponent = pItem->val.expAndMantissa.nExponent;
5211 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5212 break;
5213
5214 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5215 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5216 *pnExponent = pItem->val.expAndMantissa.nExponent;
5217 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5218 break;
5219
5220 default:
5221 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5222 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005223
5224 Done:
5225 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005226}
5227
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005228
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005229static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005230 TagSpecification TagSpec,
5231 QCBORItem *pItem,
5232 UsefulBuf BufferForMantissa,
5233 UsefulBufC *pMantissa,
5234 bool *pbIsNegative,
5235 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005236{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005237 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005238
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005239 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005240 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005241 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005242 }
5243
5244 uint64_t uMantissa;
5245
5246 switch (pItem->uDataType) {
5247
5248 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005249 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005250 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5251 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5252 *pbIsNegative = false;
5253 } else {
5254 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5255 *pbIsNegative = true;
5256 }
5257 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5258 *pnExponent = pItem->val.expAndMantissa.nExponent;
5259 break;
5260
5261 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005262 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005263 *pnExponent = pItem->val.expAndMantissa.nExponent;
5264 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5265 *pbIsNegative = false;
5266 break;
5267
5268 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005269 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005270 *pnExponent = pItem->val.expAndMantissa.nExponent;
5271 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5272 *pbIsNegative = true;
5273 break;
5274
5275 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005276 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005277 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005278
5279Done:
5280 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005281}
5282
5283
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005284/*
5285 Public function, see header qcbor/qcbor_decode.h file
5286*/
5287void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5288 uint8_t uTagRequirement,
5289 int64_t *pnMantissa,
5290 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005291{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005292 if(pMe->uLastError != QCBOR_SUCCESS) {
5293 return;
5294 }
5295
5296 QCBORItem Item;
5297 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5298 if(uError) {
5299 pMe->uLastError = (uint8_t)uError;
5300 return;
5301 }
5302
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005303 const TagSpecification TagSpec =
5304 {
5305 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005306 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5307 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5308 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005309 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005310
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005311 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005312}
5313
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005314
5315/*
5316 Public function, see header qcbor/qcbor_decode.h file
5317*/
5318void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005319 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005320 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005321 int64_t *pnMantissa,
5322 int64_t *pnExponent)
5323{
5324 if(pMe->uLastError != QCBOR_SUCCESS) {
5325 return;
5326 }
5327
5328 QCBORItem Item;
5329 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5330
5331 const TagSpecification TagSpec =
5332 {
5333 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005334 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5335 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5336 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005337 };
5338
5339 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5340}
5341
5342
5343/*
5344 Public function, see header qcbor/qcbor_decode.h file
5345*/
5346void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005347 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005348 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005349 int64_t *pnMantissa,
5350 int64_t *pnExponent)
5351{
5352 if(pMe->uLastError != QCBOR_SUCCESS) {
5353 return;
5354 }
5355
5356 QCBORItem Item;
5357 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5358
5359 const TagSpecification TagSpec =
5360 {
5361 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005362 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5363 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5364 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005365 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005366
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005367 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5368}
5369
5370
5371/*
5372 Public function, see header qcbor/qcbor_decode.h file
5373*/
5374void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5375 uint8_t uTagRequirement,
5376 UsefulBuf MantissaBuffer,
5377 UsefulBufC *pMantissa,
5378 bool *pbMantissaIsNegative,
5379 int64_t *pnExponent)
5380{
5381 if(pMe->uLastError != QCBOR_SUCCESS) {
5382 return;
5383 }
5384
5385 QCBORItem Item;
5386 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5387 if(uError) {
5388 pMe->uLastError = (uint8_t)uError;
5389 return;
5390 }
5391
5392 const TagSpecification TagSpec =
5393 {
5394 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005395 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5396 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5397 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005398 };
5399
Laurence Lundblade93d89472020-10-03 22:30:50 -07005400 ProcessMantissaAndExponentBig(pMe,
5401 TagSpec,
5402 &Item,
5403 MantissaBuffer,
5404 pMantissa,
5405 pbMantissaIsNegative,
5406 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005407}
5408
5409
5410/*
5411 Public function, see header qcbor/qcbor_decode.h file
5412*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005413void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005414 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005415 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005416 UsefulBuf BufferForMantissa,
5417 UsefulBufC *pMantissa,
5418 bool *pbIsNegative,
5419 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005420{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005421 if(pMe->uLastError != QCBOR_SUCCESS) {
5422 return;
5423 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005424
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005425 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005426 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005427 if(pMe->uLastError != QCBOR_SUCCESS) {
5428 return;
5429 }
5430
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005431 const TagSpecification TagSpec =
5432 {
5433 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005434 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5435 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5436 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005437 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005438
Laurence Lundblade93d89472020-10-03 22:30:50 -07005439 ProcessMantissaAndExponentBig(pMe,
5440 TagSpec,
5441 &Item,
5442 BufferForMantissa,
5443 pMantissa,
5444 pbIsNegative,
5445 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005446}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005447
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005448
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005449/*
5450 Public function, see header qcbor/qcbor_decode.h file
5451*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005452void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005453 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005454 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005455 UsefulBuf BufferForMantissa,
5456 UsefulBufC *pMantissa,
5457 bool *pbIsNegative,
5458 int64_t *pnExponent)
5459{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005460 if(pMe->uLastError != QCBOR_SUCCESS) {
5461 return;
5462 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005463
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005464 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005465 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5466 if(pMe->uLastError != QCBOR_SUCCESS) {
5467 return;
5468 }
5469
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005470 const TagSpecification TagSpec =
5471 {
5472 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005473 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5474 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5475 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005476 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005477
5478 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5479}
5480
5481
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005482/*
5483 Public function, see header qcbor/qcbor_decode.h file
5484*/
5485void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5486 uint8_t uTagRequirement,
5487 int64_t *pnMantissa,
5488 int64_t *pnExponent)
5489{
5490 if(pMe->uLastError != QCBOR_SUCCESS) {
5491 return;
5492 }
5493
5494 QCBORItem Item;
5495 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5496 if(uError) {
5497 pMe->uLastError = (uint8_t)uError;
5498 return;
5499 }
5500 const TagSpecification TagSpec =
5501 {
5502 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005503 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5504 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5505 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005506 };
5507
5508 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5509}
5510
5511
5512/*
5513 Public function, see header qcbor/qcbor_decode.h file
5514*/
5515void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005516 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005517 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005518 int64_t *pnMantissa,
5519 int64_t *pnExponent)
5520{
5521 if(pMe->uLastError != QCBOR_SUCCESS) {
5522 return;
5523 }
5524
5525 QCBORItem Item;
5526 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5527 if(pMe->uLastError != QCBOR_SUCCESS) {
5528 return;
5529 }
5530
5531 const TagSpecification TagSpec =
5532 {
5533 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005534 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5535 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5536 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005537 };
5538
5539 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5540}
5541
5542
5543/*
5544 Public function, see header qcbor/qcbor_decode.h file
5545*/
5546void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005547 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005548 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005549 int64_t *pnMantissa,
5550 int64_t *pnExponent)
5551{
5552 if(pMe->uLastError != QCBOR_SUCCESS) {
5553 return;
5554 }
5555
5556 QCBORItem Item;
5557 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5558 if(pMe->uLastError != QCBOR_SUCCESS) {
5559 return;
5560 }
5561
5562 const TagSpecification TagSpec =
5563 {
5564 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005565 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5566 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5567 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005568 };
5569
5570 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5571}
5572
5573
5574/*
5575 Public function, see header qcbor/qcbor_decode.h file
5576*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005577void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5578 uint8_t uTagRequirement,
5579 UsefulBuf MantissaBuffer,
5580 UsefulBufC *pMantissa,
5581 bool *pbMantissaIsNegative,
5582 int64_t *pnExponent)
5583{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005584 if(pMe->uLastError != QCBOR_SUCCESS) {
5585 return;
5586 }
5587
5588 QCBORItem Item;
5589 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5590 if(uError) {
5591 pMe->uLastError = (uint8_t)uError;
5592 return;
5593 }
5594
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005595 const TagSpecification TagSpec =
5596 {
5597 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005598 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5599 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5600 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005601 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005602
5603 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005604}
5605
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005606
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005607/*
5608 Public function, see header qcbor/qcbor_decode.h file
5609*/
5610void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005611 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005612 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005613 UsefulBuf BufferForMantissa,
5614 UsefulBufC *pMantissa,
5615 bool *pbIsNegative,
5616 int64_t *pnExponent)
5617{
5618 if(pMe->uLastError != QCBOR_SUCCESS) {
5619 return;
5620 }
5621
5622 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005623 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5624 if(pMe->uLastError != QCBOR_SUCCESS) {
5625 return;
5626 }
5627
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005628 const TagSpecification TagSpec =
5629 {
5630 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005631 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5632 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5633 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005634 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005635
Laurence Lundblade93d89472020-10-03 22:30:50 -07005636 ProcessMantissaAndExponentBig(pMe,
5637 TagSpec,
5638 &Item,
5639 BufferForMantissa,
5640 pMantissa,
5641 pbIsNegative,
5642 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005643}
5644
5645
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005646/*
5647 Public function, see header qcbor/qcbor_decode.h file
5648*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005649void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005650 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005651 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005652 UsefulBuf BufferForMantissa,
5653 UsefulBufC *pMantissa,
5654 bool *pbIsNegative,
5655 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005656{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005657 if(pMe->uLastError != QCBOR_SUCCESS) {
5658 return;
5659 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005660
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005661 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005662 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5663 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005664 return;
5665 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005666
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005667 const TagSpecification TagSpec =
5668 {
5669 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005670 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5671 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5672 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005673 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005674
Laurence Lundblade93d89472020-10-03 22:30:50 -07005675 ProcessMantissaAndExponentBig(pMe,
5676 TagSpec,
5677 &Item,
5678 BufferForMantissa,
5679 pMantissa,
5680 pbIsNegative,
5681 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005682}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005683
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005684#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */