blob: f463e628f90839f9c6613beba7a088acbb6abe8c [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
Laurence Lundbladed92a6162018-11-01 11:38:35 +07002 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundbladea3336842021-01-03 12:38:36 -08003 Copyright (c) 2018-2021, Laurence Lundblade.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07004 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08005
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07006Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are
8met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15 * Neither the name of The Linux Foundation nor the names of its
16 contributors, nor the name "Laurence Lundblade" may be used to
17 endorse or promote products derived from this software without
18 specific prior written permission.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080019
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070020THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080031 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070032
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080033
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080034#include "qcbor/qcbor_decode.h"
Laurence Lundblade67257dc2020-07-27 03:33:37 -070035#include "qcbor/qcbor_spiffy_decode.h"
Laurence Lundblade6474c982020-12-26 22:14:34 -080036#include "ieee754.h" /* Does not use math.h */
Laurence Lundbladec7114722020-08-13 05:11:40 -070037
38#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade53b945a2020-12-27 02:05:01 -080039
Laurence Lundblade6474c982020-12-26 22:14:34 -080040#include <math.h> /* For isnan(), llround(), llroudf(), round(), roundf(),
41 * pow(), exp2()
42 */
43#include <fenv.h> /* feclearexcept(), fetestexcept() */
Laurence Lundblade53b945a2020-12-27 02:05:01 -080044
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080045#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070046
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070047
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070048
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053049/*
Laurence Lundblade6474c982020-12-26 22:14:34 -080050 * This casts away the const-ness of a pointer, usually so it can be
51 * freed or realloced.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053052 */
53#define UNCONST_POINTER(ptr) ((void *)(ptr))
54
Laurence Lundbladea9489f82020-09-12 13:50:56 -070055#define SIZEOF_C_ARRAY(array,type) (sizeof(array)/sizeof(type))
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070056
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070057
Laurence Lundblade6474c982020-12-26 22:14:34 -080058
59
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070060static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070061QCBORItem_IsMapOrArray(const QCBORItem *pMe)
62{
63 const uint8_t uDataType = pMe->uDataType;
64 return uDataType == QCBOR_TYPE_MAP ||
65 uDataType == QCBOR_TYPE_ARRAY ||
66 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
67}
68
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070069static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070070QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem *pMe)
71{
72 if(!QCBORItem_IsMapOrArray(pMe)){
73 return false;
74 }
75
76 if(pMe->val.uCount != 0) {
77 return false;
78 }
79 return true;
80}
81
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070082static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070083QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem *pMe)
84{
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080085#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -070086 if(!QCBORItem_IsMapOrArray(pMe)){
87 return false;
88 }
89
90 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
91 return false;
92 }
93 return true;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080094#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
95 (void)pMe;
96 return false;
97#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade02625d42020-06-25 14:41:41 -070098}
99
100
Laurence Lundbladeee851742020-01-08 08:37:05 -0800101/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700102 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -0800103 ===========================================================================*/
104
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700105/*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800106 * See comments about and typedef of QCBORDecodeNesting in qcbor_private.h,
107 * the data structure all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700108 */
109
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700110
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700111static inline uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700112DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700113{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700114 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade6474c982020-12-26 22:14:34 -0800115 /* Limit in DecodeNesting_Descend against more than
116 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700117 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700118 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700119}
120
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700121
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700122static inline uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700123DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700124{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700125 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade6474c982020-12-26 22:14:34 -0800126 /* Limit in DecodeNesting_Descend against more than
127 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700128 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700129 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700130}
131
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700132
Laurence Lundblade5f4e8712020-07-25 11:44:43 -0700133static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700134DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700135{
136 return pNesting->pCurrentBounded->u.ma.uStartOffset;
137}
138
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700139
Laurence Lundblade085d7952020-07-24 10:26:30 -0700140static inline bool
141DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
142{
143 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
144 return true;
145 } else {
146 return false;
147 }
148}
149
150
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700151static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700152DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700153{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700154 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700155 return true;
156 } else {
157 return false;
158 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700159}
160
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700161
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700162static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700163DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700164{
165 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800166 /* Not a map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700167 return false;
168 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800169
170#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700171 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800172 /* Is indefinite */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700173 return false;
174 }
Laurence Lundblade53b945a2020-12-27 02:05:01 -0800175
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800176#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
177
Laurence Lundblade6474c982020-12-26 22:14:34 -0800178 /* All checks passed; is a definte length map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700179 return true;
180}
181
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700182static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700183DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700184{
185 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800186 /* is a byte string */
Laurence Lundblade642282a2020-06-23 12:00:33 -0700187 return true;
188 }
189 return false;
190}
191
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700192
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700193static inline bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700194{
195 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
196 return true;
197 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700198 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700199 return true;
200 }
201 return false;
202}
203
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700204
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700205static inline void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700206{
Laurence Lundblade6474c982020-12-26 22:14:34 -0800207 /* Should be only called on maps and arrays */
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700208 /*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800209 * DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
210 * larger than DecodeNesting_EnterBoundedMode which keeps it less than
211 * uin32_t so the cast is safe.
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700212 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700213 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700214
215 if(bIsEmpty) {
216 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
217 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700218}
219
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700220
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700221static inline void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700222{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700223 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700224}
225
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700226
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700227static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700228DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700229{
230 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800231 /* No bounded map or array set up */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700232 return false;
233 }
234 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800235 /* Not a map or array; end of those is by byte count */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700236 return false;
237 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700238 if(!DecodeNesting_IsCurrentBounded(pNesting)) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800239 /* In a traveral at a level deeper than the bounded level */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700240 return false;
241 }
Laurence Lundblade6474c982020-12-26 22:14:34 -0800242 /* Works for both definite and indefinite length maps/arrays */
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800243 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0 &&
244 pNesting->pCurrentBounded->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800245 /* Count is not zero, still unconsumed item */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700246 return false;
247 }
Laurence Lundblade6474c982020-12-26 22:14:34 -0800248 /* All checks passed, got to the end of an array or map*/
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700249 return true;
250}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700251
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700252
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700253static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700254DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700255{
Laurence Lundblade6474c982020-12-26 22:14:34 -0800256 /* Must only be called on map / array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700257 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
258 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700259 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700260 return false;
261 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700262}
263
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700264
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700265static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700266DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700267{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700268 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
269 return true;
270 } else {
271 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700272 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700273}
274
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700275
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700276static inline bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700277DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700278{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700279 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700280 return false;
281 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700282
283 if(pNesting->pCurrentBounded->uLevelType != uType) {
284 return false;
285 }
286
287 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700288}
289
Laurence Lundblade02625d42020-06-25 14:41:41 -0700290
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700291static inline void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700292DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700293{
Laurence Lundblade6474c982020-12-26 22:14:34 -0800294 /* Only call on a defnite length array / map */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700295 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700296}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700297
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700298
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700299static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700300DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
301{
Laurence Lundblade6474c982020-12-26 22:14:34 -0800302 /* Only call on a defnite length array / map */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700303 pNesting->pCurrent->u.ma.uCountCursor++;
304}
305
306
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700307static inline void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700308DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
309{
310 pNesting->pCurrent--;
311}
312
Laurence Lundblade02625d42020-06-25 14:41:41 -0700313
314static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700315DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700316{
Laurence Lundblade6474c982020-12-26 22:14:34 -0800317 /* Error out if nesting is too deep */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700318 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700319 return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700320 }
321
Laurence Lundblade6474c982020-12-26 22:14:34 -0800322 /* The actual descend */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700323 pNesting->pCurrent++;
324
325 pNesting->pCurrent->uLevelType = uType;
326
327 return QCBOR_SUCCESS;
328}
329
330
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700331static inline QCBORError
Laurence Lundblade6474c982020-12-26 22:14:34 -0800332DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting,
333 bool bIsEmpty,
334 size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700335{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700336 /*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800337 * Should only be called on map/array.
338 *
339 * Have descended into this before this is called. The job here is
340 * just to mark it in bounded mode.
341 *
342 * Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
Laurence Lundblade53b945a2020-12-27 02:05:01 -0800343 * uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET.
344 *
345 * Cast of uOffset to uint32_t for cases where SIZE_MAX < UINT32_MAX.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700346 */
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -0800347 if((uint32_t)uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700348 return QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700349 }
350
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700351 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700352
353 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700354
355 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700356}
357
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700358
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700359static inline QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700360DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700361 uint8_t uQCBORType,
362 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700363{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700364 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700365
366 if(uCount == 0) {
Laurence Lundblade6474c982020-12-26 22:14:34 -0800367 /* Nothing to do for empty definite lenth arrays. They are just are
368 * effectively the same as an item that is not a map or array.
369 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700370 goto Done;
Laurence Lundblade6474c982020-12-26 22:14:34 -0800371 /* Empty indefinite length maps and arrays are handled elsewhere */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700372 }
373
Laurence Lundblade6474c982020-12-26 22:14:34 -0800374 /* Error out if arrays is too long to handle */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700375 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
376 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700377 uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700378 goto Done;
379 }
380
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700381 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700382 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700383 goto Done;
384 }
385
Laurence Lundblade6474c982020-12-26 22:14:34 -0800386 /* Fill in the new map/array level. Check above makes casts OK. */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700387 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
388 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700389
390 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700391
392Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700393 return uError;;
394}
395
396
397static inline void
398DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
399{
400 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
401}
402
403
404static inline void
405DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
406{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700407 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700408 pNesting->pCurrentBounded--;
409 if(DecodeNesting_IsCurrentBounded(pNesting)) {
410 break;
411 }
412 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700413}
414
Laurence Lundblade6474c982020-12-26 22:14:34 -0800415
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700416static inline void
417DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
418{
419 pNesting->pCurrent = pNesting->pCurrentBounded;
420}
421
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700422
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700423static inline QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700424DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700425 uint32_t uEndOffset,
426 uint32_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700427{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700428 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700429
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700430 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700431 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700432 goto Done;
433 }
434
Laurence Lundblade6474c982020-12-26 22:14:34 -0800435 /* Fill in the new byte string level */
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700436 pNesting->pCurrent->u.bs.uPreviousEndOffset = uEndOffset;
437 pNesting->pCurrent->u.bs.uEndOfBstr = uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700438
Laurence Lundblade6474c982020-12-26 22:14:34 -0800439 /* Bstr wrapped levels are always bounded */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700440 pNesting->pCurrentBounded = pNesting->pCurrent;
441
442Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700443 return uError;;
444}
445
Laurence Lundbladed0304932020-06-27 10:59:38 -0700446
447static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700448DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700449{
450 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700451}
452
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700453
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700454static inline void
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800455DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
456{
457 pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
458}
459
460
461static inline void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700462DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700463{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700464 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700465 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
466 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700467}
468
469
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700470static inline void
Laurence Lundblade6474c982020-12-26 22:14:34 -0800471DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting,
472 QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700473{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700474 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700475 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800476 DecodeNesting_ResetMapOrArrayCount(pNesting);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700477}
478
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700479
Laurence Lundblade02625d42020-06-25 14:41:41 -0700480static inline void
Laurence Lundblade6474c982020-12-26 22:14:34 -0800481DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting,
482 const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700483{
484 *pNesting = *pSave;
485}
486
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700487
Laurence Lundblade02625d42020-06-25 14:41:41 -0700488static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700489DecodeNesting_GetEndOfBstr(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700490{
491 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
492}
493
494
Laurence Lundblade02625d42020-06-25 14:41:41 -0700495static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700496DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700497{
498 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
499}
500
501
Laurence Lundblade6474c982020-12-26 22:14:34 -0800502
503
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800504#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladeee851742020-01-08 08:37:05 -0800505/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800506 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
507
508 The following four functions are pretty wrappers for invocation of
509 the string allocator supplied by the caller.
510
Laurence Lundbladeee851742020-01-08 08:37:05 -0800511 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800512
Laurence Lundbladeee851742020-01-08 08:37:05 -0800513static inline void
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800514StringAllocator_Free(const QCBORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800515{
516 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
517}
518
Laurence Lundbladeee851742020-01-08 08:37:05 -0800519// StringAllocator_Reallocate called with pMem NULL is
520// equal to StringAllocator_Allocate()
521static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800522StringAllocator_Reallocate(const QCBORInternalAllocator *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800523 void *pMem,
524 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800525{
526 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
527}
528
Laurence Lundbladeee851742020-01-08 08:37:05 -0800529static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800530StringAllocator_Allocate(const QCBORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800531{
532 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
533}
534
Laurence Lundbladeee851742020-01-08 08:37:05 -0800535static inline void
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800536StringAllocator_Destruct(const QCBORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800537{
538 if(pMe->pfAllocator) {
539 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
540 }
541}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800542#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800543
544
Laurence Lundblade6474c982020-12-26 22:14:34 -0800545
546
Laurence Lundbladeee851742020-01-08 08:37:05 -0800547/*===========================================================================
548 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700549
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800550 See qcbor/qcbor_decode.h for definition of the object
551 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800552 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700553/*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800554 * Public function, see header file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700555 */
Laurence Lundblade25403ed2021-01-02 16:28:07 -0800556void QCBORDecode_Init(QCBORDecodeContext *pMe,
Laurence Lundblade6474c982020-12-26 22:14:34 -0800557 UsefulBufC EncodedCBOR,
558 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700559{
Laurence Lundblade25403ed2021-01-02 16:28:07 -0800560 memset(pMe, 0, sizeof(QCBORDecodeContext));
561 UsefulInputBuf_Init(&(pMe->InBuf), EncodedCBOR);
Laurence Lundblade6474c982020-12-26 22:14:34 -0800562 /* Don't bother with error check on decode mode. If a bad value is
563 * passed it will just act as if the default normal mode of 0 was set.
564 */
Laurence Lundblade25403ed2021-01-02 16:28:07 -0800565 pMe->uDecodeMode = (uint8_t)nDecodeMode;
566 DecodeNesting_Init(&(pMe->nesting));
567
568 /* Inialize me->auMappedTags to CBOR_TAG_INVALID16. See
569 * GetNext_TaggedItem() and MapTagNumber(). */
570 memset(pMe->auMappedTags, 0xff, sizeof(pMe->auMappedTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700571}
572
573
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800574#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
575
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700576/*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800577 * Public function, see header file
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700578 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800579void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
580 QCBORStringAllocate pfAllocateFunction,
Laurence Lundblade6474c982020-12-26 22:14:34 -0800581 void *pAllocateContext,
582 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700583{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800584 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
585 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
586 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700587}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800588#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700589
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800590
Laurence Lundblade6474c982020-12-26 22:14:34 -0800591
592
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800593/*
Laurence Lundblade6474c982020-12-26 22:14:34 -0800594 * Deprecated public function, see header file
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800595 */
Laurence Lundblade6474c982020-12-26 22:14:34 -0800596void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800597 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700598{
Laurence Lundblade6474c982020-12-26 22:14:34 -0800599 /* This does nothing now. It is retained for backwards compatibility */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700600 (void)pMe;
601 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700602}
603
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700604
Laurence Lundblade25403ed2021-01-02 16:28:07 -0800605
606
607/*
Laurence Lundblade123224b2021-01-03 20:58:06 -0800608 * Decoding items is done in six layers, one calling the next one
609 * down. If a layer has no work to do for a particular item, it
610 * returns quickly.
611 *
612 * 1. QCBORDecode_GetNext, GetNextWithTags - The top layer processes
613 * tagged data items, turning them into the local C representation.
614 * For the most simple it is just associating a QCBOR_TYPE with the
615 * data. For the complex ones that an aggregate of data items, there
616 * is some further decoding and some limited recursion.
617 *
618 * 2. QCBORDecode_GetNextMapOrArray - This manages the beginnings and
619 * ends of maps and arrays. It tracks descending into and ascending
620 * out of maps/arrays. It processes breaks that terminate
621 * indefinite-length maps and arrays.
622 *
623 * 3. GetNext_MapEntry - This handles the combining of two items, the
624 * label and the data, that make up a map entry. It only does work on
625 * maps. It combines the label and data items into one labeled item.
626 *
627 * 4. GetNext_TaggedItem - This decodes type 6 tag numbers. It turns
628 * the tag numbers into bit flags associated with the data item. No
629 * actual decoding of the contents of the tag is performed here.
630 *
631 * 5. GetNext_FullItem - This assembles the sub-items that make up an
632 * indefinite-length string into one string item. It uses the string
633 * allocator to create contiguous space for the item. It processes all
634 * breaks that are part of indefinite-length strings.
635 *
636 * 6. GetNext_Item - This decodes the atomic data items in CBOR. Each
637 * atomic data item has a "major type", an integer "argument" and
638 * optionally some content. For text and byte strings, the content is
639 * the bytes that make up the string. These are the smallest data
640 * items that are considered to be well-formed. The content may also
641 * be other data items in the case of aggregate types. They are not
642 * handled in this layer.
643 *
644 * Roughly this takes 300 bytes of stack for vars. TODO: evaluate this
645 * more carefully and correctly.
Laurence Lundblade25403ed2021-01-02 16:28:07 -0800646 */
647
648
Laurence Lundblade1c929722020-12-27 02:44:57 -0800649/**
650 * @brief Decode the CBOR head, the type and argument.
651 *
652 * @param[in] pUInBuf The input buffer to read from.
653 * @param[out] pnMajorType The decoded major type.
654 * @param[out] puArgument The decoded argument.
655 * @param[out] pnAdditionalInfo The decoded Lower 5 bits of initial byte.
656 *
657 * @retval QCBOR_ERR_UNSUPPORTED
658 * @retval QCBOR_ERR_HIT_END
659 *
660 * This decodes the CBOR "head" that every CBOR data item has. See
661 * longer explaination of the head in documentation for
662 * QCBOREncode_EncodeHead().
663 *
664 * This does the network->host byte order conversion. The conversion
665 * here also results in the conversion for floats in addition to that
666 * for lengths, tags and integer values.
667 *
668 * The int type is preferred to uint8_t for some variables as this
669 * avoids integer promotions, can reduce code size and makes static
670 * analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700671 */
Laurence Lundblade1c929722020-12-27 02:44:57 -0800672static inline QCBORError
673DecodeHead(UsefulInputBuf *pUInBuf,
674 int *pnMajorType,
675 uint64_t *puArgument,
676 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700677{
Laurence Lundblade1c929722020-12-27 02:44:57 -0800678 QCBORError uReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800679
Laurence Lundblade1c929722020-12-27 02:44:57 -0800680 /* Get the initial byte that every CBOR data item has and break it
681 * down. */
682 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800683 const int nTmpMajorType = nInitialByte >> 5;
684 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800685
Laurence Lundblade1c929722020-12-27 02:44:57 -0800686 /* Where the argument accumulates */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800687 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800688
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800689 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800690 /* Need to get 1,2,4 or 8 additional argument bytes. Map
691 * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
692 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800693 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800694
Laurence Lundblade1c929722020-12-27 02:44:57 -0800695 /* Loop getting all the bytes in the argument */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800696 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800697 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800698 /* This shift and add gives the endian conversion. */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800699 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
700 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800701 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800702 /* The reserved and thus-far unused additional info values */
703 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800704 goto Done;
705 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800706 /* Less than 24, additional info is argument or 31, an
707 * indefinite length. No more bytes to get.
708 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800709 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700710 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800711
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700712 if(UsefulInputBuf_GetError(pUInBuf)) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800713 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700714 goto Done;
715 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800716
Laurence Lundblade1c929722020-12-27 02:44:57 -0800717 /* All successful if arrived here. */
718 uReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800719 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800720 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800721 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800722
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700723Done:
Laurence Lundblade1c929722020-12-27 02:44:57 -0800724 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700725}
726
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800727
Laurence Lundblade1c929722020-12-27 02:44:57 -0800728/**
729 * @brief Decode integer types, major types 0 and 1.
730 *
731 * @param[in] nMajorType The CBOR major type (0 or 1).
732 * @param[in] uArgument The argument from the head.
733 * @param[out] pDecodedItem The filled in decoded item.
734 *
735 * @retval QCBOR_ERR_INT_OVERFLOW
736 *
737 * Must only be called when major type is 0 or 1.
738 *
739 * CBOR doesn't explicitly specify two's compliment for integers but
740 * all CPUs use it these days and the test vectors in the RFC are
741 * so. All integers in the CBOR structure are positive and the major
742 * type indicates positive or negative. CBOR can express positive
743 * integers up to 2^x - 1 where x is the number of bits and negative
744 * integers down to 2^x. Note that negative numbers can be one more
745 * away from zero than positive. Stdint, as far as I can tell, uses
746 * two's compliment to represent negative integers.
747 *
748 * See http://www.unix.org/whitepapers/64bit.html for reasons int is
749 * used carefully here, and in particular why it isn't used in the
750 * public interface. Also see
751 * https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
752 *
753 * Int is used for values that need less than 16-bits and would be
754 * subject to integer promotion and result in complaining from static
755 * analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700756 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700757static inline QCBORError
Laurence Lundblade1c929722020-12-27 02:44:57 -0800758DecodeInteger(int nMajorType, uint64_t uArgument, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700759{
Laurence Lundblade1c929722020-12-27 02:44:57 -0800760 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800761
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700762 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800763 if (uArgument <= INT64_MAX) {
764 pDecodedItem->val.int64 = (int64_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700765 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800766
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700767 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800768 pDecodedItem->val.uint64 = uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700769 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700770 }
Laurence Lundblade1c929722020-12-27 02:44:57 -0800771
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700772 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800773 if(uArgument <= INT64_MAX) {
774 /* CBOR's representation of negative numbers lines up with
775 * the two-compliment representation. A negative integer has
776 * one more in range than a positive integer. INT64_MIN is
777 * equal to (-INT64_MAX) - 1.
778 */
779 pDecodedItem->val.int64 = (-(int64_t)uArgument) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700780 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800781
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700782 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -0800783 /* C can't represent a negative integer in this range so it
784 * is an error.
785 */
786 uReturn = QCBOR_ERR_INT_OVERFLOW;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700787 }
788 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800789
Laurence Lundblade1c929722020-12-27 02:44:57 -0800790 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700791}
792
Laurence Lundblade1c929722020-12-27 02:44:57 -0800793
Laurence Lundblade38299092020-12-28 04:13:50 -0800794/* Make sure #define value line up as DecodeSimple counts on this. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700795#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
796#error QCBOR_TYPE_FALSE macro value wrong
797#endif
798
799#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
800#error QCBOR_TYPE_TRUE macro value wrong
801#endif
802
803#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
804#error QCBOR_TYPE_NULL macro value wrong
805#endif
806
807#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
808#error QCBOR_TYPE_UNDEF macro value wrong
809#endif
810
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700811#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
812#error QCBOR_TYPE_BREAK macro value wrong
813#endif
814
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700815#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
816#error QCBOR_TYPE_DOUBLE macro value wrong
817#endif
818
819#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
820#error QCBOR_TYPE_FLOAT macro value wrong
821#endif
822
Laurence Lundblade38299092020-12-28 04:13:50 -0800823
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800824/**
825 * @brief Decode type 7 -- true, false, floating-point, break...
826 *
827 * @param[in] nAdditionalInfo The lower five bits from the initial byte.
828 * @param[in] uArgument The argument from the head.
829 * @param[out] pDecodedItem The filled in decoded item.
830 *
831 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
832 * @retval QCBOR_ERR_BAD_TYPE_7
833 */
Laurence Lundblade9b334962020-08-27 10:55:53 -0700834
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700835static inline QCBORError
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800836DecodeType7(int nAdditionalInfo, uint64_t uArgument, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700837{
Laurence Lundblade38299092020-12-28 04:13:50 -0800838 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800839
Laurence Lundblade38299092020-12-28 04:13:50 -0800840 /* uAdditionalInfo is 5 bits from the initial byte. Compile time
841 * checks above make sure uAdditionalInfo values line up with
842 * uDataType values. DecodeHead() never returns an AdditionalInfo
843 * > 0x1f so cast is safe.
844 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800845 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800846
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800847 switch(nAdditionalInfo) {
Laurence Lundblade38299092020-12-28 04:13:50 -0800848 /* No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they
849 * are caught before this is called.
850 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800851
Laurence Lundblade38299092020-12-28 04:13:50 -0800852 case HALF_PREC_FLOAT: /* 25 */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700853#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade38299092020-12-28 04:13:50 -0800854 /* Half-precision is returned as a double. The cast to
855 * uint16_t is safe because the encoded value was 16 bits. It
856 * was widened to 64 bits to be passed in here.
857 */
858 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700859 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800860#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade38299092020-12-28 04:13:50 -0800861 uReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800862#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700863 break;
Laurence Lundblade38299092020-12-28 04:13:50 -0800864 case SINGLE_PREC_FLOAT: /* 26 */
865 /* Single precision is normally returned as a double since
866 * double is widely supported, there is no loss of precision,
867 * it makes it easy for the caller in most cases and it can
868 * be converted back to single with no loss of precision
869 *
870 * The cast to uint32_t is safe because the encoded value was
871 * 32 bits. It was widened to 64 bits to be passed in here.
872 */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700873 {
Laurence Lundblade38299092020-12-28 04:13:50 -0800874 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uArgument);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700875#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade38299092020-12-28 04:13:50 -0800876 /* In the normal case, use HW to convert float to
877 * double. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700878 pDecodedItem->val.dfnum = (double)f;
879 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800880#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade38299092020-12-28 04:13:50 -0800881 /* Use of float HW is disabled, return as a float. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700882 pDecodedItem->val.fnum = f;
883 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
884
Laurence Lundblade38299092020-12-28 04:13:50 -0800885 /* IEEE754_FloatToDouble() could be used here to return as
886 * a double, but it adds object code and most likely
887 * anyone disabling FLOAT HW use doesn't care about floats
888 * and wants to save object code.
889 */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800890#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700891 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700892 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700893
Laurence Lundblade38299092020-12-28 04:13:50 -0800894 case DOUBLE_PREC_FLOAT: /* 27 */
895 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700896 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700897 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800898
Laurence Lundblade38299092020-12-28 04:13:50 -0800899 case CBOR_SIMPLEV_FALSE: /* 20 */
900 case CBOR_SIMPLEV_TRUE: /* 21 */
901 case CBOR_SIMPLEV_NULL: /* 22 */
902 case CBOR_SIMPLEV_UNDEF: /* 23 */
903 case CBOR_SIMPLE_BREAK: /* 31 */
904 break; /* nothing to do */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800905
Laurence Lundblade38299092020-12-28 04:13:50 -0800906 case CBOR_SIMPLEV_ONEBYTE: /* 24 */
907 if(uArgument <= CBOR_SIMPLE_BREAK) {
908 /* This takes out f8 00 ... f8 1f which should be encoded
909 * as e0 … f7
910 */
911 uReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700912 goto Done;
913 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800914 /* FALLTHROUGH */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800915
Laurence Lundblade38299092020-12-28 04:13:50 -0800916 default: /* 0-19 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700917 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundblade38299092020-12-28 04:13:50 -0800918 /* DecodeHead() will make uArgument equal to
919 * nAdditionalInfo when nAdditionalInfo is < 24. This cast is
920 * safe because the 2, 4 and 8 byte lengths of uNumber are in
921 * the double/float cases above
Laurence Lundbladeee851742020-01-08 08:37:05 -0800922 */
Laurence Lundblade38299092020-12-28 04:13:50 -0800923 pDecodedItem->val.uSimple = (uint8_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700924 break;
925 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800926
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700927Done:
Laurence Lundblade38299092020-12-28 04:13:50 -0800928 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700929}
930
931
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800932/**
933 * @brief Decode text and byte strings
934 *
935 * @param[in] pAllocator The string allocator or NULL.
936 * @param[in] uStrLen The length of the string.
937 * @param[in] pUInBuf The surce from which to read the string's bytes.
938 * @param[out] pDecodedItem The filled in decoded item.
939 *
940 * @retval QCBOR_ERR_HIT_END
941 * @retval QCBOR_ERR_STRING_ALLOCATE
942 * @retval QCBOR_ERR_STRING_TOO_LONG
943 *
944 * The reads @c uStrlen bytes from @c pUInBuf and fills in @c
945 * pDecodedItem. If @c pAllocator is not NULL then memory for the
946 * string is allocated.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700947 */
Laurence Lundblade38299092020-12-28 04:13:50 -0800948static inline QCBORError
Laurence Lundblade63e68f72020-12-28 04:24:11 -0800949DecodeBytes(const QCBORInternalAllocator *pAllocator,
950 uint64_t uStrLen,
951 UsefulInputBuf *pUInBuf,
952 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700953{
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800954 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800955
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800956 /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
957 * CPUs. This check makes the casts to size_t below safe.
958 *
959 * The max is 4 bytes less than the largest sizeof() so this can be
960 * tested by putting a SIZE_MAX length in the CBOR test input (no
961 * one will care the limit on strings is 4 bytes shorter).
962 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800963 if(uStrLen > SIZE_MAX-4) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800964 uReturn = QCBOR_ERR_STRING_TOO_LONG;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800965 goto Done;
966 }
967
968 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530969 if(UsefulBuf_IsNULLC(Bytes)) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800970 /* Failed to get the bytes for this string item */
971 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530972 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700973 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530974
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800975#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800976 /* Note that this is not where allocation to coallsece
977 * indefinite-length strings is done. This is for when the caller
978 * has requested all strings be allocated. Disabling indefinite
979 * length strings also disables this allocate-all option.
980 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800981 if(pAllocator) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800982 /* request to use the string allocator to make a copy */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800983 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530984 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800985 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530986 goto Done;
987 }
988 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800989 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800990 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530991 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800992#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
993 (void)pAllocator;
994#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
995
Laurence Lundblade554ebd52020-12-29 03:26:06 -0800996 /* Normal case with no string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800997 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800998
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530999Done:
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001000 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001001}
1002
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001003
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001004/**
1005 * @brief Map the CBOR major types for strings to the QCBOR types.
1006 *
1007 * @param[in] nCBORMajorType The CBOR major type to convert.
1008 * @retturns QCBOR type number.
1009 *
1010 * This only works for the two string types.
1011 */
1012static inline uint8_t ConvertStringMajorTypes(int nCBORMajorType)
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001013{
1014 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
1015 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
1016 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001017
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001018 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
1019 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
1020 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001021
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001022 return (uint8_t)(nCBORMajorType + 4);
1023}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001024
1025
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001026/**
1027 * @brief Map the CBOR major types for arrays/maps to the QCBOR types.
1028 *
1029 * @param[in] nCBORMajorType The CBOR major type to convert.
1030 * @retturns QCBOR type number.
1031 *
1032 * This only works for the two aggregate types.
1033 */
1034static inline uint8_t ConvertArrayOrMapType(int nCBORMajorType)
1035{
1036 #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
1037 #error QCBOR_TYPE_ARRAY value not lined up with major type
1038 #endif
1039
1040 #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
1041 #error QCBOR_TYPE_MAP value not lined up with major type
1042 #endif
1043
1044 return (uint8_t)(nCBORMajorType);
1045}
1046
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001047
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001048/**
Laurence Lundblade123224b2021-01-03 20:58:06 -08001049 * @brief Decode a single primitive data item (decode layer 6).
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001050 *
1051 * @param[in] pUInBuf Input buffer to read data item from.
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001052 * @param[out] pDecodedItem The filled-in decoded item.
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001053 * @param[in] pAllocator The allocator to use for strings or NULL.
1054 *
1055 * @retval QCBOR_ERR_UNSUPPORTED
1056 * @retval QCBOR_ERR_HIT_END
1057 * @retval QCBOR_ERR_INT_OVERFLOW
1058 * @retval QCBOR_ERR_STRING_ALLOCATE
1059 * @retval QCBOR_ERR_STRING_TOO_LONG
1060 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1061 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001062 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001063 *
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001064 * This decodes the most primitive / atomic data item. It does
1065 * no combing of data items.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001066 */
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001067static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
1068 QCBORItem *pDecodedItem,
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001069 const QCBORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001070{
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001071 QCBORError uReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001072
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001073 /* Get the major type and the argument. The argument could be
1074 * length of more bytes or the value depending on the major
1075 * type. nAdditionalInfo is an encoding of the length of the
1076 * uNumber and is needed to decode floats and doubles.
1077 */
Rob Gilton47cc9562020-08-10 12:03:38 +01001078 int nMajorType = 0;
Laurence Lundblade1c929722020-12-27 02:44:57 -08001079 uint64_t uArgument = 0;
Rob Gilton47cc9562020-08-10 12:03:38 +01001080 int nAdditionalInfo = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001081
Laurence Lundblade4b09f632019-10-09 14:34:59 -07001082 memset(pDecodedItem, 0, sizeof(QCBORItem));
1083
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001084 uReturn = DecodeHead(pUInBuf, &nMajorType, &uArgument, &nAdditionalInfo);
1085 if(uReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001086 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001087 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001088
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001089 /* At this point the major type and the argument are valid. We've
1090 * got the type and the argument that starts every CBOR data item.
1091 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001092 switch (nMajorType) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001093 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1094 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001095 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001096 uReturn = QCBOR_ERR_BAD_INT;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001097 } else {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001098 uReturn = DecodeInteger(nMajorType, uArgument, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -07001099 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001100 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001101
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001102 case CBOR_MAJOR_TYPE_BYTE_STRING: /* Major type 2 */
1103 case CBOR_MAJOR_TYPE_TEXT_STRING: /* Major type 3 */
1104 pDecodedItem->uDataType = ConvertStringMajorTypes(nMajorType);
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001105 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001106 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001107 } else {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001108 uReturn = DecodeBytes(pAllocator, uArgument, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001109 }
1110 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001111
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001112 case CBOR_MAJOR_TYPE_ARRAY: /* Major type 4 */
1113 case CBOR_MAJOR_TYPE_MAP: /* Major type 5 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001114 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001115 /* Indefinite-length string. */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001116#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -07001117 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001118#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001119 uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001120 break;
1121#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001122 } else {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001123 /* Definite-length string. */
1124 if(uArgument > QCBOR_MAX_ITEMS_IN_ARRAY) {
1125 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
1126 goto Done;
1127 }
1128 /* cast OK because of check above */
Laurence Lundblade1c929722020-12-27 02:44:57 -08001129 pDecodedItem->val.uCount = (uint16_t)uArgument;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001130 }
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001131 pDecodedItem->uDataType = ConvertArrayOrMapType(nMajorType);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001132 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001133
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001134 case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001135 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001136 uReturn = QCBOR_ERR_BAD_INT;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001137 } else {
Laurence Lundblade1c929722020-12-27 02:44:57 -08001138 pDecodedItem->val.uTagV = uArgument;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001139 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001140 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001141 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001142
Laurence Lundbladeee851742020-01-08 08:37:05 -08001143 case CBOR_MAJOR_TYPE_SIMPLE:
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001144 /* Major type 7: float, double, true, false, null... */
1145 uReturn = DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001146 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001147
Laurence Lundbladeee851742020-01-08 08:37:05 -08001148 default:
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001149 /* Never happens because DecodeHead() should never return > 7 */
1150 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001151 break;
1152 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001153
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001154Done:
Laurence Lundblade554ebd52020-12-29 03:26:06 -08001155 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001156}
1157
1158
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001159/**
Laurence Lundblade123224b2021-01-03 20:58:06 -08001160 * @brief Process indefinite length strings (decode layer 5).
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001161 *
1162 * @param[in] pMe Decoder context
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001163 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001164 *
1165 * @retval QCBOR_ERR_UNSUPPORTED
1166 * @retval QCBOR_ERR_HIT_END
1167 * @retval QCBOR_ERR_INT_OVERFLOW
1168 * @retval QCBOR_ERR_STRING_ALLOCATE
1169 * @retval QCBOR_ERR_STRING_TOO_LONG
1170 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1171 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001172 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001173 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1174 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001175 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001176 *
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001177 * If @c pDecodedItem is not an indefinite-length string, this does nothing.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001178 *
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001179 * If it is, this loops getting the subsequent chunk data items that
1180 * make up the string. The string allocator is used to make a
1181 * contiguous buffer for the chunks. When this completes @c
1182 * pDecodedItem contains the put-together string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001183 *
1184 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001185 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001186static inline QCBORError
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001187GetNext_FullItem(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001188{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001189 /* Aproximate stack usage
1190 * 64-bit 32-bit
1191 * local vars 32 16
1192 * 2 UsefulBufs 32 16
1193 * QCBORItem 56 52
1194 * TOTAL 120 74
1195 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001196
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001197 /* The string allocator is used here for two purposes: 1)
1198 * coalescing the chunks of an indefinite length string, 2)
1199 * allocating storage for every string returned.
1200 *
1201 * The first use is below in this function. Indefinite length
1202 * strings cannot be processed at all without a string allocator.
1203 *
1204 * The second used is in DecodeBytes() which is called by
1205 * GetNext_Item() below. This second use unneccessary for most use
1206 * and only happens when requested in the call to
1207 * QCBORDecode_SetMemPool(). If the second use not requested then
1208 * NULL is passed for the string allocator to GetNext_Item().
1209 *
1210 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1211 * allocator altogether and thus both of these uses. It reduced the
1212 * decoder object code by about 400 bytes.
1213 */
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001214 const QCBORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001215
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001216#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001217 const QCBORInternalAllocator *pAllocator = NULL;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001218
1219 if(pMe->StringAllocator.pfAllocator) {
1220 pAllocator = &(pMe->StringAllocator);
1221 if(pMe->bStringAllocateAll) {
1222 pAllocatorForGetNext = pAllocator;
1223 }
1224 }
1225#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1226
1227 QCBORError uReturn;
1228 uReturn = GetNext_Item(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
1229 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001230 goto Done;
1231 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001232
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001233 /* Only do indefinite length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001234 const uint8_t uStringType = pDecodedItem->uDataType;
1235 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001236 goto Done;
1237 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001238
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001239 /* Is this a string with an indefinite length? */
1240 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1241 goto Done;
1242 }
1243
1244#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
1245 /* Can't do indefinite length strings without a string allocator */
1246 if(pAllocator == NULL) {
1247 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1248 goto Done;
1249 }
1250
1251 /* Loop getting chunks of the indefinite length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001252 UsefulBufC FullString = NULLUsefulBufC;
1253
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001254 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001255 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001256 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001257 /* Pass a NULL string allocator to GetNext_Item() because the
1258 * individual string chunks in an indefinite length should not
1259 * be allocated. They are always copied in the the contiguous
1260 * buffer allocated here.
1261 */
1262 uReturn = GetNext_Item(&(pMe->InBuf), &StringChunkItem, NULL);
1263 if(uReturn) {
1264 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001265 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001266
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001267 /* Is item is the marker for end of the indefinite length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001268 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001269 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001270 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301271 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001272 break;
1273 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001274
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001275 /* All chunks must be of the same type, the type of the item
1276 * that introduces the indefinite length string. This also
1277 * catches errors where the chunk is not a string at all and an
1278 * indefinite length string inside an indefinite length string.
1279 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001280 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001281 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1282 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001283 break;
1284 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001285
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001286 /* The first time throurgh FullString.ptr is NULL and this is
1287 * equivalent to StringAllocator_Allocate(). Subsequently it is
1288 * not NULL and a reallocation happens.
1289 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001290 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1291 UNCONST_POINTER(FullString.ptr),
1292 FullString.len + StringChunkItem.val.string.len);
1293
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001294 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001295 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001296 break;
1297 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001298
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001299 /* Copy new string chunk to the end of accumulated string */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001300 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001301 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001302
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001303 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1304 /* Getting the item failed, clean up the allocated memory */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001305 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001306 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001307#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1308 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1309#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001310
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001311Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001312 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001313}
1314
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001315
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001316/**
1317 * @brief This converts a tag number to a shorter mapped value for storage.
1318 *
1319 * @param[in] pMe The decode context.
1320 * @param[in] uUnMappedTag The tag number to map
1321 * @param[out] puMappedTagNumer The stored tag number.
1322 *
1323 * @return error code.
1324 *
1325 * The main point of mapping tag numbers is make QCBORItem
1326 * smaller. With this mapping storage of 4 tags takes up 8
1327 * bytes. Without, it would take up 32 bytes.
1328 *
1329 * This maps tag numbers greater than QCBOR_LAST_UNMAPPED_TAG.
1330 * QCBOR_LAST_UNMAPPED_TAG is a little smaller than MAX_UINT16.
1331 *
1332 * See also UnMapTagNumber() and @ref QCBORItem.
1333 */
1334static inline QCBORError
1335MapTagNumber(QCBORDecodeContext *pMe, uint64_t uUnMappedTag, uint16_t *puMappedTagNumer)
1336{
1337 if(uUnMappedTag > QCBOR_LAST_UNMAPPED_TAG) {
1338 int uTagMapIndex;
1339 /* Is there room in the tag map, or is it in it already? */
1340 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
1341 if(pMe->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID64) {
1342 break;
1343 }
1344 if(pMe->auMappedTags[uTagMapIndex] == uUnMappedTag) {
1345 break;
1346 }
1347 }
1348 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1349 return QCBOR_ERR_TOO_MANY_TAGS;
1350 }
1351
1352 /* Covers the cases where tag is new and were it is already in the map */
1353 pMe->auMappedTags[uTagMapIndex] = uUnMappedTag;
1354 *puMappedTagNumer = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
1355
1356 } else {
1357 *puMappedTagNumer = (uint16_t)uUnMappedTag;
1358 }
1359
1360 return QCBOR_SUCCESS;
1361}
1362
1363
1364/**
1365 * @brief This converts a mapped tag number to the actual tag number.
1366 *
1367 * @param[in] pMe The decode context.
1368 * @param[in] uMappedTagNumber The stored tag number.
1369 *
1370 * @return The actual tag number is returned or
1371 * @ref CBOR_TAG_INVALID64 on error.
1372 *
1373 * This is the reverse of MapTagNumber()
1374 */
1375static uint64_t
1376UnMapTagNumber(const QCBORDecodeContext *pMe, uint16_t uMappedTagNumber)
1377{
1378 if(uMappedTagNumber <= QCBOR_LAST_UNMAPPED_TAG) {
1379 return uMappedTagNumber;
1380 } else if(uMappedTagNumber == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001381 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001382 } else {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001383 /* This won't be negative because of code below in
1384 * MapTagNumber()
1385 */
1386 const unsigned uIndex = uMappedTagNumber - (QCBOR_LAST_UNMAPPED_TAG + 1);
1387 return pMe->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001388 }
1389}
1390
Laurence Lundblade9b334962020-08-27 10:55:53 -07001391
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001392/**
Laurence Lundblade123224b2021-01-03 20:58:06 -08001393 * @brief Aggregate all tags wrapping a data item (decode layer 4).
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001394 *
1395 * @param[in] pMe Decoder context
1396 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001397
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001398 * @retval QCBOR_ERR_UNSUPPORTED
1399 * @retval QCBOR_ERR_HIT_END
1400 * @retval QCBOR_ERR_INT_OVERFLOW
1401 * @retval QCBOR_ERR_STRING_ALLOCATE
1402 * @retval QCBOR_ERR_STRING_TOO_LONG
1403 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1404 * @retval QCBOR_ERR_BAD_TYPE_7
1405 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1406 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1407 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1408 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1409 * @retval QCBOR_ERR_TOO_MANY_TAGS
1410 *
1411 * This loops getting atomic data items until one is not a tag
1412 * number. Usually this is largely pass-through because most
1413 * item are not tag numbers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001414 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001415static QCBORError
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001416GetNext_TaggedItem(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001417{
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001418 uint16_t auItemsTags[QCBOR_MAX_TAGS_PER_ITEM];
1419
1420 /* Initialize to CBOR_TAG_INVALID16 */
1421 #if CBOR_TAG_INVALID16 != 0xffff
1422 /* Be sure the memset does the right thing. */
1423 #err CBOR_TAG_INVALID16 tag not defined as expected
1424 #endif
1425 memset(auItemsTags, 0xff, sizeof(auItemsTags));
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001426
Laurence Lundblade9b334962020-08-27 10:55:53 -07001427 QCBORError uReturn = QCBOR_SUCCESS;
1428
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001429 /* Loop fetching data items until the item fetched is not a tag */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001430 for(;;) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001431 QCBORError uErr = GetNext_FullItem(pMe, pDecodedItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07001432 if(uErr != QCBOR_SUCCESS) {
1433 uReturn = uErr;
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001434 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001435 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001436
Laurence Lundblade9b334962020-08-27 10:55:53 -07001437 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001438 /* Successful exit from loop; maybe got some tags, maybe not */
1439 memcpy(pDecodedItem->uTags, auItemsTags, sizeof(auItemsTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001440 break;
1441 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001442
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001443 if(auItemsTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1444 /* No room in the tag list */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001445 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001446 /* Continue on to get all tags wrapping this item even though
1447 * it is erroring out in the end. This allows decoding to
1448 * continue. This is a resource limit error, not a problem
1449 * with being well-formed CBOR.
1450 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001451 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001452 }
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001453 /* Slide tags over one in the array to make room at index 0.
1454 * Must use memmove because the move source and destination
1455 * overlap.
1456 */
1457 memmove(&auItemsTags[1], auItemsTags, sizeof(auItemsTags) - sizeof(auItemsTags[0]));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001458
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001459 /* Map the tag */
1460 uint16_t uMappedTagNumer;
1461 uReturn = MapTagNumber(pMe, pDecodedItem->val.uTagV, &uMappedTagNumer);
1462 /* Continue even on error so as to consume all tags wrapping
1463 * this data item so decoding can go on. If MapTagNumber()
1464 * errors once it will continue to error.
1465 */
1466 auItemsTags[0] = uMappedTagNumer;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001467 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001468
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001469Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001470 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001471}
1472
1473
1474/*
Laurence Lundblade123224b2021-01-03 20:58:06 -08001475 * @brief Combine a map entry label and value into one item (decode layer 3).
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001476 *
1477 * @param[in] pMe Decoder context
1478 * @param[out] pDecodedItem The decoded item that work is done on.
1479 *
1480 * @retval QCBOR_ERR_UNSUPPORTED
1481 * @retval QCBOR_ERR_HIT_END
1482 * @retval QCBOR_ERR_INT_OVERFLOW
1483 * @retval QCBOR_ERR_STRING_ALLOCATE
1484 * @retval QCBOR_ERR_STRING_TOO_LONG
1485 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1486 * @retval QCBOR_ERR_BAD_TYPE_7
1487 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1488 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1489 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1490 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1491 * @retval QCBOR_ERR_TOO_MANY_TAGS
1492 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1493 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1494 *
1495 * If a the current nesting level is a map, then this
1496 * combines pairs of items into one data item with a label
1497 * and value.
1498 *
1499 * This is pass-through if the current nesting leve is
1500 * not a map.
1501 *
1502 * This also implements maps-as-array mode where a map
1503 * is treated like an array to allow caller to do their
1504 * own label processing.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001505 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001506static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001507GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001508{
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001509 QCBORError uReturn = GetNext_TaggedItem(me, pDecodedItem);
1510 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001511 goto Done;
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001512 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001513
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001514 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001515 /* Break can't be a map entry */
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001516 goto Done;
1517 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001518
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001519 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001520 /* Normal decoding of maps -- combine label and value into one item. */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001521
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001522 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001523 /* Save label in pDecodedItem and get the next which will
1524 * be the real data item.
1525 */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001526 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001527 uReturn = GetNext_TaggedItem(me, pDecodedItem);
1528 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001529 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001530 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001531
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301532 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001533
1534 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001535 /* strings are always good labels */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001536 pDecodedItem->label.string = LabelItem.val.string;
1537 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1538 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001539 /* It's not a string and we only want strings */
1540 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001541 goto Done;
1542 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1543 pDecodedItem->label.int64 = LabelItem.val.int64;
1544 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1545 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1546 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1547 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1548 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1549 pDecodedItem->label.string = LabelItem.val.string;
1550 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1551 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1552 } else {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001553 /* label is not an int or a string. It is an arrray
1554 * or a float or such and this implementation doesn't handle that.
1555 * Also, tags on labels are ignored.
1556 */
1557 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001558 goto Done;
1559 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001560 }
1561 } else {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001562 /* Decoding of maps as arrays to let the caller decide what to do
1563 * about labels, particularly lables that are not integers or
1564 * strings.
1565 */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001566 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001567 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001568 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001569 goto Done;
1570 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001571 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001572 /* Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2.
1573 * Cast is needed because of integer promotion.
1574 */
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001575 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001576 }
1577 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001578
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001579Done:
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001580 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001581}
1582
1583
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001584#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001585/**
1586 * @brief Peek and see if next data item is a break;
1587 *
1588 * @param[in] pUIB UsefulInputBuf to read from.
1589 * @param[out] pbNextIsBreak Indicate if next was a break or not.
1590 *
1591 * @return Any decoding error.
1592 *
1593 * See if next item is a CBOR break. If it is, it is consumed,
1594 * if not it is not consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001595*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001596static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001597NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1598{
1599 *pbNextIsBreak = false;
1600 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001601 QCBORItem Peek;
1602 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1603 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1604 if(uReturn != QCBOR_SUCCESS) {
1605 return uReturn;
1606 }
1607 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001608 /* It is not a break, rewind so it can be processed normally. */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001609 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001610 } else {
1611 *pbNextIsBreak = true;
1612 }
1613 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001614
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001615 return QCBOR_SUCCESS;
1616}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001617#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001618
1619
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001620/*
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001621 * @brief Ascend up nesting levels if all items in them have been consumed.
1622 *
1623 * @param[in] pMe The decode context.
1624 * @param[in] bMarkEnd If true mark end of maps/arrays with count of zero.
1625 *
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001626 * An item was just consumed, now figure out if it was the
1627 * end of an array/map map that can be closed out. That
1628 * may in turn close out the above array/map...
Laurence Lundblade642282a2020-06-23 12:00:33 -07001629*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001630static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001631{
1632 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001633
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001634 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001635 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1636
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001637 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1638 /* Nesting level is bstr-wrapped CBOR */
1639
1640 /* Ascent for bstr-wrapped CBOR is always by explicit call
1641 * so no further ascending can happen.
1642 */
1643 break;
1644
1645 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1646 /* Level is a definite-length array/map */
1647
1648 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001649 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1650 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001651 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001652 break;
1653 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001654 /* All items in a definite length array were consumed so it
1655 * is time to ascend one level. This happens below.
1656 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001657
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001658#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001659 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001660 /* Level is an indefinite-length array/map. */
1661
1662 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001663 bool bIsBreak = false;
1664 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1665 if(uReturn != QCBOR_SUCCESS) {
1666 goto Done;
1667 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001668
1669 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001670 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001671 break;
1672 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001673
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001674 /* It was a break in an indefinite length map / array so
1675 * it is time to ascend one level.
1676 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001677
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001678#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001679 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001680
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001681
1682 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001683
Laurence Lundblade93d89472020-10-03 22:30:50 -07001684 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001685 * QCBORDecode_ExitBoundedMode().
1686 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001687 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade93d89472020-10-03 22:30:50 -07001688 /* Set the count to zero for definite length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001689 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001690 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001691 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001692 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001693
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001694 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001695 break;
1696 }
1697
1698 /* Finally, actually ascend one level. */
1699 DecodeNesting_Ascend(&(pMe->nesting));
1700 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001701
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001702 uReturn = QCBOR_SUCCESS;
1703
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001704#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001705Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001706#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1707
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001708 return uReturn;
1709}
1710
1711
1712/*
Laurence Lundblade123224b2021-01-03 20:58:06 -08001713 * @brief Ascending & Descending out of nesting levels (decode layer 2).
1714
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001715 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001716 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1717 indefinte length maps and arrays by looking at the item count or
1718 finding CBOR breaks. It detects the ends of the top-level sequence
1719 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001720
1721 @retval QCBOR_ERR_UNSUPPORTED X
1722
1723 @retval QCBOR_ERR_HIT_END
1724
1725 @retval QCBOR_ERR_INT_OVERFLOW X
1726
1727 @retval QCBOR_ERR_STRING_ALLOCATE
1728
1729 @retval QCBOR_ERR_STRING_TOO_LONG
1730
1731 @retval QCBOR_ERR_HALF_PRECISION_DISABLED X
1732
1733 @retval QCBOR_ERR_BAD_TYPE_7 X
1734
1735 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1736
1737 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1738
1739 @retval QCBOR_ERR_TOO_MANY_TAGS
1740
1741 @retval QCBOR_ERR_MAP_LABEL_TYPE X
1742
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001743 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade9b334962020-08-27 10:55:53 -07001744
1745 @retval QCBOR_ERR_NO_MORE_ITEMS
1746
1747 @retval QCBOR_ERR_BAD_BREAK
1748
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001749 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001750static QCBORError
1751QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001752{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001753 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001754 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001755
Laurence Lundblade642282a2020-06-23 12:00:33 -07001756 /*
1757 If out of bytes to consume, it is either the end of the top-level
1758 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001759
Laurence Lundblade642282a2020-06-23 12:00:33 -07001760 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1761 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1762 CBOR is exited, the length is set back to the top-level's length
1763 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001764 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001765 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001766 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001767 goto Done;
1768 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001769
Laurence Lundblade642282a2020-06-23 12:00:33 -07001770 /*
1771 Check to see if at the end of a bounded definite length map or
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001772 array. The check for a break ending indefinite length array is
1773 later in NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001774 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001775 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001776 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001777 goto Done;
1778 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001779
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001780 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001781 uReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001782 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1783 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001784 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001785 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301786
Laurence Lundblade642282a2020-06-23 12:00:33 -07001787 /*
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001788 Breaks ending arrays/maps are processed later in the call to
1789 NestLevelAscender(). They should never show up here.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001790 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301791 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001792 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301793 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301794 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001795
Laurence Lundblade642282a2020-06-23 12:00:33 -07001796 /*
1797 Record the nesting level for this data item before processing any
1798 of decrementing and descending.
1799 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001800 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001801
Laurence Lundblade642282a2020-06-23 12:00:33 -07001802
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001803 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001804 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001805 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001806 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001807
Laurence Lundblade93d89472020-10-03 22:30:50 -07001808 Empty indefinite length maps and arrays are descended into, but
1809 then ascended out of in the next chunk of code.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001810
1811 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001812 encloses them so a decrement needs to be done for them too, but
1813 that is done only when all the items in them have been
1814 processed, not when they are opened with the exception of an
1815 empty map or array.
1816 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001817 QCBORError uDescendErr;
1818 uDescendErr = DecodeNesting_DescendMapOrArray(&(me->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001819 pDecodedItem->uDataType,
1820 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001821 if(uDescendErr != QCBOR_SUCCESS) {
1822 /* This error is probably a traversal error and it
1823 overrides the non-traversal error. */
1824 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001825 goto Done;
1826 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001827 }
1828
Laurence Lundblade02625d42020-06-25 14:41:41 -07001829 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1830 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1831 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001832 /*
1833 The following cases are handled here:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001834 - A non-aggregate item like an integer or string
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001835 - An empty definite length map or array
1836 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001837
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001838 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001839 definite length map/array and break detection for an indefinite
1840 length map/array. If the end of the map/array was reached, then
1841 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001842 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001843 QCBORError uAscendErr;
1844 uAscendErr = NestLevelAscender(me, true);
1845 if(uAscendErr != QCBOR_SUCCESS) {
1846 /* This error is probably a traversal error and it
1847 overrides the non-traversal error. */
1848 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001849 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001850 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301851 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001852
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001853 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001854 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001855 Tell the caller what level is next. This tells them what
1856 maps/arrays were closed out and makes it possible for them to
1857 reconstruct the tree with just the information returned in
1858 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001859 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001860 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001861 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001862 pDecodedItem->uNextNestLevel = 0;
1863 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001864 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001865 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001866
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001867Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001868 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001869}
1870
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001871
1872static inline void ShiftTags(QCBORItem *pDecodedItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07001873{
Laurence Lundblade25403ed2021-01-02 16:28:07 -08001874 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM-1; i++) {
1875 pDecodedItem->uTags[i] = pDecodedItem->uTags[i+1];
1876 }
1877 pDecodedItem->uTags[QCBOR_MAX_TAGS_PER_ITEM-1] = CBOR_TAG_INVALID16;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001878}
1879
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001880
Laurence Lundblade9b334962020-08-27 10:55:53 -07001881
Laurence Lundbladea3336842021-01-03 12:38:36 -08001882/**
1883 * @brief Convert different epoch date formats in to the QCBOR epoch date format
1884 *
1885 * pDecodedItem[in,out] The data item to convert.
1886 *
1887 * @retval QCBOR_ERR_DATE_OVERFLOW
1888 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
1889 * @retval QCBOR_ERR_BAD_TAG_CONTENT
1890 *
1891 * The epoch date tag defined in QCBOR allows for floating-point
1892 * dates. It even allows a protocol to flop between date formats when
1893 * ever it wants. Floating-point dates aren't that useful as they are
1894 * only needed for dates beyond the age of the earth.
1895 *
1896 * This converts all the date formats into one format of an unsigned
1897 * integer plus a floating-point fraction.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001898 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001899static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001900{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001901 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001902
1903 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1904
1905 switch (pDecodedItem->uDataType) {
1906
1907 case QCBOR_TYPE_INT64:
1908 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1909 break;
1910
1911 case QCBOR_TYPE_UINT64:
Laurence Lundbladea3336842021-01-03 12:38:36 -08001912 /* This only happens for CBOR type 0 > INT64_MAX so it is
1913 * always an overflow.
1914 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07001915 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1916 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001917 break;
1918
1919 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001920 case QCBOR_TYPE_FLOAT:
1921#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001922 {
Laurence Lundbladea3336842021-01-03 12:38:36 -08001923 /* Convert working value to double if input was a float */
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001924 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
Laurence Lundbladea3336842021-01-03 12:38:36 -08001925 pDecodedItem->val.dfnum :
1926 (double)pDecodedItem->val.fnum;
1927
1928 /* The conversion from float to integer requires overflow
1929 * detection since floats can be much larger than integers.
1930 * This implementation errors out on these large float values
1931 * since they are beyond the age of the earth.
1932 *
1933 * These constants for the overflow check are computed by the
1934 * compiler. They are not computed at run time.
1935 *
1936 * The factor of 0x7ff is added/subtracted to avoid a
1937 * rounding error in the wrong direction when the compiler
1938 * computes these constants. There is rounding because an
1939 * 64-bit integer has 63 bits of precision where a double
1940 * only has 53 bits. Without the 0x7ff factor, the compiler
1941 * may round up and produce a double for the bounds check
1942 * that is larger than can be stored in a 64-bit integer. The
1943 * amoutn of 0x7ff is picked because it has 11 bits set.
1944 *
1945 * Without the 0x7ff there is a ~30 minute range of time
1946 * values 10 billion years in the past and in the future
1947 * where this code could go wrong. Some compilers correctly
1948 * generate a warning or error without the 0x7ff.
1949 */
1950 const double dDateMax = (double)(INT64_MAX - 0x7ff);
1951 const double dDateMin = (double)(INT64_MIN + 0x7ff);
1952
1953 if(isnan(d) || d > dDateMax || d < dDateMin) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07001954 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001955 goto Done;
1956 }
Laurence Lundbladea3336842021-01-03 12:38:36 -08001957
1958 /* The actual conversion */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001959 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001960 pDecodedItem->val.epochDate.fSecondsFraction =
1961 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001962 }
Laurence Lundbladea3336842021-01-03 12:38:36 -08001963#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade4b270642020-08-14 12:53:07 -07001964
Laurence Lundbladec7114722020-08-13 05:11:40 -07001965 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001966 goto Done;
1967
Laurence Lundblade9682a532020-06-06 18:33:04 -07001968#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001969 break;
1970
1971 default:
Laurence Lundbladea3336842021-01-03 12:38:36 -08001972 uReturn = QCBOR_ERR_BAD_TAG_CONTENT;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001973 goto Done;
1974 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001975
Laurence Lundblade59289e52019-12-30 13:44:37 -08001976 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1977
1978Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001979 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001980}
1981
1982
1983#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade123224b2021-01-03 20:58:06 -08001984/**
Laurence Lundbladee176d852021-01-03 17:50:30 -08001985 * @brief Decode decimal fractions and big floats.
1986 *
Laurence Lundblade123224b2021-01-03 20:58:06 -08001987 * @param[in] pMe The decode context.
Laurence Lundbladee176d852021-01-03 17:50:30 -08001988 * @param[in,out] pDecodedItem On input the array data item that
1989 * holds the mantissa and exponent. On
1990 * output the decoded mantissa and
1991 * exponent.
1992 *
1993 * @returns Decoding errors from getting primitive data items or
1994 * \ref QCBOR_ERR_BAD_EXP_AND_MANTISSA.
1995 *
1996 * When called pDecodedItem must be the array that is tagged as a big
1997 * float or decimal fraction, the array that has the two members, the
1998 * exponent and mantissa.
1999 *
2000 * This will fetch and decode the exponent and mantissa and put the
2001 * result back into pDecodedItem.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002002 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002003static inline QCBORError
Laurence Lundblade123224b2021-01-03 20:58:06 -08002004QCBORDecode_MantissaAndExponent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002005{
Laurence Lundbladee176d852021-01-03 17:50:30 -08002006 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002007
Laurence Lundbladee176d852021-01-03 17:50:30 -08002008 /* --- Make sure it is an array; track nesting level of members --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002009 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundbladee176d852021-01-03 17:50:30 -08002010 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002011 goto Done;
2012 }
2013
Laurence Lundbladee176d852021-01-03 17:50:30 -08002014 /* A check for pDecodedItem->val.uCount == 2 would work for
2015 * definite length arrays, but not for indefnite. Instead remember
2016 * the nesting level the two integers must be at, which is one
2017 * deeper than that of the array.
2018 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002019 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
2020
Laurence Lundbladee176d852021-01-03 17:50:30 -08002021 /* --- Which is it, ecimal fraction or a bigfloat? --- */
Laurence Lundblade123224b2021-01-03 20:58:06 -08002022 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(pMe, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002023 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
2024
Laurence Lundbladee176d852021-01-03 17:50:30 -08002025 /* --- Get the exponent --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002026 QCBORItem exponentItem;
Laurence Lundblade123224b2021-01-03 20:58:06 -08002027 uReturn = QCBORDecode_GetNextMapOrArray(pMe, &exponentItem);
Laurence Lundbladee176d852021-01-03 17:50:30 -08002028 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002029 goto Done;
2030 }
2031 if(exponentItem.uNestingLevel != nNestLevel) {
Laurence Lundbladee176d852021-01-03 17:50:30 -08002032 /* Array is empty or a map/array encountered when expecting an int */
2033 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002034 goto Done;
2035 }
2036 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundbladee176d852021-01-03 17:50:30 -08002037 /* Data arriving as an unsigned int < INT64_MAX has been
2038 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2039 * also means that the only data arriving here of type
2040 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2041 * and thus an error that will get handled in the next else.
2042 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002043 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
2044 } else {
Laurence Lundbladee176d852021-01-03 17:50:30 -08002045 /* Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX */
2046 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002047 goto Done;
2048 }
2049
Laurence Lundbladee176d852021-01-03 17:50:30 -08002050 /* --- Get the mantissa --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002051 QCBORItem mantissaItem;
Laurence Lundblade123224b2021-01-03 20:58:06 -08002052 uReturn = QCBORDecode_GetNextWithTags(pMe, &mantissaItem, NULL);
Laurence Lundbladee176d852021-01-03 17:50:30 -08002053 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002054 goto Done;
2055 }
2056 if(mantissaItem.uNestingLevel != nNestLevel) {
Laurence Lundbladee176d852021-01-03 17:50:30 -08002057 /* Mantissa missing or map/array encountered when expecting number */
2058 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002059 goto Done;
2060 }
2061 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundbladee176d852021-01-03 17:50:30 -08002062 /* Data arriving as an unsigned int < INT64_MAX has been
2063 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2064 * also means that the only data arriving here of type
2065 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2066 * and thus an error that will get handled in an else below.
2067 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002068 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade93d89472020-10-03 22:30:50 -07002069 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
2070 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundbladee176d852021-01-03 17:50:30 -08002071 /* Got a good big num mantissa */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002072 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
Laurence Lundbladee176d852021-01-03 17:50:30 -08002073 /* Depends on numbering of QCBOR_TYPE_XXX */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002074 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
2075 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
2076 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002077 } else {
Laurence Lundbladee176d852021-01-03 17:50:30 -08002078 /* Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX */
2079 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002080 goto Done;
2081 }
2082
Laurence Lundbladee176d852021-01-03 17:50:30 -08002083 /* --- Check that array only has the two numbers --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002084 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladee176d852021-01-03 17:50:30 -08002085 /* Extra items in the decimal fraction / big float */
2086 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002087 goto Done;
2088 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002089 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002090
2091Done:
Laurence Lundbladee176d852021-01-03 17:50:30 -08002092 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002093}
2094#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
2095
2096
Laurence Lundblade123224b2021-01-03 20:58:06 -08002097/**
2098 * @brief Decode the MIME type tag
2099 *
2100 * @param[in,out] pDecodedItem The item to decode.
2101 *
2102 * Handle the text and binary MIME type tags. Slightly too complicated
2103 * f or ProcessTaggedString() because the RFC 7049 MIME type was
2104 * incorreclty text-only.
2105 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002106static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002107{
2108 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
2109 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07002110 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002111 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
2112 } else {
2113 return QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002114
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002115 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002116
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002117 return QCBOR_SUCCESS;
2118}
2119
2120
Laurence Lundblade123224b2021-01-03 20:58:06 -08002121/**
Laurence Lundblade99615302020-11-29 11:19:47 -08002122 * Table of CBOR tags whose content is either a text string or a byte
2123 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
2124 * of uQCBORtype indicates the content should be a byte string rather
2125 * than a text string
2126 */
2127struct StringTagMapEntry {
2128 uint16_t uTagNumber;
2129 uint8_t uQCBORtype;
2130};
2131
2132#define IS_BYTE_STRING_BIT 0x80
2133#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
2134
2135static const struct StringTagMapEntry StringTagMap[] = {
2136 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
2137 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
2138 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
2139 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
2140 {CBOR_TAG_URI, QCBOR_TYPE_URI},
2141 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
2142 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
2143 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
2144 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
2145 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
2146 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
2147};
2148
2149
Laurence Lundblade123224b2021-01-03 20:58:06 -08002150/**
2151 * @brief Process standard CBOR tags whose content is a string
2152 *
2153 * @param[in] uTag The tag.
2154 * @param[in,out] pDecodedItem The data item.
2155 *
2156 * @returns This returns QCBOR_SUCCESS if the tag was procssed,
2157 * \ref QCBOR_ERR_UNSUPPORTED if the tag was not processed and
2158 * \ref QCBOR_ERR_BAD_OPT_TAG if the content type was wrong for the tag.
2159 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002160 * Process the CBOR tags that whose content is a byte string or a text
2161 * string and for which the string is just passed on to the caller.
2162 *
2163 * This maps the CBOR tag to the QCBOR type and checks the content
2164 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08002165 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08002166 * possible.
Laurence Lundblade99615302020-11-29 11:19:47 -08002167 */
Laurence Lundblade123224b2021-01-03 20:58:06 -08002168static inline QCBORError
2169ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002170{
Laurence Lundblade99615302020-11-29 11:19:47 -08002171 /* This only works on tags that were not mapped; no need for other yet */
2172 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
2173 return QCBOR_ERR_UNSUPPORTED;
2174 }
2175
2176 unsigned uIndex;
2177 for(uIndex = 0; StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
2178 if(StringTagMap[uIndex].uTagNumber == uTag) {
2179 break;
2180 }
2181 }
2182
2183 const uint8_t uQCBORType = StringTagMap[uIndex].uQCBORtype;
2184 if(uQCBORType == QCBOR_TYPE_NONE) {
2185 /* repurpose this error to mean, not handled here */
2186 return QCBOR_ERR_UNSUPPORTED;
2187 }
2188
2189 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
2190 if(uQCBORType & IS_BYTE_STRING_BIT) {
2191 uExpectedType = QCBOR_TYPE_BYTE_STRING;
2192 }
2193
2194 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002195 return QCBOR_ERR_BAD_OPT_TAG;
2196 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002197
Laurence Lundblade99615302020-11-29 11:19:47 -08002198 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002199 return QCBOR_SUCCESS;
2200}
2201
2202
Laurence Lundblade123224b2021-01-03 20:58:06 -08002203/**
2204 * @brief Decode tag content for select tags (decoding layer 1).
2205 *
2206 * @param[in] pMe The decode context.
2207 * @param[out] pDecodedItem The decoded item.
2208 *
2209 * @return Decoding error code.
2210 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002211 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
2212 * but the whole tag was not decoded. Here, the whole tags (tag number
2213 * and tag content) that are supported by QCBOR are decoded. This is a
2214 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002215 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002216static QCBORError
Laurence Lundblade123224b2021-01-03 20:58:06 -08002217QCBORDecode_GetNextTag(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002218{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002219 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002220
Laurence Lundblade123224b2021-01-03 20:58:06 -08002221 uReturn = QCBORDecode_GetNextMapOrArray(pMe, pDecodedItem);
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002222 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002223 goto Done;
2224 }
2225
Laurence Lundblade99615302020-11-29 11:19:47 -08002226 /* When there are no tag numbers for the item, this exits first
2227 * thing and effectively does nothing.
2228 *
2229 * This loops over all the tag numbers accumulated for this item
2230 * trying to decode and interpret them. This stops at the end of
2231 * the list or at the first tag number that can't be interpreted by
2232 * this code. This is effectively a recursive processing of the
2233 * tags number list that handles nested tags.
2234 */
2235 while(1) {
2236 /* Don't bother to unmap tags via QCBORITem.uTags since this
2237 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2238 */
2239 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002240
Laurence Lundblade99615302020-11-29 11:19:47 -08002241 if(uTagToProcess == CBOR_TAG_INVALID16) {
2242 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002243 break;
2244
Laurence Lundblade99615302020-11-29 11:19:47 -08002245 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002246 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002247
Laurence Lundblade93d89472020-10-03 22:30:50 -07002248#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002249 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2250 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundblade123224b2021-01-03 20:58:06 -08002251 uReturn = QCBORDecode_MantissaAndExponent(pMe, pDecodedItem);
Laurence Lundblade93d89472020-10-03 22:30:50 -07002252#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002253
Laurence Lundblade99615302020-11-29 11:19:47 -08002254 } else if(uTagToProcess == CBOR_TAG_MIME ||
2255 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002256 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002257
Laurence Lundblade99615302020-11-29 11:19:47 -08002258 } else {
2259 /* See if it is a pass-through byte/text string tag; process if so */
2260 uReturn = ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002261
Laurence Lundblade99615302020-11-29 11:19:47 -08002262 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
2263 /* It wasn't a pass-through byte/text string tag so it is
2264 * an unknown tag. This is the exit from the loop on the
2265 * first unknown tag. It is a successful exit.
2266 */
2267 uReturn = QCBOR_SUCCESS;
2268 break;
2269 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002270 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002271
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002272 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002273 /* Error exit from the loop */
2274 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002275 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002276
2277 /* A tag was successfully processed, shift it out of the list of
2278 * tags returned. This is the loop increment.
2279 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002280 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002281 }
2282
2283Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002284 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002285}
2286
2287
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002288/*
Laurence Lundblade123224b2021-01-03 20:58:06 -08002289 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002290 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002291QCBORError
2292QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2293{
2294 QCBORError uErr;
2295 uErr = QCBORDecode_GetNextTag(pMe, pDecodedItem);
2296 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002297 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2298 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2299 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002300 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002301}
2302
2303
2304/*
Laurence Lundblade123224b2021-01-03 20:58:06 -08002305 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002306 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002307QCBORError
2308QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2309{
2310 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2311 const UsefulInputBuf Save = pMe->InBuf;
2312
2313 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2314
2315 pMe->nesting = SaveNesting;
2316 pMe->InBuf = Save;
2317
2318 return uErr;
2319}
2320
2321
2322/*
Laurence Lundblade123224b2021-01-03 20:58:06 -08002323 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002324 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002325void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2326{
2327 if(pMe->uLastError != QCBOR_SUCCESS) {
2328 return;
2329 }
2330
2331 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2332}
2333
2334
2335/*
Laurence Lundblade123224b2021-01-03 20:58:06 -08002336 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002337 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002338QCBORError
Laurence Lundblade123224b2021-01-03 20:58:06 -08002339QCBORDecode_GetNextWithTags(QCBORDecodeContext *pMe,
2340 QCBORItem *pDecodedItem,
2341 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002342{
Laurence Lundblade123224b2021-01-03 20:58:06 -08002343 QCBORError uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002344
Laurence Lundblade123224b2021-01-03 20:58:06 -08002345 uReturn = QCBORDecode_GetNext(pMe, pDecodedItem);
2346 if(uReturn != QCBOR_SUCCESS) {
2347 return uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002348 }
2349
2350 if(pTags != NULL) {
2351 pTags->uNumUsed = 0;
Laurence Lundblade123224b2021-01-03 20:58:06 -08002352 /* Reverse the order because pTags is reverse of QCBORItem.uTags. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002353 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2354 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002355 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002356 }
2357 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2358 return QCBOR_ERR_TOO_MANY_TAGS;
2359 }
Laurence Lundblade123224b2021-01-03 20:58:06 -08002360 pTags->puTags[pTags->uNumUsed] = UnMapTagNumber(pMe,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002361 pTags->uNumUsed++;
2362 }
2363 }
2364
2365 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002366}
2367
2368
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302369/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002370 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002371 */
Laurence Lundblade123224b2021-01-03 20:58:06 -08002372bool QCBORDecode_IsTagged(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002373 const QCBORItem *pItem,
2374 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002375{
Laurence Lundblade123224b2021-01-03 20:58:06 -08002376 for(int uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002377 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002378 break;
2379 }
Laurence Lundblade123224b2021-01-03 20:58:06 -08002380 if(UnMapTagNumber(pMe, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002381 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002382 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002383 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002384
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002385 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002386}
2387
2388
2389/*
Laurence Lundblade123224b2021-01-03 20:58:06 -08002390 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002391 */
Laurence Lundblade123224b2021-01-03 20:58:06 -08002392QCBORError QCBORDecode_Finish(QCBORDecodeContext *pMe)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002393{
Laurence Lundblade123224b2021-01-03 20:58:06 -08002394 QCBORError uReturn = pMe->uLastError;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002395
2396 if(uReturn != QCBOR_SUCCESS) {
2397 goto Done;
2398 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002399
Laurence Lundblade123224b2021-01-03 20:58:06 -08002400 /* Error out if all the maps/arrays are not closed out */
2401 if(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002402 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002403 goto Done;
2404 }
2405
Laurence Lundblade123224b2021-01-03 20:58:06 -08002406 /* Error out if not all the bytes are consumed */
2407 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002408 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002409 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002410
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002411Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002412#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade123224b2021-01-03 20:58:06 -08002413 /* Call the destructor for the string allocator if there is one.
2414 * Always called, even if there are errors; always have to clean up.
2415 */
2416 StringAllocator_Destruct(&(pMe->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002417#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002418
Laurence Lundblade085d7952020-07-24 10:26:30 -07002419 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002420}
2421
2422
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002423/*
Laurence Lundblade123224b2021-01-03 20:58:06 -08002424 * Public function, see header qcbor/qcbor_decode.h file
2425 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002426// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002427uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2428 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002429 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002430{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002431 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2432 return CBOR_TAG_INVALID64;
2433 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002434 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2435 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002436 } else {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08002437 return UnMapTagNumber(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002438 }
2439}
2440
Laurence Lundblade123224b2021-01-03 20:58:06 -08002441
Laurence Lundblade9b334962020-08-27 10:55:53 -07002442/*
Laurence Lundblade123224b2021-01-03 20:58:06 -08002443 * Public function, see header qcbor/qcbor_decode.h file
2444 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002445uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2446 uint32_t uIndex)
2447{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002448 if(pMe->uLastError != QCBOR_SUCCESS) {
2449 return CBOR_TAG_INVALID64;
2450 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002451 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2452 return CBOR_TAG_INVALID64;
2453 } else {
Laurence Lundblade25403ed2021-01-02 16:28:07 -08002454 return UnMapTagNumber(pMe, pMe->uLastTags[uIndex]);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002455 }
2456}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002457
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002458
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002459
2460
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002461#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002462
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002463/* ===========================================================================
2464 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002465
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002466 This implements a simple sting allocator for indefinite length
2467 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2468 implements the function type QCBORStringAllocate and allows easy
2469 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002470
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002471 This particular allocator is built-in for convenience. The caller
2472 can implement their own. All of this following code will get
2473 dead-stripped if QCBORDecode_SetMemPool() is not called.
2474
2475 This is a very primitive memory allocator. It does not track
2476 individual allocations, only a high-water mark. A free or
2477 reallocation must be of the last chunk allocated.
2478
2479 The size of the pool and offset to free memory are packed into the
2480 first 8 bytes of the memory pool so we don't have to keep them in
2481 the decode context. Since the address of the pool may not be
2482 aligned, they have to be packed and unpacked as if they were
2483 serialized data of the wire or such.
2484
2485 The sizes packed in are uint32_t to be the same on all CPU types
2486 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002487 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002488
2489
Laurence Lundbladeee851742020-01-08 08:37:05 -08002490static inline int
2491MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002492{
2493 // Use of UsefulInputBuf is overkill, but it is convenient.
2494 UsefulInputBuf UIB;
2495
Laurence Lundbladeee851742020-01-08 08:37:05 -08002496 // Just assume the size here. It was checked during SetUp so
2497 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002498 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002499 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2500 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2501 return UsefulInputBuf_GetError(&UIB);
2502}
2503
2504
Laurence Lundbladeee851742020-01-08 08:37:05 -08002505static inline int
2506MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002507{
2508 // Use of UsefulOutBuf is overkill, but convenient. The
2509 // length check performed here is useful.
2510 UsefulOutBuf UOB;
2511
2512 UsefulOutBuf_Init(&UOB, Pool);
2513 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2514 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2515 return UsefulOutBuf_GetError(&UOB);
2516}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002517
2518
2519/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002520 Internal function for an allocation, reallocation free and destuct.
2521
2522 Having only one function rather than one each per mode saves space in
2523 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002524
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002525 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2526 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002527static UsefulBuf
2528MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002529{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002530 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002531
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002532 uint32_t uPoolSize;
2533 uint32_t uFreeOffset;
2534
2535 if(uNewSize > UINT32_MAX) {
2536 // This allocator is only good up to 4GB. This check should
2537 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2538 goto Done;
2539 }
2540 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2541
2542 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2543 goto Done;
2544 }
2545
2546 if(uNewSize) {
2547 if(pMem) {
2548 // REALLOCATION MODE
2549 // Calculate pointer to the end of the memory pool. It is
2550 // assumed that pPool + uPoolSize won't wrap around by
2551 // assuming the caller won't pass a pool buffer in that is
2552 // not in legitimate memory space.
2553 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2554
2555 // Check that the pointer for reallocation is in the range of the
2556 // pool. This also makes sure that pointer math further down
2557 // doesn't wrap under or over.
2558 if(pMem >= pPool && pMem < pPoolEnd) {
2559 // Offset to start of chunk for reallocation. This won't
2560 // wrap under because of check that pMem >= pPool. Cast
2561 // is safe because the pool is always less than UINT32_MAX
2562 // because of check in QCBORDecode_SetMemPool().
2563 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2564
2565 // Check to see if the allocation will fit. uPoolSize -
2566 // uMemOffset will not wrap under because of check that
2567 // pMem is in the range of the uPoolSize by check above.
2568 if(uNewSize <= uPoolSize - uMemOffset) {
2569 ReturnValue.ptr = pMem;
2570 ReturnValue.len = uNewSize;
2571
2572 // Addition won't wrap around over because uNewSize was
2573 // checked to be sure it is less than the pool size.
2574 uFreeOffset = uMemOffset + uNewSize32;
2575 }
2576 }
2577 } else {
2578 // ALLOCATION MODE
2579 // uPoolSize - uFreeOffset will not underflow because this
2580 // pool implementation makes sure uFreeOffset is always
2581 // smaller than uPoolSize through this check here and
2582 // reallocation case.
2583 if(uNewSize <= uPoolSize - uFreeOffset) {
2584 ReturnValue.len = uNewSize;
2585 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002586 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002587 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002588 }
2589 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002590 if(pMem) {
2591 // FREE MODE
2592 // Cast is safe because of limit on pool size in
2593 // QCBORDecode_SetMemPool()
2594 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2595 } else {
2596 // DESTRUCT MODE
2597 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002598 }
2599 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002600
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002601 UsefulBuf Pool = {pPool, uPoolSize};
2602 MemPool_Pack(Pool, uFreeOffset);
2603
2604Done:
2605 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002606}
2607
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002608
Laurence Lundbladef6531662018-12-04 10:42:22 +09002609/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002610 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002611 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002612QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2613 UsefulBuf Pool,
2614 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002615{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002616 // The pool size and free mem offset are packed into the beginning
2617 // of the pool memory. This compile time check make sure the
2618 // constant in the header is correct. This check should optimize
2619 // down to nothing.
2620 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002621 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002622 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002623
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002624 // The pool size and free offset packed in to the beginning of pool
2625 // memory are only 32-bits. This check will optimize out on 32-bit
2626 // machines.
2627 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002628 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002629 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002630
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002631 // This checks that the pool buffer given is big enough.
2632 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002633 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002634 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002635
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002636 pMe->StringAllocator.pfAllocator = MemPool_Function;
2637 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2638 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002639
Laurence Lundblade30816f22018-11-10 13:40:22 +07002640 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002641}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002642#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002643
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002644
2645
Laurence Lundblade9b334962020-08-27 10:55:53 -07002646static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2647{
2648 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2649}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002650
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002651
2652/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002653 Consume an entire map or array (and do next to
2654 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002655 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002656static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002657ConsumeItem(QCBORDecodeContext *pMe,
2658 const QCBORItem *pItemToConsume,
2659 uint_fast8_t *puNextNestLevel)
2660{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002661 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002662 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002663
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002664 // If it is a map or array, this will tell if it is empty.
2665 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2666
2667 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2668 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002669
Laurence Lundblade1341c592020-04-11 14:19:05 -07002670 /* This works for definite and indefinite length
2671 * maps and arrays by using the nesting level
2672 */
2673 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002674 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002675 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002676 goto Done;
2677 }
2678 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002679
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002680 *puNextNestLevel = Item.uNextNestLevel;
2681
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002682 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002683
Laurence Lundblade1341c592020-04-11 14:19:05 -07002684 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002685 /* item_to_consume is not a map or array */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002686 /* Just pass the nesting level through */
2687 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2688
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002689 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002690 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002691
2692Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002693 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002694}
2695
2696
Laurence Lundblade1341c592020-04-11 14:19:05 -07002697/* Return true if the labels in Item1 and Item2 are the same.
2698 Works only for integer and string labels. Returns false
2699 for any other type. */
2700static inline bool
2701MatchLabel(QCBORItem Item1, QCBORItem Item2)
2702{
2703 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2704 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2705 return true;
2706 }
2707 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002708 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002709 return true;
2710 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002711 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002712 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2713 return true;
2714 }
2715 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2716 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2717 return true;
2718 }
2719 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002720
Laurence Lundblade1341c592020-04-11 14:19:05 -07002721 /* Other label types are never matched */
2722 return false;
2723}
2724
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002725
2726/*
2727 Returns true if Item1 and Item2 are the same type
2728 or if either are of QCBOR_TYPE_ANY.
2729 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002730static inline bool
2731MatchType(QCBORItem Item1, QCBORItem Item2)
2732{
2733 if(Item1.uDataType == Item2.uDataType) {
2734 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002735 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002736 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002737 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002738 return true;
2739 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002740 return false;
2741}
2742
2743
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002744/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002745 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002746
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002747 @param[in] pMe The decode context to search.
2748 @param[in,out] pItemArray The items to search for and the items found.
2749 @param[out] puOffset Byte offset of last item matched.
2750 @param[in] pCBContext Context for the not-found item call back.
2751 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002752
2753 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2754
Laurence Lundblade93d89472020-10-03 22:30:50 -07002755 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2756 were found for one of the labels being
2757 search for. This duplicate detection is
2758 only performed for items in pItemArray,
2759 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002760
Laurence Lundblade93d89472020-10-03 22:30:50 -07002761 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2762 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002763
2764 @retval Also errors returned by QCBORDecode_GetNext().
2765
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002766 On input pItemArray contains a list of labels and data types
2767 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002768
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002769 On output the fully retrieved items are filled in with
2770 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002771
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002772 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002773
2774 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002775 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002776static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002777MapSearch(QCBORDecodeContext *pMe,
2778 QCBORItem *pItemArray,
2779 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002780 void *pCBContext,
2781 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002782{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002783 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002784 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002785
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002786 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002787 uReturn = pMe->uLastError;
2788 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002789 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002790
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002791 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002792 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2793 /* QCBOR_TYPE_NONE as first item indicates just looking
2794 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002795 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2796 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002797 }
2798
Laurence Lundblade085d7952020-07-24 10:26:30 -07002799 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2800 // It is an empty bounded array or map
2801 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2802 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002803 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002804 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002805 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002806 // Nothing is ever found in an empty array or map. All items
2807 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002808 uReturn = QCBOR_SUCCESS;
2809 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002810 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002811 }
2812
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002813 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002814 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2815
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002816 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002817 UsefulInputBuf_Seek(&(pMe->InBuf),
2818 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002819
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002820 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002821 Loop over all the items in the map or array. Each item
2822 could be a map or array, but label matching is only at
2823 the main level. This handles definite and indefinite
2824 length maps and arrays. The only reason this is ever
2825 called on arrays is to find their end position.
2826
2827 This will always run over all items in order to do
2828 duplicate detection.
2829
2830 This will exit with failure if it encounters an
2831 unrecoverable error, but continue on for recoverable
2832 errors.
2833
2834 If a recoverable error occurs on a matched item, then
2835 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002836 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002837 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002838 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002839 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002840 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002841 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002842
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002843 /* Get the item */
2844 QCBORItem Item;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002845 QCBORError uResult = QCBORDecode_GetNextTag(pMe, &Item);
2846 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002847 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002848 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002849 goto Done;
2850 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002851 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002852 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002853 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002854 goto Done;
2855 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002856
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002857 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002858 bool bMatched = false;
2859 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2860 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002861 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002862 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2863 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002864 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002865 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002866 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002867 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002868 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002869 goto Done;
2870 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002871
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002872 if(uResult != QCBOR_SUCCESS) {
2873 uReturn = uResult;
2874 goto Done;
2875 }
2876
Laurence Lundblade1341c592020-04-11 14:19:05 -07002877 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002878 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002879 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002880 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002881 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002882 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002883 bMatched = true;
2884 }
2885 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002886
2887
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002888 if(!bMatched && pfCallback != NULL) {
2889 /*
2890 Call the callback on unmatched labels.
2891 (It is tempting to do duplicate detection here, but that would
2892 require dynamic memory allocation because the number of labels
2893 that might be encountered is unbounded.)
2894 */
2895 uReturn = (*pfCallback)(pCBContext, &Item);
2896 if(uReturn != QCBOR_SUCCESS) {
2897 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002898 }
2899 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002900
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002901 /*
2902 Consume the item whether matched or not. This
2903 does the work of traversing maps and array and
2904 everything in them. In this loop only the
2905 items at the current nesting level are examined
2906 to match the labels.
2907 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002908 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002909 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002910 goto Done;
2911 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002912
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002913 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002914
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002915 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002916
2917 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002918
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002919 // Check here makes sure that this won't accidentally be
2920 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002921 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08002922 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
2923 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002924 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
2925 goto Done;
2926 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002927 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2928 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002929
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002930 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002931 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2932
2933 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002934 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002935 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002936 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002937 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
2938 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002939 }
2940 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002941
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002942 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002943}
2944
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002945
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002946/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002947 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002948*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002949void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2950 int64_t nLabel,
2951 uint8_t uQcborType,
2952 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002953{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002954 if(pMe->uLastError != QCBOR_SUCCESS) {
2955 return;
2956 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002957
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002958 QCBORItem OneItemSeach[2];
2959 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2960 OneItemSeach[0].label.int64 = nLabel;
2961 OneItemSeach[0].uDataType = uQcborType;
2962 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002963
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002964 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002965
2966 *pItem = OneItemSeach[0];
2967
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002968 if(uReturn != QCBOR_SUCCESS) {
2969 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002970 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002971 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002972 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002973 }
2974
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002975 Done:
2976 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002977}
2978
2979
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002980/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002981 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002982*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002983void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2984 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002985 uint8_t uQcborType,
2986 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002987{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002988 if(pMe->uLastError != QCBOR_SUCCESS) {
2989 return;
2990 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002991
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002992 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002993 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2994 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2995 OneItemSeach[0].uDataType = uQcborType;
2996 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002997
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002998 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2999 if(uReturn != QCBOR_SUCCESS) {
3000 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003001 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003002 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003003 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003004 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003005 }
3006
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003007 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003008
3009Done:
3010 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003011}
3012
3013
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003014
Laurence Lundblade93d89472020-10-03 22:30:50 -07003015static QCBORError
3016CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003017{
3018 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
3019 if(uDataType == puTypeList[i]) {
3020 return QCBOR_SUCCESS;
3021 }
3022 }
3023 return QCBOR_ERR_UNEXPECTED_TYPE;
3024}
3025
Laurence Lundblade67257dc2020-07-27 03:33:37 -07003026
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003027/**
3028 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003029 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07003030
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003031 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
3032 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07003033
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003034 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered
3035 tag value.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003036 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07003037static QCBORError
3038CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07003039{
3040 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
3041 pItem->uTags[0] != CBOR_TAG_INVALID16) {
3042 /* There are tags that QCBOR couldn't process on this item and
3043 the caller has told us there should not be. */
3044 return QCBOR_ERR_UNEXPECTED_TYPE;
3045 }
3046
3047 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
3048 const int nItemType = pItem->uDataType;
3049
3050 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
3051 // Must match the tag and only the tag
3052 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3053 }
3054
3055 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
3056 if(uReturn == QCBOR_SUCCESS) {
3057 return QCBOR_SUCCESS;
3058 }
3059
3060 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
3061 /* Must match the content type and only the content type.
3062 There was no match just above so it is a fail. */
3063 return QCBOR_ERR_UNEXPECTED_TYPE;
3064 }
3065
3066 /* If here it can match either the tag or the content
3067 and it hasn't matched the content, so the end
3068 result is whether it matches the tag. This is
3069 also the case that the CBOR standard discourages. */
3070
3071 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3072}
3073
Laurence Lundblade9b334962020-08-27 10:55:53 -07003074
Laurence Lundblade9b334962020-08-27 10:55:53 -07003075
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003076// This could be semi-private if need be
3077static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003078void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
3079 int64_t nLabel,
3080 TagSpecification TagSpec,
3081 QCBORItem *pItem)
3082{
3083 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
3084 if(pMe->uLastError != QCBOR_SUCCESS) {
3085 return;
3086 }
3087
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003088 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003089}
3090
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003091
3092// This could be semi-private if need be
3093static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003094void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
3095 const char *szLabel,
3096 TagSpecification TagSpec,
3097 QCBORItem *pItem)
3098{
3099 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
3100 if(pMe->uLastError != QCBOR_SUCCESS) {
3101 return;
3102 }
3103
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003104 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003105}
3106
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003107// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003108void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
3109 int64_t nLabel,
3110 TagSpecification TagSpec,
3111 UsefulBufC *pString)
3112{
3113 QCBORItem Item;
3114 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
3115 if(pMe->uLastError == QCBOR_SUCCESS) {
3116 *pString = Item.val.string;
3117 }
3118}
3119
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003120// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003121void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
3122 const char * szLabel,
3123 TagSpecification TagSpec,
3124 UsefulBufC *pString)
3125{
3126 QCBORItem Item;
3127 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
3128 if(pMe->uLastError == QCBOR_SUCCESS) {
3129 *pString = Item.val.string;
3130 }
3131}
Laurence Lundblade1341c592020-04-11 14:19:05 -07003132
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003133/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003134 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003135*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003136void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003137{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003138 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
3139 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003140}
3141
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003142/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003143 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003144*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003145void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3146 QCBORItem *pItemList,
3147 void *pCallbackCtx,
3148 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003149{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003150 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
3151 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003152}
3153
3154
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003155/**
3156 * @brief Search for a map/array by label and enter it
3157 *
3158 * @param[in] pMe The decode context.
3159 * @param[in] pSearch The map/array to search for.
3160 *
3161 * @c pSearch is expected to contain one item of type map or array
3162 * with the label specified. The current bounded map will be searched for
3163 * this and if found will be entered.
3164 *
3165 * If the label is not found, or the item found is not a map or array,
3166 * the error state is set.
3167 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003168static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003169{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003170 // The first item in pSearch is the one that is to be
3171 // entered. It should be the only one filled in. Any other
3172 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003173 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003174 return;
3175 }
3176
3177 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003178 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003179 if(pMe->uLastError != QCBOR_SUCCESS) {
3180 return;
3181 }
3182
Laurence Lundblade9b334962020-08-27 10:55:53 -07003183 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003184 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003185 return;
3186 }
3187
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003188 /*
3189 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3190 * next item for the pre-order traversal cursor to be the map/array
3191 * found by MapSearch(). The next few lines of code force the
3192 * cursor to that.
3193 *
3194 * There is no need to retain the old cursor because
3195 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3196 * beginning of the map/array being entered.
3197 *
3198 * The cursor is forced by: 1) setting the input buffer position to
3199 * the item offset found by MapSearch(), 2) setting the map/array
3200 * counter to the total in the map/array, 3) setting the nesting
3201 * level. Setting the map/array counter to the total is not
3202 * strictly correct, but this is OK because this cursor only needs
3203 * to be used to get one item and MapSearch() has already found it
3204 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003205 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003206 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003207
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003208 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3209
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003210 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003211
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003212 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003213}
3214
3215
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003216/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003217 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003218*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003219void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003220{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003221 QCBORItem OneItemSeach[2];
3222 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3223 OneItemSeach[0].label.int64 = nLabel;
3224 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3225 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003226
Laurence Lundblade9b334962020-08-27 10:55:53 -07003227 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003228 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003229}
3230
3231
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003232/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003233 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003234*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003235void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003236{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003237 QCBORItem OneItemSeach[2];
3238 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3239 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3240 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3241 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003242
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003243 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003244}
3245
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003246/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003247 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003248*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003249void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003250{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003251 QCBORItem OneItemSeach[2];
3252 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3253 OneItemSeach[0].label.int64 = nLabel;
3254 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3255 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003256
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003257 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003258}
3259
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003260/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003261 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003262*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003263void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3264{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003265 QCBORItem OneItemSeach[2];
3266 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3267 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3268 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3269 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003270
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003271 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003272}
3273
3274
Laurence Lundblade02625d42020-06-25 14:41:41 -07003275// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003276void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003277{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003278 QCBORError uErr;
3279
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003280 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003281 if(pMe->uLastError != QCBOR_SUCCESS) {
3282 // Already in error state; do nothing.
3283 return;
3284 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003285
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003286 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003287 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003288 uErr = QCBORDecode_GetNext(pMe, &Item);
3289 if(uErr != QCBOR_SUCCESS) {
3290 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003291 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003292 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003293 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3294 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003295 }
3296
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003297 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003298
3299
Laurence Lundbladef0499502020-08-01 11:55:57 -07003300 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003301 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003302 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3303 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003304 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003305 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3306 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003307 // Special case to increment nesting level for zero-length maps
3308 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003309 DecodeNesting_Descend(&(pMe->nesting), uType);
3310 }
3311
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003312 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003313
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003314 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3315 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003316
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003317 if(pItem != NULL) {
3318 *pItem = Item;
3319 }
3320
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003321Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003322 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003323}
3324
Laurence Lundblade02625d42020-06-25 14:41:41 -07003325
3326/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003327 This is the common work for exiting a level that is a bounded map,
3328 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003329
3330 One chunk of work is to set up the pre-order traversal so it is at
3331 the item just after the bounded map, array or bstr that is being
3332 exited. This is somewhat complex.
3333
3334 The other work is to level-up the bounded mode to next higest bounded
3335 mode or the top level if there isn't one.
3336 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003337static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003338ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003339{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003340 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003341
Laurence Lundblade02625d42020-06-25 14:41:41 -07003342 /*
3343 First the pre-order-traversal byte offset is positioned to the
3344 item just after the bounded mode item that was just consumed.
3345 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003346 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3347
Laurence Lundblade02625d42020-06-25 14:41:41 -07003348 /*
3349 Next, set the current nesting level to one above the bounded level
3350 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003351
Laurence Lundblade02625d42020-06-25 14:41:41 -07003352 DecodeNesting_CheckBoundedType() is always called before this and
3353 makes sure pCurrentBounded is valid.
3354 */
3355 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3356
3357 /*
3358 This does the complex work of leveling up the pre-order traversal
3359 when the end of a map or array or another bounded level is
3360 reached. It may do nothing, or ascend all the way to the top
3361 level.
3362 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07003363 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003364 if(uErr != QCBOR_SUCCESS) {
3365 goto Done;
3366 }
3367
Laurence Lundblade02625d42020-06-25 14:41:41 -07003368 /*
3369 This makes the next highest bounded level the current bounded
3370 level. If there is no next highest level, then no bounded mode is
3371 in effect.
3372 */
3373 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003374
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003375 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003376
3377Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003378 return uErr;
3379}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003380
Laurence Lundblade02625d42020-06-25 14:41:41 -07003381
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003382// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003383void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003384{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003385 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003386 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003387 return;
3388 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003389
Laurence Lundblade02625d42020-06-25 14:41:41 -07003390 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003391
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003392 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003393 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003394 goto Done;
3395 }
3396
Laurence Lundblade02625d42020-06-25 14:41:41 -07003397 /*
3398 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003399 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003400 from previous map search, then do a dummy search.
3401 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003402 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003403 QCBORItem Dummy;
3404 Dummy.uLabelType = QCBOR_TYPE_NONE;
3405 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3406 if(uErr != QCBOR_SUCCESS) {
3407 goto Done;
3408 }
3409 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003410
Laurence Lundblade02625d42020-06-25 14:41:41 -07003411 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003412
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003413Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003414 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003415}
3416
3417
Laurence Lundblade1341c592020-04-11 14:19:05 -07003418
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003419static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003420 const QCBORItem *pItem,
3421 uint8_t uTagRequirement,
3422 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003423{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003424 if(pBstr) {
3425 *pBstr = NULLUsefulBufC;
3426 }
3427
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003428 if(pMe->uLastError != QCBOR_SUCCESS) {
3429 // Already in error state; do nothing.
3430 return pMe->uLastError;
3431 }
3432
3433 QCBORError uError = QCBOR_SUCCESS;
3434
3435 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3436 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3437 goto Done;;
3438 }
3439
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003440 const TagSpecification TagSpec =
3441 {
3442 uTagRequirement,
3443 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3444 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3445 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003446
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003447 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003448 if(uError != QCBOR_SUCCESS) {
3449 goto Done;
3450 }
3451
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003452 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003453 // Reverse the decrement done by GetNext() for the bstr so the
3454 // increment in NestLevelAscender() called by ExitBoundedLevel()
3455 // will work right.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003456 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003457 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003458
3459 if(pBstr) {
3460 *pBstr = pItem->val.string;
3461 }
3462
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003463 // This saves the current length of the UsefulInputBuf and then
3464 // narrows the UsefulInputBuf to start and length of the wrapped
3465 // CBOR that is being entered.
3466 //
3467 // This makes sure the length is less than
3468 // QCBOR_MAX_DECODE_INPUT_SIZE which is slighly less than
3469 // UINT32_MAX. The value UINT32_MAX is used as a special indicator
3470 // value. The checks against QCBOR_MAX_DECODE_INPUT_SIZE also make
3471 // the casts safe. uEndOfBstr will always be less than
3472 // uPreviousLength because of the way UsefulInputBuf works so there
3473 // is no need to check it. There is also a range check in the
3474 // seek.
3475 //
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003476 // Most of these calls are simple inline accessors so this doesn't
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003477 // amount to much code.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003478 // Cast of uPreviousLength to uint32_t for cases where SIZE_MAX < UINT32_MAX.
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003479 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003480 if((uint32_t)uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003481 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003482 goto Done;
3483 }
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003484 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003485 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003486 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003487
Laurence Lundblade02625d42020-06-25 14:41:41 -07003488 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003489 (uint32_t)uPreviousLength,
3490 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003491Done:
3492 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003493}
3494
3495
Laurence Lundblade02625d42020-06-25 14:41:41 -07003496/*
3497 Public function, see header qcbor/qcbor_decode.h file
3498 */
3499void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003500 uint8_t uTagRequirement,
3501 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003502{
3503 if(pMe->uLastError != QCBOR_SUCCESS) {
3504 // Already in error state; do nothing.
3505 return;
3506 }
3507
3508 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003509 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003510 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3511 if(pMe->uLastError != QCBOR_SUCCESS) {
3512 return;
3513 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003514
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003515 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003516 &Item,
3517 uTagRequirement,
3518 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003519}
3520
3521
Laurence Lundblade02625d42020-06-25 14:41:41 -07003522/*
3523 Public function, see header qcbor/qcbor_decode.h file
3524 */
3525void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003526 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003527 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003528 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003529{
3530 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003531 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003532
Laurence Lundblade93d89472020-10-03 22:30:50 -07003533 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3534 &Item,
3535 uTagRequirement,
3536 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003537}
3538
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003539
Laurence Lundblade02625d42020-06-25 14:41:41 -07003540/*
3541 Public function, see header qcbor/qcbor_decode.h file
3542 */
3543void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003544 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003545 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003546 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003547{
3548 QCBORItem Item;
3549 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3550
Laurence Lundblade93d89472020-10-03 22:30:50 -07003551 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3552 &Item,
3553 uTagRequirement,
3554 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003555}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003556
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003557
Laurence Lundblade02625d42020-06-25 14:41:41 -07003558/*
3559 Public function, see header qcbor/qcbor_decode.h file
3560 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003561void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003562{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003563 if(pMe->uLastError != QCBOR_SUCCESS) {
3564 // Already in error state; do nothing.
3565 return;
3566 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003567
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003568 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003569 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003570 return;
3571 }
3572
3573 /*
3574 Reset the length of the UsefulInputBuf to what it was before
3575 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003576 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003577 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003578 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003579
3580
Laurence Lundblade02625d42020-06-25 14:41:41 -07003581 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003582 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003583}
3584
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003585
Laurence Lundbladee6430642020-03-14 21:15:44 -07003586
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003587
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003588
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003589
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003590
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003591
Laurence Lundblade93d89472020-10-03 22:30:50 -07003592static QCBORError
3593InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003594{
3595 switch(pItem->uDataType) {
3596 case QCBOR_TYPE_TRUE:
3597 *pBool = true;
3598 return QCBOR_SUCCESS;
3599 break;
3600
3601 case QCBOR_TYPE_FALSE:
3602 *pBool = false;
3603 return QCBOR_SUCCESS;
3604 break;
3605
3606 default:
3607 return QCBOR_ERR_UNEXPECTED_TYPE;
3608 break;
3609 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003610 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003611}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003612
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003613
Laurence Lundblade9b334962020-08-27 10:55:53 -07003614
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003615/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003616 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003617*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003618void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003619{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003620 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003621 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003622 return;
3623 }
3624
Laurence Lundbladec4537442020-04-14 18:53:22 -07003625 QCBORError nError;
3626 QCBORItem Item;
3627
3628 nError = QCBORDecode_GetNext(pMe, &Item);
3629 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003630 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003631 return;
3632 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003633 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003634}
3635
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003636
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003637/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003638 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003639*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003640void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003641{
3642 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003643 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003644
Laurence Lundblade9b334962020-08-27 10:55:53 -07003645 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003646}
3647
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003648
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003649/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003650 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003651*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003652void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3653{
3654 QCBORItem Item;
3655 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3656
Laurence Lundblade9b334962020-08-27 10:55:53 -07003657 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003658}
3659
3660
3661
Laurence Lundbladec7114722020-08-13 05:11:40 -07003662
3663static void ProcessEpochDate(QCBORDecodeContext *pMe,
3664 QCBORItem *pItem,
3665 uint8_t uTagRequirement,
3666 int64_t *pnTime)
3667{
3668 if(pMe->uLastError != QCBOR_SUCCESS) {
3669 // Already in error state, do nothing
3670 return;
3671 }
3672
3673 QCBORError uErr;
3674
3675 const TagSpecification TagSpec =
3676 {
3677 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003678 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3679 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003680 };
3681
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003682 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003683 if(uErr != QCBOR_SUCCESS) {
3684 goto Done;
3685 }
3686
3687 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3688 uErr = DecodeDateEpoch(pItem);
3689 if(uErr != QCBOR_SUCCESS) {
3690 goto Done;
3691 }
3692 }
3693
Laurence Lundblade9b334962020-08-27 10:55:53 -07003694 // Save the tags in the last item's tags in the decode context
3695 // for QCBORDecode_GetNthTagOfLast()
3696 CopyTags(pMe, pItem);
3697
Laurence Lundbladec7114722020-08-13 05:11:40 -07003698 *pnTime = pItem->val.epochDate.nSeconds;
3699
3700Done:
3701 pMe->uLastError = (uint8_t)uErr;
3702}
3703
3704
3705void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003706 uint8_t uTagRequirement,
3707 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07003708{
3709 if(pMe->uLastError != QCBOR_SUCCESS) {
3710 // Already in error state, do nothing
3711 return;
3712 }
3713
3714 QCBORItem Item;
3715 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3716
3717 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3718}
3719
3720
3721void
3722QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3723 int64_t nLabel,
3724 uint8_t uTagRequirement,
3725 int64_t *pnTime)
3726{
3727 QCBORItem Item;
3728 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3729 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3730}
3731
3732
3733void
3734QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3735 const char *szLabel,
3736 uint8_t uTagRequirement,
3737 int64_t *pnTime)
3738{
3739 QCBORItem Item;
3740 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3741 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3742}
3743
3744
3745
3746
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003747void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3748 TagSpecification TagSpec,
3749 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003750{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003751 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003752 // Already in error state, do nothing
3753 return;
3754 }
3755
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003756 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003757 QCBORItem Item;
3758
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003759 uError = QCBORDecode_GetNext(pMe, &Item);
3760 if(uError != QCBOR_SUCCESS) {
3761 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003762 return;
3763 }
3764
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003765 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003766
3767 if(pMe->uLastError == QCBOR_SUCCESS) {
3768 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003769 } else {
3770 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003771 }
3772}
3773
Laurence Lundbladec4537442020-04-14 18:53:22 -07003774
3775
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003776
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003777static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003778 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003779 UsefulBufC *pValue,
3780 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003781{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003782 const TagSpecification TagSpec =
3783 {
3784 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003785 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3786 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003787 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003788
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003789 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003790 if(uErr != QCBOR_SUCCESS) {
3791 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003792 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003793
3794 *pValue = pItem->val.string;
3795
3796 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3797 *pbIsNegative = false;
3798 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3799 *pbIsNegative = true;
3800 }
3801
3802 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003803}
3804
3805
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003806/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003807 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003808 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003809void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3810 uint8_t uTagRequirement,
3811 UsefulBufC *pValue,
3812 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003813{
3814 if(pMe->uLastError != QCBOR_SUCCESS) {
3815 // Already in error state, do nothing
3816 return;
3817 }
3818
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003819 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003820 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3821 if(uError != QCBOR_SUCCESS) {
3822 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003823 return;
3824 }
3825
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003826 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003827}
3828
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003829
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003830/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003831 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003832*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003833void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3834 int64_t nLabel,
3835 uint8_t uTagRequirement,
3836 UsefulBufC *pValue,
3837 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003838{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003839 QCBORItem Item;
3840 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003841 if(pMe->uLastError != QCBOR_SUCCESS) {
3842 return;
3843 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003844
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003845 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003846}
3847
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003848
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003849/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003850 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003851*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003852void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3853 const char *szLabel,
3854 uint8_t uTagRequirement,
3855 UsefulBufC *pValue,
3856 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003857{
3858 QCBORItem Item;
3859 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003860 if(pMe->uLastError != QCBOR_SUCCESS) {
3861 return;
3862 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003863
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003864 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003865}
3866
3867
3868
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003869
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003870// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003871QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3872 const QCBORItem *pItem,
3873 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07003874 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003875{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003876 const TagSpecification TagSpecText =
3877 {
3878 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003879 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3880 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003881 };
3882 const TagSpecification TagSpecBinary =
3883 {
3884 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003885 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3886 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003887 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003888
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003889 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003890
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003891 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003892 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003893 if(pbIsTag257 != NULL) {
3894 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003895 }
3896 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003897 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003898 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003899 if(pbIsTag257 != NULL) {
3900 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003901 }
3902 uReturn = QCBOR_SUCCESS;
3903
3904 } else {
3905 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3906 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003907
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003908 return uReturn;
3909}
3910
Laurence Lundblade93d89472020-10-03 22:30:50 -07003911// Improvement: add methods for wrapped CBOR, a simple alternate
3912// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003913
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003914
3915
3916
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003917#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003918
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003919typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003920
3921
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003922// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003923static QCBORError
3924Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003925{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003926 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003927
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003928 if(uResult != 0) {
3929 /* This loop will run a maximum of 19 times because
3930 * UINT64_MAX < 10 ^^ 19. More than that will cause
3931 * exit with the overflow error
3932 */
3933 for(; nExponent > 0; nExponent--) {
3934 if(uResult > UINT64_MAX / 10) {
3935 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3936 }
3937 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003938 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003939
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003940 for(; nExponent < 0; nExponent++) {
3941 uResult = uResult / 10;
3942 if(uResult == 0) {
3943 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3944 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003945 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003946 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003947 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003948
3949 *puResult = uResult;
3950
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003951 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003952}
3953
3954
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003955// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003956static QCBORError
3957Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003958{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003959 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003960
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003961 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003962
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003963 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003964 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003965 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003966 */
3967 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003968 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003969 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003970 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003971 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003972 nExponent--;
3973 }
3974
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003975 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003976 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003977 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3978 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003979 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003980 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003981 }
3982
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003983 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003984
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003985 return QCBOR_SUCCESS;
3986}
3987
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003988
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003989/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003990 Compute value with signed mantissa and signed result. Works with
3991 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003992 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003993static inline QCBORError ExponentiateNN(int64_t nMantissa,
3994 int64_t nExponent,
3995 int64_t *pnResult,
3996 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003997{
3998 uint64_t uResult;
3999
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004000 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004001 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004002 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
4003
4004 // Do the exponentiation of the positive mantissa
4005 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
4006 if(uReturn) {
4007 return uReturn;
4008 }
4009
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004010
Laurence Lundblade983500d2020-05-14 11:49:34 -07004011 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
4012 of INT64_MIN. This assumes two's compliment representation where
4013 INT64_MIN is one increment farther from 0 than INT64_MAX.
4014 Trying to write -INT64_MIN doesn't work to get this because the
4015 compiler tries to work with an int64_t which can't represent
4016 -INT64_MIN.
4017 */
4018 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
4019
4020 // Error out if too large
4021 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004022 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4023 }
4024
4025 // Casts are safe because of checks above
4026 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
4027
4028 return QCBOR_SUCCESS;
4029}
4030
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004031
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004032/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004033 Compute value with signed mantissa and unsigned result. Works with
4034 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004035 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004036static inline QCBORError ExponentitateNU(int64_t nMantissa,
4037 int64_t nExponent,
4038 uint64_t *puResult,
4039 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004040{
4041 if(nMantissa < 0) {
4042 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4043 }
4044
4045 // Cast to unsigned is OK because of check for negative
4046 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
4047 // Exponentiation is straight forward
4048 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
4049}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004050
4051
4052/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004053 Compute value with signed mantissa and unsigned result. Works with
4054 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004055 */
4056static inline QCBORError ExponentitateUU(uint64_t uMantissa,
4057 int64_t nExponent,
4058 uint64_t *puResult,
4059 fExponentiator pfExp)
4060{
4061 return (*pfExp)(uMantissa, nExponent, puResult);
4062}
4063
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004064#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4065
4066
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004067
4068
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004069
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004070static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004071{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004072 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004073
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004074 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004075 const uint8_t *pByte = BigNum.ptr;
4076 size_t uLen = BigNum.len;
4077 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07004078 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004079 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004080 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07004081 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004082 }
4083
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004084 *pResult = uResult;
4085 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004086}
4087
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004088
Laurence Lundblade887add82020-05-17 05:50:34 -07004089static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004090{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004091 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004092}
4093
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004094
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004095static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004096{
4097 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004098 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
4099 if(uError) {
4100 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004101 }
4102 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
4103 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004104 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004105}
4106
4107
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004108static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004109{
4110 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004111 /* The negative integer furthest from zero for a C int64_t is
4112 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
4113 negative number in CBOR is computed as -n - 1 where n is the
4114 encoded integer, where n is what is in the variable BigNum. When
4115 converting BigNum to a uint64_t, the maximum value is thus
4116 INT64_MAX, so that when it -n - 1 is applied to it the result will
4117 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07004118
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004119 -n - 1 <= INT64_MIN.
4120 -n - 1 <= -INT64_MAX - 1
4121 n <= INT64_MAX.
4122 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07004123 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004124 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004125 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004126 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004127
4128 /// Now apply -n - 1. The cast is safe because
4129 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
4130 // is the largest positive integer that an int64_t can
4131 // represent. */
4132 *pnResult = -(int64_t)uResult - 1;
4133
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004134 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004135}
4136
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004137
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004138
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004139
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004140
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004141/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004142Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004143
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004144\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004145
Laurence Lundblade93d89472020-10-03 22:30:50 -07004146\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4147 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004148
4149\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4150
Laurence Lundblade93d89472020-10-03 22:30:50 -07004151\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4152 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004153*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07004154static QCBORError
4155ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004156{
4157 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004158 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004159 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004160#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004161 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004162 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
4163 http://www.cplusplus.com/reference/cmath/llround/
4164 */
4165 // Not interested in FE_INEXACT
4166 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004167 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4168 *pnValue = llround(pItem->val.dfnum);
4169 } else {
4170 *pnValue = lroundf(pItem->val.fnum);
4171 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004172 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4173 // llround() shouldn't result in divide by zero, but catch
4174 // it here in case it unexpectedly does. Don't try to
4175 // distinguish between the various exceptions because it seems
4176 // they vary by CPU, compiler and OS.
4177 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004178 }
4179 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004180 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004181 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004182#else
4183 return QCBOR_ERR_HW_FLOAT_DISABLED;
4184#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004185 break;
4186
4187 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004188 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004189 *pnValue = pItem->val.int64;
4190 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004191 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004192 }
4193 break;
4194
4195 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004196 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004197 if(pItem->val.uint64 < INT64_MAX) {
4198 *pnValue = pItem->val.int64;
4199 } else {
4200 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4201 }
4202 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004203 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004204 }
4205 break;
4206
4207 default:
4208 return QCBOR_ERR_UNEXPECTED_TYPE;
4209 }
4210 return QCBOR_SUCCESS;
4211}
4212
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004213
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004214void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004215 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004216 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004217 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004218{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004219 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004220 return;
4221 }
4222
Laurence Lundbladee6430642020-03-14 21:15:44 -07004223 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004224 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4225 if(uError) {
4226 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004227 return;
4228 }
4229
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004230 if(pItem) {
4231 *pItem = Item;
4232 }
4233
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004234 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004235}
4236
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004237
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004238void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4239 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004240 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004241 int64_t *pnValue,
4242 QCBORItem *pItem)
4243{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004244 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004245 if(pMe->uLastError != QCBOR_SUCCESS) {
4246 return;
4247 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004248
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004249 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004250}
4251
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004252
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004253void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4254 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004255 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004256 int64_t *pnValue,
4257 QCBORItem *pItem)
4258{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004259 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004260 if(pMe->uLastError != QCBOR_SUCCESS) {
4261 return;
4262 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004263
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004264 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004265}
4266
4267
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004268/*
4269 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004270
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004271 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004272
Laurence Lundblade93d89472020-10-03 22:30:50 -07004273 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4274 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004275
4276 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4277
Laurence Lundblade93d89472020-10-03 22:30:50 -07004278 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4279 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004280 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004281static QCBORError
4282Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004283{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004284 switch(pItem->uDataType) {
4285
4286 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004287 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004288 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004289 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004290 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004291 }
4292 break;
4293
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004294 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004295 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004296 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004297 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004298 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004299 }
4300 break;
4301
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004302#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4303 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004304 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004305 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004306 pItem->val.expAndMantissa.nExponent,
4307 pnValue,
4308 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004309 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004310 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004311 }
4312 break;
4313
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004314 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004315 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004316 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004317 pItem->val.expAndMantissa.nExponent,
4318 pnValue,
4319 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004320 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004321 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004322 }
4323 break;
4324
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004325 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004326 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004327 int64_t nMantissa;
4328 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004329 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4330 if(uErr) {
4331 return uErr;
4332 }
4333 return ExponentiateNN(nMantissa,
4334 pItem->val.expAndMantissa.nExponent,
4335 pnValue,
4336 Exponentitate10);
4337 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004338 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004339 }
4340 break;
4341
4342 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004343 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004344 int64_t nMantissa;
4345 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004346 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4347 if(uErr) {
4348 return uErr;
4349 }
4350 return ExponentiateNN(nMantissa,
4351 pItem->val.expAndMantissa.nExponent,
4352 pnValue,
4353 Exponentitate10);
4354 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004355 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004356 }
4357 break;
4358
4359 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004360 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004361 int64_t nMantissa;
4362 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004363 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4364 if(uErr) {
4365 return uErr;
4366 }
4367 return ExponentiateNN(nMantissa,
4368 pItem->val.expAndMantissa.nExponent,
4369 pnValue,
4370 Exponentitate2);
4371 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004372 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004373 }
4374 break;
4375
4376 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004377 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004378 int64_t nMantissa;
4379 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004380 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4381 if(uErr) {
4382 return uErr;
4383 }
4384 return ExponentiateNN(nMantissa,
4385 pItem->val.expAndMantissa.nExponent,
4386 pnValue,
4387 Exponentitate2);
4388 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004389 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004390 }
4391 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004392#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4393
Laurence Lundbladee6430642020-03-14 21:15:44 -07004394
Laurence Lundbladec4537442020-04-14 18:53:22 -07004395 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004396 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004397}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004398
4399
Laurence Lundbladec4537442020-04-14 18:53:22 -07004400/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004401 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004402 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004403void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004404{
4405 QCBORItem Item;
4406
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004407 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004408
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004409 if(pMe->uLastError == QCBOR_SUCCESS) {
4410 // The above conversion succeeded
4411 return;
4412 }
4413
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004414 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004415 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004416 return;
4417 }
4418
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004419 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004420}
4421
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004422
4423/*
4424Public function, see header qcbor/qcbor_decode.h file
4425*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004426void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4427 int64_t nLabel,
4428 uint32_t uConvertTypes,
4429 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004430{
4431 QCBORItem Item;
4432
Laurence Lundblade93d89472020-10-03 22:30:50 -07004433 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4434 nLabel,
4435 uConvertTypes,
4436 pnValue,
4437 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004438
4439 if(pMe->uLastError == QCBOR_SUCCESS) {
4440 // The above conversion succeeded
4441 return;
4442 }
4443
4444 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4445 // The above conversion failed in a way that code below can't correct
4446 return;
4447 }
4448
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004449 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004450}
4451
4452
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004453/*
4454Public function, see header qcbor/qcbor_decode.h file
4455*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004456void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4457 const char *szLabel,
4458 uint32_t uConvertTypes,
4459 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004460{
4461 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004462 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4463 szLabel,
4464 uConvertTypes,
4465 pnValue,
4466 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004467
4468 if(pMe->uLastError == QCBOR_SUCCESS) {
4469 // The above conversion succeeded
4470 return;
4471 }
4472
4473 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4474 // The above conversion failed in a way that code below can't correct
4475 return;
4476 }
4477
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004478 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004479}
4480
4481
Laurence Lundblade93d89472020-10-03 22:30:50 -07004482static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004483{
4484 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004485 case QCBOR_TYPE_DOUBLE:
4486 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004487#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004488 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004489 // Can't use llround here because it will not convert values
4490 // greater than INT64_MAX and less than UINT64_MAX that
4491 // need to be converted so it is more complicated.
4492 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4493 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4494 if(isnan(pItem->val.dfnum)) {
4495 return QCBOR_ERR_FLOAT_EXCEPTION;
4496 } else if(pItem->val.dfnum < 0) {
4497 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4498 } else {
4499 double dRounded = round(pItem->val.dfnum);
4500 // See discussion in DecodeDateEpoch() for
4501 // explanation of - 0x7ff
4502 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4503 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4504 }
4505 *puValue = (uint64_t)dRounded;
4506 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004507 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004508 if(isnan(pItem->val.fnum)) {
4509 return QCBOR_ERR_FLOAT_EXCEPTION;
4510 } else if(pItem->val.fnum < 0) {
4511 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4512 } else {
4513 float fRounded = roundf(pItem->val.fnum);
4514 // See discussion in DecodeDateEpoch() for
4515 // explanation of - 0x7ff
4516 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4517 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4518 }
4519 *puValue = (uint64_t)fRounded;
4520 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004521 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004522 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4523 // round() and roundf() shouldn't result in exceptions here, but
4524 // catch them to be robust and thorough. Don't try to
4525 // distinguish between the various exceptions because it seems
4526 // they vary by CPU, compiler and OS.
4527 return QCBOR_ERR_FLOAT_EXCEPTION;
4528 }
4529
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004530 } else {
4531 return QCBOR_ERR_UNEXPECTED_TYPE;
4532 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004533#else
4534 return QCBOR_ERR_HW_FLOAT_DISABLED;
4535#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004536 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004537
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004538 case QCBOR_TYPE_INT64:
4539 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4540 if(pItem->val.int64 >= 0) {
4541 *puValue = (uint64_t)pItem->val.int64;
4542 } else {
4543 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4544 }
4545 } else {
4546 return QCBOR_ERR_UNEXPECTED_TYPE;
4547 }
4548 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004549
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004550 case QCBOR_TYPE_UINT64:
4551 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4552 *puValue = pItem->val.uint64;
4553 } else {
4554 return QCBOR_ERR_UNEXPECTED_TYPE;
4555 }
4556 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004557
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004558 default:
4559 return QCBOR_ERR_UNEXPECTED_TYPE;
4560 }
4561
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004562 return QCBOR_SUCCESS;
4563}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004564
4565
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004566void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004567 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004568 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004569 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004570{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004571 if(pMe->uLastError != QCBOR_SUCCESS) {
4572 return;
4573 }
4574
Laurence Lundbladec4537442020-04-14 18:53:22 -07004575 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004576
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004577 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4578 if(uError) {
4579 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004580 return;
4581 }
4582
Laurence Lundbladea826c502020-05-10 21:07:00 -07004583 if(pItem) {
4584 *pItem = Item;
4585 }
4586
Laurence Lundblade93d89472020-10-03 22:30:50 -07004587 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004588}
4589
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004590
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004591void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004592 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004593 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004594 uint64_t *puValue,
4595 QCBORItem *pItem)
4596{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004597 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004598 if(pMe->uLastError != QCBOR_SUCCESS) {
4599 return;
4600 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004601
Laurence Lundblade93d89472020-10-03 22:30:50 -07004602 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004603}
4604
4605
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004606void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004607 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004608 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004609 uint64_t *puValue,
4610 QCBORItem *pItem)
4611{
4612 if(pMe->uLastError != QCBOR_SUCCESS) {
4613 return;
4614 }
4615
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004616 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004617 if(pMe->uLastError != QCBOR_SUCCESS) {
4618 return;
4619 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004620
Laurence Lundblade93d89472020-10-03 22:30:50 -07004621 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004622}
4623
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004624
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004625
Laurence Lundblade93d89472020-10-03 22:30:50 -07004626static QCBORError
4627UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004628{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004629 switch(pItem->uDataType) {
4630
4631 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004632 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004633 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4634 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004635 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004636 }
4637 break;
4638
4639 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004640 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004641 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4642 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004643 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004644 }
4645 break;
4646
4647#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4648
4649 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004650 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004651 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004652 pItem->val.expAndMantissa.nExponent,
4653 puValue,
4654 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004655 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004656 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004657 }
4658 break;
4659
4660 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004661 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004662 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4663 pItem->val.expAndMantissa.nExponent,
4664 puValue,
4665 Exponentitate2);
4666 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004667 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004668 }
4669 break;
4670
4671 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004672 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004673 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004674 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004675 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004676 if(uErr != QCBOR_SUCCESS) {
4677 return uErr;
4678 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004679 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004680 pItem->val.expAndMantissa.nExponent,
4681 puValue,
4682 Exponentitate10);
4683 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004684 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004685 }
4686 break;
4687
4688 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004689 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004690 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4691 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004692 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004693 }
4694 break;
4695
4696 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004697 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004698 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004699 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004700 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004701 if(uErr != QCBOR_SUCCESS) {
4702 return uErr;
4703 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004704 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004705 pItem->val.expAndMantissa.nExponent,
4706 puValue,
4707 Exponentitate2);
4708 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004709 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004710 }
4711 break;
4712
4713 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004714 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004715 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4716 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004717 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004718 }
4719 break;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004720#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004721 default:
4722 return QCBOR_ERR_UNEXPECTED_TYPE;
4723 }
4724}
4725
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004726
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004727/*
4728 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004729 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004730void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004731{
4732 QCBORItem Item;
4733
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004734 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004735
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004736 if(pMe->uLastError == QCBOR_SUCCESS) {
4737 // The above conversion succeeded
4738 return;
4739 }
4740
4741 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4742 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004743 return;
4744 }
4745
Laurence Lundblade93d89472020-10-03 22:30:50 -07004746 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004747}
4748
Laurence Lundbladec4537442020-04-14 18:53:22 -07004749
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004750/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004751 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004752*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004753void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004754 int64_t nLabel,
4755 uint32_t uConvertTypes,
4756 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004757{
4758 QCBORItem Item;
4759
Laurence Lundblade93d89472020-10-03 22:30:50 -07004760 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
4761 nLabel,
4762 uConvertTypes,
4763 puValue,
4764 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004765
4766 if(pMe->uLastError == QCBOR_SUCCESS) {
4767 // The above conversion succeeded
4768 return;
4769 }
4770
4771 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4772 // The above conversion failed in a way that code below can't correct
4773 return;
4774 }
4775
Laurence Lundblade93d89472020-10-03 22:30:50 -07004776 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004777}
4778
4779
4780/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004781 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004782*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004783void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004784 const char *szLabel,
4785 uint32_t uConvertTypes,
4786 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004787{
4788 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004789 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
4790 szLabel,
4791 uConvertTypes,
4792 puValue,
4793 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004794
4795 if(pMe->uLastError == QCBOR_SUCCESS) {
4796 // The above conversion succeeded
4797 return;
4798 }
4799
4800 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4801 // The above conversion failed in a way that code below can't correct
4802 return;
4803 }
4804
Laurence Lundblade93d89472020-10-03 22:30:50 -07004805 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004806}
4807
4808
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004809
4810
Laurence Lundblade9b334962020-08-27 10:55:53 -07004811static QCBORError ConvertDouble(const QCBORItem *pItem,
4812 uint32_t uConvertTypes,
4813 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004814{
4815 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004816 case QCBOR_TYPE_FLOAT:
4817#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4818 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4819 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004820 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004821 *pdValue = (double)pItem->val.fnum;
4822 } else {
4823 return QCBOR_ERR_UNEXPECTED_TYPE;
4824 }
4825 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004826#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004827 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004828#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004829 break;
4830
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004831 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004832 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4833 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004834 *pdValue = pItem->val.dfnum;
4835 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004836 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004837 }
4838 }
4839 break;
4840
4841 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004842#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004843 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004844 // A simple cast seems to do the job with no worry of exceptions.
4845 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004846 *pdValue = (double)pItem->val.int64;
4847
4848 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004849 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004850 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004851#else
4852 return QCBOR_ERR_HW_FLOAT_DISABLED;
4853#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004854 break;
4855
4856 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004857#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004858 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004859 // A simple cast seems to do the job with no worry of exceptions.
4860 // There will be precision loss for some values.
4861 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004862 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004863 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004864 }
4865 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004866#else
4867 return QCBOR_ERR_HW_FLOAT_DISABLED;
4868#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004869
4870 default:
4871 return QCBOR_ERR_UNEXPECTED_TYPE;
4872 }
4873
4874 return QCBOR_SUCCESS;
4875}
4876
4877
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004878void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004879 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004880 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004881 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004882{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004883 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004884 return;
4885 }
4886
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004887 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004888
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004889 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004890 if(uError) {
4891 pMe->uLastError = (uint8_t)uError;
4892 return;
4893 }
4894
4895 if(pItem) {
4896 *pItem = Item;
4897 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004898
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004899 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004900}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004901
Laurence Lundbladec4537442020-04-14 18:53:22 -07004902
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004903void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4904 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004905 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004906 double *pdValue,
4907 QCBORItem *pItem)
4908{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004909 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004910 if(pMe->uLastError != QCBOR_SUCCESS) {
4911 return;
4912 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004913
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004914 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004915}
4916
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004917
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004918void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4919 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004920 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004921 double *pdValue,
4922 QCBORItem *pItem)
4923{
4924 if(pMe->uLastError != QCBOR_SUCCESS) {
4925 return;
4926 }
4927
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004928 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004929 if(pMe->uLastError != QCBOR_SUCCESS) {
4930 return;
4931 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004932
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004933 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004934}
4935
4936
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004937#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004938static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4939{
4940 double dResult;
4941
4942 dResult = 0.0;
4943 const uint8_t *pByte = BigNum.ptr;
4944 size_t uLen = BigNum.len;
4945 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004946 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004947 while(uLen--) {
4948 dResult = (dResult * 256.0) + (double)*pByte++;
4949 }
4950
4951 return dResult;
4952}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004953#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4954
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004955
Laurence Lundblade93d89472020-10-03 22:30:50 -07004956static QCBORError
4957DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004958{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004959#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004960 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004961 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4962
4963 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004964 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004965
4966#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004967 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004968 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004969 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004970 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4971 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4972 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004973 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004974 }
4975 break;
4976
4977 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004978 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004979 // Underflow gives 0, overflow gives infinity
4980 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4981 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004982 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004983 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004984 }
4985 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004986#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004987
4988 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004989 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004990 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4991 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004992 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004993 }
4994 break;
4995
4996 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004997 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004998 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004999 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005000 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005001 }
5002 break;
5003
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005004#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005005 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005006 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005007 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5008 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5009 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005010 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005011 }
5012 break;
5013
5014 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005015 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005016 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5017 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5018 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005019 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005020 }
5021 break;
5022
5023 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005024 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005025 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5026 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5027 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005028 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005029 }
5030 break;
5031
5032 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005033 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07005034 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005035 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5036 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005037 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005038 }
5039 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005040#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
5041
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005042 default:
5043 return QCBOR_ERR_UNEXPECTED_TYPE;
5044 }
5045
5046 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005047
5048#else
5049 (void)pItem;
5050 (void)uConvertTypes;
5051 (void)pdValue;
5052 return QCBOR_ERR_HW_FLOAT_DISABLED;
5053#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5054
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005055}
5056
5057
5058/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005059 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005060*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005061void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
5062 uint32_t uConvertTypes,
5063 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005064{
5065
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005066 QCBORItem Item;
5067
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005068 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005069
5070 if(pMe->uLastError == QCBOR_SUCCESS) {
5071 // The above conversion succeeded
5072 return;
5073 }
5074
5075 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5076 // The above conversion failed in a way that code below can't correct
5077 return;
5078 }
5079
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005080 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005081}
5082
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005083
5084/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005085 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005086*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005087void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
5088 int64_t nLabel,
5089 uint32_t uConvertTypes,
5090 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005091{
5092 QCBORItem Item;
5093
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005094 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005095
5096 if(pMe->uLastError == QCBOR_SUCCESS) {
5097 // The above conversion succeeded
5098 return;
5099 }
5100
5101 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5102 // The above conversion failed in a way that code below can't correct
5103 return;
5104 }
5105
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005106 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005107}
5108
5109
5110/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005111 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005112*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005113void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
5114 const char *szLabel,
5115 uint32_t uConvertTypes,
5116 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005117{
5118 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005119 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005120
5121 if(pMe->uLastError == QCBOR_SUCCESS) {
5122 // The above conversion succeeded
5123 return;
5124 }
5125
5126 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5127 // The above conversion failed in a way that code below can't correct
5128 return;
5129 }
5130
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005131 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005132}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005133
5134
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005135
5136
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005137#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005138static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
5139{
5140 while((uInt & 0xff00000000000000UL) == 0) {
5141 uInt = uInt << 8;
5142 };
5143
5144 UsefulOutBuf UOB;
5145
5146 UsefulOutBuf_Init(&UOB, Buffer);
5147
5148 while(uInt) {
5149 const uint64_t xx = uInt & 0xff00000000000000UL;
5150 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
5151 uInt = uInt << 8;
5152 (void)xx;
5153 }
5154
5155 return UsefulOutBuf_OutUBuf(&UOB);
5156}
5157
5158
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005159static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
5160 TagSpecification TagSpec,
5161 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005162{
5163 QCBORError uErr;
5164 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005165 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07005166 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005167 if(uErr != QCBOR_SUCCESS) {
5168 goto Done;
5169 }
5170
5171 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
5172 break; // Successful exit. Moving on to finish decoding.
5173 }
5174
5175 // The item is an array, which means an undecoded
5176 // mantissa and exponent, so decode it. It will then
5177 // have a different type and exit the loop if.
5178 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
5179 if(uErr != QCBOR_SUCCESS) {
5180 goto Done;
5181 }
5182
5183 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07005184 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005185 }
5186Done:
5187 return uErr;
5188}
5189
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005190
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005191static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005192 TagSpecification TagSpec,
5193 QCBORItem *pItem,
5194 int64_t *pnMantissa,
5195 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005196{
5197 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005198
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005199 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005200 if(uErr != QCBOR_SUCCESS) {
5201 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005202 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005203
Laurence Lundblade9b334962020-08-27 10:55:53 -07005204 switch (pItem->uDataType) {
5205
5206 case QCBOR_TYPE_DECIMAL_FRACTION:
5207 case QCBOR_TYPE_BIGFLOAT:
5208 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5209 *pnExponent = pItem->val.expAndMantissa.nExponent;
5210 break;
5211
5212 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5213 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5214 *pnExponent = pItem->val.expAndMantissa.nExponent;
5215 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5216 break;
5217
5218 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5219 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5220 *pnExponent = pItem->val.expAndMantissa.nExponent;
5221 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5222 break;
5223
5224 default:
5225 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5226 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005227
5228 Done:
5229 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005230}
5231
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005232
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005233static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005234 TagSpecification TagSpec,
5235 QCBORItem *pItem,
5236 UsefulBuf BufferForMantissa,
5237 UsefulBufC *pMantissa,
5238 bool *pbIsNegative,
5239 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005240{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005241 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005242
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005243 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005244 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005245 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005246 }
5247
5248 uint64_t uMantissa;
5249
5250 switch (pItem->uDataType) {
5251
5252 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005253 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005254 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5255 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5256 *pbIsNegative = false;
5257 } else {
5258 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5259 *pbIsNegative = true;
5260 }
5261 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5262 *pnExponent = pItem->val.expAndMantissa.nExponent;
5263 break;
5264
5265 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005266 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005267 *pnExponent = pItem->val.expAndMantissa.nExponent;
5268 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5269 *pbIsNegative = false;
5270 break;
5271
5272 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005273 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005274 *pnExponent = pItem->val.expAndMantissa.nExponent;
5275 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5276 *pbIsNegative = true;
5277 break;
5278
5279 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005280 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005281 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005282
5283Done:
5284 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005285}
5286
5287
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005288/*
5289 Public function, see header qcbor/qcbor_decode.h file
5290*/
5291void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5292 uint8_t uTagRequirement,
5293 int64_t *pnMantissa,
5294 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005295{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005296 if(pMe->uLastError != QCBOR_SUCCESS) {
5297 return;
5298 }
5299
5300 QCBORItem Item;
5301 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5302 if(uError) {
5303 pMe->uLastError = (uint8_t)uError;
5304 return;
5305 }
5306
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005307 const TagSpecification TagSpec =
5308 {
5309 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005310 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5311 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5312 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005313 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005314
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005315 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005316}
5317
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005318
5319/*
5320 Public function, see header qcbor/qcbor_decode.h file
5321*/
5322void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005323 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005324 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005325 int64_t *pnMantissa,
5326 int64_t *pnExponent)
5327{
5328 if(pMe->uLastError != QCBOR_SUCCESS) {
5329 return;
5330 }
5331
5332 QCBORItem Item;
5333 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5334
5335 const TagSpecification TagSpec =
5336 {
5337 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005338 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5339 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5340 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005341 };
5342
5343 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5344}
5345
5346
5347/*
5348 Public function, see header qcbor/qcbor_decode.h file
5349*/
5350void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005351 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005352 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005353 int64_t *pnMantissa,
5354 int64_t *pnExponent)
5355{
5356 if(pMe->uLastError != QCBOR_SUCCESS) {
5357 return;
5358 }
5359
5360 QCBORItem Item;
5361 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5362
5363 const TagSpecification TagSpec =
5364 {
5365 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005366 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5367 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5368 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005369 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005370
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005371 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5372}
5373
5374
5375/*
5376 Public function, see header qcbor/qcbor_decode.h file
5377*/
5378void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5379 uint8_t uTagRequirement,
5380 UsefulBuf MantissaBuffer,
5381 UsefulBufC *pMantissa,
5382 bool *pbMantissaIsNegative,
5383 int64_t *pnExponent)
5384{
5385 if(pMe->uLastError != QCBOR_SUCCESS) {
5386 return;
5387 }
5388
5389 QCBORItem Item;
5390 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5391 if(uError) {
5392 pMe->uLastError = (uint8_t)uError;
5393 return;
5394 }
5395
5396 const TagSpecification TagSpec =
5397 {
5398 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005399 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5400 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5401 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005402 };
5403
Laurence Lundblade93d89472020-10-03 22:30:50 -07005404 ProcessMantissaAndExponentBig(pMe,
5405 TagSpec,
5406 &Item,
5407 MantissaBuffer,
5408 pMantissa,
5409 pbMantissaIsNegative,
5410 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005411}
5412
5413
5414/*
5415 Public function, see header qcbor/qcbor_decode.h file
5416*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005417void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005418 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005419 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005420 UsefulBuf BufferForMantissa,
5421 UsefulBufC *pMantissa,
5422 bool *pbIsNegative,
5423 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005424{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005425 if(pMe->uLastError != QCBOR_SUCCESS) {
5426 return;
5427 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005428
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005429 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005430 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005431 if(pMe->uLastError != QCBOR_SUCCESS) {
5432 return;
5433 }
5434
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005435 const TagSpecification TagSpec =
5436 {
5437 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005438 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5439 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5440 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005441 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005442
Laurence Lundblade93d89472020-10-03 22:30:50 -07005443 ProcessMantissaAndExponentBig(pMe,
5444 TagSpec,
5445 &Item,
5446 BufferForMantissa,
5447 pMantissa,
5448 pbIsNegative,
5449 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005450}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005451
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005452
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005453/*
5454 Public function, see header qcbor/qcbor_decode.h file
5455*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005456void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005457 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005458 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005459 UsefulBuf BufferForMantissa,
5460 UsefulBufC *pMantissa,
5461 bool *pbIsNegative,
5462 int64_t *pnExponent)
5463{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005464 if(pMe->uLastError != QCBOR_SUCCESS) {
5465 return;
5466 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005467
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005468 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005469 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5470 if(pMe->uLastError != QCBOR_SUCCESS) {
5471 return;
5472 }
5473
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005474 const TagSpecification TagSpec =
5475 {
5476 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005477 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5478 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5479 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005480 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005481
5482 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5483}
5484
5485
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005486/*
5487 Public function, see header qcbor/qcbor_decode.h file
5488*/
5489void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5490 uint8_t uTagRequirement,
5491 int64_t *pnMantissa,
5492 int64_t *pnExponent)
5493{
5494 if(pMe->uLastError != QCBOR_SUCCESS) {
5495 return;
5496 }
5497
5498 QCBORItem Item;
5499 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5500 if(uError) {
5501 pMe->uLastError = (uint8_t)uError;
5502 return;
5503 }
5504 const TagSpecification TagSpec =
5505 {
5506 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005507 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5508 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5509 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005510 };
5511
5512 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5513}
5514
5515
5516/*
5517 Public function, see header qcbor/qcbor_decode.h file
5518*/
5519void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005520 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005521 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005522 int64_t *pnMantissa,
5523 int64_t *pnExponent)
5524{
5525 if(pMe->uLastError != QCBOR_SUCCESS) {
5526 return;
5527 }
5528
5529 QCBORItem Item;
5530 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5531 if(pMe->uLastError != QCBOR_SUCCESS) {
5532 return;
5533 }
5534
5535 const TagSpecification TagSpec =
5536 {
5537 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005538 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5539 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5540 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005541 };
5542
5543 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5544}
5545
5546
5547/*
5548 Public function, see header qcbor/qcbor_decode.h file
5549*/
5550void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005551 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005552 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005553 int64_t *pnMantissa,
5554 int64_t *pnExponent)
5555{
5556 if(pMe->uLastError != QCBOR_SUCCESS) {
5557 return;
5558 }
5559
5560 QCBORItem Item;
5561 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5562 if(pMe->uLastError != QCBOR_SUCCESS) {
5563 return;
5564 }
5565
5566 const TagSpecification TagSpec =
5567 {
5568 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005569 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5570 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5571 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005572 };
5573
5574 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5575}
5576
5577
5578/*
5579 Public function, see header qcbor/qcbor_decode.h file
5580*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005581void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5582 uint8_t uTagRequirement,
5583 UsefulBuf MantissaBuffer,
5584 UsefulBufC *pMantissa,
5585 bool *pbMantissaIsNegative,
5586 int64_t *pnExponent)
5587{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005588 if(pMe->uLastError != QCBOR_SUCCESS) {
5589 return;
5590 }
5591
5592 QCBORItem Item;
5593 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5594 if(uError) {
5595 pMe->uLastError = (uint8_t)uError;
5596 return;
5597 }
5598
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005599 const TagSpecification TagSpec =
5600 {
5601 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005602 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5603 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5604 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005605 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005606
5607 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005608}
5609
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005610
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005611/*
5612 Public function, see header qcbor/qcbor_decode.h file
5613*/
5614void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005615 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005616 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005617 UsefulBuf BufferForMantissa,
5618 UsefulBufC *pMantissa,
5619 bool *pbIsNegative,
5620 int64_t *pnExponent)
5621{
5622 if(pMe->uLastError != QCBOR_SUCCESS) {
5623 return;
5624 }
5625
5626 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005627 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5628 if(pMe->uLastError != QCBOR_SUCCESS) {
5629 return;
5630 }
5631
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005632 const TagSpecification TagSpec =
5633 {
5634 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005635 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5636 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5637 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005638 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005639
Laurence Lundblade93d89472020-10-03 22:30:50 -07005640 ProcessMantissaAndExponentBig(pMe,
5641 TagSpec,
5642 &Item,
5643 BufferForMantissa,
5644 pMantissa,
5645 pbIsNegative,
5646 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005647}
5648
5649
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005650/*
5651 Public function, see header qcbor/qcbor_decode.h file
5652*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005653void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005654 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005655 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005656 UsefulBuf BufferForMantissa,
5657 UsefulBufC *pMantissa,
5658 bool *pbIsNegative,
5659 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005660{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005661 if(pMe->uLastError != QCBOR_SUCCESS) {
5662 return;
5663 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005664
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005665 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005666 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5667 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005668 return;
5669 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005670
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005671 const TagSpecification TagSpec =
5672 {
5673 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005674 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5675 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5676 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005677 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005678
Laurence Lundblade93d89472020-10-03 22:30:50 -07005679 ProcessMantissaAndExponentBig(pMe,
5680 TagSpec,
5681 &Item,
5682 BufferForMantissa,
5683 pMantissa,
5684 pbIsNegative,
5685 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005686}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005687
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005688#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */