blob: 7adfb5f488472bddb7985ebffcbc98cc9ad36489 [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 Lundbladeee851742020-01-08 08:37:05 -08003 Copyright (c) 2018-2020, 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
514StringAllocator_Free(const QCORInternalAllocator *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
522StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
523 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
530StringAllocator_Allocate(const QCORInternalAllocator *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
536StringAllocator_Destruct(const QCORInternalAllocator *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 Lundbladeee851742020-01-08 08:37:05 -0800556void QCBORDecode_Init(QCBORDecodeContext *me,
Laurence Lundblade6474c982020-12-26 22:14:34 -0800557 UsefulBufC EncodedCBOR,
558 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700559{
560 memset(me, 0, sizeof(QCBORDecodeContext));
561 UsefulInputBuf_Init(&(me->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 Lundbladee6bcef12020-04-01 10:56:27 -0700565 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700566 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700567 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700568 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700569 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700570}
571
572
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800573#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
574
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700575/*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800576 * Public function, see header file
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700577 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800578void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
579 QCBORStringAllocate pfAllocateFunction,
Laurence Lundblade6474c982020-12-26 22:14:34 -0800580 void *pAllocateContext,
581 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700582{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800583 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
584 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
585 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700586}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800587#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700588
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800589
Laurence Lundblade6474c982020-12-26 22:14:34 -0800590
591
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800592/*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800593 * Deprecated public function, see header file
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800594 */
Laurence Lundblade6474c982020-12-26 22:14:34 -0800595void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800596 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700597{
Laurence Lundblade6474c982020-12-26 22:14:34 -0800598 /* This does nothing now. It is retained for backwards compatibility */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700599 (void)pMe;
600 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700601}
602
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700603
Laurence Lundblade1c929722020-12-27 02:44:57 -0800604/**
605 * @brief Decode the CBOR head, the type and argument.
606 *
607 * @param[in] pUInBuf The input buffer to read from.
608 * @param[out] pnMajorType The decoded major type.
609 * @param[out] puArgument The decoded argument.
610 * @param[out] pnAdditionalInfo The decoded Lower 5 bits of initial byte.
611 *
612 * @retval QCBOR_ERR_UNSUPPORTED
613 * @retval QCBOR_ERR_HIT_END
614 *
615 * This decodes the CBOR "head" that every CBOR data item has. See
616 * longer explaination of the head in documentation for
617 * QCBOREncode_EncodeHead().
618 *
619 * This does the network->host byte order conversion. The conversion
620 * here also results in the conversion for floats in addition to that
621 * for lengths, tags and integer values.
622 *
623 * The int type is preferred to uint8_t for some variables as this
624 * avoids integer promotions, can reduce code size and makes static
625 * analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700626 */
Laurence Lundblade1c929722020-12-27 02:44:57 -0800627static inline QCBORError
628DecodeHead(UsefulInputBuf *pUInBuf,
629 int *pnMajorType,
630 uint64_t *puArgument,
631 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700632{
Laurence Lundblade1c929722020-12-27 02:44:57 -0800633 QCBORError uReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800634
Laurence Lundblade1c929722020-12-27 02:44:57 -0800635 /* Get the initial byte that every CBOR data item has and break it
636 * down. */
637 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800638 const int nTmpMajorType = nInitialByte >> 5;
639 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800640
Laurence Lundblade1c929722020-12-27 02:44:57 -0800641 /* Where the argument accumulates */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800642 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800643
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800644 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800645 /* Need to get 1,2,4 or 8 additional argument bytes. Map
646 * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
647 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800648 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800649
Laurence Lundblade1c929722020-12-27 02:44:57 -0800650 /* Loop getting all the bytes in the argument */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800651 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800652 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800653 /* This shift and add gives the endian conversion. */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800654 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
655 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800656 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800657 /* The reserved and thus-far unused additional info values */
658 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800659 goto Done;
660 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800661 /* Less than 24, additional info is argument or 31, an
662 * indefinite length. No more bytes to get.
663 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800664 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700665 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800666
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700667 if(UsefulInputBuf_GetError(pUInBuf)) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800668 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700669 goto Done;
670 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800671
Laurence Lundblade1c929722020-12-27 02:44:57 -0800672 /* All successful if arrived here. */
673 uReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800674 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800675 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800676 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800677
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700678Done:
Laurence Lundblade1c929722020-12-27 02:44:57 -0800679 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700680}
681
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800682
Laurence Lundblade1c929722020-12-27 02:44:57 -0800683/**
684 * @brief Decode integer types, major types 0 and 1.
685 *
686 * @param[in] nMajorType The CBOR major type (0 or 1).
687 * @param[in] uArgument The argument from the head.
688 * @param[out] pDecodedItem The filled in decoded item.
689 *
690 * @retval QCBOR_ERR_INT_OVERFLOW
691 *
692 * Must only be called when major type is 0 or 1.
693 *
694 * CBOR doesn't explicitly specify two's compliment for integers but
695 * all CPUs use it these days and the test vectors in the RFC are
696 * so. All integers in the CBOR structure are positive and the major
697 * type indicates positive or negative. CBOR can express positive
698 * integers up to 2^x - 1 where x is the number of bits and negative
699 * integers down to 2^x. Note that negative numbers can be one more
700 * away from zero than positive. Stdint, as far as I can tell, uses
701 * two's compliment to represent negative integers.
702 *
703 * See http://www.unix.org/whitepapers/64bit.html for reasons int is
704 * used carefully here, and in particular why it isn't used in the
705 * public interface. Also see
706 * https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
707 *
708 * Int is used for values that need less than 16-bits and would be
709 * subject to integer promotion and result in complaining from static
710 * analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700711 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700712static inline QCBORError
Laurence Lundblade1c929722020-12-27 02:44:57 -0800713DecodeInteger(int nMajorType, uint64_t uArgument, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700714{
Laurence Lundblade1c929722020-12-27 02:44:57 -0800715 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800716
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700717 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800718 if (uArgument <= INT64_MAX) {
719 pDecodedItem->val.int64 = (int64_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700720 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800721
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700722 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800723 pDecodedItem->val.uint64 = uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700724 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700725 }
Laurence Lundblade1c929722020-12-27 02:44:57 -0800726
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700727 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800728 if(uArgument <= INT64_MAX) {
729 /* CBOR's representation of negative numbers lines up with
730 * the two-compliment representation. A negative integer has
731 * one more in range than a positive integer. INT64_MIN is
732 * equal to (-INT64_MAX) - 1.
733 */
734 pDecodedItem->val.int64 = (-(int64_t)uArgument) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700735 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800736
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700737 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800738 /* C can't represent a negative integer in this range so it
739 * is an error.
740 */
741 uReturn = QCBOR_ERR_INT_OVERFLOW;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700742 }
743 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800744
Laurence Lundblade1c929722020-12-27 02:44:57 -0800745 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700746}
747
Laurence Lundblade1c929722020-12-27 02:44:57 -0800748
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700749// Make sure #define value line up as DecodeSimple counts on this.
750#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
751#error QCBOR_TYPE_FALSE macro value wrong
752#endif
753
754#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
755#error QCBOR_TYPE_TRUE macro value wrong
756#endif
757
758#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
759#error QCBOR_TYPE_NULL macro value wrong
760#endif
761
762#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
763#error QCBOR_TYPE_UNDEF macro value wrong
764#endif
765
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700766#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
767#error QCBOR_TYPE_BREAK macro value wrong
768#endif
769
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700770#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
771#error QCBOR_TYPE_DOUBLE macro value wrong
772#endif
773
774#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
775#error QCBOR_TYPE_FLOAT macro value wrong
776#endif
777
778/*
779 Decode true, false, floats, break...
Laurence Lundblade9b334962020-08-27 10:55:53 -0700780
781 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
782
783 @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700784 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700785static inline QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800786DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700787{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700788 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800789
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700790 // uAdditionalInfo is 5 bits from the initial byte. Compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800791 // above make sure uAdditionalInfo values line up with uDataType values.
Laurence Lundblade93d89472020-10-03 22:30:50 -0700792 // DecodeTypeAndNumber() never returns an AdditionalInfo > 0x1f so cast
793 // is safe
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800794 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800795
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800796 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800797 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
798 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800799
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700800 case HALF_PREC_FLOAT: // 25
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700801#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700802 // Half-precision is returned as a double.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700803 // The cast to uint16_t is safe because the encoded value
Laurence Lundblade9682a532020-06-06 18:33:04 -0700804 // was 16 bits. It was widened to 64 bits to be passed in here.
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700805 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
806 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800807#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700808 nReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800809#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700810 break;
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700811 case SINGLE_PREC_FLOAT: // 26
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700812 // Single precision is normally returned as a double
813 // since double is widely supported, there is no loss of
814 // precision, it makes it easy for the caller in
815 // most cases and it can be converted back to single
816 // with no loss of precision
817 //
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700818 // The cast to uint32_t is safe because the encoded value
Laurence Lundblade8fa7d5d2020-07-11 16:30:47 -0700819 // was 32 bits. It was widened to 64 bits to be passed in here.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700820 {
821 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
822#ifndef QCBOR_DISABLE_FLOAT_HW_USE
823 // In the normal case, use HW to convert float to double.
824 pDecodedItem->val.dfnum = (double)f;
825 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800826#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700827 // Use of float HW is disabled, return as a float.
828 pDecodedItem->val.fnum = f;
829 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
830
831 // IEEE754_FloatToDouble() could be used here to return
832 // as a double, but it adds object code and most likely
833 // anyone disabling FLOAT HW use doesn't care about
834 // floats and wants to save object code.
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800835#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700836 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700837 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700838
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700839 case DOUBLE_PREC_FLOAT: // 27
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700840 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700841 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700842 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800843
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700844 case CBOR_SIMPLEV_FALSE: // 20
845 case CBOR_SIMPLEV_TRUE: // 21
846 case CBOR_SIMPLEV_NULL: // 22
847 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700848 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700849 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800850
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700851 case CBOR_SIMPLEV_ONEBYTE: // 24
852 if(uNumber <= CBOR_SIMPLE_BREAK) {
853 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700854 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700855 goto Done;
856 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800857 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700858 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800859
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700860 default: // 0-19
861 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800862 /*
863 DecodeTypeAndNumber will make uNumber equal to
864 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
865 safe because the 2, 4 and 8 byte lengths of uNumber are in
866 the double/float cases above
867 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700868 pDecodedItem->val.uSimple = (uint8_t)uNumber;
869 break;
870 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800871
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700872Done:
873 return nReturn;
874}
875
876
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700877/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530878 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700879
880 @retval QCBOR_ERR_HIT_END
881
882 @retval QCBOR_ERR_STRING_ALLOCATE
883
884 @retval QCBOR_ERR_STRING_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700885 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700886static inline QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800887 uint64_t uStrLen,
888 UsefulInputBuf *pUInBuf,
889 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700890{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700891 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800892
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800893 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
894 // This check makes the casts to size_t below safe.
895
896 // 4 bytes less than the largest sizeof() so this can be tested by
897 // putting a SIZE_MAX length in the CBOR test input (no one will
898 // care the limit on strings is 4 bytes shorter).
899 if(uStrLen > SIZE_MAX-4) {
900 nReturn = QCBOR_ERR_STRING_TOO_LONG;
901 goto Done;
902 }
903
904 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530905 if(UsefulBuf_IsNULLC(Bytes)) {
906 // Failed to get the bytes for this string item
907 nReturn = QCBOR_ERR_HIT_END;
908 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700909 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530910
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800911#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800912 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530913 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800914 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530915 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700916 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530917 goto Done;
918 }
919 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800920 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800921 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530922 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800923#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
924 (void)pAllocator;
925#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
926
927 // Normal case with no string allocator
928 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800929
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530930Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700931 return nReturn;
932}
933
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700934
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800935/* Map the CBOR major types for strings to the QCBOR types for strngs */
936static inline uint8_t MapStringMajorTypes(int nCBORMajorType)
937{
938 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
939 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
940 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800941
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800942 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
943 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
944 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700945
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800946 return (uint8_t)(nCBORMajorType + 4);
947}
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700948
949
Laurence Lundbladeee851742020-01-08 08:37:05 -0800950// Make sure the constants align as this is assumed by
951// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700952#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
953#error QCBOR_TYPE_ARRAY value not lined up with major type
954#endif
955#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
956#error QCBOR_TYPE_MAP value not lined up with major type
957#endif
958
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700959/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800960 This gets a single data item and decodes it including preceding
961 optional tagging. This does not deal with arrays and maps and nesting
962 except to decode the data item introducing them. Arrays and maps are
963 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800964
Laurence Lundbladeee851742020-01-08 08:37:05 -0800965 Errors detected here include: an array that is too long to decode,
966 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundblade9b334962020-08-27 10:55:53 -0700967
968 @retval QCBOR_ERR_UNSUPPORTED
969
970 @retval QCBOR_ERR_HIT_END
971
972 @retval QCBOR_ERR_INT_OVERFLOW
973
974 @retval QCBOR_ERR_STRING_ALLOCATE
975
976 @retval QCBOR_ERR_STRING_TOO_LONG
977
978 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
979
980 @retval QCBOR_ERR_BAD_TYPE_7
981
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700982 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800983static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
984 QCBORItem *pDecodedItem,
985 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700986{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700987 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800988
Laurence Lundbladeee851742020-01-08 08:37:05 -0800989 /*
990 Get the major type and the number. Number could be length of more
991 bytes or the value depending on the major type nAdditionalInfo is
992 an encoding of the length of the uNumber and is needed to decode
993 floats and doubles
994 */
Rob Gilton47cc9562020-08-10 12:03:38 +0100995 int nMajorType = 0;
Laurence Lundblade1c929722020-12-27 02:44:57 -0800996 uint64_t uArgument = 0;
Rob Gilton47cc9562020-08-10 12:03:38 +0100997 int nAdditionalInfo = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800998
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700999 memset(pDecodedItem, 0, sizeof(QCBORItem));
1000
Laurence Lundblade1c929722020-12-27 02:44:57 -08001001 nReturn = DecodeHead(pUInBuf, &nMajorType, &uArgument, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001002
Laurence Lundbladeee851742020-01-08 08:37:05 -08001003 // Error out here if we got into trouble on the type and number. The
1004 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001005 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001006 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001007 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001008
Laurence Lundbladeee851742020-01-08 08:37:05 -08001009 // At this point the major type and the value are valid. We've got
1010 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001011 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001012 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
1013 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001014 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001015 nReturn = QCBOR_ERR_BAD_INT;
1016 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -08001017 nReturn = DecodeInteger(nMajorType, uArgument, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001018 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001019 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001020
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001021 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
1022 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001023 pDecodedItem->uDataType = MapStringMajorTypes(nMajorType);
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001024 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001025 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001026 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -08001027 nReturn = DecodeBytes(pAllocator, uArgument, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001028 }
1029 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001030
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001031 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
1032 case CBOR_MAJOR_TYPE_MAP: // Major type 5
1033 // Record the number of items in the array or map
Laurence Lundblade1c929722020-12-27 02:44:57 -08001034 if(uArgument > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001035 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001036 goto Done;
1037 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001038 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001039#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -07001040 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001041#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1042 nReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
1043 break;
1044#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001045 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001046 // type conversion OK because of check above
Laurence Lundblade1c929722020-12-27 02:44:57 -08001047 pDecodedItem->val.uCount = (uint16_t)uArgument;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001048 }
Laurence Lundbladeee851742020-01-08 08:37:05 -08001049 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001050 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001051 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001052 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001053
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001054 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001055 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001056 nReturn = QCBOR_ERR_BAD_INT;
1057 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -08001058 pDecodedItem->val.uTagV = uArgument;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001059 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001060 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001061 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001062
Laurence Lundbladeee851742020-01-08 08:37:05 -08001063 case CBOR_MAJOR_TYPE_SIMPLE:
1064 // Major type 7, float, double, true, false, null...
Laurence Lundblade1c929722020-12-27 02:44:57 -08001065 nReturn = DecodeSimple(nAdditionalInfo, uArgument, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001066 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001067
Laurence Lundbladeee851742020-01-08 08:37:05 -08001068 default:
1069 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001070 nReturn = QCBOR_ERR_UNSUPPORTED;
1071 break;
1072 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001073
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001074Done:
1075 return nReturn;
1076}
1077
1078
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001079/**
1080 * @brief Process indefinite length strings
1081 *
1082 * @param[in] pMe Decoder context
1083 * @param[in,out] pDecodedItem The decoded item that work is done on.
1084 *
1085 * @retval QCBOR_ERR_UNSUPPORTED
1086 * @retval QCBOR_ERR_HIT_END
1087 * @retval QCBOR_ERR_INT_OVERFLOW
1088 * @retval QCBOR_ERR_STRING_ALLOCATE
1089 * @retval QCBOR_ERR_STRING_TOO_LONG
1090 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1091 * @retval QCBOR_ERR_BAD_TYPE_7
1092 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1093 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1094 *
1095 * If @c pDecodedItem is not an indefinite length string, this does nothing.
1096 *
1097 * If it is, this loops getting the subsequent chunks that make up the
1098 * string. The string allocator is used to make a contiguous buffer for
1099 * the chunks. When this completes @c pDecodedItem contains the
1100 * put-together string.
1101 *
1102 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001103 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001104static inline QCBORError
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001105GetNext_FullItem(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001106{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001107 /* Aproximate stack usage
1108 * 64-bit 32-bit
1109 * local vars 32 16
1110 * 2 UsefulBufs 32 16
1111 * QCBORItem 56 52
1112 * TOTAL 120 74
1113 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001114
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001115 /* The string allocator is used here for two purposes: 1)
1116 * coalescing the chunks of an indefinite length string, 2)
1117 * allocating storage for every string returned.
1118 *
1119 * The first use is below in this function. Indefinite length
1120 * strings cannot be processed at all without a string allocator.
1121 *
1122 * The second used is in DecodeBytes() which is called by
1123 * GetNext_Item() below. This second use unneccessary for most use
1124 * and only happens when requested in the call to
1125 * QCBORDecode_SetMemPool(). If the second use not requested then
1126 * NULL is passed for the string allocator to GetNext_Item().
1127 *
1128 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1129 * allocator altogether and thus both of these uses. It reduced the
1130 * decoder object code by about 400 bytes.
1131 */
1132 const QCORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001133
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001134#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
1135 const QCORInternalAllocator *pAllocator = NULL;
1136
1137 if(pMe->StringAllocator.pfAllocator) {
1138 pAllocator = &(pMe->StringAllocator);
1139 if(pMe->bStringAllocateAll) {
1140 pAllocatorForGetNext = pAllocator;
1141 }
1142 }
1143#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1144
1145 QCBORError uReturn;
1146 uReturn = GetNext_Item(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
1147 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001148 goto Done;
1149 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001150
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001151 /* Only do indefinite length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001152 const uint8_t uStringType = pDecodedItem->uDataType;
1153 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001154 goto Done;
1155 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001156
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001157 /* Is this a string with an indefinite length? */
1158 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1159 goto Done;
1160 }
1161
1162#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
1163 /* Can't do indefinite length strings without a string allocator */
1164 if(pAllocator == NULL) {
1165 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1166 goto Done;
1167 }
1168
1169 /* Loop getting chunks of the indefinite length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001170 UsefulBufC FullString = NULLUsefulBufC;
1171
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001172 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001173 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001174 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001175 /* Pass a NULL string allocator to GetNext_Item() because the
1176 * individual string chunks in an indefinite length should not
1177 * be allocated. They are always copied in the the contiguous
1178 * buffer allocated here.
1179 */
1180 uReturn = GetNext_Item(&(pMe->InBuf), &StringChunkItem, NULL);
1181 if(uReturn) {
1182 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001183 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001184
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001185 /* Is item is the marker for end of the indefinite length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001186 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001187 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001188 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301189 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001190 break;
1191 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001192
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001193 /* All chunks must be of the same type, the type of the item
1194 * that introduces the indefinite length string. This also
1195 * catches errors where the chunk is not a string at all and an
1196 * indefinite length string inside an indefinite length string.
1197 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001198 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001199 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1200 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001201 break;
1202 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001203
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001204 /* The first time throurgh FullString.ptr is NULL and this is
1205 * equivalent to StringAllocator_Allocate(). Subsequently it is
1206 * not NULL and a reallocation happens.
1207 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001208 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1209 UNCONST_POINTER(FullString.ptr),
1210 FullString.len + StringChunkItem.val.string.len);
1211
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001212 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001213 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001214 break;
1215 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001216
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001217 /* Copy new string chunk to the end of accumulated string */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001218 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001219 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001220
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001221 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1222 /* Getting the item failed, clean up the allocated memory */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001223 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001224 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001225#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1226 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1227#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001228
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001229Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001230 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001231}
1232
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001233
Laurence Lundblade9b334962020-08-27 10:55:53 -07001234static uint64_t ConvertTag(const QCBORDecodeContext *me, uint16_t uTagVal) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001235 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001236 return uTagVal;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001237 } else if(uTagVal == CBOR_TAG_INVALID16) {
1238 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001239 } else {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001240 // This won't be negative because of code below in GetNext_TaggedItem()
1241 const unsigned uIndex = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
1242 return me->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001243 }
1244}
1245
Laurence Lundblade9b334962020-08-27 10:55:53 -07001246
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001247/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001248 Gets all optional tag data items preceding a data item that is not an
1249 optional tag and records them as bits in the tag map.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001250
1251 @retval QCBOR_ERR_UNSUPPORTED
1252
1253 @retval QCBOR_ERR_HIT_END
1254
1255 @retval QCBOR_ERR_INT_OVERFLOW
1256
1257 @retval QCBOR_ERR_STRING_ALLOCATE
1258
1259 @retval QCBOR_ERR_STRING_TOO_LONG
1260
1261 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1262
1263 @retval QCBOR_ERR_BAD_TYPE_7
1264
1265 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1266
1267 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1268
1269 @retval QCBOR_ERR_TOO_MANY_TAGS
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001270 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001271static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001272GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001273{
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001274 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1275 CBOR_TAG_INVALID16,
1276 CBOR_TAG_INVALID16,
1277 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001278
Laurence Lundblade9b334962020-08-27 10:55:53 -07001279 QCBORError uReturn = QCBOR_SUCCESS;
1280
Laurence Lundblade59289e52019-12-30 13:44:37 -08001281 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001282 for(;;) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001283 QCBORError uErr = GetNext_FullItem(me, pDecodedItem);
1284 if(uErr != QCBOR_SUCCESS) {
1285 uReturn = uErr;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001286 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001287 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001288
Laurence Lundblade9b334962020-08-27 10:55:53 -07001289 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001290 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001291 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001292 break;
1293 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001294
Laurence Lundblade9b334962020-08-27 10:55:53 -07001295 if(auTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1296 // No room in the tag list
1297 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1298 // Continue on to get all tags on this item even though
1299 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001300 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001301 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001302 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001303 // Slide tags over one in the array to make room at index 0
1304 for(size_t uTagIndex = QCBOR_MAX_TAGS_PER_ITEM - 1; uTagIndex > 0; uTagIndex--) {
1305 auTags[uTagIndex] = auTags[uTagIndex-1];
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001306 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001307
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001308 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001309 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001310 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001311 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001312 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001313 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001314 break;
1315 }
1316 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
1317 break;
1318 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001319 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001320 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1321 // No room for the tag
Laurence Lundblade9b334962020-08-27 10:55:53 -07001322 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1323 // Continue on to get all tags on this item even though
1324 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001325 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001326 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001327 }
1328
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001329 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001330 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001331 auTags[0] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001332
1333 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001334 auTags[0] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001335 }
1336 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001337
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001338Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001339 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001340}
1341
1342
1343/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001344 This layer takes care of map entries. It combines the label and data
1345 items into one QCBORItem.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001346
1347 @retval QCBOR_ERR_UNSUPPORTED
1348
1349 @retval QCBOR_ERR_HIT_END
1350
1351 @retval QCBOR_ERR_INT_OVERFLOW
1352
1353 @retval QCBOR_ERR_STRING_ALLOCATE
1354
1355 @retval QCBOR_ERR_STRING_TOO_LONG
1356
1357 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1358
1359 @retval QCBOR_ERR_BAD_TYPE_7
1360
1361 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1362
1363 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1364
1365 @retval QCBOR_ERR_TOO_MANY_TAGS
1366
1367 @retval QCBOR_ERR_MAP_LABEL_TYPE
1368
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001369 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001370 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001371static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001372GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001373{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001374 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001375 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001376 if(nReturn)
1377 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001378
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001379 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001380 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001381 goto Done;
1382 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001383
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001384 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1385 // In a map and caller wants maps decoded, not treated as arrays
1386
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001387 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001388 // If in a map and the right decoding mode, get the label
1389
Laurence Lundbladeee851742020-01-08 08:37:05 -08001390 // Save label in pDecodedItem and get the next which will
1391 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001392 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001393 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001394 if(QCBORDecode_IsUnrecoverableError(nReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001395 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001396 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001397
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301398 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001399
1400 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1401 // strings are always good labels
1402 pDecodedItem->label.string = LabelItem.val.string;
1403 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1404 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001405 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001406 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1407 goto Done;
1408 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1409 pDecodedItem->label.int64 = LabelItem.val.int64;
1410 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1411 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1412 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1413 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1414 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1415 pDecodedItem->label.string = LabelItem.val.string;
1416 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1417 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1418 } else {
1419 // label is not an int or a string. It is an arrray
1420 // or a float or such and this implementation doesn't handle that.
1421 // Also, tags on labels are ignored.
1422 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1423 goto Done;
1424 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001425 }
1426 } else {
1427 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001428 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001429 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001430 goto Done;
1431 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001432 // Decoding a map as an array
1433 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001434 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1435 // Cast is needed because of integer promotion
1436 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001437 }
1438 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001439
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001440Done:
1441 return nReturn;
1442}
1443
1444
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001445#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -07001446/*
1447 See if next item is a CBOR break. If it is, it is consumed,
1448 if not it is not consumed.
1449*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001450static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001451NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1452{
1453 *pbNextIsBreak = false;
1454 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001455 QCBORItem Peek;
1456 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1457 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1458 if(uReturn != QCBOR_SUCCESS) {
1459 return uReturn;
1460 }
1461 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001462 // It is not a break, rewind so it can be processed normally.
1463 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001464 } else {
1465 *pbNextIsBreak = true;
1466 }
1467 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001468
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001469 return QCBOR_SUCCESS;
1470}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001471#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001472
1473
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001474/*
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001475 * An item was just consumed, now figure out if it was the
1476 * end of an array/map map that can be closed out. That
1477 * may in turn close out the above array/map...
Laurence Lundblade642282a2020-06-23 12:00:33 -07001478*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001479static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001480{
1481 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001482
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001483 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001484 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1485
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001486 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1487 /* Nesting level is bstr-wrapped CBOR */
1488
1489 /* Ascent for bstr-wrapped CBOR is always by explicit call
1490 * so no further ascending can happen.
1491 */
1492 break;
1493
1494 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1495 /* Level is a definite-length array/map */
1496
1497 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001498 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1499 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001500 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001501 break;
1502 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001503 /* All items in a definite length array were consumed so it
1504 * is time to ascend one level. This happens below.
1505 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001506
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001507#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001508 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001509 /* Level is an indefinite-length array/map. */
1510
1511 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001512 bool bIsBreak = false;
1513 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1514 if(uReturn != QCBOR_SUCCESS) {
1515 goto Done;
1516 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001517
1518 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001519 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001520 break;
1521 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001522
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001523 /* It was a break in an indefinite length map / array so
1524 * it is time to ascend one level.
1525 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001526
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001527#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001528 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001529
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001530
1531 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001532
Laurence Lundblade93d89472020-10-03 22:30:50 -07001533 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001534 * QCBORDecode_ExitBoundedMode().
1535 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001536 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade93d89472020-10-03 22:30:50 -07001537 /* Set the count to zero for definite length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001538 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001539 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001540 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001541 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001542
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001543 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001544 break;
1545 }
1546
1547 /* Finally, actually ascend one level. */
1548 DecodeNesting_Ascend(&(pMe->nesting));
1549 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001550
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001551 uReturn = QCBOR_SUCCESS;
1552
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001553#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001554Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001555#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1556
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001557 return uReturn;
1558}
1559
1560
1561/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001562 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001563 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1564 indefinte length maps and arrays by looking at the item count or
1565 finding CBOR breaks. It detects the ends of the top-level sequence
1566 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001567
1568 @retval QCBOR_ERR_UNSUPPORTED X
1569
1570 @retval QCBOR_ERR_HIT_END
1571
1572 @retval QCBOR_ERR_INT_OVERFLOW X
1573
1574 @retval QCBOR_ERR_STRING_ALLOCATE
1575
1576 @retval QCBOR_ERR_STRING_TOO_LONG
1577
1578 @retval QCBOR_ERR_HALF_PRECISION_DISABLED X
1579
1580 @retval QCBOR_ERR_BAD_TYPE_7 X
1581
1582 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1583
1584 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1585
1586 @retval QCBOR_ERR_TOO_MANY_TAGS
1587
1588 @retval QCBOR_ERR_MAP_LABEL_TYPE X
1589
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001590 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade9b334962020-08-27 10:55:53 -07001591
1592 @retval QCBOR_ERR_NO_MORE_ITEMS
1593
1594 @retval QCBOR_ERR_BAD_BREAK
1595
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001596 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001597static QCBORError
1598QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001599{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001600 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001601 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001602
Laurence Lundblade642282a2020-06-23 12:00:33 -07001603 /*
1604 If out of bytes to consume, it is either the end of the top-level
1605 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001606
Laurence Lundblade642282a2020-06-23 12:00:33 -07001607 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1608 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1609 CBOR is exited, the length is set back to the top-level's length
1610 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001611 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001612 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001613 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001614 goto Done;
1615 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001616
Laurence Lundblade642282a2020-06-23 12:00:33 -07001617 /*
1618 Check to see if at the end of a bounded definite length map or
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001619 array. The check for a break ending indefinite length array is
1620 later in NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001621 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001622 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001623 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001624 goto Done;
1625 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001626
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001627 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001628 uReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001629 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1630 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001631 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001632 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301633
Laurence Lundblade642282a2020-06-23 12:00:33 -07001634 /*
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001635 Breaks ending arrays/maps are processed later in the call to
1636 NestLevelAscender(). They should never show up here.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001637 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301638 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001639 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301640 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301641 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001642
Laurence Lundblade642282a2020-06-23 12:00:33 -07001643 /*
1644 Record the nesting level for this data item before processing any
1645 of decrementing and descending.
1646 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001647 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001648
Laurence Lundblade642282a2020-06-23 12:00:33 -07001649
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001650 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001651 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001652 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001653 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001654
Laurence Lundblade93d89472020-10-03 22:30:50 -07001655 Empty indefinite length maps and arrays are descended into, but
1656 then ascended out of in the next chunk of code.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001657
1658 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001659 encloses them so a decrement needs to be done for them too, but
1660 that is done only when all the items in them have been
1661 processed, not when they are opened with the exception of an
1662 empty map or array.
1663 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001664 QCBORError uDescendErr;
1665 uDescendErr = DecodeNesting_DescendMapOrArray(&(me->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001666 pDecodedItem->uDataType,
1667 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001668 if(uDescendErr != QCBOR_SUCCESS) {
1669 /* This error is probably a traversal error and it
1670 overrides the non-traversal error. */
1671 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001672 goto Done;
1673 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001674 }
1675
Laurence Lundblade02625d42020-06-25 14:41:41 -07001676 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1677 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1678 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001679 /*
1680 The following cases are handled here:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001681 - A non-aggregate item like an integer or string
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001682 - An empty definite length map or array
1683 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001684
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001685 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001686 definite length map/array and break detection for an indefinite
1687 length map/array. If the end of the map/array was reached, then
1688 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001689 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001690 QCBORError uAscendErr;
1691 uAscendErr = NestLevelAscender(me, true);
1692 if(uAscendErr != QCBOR_SUCCESS) {
1693 /* This error is probably a traversal error and it
1694 overrides the non-traversal error. */
1695 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001696 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001697 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301698 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001699
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001700 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001701 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001702 Tell the caller what level is next. This tells them what
1703 maps/arrays were closed out and makes it possible for them to
1704 reconstruct the tree with just the information returned in
1705 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001706 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001707 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001708 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001709 pDecodedItem->uNextNestLevel = 0;
1710 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001711 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001712 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001713
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001714Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001715 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001716}
1717
Laurence Lundblade9b334962020-08-27 10:55:53 -07001718static void ShiftTags(QCBORItem *pDecodedItem)
1719{
1720 pDecodedItem->uTags[0] = pDecodedItem->uTags[1];
1721 pDecodedItem->uTags[1] = pDecodedItem->uTags[2];
1722 pDecodedItem->uTags[2] = pDecodedItem->uTags[3];
1723 pDecodedItem->uTags[2] = CBOR_TAG_INVALID16;
1724}
1725
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001726
Laurence Lundblade9b334962020-08-27 10:55:53 -07001727
Laurence Lundblade59289e52019-12-30 13:44:37 -08001728/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001729 The epoch formatted date. Turns lots of different forms of encoding
1730 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001731 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001732static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001733{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001734 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001735
1736 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1737
1738 switch (pDecodedItem->uDataType) {
1739
1740 case QCBOR_TYPE_INT64:
1741 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1742 break;
1743
1744 case QCBOR_TYPE_UINT64:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001745 // This only happens for CBOR type 0 > INT64_MAX so it is
1746 // always an overflow.
1747 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1748 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001749 break;
1750
1751 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001752 case QCBOR_TYPE_FLOAT:
1753#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001754 {
1755 // This comparison needs to be done as a float before
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001756 // conversion to an int64_t to be able to detect doubles that
1757 // are too large to fit into an int64_t. A double has 52
1758 // bits of preceision. An int64_t has 63. Casting INT64_MAX
1759 // to a double actually causes a round up which is bad and
1760 // wrong for the comparison because it will allow conversion
1761 // of doubles that can't fit into a uint64_t. To remedy this
1762 // INT64_MAX - 0x7ff is used as the cutoff point because if
1763 // that value rounds up in conversion to double it will still
1764 // be less than INT64_MAX. 0x7ff is picked because it has 11
1765 // bits set.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001766 //
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001767 // INT64_MAX seconds is on the order of 10 billion years, and
1768 // the earth is less than 5 billion years old, so for most
1769 // uses this conversion error won't occur even though doubles
1770 // can go much larger.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001771 //
1772 // Without the 0x7ff there is a ~30 minute range of time
1773 // values 10 billion years in the past and in the future
Laurence Lundbladec7114722020-08-13 05:11:40 -07001774 // where this code would go wrong. Some compilers
1775 // will generate warnings or errors without the 0x7ff
1776 // because of the precision issue.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001777 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
1778 pDecodedItem->val.dfnum :
1779 (double)pDecodedItem->val.fnum;
Laurence Lundbladec7114722020-08-13 05:11:40 -07001780 if(isnan(d) ||
1781 d > (double)(INT64_MAX - 0x7ff) ||
1782 d < (double)(INT64_MIN + 0x7ff)) {
1783 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001784 goto Done;
1785 }
1786 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001787 pDecodedItem->val.epochDate.fSecondsFraction =
1788 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001789 }
Laurence Lundblade9682a532020-06-06 18:33:04 -07001790#else
Laurence Lundblade4b270642020-08-14 12:53:07 -07001791
Laurence Lundbladec7114722020-08-13 05:11:40 -07001792 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001793 goto Done;
1794
Laurence Lundblade9682a532020-06-06 18:33:04 -07001795#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001796 break;
1797
1798 default:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001799 uReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001800 goto Done;
1801 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001802
Laurence Lundblade59289e52019-12-30 13:44:37 -08001803 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1804
1805Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001806 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001807}
1808
1809
1810#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1811/*
1812 Decode decimal fractions and big floats.
1813
1814 When called pDecodedItem must be the array that is tagged as a big
1815 float or decimal fraction, the array that has the two members, the
1816 exponent and mantissa.
1817
1818 This will fetch and decode the exponent and mantissa and put the
1819 result back into pDecodedItem.
1820 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001821static inline QCBORError
Laurence Lundblade59289e52019-12-30 13:44:37 -08001822QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1823{
1824 QCBORError nReturn;
1825
1826 // --- Make sure it is an array; track nesting level of members ---
1827 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1828 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1829 goto Done;
1830 }
1831
1832 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001833 // definite length arrays, but not for indefnite. Instead remember
1834 // the nesting level the two integers must be at, which is one
1835 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001836 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1837
1838 // --- Is it a decimal fraction or a bigfloat? ---
1839 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1840 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1841
1842 // --- Get the exponent ---
1843 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001844 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001845 if(nReturn != QCBOR_SUCCESS) {
1846 goto Done;
1847 }
1848 if(exponentItem.uNestingLevel != nNestLevel) {
1849 // Array is empty or a map/array encountered when expecting an int
1850 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1851 goto Done;
1852 }
1853 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1854 // Data arriving as an unsigned int < INT64_MAX has been converted
1855 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1856 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1857 // will be too large for this to handle and thus an error that will
1858 // get handled in the next else.
1859 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1860 } else {
1861 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1862 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1863 goto Done;
1864 }
1865
1866 // --- Get the mantissa ---
1867 QCBORItem mantissaItem;
1868 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1869 if(nReturn != QCBOR_SUCCESS) {
1870 goto Done;
1871 }
1872 if(mantissaItem.uNestingLevel != nNestLevel) {
1873 // Mantissa missing or map/array encountered when expecting number
1874 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1875 goto Done;
1876 }
1877 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1878 // Data arriving as an unsigned int < INT64_MAX has been converted
1879 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1880 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1881 // will be too large for this to handle and thus an error that
1882 // will get handled in an else below.
1883 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade93d89472020-10-03 22:30:50 -07001884 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
1885 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001886 // Got a good big num mantissa
1887 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1888 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001889 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1890 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1891 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001892 } else {
1893 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1894 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1895 goto Done;
1896 }
1897
1898 // --- Check that array only has the two numbers ---
1899 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07001900 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08001901 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1902 goto Done;
1903 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07001904 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001905
1906Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001907 return nReturn;
1908}
1909#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1910
1911
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001912static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001913{
1914 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1915 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07001916 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001917 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1918 } else {
1919 return QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001920
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001921 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001922
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001923 return QCBOR_SUCCESS;
1924}
1925
1926
Laurence Lundblade99615302020-11-29 11:19:47 -08001927/*
1928 * Table of CBOR tags whose content is either a text string or a byte
1929 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
1930 * of uQCBORtype indicates the content should be a byte string rather
1931 * than a text string
1932 */
1933struct StringTagMapEntry {
1934 uint16_t uTagNumber;
1935 uint8_t uQCBORtype;
1936};
1937
1938#define IS_BYTE_STRING_BIT 0x80
1939#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
1940
1941static const struct StringTagMapEntry StringTagMap[] = {
1942 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
1943 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
1944 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
1945 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
1946 {CBOR_TAG_URI, QCBOR_TYPE_URI},
1947 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
1948 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
1949 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
1950 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
1951 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
1952 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
1953};
1954
1955
1956/*
1957 * Process the CBOR tags that whose content is a byte string or a text
1958 * string and for which the string is just passed on to the caller.
1959 *
1960 * This maps the CBOR tag to the QCBOR type and checks the content
1961 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08001962 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08001963 * possible.
1964 *
1965 * This returns QCBOR_SUCCESS if the tag was procssed,
1966 * QCBOR_ERR_UNSUPPORTED if the tag was not processed and
1967 * QCBOR_ERR_BAD_OPT_TAG if the content type was wrong for the tag.
1968 */
1969static inline
1970QCBORError ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001971{
Laurence Lundblade99615302020-11-29 11:19:47 -08001972 /* This only works on tags that were not mapped; no need for other yet */
1973 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
1974 return QCBOR_ERR_UNSUPPORTED;
1975 }
1976
1977 unsigned uIndex;
1978 for(uIndex = 0; StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
1979 if(StringTagMap[uIndex].uTagNumber == uTag) {
1980 break;
1981 }
1982 }
1983
1984 const uint8_t uQCBORType = StringTagMap[uIndex].uQCBORtype;
1985 if(uQCBORType == QCBOR_TYPE_NONE) {
1986 /* repurpose this error to mean, not handled here */
1987 return QCBOR_ERR_UNSUPPORTED;
1988 }
1989
1990 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
1991 if(uQCBORType & IS_BYTE_STRING_BIT) {
1992 uExpectedType = QCBOR_TYPE_BYTE_STRING;
1993 }
1994
1995 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001996 return QCBOR_ERR_BAD_OPT_TAG;
1997 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001998
Laurence Lundblade99615302020-11-29 11:19:47 -08001999 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002000 return QCBOR_SUCCESS;
2001}
2002
2003
Laurence Lundblade59289e52019-12-30 13:44:37 -08002004/*
Laurence Lundblade99615302020-11-29 11:19:47 -08002005 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
2006 * but the whole tag was not decoded. Here, the whole tags (tag number
2007 * and tag content) that are supported by QCBOR are decoded. This is a
2008 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002009 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002010static QCBORError
2011QCBORDecode_GetNextTag(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002012{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002013 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002014
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002015 uReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
2016 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002017 goto Done;
2018 }
2019
Laurence Lundblade99615302020-11-29 11:19:47 -08002020 /* When there are no tag numbers for the item, this exits first
2021 * thing and effectively does nothing.
2022 *
2023 * This loops over all the tag numbers accumulated for this item
2024 * trying to decode and interpret them. This stops at the end of
2025 * the list or at the first tag number that can't be interpreted by
2026 * this code. This is effectively a recursive processing of the
2027 * tags number list that handles nested tags.
2028 */
2029 while(1) {
2030 /* Don't bother to unmap tags via QCBORITem.uTags since this
2031 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2032 */
2033 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002034
Laurence Lundblade99615302020-11-29 11:19:47 -08002035 if(uTagToProcess == CBOR_TAG_INVALID16) {
2036 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002037 break;
2038
Laurence Lundblade99615302020-11-29 11:19:47 -08002039 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002040 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002041
Laurence Lundblade93d89472020-10-03 22:30:50 -07002042#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002043 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2044 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002045 uReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
Laurence Lundblade93d89472020-10-03 22:30:50 -07002046#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002047
Laurence Lundblade99615302020-11-29 11:19:47 -08002048 } else if(uTagToProcess == CBOR_TAG_MIME ||
2049 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002050 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002051
Laurence Lundblade99615302020-11-29 11:19:47 -08002052 } else {
2053 /* See if it is a pass-through byte/text string tag; process if so */
2054 uReturn = ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002055
Laurence Lundblade99615302020-11-29 11:19:47 -08002056 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
2057 /* It wasn't a pass-through byte/text string tag so it is
2058 * an unknown tag. This is the exit from the loop on the
2059 * first unknown tag. It is a successful exit.
2060 */
2061 uReturn = QCBOR_SUCCESS;
2062 break;
2063 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002064 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002065
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002066 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002067 /* Error exit from the loop */
2068 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002069 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002070
2071 /* A tag was successfully processed, shift it out of the list of
2072 * tags returned. This is the loop increment.
2073 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002074 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002075 }
2076
2077Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002078 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002079}
2080
2081
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002082/*
2083 Public function, see header qcbor/qcbor_decode.h file
2084 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002085QCBORError
2086QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2087{
2088 QCBORError uErr;
2089 uErr = QCBORDecode_GetNextTag(pMe, pDecodedItem);
2090 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002091 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2092 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2093 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002094 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002095}
2096
2097
2098/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002099 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002100 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002101QCBORError
2102QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2103{
2104 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2105 const UsefulInputBuf Save = pMe->InBuf;
2106
2107 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2108
2109 pMe->nesting = SaveNesting;
2110 pMe->InBuf = Save;
2111
2112 return uErr;
2113}
2114
2115
2116/*
2117 Public function, see header qcbor/qcbor_decode.h file
2118 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002119void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2120{
2121 if(pMe->uLastError != QCBOR_SUCCESS) {
2122 return;
2123 }
2124
2125 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2126}
2127
2128
2129/*
2130 Public function, see header qcbor/qcbor_decode.h file
2131 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002132QCBORError
2133QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
2134 QCBORItem *pDecodedItem,
2135 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002136{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002137 QCBORError nReturn;
2138
2139 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
2140 if(nReturn != QCBOR_SUCCESS) {
2141 return nReturn;
2142 }
2143
2144 if(pTags != NULL) {
2145 pTags->uNumUsed = 0;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002146 // Reverse the order because pTags is reverse of
2147 // QCBORItem.uTags.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002148 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2149 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002150 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002151 }
2152 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2153 return QCBOR_ERR_TOO_MANY_TAGS;
2154 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002155 pTags->puTags[pTags->uNumUsed] = ConvertTag(me,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002156 pTags->uNumUsed++;
2157 }
2158 }
2159
2160 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002161}
2162
2163
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002164/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05302165 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302166 next one down. If a layer has no work to do for a particular item
2167 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002168
Laurence Lundblade59289e52019-12-30 13:44:37 -08002169 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
2170 tagged data items, turning them into the local C representation.
2171 For the most simple it is just associating a QCBOR_TYPE with the data. For
2172 the complex ones that an aggregate of data items, there is some further
2173 decoding and a little bit of recursion.
2174
2175 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302176 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05302177 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002178 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002179
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302180 - GetNext_MapEntry -- This handles the combining of two
2181 items, the label and the data, that make up a map entry.
2182 It only does work on maps. It combines the label and data
2183 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002184
Laurence Lundblade59289e52019-12-30 13:44:37 -08002185 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
2186 tags into bit flags associated with the data item. No actual decoding
2187 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002188
Laurence Lundblade59289e52019-12-30 13:44:37 -08002189 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302190 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05302191 string allocater to create contiguous space for the item. It
2192 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002193
Laurence Lundblade59289e52019-12-30 13:44:37 -08002194 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
2195 atomic data item has a "major type", an integer "argument" and optionally
2196 some content. For text and byte strings, the content is the bytes
2197 that make up the string. These are the smallest data items that are
2198 considered to be well-formed. The content may also be other data items in
2199 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002200
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002201 Roughly this takes 300 bytes of stack for vars. Need to
2202 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002203
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302204 */
2205
2206
2207/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002208 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002209 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002210bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002211 const QCBORItem *pItem,
2212 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002213{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002214 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2215 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002216 break;
2217 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002218 if(ConvertTag(me, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002219 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002220 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002221 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002222
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002223 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002224}
2225
2226
2227/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002228 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002229 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002230QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002231{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002232 QCBORError uReturn = me->uLastError;
2233
2234 if(uReturn != QCBOR_SUCCESS) {
2235 goto Done;
2236 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002237
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002238 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002239 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002240 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002241 goto Done;
2242 }
2243
2244 // Error out if not all the bytes are consumed
2245 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002246 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002247 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002248
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002249Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002250#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade6de37062018-10-15 12:22:42 +05302251 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002252 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002253 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002254#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002255
Laurence Lundblade085d7952020-07-24 10:26:30 -07002256 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002257}
2258
2259
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002260/*
Laurence Lundblade9b334962020-08-27 10:55:53 -07002261 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002262*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07002263// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002264uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2265 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002266 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002267{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002268 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2269 return CBOR_TAG_INVALID64;
2270 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002271 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2272 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002273 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002274 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002275 }
2276}
2277
Laurence Lundblade9b334962020-08-27 10:55:53 -07002278/*
2279 Public function, see header qcbor/qcbor_decode.h file
2280*/
2281uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2282 uint32_t uIndex)
2283{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002284 if(pMe->uLastError != QCBOR_SUCCESS) {
2285 return CBOR_TAG_INVALID64;
2286 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002287 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2288 return CBOR_TAG_INVALID64;
2289 } else {
2290 return ConvertTag(pMe, pMe->uLastTags[uIndex]);
2291 }
2292}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002293
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002294/*
2295
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002296Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002297
Laurence Lundbladeee851742020-01-08 08:37:05 -08002298 - Hit end of input before it was expected while decoding type and
2299 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002300
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002301 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002302
Laurence Lundbladeee851742020-01-08 08:37:05 -08002303 - Hit end of input while decoding a text or byte string
2304 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002305
Laurence Lundbladeee851742020-01-08 08:37:05 -08002306 - Encountered conflicting tags -- e.g., an item is tagged both a date
2307 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002308
Laurence Lundbladeee851742020-01-08 08:37:05 -08002309 - Encontered an array or mapp that has too many items
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002310 QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002311
Laurence Lundbladeee851742020-01-08 08:37:05 -08002312 - Encountered array/map nesting that is too deep
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002313 QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002314
Laurence Lundbladeee851742020-01-08 08:37:05 -08002315 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2316 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002317
Laurence Lundbladeee851742020-01-08 08:37:05 -08002318 - The type of a map label is not a string or int
2319 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002320
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002321 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002322
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002323 */
2324
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002325
2326
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002327#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002328
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002329/* ===========================================================================
2330 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002331
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002332 This implements a simple sting allocator for indefinite length
2333 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2334 implements the function type QCBORStringAllocate and allows easy
2335 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002336
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002337 This particular allocator is built-in for convenience. The caller
2338 can implement their own. All of this following code will get
2339 dead-stripped if QCBORDecode_SetMemPool() is not called.
2340
2341 This is a very primitive memory allocator. It does not track
2342 individual allocations, only a high-water mark. A free or
2343 reallocation must be of the last chunk allocated.
2344
2345 The size of the pool and offset to free memory are packed into the
2346 first 8 bytes of the memory pool so we don't have to keep them in
2347 the decode context. Since the address of the pool may not be
2348 aligned, they have to be packed and unpacked as if they were
2349 serialized data of the wire or such.
2350
2351 The sizes packed in are uint32_t to be the same on all CPU types
2352 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002353 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002354
2355
Laurence Lundbladeee851742020-01-08 08:37:05 -08002356static inline int
2357MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002358{
2359 // Use of UsefulInputBuf is overkill, but it is convenient.
2360 UsefulInputBuf UIB;
2361
Laurence Lundbladeee851742020-01-08 08:37:05 -08002362 // Just assume the size here. It was checked during SetUp so
2363 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002364 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002365 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2366 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2367 return UsefulInputBuf_GetError(&UIB);
2368}
2369
2370
Laurence Lundbladeee851742020-01-08 08:37:05 -08002371static inline int
2372MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002373{
2374 // Use of UsefulOutBuf is overkill, but convenient. The
2375 // length check performed here is useful.
2376 UsefulOutBuf UOB;
2377
2378 UsefulOutBuf_Init(&UOB, Pool);
2379 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2380 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2381 return UsefulOutBuf_GetError(&UOB);
2382}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002383
2384
2385/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002386 Internal function for an allocation, reallocation free and destuct.
2387
2388 Having only one function rather than one each per mode saves space in
2389 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002390
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002391 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2392 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002393static UsefulBuf
2394MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002395{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002396 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002397
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002398 uint32_t uPoolSize;
2399 uint32_t uFreeOffset;
2400
2401 if(uNewSize > UINT32_MAX) {
2402 // This allocator is only good up to 4GB. This check should
2403 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2404 goto Done;
2405 }
2406 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2407
2408 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2409 goto Done;
2410 }
2411
2412 if(uNewSize) {
2413 if(pMem) {
2414 // REALLOCATION MODE
2415 // Calculate pointer to the end of the memory pool. It is
2416 // assumed that pPool + uPoolSize won't wrap around by
2417 // assuming the caller won't pass a pool buffer in that is
2418 // not in legitimate memory space.
2419 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2420
2421 // Check that the pointer for reallocation is in the range of the
2422 // pool. This also makes sure that pointer math further down
2423 // doesn't wrap under or over.
2424 if(pMem >= pPool && pMem < pPoolEnd) {
2425 // Offset to start of chunk for reallocation. This won't
2426 // wrap under because of check that pMem >= pPool. Cast
2427 // is safe because the pool is always less than UINT32_MAX
2428 // because of check in QCBORDecode_SetMemPool().
2429 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2430
2431 // Check to see if the allocation will fit. uPoolSize -
2432 // uMemOffset will not wrap under because of check that
2433 // pMem is in the range of the uPoolSize by check above.
2434 if(uNewSize <= uPoolSize - uMemOffset) {
2435 ReturnValue.ptr = pMem;
2436 ReturnValue.len = uNewSize;
2437
2438 // Addition won't wrap around over because uNewSize was
2439 // checked to be sure it is less than the pool size.
2440 uFreeOffset = uMemOffset + uNewSize32;
2441 }
2442 }
2443 } else {
2444 // ALLOCATION MODE
2445 // uPoolSize - uFreeOffset will not underflow because this
2446 // pool implementation makes sure uFreeOffset is always
2447 // smaller than uPoolSize through this check here and
2448 // reallocation case.
2449 if(uNewSize <= uPoolSize - uFreeOffset) {
2450 ReturnValue.len = uNewSize;
2451 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002452 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002453 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002454 }
2455 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002456 if(pMem) {
2457 // FREE MODE
2458 // Cast is safe because of limit on pool size in
2459 // QCBORDecode_SetMemPool()
2460 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2461 } else {
2462 // DESTRUCT MODE
2463 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002464 }
2465 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002466
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002467 UsefulBuf Pool = {pPool, uPoolSize};
2468 MemPool_Pack(Pool, uFreeOffset);
2469
2470Done:
2471 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002472}
2473
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002474
Laurence Lundbladef6531662018-12-04 10:42:22 +09002475/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002476 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002477 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002478QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2479 UsefulBuf Pool,
2480 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002481{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002482 // The pool size and free mem offset are packed into the beginning
2483 // of the pool memory. This compile time check make sure the
2484 // constant in the header is correct. This check should optimize
2485 // down to nothing.
2486 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002487 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002488 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002489
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002490 // The pool size and free offset packed in to the beginning of pool
2491 // memory are only 32-bits. This check will optimize out on 32-bit
2492 // machines.
2493 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002494 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002495 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002496
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002497 // This checks that the pool buffer given is big enough.
2498 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002499 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002500 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002501
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002502 pMe->StringAllocator.pfAllocator = MemPool_Function;
2503 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2504 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002505
Laurence Lundblade30816f22018-11-10 13:40:22 +07002506 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002507}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002508#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002509
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002510
2511
Laurence Lundblade9b334962020-08-27 10:55:53 -07002512static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2513{
2514 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2515}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002516
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002517
2518/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002519 Consume an entire map or array (and do next to
2520 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002521 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002522static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002523ConsumeItem(QCBORDecodeContext *pMe,
2524 const QCBORItem *pItemToConsume,
2525 uint_fast8_t *puNextNestLevel)
2526{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002527 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002528 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002529
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002530 // If it is a map or array, this will tell if it is empty.
2531 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2532
2533 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2534 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002535
Laurence Lundblade1341c592020-04-11 14:19:05 -07002536 /* This works for definite and indefinite length
2537 * maps and arrays by using the nesting level
2538 */
2539 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002540 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002541 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002542 goto Done;
2543 }
2544 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002545
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002546 *puNextNestLevel = Item.uNextNestLevel;
2547
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002548 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002549
Laurence Lundblade1341c592020-04-11 14:19:05 -07002550 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002551 /* item_to_consume is not a map or array */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002552 /* Just pass the nesting level through */
2553 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2554
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002555 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002556 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002557
2558Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002559 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002560}
2561
2562
Laurence Lundblade1341c592020-04-11 14:19:05 -07002563/* Return true if the labels in Item1 and Item2 are the same.
2564 Works only for integer and string labels. Returns false
2565 for any other type. */
2566static inline bool
2567MatchLabel(QCBORItem Item1, QCBORItem Item2)
2568{
2569 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2570 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2571 return true;
2572 }
2573 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002574 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002575 return true;
2576 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002577 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002578 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2579 return true;
2580 }
2581 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2582 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2583 return true;
2584 }
2585 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002586
Laurence Lundblade1341c592020-04-11 14:19:05 -07002587 /* Other label types are never matched */
2588 return false;
2589}
2590
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002591
2592/*
2593 Returns true if Item1 and Item2 are the same type
2594 or if either are of QCBOR_TYPE_ANY.
2595 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002596static inline bool
2597MatchType(QCBORItem Item1, QCBORItem Item2)
2598{
2599 if(Item1.uDataType == Item2.uDataType) {
2600 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002601 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002602 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002603 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002604 return true;
2605 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002606 return false;
2607}
2608
2609
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002610/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002611 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002612
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002613 @param[in] pMe The decode context to search.
2614 @param[in,out] pItemArray The items to search for and the items found.
2615 @param[out] puOffset Byte offset of last item matched.
2616 @param[in] pCBContext Context for the not-found item call back.
2617 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002618
2619 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2620
Laurence Lundblade93d89472020-10-03 22:30:50 -07002621 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2622 were found for one of the labels being
2623 search for. This duplicate detection is
2624 only performed for items in pItemArray,
2625 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002626
Laurence Lundblade93d89472020-10-03 22:30:50 -07002627 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2628 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002629
2630 @retval Also errors returned by QCBORDecode_GetNext().
2631
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002632 On input pItemArray contains a list of labels and data types
2633 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002634
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002635 On output the fully retrieved items are filled in with
2636 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002637
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002638 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002639
2640 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002641 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002642static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002643MapSearch(QCBORDecodeContext *pMe,
2644 QCBORItem *pItemArray,
2645 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002646 void *pCBContext,
2647 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002648{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002649 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002650 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002651
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002652 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002653 uReturn = pMe->uLastError;
2654 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002655 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002656
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002657 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002658 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2659 /* QCBOR_TYPE_NONE as first item indicates just looking
2660 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002661 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2662 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002663 }
2664
Laurence Lundblade085d7952020-07-24 10:26:30 -07002665 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2666 // It is an empty bounded array or map
2667 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2668 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002669 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002670 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002671 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002672 // Nothing is ever found in an empty array or map. All items
2673 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002674 uReturn = QCBOR_SUCCESS;
2675 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002676 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002677 }
2678
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002679 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002680 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2681
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002682 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002683 UsefulInputBuf_Seek(&(pMe->InBuf),
2684 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002685
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002686 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002687 Loop over all the items in the map or array. Each item
2688 could be a map or array, but label matching is only at
2689 the main level. This handles definite and indefinite
2690 length maps and arrays. The only reason this is ever
2691 called on arrays is to find their end position.
2692
2693 This will always run over all items in order to do
2694 duplicate detection.
2695
2696 This will exit with failure if it encounters an
2697 unrecoverable error, but continue on for recoverable
2698 errors.
2699
2700 If a recoverable error occurs on a matched item, then
2701 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002702 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002703 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002704 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002705 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002706 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002707 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002708
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002709 /* Get the item */
2710 QCBORItem Item;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002711 QCBORError uResult = QCBORDecode_GetNextTag(pMe, &Item);
2712 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002713 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002714 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002715 goto Done;
2716 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002717 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002718 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002719 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002720 goto Done;
2721 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002722
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002723 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002724 bool bMatched = false;
2725 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2726 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002727 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002728 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2729 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002730 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002731 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002732 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002733 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002734 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002735 goto Done;
2736 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002737
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002738 if(uResult != QCBOR_SUCCESS) {
2739 uReturn = uResult;
2740 goto Done;
2741 }
2742
Laurence Lundblade1341c592020-04-11 14:19:05 -07002743 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002744 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002745 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002746 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002747 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002748 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002749 bMatched = true;
2750 }
2751 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002752
2753
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002754 if(!bMatched && pfCallback != NULL) {
2755 /*
2756 Call the callback on unmatched labels.
2757 (It is tempting to do duplicate detection here, but that would
2758 require dynamic memory allocation because the number of labels
2759 that might be encountered is unbounded.)
2760 */
2761 uReturn = (*pfCallback)(pCBContext, &Item);
2762 if(uReturn != QCBOR_SUCCESS) {
2763 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002764 }
2765 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002766
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002767 /*
2768 Consume the item whether matched or not. This
2769 does the work of traversing maps and array and
2770 everything in them. In this loop only the
2771 items at the current nesting level are examined
2772 to match the labels.
2773 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002774 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002775 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002776 goto Done;
2777 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002778
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002779 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002780
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002781 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002782
2783 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002784
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002785 // Check here makes sure that this won't accidentally be
2786 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002787 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08002788 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
2789 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002790 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
2791 goto Done;
2792 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002793 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2794 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002795
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002796 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002797 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2798
2799 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002800 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002801 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002802 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002803 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
2804 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002805 }
2806 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002807
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002808 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002809}
2810
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002811
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002812/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002813 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002814*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002815void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2816 int64_t nLabel,
2817 uint8_t uQcborType,
2818 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002819{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002820 if(pMe->uLastError != QCBOR_SUCCESS) {
2821 return;
2822 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002823
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002824 QCBORItem OneItemSeach[2];
2825 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2826 OneItemSeach[0].label.int64 = nLabel;
2827 OneItemSeach[0].uDataType = uQcborType;
2828 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002829
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002830 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002831
2832 *pItem = OneItemSeach[0];
2833
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002834 if(uReturn != QCBOR_SUCCESS) {
2835 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002836 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002837 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002838 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002839 }
2840
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002841 Done:
2842 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002843}
2844
2845
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002846/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002847 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002848*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002849void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2850 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002851 uint8_t uQcborType,
2852 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002853{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002854 if(pMe->uLastError != QCBOR_SUCCESS) {
2855 return;
2856 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002857
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002858 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002859 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2860 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2861 OneItemSeach[0].uDataType = uQcborType;
2862 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002863
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002864 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2865 if(uReturn != QCBOR_SUCCESS) {
2866 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002867 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002868 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002869 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002870 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002871 }
2872
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002873 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002874
2875Done:
2876 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002877}
2878
2879
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002880
Laurence Lundblade93d89472020-10-03 22:30:50 -07002881static QCBORError
2882CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002883{
2884 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2885 if(uDataType == puTypeList[i]) {
2886 return QCBOR_SUCCESS;
2887 }
2888 }
2889 return QCBOR_ERR_UNEXPECTED_TYPE;
2890}
2891
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002892
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002893/**
2894 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002895 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002896
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002897 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2898 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07002899
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002900 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered
2901 tag value.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002902 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002903static QCBORError
2904CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002905{
2906 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
2907 pItem->uTags[0] != CBOR_TAG_INVALID16) {
2908 /* There are tags that QCBOR couldn't process on this item and
2909 the caller has told us there should not be. */
2910 return QCBOR_ERR_UNEXPECTED_TYPE;
2911 }
2912
2913 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
2914 const int nItemType = pItem->uDataType;
2915
2916 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
2917 // Must match the tag and only the tag
2918 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2919 }
2920
2921 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
2922 if(uReturn == QCBOR_SUCCESS) {
2923 return QCBOR_SUCCESS;
2924 }
2925
2926 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
2927 /* Must match the content type and only the content type.
2928 There was no match just above so it is a fail. */
2929 return QCBOR_ERR_UNEXPECTED_TYPE;
2930 }
2931
2932 /* If here it can match either the tag or the content
2933 and it hasn't matched the content, so the end
2934 result is whether it matches the tag. This is
2935 also the case that the CBOR standard discourages. */
2936
2937 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2938}
2939
Laurence Lundblade9b334962020-08-27 10:55:53 -07002940
Laurence Lundblade9b334962020-08-27 10:55:53 -07002941
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002942// This could be semi-private if need be
2943static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002944void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2945 int64_t nLabel,
2946 TagSpecification TagSpec,
2947 QCBORItem *pItem)
2948{
2949 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2950 if(pMe->uLastError != QCBOR_SUCCESS) {
2951 return;
2952 }
2953
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002954 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002955}
2956
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002957
2958// This could be semi-private if need be
2959static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002960void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2961 const char *szLabel,
2962 TagSpecification TagSpec,
2963 QCBORItem *pItem)
2964{
2965 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2966 if(pMe->uLastError != QCBOR_SUCCESS) {
2967 return;
2968 }
2969
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002970 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002971}
2972
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002973// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002974void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2975 int64_t nLabel,
2976 TagSpecification TagSpec,
2977 UsefulBufC *pString)
2978{
2979 QCBORItem Item;
2980 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2981 if(pMe->uLastError == QCBOR_SUCCESS) {
2982 *pString = Item.val.string;
2983 }
2984}
2985
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002986// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002987void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2988 const char * szLabel,
2989 TagSpecification TagSpec,
2990 UsefulBufC *pString)
2991{
2992 QCBORItem Item;
2993 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2994 if(pMe->uLastError == QCBOR_SUCCESS) {
2995 *pString = Item.val.string;
2996 }
2997}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002998
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002999/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003000 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003001*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003002void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003003{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003004 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
3005 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003006}
3007
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003008/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003009 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003010*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003011void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3012 QCBORItem *pItemList,
3013 void *pCallbackCtx,
3014 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003015{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003016 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
3017 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003018}
3019
3020
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003021/**
3022 * @brief Search for a map/array by label and enter it
3023 *
3024 * @param[in] pMe The decode context.
3025 * @param[in] pSearch The map/array to search for.
3026 *
3027 * @c pSearch is expected to contain one item of type map or array
3028 * with the label specified. The current bounded map will be searched for
3029 * this and if found will be entered.
3030 *
3031 * If the label is not found, or the item found is not a map or array,
3032 * the error state is set.
3033 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003034static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003035{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003036 // The first item in pSearch is the one that is to be
3037 // entered. It should be the only one filled in. Any other
3038 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003039 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003040 return;
3041 }
3042
3043 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003044 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003045 if(pMe->uLastError != QCBOR_SUCCESS) {
3046 return;
3047 }
3048
Laurence Lundblade9b334962020-08-27 10:55:53 -07003049 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003050 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003051 return;
3052 }
3053
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003054 /*
3055 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3056 * next item for the pre-order traversal cursor to be the map/array
3057 * found by MapSearch(). The next few lines of code force the
3058 * cursor to that.
3059 *
3060 * There is no need to retain the old cursor because
3061 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3062 * beginning of the map/array being entered.
3063 *
3064 * The cursor is forced by: 1) setting the input buffer position to
3065 * the item offset found by MapSearch(), 2) setting the map/array
3066 * counter to the total in the map/array, 3) setting the nesting
3067 * level. Setting the map/array counter to the total is not
3068 * strictly correct, but this is OK because this cursor only needs
3069 * to be used to get one item and MapSearch() has already found it
3070 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003071 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003072 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003073
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003074 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3075
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003076 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003077
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003078 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003079}
3080
3081
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003082/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003083 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003084*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003085void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003086{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003087 QCBORItem OneItemSeach[2];
3088 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3089 OneItemSeach[0].label.int64 = nLabel;
3090 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3091 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003092
Laurence Lundblade9b334962020-08-27 10:55:53 -07003093 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003094 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003095}
3096
3097
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003098/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003099 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003100*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003101void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003102{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003103 QCBORItem OneItemSeach[2];
3104 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3105 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3106 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3107 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003108
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003109 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003110}
3111
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003112/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003113 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003114*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003115void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003116{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003117 QCBORItem OneItemSeach[2];
3118 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3119 OneItemSeach[0].label.int64 = nLabel;
3120 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3121 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003122
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003123 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003124}
3125
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003126/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003127 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003128*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003129void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3130{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003131 QCBORItem OneItemSeach[2];
3132 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3133 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3134 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3135 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003136
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003137 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003138}
3139
3140
Laurence Lundblade02625d42020-06-25 14:41:41 -07003141// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003142void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003143{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003144 QCBORError uErr;
3145
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003146 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003147 if(pMe->uLastError != QCBOR_SUCCESS) {
3148 // Already in error state; do nothing.
3149 return;
3150 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003151
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003152 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003153 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003154 uErr = QCBORDecode_GetNext(pMe, &Item);
3155 if(uErr != QCBOR_SUCCESS) {
3156 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003157 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003158 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003159 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3160 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003161 }
3162
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003163 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003164
3165
Laurence Lundbladef0499502020-08-01 11:55:57 -07003166 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003167 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003168 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3169 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003170 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003171 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3172 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003173 // Special case to increment nesting level for zero-length maps
3174 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003175 DecodeNesting_Descend(&(pMe->nesting), uType);
3176 }
3177
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003178 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003179
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003180 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3181 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003182
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003183 if(pItem != NULL) {
3184 *pItem = Item;
3185 }
3186
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003187Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003188 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003189}
3190
Laurence Lundblade02625d42020-06-25 14:41:41 -07003191
3192/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003193 This is the common work for exiting a level that is a bounded map,
3194 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003195
3196 One chunk of work is to set up the pre-order traversal so it is at
3197 the item just after the bounded map, array or bstr that is being
3198 exited. This is somewhat complex.
3199
3200 The other work is to level-up the bounded mode to next higest bounded
3201 mode or the top level if there isn't one.
3202 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003203static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003204ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003205{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003206 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003207
Laurence Lundblade02625d42020-06-25 14:41:41 -07003208 /*
3209 First the pre-order-traversal byte offset is positioned to the
3210 item just after the bounded mode item that was just consumed.
3211 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003212 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3213
Laurence Lundblade02625d42020-06-25 14:41:41 -07003214 /*
3215 Next, set the current nesting level to one above the bounded level
3216 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003217
Laurence Lundblade02625d42020-06-25 14:41:41 -07003218 DecodeNesting_CheckBoundedType() is always called before this and
3219 makes sure pCurrentBounded is valid.
3220 */
3221 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3222
3223 /*
3224 This does the complex work of leveling up the pre-order traversal
3225 when the end of a map or array or another bounded level is
3226 reached. It may do nothing, or ascend all the way to the top
3227 level.
3228 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07003229 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003230 if(uErr != QCBOR_SUCCESS) {
3231 goto Done;
3232 }
3233
Laurence Lundblade02625d42020-06-25 14:41:41 -07003234 /*
3235 This makes the next highest bounded level the current bounded
3236 level. If there is no next highest level, then no bounded mode is
3237 in effect.
3238 */
3239 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003240
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003241 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003242
3243Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003244 return uErr;
3245}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003246
Laurence Lundblade02625d42020-06-25 14:41:41 -07003247
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003248// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003249void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003250{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003251 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003252 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003253 return;
3254 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003255
Laurence Lundblade02625d42020-06-25 14:41:41 -07003256 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003257
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003258 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003259 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003260 goto Done;
3261 }
3262
Laurence Lundblade02625d42020-06-25 14:41:41 -07003263 /*
3264 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003265 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003266 from previous map search, then do a dummy search.
3267 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003268 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003269 QCBORItem Dummy;
3270 Dummy.uLabelType = QCBOR_TYPE_NONE;
3271 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3272 if(uErr != QCBOR_SUCCESS) {
3273 goto Done;
3274 }
3275 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003276
Laurence Lundblade02625d42020-06-25 14:41:41 -07003277 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003278
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003279Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003280 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003281}
3282
3283
Laurence Lundblade1341c592020-04-11 14:19:05 -07003284
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003285static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003286 const QCBORItem *pItem,
3287 uint8_t uTagRequirement,
3288 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003289{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003290 if(pBstr) {
3291 *pBstr = NULLUsefulBufC;
3292 }
3293
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003294 if(pMe->uLastError != QCBOR_SUCCESS) {
3295 // Already in error state; do nothing.
3296 return pMe->uLastError;
3297 }
3298
3299 QCBORError uError = QCBOR_SUCCESS;
3300
3301 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3302 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3303 goto Done;;
3304 }
3305
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003306 const TagSpecification TagSpec =
3307 {
3308 uTagRequirement,
3309 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3310 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3311 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003312
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003313 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003314 if(uError != QCBOR_SUCCESS) {
3315 goto Done;
3316 }
3317
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003318 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003319 // Reverse the decrement done by GetNext() for the bstr so the
3320 // increment in NestLevelAscender() called by ExitBoundedLevel()
3321 // will work right.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003322 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003323 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003324
3325 if(pBstr) {
3326 *pBstr = pItem->val.string;
3327 }
3328
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003329 // This saves the current length of the UsefulInputBuf and then
3330 // narrows the UsefulInputBuf to start and length of the wrapped
3331 // CBOR that is being entered.
3332 //
3333 // This makes sure the length is less than
3334 // QCBOR_MAX_DECODE_INPUT_SIZE which is slighly less than
3335 // UINT32_MAX. The value UINT32_MAX is used as a special indicator
3336 // value. The checks against QCBOR_MAX_DECODE_INPUT_SIZE also make
3337 // the casts safe. uEndOfBstr will always be less than
3338 // uPreviousLength because of the way UsefulInputBuf works so there
3339 // is no need to check it. There is also a range check in the
3340 // seek.
3341 //
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003342 // Most of these calls are simple inline accessors so this doesn't
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003343 // amount to much code.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003344 // Cast of uPreviousLength to uint32_t for cases where SIZE_MAX < UINT32_MAX.
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003345 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003346 if((uint32_t)uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003347 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003348 goto Done;
3349 }
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003350 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003351 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003352 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003353
Laurence Lundblade02625d42020-06-25 14:41:41 -07003354 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003355 (uint32_t)uPreviousLength,
3356 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003357Done:
3358 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003359}
3360
3361
Laurence Lundblade02625d42020-06-25 14:41:41 -07003362/*
3363 Public function, see header qcbor/qcbor_decode.h file
3364 */
3365void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003366 uint8_t uTagRequirement,
3367 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003368{
3369 if(pMe->uLastError != QCBOR_SUCCESS) {
3370 // Already in error state; do nothing.
3371 return;
3372 }
3373
3374 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003375 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003376 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3377 if(pMe->uLastError != QCBOR_SUCCESS) {
3378 return;
3379 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003380
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003381 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003382 &Item,
3383 uTagRequirement,
3384 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003385}
3386
3387
Laurence Lundblade02625d42020-06-25 14:41:41 -07003388/*
3389 Public function, see header qcbor/qcbor_decode.h file
3390 */
3391void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003392 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003393 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003394 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003395{
3396 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003397 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003398
Laurence Lundblade93d89472020-10-03 22:30:50 -07003399 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3400 &Item,
3401 uTagRequirement,
3402 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003403}
3404
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003405
Laurence Lundblade02625d42020-06-25 14:41:41 -07003406/*
3407 Public function, see header qcbor/qcbor_decode.h file
3408 */
3409void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003410 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003411 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003412 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003413{
3414 QCBORItem Item;
3415 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3416
Laurence Lundblade93d89472020-10-03 22:30:50 -07003417 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3418 &Item,
3419 uTagRequirement,
3420 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003421}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003422
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003423
Laurence Lundblade02625d42020-06-25 14:41:41 -07003424/*
3425 Public function, see header qcbor/qcbor_decode.h file
3426 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003427void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003428{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003429 if(pMe->uLastError != QCBOR_SUCCESS) {
3430 // Already in error state; do nothing.
3431 return;
3432 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003433
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003434 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003435 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003436 return;
3437 }
3438
3439 /*
3440 Reset the length of the UsefulInputBuf to what it was before
3441 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003442 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003443 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003444 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003445
3446
Laurence Lundblade02625d42020-06-25 14:41:41 -07003447 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003448 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003449}
3450
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003451
Laurence Lundbladee6430642020-03-14 21:15:44 -07003452
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003453
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003454
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003455
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003456
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003457
Laurence Lundblade93d89472020-10-03 22:30:50 -07003458static QCBORError
3459InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003460{
3461 switch(pItem->uDataType) {
3462 case QCBOR_TYPE_TRUE:
3463 *pBool = true;
3464 return QCBOR_SUCCESS;
3465 break;
3466
3467 case QCBOR_TYPE_FALSE:
3468 *pBool = false;
3469 return QCBOR_SUCCESS;
3470 break;
3471
3472 default:
3473 return QCBOR_ERR_UNEXPECTED_TYPE;
3474 break;
3475 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003476 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003477}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003478
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003479
Laurence Lundblade9b334962020-08-27 10:55:53 -07003480
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003481/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003482 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003483*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003484void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003485{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003486 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003487 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003488 return;
3489 }
3490
Laurence Lundbladec4537442020-04-14 18:53:22 -07003491 QCBORError nError;
3492 QCBORItem Item;
3493
3494 nError = QCBORDecode_GetNext(pMe, &Item);
3495 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003496 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003497 return;
3498 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003499 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003500}
3501
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003502
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003503/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003504 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003505*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003506void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003507{
3508 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003509 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003510
Laurence Lundblade9b334962020-08-27 10:55:53 -07003511 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003512}
3513
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003514
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003515/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003516 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003517*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003518void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3519{
3520 QCBORItem Item;
3521 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3522
Laurence Lundblade9b334962020-08-27 10:55:53 -07003523 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003524}
3525
3526
3527
Laurence Lundbladec7114722020-08-13 05:11:40 -07003528
3529static void ProcessEpochDate(QCBORDecodeContext *pMe,
3530 QCBORItem *pItem,
3531 uint8_t uTagRequirement,
3532 int64_t *pnTime)
3533{
3534 if(pMe->uLastError != QCBOR_SUCCESS) {
3535 // Already in error state, do nothing
3536 return;
3537 }
3538
3539 QCBORError uErr;
3540
3541 const TagSpecification TagSpec =
3542 {
3543 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003544 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3545 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003546 };
3547
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003548 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003549 if(uErr != QCBOR_SUCCESS) {
3550 goto Done;
3551 }
3552
3553 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3554 uErr = DecodeDateEpoch(pItem);
3555 if(uErr != QCBOR_SUCCESS) {
3556 goto Done;
3557 }
3558 }
3559
Laurence Lundblade9b334962020-08-27 10:55:53 -07003560 // Save the tags in the last item's tags in the decode context
3561 // for QCBORDecode_GetNthTagOfLast()
3562 CopyTags(pMe, pItem);
3563
Laurence Lundbladec7114722020-08-13 05:11:40 -07003564 *pnTime = pItem->val.epochDate.nSeconds;
3565
3566Done:
3567 pMe->uLastError = (uint8_t)uErr;
3568}
3569
3570
3571void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003572 uint8_t uTagRequirement,
3573 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07003574{
3575 if(pMe->uLastError != QCBOR_SUCCESS) {
3576 // Already in error state, do nothing
3577 return;
3578 }
3579
3580 QCBORItem Item;
3581 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3582
3583 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3584}
3585
3586
3587void
3588QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3589 int64_t nLabel,
3590 uint8_t uTagRequirement,
3591 int64_t *pnTime)
3592{
3593 QCBORItem Item;
3594 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3595 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3596}
3597
3598
3599void
3600QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3601 const char *szLabel,
3602 uint8_t uTagRequirement,
3603 int64_t *pnTime)
3604{
3605 QCBORItem Item;
3606 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3607 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3608}
3609
3610
3611
3612
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003613void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3614 TagSpecification TagSpec,
3615 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003616{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003617 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003618 // Already in error state, do nothing
3619 return;
3620 }
3621
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003622 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003623 QCBORItem Item;
3624
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003625 uError = QCBORDecode_GetNext(pMe, &Item);
3626 if(uError != QCBOR_SUCCESS) {
3627 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003628 return;
3629 }
3630
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003631 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003632
3633 if(pMe->uLastError == QCBOR_SUCCESS) {
3634 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003635 } else {
3636 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003637 }
3638}
3639
Laurence Lundbladec4537442020-04-14 18:53:22 -07003640
3641
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003642
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003643static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003644 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003645 UsefulBufC *pValue,
3646 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003647{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003648 const TagSpecification TagSpec =
3649 {
3650 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003651 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3652 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003653 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003654
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003655 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003656 if(uErr != QCBOR_SUCCESS) {
3657 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003658 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003659
3660 *pValue = pItem->val.string;
3661
3662 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3663 *pbIsNegative = false;
3664 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3665 *pbIsNegative = true;
3666 }
3667
3668 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003669}
3670
3671
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003672/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003673 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003674 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003675void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3676 uint8_t uTagRequirement,
3677 UsefulBufC *pValue,
3678 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003679{
3680 if(pMe->uLastError != QCBOR_SUCCESS) {
3681 // Already in error state, do nothing
3682 return;
3683 }
3684
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003685 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003686 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3687 if(uError != QCBOR_SUCCESS) {
3688 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003689 return;
3690 }
3691
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003692 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003693}
3694
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003695
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003696/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003697 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003698*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003699void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3700 int64_t nLabel,
3701 uint8_t uTagRequirement,
3702 UsefulBufC *pValue,
3703 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003704{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003705 QCBORItem Item;
3706 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003707 if(pMe->uLastError != QCBOR_SUCCESS) {
3708 return;
3709 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003710
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003711 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003712}
3713
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003714
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003715/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003716 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003717*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003718void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3719 const char *szLabel,
3720 uint8_t uTagRequirement,
3721 UsefulBufC *pValue,
3722 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003723{
3724 QCBORItem Item;
3725 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003726 if(pMe->uLastError != QCBOR_SUCCESS) {
3727 return;
3728 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003729
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003730 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003731}
3732
3733
3734
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003735
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003736// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003737QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3738 const QCBORItem *pItem,
3739 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07003740 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003741{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003742 const TagSpecification TagSpecText =
3743 {
3744 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003745 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3746 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003747 };
3748 const TagSpecification TagSpecBinary =
3749 {
3750 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003751 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3752 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003753 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003754
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003755 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003756
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003757 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003758 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003759 if(pbIsTag257 != NULL) {
3760 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003761 }
3762 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003763 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003764 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003765 if(pbIsTag257 != NULL) {
3766 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003767 }
3768 uReturn = QCBOR_SUCCESS;
3769
3770 } else {
3771 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3772 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003773
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003774 return uReturn;
3775}
3776
Laurence Lundblade93d89472020-10-03 22:30:50 -07003777// Improvement: add methods for wrapped CBOR, a simple alternate
3778// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003779
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003780
3781
3782
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003783#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003784
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003785typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003786
3787
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003788// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003789static QCBORError
3790Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003791{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003792 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003793
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003794 if(uResult != 0) {
3795 /* This loop will run a maximum of 19 times because
3796 * UINT64_MAX < 10 ^^ 19. More than that will cause
3797 * exit with the overflow error
3798 */
3799 for(; nExponent > 0; nExponent--) {
3800 if(uResult > UINT64_MAX / 10) {
3801 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3802 }
3803 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003804 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003805
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003806 for(; nExponent < 0; nExponent++) {
3807 uResult = uResult / 10;
3808 if(uResult == 0) {
3809 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3810 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003811 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003812 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003813 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003814
3815 *puResult = uResult;
3816
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003817 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003818}
3819
3820
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003821// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003822static QCBORError
3823Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003824{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003825 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003826
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003827 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003828
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003829 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003830 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003831 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003832 */
3833 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003834 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003835 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003836 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003837 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003838 nExponent--;
3839 }
3840
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003841 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003842 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003843 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3844 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003845 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003846 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003847 }
3848
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003849 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003850
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003851 return QCBOR_SUCCESS;
3852}
3853
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003854
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003855/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003856 Compute value with signed mantissa and signed result. Works with
3857 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003858 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003859static inline QCBORError ExponentiateNN(int64_t nMantissa,
3860 int64_t nExponent,
3861 int64_t *pnResult,
3862 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003863{
3864 uint64_t uResult;
3865
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003866 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003867 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003868 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3869
3870 // Do the exponentiation of the positive mantissa
3871 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3872 if(uReturn) {
3873 return uReturn;
3874 }
3875
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003876
Laurence Lundblade983500d2020-05-14 11:49:34 -07003877 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3878 of INT64_MIN. This assumes two's compliment representation where
3879 INT64_MIN is one increment farther from 0 than INT64_MAX.
3880 Trying to write -INT64_MIN doesn't work to get this because the
3881 compiler tries to work with an int64_t which can't represent
3882 -INT64_MIN.
3883 */
3884 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3885
3886 // Error out if too large
3887 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003888 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3889 }
3890
3891 // Casts are safe because of checks above
3892 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3893
3894 return QCBOR_SUCCESS;
3895}
3896
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003897
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003898/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003899 Compute value with signed mantissa and unsigned result. Works with
3900 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003901 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003902static inline QCBORError ExponentitateNU(int64_t nMantissa,
3903 int64_t nExponent,
3904 uint64_t *puResult,
3905 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003906{
3907 if(nMantissa < 0) {
3908 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3909 }
3910
3911 // Cast to unsigned is OK because of check for negative
3912 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3913 // Exponentiation is straight forward
3914 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3915}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003916
3917
3918/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003919 Compute value with signed mantissa and unsigned result. Works with
3920 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003921 */
3922static inline QCBORError ExponentitateUU(uint64_t uMantissa,
3923 int64_t nExponent,
3924 uint64_t *puResult,
3925 fExponentiator pfExp)
3926{
3927 return (*pfExp)(uMantissa, nExponent, puResult);
3928}
3929
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003930#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3931
3932
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003933
3934
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003935
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003936static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003937{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003938 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003939
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003940 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003941 const uint8_t *pByte = BigNum.ptr;
3942 size_t uLen = BigNum.len;
3943 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003944 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003945 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003946 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003947 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003948 }
3949
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003950 *pResult = uResult;
3951 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003952}
3953
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003954
Laurence Lundblade887add82020-05-17 05:50:34 -07003955static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003956{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003957 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003958}
3959
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003960
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003961static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003962{
3963 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003964 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3965 if(uError) {
3966 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003967 }
3968 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3969 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003970 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003971}
3972
3973
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003974static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003975{
3976 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003977 /* The negative integer furthest from zero for a C int64_t is
3978 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
3979 negative number in CBOR is computed as -n - 1 where n is the
3980 encoded integer, where n is what is in the variable BigNum. When
3981 converting BigNum to a uint64_t, the maximum value is thus
3982 INT64_MAX, so that when it -n - 1 is applied to it the result will
3983 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07003984
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003985 -n - 1 <= INT64_MIN.
3986 -n - 1 <= -INT64_MAX - 1
3987 n <= INT64_MAX.
3988 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07003989 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003990 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003991 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003992 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003993
3994 /// Now apply -n - 1. The cast is safe because
3995 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
3996 // is the largest positive integer that an int64_t can
3997 // represent. */
3998 *pnResult = -(int64_t)uResult - 1;
3999
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004000 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004001}
4002
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004003
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004004
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004005
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004006
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004007/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004008Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004009
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004010\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004011
Laurence Lundblade93d89472020-10-03 22:30:50 -07004012\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4013 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004014
4015\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4016
Laurence Lundblade93d89472020-10-03 22:30:50 -07004017\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4018 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004019*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07004020static QCBORError
4021ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004022{
4023 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004024 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004025 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004026#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004027 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004028 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
4029 http://www.cplusplus.com/reference/cmath/llround/
4030 */
4031 // Not interested in FE_INEXACT
4032 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004033 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4034 *pnValue = llround(pItem->val.dfnum);
4035 } else {
4036 *pnValue = lroundf(pItem->val.fnum);
4037 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004038 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4039 // llround() shouldn't result in divide by zero, but catch
4040 // it here in case it unexpectedly does. Don't try to
4041 // distinguish between the various exceptions because it seems
4042 // they vary by CPU, compiler and OS.
4043 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004044 }
4045 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004046 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004047 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004048#else
4049 return QCBOR_ERR_HW_FLOAT_DISABLED;
4050#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004051 break;
4052
4053 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004054 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004055 *pnValue = pItem->val.int64;
4056 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004057 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004058 }
4059 break;
4060
4061 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004062 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004063 if(pItem->val.uint64 < INT64_MAX) {
4064 *pnValue = pItem->val.int64;
4065 } else {
4066 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4067 }
4068 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004069 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004070 }
4071 break;
4072
4073 default:
4074 return QCBOR_ERR_UNEXPECTED_TYPE;
4075 }
4076 return QCBOR_SUCCESS;
4077}
4078
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004079
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004080void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004081 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004082 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004083 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004084{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004085 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004086 return;
4087 }
4088
Laurence Lundbladee6430642020-03-14 21:15:44 -07004089 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004090 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4091 if(uError) {
4092 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004093 return;
4094 }
4095
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004096 if(pItem) {
4097 *pItem = Item;
4098 }
4099
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004100 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004101}
4102
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004103
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004104void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4105 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004106 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004107 int64_t *pnValue,
4108 QCBORItem *pItem)
4109{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004110 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004111 if(pMe->uLastError != QCBOR_SUCCESS) {
4112 return;
4113 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004114
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004115 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004116}
4117
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004118
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004119void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4120 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004121 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004122 int64_t *pnValue,
4123 QCBORItem *pItem)
4124{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004125 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004126 if(pMe->uLastError != QCBOR_SUCCESS) {
4127 return;
4128 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004129
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004130 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004131}
4132
4133
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004134/*
4135 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004136
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004137 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004138
Laurence Lundblade93d89472020-10-03 22:30:50 -07004139 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4140 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004141
4142 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4143
Laurence Lundblade93d89472020-10-03 22:30:50 -07004144 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4145 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004146 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004147static QCBORError
4148Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004149{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004150 switch(pItem->uDataType) {
4151
4152 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004153 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004154 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004155 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004156 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004157 }
4158 break;
4159
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004160 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004161 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004162 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004163 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004164 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004165 }
4166 break;
4167
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004168#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4169 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004170 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004171 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004172 pItem->val.expAndMantissa.nExponent,
4173 pnValue,
4174 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004175 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004176 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004177 }
4178 break;
4179
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004180 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004181 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004182 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004183 pItem->val.expAndMantissa.nExponent,
4184 pnValue,
4185 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004186 } 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
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004191 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004192 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004193 int64_t nMantissa;
4194 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004195 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4196 if(uErr) {
4197 return uErr;
4198 }
4199 return ExponentiateNN(nMantissa,
4200 pItem->val.expAndMantissa.nExponent,
4201 pnValue,
4202 Exponentitate10);
4203 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004204 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004205 }
4206 break;
4207
4208 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004209 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004210 int64_t nMantissa;
4211 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004212 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4213 if(uErr) {
4214 return uErr;
4215 }
4216 return ExponentiateNN(nMantissa,
4217 pItem->val.expAndMantissa.nExponent,
4218 pnValue,
4219 Exponentitate10);
4220 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004221 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004222 }
4223 break;
4224
4225 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004226 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004227 int64_t nMantissa;
4228 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004229 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4230 if(uErr) {
4231 return uErr;
4232 }
4233 return ExponentiateNN(nMantissa,
4234 pItem->val.expAndMantissa.nExponent,
4235 pnValue,
4236 Exponentitate2);
4237 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004238 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004239 }
4240 break;
4241
4242 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004243 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004244 int64_t nMantissa;
4245 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004246 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4247 if(uErr) {
4248 return uErr;
4249 }
4250 return ExponentiateNN(nMantissa,
4251 pItem->val.expAndMantissa.nExponent,
4252 pnValue,
4253 Exponentitate2);
4254 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004255 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004256 }
4257 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004258#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4259
Laurence Lundbladee6430642020-03-14 21:15:44 -07004260
Laurence Lundbladec4537442020-04-14 18:53:22 -07004261 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004262 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004263}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004264
4265
Laurence Lundbladec4537442020-04-14 18:53:22 -07004266/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004267 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004268 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004269void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004270{
4271 QCBORItem Item;
4272
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004273 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004274
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004275 if(pMe->uLastError == QCBOR_SUCCESS) {
4276 // The above conversion succeeded
4277 return;
4278 }
4279
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004280 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004281 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004282 return;
4283 }
4284
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004285 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004286}
4287
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004288
4289/*
4290Public function, see header qcbor/qcbor_decode.h file
4291*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004292void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4293 int64_t nLabel,
4294 uint32_t uConvertTypes,
4295 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004296{
4297 QCBORItem Item;
4298
Laurence Lundblade93d89472020-10-03 22:30:50 -07004299 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4300 nLabel,
4301 uConvertTypes,
4302 pnValue,
4303 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004304
4305 if(pMe->uLastError == QCBOR_SUCCESS) {
4306 // The above conversion succeeded
4307 return;
4308 }
4309
4310 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4311 // The above conversion failed in a way that code below can't correct
4312 return;
4313 }
4314
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004315 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004316}
4317
4318
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004319/*
4320Public function, see header qcbor/qcbor_decode.h file
4321*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004322void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4323 const char *szLabel,
4324 uint32_t uConvertTypes,
4325 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004326{
4327 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004328 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4329 szLabel,
4330 uConvertTypes,
4331 pnValue,
4332 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004333
4334 if(pMe->uLastError == QCBOR_SUCCESS) {
4335 // The above conversion succeeded
4336 return;
4337 }
4338
4339 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4340 // The above conversion failed in a way that code below can't correct
4341 return;
4342 }
4343
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004344 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004345}
4346
4347
Laurence Lundblade93d89472020-10-03 22:30:50 -07004348static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004349{
4350 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004351 case QCBOR_TYPE_DOUBLE:
4352 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004353#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004354 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004355 // Can't use llround here because it will not convert values
4356 // greater than INT64_MAX and less than UINT64_MAX that
4357 // need to be converted so it is more complicated.
4358 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4359 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4360 if(isnan(pItem->val.dfnum)) {
4361 return QCBOR_ERR_FLOAT_EXCEPTION;
4362 } else if(pItem->val.dfnum < 0) {
4363 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4364 } else {
4365 double dRounded = round(pItem->val.dfnum);
4366 // See discussion in DecodeDateEpoch() for
4367 // explanation of - 0x7ff
4368 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4369 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4370 }
4371 *puValue = (uint64_t)dRounded;
4372 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004373 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004374 if(isnan(pItem->val.fnum)) {
4375 return QCBOR_ERR_FLOAT_EXCEPTION;
4376 } else if(pItem->val.fnum < 0) {
4377 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4378 } else {
4379 float fRounded = roundf(pItem->val.fnum);
4380 // See discussion in DecodeDateEpoch() for
4381 // explanation of - 0x7ff
4382 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4383 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4384 }
4385 *puValue = (uint64_t)fRounded;
4386 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004387 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004388 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4389 // round() and roundf() shouldn't result in exceptions here, but
4390 // catch them to be robust and thorough. Don't try to
4391 // distinguish between the various exceptions because it seems
4392 // they vary by CPU, compiler and OS.
4393 return QCBOR_ERR_FLOAT_EXCEPTION;
4394 }
4395
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004396 } else {
4397 return QCBOR_ERR_UNEXPECTED_TYPE;
4398 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004399#else
4400 return QCBOR_ERR_HW_FLOAT_DISABLED;
4401#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004402 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004403
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004404 case QCBOR_TYPE_INT64:
4405 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4406 if(pItem->val.int64 >= 0) {
4407 *puValue = (uint64_t)pItem->val.int64;
4408 } else {
4409 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4410 }
4411 } else {
4412 return QCBOR_ERR_UNEXPECTED_TYPE;
4413 }
4414 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004415
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004416 case QCBOR_TYPE_UINT64:
4417 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4418 *puValue = pItem->val.uint64;
4419 } else {
4420 return QCBOR_ERR_UNEXPECTED_TYPE;
4421 }
4422 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004423
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004424 default:
4425 return QCBOR_ERR_UNEXPECTED_TYPE;
4426 }
4427
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004428 return QCBOR_SUCCESS;
4429}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004430
4431
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004432void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004433 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004434 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004435 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004436{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004437 if(pMe->uLastError != QCBOR_SUCCESS) {
4438 return;
4439 }
4440
Laurence Lundbladec4537442020-04-14 18:53:22 -07004441 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004442
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004443 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4444 if(uError) {
4445 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004446 return;
4447 }
4448
Laurence Lundbladea826c502020-05-10 21:07:00 -07004449 if(pItem) {
4450 *pItem = Item;
4451 }
4452
Laurence Lundblade93d89472020-10-03 22:30:50 -07004453 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004454}
4455
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004456
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004457void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004458 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004459 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004460 uint64_t *puValue,
4461 QCBORItem *pItem)
4462{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004463 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004464 if(pMe->uLastError != QCBOR_SUCCESS) {
4465 return;
4466 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004467
Laurence Lundblade93d89472020-10-03 22:30:50 -07004468 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004469}
4470
4471
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004472void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004473 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004474 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004475 uint64_t *puValue,
4476 QCBORItem *pItem)
4477{
4478 if(pMe->uLastError != QCBOR_SUCCESS) {
4479 return;
4480 }
4481
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004482 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004483 if(pMe->uLastError != QCBOR_SUCCESS) {
4484 return;
4485 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004486
Laurence Lundblade93d89472020-10-03 22:30:50 -07004487 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004488}
4489
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004490
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004491
Laurence Lundblade93d89472020-10-03 22:30:50 -07004492static QCBORError
4493UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004494{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004495 switch(pItem->uDataType) {
4496
4497 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004498 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004499 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4500 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004501 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004502 }
4503 break;
4504
4505 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004506 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004507 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4508 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004509 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004510 }
4511 break;
4512
4513#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4514
4515 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004516 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004517 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004518 pItem->val.expAndMantissa.nExponent,
4519 puValue,
4520 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004521 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004522 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004523 }
4524 break;
4525
4526 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004527 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004528 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4529 pItem->val.expAndMantissa.nExponent,
4530 puValue,
4531 Exponentitate2);
4532 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004533 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004534 }
4535 break;
4536
4537 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004538 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004539 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004540 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004541 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004542 if(uErr != QCBOR_SUCCESS) {
4543 return uErr;
4544 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004545 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004546 pItem->val.expAndMantissa.nExponent,
4547 puValue,
4548 Exponentitate10);
4549 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004550 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004551 }
4552 break;
4553
4554 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004555 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004556 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4557 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004558 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004559 }
4560 break;
4561
4562 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004563 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004564 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004565 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004566 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004567 if(uErr != QCBOR_SUCCESS) {
4568 return uErr;
4569 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004570 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004571 pItem->val.expAndMantissa.nExponent,
4572 puValue,
4573 Exponentitate2);
4574 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004575 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004576 }
4577 break;
4578
4579 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004580 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004581 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4582 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004583 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004584 }
4585 break;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004586#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004587 default:
4588 return QCBOR_ERR_UNEXPECTED_TYPE;
4589 }
4590}
4591
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004592
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004593/*
4594 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004595 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004596void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004597{
4598 QCBORItem Item;
4599
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004600 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004601
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004602 if(pMe->uLastError == QCBOR_SUCCESS) {
4603 // The above conversion succeeded
4604 return;
4605 }
4606
4607 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4608 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004609 return;
4610 }
4611
Laurence Lundblade93d89472020-10-03 22:30:50 -07004612 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004613}
4614
Laurence Lundbladec4537442020-04-14 18:53:22 -07004615
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004616/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004617 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004618*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004619void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004620 int64_t nLabel,
4621 uint32_t uConvertTypes,
4622 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004623{
4624 QCBORItem Item;
4625
Laurence Lundblade93d89472020-10-03 22:30:50 -07004626 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
4627 nLabel,
4628 uConvertTypes,
4629 puValue,
4630 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004631
4632 if(pMe->uLastError == QCBOR_SUCCESS) {
4633 // The above conversion succeeded
4634 return;
4635 }
4636
4637 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4638 // The above conversion failed in a way that code below can't correct
4639 return;
4640 }
4641
Laurence Lundblade93d89472020-10-03 22:30:50 -07004642 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004643}
4644
4645
4646/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004647 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004648*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004649void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004650 const char *szLabel,
4651 uint32_t uConvertTypes,
4652 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004653{
4654 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004655 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
4656 szLabel,
4657 uConvertTypes,
4658 puValue,
4659 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004660
4661 if(pMe->uLastError == QCBOR_SUCCESS) {
4662 // The above conversion succeeded
4663 return;
4664 }
4665
4666 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4667 // The above conversion failed in a way that code below can't correct
4668 return;
4669 }
4670
Laurence Lundblade93d89472020-10-03 22:30:50 -07004671 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004672}
4673
4674
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004675
4676
Laurence Lundblade9b334962020-08-27 10:55:53 -07004677static QCBORError ConvertDouble(const QCBORItem *pItem,
4678 uint32_t uConvertTypes,
4679 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004680{
4681 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004682 case QCBOR_TYPE_FLOAT:
4683#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4684 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4685 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004686 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004687 *pdValue = (double)pItem->val.fnum;
4688 } else {
4689 return QCBOR_ERR_UNEXPECTED_TYPE;
4690 }
4691 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004692#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004693 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004694#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004695 break;
4696
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004697 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004698 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4699 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004700 *pdValue = pItem->val.dfnum;
4701 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004702 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004703 }
4704 }
4705 break;
4706
4707 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004708#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004709 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004710 // A simple cast seems to do the job with no worry of exceptions.
4711 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004712 *pdValue = (double)pItem->val.int64;
4713
4714 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004715 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004716 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004717#else
4718 return QCBOR_ERR_HW_FLOAT_DISABLED;
4719#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004720 break;
4721
4722 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004723#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004724 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004725 // A simple cast seems to do the job with no worry of exceptions.
4726 // There will be precision loss for some values.
4727 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004728 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004729 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004730 }
4731 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004732#else
4733 return QCBOR_ERR_HW_FLOAT_DISABLED;
4734#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004735
4736 default:
4737 return QCBOR_ERR_UNEXPECTED_TYPE;
4738 }
4739
4740 return QCBOR_SUCCESS;
4741}
4742
4743
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004744void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004745 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004746 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004747 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004748{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004749 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004750 return;
4751 }
4752
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004753 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004754
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004755 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004756 if(uError) {
4757 pMe->uLastError = (uint8_t)uError;
4758 return;
4759 }
4760
4761 if(pItem) {
4762 *pItem = Item;
4763 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004764
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004765 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004766}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004767
Laurence Lundbladec4537442020-04-14 18:53:22 -07004768
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004769void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4770 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004771 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004772 double *pdValue,
4773 QCBORItem *pItem)
4774{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004775 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004776 if(pMe->uLastError != QCBOR_SUCCESS) {
4777 return;
4778 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004779
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004780 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004781}
4782
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004783
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004784void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4785 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004786 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004787 double *pdValue,
4788 QCBORItem *pItem)
4789{
4790 if(pMe->uLastError != QCBOR_SUCCESS) {
4791 return;
4792 }
4793
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004794 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004795 if(pMe->uLastError != QCBOR_SUCCESS) {
4796 return;
4797 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004798
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004799 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004800}
4801
4802
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004803#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004804static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4805{
4806 double dResult;
4807
4808 dResult = 0.0;
4809 const uint8_t *pByte = BigNum.ptr;
4810 size_t uLen = BigNum.len;
4811 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004812 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004813 while(uLen--) {
4814 dResult = (dResult * 256.0) + (double)*pByte++;
4815 }
4816
4817 return dResult;
4818}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004819#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4820
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004821
Laurence Lundblade93d89472020-10-03 22:30:50 -07004822static QCBORError
4823DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004824{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004825#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004826 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004827 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4828
4829 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004830 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004831
4832#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004833 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004834 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004835 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004836 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4837 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4838 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004839 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004840 }
4841 break;
4842
4843 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004844 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004845 // Underflow gives 0, overflow gives infinity
4846 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4847 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004848 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004849 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004850 }
4851 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004852#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004853
4854 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004855 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004856 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4857 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004858 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004859 }
4860 break;
4861
4862 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004863 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004864 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004865 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004866 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004867 }
4868 break;
4869
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004870#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004871 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004872 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004873 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4874 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4875 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004876 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004877 }
4878 break;
4879
4880 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004881 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004882 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4883 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4884 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004885 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004886 }
4887 break;
4888
4889 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004890 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004891 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4892 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4893 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004894 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004895 }
4896 break;
4897
4898 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004899 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004900 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004901 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4902 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004903 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004904 }
4905 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004906#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4907
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004908 default:
4909 return QCBOR_ERR_UNEXPECTED_TYPE;
4910 }
4911
4912 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004913
4914#else
4915 (void)pItem;
4916 (void)uConvertTypes;
4917 (void)pdValue;
4918 return QCBOR_ERR_HW_FLOAT_DISABLED;
4919#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4920
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004921}
4922
4923
4924/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004925 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004926*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004927void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
4928 uint32_t uConvertTypes,
4929 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004930{
4931
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004932 QCBORItem Item;
4933
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004934 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004935
4936 if(pMe->uLastError == QCBOR_SUCCESS) {
4937 // The above conversion succeeded
4938 return;
4939 }
4940
4941 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4942 // The above conversion failed in a way that code below can't correct
4943 return;
4944 }
4945
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004946 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004947}
4948
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004949
4950/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004951 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004952*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004953void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
4954 int64_t nLabel,
4955 uint32_t uConvertTypes,
4956 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004957{
4958 QCBORItem Item;
4959
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004960 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004961
4962 if(pMe->uLastError == QCBOR_SUCCESS) {
4963 // The above conversion succeeded
4964 return;
4965 }
4966
4967 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4968 // The above conversion failed in a way that code below can't correct
4969 return;
4970 }
4971
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004972 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004973}
4974
4975
4976/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004977 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004978*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004979void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
4980 const char *szLabel,
4981 uint32_t uConvertTypes,
4982 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004983{
4984 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004985 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004986
4987 if(pMe->uLastError == QCBOR_SUCCESS) {
4988 // The above conversion succeeded
4989 return;
4990 }
4991
4992 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4993 // The above conversion failed in a way that code below can't correct
4994 return;
4995 }
4996
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004997 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004998}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004999
5000
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005001
5002
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005003#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005004static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
5005{
5006 while((uInt & 0xff00000000000000UL) == 0) {
5007 uInt = uInt << 8;
5008 };
5009
5010 UsefulOutBuf UOB;
5011
5012 UsefulOutBuf_Init(&UOB, Buffer);
5013
5014 while(uInt) {
5015 const uint64_t xx = uInt & 0xff00000000000000UL;
5016 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
5017 uInt = uInt << 8;
5018 (void)xx;
5019 }
5020
5021 return UsefulOutBuf_OutUBuf(&UOB);
5022}
5023
5024
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005025static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
5026 TagSpecification TagSpec,
5027 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005028{
5029 QCBORError uErr;
5030 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005031 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07005032 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005033 if(uErr != QCBOR_SUCCESS) {
5034 goto Done;
5035 }
5036
5037 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
5038 break; // Successful exit. Moving on to finish decoding.
5039 }
5040
5041 // The item is an array, which means an undecoded
5042 // mantissa and exponent, so decode it. It will then
5043 // have a different type and exit the loop if.
5044 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
5045 if(uErr != QCBOR_SUCCESS) {
5046 goto Done;
5047 }
5048
5049 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07005050 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005051 }
5052Done:
5053 return uErr;
5054}
5055
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005056
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005057static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005058 TagSpecification TagSpec,
5059 QCBORItem *pItem,
5060 int64_t *pnMantissa,
5061 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005062{
5063 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005064
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005065 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005066 if(uErr != QCBOR_SUCCESS) {
5067 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005068 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005069
Laurence Lundblade9b334962020-08-27 10:55:53 -07005070 switch (pItem->uDataType) {
5071
5072 case QCBOR_TYPE_DECIMAL_FRACTION:
5073 case QCBOR_TYPE_BIGFLOAT:
5074 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5075 *pnExponent = pItem->val.expAndMantissa.nExponent;
5076 break;
5077
5078 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5079 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5080 *pnExponent = pItem->val.expAndMantissa.nExponent;
5081 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5082 break;
5083
5084 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5085 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5086 *pnExponent = pItem->val.expAndMantissa.nExponent;
5087 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5088 break;
5089
5090 default:
5091 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5092 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005093
5094 Done:
5095 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005096}
5097
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005098
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005099static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005100 TagSpecification TagSpec,
5101 QCBORItem *pItem,
5102 UsefulBuf BufferForMantissa,
5103 UsefulBufC *pMantissa,
5104 bool *pbIsNegative,
5105 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005106{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005107 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005108
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005109 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005110 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005111 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005112 }
5113
5114 uint64_t uMantissa;
5115
5116 switch (pItem->uDataType) {
5117
5118 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005119 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005120 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5121 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5122 *pbIsNegative = false;
5123 } else {
5124 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5125 *pbIsNegative = true;
5126 }
5127 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5128 *pnExponent = pItem->val.expAndMantissa.nExponent;
5129 break;
5130
5131 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005132 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005133 *pnExponent = pItem->val.expAndMantissa.nExponent;
5134 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5135 *pbIsNegative = false;
5136 break;
5137
5138 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005139 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005140 *pnExponent = pItem->val.expAndMantissa.nExponent;
5141 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5142 *pbIsNegative = true;
5143 break;
5144
5145 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005146 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005147 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005148
5149Done:
5150 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005151}
5152
5153
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005154/*
5155 Public function, see header qcbor/qcbor_decode.h file
5156*/
5157void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5158 uint8_t uTagRequirement,
5159 int64_t *pnMantissa,
5160 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005161{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005162 if(pMe->uLastError != QCBOR_SUCCESS) {
5163 return;
5164 }
5165
5166 QCBORItem Item;
5167 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5168 if(uError) {
5169 pMe->uLastError = (uint8_t)uError;
5170 return;
5171 }
5172
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005173 const TagSpecification TagSpec =
5174 {
5175 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005176 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5177 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5178 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005179 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005180
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005181 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005182}
5183
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005184
5185/*
5186 Public function, see header qcbor/qcbor_decode.h file
5187*/
5188void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005189 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005190 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005191 int64_t *pnMantissa,
5192 int64_t *pnExponent)
5193{
5194 if(pMe->uLastError != QCBOR_SUCCESS) {
5195 return;
5196 }
5197
5198 QCBORItem Item;
5199 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5200
5201 const TagSpecification TagSpec =
5202 {
5203 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005204 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5205 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5206 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005207 };
5208
5209 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5210}
5211
5212
5213/*
5214 Public function, see header qcbor/qcbor_decode.h file
5215*/
5216void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005217 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005218 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005219 int64_t *pnMantissa,
5220 int64_t *pnExponent)
5221{
5222 if(pMe->uLastError != QCBOR_SUCCESS) {
5223 return;
5224 }
5225
5226 QCBORItem Item;
5227 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5228
5229 const TagSpecification TagSpec =
5230 {
5231 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005232 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5233 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5234 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005235 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005236
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005237 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5238}
5239
5240
5241/*
5242 Public function, see header qcbor/qcbor_decode.h file
5243*/
5244void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5245 uint8_t uTagRequirement,
5246 UsefulBuf MantissaBuffer,
5247 UsefulBufC *pMantissa,
5248 bool *pbMantissaIsNegative,
5249 int64_t *pnExponent)
5250{
5251 if(pMe->uLastError != QCBOR_SUCCESS) {
5252 return;
5253 }
5254
5255 QCBORItem Item;
5256 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5257 if(uError) {
5258 pMe->uLastError = (uint8_t)uError;
5259 return;
5260 }
5261
5262 const TagSpecification TagSpec =
5263 {
5264 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005265 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5266 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5267 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005268 };
5269
Laurence Lundblade93d89472020-10-03 22:30:50 -07005270 ProcessMantissaAndExponentBig(pMe,
5271 TagSpec,
5272 &Item,
5273 MantissaBuffer,
5274 pMantissa,
5275 pbMantissaIsNegative,
5276 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005277}
5278
5279
5280/*
5281 Public function, see header qcbor/qcbor_decode.h file
5282*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005283void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005284 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005285 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005286 UsefulBuf BufferForMantissa,
5287 UsefulBufC *pMantissa,
5288 bool *pbIsNegative,
5289 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005290{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005291 if(pMe->uLastError != QCBOR_SUCCESS) {
5292 return;
5293 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005294
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005295 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005296 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005297 if(pMe->uLastError != QCBOR_SUCCESS) {
5298 return;
5299 }
5300
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005301 const TagSpecification TagSpec =
5302 {
5303 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005304 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5305 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5306 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005307 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005308
Laurence Lundblade93d89472020-10-03 22:30:50 -07005309 ProcessMantissaAndExponentBig(pMe,
5310 TagSpec,
5311 &Item,
5312 BufferForMantissa,
5313 pMantissa,
5314 pbIsNegative,
5315 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005316}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005317
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005318
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005319/*
5320 Public function, see header qcbor/qcbor_decode.h file
5321*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005322void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005323 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005324 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005325 UsefulBuf BufferForMantissa,
5326 UsefulBufC *pMantissa,
5327 bool *pbIsNegative,
5328 int64_t *pnExponent)
5329{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005330 if(pMe->uLastError != QCBOR_SUCCESS) {
5331 return;
5332 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005333
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005334 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005335 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5336 if(pMe->uLastError != QCBOR_SUCCESS) {
5337 return;
5338 }
5339
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005340 const TagSpecification TagSpec =
5341 {
5342 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005343 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5344 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5345 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005346 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005347
5348 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5349}
5350
5351
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005352/*
5353 Public function, see header qcbor/qcbor_decode.h file
5354*/
5355void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5356 uint8_t uTagRequirement,
5357 int64_t *pnMantissa,
5358 int64_t *pnExponent)
5359{
5360 if(pMe->uLastError != QCBOR_SUCCESS) {
5361 return;
5362 }
5363
5364 QCBORItem Item;
5365 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5366 if(uError) {
5367 pMe->uLastError = (uint8_t)uError;
5368 return;
5369 }
5370 const TagSpecification TagSpec =
5371 {
5372 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005373 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5374 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5375 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005376 };
5377
5378 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5379}
5380
5381
5382/*
5383 Public function, see header qcbor/qcbor_decode.h file
5384*/
5385void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005386 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005387 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005388 int64_t *pnMantissa,
5389 int64_t *pnExponent)
5390{
5391 if(pMe->uLastError != QCBOR_SUCCESS) {
5392 return;
5393 }
5394
5395 QCBORItem Item;
5396 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5397 if(pMe->uLastError != QCBOR_SUCCESS) {
5398 return;
5399 }
5400
5401 const TagSpecification TagSpec =
5402 {
5403 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005404 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5405 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5406 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005407 };
5408
5409 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5410}
5411
5412
5413/*
5414 Public function, see header qcbor/qcbor_decode.h file
5415*/
5416void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005417 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005418 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005419 int64_t *pnMantissa,
5420 int64_t *pnExponent)
5421{
5422 if(pMe->uLastError != QCBOR_SUCCESS) {
5423 return;
5424 }
5425
5426 QCBORItem Item;
5427 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5428 if(pMe->uLastError != QCBOR_SUCCESS) {
5429 return;
5430 }
5431
5432 const TagSpecification TagSpec =
5433 {
5434 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005435 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5436 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5437 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005438 };
5439
5440 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5441}
5442
5443
5444/*
5445 Public function, see header qcbor/qcbor_decode.h file
5446*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005447void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5448 uint8_t uTagRequirement,
5449 UsefulBuf MantissaBuffer,
5450 UsefulBufC *pMantissa,
5451 bool *pbMantissaIsNegative,
5452 int64_t *pnExponent)
5453{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005454 if(pMe->uLastError != QCBOR_SUCCESS) {
5455 return;
5456 }
5457
5458 QCBORItem Item;
5459 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5460 if(uError) {
5461 pMe->uLastError = (uint8_t)uError;
5462 return;
5463 }
5464
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005465 const TagSpecification TagSpec =
5466 {
5467 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005468 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5469 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5470 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005471 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005472
5473 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005474}
5475
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005476
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005477/*
5478 Public function, see header qcbor/qcbor_decode.h file
5479*/
5480void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005481 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005482 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005483 UsefulBuf BufferForMantissa,
5484 UsefulBufC *pMantissa,
5485 bool *pbIsNegative,
5486 int64_t *pnExponent)
5487{
5488 if(pMe->uLastError != QCBOR_SUCCESS) {
5489 return;
5490 }
5491
5492 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005493 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5494 if(pMe->uLastError != QCBOR_SUCCESS) {
5495 return;
5496 }
5497
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005498 const TagSpecification TagSpec =
5499 {
5500 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005501 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5502 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5503 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005504 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005505
Laurence Lundblade93d89472020-10-03 22:30:50 -07005506 ProcessMantissaAndExponentBig(pMe,
5507 TagSpec,
5508 &Item,
5509 BufferForMantissa,
5510 pMantissa,
5511 pbIsNegative,
5512 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005513}
5514
5515
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005516/*
5517 Public function, see header qcbor/qcbor_decode.h file
5518*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005519void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005520 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005521 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005522 UsefulBuf BufferForMantissa,
5523 UsefulBufC *pMantissa,
5524 bool *pbIsNegative,
5525 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005526{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005527 if(pMe->uLastError != QCBOR_SUCCESS) {
5528 return;
5529 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005530
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005531 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005532 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5533 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005534 return;
5535 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005536
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005537 const TagSpecification TagSpec =
5538 {
5539 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005540 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5541 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5542 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005543 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005544
Laurence Lundblade93d89472020-10-03 22:30:50 -07005545 ProcessMantissaAndExponentBig(pMe,
5546 TagSpec,
5547 &Item,
5548 BufferForMantissa,
5549 pMantissa,
5550 pbIsNegative,
5551 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005552}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005553
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005554#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */